diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2009-03-19 19:10:40 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2009-03-19 19:10:40 -0400 |
commit | 7d83f8fca517b123cf0136503a9e50974f65ec49 (patch) | |
tree | 92ed1faaf112e98e29a00efc99e1a4e6c79e6a8e /arch/arm/mach-orion5x | |
parent | be093beb608edf821b45fe00a8a080fb5c6ed4af (diff) | |
parent | 569106c70e49ad67c69fa7d43a2a5218e63a4619 (diff) |
Merge branch 'master' of git://git.marvell.com/orion into devel
Conflicts:
arch/arm/mach-mx1/devices.c
Diffstat (limited to 'arch/arm/mach-orion5x')
-rw-r--r-- | arch/arm/mach-orion5x/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm/mach-orion5x/common.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-orion5x/dns323-setup.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-orion5x/ts78xx-fpga.h | 29 | ||||
-rw-r--r-- | arch/arm/mach-orion5x/ts78xx-setup.c | 441 |
5 files changed, 370 insertions, 112 deletions
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig index f59a8d0e0824..2c7035d8dcbf 100644 --- a/arch/arm/mach-orion5x/Kconfig +++ b/arch/arm/mach-orion5x/Kconfig | |||
@@ -71,6 +71,7 @@ config MACH_WRT350N_V2 | |||
71 | 71 | ||
72 | config MACH_TS78XX | 72 | config MACH_TS78XX |
73 | bool "Technologic Systems TS-78xx" | 73 | bool "Technologic Systems TS-78xx" |
74 | select PM | ||
74 | help | 75 | help |
75 | Say 'Y' here if you want your kernel to support the | 76 | Say 'Y' here if you want your kernel to support the |
76 | Technologic Systems TS-78xx platform. | 77 | Technologic Systems TS-78xx platform. |
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c index 0a623379789f..8a0e49d84256 100644 --- a/arch/arm/mach-orion5x/common.c +++ b/arch/arm/mach-orion5x/common.c | |||
@@ -431,6 +431,10 @@ void __init orion5x_uart1_init(void) | |||
431 | /***************************************************************************** | 431 | /***************************************************************************** |
432 | * XOR engine | 432 | * XOR engine |
433 | ****************************************************************************/ | 433 | ****************************************************************************/ |
434 | struct mv_xor_platform_shared_data orion5x_xor_shared_data = { | ||
435 | .dram = &orion5x_mbus_dram_info, | ||
436 | }; | ||
437 | |||
434 | static struct resource orion5x_xor_shared_resources[] = { | 438 | static struct resource orion5x_xor_shared_resources[] = { |
435 | { | 439 | { |
436 | .name = "xor low", | 440 | .name = "xor low", |
@@ -448,6 +452,9 @@ static struct resource orion5x_xor_shared_resources[] = { | |||
448 | static struct platform_device orion5x_xor_shared = { | 452 | static struct platform_device orion5x_xor_shared = { |
449 | .name = MV_XOR_SHARED_NAME, | 453 | .name = MV_XOR_SHARED_NAME, |
450 | .id = 0, | 454 | .id = 0, |
455 | .dev = { | ||
456 | .platform_data = &orion5x_xor_shared_data, | ||
457 | }, | ||
451 | .num_resources = ARRAY_SIZE(orion5x_xor_shared_resources), | 458 | .num_resources = ARRAY_SIZE(orion5x_xor_shared_resources), |
452 | .resource = orion5x_xor_shared_resources, | 459 | .resource = orion5x_xor_shared_resources, |
453 | }; | 460 | }; |
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index 0722d6510df1..b31ca4cef365 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c | |||
@@ -76,7 +76,7 @@ static int __init dns323_dev_id(void) | |||
76 | 76 | ||
77 | static int __init dns323_pci_init(void) | 77 | static int __init dns323_pci_init(void) |
78 | { | 78 | { |
79 | /* The 5182 doesn't really use it's PCI bus, and initialising PCI | 79 | /* The 5182 doesn't really use its PCI bus, and initialising PCI |
80 | * gets in the way of initialising the SATA controller. | 80 | * gets in the way of initialising the SATA controller. |
81 | */ | 81 | */ |
82 | if (machine_is_dns323() && dns323_dev_id() != MV88F5182_DEV_ID) | 82 | if (machine_is_dns323() && dns323_dev_id() != MV88F5182_DEV_ID) |
@@ -418,7 +418,7 @@ static void __init dns323_init(void) | |||
418 | orion5x_i2c_init(); | 418 | orion5x_i2c_init(); |
419 | orion5x_uart0_init(); | 419 | orion5x_uart0_init(); |
420 | 420 | ||
421 | /* The 5182 has it's SATA controller on-chip, and needs it's own little | 421 | /* The 5182 has its SATA controller on-chip, and needs its own little |
422 | * init routine. | 422 | * init routine. |
423 | */ | 423 | */ |
424 | if (dns323_dev_id() == MV88F5182_DEV_ID) | 424 | if (dns323_dev_id() == MV88F5182_DEV_ID) |
diff --git a/arch/arm/mach-orion5x/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h new file mode 100644 index 000000000000..0a314ddef658 --- /dev/null +++ b/arch/arm/mach-orion5x/ts78xx-fpga.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #define FPGAID(_magic, _rev) ((_magic << 8) + _rev) | ||
2 | |||
3 | /* | ||
4 | * get yer id's from http://ts78xx.digriz.org.uk/ | ||
5 | * do *not* make up your own or 'borrow' any! | ||
6 | */ | ||
7 | enum fpga_ids { | ||
8 | /* Technologic Systems */ | ||
9 | TS7800_REV_B2 = FPGAID(0x00b480, 0x02), | ||
10 | TS7800_REV_B3 = FPGAID(0x00b480, 0x03), | ||
11 | }; | ||
12 | |||
13 | struct fpga_device { | ||
14 | unsigned present:1; | ||
15 | unsigned init:1; | ||
16 | }; | ||
17 | |||
18 | struct fpga_devices { | ||
19 | /* Technologic Systems */ | ||
20 | struct fpga_device ts_rtc; | ||
21 | struct fpga_device ts_nand; | ||
22 | }; | ||
23 | |||
24 | struct ts78xx_fpga_data { | ||
25 | unsigned int id; | ||
26 | int state; | ||
27 | |||
28 | struct fpga_devices supports; | ||
29 | }; | ||
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c index 1368e9fd1a06..f5191ddea085 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,311 @@ 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_B2: |
199 | (board_info >> 31) & 0x1); | 286 | case TS7800_REV_B3: |
287 | ts78xx_fpga.supports.ts_rtc.present = 1; | ||
288 | ts78xx_fpga.supports.ts_nand.present = 1; | ||
289 | break; | ||
290 | default: | ||
291 | ts78xx_fpga.supports.ts_rtc.present = 0; | ||
292 | ts78xx_fpga.supports.ts_nand.present = 0; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static int ts78xx_fpga_load_devices(void) | ||
297 | { | ||
298 | int tmp, ret = 0; | ||
299 | |||
300 | if (ts78xx_fpga.supports.ts_rtc.present == 1) { | ||
301 | tmp = ts78xx_ts_rtc_load(); | ||
302 | if (tmp) { | ||
303 | printk(KERN_INFO "TS-78xx: RTC not registered\n"); | ||
304 | ts78xx_fpga.supports.ts_rtc.present = 0; | ||
305 | } | ||
306 | ret |= tmp; | ||
307 | } | ||
308 | if (ts78xx_fpga.supports.ts_nand.present == 1) { | ||
309 | tmp = ts78xx_ts_nand_load(); | ||
310 | if (tmp) { | ||
311 | printk(KERN_INFO "TS-78xx: NAND not registered\n"); | ||
312 | ts78xx_fpga.supports.ts_nand.present = 0; | ||
313 | } | ||
314 | ret |= tmp; | ||
315 | } | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
320 | static int ts78xx_fpga_unload_devices(void) | ||
321 | { | ||
322 | int ret = 0; | ||
323 | |||
324 | if (ts78xx_fpga.supports.ts_rtc.present == 1) | ||
325 | ts78xx_ts_rtc_unload(); | ||
326 | if (ts78xx_fpga.supports.ts_nand.present == 1) | ||
327 | ts78xx_ts_nand_unload(); | ||
328 | |||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | static int ts78xx_fpga_load(void) | ||
333 | { | ||
334 | ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE); | ||
335 | |||
336 | printk(KERN_INFO "TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n", | ||
337 | (ts78xx_fpga.id >> 8) & 0xffffff, | ||
338 | ts78xx_fpga.id & 0xff); | ||
339 | |||
340 | ts78xx_fpga_supports(); | ||
341 | |||
342 | if (ts78xx_fpga_load_devices()) { | ||
343 | ts78xx_fpga.state = -1; | ||
344 | return -EBUSY; | ||
345 | } | ||
346 | |||
347 | return 0; | ||
200 | }; | 348 | }; |
201 | 349 | ||
350 | static int ts78xx_fpga_unload(void) | ||
351 | { | ||
352 | unsigned int fpga_id; | ||
353 | |||
354 | fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE); | ||
355 | |||
356 | /* | ||
357 | * There does not seem to be a feasible way to block access to the GPIO | ||
358 | * pins from userspace (/dev/mem). This if clause should hopefully warn | ||
359 | * those foolish enough not to follow 'policy' :) | ||
360 | * | ||
361 | * UrJTAG SVN since r1381 can be used to reprogram the FPGA | ||
362 | */ | ||
363 | if (ts78xx_fpga.id != fpga_id) { | ||
364 | printk(KERN_ERR "TS-78xx FPGA: magic/rev mismatch\n" | ||
365 | "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n", | ||
366 | (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff, | ||
367 | (fpga_id >> 8) & 0xffffff, fpga_id & 0xff); | ||
368 | ts78xx_fpga.state = -1; | ||
369 | return -EBUSY; | ||
370 | } | ||
371 | |||
372 | if (ts78xx_fpga_unload_devices()) { | ||
373 | ts78xx_fpga.state = -1; | ||
374 | return -EBUSY; | ||
375 | } | ||
376 | |||
377 | return 0; | ||
378 | }; | ||
379 | |||
380 | static ssize_t ts78xx_fpga_show(struct kobject *kobj, | ||
381 | struct kobj_attribute *attr, char *buf) | ||
382 | { | ||
383 | if (ts78xx_fpga.state < 0) | ||
384 | return sprintf(buf, "borked\n"); | ||
385 | |||
386 | return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline"); | ||
387 | } | ||
388 | |||
389 | static ssize_t ts78xx_fpga_store(struct kobject *kobj, | ||
390 | struct kobj_attribute *attr, const char *buf, size_t n) | ||
391 | { | ||
392 | int value, ret; | ||
393 | |||
394 | if (ts78xx_fpga.state < 0) { | ||
395 | printk(KERN_ERR "TS-78xx FPGA: borked, you must powercycle asap\n"); | ||
396 | return -EBUSY; | ||
397 | } | ||
398 | |||
399 | if (strncmp(buf, "online", sizeof("online") - 1) == 0) | ||
400 | value = 1; | ||
401 | else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0) | ||
402 | value = 0; | ||
403 | else { | ||
404 | printk(KERN_ERR "ts78xx_fpga_store: Invalid value\n"); | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | |||
408 | if (ts78xx_fpga.state == value) | ||
409 | return n; | ||
410 | |||
411 | ret = (ts78xx_fpga.state == 0) | ||
412 | ? ts78xx_fpga_load() | ||
413 | : ts78xx_fpga_unload(); | ||
414 | |||
415 | if (!(ret < 0)) | ||
416 | ts78xx_fpga.state = value; | ||
417 | |||
418 | return n; | ||
419 | } | ||
420 | |||
421 | static struct kobj_attribute ts78xx_fpga_attr = | ||
422 | __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store); | ||
423 | |||
202 | /***************************************************************************** | 424 | /***************************************************************************** |
203 | * General Setup | 425 | * General Setup |
204 | ****************************************************************************/ | 426 | ****************************************************************************/ |
@@ -223,30 +445,29 @@ static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = { | |||
223 | { 17, MPP_UART }, | 445 | { 17, MPP_UART }, |
224 | { 18, MPP_UART }, | 446 | { 18, MPP_UART }, |
225 | { 19, MPP_UART }, | 447 | { 19, MPP_UART }, |
448 | /* | ||
449 | * MPP[20] PCI Clock Out 1 | ||
450 | * MPP[21] PCI Clock Out 0 | ||
451 | * MPP[22] Unused | ||
452 | * MPP[23] Unused | ||
453 | * MPP[24] Unused | ||
454 | * MPP[25] Unused | ||
455 | */ | ||
226 | { -1 }, | 456 | { -1 }, |
227 | }; | 457 | }; |
228 | 458 | ||
229 | static void __init ts78xx_init(void) | 459 | static void __init ts78xx_init(void) |
230 | { | 460 | { |
461 | int ret; | ||
462 | |||
231 | /* | 463 | /* |
232 | * Setup basic Orion functions. Need to be called early. | 464 | * Setup basic Orion functions. Need to be called early. |
233 | */ | 465 | */ |
234 | orion5x_init(); | 466 | orion5x_init(); |
235 | 467 | ||
236 | ts78xx_print_board_id(); | ||
237 | |||
238 | orion5x_mpp_conf(ts78xx_mpp_modes); | 468 | orion5x_mpp_conf(ts78xx_mpp_modes); |
239 | 469 | ||
240 | /* | 470 | /* |
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. | 471 | * Configure peripherals. |
251 | */ | 472 | */ |
252 | orion5x_ehci0_init(); | 473 | orion5x_ehci0_init(); |
@@ -257,12 +478,12 @@ static void __init ts78xx_init(void) | |||
257 | orion5x_uart1_init(); | 478 | orion5x_uart1_init(); |
258 | orion5x_xor_init(); | 479 | orion5x_xor_init(); |
259 | 480 | ||
260 | orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE, | 481 | /* FPGA init */ |
261 | TS78XX_NOR_BOOT_SIZE); | 482 | ts78xx_fpga_devices_zero_init(); |
262 | platform_device_register(&ts78xx_nor_boot_flash); | 483 | ret = ts78xx_fpga_load(); |
263 | 484 | ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr); | |
264 | if (!ts78xx_rtc_init()) | 485 | if (ret) |
265 | printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); | 486 | printk(KERN_ERR "sysfs_create_file failed: %d\n", ret); |
266 | } | 487 | } |
267 | 488 | ||
268 | MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") | 489 | MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") |