summaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/44x/warp-nand.c
blob: 89ecd76127d892237c6d50796d064922a1ea5676 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * PIKA Warp(tm) NAND flash specific routines
 *
 * Copyright (c) 2008 PIKA Technologies
 *   Sean MacLennan <smaclennan@pikatech.com>
 */

#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/ndfc.h>
#include <linux/of.h>
#include <asm/machdep.h>


#ifdef CONFIG_MTD_NAND_NDFC

#define CS_NAND_0	1	/* use chip select 1 for NAND device 0 */

#define WARP_NAND_FLASH_REG_ADDR	0xD0000000UL
#define WARP_NAND_FLASH_REG_SIZE	0x2000

static struct resource warp_ndfc = {
	.start = WARP_NAND_FLASH_REG_ADDR,
	.end   = WARP_NAND_FLASH_REG_ADDR + WARP_NAND_FLASH_REG_SIZE - 1,
	.flags = IORESOURCE_MEM,
};

static struct mtd_partition nand_parts[] = {
	{
		.name   = "kernel",
		.offset = 0,
		.size   = 0x0200000
	},
	{
		.name   = "root",
		.offset = 0x0200000,
		.size   = 0x3E00000
	},
	{
		.name   = "persistent",
		.offset = 0x4000000,
		.size   = 0x4000000
	},
	{
		.name   = "persistent1",
		.offset = 0x8000000,
		.size   = 0x4000000
	},
	{
		.name   = "persistent2",
		.offset = 0xC000000,
		.size   = 0x4000000
	}
};

struct ndfc_controller_settings warp_ndfc_settings = {
	.ccr_settings = (NDFC_CCR_BS(CS_NAND_0) | NDFC_CCR_ARAC1),
	.ndfc_erpn = 0,
};

static struct ndfc_chip_settings warp_chip0_settings = {
	.bank_settings = 0x80002222,
};

struct platform_nand_ctrl warp_nand_ctrl = {
	.priv = &warp_ndfc_settings,
};

static struct platform_device warp_ndfc_device = {
	.name = "ndfc-nand",
	.id = 0,
	.dev = {
		.platform_data = &warp_nand_ctrl,
	},
	.num_resources = 1,
	.resource = &warp_ndfc,
};

/* Do NOT set the ecclayout: let it default so it is correct for both
 * 64M and 256M flash chips.
 */
static struct platform_nand_chip warp_nand_chip0 = {
	.nr_chips = 1,
	.chip_offset = CS_NAND_0,
	.nr_partitions = ARRAY_SIZE(nand_parts),
	.partitions = nand_parts,
	.chip_delay = 20,
	.priv = &warp_chip0_settings,
};

static struct platform_device warp_nand_device = {
	.name = "ndfc-chip",
	.id = 0,
	.num_resources = 0,
	.dev = {
		.platform_data = &warp_nand_chip0,
		.parent = &warp_ndfc_device.dev,
	}
};

static int warp_setup_nand_flash(void)
{
	struct device_node *np;

	/* Try to detect a rev A based on NOR size. */
	np = of_find_compatible_node(NULL, NULL, "cfi-flash");
	if (np) {
		struct property *pp;

		pp = of_find_property(np, "reg", NULL);
		if (pp && (pp->length == 12)) {
			u32 *v = pp->value;
			if (v[2] == 0x4000000) {
				/* Rev A = 64M NAND */
				warp_nand_chip0.nr_partitions = 3;

				nand_parts[1].size   = 0x3000000;
				nand_parts[2].offset = 0x3200000;
				nand_parts[2].size   = 0x0e00000;
			}
		}
		of_node_put(np);
	}

	platform_device_register(&warp_ndfc_device);
	platform_device_register(&warp_nand_device);

	return 0;
}
machine_device_initcall(warp, warp_setup_nand_flash);

#endif