1/* 2 * arch/arm/mach-iop32x/n2100.c 3 * 4 * Board support code for the Thecus N2100 platform. 5 * 6 * Author: Rory Bolt <rorybolt@pacbell.net> 7 * Copyright (C) 2002 Rory Bolt 8 * Copyright 2003 (c) MontaVista, Software, Inc. 9 * Copyright (C) 2004 Intel Corp. 10 * 11 * This program is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. 15 */ 16 17#include <linux/mm.h> 18#include <linux/init.h> 19#include <linux/f75375s.h> 20#include <linux/leds-pca9532.h> 21#include <linux/delay.h> 22#include <linux/kernel.h> 23#include <linux/pci.h> 24#include <linux/pm.h> 25#include <linux/string.h> 26#include <linux/serial_core.h> 27#include <linux/serial_8250.h> 28#include <linux/mtd/physmap.h> 29#include <linux/i2c.h> 30#include <linux/platform_device.h> 31#include <linux/reboot.h> 32#include <linux/io.h> 33#include <linux/gpio.h> 34#include <mach/hardware.h> 35#include <asm/irq.h> 36#include <asm/mach/arch.h> 37#include <asm/mach/map.h> 38#include <asm/mach/pci.h> 39#include <asm/mach/time.h> 40#include <asm/mach-types.h> 41#include <asm/page.h> 42#include <asm/pgtable.h> 43#include <mach/time.h> 44#include "gpio-iop32x.h" 45 46/* 47 * N2100 timer tick configuration. 48 */ 49static void __init n2100_timer_init(void) 50{ 51 /* 33.000 MHz crystal. */ 52 iop_init_time(198000000); 53} 54 55 56/* 57 * N2100 I/O. 58 */ 59static struct map_desc n2100_io_desc[] __initdata = { 60 { /* on-board devices */ 61 .virtual = N2100_UART, 62 .pfn = __phys_to_pfn(N2100_UART), 63 .length = 0x00100000, 64 .type = MT_DEVICE 65 }, 66}; 67 68void __init n2100_map_io(void) 69{ 70 iop3xx_map_io(); 71 iotable_init(n2100_io_desc, ARRAY_SIZE(n2100_io_desc)); 72} 73 74 75/* 76 * N2100 PCI. 77 */ 78static int __init 79n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 80{ 81 int irq; 82 83 if (PCI_SLOT(dev->devfn) == 1) { 84 /* RTL8110SB #1 */ 85 irq = IRQ_IOP32X_XINT0; 86 } else if (PCI_SLOT(dev->devfn) == 2) { 87 /* RTL8110SB #2 */ 88 irq = IRQ_IOP32X_XINT3; 89 } else if (PCI_SLOT(dev->devfn) == 3) { 90 /* Sil3512 */ 91 irq = IRQ_IOP32X_XINT2; 92 } else if (PCI_SLOT(dev->devfn) == 4 && pin == 1) { 93 /* VT6212 INTA */ 94 irq = IRQ_IOP32X_XINT1; 95 } else if (PCI_SLOT(dev->devfn) == 4 && pin == 2) { 96 /* VT6212 INTB */ 97 irq = IRQ_IOP32X_XINT0; 98 } else if (PCI_SLOT(dev->devfn) == 4 && pin == 3) { 99 /* VT6212 INTC */ 100 irq = IRQ_IOP32X_XINT2; 101 } else if (PCI_SLOT(dev->devfn) == 5) { 102 /* Mini-PCI slot */ 103 irq = IRQ_IOP32X_XINT3; 104 } else { 105 printk(KERN_ERR "n2100_pci_map_irq() called for unknown " 106 "device PCI:%d:%d:%d\n", dev->bus->number, 107 PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); 108 irq = -1; 109 } 110 111 return irq; 112} 113 114static struct hw_pci n2100_pci __initdata = { 115 .nr_controllers = 1, 116 .ops = &iop3xx_ops, 117 .setup = iop3xx_pci_setup, 118 .preinit = iop3xx_pci_preinit, 119 .map_irq = n2100_pci_map_irq, 120}; 121 122/* 123 * Both r8169 chips on the n2100 exhibit PCI parity problems. Set 124 * the ->broken_parity_status flag for both ports so that the r8169 125 * driver knows it should ignore error interrupts. 126 */ 127static void n2100_fixup_r8169(struct pci_dev *dev) 128{ 129 if (dev->bus->number == 0 && 130 (dev->devfn == PCI_DEVFN(1, 0) || 131 dev->devfn == PCI_DEVFN(2, 0))) 132 dev->broken_parity_status = 1; 133} 134DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169); 135 136static int __init n2100_pci_init(void) 137{ 138 if (machine_is_n2100()) 139 pci_common_init(&n2100_pci); 140 141 return 0; 142} 143 144subsys_initcall(n2100_pci_init); 145 146 147/* 148 * N2100 machine initialisation. 149 */ 150static struct physmap_flash_data n2100_flash_data = { 151 .width = 2, 152}; 153 154static struct resource n2100_flash_resource = { 155 .start = 0xf0000000, 156 .end = 0xf0ffffff, 157 .flags = IORESOURCE_MEM, 158}; 159 160static struct platform_device n2100_flash_device = { 161 .name = "physmap-flash", 162 .id = 0, 163 .dev = { 164 .platform_data = &n2100_flash_data, 165 }, 166 .num_resources = 1, 167 .resource = &n2100_flash_resource, 168}; 169 170 171static struct plat_serial8250_port n2100_serial_port[] = { 172 { 173 .mapbase = N2100_UART, 174 .membase = (char *)N2100_UART, 175 .irq = 0, 176 .flags = UPF_SKIP_TEST | UPF_AUTO_IRQ | UPF_SHARE_IRQ, 177 .iotype = UPIO_MEM, 178 .regshift = 0, 179 .uartclk = 1843200, 180 }, 181 { }, 182}; 183 184static struct resource n2100_uart_resource = { 185 .start = N2100_UART, 186 .end = N2100_UART + 7, 187 .flags = IORESOURCE_MEM, 188}; 189 190static struct platform_device n2100_serial_device = { 191 .name = "serial8250", 192 .id = PLAT8250_DEV_PLATFORM, 193 .dev = { 194 .platform_data = n2100_serial_port, 195 }, 196 .num_resources = 1, 197 .resource = &n2100_uart_resource, 198}; 199 200static struct f75375s_platform_data n2100_f75375s = { 201 .pwm = { 255, 255 }, 202 .pwm_enable = { 0, 0 }, 203}; 204 205static struct pca9532_platform_data n2100_leds = { 206 .leds = { 207 { .name = "n2100:red:satafail0", 208 .state = PCA9532_OFF, 209 .type = PCA9532_TYPE_LED, 210 }, 211 { .name = "n2100:red:satafail1", 212 .state = PCA9532_OFF, 213 .type = PCA9532_TYPE_LED, 214 }, 215 { .name = "n2100:blue:usb", 216 .state = PCA9532_OFF, 217 .type = PCA9532_TYPE_LED, 218 }, 219 { .type = PCA9532_TYPE_NONE }, 220 221 { .type = PCA9532_TYPE_NONE }, 222 { .type = PCA9532_TYPE_NONE }, 223 { .type = PCA9532_TYPE_NONE }, 224 { .name = "n2100:red:usb", 225 .state = PCA9532_OFF, 226 .type = PCA9532_TYPE_LED, 227 }, 228 229 { .type = PCA9532_TYPE_NONE }, /* power OFF gpio */ 230 { .type = PCA9532_TYPE_NONE }, /* reset gpio */ 231 { .type = PCA9532_TYPE_NONE }, 232 { .type = PCA9532_TYPE_NONE }, 233 234 { .type = PCA9532_TYPE_NONE }, 235 { .name = "n2100:orange:system", 236 .state = PCA9532_OFF, 237 .type = PCA9532_TYPE_LED, 238 }, 239 { .name = "n2100:red:system", 240 .state = PCA9532_OFF, 241 .type = PCA9532_TYPE_LED, 242 }, 243 { .name = "N2100 beeper" , 244 .state = PCA9532_OFF, 245 .type = PCA9532_TYPE_N2100_BEEP, 246 }, 247 }, 248 .psc = { 0, 0 }, 249 .pwm = { 0, 0 }, 250}; 251 252static struct i2c_board_info __initdata n2100_i2c_devices[] = { 253 { 254 I2C_BOARD_INFO("rs5c372b", 0x32), 255 }, 256 { 257 I2C_BOARD_INFO("f75375", 0x2e), 258 .platform_data = &n2100_f75375s, 259 }, 260 { 261 I2C_BOARD_INFO("pca9532", 0x60), 262 .platform_data = &n2100_leds, 263 }, 264}; 265 266/* 267 * Pull PCA9532 GPIO #8 low to power off the machine. 268 */ 269static void n2100_power_off(void) 270{ 271 local_irq_disable(); 272 273 /* Start condition, I2C address of PCA9532, write transaction. */ 274 *IOP3XX_IDBR0 = 0xc0; 275 *IOP3XX_ICR0 = 0xe9; 276 mdelay(1); 277 278 /* Write address 0x08. */ 279 *IOP3XX_IDBR0 = 0x08; 280 *IOP3XX_ICR0 = 0xe8; 281 mdelay(1); 282 283 /* Write data 0x01, stop condition. */ 284 *IOP3XX_IDBR0 = 0x01; 285 *IOP3XX_ICR0 = 0xea; 286 287 while (1) 288 ; 289} 290 291static void n2100_restart(enum reboot_mode mode, const char *cmd) 292{ 293 int ret; 294 295 ret = gpio_direction_output(N2100_HARDWARE_RESET, 0); 296 if (ret) { 297 pr_crit("could not drive reset GPIO low\n"); 298 return; 299 } 300 /* Wait for reset to happen */ 301 while (1) 302 ; 303} 304 305 306static struct timer_list power_button_poll_timer; 307 308static void power_button_poll(unsigned long dummy) 309{ 310 if (gpio_get_value(N2100_POWER_BUTTON) == 0) { 311 ctrl_alt_del(); 312 return; 313 } 314 315 power_button_poll_timer.expires = jiffies + (HZ / 10); 316 add_timer(&power_button_poll_timer); 317} 318 319static int __init n2100_request_gpios(void) 320{ 321 int ret; 322 323 if (!machine_is_n2100()) 324 return 0; 325 326 ret = gpio_request(N2100_HARDWARE_RESET, "reset"); 327 if (ret) 328 pr_err("could not request reset GPIO\n"); 329 330 ret = gpio_request(N2100_POWER_BUTTON, "power"); 331 if (ret) 332 pr_err("could not request power GPIO\n"); 333 else { 334 ret = gpio_direction_input(N2100_POWER_BUTTON); 335 if (ret) 336 pr_err("could not set power GPIO as input\n"); 337 } 338 /* Set up power button poll timer */ 339 init_timer(&power_button_poll_timer); 340 power_button_poll_timer.function = power_button_poll; 341 power_button_poll_timer.expires = jiffies + (HZ / 10); 342 add_timer(&power_button_poll_timer); 343 return 0; 344} 345device_initcall(n2100_request_gpios); 346 347static void __init n2100_init_machine(void) 348{ 349 register_iop32x_gpio(); 350 platform_device_register(&iop3xx_i2c0_device); 351 platform_device_register(&n2100_flash_device); 352 platform_device_register(&n2100_serial_device); 353 platform_device_register(&iop3xx_dma_0_channel); 354 platform_device_register(&iop3xx_dma_1_channel); 355 356 i2c_register_board_info(0, n2100_i2c_devices, 357 ARRAY_SIZE(n2100_i2c_devices)); 358 359 pm_power_off = n2100_power_off; 360} 361 362MACHINE_START(N2100, "Thecus N2100") 363 /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ 364 .atag_offset = 0x100, 365 .map_io = n2100_map_io, 366 .init_irq = iop32x_init_irq, 367 .init_time = n2100_timer_init, 368 .init_machine = n2100_init_machine, 369 .restart = n2100_restart, 370MACHINE_END 371