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