Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[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 <asm/arch/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       = 0,
107         .force_phy_addr = 1,
108 };
109
110 /*****************************************************************************
111  * RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
112  ****************************************************************************/
113 #ifdef CONFIG_RTC_DRV_M48T86
114 static unsigned char ts78xx_rtc_readbyte(unsigned long addr)
115 {
116         writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
117         return readb(TS78XX_FPGA_REGS_RTC_DATA);
118 }
119
120 static void ts78xx_rtc_writebyte(unsigned char value, unsigned long addr)
121 {
122         writeb(addr, TS78XX_FPGA_REGS_RTC_CTRL);
123         writeb(value, TS78XX_FPGA_REGS_RTC_DATA);
124 }
125
126 static struct m48t86_ops ts78xx_rtc_ops = {
127         .readbyte       = ts78xx_rtc_readbyte,
128         .writebyte      = ts78xx_rtc_writebyte,
129 };
130
131 static struct platform_device ts78xx_rtc_device = {
132         .name           = "rtc-m48t86",
133         .id             = -1,
134         .dev            = {
135                 .platform_data  = &ts78xx_rtc_ops,
136         },
137         .num_resources  = 0,
138 };
139
140 /*
141  * TS uses some of the user storage space on the RTC chip so see if it is
142  * present; as it's an optional feature at purchase time and not all boards
143  * will have it present
144  *
145  * I've used the method TS use in their rtc7800.c example for the detection
146  *
147  * TODO: track down a guinea pig without an RTC to see if we can work out a
148  *              better RTC detection routine
149  */
150 static int __init ts78xx_rtc_init(void)
151 {
152         unsigned char tmp_rtc0, tmp_rtc1;
153
154         tmp_rtc0 = ts78xx_rtc_readbyte(126);
155         tmp_rtc1 = ts78xx_rtc_readbyte(127);
156
157         ts78xx_rtc_writebyte(0x00, 126);
158         ts78xx_rtc_writebyte(0x55, 127);
159         if (ts78xx_rtc_readbyte(127) == 0x55) {
160                 ts78xx_rtc_writebyte(0xaa, 127);
161                 if (ts78xx_rtc_readbyte(127) == 0xaa
162                                 && ts78xx_rtc_readbyte(126) == 0x00) {
163                         ts78xx_rtc_writebyte(tmp_rtc0, 126);
164                         ts78xx_rtc_writebyte(tmp_rtc1, 127);
165                         platform_device_register(&ts78xx_rtc_device);
166                         return 1;
167                 }
168         }
169
170         return 0;
171 };
172 #else
173 static int __init ts78xx_rtc_init(void)
174 {
175         return 0;
176 }
177 #endif
178
179 /*****************************************************************************
180  * SATA
181  ****************************************************************************/
182 static struct mv_sata_platform_data ts78xx_sata_data = {
183         .n_ports        = 2,
184 };
185
186 /*****************************************************************************
187  * print some information regarding the board
188  ****************************************************************************/
189 static void __init ts78xx_print_board_id(void)
190 {
191         unsigned int board_info;
192
193         board_info = readl(TS78XX_FPGA_REGS_SYSCON_ID);
194         printk(KERN_INFO "TS-78xx Info: FPGA rev=%.2x, Board Magic=%.6x, ",
195                                 board_info & 0xff,
196                                 (board_info >> 8) & 0xffffff);
197         board_info = readl(TS78XX_FPGA_REGS_SYSCON_LCDI);
198         printk("JP1=%d, JP2=%d\n",
199                                 (board_info >> 30) & 0x1,
200                                 (board_info >> 31) & 0x1);
201 };
202
203 /*****************************************************************************
204  * General Setup
205  ****************************************************************************/
206 static struct orion5x_mpp_mode ts78xx_mpp_modes[] __initdata = {
207         {  0, MPP_UNUSED },
208         {  1, MPP_GPIO },               /* JTAG Clock */
209         {  2, MPP_GPIO },               /* JTAG Data In */
210         {  3, MPP_GPIO },               /* Lat ECP2 256 FPGA - PB2B */
211         {  4, MPP_GPIO },               /* JTAG Data Out */
212         {  5, MPP_GPIO },               /* JTAG TMS */
213         {  6, MPP_GPIO },               /* Lat ECP2 256 FPGA - PB31A_CLK4+ */
214         {  7, MPP_GPIO },               /* Lat ECP2 256 FPGA - PB22B */
215         {  8, MPP_UNUSED },
216         {  9, MPP_UNUSED },
217         { 10, MPP_UNUSED },
218         { 11, MPP_UNUSED },
219         { 12, MPP_UNUSED },
220         { 13, MPP_UNUSED },
221         { 14, MPP_UNUSED },
222         { 15, MPP_UNUSED },
223         { 16, MPP_UART },
224         { 17, MPP_UART },
225         { 18, MPP_UART },
226         { 19, MPP_UART },
227         { -1 },
228 };
229
230 static void __init ts78xx_init(void)
231 {
232         /*
233          * Setup basic Orion functions. Need to be called early.
234          */
235         orion5x_init();
236
237         ts78xx_print_board_id();
238
239         orion5x_mpp_conf(ts78xx_mpp_modes);
240
241         /*
242          * MPP[20] PCI Clock Out 1
243          * MPP[21] PCI Clock Out 0
244          * MPP[22] Unused
245          * MPP[23] Unused
246          * MPP[24] Unused
247          * MPP[25] Unused
248          */
249
250         /*
251          * Configure peripherals.
252          */
253         orion5x_ehci0_init();
254         orion5x_ehci1_init();
255         orion5x_eth_init(&ts78xx_eth_data);
256         orion5x_sata_init(&ts78xx_sata_data);
257         orion5x_uart0_init();
258         orion5x_uart1_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