|
10 | 10 | * your option) any later version.
|
11 | 11 | */
|
12 | 12 |
|
| 13 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
| 14 | + |
13 | 15 | #include <linux/kernel.h>
|
14 | 16 | #include <linux/init.h>
|
15 | 17 | #include <linux/platform_device.h>
|
16 | 18 | #include <linux/io.h>
|
17 | 19 | #include <linux/m48t86.h>
|
18 | 20 | #include <linux/mtd/physmap.h>
|
| 21 | +#include <linux/mtd/nand.h> |
| 22 | +#include <linux/mtd/partitions.h> |
19 | 23 |
|
20 | 24 | #include <mach/hardware.h>
|
21 | 25 | #include <mach/ts72xx.h>
|
@@ -54,92 +58,162 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
|
54 | 58 | }
|
55 | 59 | };
|
56 | 60 |
|
57 |
| -static struct map_desc ts72xx_nand_io_desc[] __initdata = { |
58 |
| - { |
59 |
| - .virtual = TS72XX_NAND_DATA_VIRT_BASE, |
60 |
| - .pfn = __phys_to_pfn(TS72XX_NAND1_DATA_PHYS_BASE), |
61 |
| - .length = TS72XX_NAND_DATA_SIZE, |
62 |
| - .type = MT_DEVICE, |
63 |
| - }, { |
64 |
| - .virtual = TS72XX_NAND_CONTROL_VIRT_BASE, |
65 |
| - .pfn = __phys_to_pfn(TS72XX_NAND1_CONTROL_PHYS_BASE), |
66 |
| - .length = TS72XX_NAND_CONTROL_SIZE, |
67 |
| - .type = MT_DEVICE, |
68 |
| - }, { |
69 |
| - .virtual = TS72XX_NAND_BUSY_VIRT_BASE, |
70 |
| - .pfn = __phys_to_pfn(TS72XX_NAND1_BUSY_PHYS_BASE), |
71 |
| - .length = TS72XX_NAND_BUSY_SIZE, |
72 |
| - .type = MT_DEVICE, |
| 61 | +static void __init ts72xx_map_io(void) |
| 62 | +{ |
| 63 | + ep93xx_map_io(); |
| 64 | + iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); |
| 65 | +} |
| 66 | + |
| 67 | + |
| 68 | +/************************************************************************* |
| 69 | + * NAND flash |
| 70 | + *************************************************************************/ |
| 71 | +#define TS72XX_NAND_CONTROL_ADDR_LINE 22 /* 0xN0400000 */ |
| 72 | +#define TS72XX_NAND_BUSY_ADDR_LINE 23 /* 0xN0800000 */ |
| 73 | + |
| 74 | +static void ts72xx_nand_hwcontrol(struct mtd_info *mtd, |
| 75 | + int cmd, unsigned int ctrl) |
| 76 | +{ |
| 77 | + struct nand_chip *chip = mtd->priv; |
| 78 | + |
| 79 | + if (ctrl & NAND_CTRL_CHANGE) { |
| 80 | + void __iomem *addr = chip->IO_ADDR_R; |
| 81 | + unsigned char bits; |
| 82 | + |
| 83 | + addr += (1 << TS72XX_NAND_CONTROL_ADDR_LINE); |
| 84 | + |
| 85 | + bits = __raw_readb(addr) & ~0x07; |
| 86 | + bits |= (ctrl & NAND_NCE) << 2; /* bit 0 -> bit 2 */ |
| 87 | + bits |= (ctrl & NAND_CLE); /* bit 1 -> bit 1 */ |
| 88 | + bits |= (ctrl & NAND_ALE) >> 2; /* bit 2 -> bit 0 */ |
| 89 | + |
| 90 | + __raw_writeb(bits, addr); |
73 | 91 | }
|
74 |
| -}; |
75 | 92 |
|
76 |
| -static struct map_desc ts72xx_alternate_nand_io_desc[] __initdata = { |
| 93 | + if (cmd != NAND_CMD_NONE) |
| 94 | + __raw_writeb(cmd, chip->IO_ADDR_W); |
| 95 | +} |
| 96 | + |
| 97 | +static int ts72xx_nand_device_ready(struct mtd_info *mtd) |
| 98 | +{ |
| 99 | + struct nand_chip *chip = mtd->priv; |
| 100 | + void __iomem *addr = chip->IO_ADDR_R; |
| 101 | + |
| 102 | + addr += (1 << TS72XX_NAND_BUSY_ADDR_LINE); |
| 103 | + |
| 104 | + return !!(__raw_readb(addr) & 0x20); |
| 105 | +} |
| 106 | + |
| 107 | +static const char *ts72xx_nand_part_probes[] = { "cmdlinepart", NULL }; |
| 108 | + |
| 109 | +#define TS72XX_BOOTROM_PART_SIZE (SZ_16K) |
| 110 | +#define TS72XX_REDBOOT_PART_SIZE (SZ_2M + SZ_1M) |
| 111 | + |
| 112 | +static struct mtd_partition ts72xx_nand_parts[] = { |
77 | 113 | {
|
78 |
| - .virtual = TS72XX_NAND_DATA_VIRT_BASE, |
79 |
| - .pfn = __phys_to_pfn(TS72XX_NAND2_DATA_PHYS_BASE), |
80 |
| - .length = TS72XX_NAND_DATA_SIZE, |
81 |
| - .type = MT_DEVICE, |
| 114 | + .name = "TS-BOOTROM", |
| 115 | + .offset = 0, |
| 116 | + .size = TS72XX_BOOTROM_PART_SIZE, |
| 117 | + .mask_flags = MTD_WRITEABLE, /* force read-only */ |
82 | 118 | }, {
|
83 |
| - .virtual = TS72XX_NAND_CONTROL_VIRT_BASE, |
84 |
| - .pfn = __phys_to_pfn(TS72XX_NAND2_CONTROL_PHYS_BASE), |
85 |
| - .length = TS72XX_NAND_CONTROL_SIZE, |
86 |
| - .type = MT_DEVICE, |
| 119 | + .name = "Linux", |
| 120 | + .offset = MTDPART_OFS_APPEND, |
| 121 | + .size = 0, /* filled in later */ |
87 | 122 | }, {
|
88 |
| - .virtual = TS72XX_NAND_BUSY_VIRT_BASE, |
89 |
| - .pfn = __phys_to_pfn(TS72XX_NAND2_BUSY_PHYS_BASE), |
90 |
| - .length = TS72XX_NAND_BUSY_SIZE, |
91 |
| - .type = MT_DEVICE, |
92 |
| - } |
| 123 | + .name = "RedBoot", |
| 124 | + .offset = MTDPART_OFS_APPEND, |
| 125 | + .size = MTDPART_SIZ_FULL, |
| 126 | + .mask_flags = MTD_WRITEABLE, /* force read-only */ |
| 127 | + }, |
93 | 128 | };
|
94 | 129 |
|
95 |
| -static void __init ts72xx_map_io(void) |
| 130 | +static void ts72xx_nand_set_parts(uint64_t size, |
| 131 | + struct platform_nand_chip *chip) |
96 | 132 | {
|
97 |
| - ep93xx_map_io(); |
98 |
| - iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); |
| 133 | + /* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */ |
| 134 | + if (size == SZ_32M || size == SZ_128M) { |
| 135 | + /* Set the "Linux" partition size */ |
| 136 | + ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE; |
99 | 137 |
|
100 |
| - /* |
101 |
| - * The TS-7200 has NOR flash, the other models have NAND flash. |
102 |
| - */ |
103 |
| - if (!board_is_ts7200()) { |
104 |
| - if (is_ts9420_installed()) { |
105 |
| - iotable_init(ts72xx_alternate_nand_io_desc, |
106 |
| - ARRAY_SIZE(ts72xx_alternate_nand_io_desc)); |
107 |
| - } else { |
108 |
| - iotable_init(ts72xx_nand_io_desc, |
109 |
| - ARRAY_SIZE(ts72xx_nand_io_desc)); |
110 |
| - } |
| 138 | + chip->partitions = ts72xx_nand_parts; |
| 139 | + chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts); |
| 140 | + } else { |
| 141 | + pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20); |
111 | 142 | }
|
112 | 143 | }
|
113 | 144 |
|
| 145 | +static struct platform_nand_data ts72xx_nand_data = { |
| 146 | + .chip = { |
| 147 | + .nr_chips = 1, |
| 148 | + .chip_offset = 0, |
| 149 | + .chip_delay = 15, |
| 150 | + .part_probe_types = ts72xx_nand_part_probes, |
| 151 | + .set_parts = ts72xx_nand_set_parts, |
| 152 | + }, |
| 153 | + .ctrl = { |
| 154 | + .cmd_ctrl = ts72xx_nand_hwcontrol, |
| 155 | + .dev_ready = ts72xx_nand_device_ready, |
| 156 | + }, |
| 157 | +}; |
| 158 | + |
| 159 | +static struct resource ts72xx_nand_resource[] = { |
| 160 | + { |
| 161 | + .start = 0, /* filled in later */ |
| 162 | + .end = 0, /* filled in later */ |
| 163 | + .flags = IORESOURCE_MEM, |
| 164 | + }, |
| 165 | +}; |
| 166 | + |
| 167 | +static struct platform_device ts72xx_nand_flash = { |
| 168 | + .name = "gen_nand", |
| 169 | + .id = -1, |
| 170 | + .dev.platform_data = &ts72xx_nand_data, |
| 171 | + .resource = ts72xx_nand_resource, |
| 172 | + .num_resources = ARRAY_SIZE(ts72xx_nand_resource), |
| 173 | +}; |
| 174 | + |
| 175 | + |
114 | 176 | /*************************************************************************
|
115 | 177 | * NOR flash (TS-7200 only)
|
116 | 178 | *************************************************************************/
|
117 |
| -static struct physmap_flash_data ts72xx_flash_data = { |
| 179 | +static struct physmap_flash_data ts72xx_nor_data = { |
118 | 180 | .width = 2,
|
119 | 181 | };
|
120 | 182 |
|
121 |
| -static struct resource ts72xx_flash_resource = { |
| 183 | +static struct resource ts72xx_nor_resource = { |
122 | 184 | .start = EP93XX_CS6_PHYS_BASE,
|
123 | 185 | .end = EP93XX_CS6_PHYS_BASE + SZ_16M - 1,
|
124 | 186 | .flags = IORESOURCE_MEM,
|
125 | 187 | };
|
126 | 188 |
|
127 |
| -static struct platform_device ts72xx_flash = { |
128 |
| - .name = "physmap-flash", |
129 |
| - .id = 0, |
130 |
| - .dev = { |
131 |
| - .platform_data = &ts72xx_flash_data, |
132 |
| - }, |
133 |
| - .num_resources = 1, |
134 |
| - .resource = &ts72xx_flash_resource, |
| 189 | +static struct platform_device ts72xx_nor_flash = { |
| 190 | + .name = "physmap-flash", |
| 191 | + .id = 0, |
| 192 | + .dev.platform_data = &ts72xx_nor_data, |
| 193 | + .resource = &ts72xx_nor_resource, |
| 194 | + .num_resources = 1, |
135 | 195 | };
|
136 | 196 |
|
137 | 197 | static void __init ts72xx_register_flash(void)
|
138 | 198 | {
|
139 |
| - if (board_is_ts7200()) |
140 |
| - platform_device_register(&ts72xx_flash); |
| 199 | + if (board_is_ts7200()) { |
| 200 | + platform_device_register(&ts72xx_nor_flash); |
| 201 | + } else { |
| 202 | + resource_size_t start; |
| 203 | + |
| 204 | + if (is_ts9420_installed()) |
| 205 | + start = EP93XX_CS7_PHYS_BASE; |
| 206 | + else |
| 207 | + start = EP93XX_CS6_PHYS_BASE; |
| 208 | + |
| 209 | + ts72xx_nand_resource[0].start = start; |
| 210 | + ts72xx_nand_resource[0].end = start + SZ_16M - 1; |
| 211 | + |
| 212 | + platform_device_register(&ts72xx_nand_flash); |
| 213 | + } |
141 | 214 | }
|
142 | 215 |
|
| 216 | + |
143 | 217 | static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
|
144 | 218 | {
|
145 | 219 | __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
|
|
0 commit comments