Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[pandora-kernel.git] / arch / arm / mach-ixp4xx / fsg-setup.c
1 /*
2  * arch/arm/mach-ixp4xx/fsg-setup.c
3  *
4  * FSG board-setup
5  *
6  * Copyright (C) 2008 Rod Whitby <rod@whitby.id.au>
7  *
8  * based on ixdp425-setup.c:
9  *      Copyright (C) 2003-2004 MontaVista Software, Inc.
10  * based on nslu2-power.c
11  *      Copyright (C) 2005 Tower Technologies
12  *
13  * Author: Rod Whitby <rod@whitby.id.au>
14  * Maintainers: http://www.nslu2-linux.org/
15  *
16  */
17
18 #include <linux/if_ether.h>
19 #include <linux/irq.h>
20 #include <linux/serial.h>
21 #include <linux/serial_8250.h>
22 #include <linux/leds.h>
23 #include <linux/reboot.h>
24 #include <linux/i2c.h>
25 #include <linux/i2c-gpio.h>
26 #include <linux/io.h>
27 #include <asm/mach-types.h>
28 #include <asm/mach/arch.h>
29 #include <asm/mach/flash.h>
30 #include <asm/gpio.h>
31
32 #define FSG_SDA_PIN             12
33 #define FSG_SCL_PIN             13
34
35 #define FSG_SB_GPIO             4       /* sync button */
36 #define FSG_RB_GPIO             9       /* reset button */
37 #define FSG_UB_GPIO             10      /* usb button */
38
39 static struct flash_platform_data fsg_flash_data = {
40         .map_name               = "cfi_probe",
41         .width                  = 2,
42 };
43
44 static struct resource fsg_flash_resource = {
45         .flags                  = IORESOURCE_MEM,
46 };
47
48 static struct platform_device fsg_flash = {
49         .name                   = "IXP4XX-Flash",
50         .id                     = 0,
51         .dev = {
52                 .platform_data  = &fsg_flash_data,
53         },
54         .num_resources          = 1,
55         .resource               = &fsg_flash_resource,
56 };
57
58 static struct i2c_gpio_platform_data fsg_i2c_gpio_data = {
59         .sda_pin                = FSG_SDA_PIN,
60         .scl_pin                = FSG_SCL_PIN,
61 };
62
63 static struct platform_device fsg_i2c_gpio = {
64         .name                   = "i2c-gpio",
65         .id                     = 0,
66         .dev = {
67                 .platform_data  = &fsg_i2c_gpio_data,
68         },
69 };
70
71 static struct i2c_board_info __initdata fsg_i2c_board_info [] = {
72         {
73                 I2C_BOARD_INFO("isl1208", 0x6f),
74         },
75 };
76
77 static struct resource fsg_uart_resources[] = {
78         {
79                 .start          = IXP4XX_UART1_BASE_PHYS,
80                 .end            = IXP4XX_UART1_BASE_PHYS + 0x0fff,
81                 .flags          = IORESOURCE_MEM,
82         },
83         {
84                 .start          = IXP4XX_UART2_BASE_PHYS,
85                 .end            = IXP4XX_UART2_BASE_PHYS + 0x0fff,
86                 .flags          = IORESOURCE_MEM,
87         }
88 };
89
90 static struct plat_serial8250_port fsg_uart_data[] = {
91         {
92                 .mapbase        = IXP4XX_UART1_BASE_PHYS,
93                 .membase        = (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
94                 .irq            = IRQ_IXP4XX_UART1,
95                 .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
96                 .iotype         = UPIO_MEM,
97                 .regshift       = 2,
98                 .uartclk        = IXP4XX_UART_XTAL,
99         },
100         {
101                 .mapbase        = IXP4XX_UART2_BASE_PHYS,
102                 .membase        = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
103                 .irq            = IRQ_IXP4XX_UART2,
104                 .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
105                 .iotype         = UPIO_MEM,
106                 .regshift       = 2,
107                 .uartclk        = IXP4XX_UART_XTAL,
108         },
109         { }
110 };
111
112 static struct platform_device fsg_uart = {
113         .name                   = "serial8250",
114         .id                     = PLAT8250_DEV_PLATFORM,
115         .dev = {
116                 .platform_data  = fsg_uart_data,
117         },
118         .num_resources          = ARRAY_SIZE(fsg_uart_resources),
119         .resource               = fsg_uart_resources,
120 };
121
122 static struct platform_device fsg_leds = {
123         .name           = "fsg-led",
124         .id             = -1,
125 };
126
127 /* Built-in 10/100 Ethernet MAC interfaces */
128 static struct eth_plat_info fsg_plat_eth[] = {
129         {
130                 .phy            = 5,
131                 .rxq            = 3,
132                 .txreadyq       = 20,
133         }, {
134                 .phy            = 4,
135                 .rxq            = 4,
136                 .txreadyq       = 21,
137         }
138 };
139
140 static struct platform_device fsg_eth[] = {
141         {
142                 .name                   = "ixp4xx_eth",
143                 .id                     = IXP4XX_ETH_NPEB,
144                 .dev = {
145                         .platform_data  = fsg_plat_eth,
146                 },
147         }, {
148                 .name                   = "ixp4xx_eth",
149                 .id                     = IXP4XX_ETH_NPEC,
150                 .dev = {
151                         .platform_data  = fsg_plat_eth + 1,
152                 },
153         }
154 };
155
156 static struct platform_device *fsg_devices[] __initdata = {
157         &fsg_i2c_gpio,
158         &fsg_flash,
159         &fsg_leds,
160         &fsg_eth[0],
161         &fsg_eth[1],
162 };
163
164 static irqreturn_t fsg_power_handler(int irq, void *dev_id)
165 {
166         /* Signal init to do the ctrlaltdel action, this will bypass init if
167          * it hasn't started and do a kernel_restart.
168          */
169         ctrl_alt_del();
170
171         return IRQ_HANDLED;
172 }
173
174 static irqreturn_t fsg_reset_handler(int irq, void *dev_id)
175 {
176         /* This is the paper-clip reset which does an emergency reboot. */
177         printk(KERN_INFO "Restarting system.\n");
178         machine_restart(NULL);
179
180         /* This should never be reached. */
181         return IRQ_HANDLED;
182 }
183
184 static void __init fsg_init(void)
185 {
186         uint8_t __iomem *f;
187
188         ixp4xx_sys_init();
189
190         fsg_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
191         fsg_flash_resource.end =
192                 IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
193
194         *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
195         *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
196
197         /* Configure CS2 for operation, 8bit and writable */
198         *IXP4XX_EXP_CS2 = 0xbfff0002;
199
200         i2c_register_board_info(0, fsg_i2c_board_info,
201                                 ARRAY_SIZE(fsg_i2c_board_info));
202
203         /* This is only useful on a modified machine, but it is valuable
204          * to have it first in order to see debug messages, and so that
205          * it does *not* get removed if platform_add_devices fails!
206          */
207         (void)platform_device_register(&fsg_uart);
208
209         platform_add_devices(fsg_devices, ARRAY_SIZE(fsg_devices));
210
211         if (request_irq(gpio_to_irq(FSG_RB_GPIO), &fsg_reset_handler,
212                         IRQF_DISABLED | IRQF_TRIGGER_LOW,
213                         "FSG reset button", NULL) < 0) {
214
215                 printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
216                         gpio_to_irq(FSG_RB_GPIO));
217         }
218
219         if (request_irq(gpio_to_irq(FSG_SB_GPIO), &fsg_power_handler,
220                         IRQF_DISABLED | IRQF_TRIGGER_LOW,
221                         "FSG power button", NULL) < 0) {
222
223                 printk(KERN_DEBUG "Power Button IRQ %d not available\n",
224                         gpio_to_irq(FSG_SB_GPIO));
225         }
226
227         /*
228          * Map in a portion of the flash and read the MAC addresses.
229          * Since it is stored in BE in the flash itself, we need to
230          * byteswap it if we're in LE mode.
231          */
232         f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x400000);
233         if (f) {
234 #ifdef __ARMEB__
235                 int i;
236                 for (i = 0; i < 6; i++) {
237                         fsg_plat_eth[0].hwaddr[i] = readb(f + 0x3C0422 + i);
238                         fsg_plat_eth[1].hwaddr[i] = readb(f + 0x3C043B + i);
239                 }
240 #else
241
242                 /*
243                   Endian-swapped reads from unaligned addresses are
244                   required to extract the two MACs from the big-endian
245                   Redboot config area in flash.
246                 */
247
248                 fsg_plat_eth[0].hwaddr[0] = readb(f + 0x3C0421);
249                 fsg_plat_eth[0].hwaddr[1] = readb(f + 0x3C0420);
250                 fsg_plat_eth[0].hwaddr[2] = readb(f + 0x3C0427);
251                 fsg_plat_eth[0].hwaddr[3] = readb(f + 0x3C0426);
252                 fsg_plat_eth[0].hwaddr[4] = readb(f + 0x3C0425);
253                 fsg_plat_eth[0].hwaddr[5] = readb(f + 0x3C0424);
254
255                 fsg_plat_eth[1].hwaddr[0] = readb(f + 0x3C0439);
256                 fsg_plat_eth[1].hwaddr[1] = readb(f + 0x3C043F);
257                 fsg_plat_eth[1].hwaddr[2] = readb(f + 0x3C043E);
258                 fsg_plat_eth[1].hwaddr[3] = readb(f + 0x3C043D);
259                 fsg_plat_eth[1].hwaddr[4] = readb(f + 0x3C043C);
260                 fsg_plat_eth[1].hwaddr[5] = readb(f + 0x3C0443);
261 #endif
262                 iounmap(f);
263         }
264         printk(KERN_INFO "FSG: Using MAC address %pM for port 0\n",
265                fsg_plat_eth[0].hwaddr);
266         printk(KERN_INFO "FSG: Using MAC address %pM for port 1\n",
267                fsg_plat_eth[1].hwaddr);
268
269 }
270
271 MACHINE_START(FSG, "Freecom FSG-3")
272         /* Maintainer: www.nslu2-linux.org */
273         .map_io         = ixp4xx_map_io,
274         .init_irq       = ixp4xx_init_irq,
275         .timer          = &ixp4xx_timer,
276         .boot_params    = 0x0100,
277         .init_machine   = fsg_init,
278 MACHINE_END
279