aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-orion5x/ts78xx-setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-orion5x/ts78xx-setup.c')
-rw-r--r--arch/arm/mach-orion5x/ts78xx-setup.c310
1 files changed, 202 insertions, 108 deletions
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index 1368e9fd1a06..baa25d0fd5c9 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -10,8 +10,8 @@
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>
@@ -21,6 +21,7 @@
21#include <mach/orion5x.h> 21#include <mach/orion5x.h>
22#include "common.h" 22#include "common.h"
23#include "mpp.h" 23#include "mpp.h"
24#include "ts78xx-fpga.h"
24 25
25/***************************************************************************** 26/*****************************************************************************
26 * TS-78xx Info 27 * TS-78xx Info
@@ -33,18 +34,11 @@
33#define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000 34#define TS78XX_FPGA_REGS_VIRT_BASE 0xff900000
34#define TS78XX_FPGA_REGS_SIZE SZ_1M 35#define TS78XX_FPGA_REGS_SIZE SZ_1M
35 36
36#define TS78XX_FPGA_REGS_SYSCON_ID (TS78XX_FPGA_REGS_VIRT_BASE | 0x000) 37static struct ts78xx_fpga_data ts78xx_fpga = {
37#define TS78XX_FPGA_REGS_SYSCON_LCDI (TS78XX_FPGA_REGS_VIRT_BASE | 0x004) 38 .id = 0,
38#define TS78XX_FPGA_REGS_SYSCON_LCDO (TS78XX_FPGA_REGS_VIRT_BASE | 0x008) 39 .state = 1,
39 40/* .supports = ... - populated by ts78xx_fpga_supports() */
40#define TS78XX_FPGA_REGS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808) 41};
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 42
49/***************************************************************************** 43/*****************************************************************************
50 * I/O Address Mapping 44 * I/O Address Mapping
@@ -65,73 +59,48 @@ void __init ts78xx_map_io(void)
65} 59}
66 60
67/***************************************************************************** 61/*****************************************************************************
68 * 512kB NOR Boot Flash - the chip is a M25P40 62 * Ethernet
69 ****************************************************************************/ 63 ****************************************************************************/
70static struct mtd_partition ts78xx_nor_boot_flash_resources[] = { 64static struct mv643xx_eth_platform_data ts78xx_eth_data = {
71 { 65 .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
80static 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
86static 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
92static 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}; 66};
101 67
102/***************************************************************************** 68/*****************************************************************************
103 * Ethernet 69 * SATA
104 ****************************************************************************/ 70 ****************************************************************************/
105static struct mv643xx_eth_platform_data ts78xx_eth_data = { 71static struct mv_sata_platform_data ts78xx_sata_data = {
106 .phy_addr = MV643XX_ETH_PHY_ADDR(0), 72 .n_ports = 2,
107}; 73};
108 74
109/***************************************************************************** 75/*****************************************************************************
110 * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c 76 * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
111 ****************************************************************************/ 77 ****************************************************************************/
112#ifdef CONFIG_RTC_DRV_M48T86 78#ifdef CONFIG_RTC_DRV_M48T86
113static unsigned char ts78xx_rtc_readbyte(unsigned long addr) 79#define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE | 0x808)
80#define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE | 0x80c)
81
82static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr)
114{ 83{
115 writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); 84 writeb(addr, TS_RTC_CTRL);
116 return readb(TS78XX_FPGA_REGS_RTC_DATA); 85 return readb(TS_RTC_DATA);
117} 86}
118 87
119static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr) 88static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr)
120{ 89{
121 writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL); 90 writeb(addr, TS_RTC_CTRL);
122 writeb(value, TS78XX_FPGA_REGS_RTC_DATA); 91 writeb(value, TS_RTC_DATA);
123} 92}
124 93
125static struct m48t86_ops ts78xx_rtc_ops = { 94static struct m48t86_ops ts78xx_ts_rtc_ops = {
126 .readbyte = ts78xx_rtc_readbyte, 95 .readbyte = ts78xx_ts_rtc_readbyte,
127 .writebyte = ts78xx_rtc_writebyte, 96 .writebyte = ts78xx_ts_rtc_writebyte,
128}; 97};
129 98
130static struct platform_device ts78xx_rtc_device = { 99static struct platform_device ts78xx_ts_rtc_device = {
131 .name = "rtc-m48t86", 100 .name = "rtc-m48t86",
132 .id = -1, 101 .id = -1,
133 .dev = { 102 .dev = {
134 .platform_data = &ts78xx_rtc_ops, 103 .platform_data = &ts78xx_ts_rtc_ops,
135 }, 104 },
136 .num_resources = 0, 105 .num_resources = 0,
137}; 106};
@@ -146,59 +115,185 @@ 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 115 * TODO: track down a guinea pig without an RTC to see if we can work out a
147 * better RTC detection routine 116 * better RTC detection routine
148 */ 117 */
149static int __init ts78xx_rtc_init(void) 118static int ts78xx_ts_rtc_load(void)
150{ 119{
151 unsigned char tmp_rtc0, tmp_rtc1; 120 unsigned char tmp_rtc0, tmp_rtc1;
152 121
153 tmp_rtc0 = ts78xx_rtc_readbyte(126); 122 tmp_rtc0 = ts78xx_ts_rtc_readbyte(126);
154 tmp_rtc1 = ts78xx_rtc_readbyte(127); 123 tmp_rtc1 = ts78xx_ts_rtc_readbyte(127);
155 124
156 ts78xx_rtc_writebyte(0x00, 126); 125 ts78xx_ts_rtc_writebyte(0x00, 126);
157 ts78xx_rtc_writebyte(0x55, 127); 126 ts78xx_ts_rtc_writebyte(0x55, 127);
158 if (ts78xx_rtc_readbyte(127) == 0x55) { 127 if (ts78xx_ts_rtc_readbyte(127) == 0x55) {
159 ts78xx_rtc_writebyte(0xaa, 127); 128 ts78xx_ts_rtc_writebyte(0xaa, 127);
160 if (ts78xx_rtc_readbyte(127) == 0xaa 129 if (ts78xx_ts_rtc_readbyte(127) == 0xaa
161 && ts78xx_rtc_readbyte(126) == 0x00) { 130 && ts78xx_ts_rtc_readbyte(126) == 0x00) {
162 ts78xx_rtc_writebyte(tmp_rtc0, 126); 131 ts78xx_ts_rtc_writebyte(tmp_rtc0, 126);
163 ts78xx_rtc_writebyte(tmp_rtc1, 127); 132 ts78xx_ts_rtc_writebyte(tmp_rtc1, 127);
164 platform_device_register(&ts78xx_rtc_device); 133 if (ts78xx_fpga.supports.ts_rtc.init == 0) {
165 return 1; 134 ts78xx_fpga.supports.ts_rtc.init = 1;
135 platform_device_register(&ts78xx_ts_rtc_device);
136 } else
137 platform_device_add(&ts78xx_ts_rtc_device);
138 return 0;
166 } 139 }
167 } 140 }
168 141
169 return 0; 142 ts78xx_fpga.supports.ts_rtc.present = 0;
143 return -ENODEV;
170}; 144};
145
146static void ts78xx_ts_rtc_unload(void)
147{
148 platform_device_del(&ts78xx_ts_rtc_device);
149}
171#else 150#else
172static int __init ts78xx_rtc_init(void) 151static int ts78xx_ts_rtc_load(void)
173{ 152{
174 return 0; 153 return 0;
175} 154}
155
156static void ts78xx_ts_rtc_unload(void)
157{
158}
176#endif 159#endif
177 160
178/***************************************************************************** 161/*****************************************************************************
179 * SATA 162 * FPGA 'hotplug' support code
180 ****************************************************************************/ 163 ****************************************************************************/
181static struct mv_sata_platform_data ts78xx_sata_data = { 164static void ts78xx_fpga_devices_zero_init(void)
182 .n_ports = 2, 165{
166 ts78xx_fpga.supports.ts_rtc.init = 0;
167}
168
169static void ts78xx_fpga_supports(void)
170{
171 /* TODO: put this 'table' into ts78xx-fpga.h */
172 switch (ts78xx_fpga.id) {
173 case TS7800_REV_B:
174 ts78xx_fpga.supports.ts_rtc.present = 1;
175 break;
176 default:
177 ts78xx_fpga.supports.ts_rtc.present = 0;
178 }
179}
180
181static int ts78xx_fpga_load_devices(void)
182{
183 int tmp, ret = 0;
184
185 if (ts78xx_fpga.supports.ts_rtc.present == 1) {
186 tmp = ts78xx_ts_rtc_load();
187 if (tmp)
188 printk(KERN_INFO "TS-78xx RTC not detected or enabled\n");
189 ret |= tmp;
190 }
191
192 return ret;
193}
194
195static int ts78xx_fpga_unload_devices(void)
196{
197 int ret = 0;
198
199 if (ts78xx_fpga.supports.ts_rtc.present == 1)
200 ts78xx_ts_rtc_unload();
201
202 return ret;
203}
204
205static int ts78xx_fpga_load(void)
206{
207 ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
208
209 printk(KERN_INFO "TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n",
210 (ts78xx_fpga.id >> 8) & 0xffffff,
211 ts78xx_fpga.id & 0xff);
212
213 ts78xx_fpga_supports();
214
215 if (ts78xx_fpga_load_devices()) {
216 ts78xx_fpga.state = -1;
217 return -EBUSY;
218 }
219
220 return 0;
183}; 221};
184 222
185/***************************************************************************** 223static int ts78xx_fpga_unload(void)
186 * print some information regarding the board
187 ****************************************************************************/
188static void __init ts78xx_print_board_id(void)
189{ 224{
190 unsigned int board_info; 225 unsigned int fpga_id;
191 226
192 board_info = readl(TS78XX_FPGA_REGS_SYSCON_ID); 227 fpga_id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
193 printk(KERN_INFO "TS-78xx Info: FPGA rev=%.2x, Board Magic=%.6x, ", 228
194 board_info & 0xff, 229 /*
195 (board_info >> 8) & 0xffffff); 230 * There does not seem to be a feasible way to block access to the GPIO
196 board_info = readl(TS78XX_FPGA_REGS_SYSCON_LCDI); 231 * pins from userspace (/dev/mem). This if clause should hopefully warn
197 printk("JP1=%d, JP2=%d\n", 232 * those foolish enough not to follow 'policy' :)
198 (board_info >> 30) & 0x1, 233 *
199 (board_info >> 31) & 0x1); 234 * UrJTAG SVN since r1381 can be used to reprogram the FPGA
235 */
236 if (ts78xx_fpga.id != fpga_id) {
237 printk(KERN_ERR "TS-78xx FPGA: magic/rev mismatch\n"
238 "TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n",
239 (ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff,
240 (fpga_id >> 8) & 0xffffff, fpga_id & 0xff);
241 ts78xx_fpga.state = -1;
242 return -EBUSY;
243 }
244
245 if (ts78xx_fpga_unload_devices()) {
246 ts78xx_fpga.state = -1;
247 return -EBUSY;
248 }
249
250 return 0;
200}; 251};
201 252
253static ssize_t ts78xx_fpga_show(struct kobject *kobj,
254 struct kobj_attribute *attr, char *buf)
255{
256 if (ts78xx_fpga.state < 0)
257 return sprintf(buf, "borked\n");
258
259 return sprintf(buf, "%s\n", (ts78xx_fpga.state) ? "online" : "offline");
260}
261
262static ssize_t ts78xx_fpga_store(struct kobject *kobj,
263 struct kobj_attribute *attr, const char *buf, size_t n)
264{
265 int value, ret;
266
267 if (ts78xx_fpga.state < 0) {
268 printk(KERN_ERR "TS-78xx FPGA: borked, you must powercycle asap\n");
269 return -EBUSY;
270 }
271
272 if (strncmp(buf, "online", sizeof("online") - 1) == 0)
273 value = 1;
274 else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
275 value = 0;
276 else {
277 printk(KERN_ERR "ts78xx_fpga_store: Invalid value\n");
278 return -EINVAL;
279 }
280
281 if (ts78xx_fpga.state == value)
282 return n;
283
284 ret = (ts78xx_fpga.state == 0)
285 ? ts78xx_fpga_load()
286 : ts78xx_fpga_unload();
287
288 if (!(ret < 0))
289 ts78xx_fpga.state = value;
290
291 return n;
292}
293
294static struct kobj_attribute ts78xx_fpga_attr =
295 __ATTR(ts78xx_fpga, 0644, ts78xx_fpga_show, ts78xx_fpga_store);
296
202/***************************************************************************** 297/*****************************************************************************
203 * General Setup 298 * General Setup
204 ****************************************************************************/ 299 ****************************************************************************/
@@ -223,30 +318,29 @@ static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = {
223 { 17, MPP_UART }, 318 { 17, MPP_UART },
224 { 18, MPP_UART }, 319 { 18, MPP_UART },
225 { 19, MPP_UART }, 320 { 19, MPP_UART },
321 /*
322 * MPP[20] PCI Clock Out 1
323 * MPP[21] PCI Clock Out 0
324 * MPP[22] Unused
325 * MPP[23] Unused
326 * MPP[24] Unused
327 * MPP[25] Unused
328 */
226 { -1 }, 329 { -1 },
227}; 330};
228 331
229static void __init ts78xx_init(void) 332static void __init ts78xx_init(void)
230{ 333{
334 int ret;
335
231 /* 336 /*
232 * Setup basic Orion functions. Need to be called early. 337 * Setup basic Orion functions. Need to be called early.
233 */ 338 */
234 orion5x_init(); 339 orion5x_init();
235 340
236 ts78xx_print_board_id();
237
238 orion5x_mpp_conf(ts78xx_mpp_modes); 341 orion5x_mpp_conf(ts78xx_mpp_modes);
239 342
240 /* 343 /*
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. 344 * Configure peripherals.
251 */ 345 */
252 orion5x_ehci0_init(); 346 orion5x_ehci0_init();
@@ -257,12 +351,12 @@ static void __init ts78xx_init(void)
257 orion5x_uart1_init(); 351 orion5x_uart1_init();
258 orion5x_xor_init(); 352 orion5x_xor_init();
259 353
260 orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE, 354 /* FPGA init */
261 TS78XX_NOR_BOOT_SIZE); 355 ts78xx_fpga_devices_zero_init();
262 platform_device_register(&ts78xx_nor_boot_flash); 356 ret = ts78xx_fpga_load();
263 357 ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr);
264 if (!ts78xx_rtc_init()) 358 if (ret)
265 printk(KERN_INFO "TS-78xx RTC not detected or enabled\n"); 359 printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
266} 360}
267 361
268MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC") 362MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")