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