diff options
Diffstat (limited to 'arch/arm/mach-orion5x/ts78xx-setup.c')
-rw-r--r-- | arch/arm/mach-orion5x/ts78xx-setup.c | 444 |
1 files changed, 334 insertions, 110 deletions
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 1368e9fd1a06..9a6b397f972d 100644 --- a/arch/arm/mach-orion5x/ts78xx-setup.c +++ b/arch/arm/mach-orion5x/ts78xx-setup.c | |||
@@ -10,17 +10,20 @@ | |||
10 | 10 | ||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/sysfs.h> | ||
13 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
14 | #include <linux/mtd/physmap.h> | ||
15 | #include <linux/mv643xx_eth.h> | 15 | #include <linux/mv643xx_eth.h> |
16 | #include <linux/ata_platform.h> | 16 | #include <linux/ata_platform.h> |
17 | #include <linux/m48t86.h> | 17 | #include <linux/m48t86.h> |
18 | #include <linux/mtd/nand.h> | ||
19 | #include <linux/mtd/partitions.h> | ||
18 | #include <asm/mach-types.h> | 20 | #include <asm/mach-types.h> |
19 | #include <asm/mach/arch.h> | 21 | #include <asm/mach/arch.h> |
20 | #include <asm/mach/map.h> | 22 | #include <asm/mach/map.h> |
21 | #include <mach/orion5x.h> | 23 | #include <mach/orion5x.h> |
22 | #include "common.h" | 24 | #include "common.h" |
23 | #include "mpp.h" | 25 | #include "mpp.h" |
26 | #include "ts78xx-fpga.h" | ||
24 | 27 | ||
25 | /***************************************************************************** | 28 | /***************************************************************************** |
26 | * TS-78xx Info | 29 | * TS-78xx Info |
@@ -33,18 +36,11 @@ | |||
33 | #define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000 | 36 | #define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000 |
34 | #define TS78XX_FPGA_REGS_SIZE SZ_1M | 37 | #define TS78XX_FPGA_REGS_SIZE SZ_1M |
35 | 38 | ||
36 | #define TS78XX_FPGA_REGS_SYSCON_ID (TS78XX_FPGA_REGS_VIRT_BASE | 0x000) | 39 | static struct ts78xx_fpga_data ts78xx_fpga = { |
37 | #define TS78XX_FPGA_REGS_SYSCON_LCDI (TS78XX_FPGA_REGS_VIRT_BASE | 0x004) | 40 | .id = 0, |
38 | #define TS78XX_FPGA_REGS_SYSCON_LCDO (TS78XX_FPGA_REGS_VIRT_BASE | 0x008) | 41 | .state = 1, |
39 | 42 | /* .supports = ... - populated by ts78xx_fpga_supports() */ | |
40 | #define TS78XX_FPGA_REGS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) | 43 | }; |
41 | #define TS78XX_FPGA_REGS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) | ||
42 | |||
43 | /* | ||
44 | * 512kB NOR flash Device | ||
45 | */ | ||
46 | #define TS78XX_NOR_BOOT_BASE 0xff800000 | ||
47 | #define TS78XX_NOR_BOOT_SIZE SZ_512K | ||
48 | 44 | ||
49 | /***************************************************************************** | 45 | /***************************************************************************** |
50 | * I/O Address Mapping | 46 | * I/O Address Mapping |
@@ -65,73 +61,47 @@ void __init ts78xx_map_io(void) | |||
65 | } | 61 | } |
66 | 62 | ||
67 | /***************************************************************************** | 63 | /***************************************************************************** |
68 | * 512kB NOR Boot Flash - the chip is a M25P40 | 64 | * Ethernet |
69 | ****************************************************************************/ | 65 | ****************************************************************************/ |
70 | static struct mtd_partition ts78xx_nor_boot_flash_resources[] = { | 66 | static struct mv643xx_eth_platform_data ts78xx_eth_data = { |
71 | { | 67 | .phy_addr = MV643XX_ETH_PHY_ADDR(0), |
72 | .name = "ts-bootrom", | ||
73 | .offset = 0, | ||
74 | /* only the first 256kB is used */ | ||
75 | .size = SZ_256K, | ||
76 | .mask_flags = MTD_WRITEABLE, | ||
77 | }, | ||
78 | }; | ||
79 | |||
80 | static struct physmap_flash_data ts78xx_nor_boot_flash_data = { | ||
81 | .width = 1, | ||
82 | .parts = ts78xx_nor_boot_flash_resources, | ||
83 | .nr_parts = ARRAY_SIZE(ts78xx_nor_boot_flash_resources), | ||
84 | }; | ||
85 | |||
86 | static struct resource ts78xx_nor_boot_flash_resource = { | ||
87 | .flags = IORESOURCE_MEM, | ||
88 | .start = TS78XX_NOR_BOOT_BASE, | ||
89 | .end = TS78XX_NOR_BOOT_BASE + TS78XX_NOR_BOOT_SIZE - 1, | ||
90 | }; | ||
91 | |||
92 | static struct platform_device ts78xx_nor_boot_flash = { | ||
93 | .name = "physmap-flash", | ||
94 | .id = -1, | ||
95 | .dev = { | ||
96 | .platform_data = &ts78xx_nor_boot_flash_data, | ||
97 | }, | ||
98 | .num_resources = 1, | ||
99 | .resource = &ts78xx_nor_boot_flash_resource, | ||
100 | }; | 68 | }; |
101 | 69 | ||
102 | /***************************************************************************** | 70 | /***************************************************************************** |
103 | * Ethernet | 71 | * SATA |
104 | ****************************************************************************/ | 72 | ****************************************************************************/ |
105 | static struct mv643xx_eth_platform_data ts78xx_eth_data = { | 73 | static struct mv_sata_platform_data ts78xx_sata_data = { |
106 | .phy_addr = MV643XX_ETH_PHY_ADDR(0), | 74 | .n_ports = 2, |
107 | }; | 75 | }; |
108 | 76 | ||
109 | /***************************************************************************** | 77 | /***************************************************************************** |
110 | * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c | 78 | * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c |
111 | ****************************************************************************/ | 79 | ****************************************************************************/ |
112 | #ifdef CONFIG_RTC_DRV_M48T86 | 80 | #define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) |
113 | static unsigned char ts78xx_rtc_readbyte(unsigned long addr) | 81 | #define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c) |
82 | |||
83 | static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr) | ||
114 | { | 84 | { |
115 | writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); | 85 | writeb(addr, TS_RTC_CTRL); |
116 | return readb(TS78XX_FPGA_REGS_RTC_DATA); | 86 | return readb(TS_RTC_DATA); |
117 | } | 87 | } |
118 | 88 | ||
119 | static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr) | 89 | static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr) |
120 | { | 90 | { |
121 | writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); | 91 | writeb(addr, TS_RTC_CTRL); |
122 | writeb(value, TS78XX_FPGA_REGS_RTC_DATA); | 92 | writeb(value, TS_RTC_DATA); |
123 | } | 93 | } |
124 | 94 | ||
125 | static struct m48t86_ops ts78xx_rtc_ops = { | 95 | static struct m48t86_ops ts78xx_ts_rtc_ops = { |
126 | .readbyte = ts78xx_rtc_readbyte, | 96 | .readbyte = ts78xx_ts_rtc_readbyte, |
127 | .writebyte = ts78xx_rtc_writebyte, | 97 | .writebyte = ts78xx_ts_rtc_writebyte, |
128 | }; | 98 | }; |
129 | 99 | ||
130 | static struct platform_device ts78xx_rtc_device = { | 100 | static struct platform_device ts78xx_ts_rtc_device = { |
131 | .name = "rtc-m48t86", | 101 | .name = "rtc-m48t86", |
132 | .id = -1, | 102 | .id = -1, |
133 | .dev = { | 103 | .dev = { |
134 | .platform_data = &ts78xx_rtc_ops, | 104 | .platform_data = &ts78xx_ts_rtc_ops, |
135 | }, | 105 | }, |
136 | .num_resources = 0, | 106 | .num_resources = 0, |
137 | }; | 107 | }; |
@@ -146,59 +116,314 @@ static struct platform_device ts78xx_rtc_device = { | |||
146 | * TODO: track down a guinea pig without an RTC to see if we can work out a | 116 | * TODO: track down a guinea pig without an RTC to see if we can work out a |
147 | * better RTC detection routine | 117 | * better RTC detection routine |
148 | */ | 118 | */ |
149 | static int __init ts78xx_rtc_init(void) | 119 | static int ts78xx_ts_rtc_load(void) |
150 | { | 120 | { |
121 | int rc; | ||
151 | unsigned char tmp_rtc0, tmp_rtc1; | 122 | unsigned char tmp_rtc0, tmp_rtc1; |
152 | 123 | ||
153 | tmp_rtc0 = ts78xx_rtc_readbyte(126); | 124 | tmp_rtc0 = ts78xx_ts_rtc_readbyte(126); |
154 | tmp_rtc1 = ts78xx_rtc_readbyte(127); | 125 | tmp_rtc1 = ts78xx_ts_rtc_readbyte(127); |
155 | 126 | ||
156 | ts78xx_rtc_writebyte(0x00, 126); | 127 | ts78xx_ts_rtc_writebyte(0x00, 126); |
157 | ts78xx_rtc_writebyte(0x55, 127); | 128 | ts78xx_ts_rtc_writebyte(0x55, 127); |
158 | if (ts78xx_rtc_readbyte(127) == 0x55) { | 129 | if (ts78xx_ts_rtc_readbyte(127) == 0x55) { |
159 | ts78xx_rtc_writebyte(0xaa, 127); | 130 | ts78xx_ts_rtc_writebyte(0xaa, 127); |
160 | if (ts78xx_rtc_readbyte(127) == 0xaa | 131 | if (ts78xx_ts_rtc_readbyte(127) == 0xaa |
161 | && ts78xx_rtc_readbyte(126) == 0x00) { | 132 | && ts78xx_ts_rtc_readbyte(126) == 0x00) { |
162 | ts78xx_rtc_writebyte(tmp_rtc0, 126); | 133 | ts78xx_ts_rtc_writebyte(tmp_rtc0, 126); |
163 | ts78xx_rtc_writebyte(tmp_rtc1, 127); | 134 | ts78xx_ts_rtc_writebyte(tmp_rtc1, 127); |
164 | platform_device_register(&ts78xx_rtc_device); | 135 | |
165 | return 1; | 136 | if (ts78xx_fpga.supports.ts_rtc.init == 0) { |
137 | rc = platform_device_register(&ts78xx_ts_rtc_device); | ||
138 | if (!rc) | ||
139 | ts78xx_fpga.supports.ts_rtc.init = 1; | ||
140 | } else | ||
141 | rc = platform_device_add(&ts78xx_ts_rtc_device); | ||
142 | |||
143 | return rc; | ||
166 | } | 144 | } |
167 | } | 145 | } |
168 | 146 | ||
169 | return 0; | 147 | return -ENODEV; |
170 | }; | 148 | }; |
171 | #else | 149 | |
172 | static int __init ts78xx_rtc_init(void) | 150 | static void ts78xx_ts_rtc_unload(void) |
173 | { | 151 | { |
174 | return 0; | 152 | platform_device_del(&ts78xx_ts_rtc_device); |
175 | } | 153 | } |
176 | #endif | ||
177 | 154 | ||
178 | /***************************************************************************** | 155 | /***************************************************************************** |
179 | * SATA | 156 | * NAND Flash |
180 | ****************************************************************************/ | 157 | ****************************************************************************/ |
181 | static struct mv_sata_platform_data ts78xx_sata_data = { | 158 | #define TS_NAND_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x800) /* VIRT */ |
182 | .n_ports = 2, | 159 | #define TS_NAND_DATA (TS78XX_FPGA_REGS_PHYS_BASE | 0x804) /* PHYS */ |
160 | |||
161 | /* | ||
162 | * hardware specific access to control-lines | ||
163 | * | ||
164 | * ctrl: | ||
165 | * NAND_NCE: bit 0 -> bit 2 | ||
166 | * NAND_CLE: bit 1 -> bit 1 | ||
167 | * NAND_ALE: bit 2 -> bit 0 | ||
168 | */ | ||
169 | static void ts78xx_ts_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, | ||
170 | unsigned int ctrl) | ||
171 | { | ||
172 | struct nand_chip *this = mtd->priv; | ||
173 | |||
174 | if (ctrl & NAND_CTRL_CHANGE) { | ||
175 | unsigned char bits; | ||
176 | |||
177 | bits = (ctrl & NAND_NCE) << 2; | ||
178 | bits |= ctrl & NAND_CLE; | ||
179 | bits |= (ctrl & NAND_ALE) >> 2; | ||
180 | |||
181 | writeb((readb(TS_NAND_CTRL) & ~0x7) | bits, TS_NAND_CTRL); | ||
182 | } | ||
183 | |||
184 | if (cmd != NAND_CMD_NONE) | ||
185 | writeb(cmd, this->IO_ADDR_W); | ||
186 | } | ||
187 | |||
188 | static int ts78xx_ts_nand_dev_ready(struct mtd_info *mtd) | ||
189 | { | ||
190 | return readb(TS_NAND_CTRL) & 0x20; | ||
191 | } | ||
192 | |||
193 | const char *ts_nand_part_probes[] = { "cmdlinepart", NULL }; | ||
194 | |||
195 | static struct mtd_partition ts78xx_ts_nand_parts[] = { | ||
196 | { | ||
197 | .name = "mbr", | ||
198 | .offset = 0, | ||
199 | .size = SZ_128K, | ||
200 | .mask_flags = MTD_WRITEABLE, | ||
201 | }, { | ||
202 | .name = "kernel", | ||
203 | .offset = MTDPART_OFS_APPEND, | ||
204 | .size = SZ_4M, | ||
205 | }, { | ||
206 | .name = "initrd", | ||
207 | .offset = MTDPART_OFS_APPEND, | ||
208 | .size = SZ_4M, | ||
209 | }, { | ||
210 | .name = "rootfs", | ||
211 | .offset = MTDPART_OFS_APPEND, | ||
212 | .size = MTDPART_SIZ_FULL, | ||
213 | } | ||
183 | }; | 214 | }; |
184 | 215 | ||
216 | static struct platform_nand_data ts78xx_ts_nand_data = { | ||
217 | .chip = { | ||
218 | .part_probe_types = ts_nand_part_probes, | ||
219 | .partitions = ts78xx_ts_nand_parts, | ||
220 | .nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts), | ||
221 | .chip_delay = 15, | ||
222 | .options = NAND_USE_FLASH_BBT, | ||
223 | }, | ||
224 | .ctrl = { | ||
225 | /* | ||
226 | * The HW ECC offloading functions, used to give about a 9% | ||
227 | * performance increase for 'dd if=/dev/mtdblockX' and 5% for | ||
228 | * nanddump. This all however was changed by git commit | ||
229 | * e6cf5df1838c28bb060ac45b5585e48e71bbc740 so now there is | ||
230 | * no performance advantage to be had so we no longer bother | ||
231 | */ | ||
232 | .cmd_ctrl = ts78xx_ts_nand_cmd_ctrl, | ||
233 | .dev_ready = ts78xx_ts_nand_dev_ready, | ||
234 | }, | ||
235 | }; | ||
236 | |||
237 | static struct resource ts78xx_ts_nand_resources = { | ||
238 | .start = TS_NAND_DATA, | ||
239 | .end = TS_NAND_DATA + 4, | ||
240 | .flags = IORESOURCE_IO, | ||
241 | }; | ||
242 | |||
243 | static struct platform_device ts78xx_ts_nand_device = { | ||
244 | .name = "gen_nand", | ||
245 | .id = -1, | ||
246 | .dev = { | ||
247 | .platform_data = &ts78xx_ts_nand_data, | ||
248 | }, | ||
249 | .resource = &ts78xx_ts_nand_resources, | ||
250 | .num_resources = 1, | ||
251 | }; | ||
252 | |||
253 | static int ts78xx_ts_nand_load(void) | ||
254 | { | ||
255 | int rc; | ||
256 | |||
257 | if (ts78xx_fpga.supports.ts_nand.init == 0) { | ||
258 | rc = platform_device_register(&ts78xx_ts_nand_device); | ||
259 | if (!rc) | ||
260 | ts78xx_fpga.supports.ts_nand.init = 1; | ||
261 | } else | ||
262 | rc = platform_device_add(&ts78xx_ts_nand_device); | ||
263 | |||
264 | return rc; | ||
265 | }; | ||
266 | |||
267 | static void ts78xx_ts_nand_unload(void) | ||
268 | { | ||
269 | platform_device_del(&ts78xx_ts_nand_device); | ||
270 | } | ||
271 | |||
185 | /***************************************************************************** | 272 | /***************************************************************************** |
186 | * print some information regarding the board | 273 | * FPGA 'hotplug' support code |
187 | ****************************************************************************/ | 274 | ****************************************************************************/ |
188 | static void __init ts78xx_print_board_id(void) | 275 | static void ts78xx_fpga_devices_zero_init(void) |
189 | { | 276 | { |
190 | unsigned int board_info; | 277 | ts78xx_fpga.supports.ts_rtc.init = 0; |
191 | 278 | ts78xx_fpga.supports.ts_nand.init = 0; | |
192 | board_info = readl(TS78XX_FPGA_REGS_SYSCON_ID); | 279 | } |
193 | printk(KERN_INFO "TS-78xx Info: FPGA rev=%.2x, Board Magic=%.6x, ", | 280 | |
194 | board_info & 0xff, | 281 | static void ts78xx_fpga_supports(void) |
195 | (board_info >> 8) & 0xffffff); | 282 | { |
196 | board_info = readl(TS78XX_FPGA_REGS_SYSCON_LCDI); | 283 | /* TODO: put this 'table' into ts78xx-fpga.h */ |
197 | printk("JP1=%d, JP2=%d\n", | 284 | switch (ts78xx_fpga.id) { |
198 | (board_info >> 30) & 0x1, | 285 | case TS7800_REV_1: |
199 | (board_info >> 31) & 0x1); | 286 | case TS7800_REV_2: |
287 | case TS7800_REV_3: | ||
288 | case TS7800_REV_4: | ||
289 | case TS7800_REV_5: | ||
290 | ts78xx_fpga.supports.ts_rtc.present = 1; | ||
291 | ts78xx_fpga.supports.ts_nand.present = 1; | ||
292 | break; | ||
293 | default: | ||
294 | ts78xx_fpga.supports.ts_rtc.present = 0; | ||
295 | ts78xx_fpga.supports.ts_nand.present = 0; | ||
296 | } | ||
297 | } | ||
298 | |||
299 | static int ts78xx_fpga_load_devices(void) | ||
300 | { | ||
301 | int tmp, ret = 0; | ||
302 | |||
303 | if (ts78xx_fpga.supports.ts_rtc.present == 1) { | ||
304 | tmp = ts78xx_ts_rtc_load(); | ||
305 | if (tmp) { | ||
306 | printk(KERN_INFO "TS-78xx: RTC not registered\n"); | ||
307 | ts78xx_fpga.supports.ts_rtc.present = 0; | ||
308 | } | ||
309 | ret |= tmp; | ||
310 | } | ||
311 | if (ts78xx_fpga.supports.ts_nand.present == 1) { | ||
312 | tmp = ts78xx_ts_nand_load(); | ||
313 | if (tmp) { | ||
314 | printk(KERN_INFO "TS-78xx: NAND not registered\n"); | ||
315 | ts78xx_fpga.supports.ts_nand.present = 0; | ||
316 | } | ||
317 | ret |= tmp; | ||
318 | } | ||
319 | |||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static int ts78xx_fpga_unload_devices(void) | ||
324 | { | ||
325 | int ret = 0; | ||
326 | |||
327 | if (ts78xx_fpga.supports.ts_rtc.present == 1) | ||
328 | ts78xx_ts_rtc_unload(); | ||
329 | if (ts78xx_fpga.supports.ts_nand.present == 1) | ||
330 | ts78xx_ts_nand_unload(); | ||
331 | |||
332 | return ret; | ||
333 | } | ||
334 | |||
335 | static int ts78xx_fpga_load(void) | ||
336 | { | ||
337 | ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE); | ||
338 | |||
339 | printk(KERN_INFO "TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n", | ||
340 | (ts78xx_fpga.id >> 8) & 0xffffff, | ||
341 | ts78xx_fpga.id & 0xff); | ||
342 | |||
343 | ts78xx_fpga_supports(); | ||
344 | |||
345 | if (ts78xx_fpga_load_devices()) { | ||
346 | ts78xx_fpga.state = -1; | ||
347 | return -EBUSY; | ||
348 | } | ||
349 | |||
350 | return 0; | ||
200 | }; | 351 | }; |
201 | 352 | ||
353 | static int ts78xx_fpga_unload(void) | ||
354 | { | ||
355 | unsigned int fpga_id; | ||
356 | |||
357 | fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE); | ||
358 | |||
359 | /* | ||
360 | * There does not seem to be a feasible way to block access to the GPIO | ||
361 | * pins from userspace (/dev/mem). This if clause should hopefully warn | ||
362 | * those foolish enough not to follow 'policy' :) | ||
363 | * | ||
364 | * UrJTAG SVN since r1381 can be used to reprogram the FPGA | ||
365 | */ | ||
366 | if (ts78xx_fpga.id != fpga_id) { | ||
367 | printk(KERN_ERR "TS-78xx FPGA: magic/rev mismatch\n" | ||
368 | "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n", | ||
369 | (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff, | ||
370 | (fpga_id >> 8) & 0xffffff, fpga_id & 0xff); | ||
371 | ts78xx_fpga.state = -1; | ||
372 | return -EBUSY; | ||
373 | } | ||
374 | |||
375 | if (ts78xx_fpga_unload_devices()) { | ||
376 | ts78xx_fpga.state = -1; | ||
377 | return -EBUSY; | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | }; | ||
382 | |||
383 | static ssize_t ts78xx_fpga_show(struct kobject *kobj, | ||
384 | struct kobj_attribute *attr, char *buf) | ||
385 | { | ||
386 | if (ts78xx_fpga.state < 0) | ||
387 | return sprintf(buf, "borked\n"); | ||
388 | |||
389 | return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline"); | ||
390 | } | ||
391 | |||
392 | static ssize_t ts78xx_fpga_store(struct kobject *kobj, | ||
393 | struct kobj_attribute *attr, const char *buf, size_t n) | ||
394 | { | ||
395 | int value, ret; | ||
396 | |||
397 | if (ts78xx_fpga.state < 0) { | ||
398 | printk(KERN_ERR "TS-78xx FPGA: borked, you must powercycle asap\n"); | ||
399 | return -EBUSY; | ||
400 | } | ||
401 | |||
402 | if (strncmp(buf, "online", sizeof("online") - 1) == 0) | ||
403 | value = 1; | ||
404 | else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) | ||
405 | value = 0; | ||
406 | else { | ||
407 | printk(KERN_ERR "ts78xx_fpga_store: Invalid value\n"); | ||
408 | return -EINVAL; | ||
409 | } | ||
410 | |||
411 | if (ts78xx_fpga.state == value) | ||
412 | return n; | ||
413 | |||
414 | ret = (ts78xx_fpga.state == 0) | ||
415 | ? ts78xx_fpga_load() | ||
416 | : ts78xx_fpga_unload(); | ||
417 | |||
418 | if (!(ret < 0)) | ||
419 | ts78xx_fpga.state = value; | ||
420 | |||
421 | return n; | ||
422 | } | ||
423 | |||
424 | static struct kobj_attribute ts78xx_fpga_attr = | ||
425 | __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store); | ||
426 | |||
202 | /***************************************************************************** | 427 | /***************************************************************************** |
203 | * General Setup | 428 | * General Setup |
204 | ****************************************************************************/ | 429 | ****************************************************************************/ |
@@ -223,30 +448,29 @@ static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = { | |||
223 | { 17, MPP_UART }, | 448 | { 17, MPP_UART }, |
224 | { 18, MPP_UART }, | 449 | { 18, MPP_UART }, |
225 | { 19, MPP_UART }, | 450 | { 19, MPP_UART }, |
451 | /* | ||
452 | * MPP[20] PCI Clock Out 1 | ||
453 | * MPP[21] PCI Clock Out 0 | ||
454 | * MPP[22] Unused | ||
455 | * MPP[23] Unused | ||
456 | * MPP[24] Unused | ||
457 | * MPP[25] Unused | ||
458 | */ | ||
226 | { -1 }, | 459 | { -1 }, |
227 | }; | 460 | }; |
228 | 461 | ||
229 | static void __init ts78xx_init(void) | 462 | static void __init ts78xx_init(void) |
230 | { | 463 | { |
464 | int ret; | ||
465 | |||
231 | /* | 466 | /* |
232 | * Setup basic Orion functions. Need to be called early. | 467 | * Setup basic Orion functions. Need to be called early. |
233 | */ | 468 | */ |
234 | orion5x_init(); | 469 | orion5x_init(); |
235 | 470 | ||
236 | ts78xx_print_board_id(); | ||
237 | |||
238 | orion5x_mpp_conf(ts78xx_mpp_modes); | 471 | orion5x_mpp_conf(ts78xx_mpp_modes); |
239 | 472 | ||
240 | /* | 473 | /* |
241 | * MPP[20] PCI Clock Out 1 | ||
242 | * MPP[21] PCI Clock Out 0 | ||
243 | * MPP[22] Unused | ||
244 | * MPP[23] Unused | ||
245 | * MPP[24] Unused | ||
246 | * MPP[25] Unused | ||
247 | */ | ||
248 | |||
249 | /* | ||
250 | * Configure peripherals. | 474 | * Configure peripherals. |
251 | */ | 475 | */ |
252 | orion5x_ehci0_init(); | 476 | orion5x_ehci0_init(); |
@@ -257,12 +481,12 @@ static void __init ts78xx_init(void) | |||
257 | orion5x_uart1_init(); | 481 | orion5x_uart1_init(); |
258 | orion5x_xor_init(); | 482 | orion5x_xor_init(); |
259 | 483 | ||
260 | orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE, | 484 | /* FPGA init */ |
261 | TS78XX_NOR_BOOT_SIZE); | 485 | ts78xx_fpga_devices_zero_init(); |
262 | platform_device_register(&ts78xx_nor_boot_flash); | 486 | ret = ts78xx_fpga_load(); |
263 | 487 | ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr); | |
264 | if (!ts78xx_rtc_init()) | 488 | if (ret) |
265 | printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); | 489 | printk(KERN_ERR "sysfs_create_file failed: %d\n", ret); |
266 | } | 490 | } |
267 | 491 | ||
268 | MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") | 492 | MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") |