aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/configs/orion5x_defconfig2
-rw-r--r--arch/arm/mach-orion5x/Kconfig1
-rw-r--r--arch/arm/mach-orion5x/ts78xx-fpga.h27
-rw-r--r--arch/arm/mach-orion5x/ts78xx-setup.c310
4 files changed, 231 insertions, 109 deletions
diff --git a/arch/arm/configs/orion5x_defconfig b/arch/arm/configs/orion5x_defconfig
index a8ee6984a09e..a34ea6b2cc51 100644
--- a/arch/arm/configs/orion5x_defconfig
+++ b/arch/arm/configs/orion5x_defconfig
@@ -1177,7 +1177,7 @@ CONFIG_RTC_DRV_S35390A=y
1177# CONFIG_RTC_DRV_DS1553 is not set 1177# CONFIG_RTC_DRV_DS1553 is not set
1178# CONFIG_RTC_DRV_DS1742 is not set 1178# CONFIG_RTC_DRV_DS1742 is not set
1179# CONFIG_RTC_DRV_STK17TA8 is not set 1179# CONFIG_RTC_DRV_STK17TA8 is not set
1180# CONFIG_RTC_DRV_M48T86 is not set 1180CONFIG_RTC_DRV_M48T86=y
1181# CONFIG_RTC_DRV_M48T59 is not set 1181# CONFIG_RTC_DRV_M48T59 is not set
1182# CONFIG_RTC_DRV_V3020 is not set 1182# CONFIG_RTC_DRV_V3020 is not set
1183 1183
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
72config MACH_TS78XX 72config 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/ts78xx-fpga.h b/arch/arm/mach-orion5x/ts78xx-fpga.h
new file mode 100644
index 000000000000..0b8e30faff14
--- /dev/null
+++ b/arch/arm/mach-orion5x/ts78xx-fpga.h
@@ -0,0 +1,27 @@
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 */
7enum fpga_ids {
8 /* Technologic Systems */
9 TS7800_REV_B = FPGAID(0x00b480, 0x03),
10};
11
12struct fpga_device {
13 unsigned present:1;
14 unsigned init:1;
15};
16
17struct fpga_devices {
18 /* Technologic Systems */
19 struct fpga_device ts_rtc;
20};
21
22struct ts78xx_fpga_data {
23 unsigned int id;
24 int state;
25
26 struct fpga_devices supports;
27};
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")