Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
[linux-2.6] / arch / arm / mach-orion5x / ts78xx-setup.c
1 /*
2  * arch/arm/mach-orion5x/ts78xx-setup.c
3  *
4  * Maintainer: Alexander Clouter <alex@digriz.org.uk>
5  *
6  * This file is licensed under the terms of the GNU General Public
7  * License version 2.  This program is licensed "as is" without any
8  * warranty of any kind, whether express or implied.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/platform_device.h>
14 #include <linux/mtd/physmap.h>
15 #include <linux/mv643xx_eth.h>
16 #include <linux/ata_platform.h>
17 #include <linux/m48t86.h>
18 #include <asm/mach-types.h>
19 #include <asm/mach/arch.h>
20 #include <asm/mach/map.h>
21 #include <mach/orion5x.h>
22 #include "common.h"
23 #include "mpp.h"
24
25 /*****************************************************************************
26  * TS-78xx Info
27  ****************************************************************************/
28
29 /*
30  * FPGA - lives where the PCI bus would be at ORION5X_PCI_MEM_PHYS_BASE
31  */
32 #define TS78XX_FPGA_REGS_PHYS_BASE      0xe8000000
33 #define TS78XX_FPGA_REGS_VIRT_BASE      0xff900000
34 #define TS78XX_FPGA_REGS_SIZE           SZ_1M
35
36 #define TS78XX_FPGA_REGS_SYSCON_ID      (TS78XX_FPGA_REGS_VIRT_BASE | 0x000)
37 #define TS78XX_FPGA_REGS_SYSCON_LCDI    (TS78XX_FPGA_REGS_VIRT_BASE | 0x004)
38 #define TS78XX_FPGA_REGS_SYSCON_LCDO    (TS78XX_FPGA_REGS_VIRT_BASE | 0x008)
39
40 #define TS78XX_FPGA_REGS_RTC_CTRL       (TS78XX_FPGA_REGS_VIRT_BASE | 0x808)
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
49 /*****************************************************************************
50  * I/O Address Mapping
51  ****************************************************************************/
52 static struct map_desc ts78xx_io_desc[] __initdata = {
53         {
54                 .virtual        = TS78XX_FPGA_REGS_VIRT_BASE,
55                 .pfn            = __phys_to_pfn(TS78XX_FPGA_REGS_PHYS_BASE),
56                 .length         = TS78XX_FPGA_REGS_SIZE,
57                 .type           = MT_DEVICE,
58         },
59 };
60
61 void __init ts78xx_map_io(void)
62 {
63         orion5x_map_io();
64         iotable_init(ts78xx_io_desc, ARRAY_SIZE(ts78xx_io_desc));
65 }
66
67 /*****************************************************************************
68  * 512kB NOR Boot Flash - the chip is a M25P40
69  ****************************************************************************/
70 static struct mtd_partition ts78xx_nor_boot_flash_resources[] = {
71         {
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 };
101
102 /*****************************************************************************
103  * Ethernet
104  ****************************************************************************/
105 static struct mv643xx_eth_platform_data ts78xx_eth_data = {
106         .phy_addr       = MV643XX_ETH_PHY_ADDR(0),
107 };
108
109 /*****************************************************************************
110  * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
111  ****************************************************************************/
112 #ifdef CONFIG_RTC_DRV_M48T86
113 static unsigned char ts78xx_rtc_readbyte(unsigned long addr)
114 {
115         writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
116         return readb(TS78XX_FPGA_REGS_RTC_DATA);
117 }
118
119 static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr)
120 {
121         writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
122         writeb(value, TS78XX_FPGA_REGS_RTC_DATA);
123 }
124
125 static struct m48t86_ops ts78xx_rtc_ops = {
126         .readbyte       = ts78xx_rtc_readbyte,
127         .writebyte      = ts78xx_rtc_writebyte,
128 };
129
130 static struct platform_device ts78xx_rtc_device = {
131         .name           = "rtc-m48t86",
132         .id             = -1,
133         .dev            = {
134                 .platform_data  = &ts78xx_rtc_ops,
135         },
136         .num_resources  = 0,
137 };
138
139 /*
140  * TS uses some of the user storage space on the RTC chip so see if it is
141  * present; as it's an optional feature at purchase time and not all boards
142  * will have it present
143  *
144  * I've used the method TS use in their rtc7800.c example for the detection
145  *
146  * TODO: track down a guinea pig without an RTC to see if we can work out a
147  *              better RTC detection routine
148  */
149 static int __init ts78xx_rtc_init(void)
150 {
151         unsigned char tmp_rtc0, tmp_rtc1;
152
153         tmp_rtc0 = ts78xx_rtc_readbyte(126);
154         tmp_rtc1 = ts78xx_rtc_readbyte(127);
155
156         ts78xx_rtc_writebyte(0x00, 126);
157         ts78xx_rtc_writebyte(0x55, 127);
158         if (ts78xx_rtc_readbyte(127) == 0x55) {
159                 ts78xx_rtc_writebyte(0xaa, 127);
160                 if (ts78xx_rtc_readbyte(127) == 0xaa
161                                 && ts78xx_rtc_readbyte(126) == 0x00) {
162                         ts78xx_rtc_writebyte(tmp_rtc0, 126);
163                         ts78xx_rtc_writebyte(tmp_rtc1, 127);
164                         platform_device_register(&ts78xx_rtc_device);
165                         return 1;
166                 }
167         }
168
169         return 0;
170 };
171 #else
172 static int __init ts78xx_rtc_init(void)
173 {
174         return 0;
175 }
176 #endif
177
178 /*****************************************************************************
179  * SATA
180  ****************************************************************************/
181 static struct mv_sata_platform_data ts78xx_sata_data = {
182         .n_ports        = 2,
183 };
184
185 /*****************************************************************************
186  * print some information regarding the board
187  ****************************************************************************/
188 static void __init ts78xx_print_board_id(void)
189 {
190         unsigned int board_info;
191
192         board_info = readl(TS78XX_FPGA_REGS_SYSCON_ID);
193         printk(KERN_INFO "TS-78xx Info: FPGA rev=%.2x, Board Magic=%.6x, ",
194                                 board_info & 0xff,
195                                 (board_info >> 8) & 0xffffff);
196         board_info = readl(TS78XX_FPGA_REGS_SYSCON_LCDI);
197         printk("JP1=%d, JP2=%d\n",
198                                 (board_info >> 30) & 0x1,
199                                 (board_info >> 31) & 0x1);
200 };
201
202 /*****************************************************************************
203  * General Setup
204  ****************************************************************************/
205 static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = {
206         {  0, MPP_UNUSED },
207         {  1, MPP_GPIO },               /* JTAG Clock */
208         {  2, MPP_GPIO },               /* JTAG Data In */
209         {  3, MPP_GPIO },               /* Lat ECP2 256 FPGA - PB2B */
210         {  4, MPP_GPIO },               /* JTAG Data Out */
211         {  5, MPP_GPIO },               /* JTAG TMS */
212         {  6, MPP_GPIO },               /* Lat ECP2 256 FPGA - PB31A_CLK4+ */
213         {  7, MPP_GPIO },               /* Lat ECP2 256 FPGA - PB22B */
214         {  8, MPP_UNUSED },
215         {  9, MPP_UNUSED },
216         { 10, MPP_UNUSED },
217         { 11, MPP_UNUSED },
218         { 12, MPP_UNUSED },
219         { 13, MPP_UNUSED },
220         { 14, MPP_UNUSED },
221         { 15, MPP_UNUSED },
222         { 16, MPP_UART },
223         { 17, MPP_UART },
224         { 18, MPP_UART },
225         { 19, MPP_UART },
226         { -1 },
227 };
228
229 static void __init ts78xx_init(void)
230 {
231         /*
232          * Setup basic Orion functions. Need to be called early.
233          */
234         orion5x_init();
235
236         ts78xx_print_board_id();
237
238         orion5x_mpp_conf(ts78xx_mpp_modes);
239
240         /*
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.
251          */
252         orion5x_ehci0_init();
253         orion5x_ehci1_init();
254         orion5x_eth_init(&ts78xx_eth_data);
255         orion5x_sata_init(&ts78xx_sata_data);
256         orion5x_uart0_init();
257         orion5x_uart1_init();
258         orion5x_xor_init();
259
260         orion5x_setup_dev_boot_win(TS78XX_NOR_BOOT_BASE,
261                                    TS78XX_NOR_BOOT_SIZE);
262         platform_device_register(&ts78xx_nor_boot_flash);
263
264         if (!ts78xx_rtc_init())
265                 printk(KERN_INFO "TS-78xx RTC not detected or enabled\n");
266 }
267
268 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
269         /* Maintainer: Alexander Clouter <alex@digriz.org.uk> */
270         .phys_io        = ORION5X_REGS_PHYS_BASE,
271         .io_pg_offst    = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
272         .boot_params    = 0x00000100,
273         .init_machine   = ts78xx_init,
274         .map_io         = ts78xx_map_io,
275         .init_irq       = orion5x_init_irq,
276         .timer          = &orion5x_timer,
277 MACHINE_END