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 <mach/hardware.h> 34#include <asm/irq.h> 35#include <asm/mach/arch.h> 36#include <asm/mach/map.h> 37#include <asm/mach/pci.h> 38#include <asm/mach/time.h> 39#include <asm/mach-types.h> 40#include <asm/page.h> 41#include <asm/pgtable.h> 42#include <mach/time.h> 43 44/* 45 * N2100 timer tick configuration. 46 */ 47static void __init n2100_timer_init(void) 48{ 49 /* 33.000 MHz crystal. */ 50 iop_init_time(198000000); 51} 52 53static struct sys_timer n2100_timer = { 54 .init = n2100_timer_init, 55}; 56 57 58/* 59 * N2100 I/O. 60 */ 61static struct map_desc n2100_io_desc[] __initdata = { 62 { /* on-board devices */ 63 .virtual = N2100_UART, 64 .pfn = __phys_to_pfn(N2100_UART), 65 .length = 0x00100000, 66 .type = MT_DEVICE 67 }, 68}; 69 70void __init n2100_map_io(void) 71{ 72 iop3xx_map_io(); 73 iotable_init(n2100_io_desc, ARRAY_SIZE(n2100_io_desc)); 74} 75 76 77/* 78 * N2100 PCI. 79 */ 80static int __init 81n2100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 82{ 83 int irq; 84 85 if (PCI_SLOT(dev->devfn) == 1) { 86 /* RTL8110SB #1 */ 87 irq = IRQ_IOP32X_XINT0; 88 } else if (PCI_SLOT(dev->devfn) == 2) { 89 /* RTL8110SB #2 */ 90 irq = IRQ_IOP32X_XINT3; 91 } else if (PCI_SLOT(dev->devfn) == 3) { 92 /* Sil3512 */ 93 irq = IRQ_IOP32X_XINT2; 94 } else if (PCI_SLOT(dev->devfn) == 4 && pin == 1) { 95 /* VT6212 INTA */ 96 irq = IRQ_IOP32X_XINT1; 97 } else if (PCI_SLOT(dev->devfn) == 4 && pin == 2) { 98 /* VT6212 INTB */ 99 irq = IRQ_IOP32X_XINT0; 100 } else if (PCI_SLOT(dev->devfn) == 4 && pin == 3) { 101 /* VT6212 INTC */ 102 irq = IRQ_IOP32X_XINT2; 103 } else if (PCI_SLOT(dev->devfn) == 5) { 104 /* Mini-PCI slot */ 105 irq = IRQ_IOP32X_XINT3; 106 } else { 107 printk(KERN_ERR "n2100_pci_map_irq() called for unknown " 108 "device PCI:%d:%d:%d\n", dev->bus->number, 109 PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); 110 irq = -1; 111 } 112 113 return irq; 114} 115 116static struct hw_pci n2100_pci __initdata = { 117 .swizzle = pci_std_swizzle, 118 .nr_controllers = 1, 119 .setup = iop3xx_pci_setup, 120 .preinit = iop3xx_pci_preinit, 121 .scan = iop3xx_pci_scan_bus, 122 .map_irq = n2100_pci_map_irq, 123}; 124 125/* 126 * Both r8169 chips on the n2100 exhibit PCI parity problems. Set 127 * the ->broken_parity_status flag for both ports so that the r8169 128 * driver knows it should ignore error interrupts. 129 */ 130static void n2100_fixup_r8169(struct pci_dev *dev) 131{ 132 if (dev->bus->number == 0 && 133 (dev->devfn == PCI_DEVFN(1, 0) || 134 dev->devfn == PCI_DEVFN(2, 0))) 135 dev->broken_parity_status = 1; 136} 137DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169); 138 139static int __init n2100_pci_init(void) 140{ 141 if (machine_is_n2100()) 142 pci_common_init(&n2100_pci); 143 144 return 0; 145} 146 147subsys_initcall(n2100_pci_init); 148 149 150/* 151 * N2100 machine initialisation. 152 */ 153static struct physmap_flash_data n2100_flash_data = { 154 .width = 2, 155}; 156 157static struct resource n2100_flash_resource = { 158 .start = 0xf0000000, 159 .end = 0xf0ffffff, 160 .flags = IORESOURCE_MEM, 161}; 162 163static struct platform_device n2100_flash_device = { 164 .name = "physmap-flash", 165 .id = 0, 166 .dev = { 167 .platform_data = &n2100_flash_data, 168 }, 169 .num_resources = 1, 170 .resource = &n2100_flash_resource, 171}; 172 173 174static struct plat_serial8250_port n2100_serial_port[] = { 175 { 176 .mapbase = N2100_UART, 177 .membase = (char *)N2100_UART, 178 .irq = 0, 179 .flags = UPF_SKIP_TEST | UPF_AUTO_IRQ | UPF_SHARE_IRQ, 180 .iotype = UPIO_MEM, 181 .regshift = 0, 182 .uartclk = 1843200, 183 }, 184 { }, 185}; 186 187static struct resource n2100_uart_resource = { 188 .start = N2100_UART, 189 .end = N2100_UART + 7, 190 .flags = IORESOURCE_MEM, 191}; 192 193static struct platform_device n2100_serial_device = { 194 .name = "serial8250", 195 .id = PLAT8250_DEV_PLATFORM, 196 .dev = { 197 .platform_data = n2100_serial_port, 198 }, 199 .num_resources = 1, 200 .resource = &n2100_uart_resource, 201}; 202 203static struct f75375s_platform_data n2100_f75375s = { 204 .pwm = { 255, 255 }, 205 .pwm_enable = { 0, 0 }, 206}; 207 208static struct pca9532_platform_data n2100_leds = { 209 .leds = { 210 { .name = "n2100:red:satafail0", 211 .state = PCA9532_OFF, 212 .type = PCA9532_TYPE_LED, 213 }, 214 { .name = "n2100:red:satafail1", 215 .state = PCA9532_OFF, 216 .type = PCA9532_TYPE_LED, 217 }, 218 { .name = "n2100:blue:usb", 219 .state = PCA9532_OFF, 220 .type = PCA9532_TYPE_LED, 221 }, 222 { .type = PCA9532_TYPE_NONE }, 223 224 { .type = PCA9532_TYPE_NONE }, 225 { .type = PCA9532_TYPE_NONE }, 226 { .type = PCA9532_TYPE_NONE }, 227 { .name = "n2100:red:usb", 228 .state = PCA9532_OFF, 229 .type = PCA9532_TYPE_LED, 230 }, 231 232 { .type = PCA9532_TYPE_NONE }, /* power OFF gpio */ 233 { .type = PCA9532_TYPE_NONE }, /* reset gpio */ 234 { .type = PCA9532_TYPE_NONE }, 235 { .type = PCA9532_TYPE_NONE }, 236 237 { .type = PCA9532_TYPE_NONE }, 238 { .name = "n2100:orange:system", 239 .state = PCA9532_OFF, 240 .type = PCA9532_TYPE_LED, 241 }, 242 { .name = "n2100:red:system", 243 .state = PCA9532_OFF, 244 .type = PCA9532_TYPE_LED, 245 }, 246 { .name = "N2100 beeper" , 247 .state = PCA9532_OFF, 248 .type = PCA9532_TYPE_N2100_BEEP, 249 }, 250 }, 251 .psc = { 0, 0 }, 252 .pwm = { 0, 0 }, 253}; 254 255static struct i2c_board_info __initdata n2100_i2c_devices[] = { 256 { 257 I2C_BOARD_INFO("rs5c372b", 0x32), 258 }, 259 { 260 I2C_BOARD_INFO("f75375", 0x2e), 261 .platform_data = &n2100_f75375s, 262 }, 263 { 264 I2C_BOARD_INFO("pca9532", 0x60), 265 .platform_data = &n2100_leds, 266 }, 267}; 268 269/* 270 * Pull PCA9532 GPIO #8 low to power off the machine. 271 */ 272static void n2100_power_off(void) 273{ 274 local_irq_disable(); 275 276 /* Start condition, I2C address of PCA9532, write transaction. */ 277 *IOP3XX_IDBR0 = 0xc0; 278 *IOP3XX_ICR0 = 0xe9; 279 mdelay(1); 280 281 /* Write address 0x08. */ 282 *IOP3XX_IDBR0 = 0x08; 283 *IOP3XX_ICR0 = 0xe8; 284 mdelay(1); 285 286 /* Write data 0x01, stop condition. */ 287 *IOP3XX_IDBR0 = 0x01; 288 *IOP3XX_ICR0 = 0xea; 289 290 while (1) 291 ; 292} 293 294 295static struct timer_list power_button_poll_timer; 296 297static void power_button_poll(unsigned long dummy) 298{ 299 if (gpio_line_get(N2100_POWER_BUTTON) == 0) { 300 ctrl_alt_del(); 301 return; 302 } 303 304 power_button_poll_timer.expires = jiffies + (HZ / 10); 305 add_timer(&power_button_poll_timer); 306} 307 308 309static void __init n2100_init_machine(void) 310{ 311 platform_device_register(&iop3xx_i2c0_device); 312 platform_device_register(&n2100_flash_device); 313 platform_device_register(&n2100_serial_device); 314 platform_device_register(&iop3xx_dma_0_channel); 315 platform_device_register(&iop3xx_dma_1_channel); 316 317 i2c_register_board_info(0, n2100_i2c_devices, 318 ARRAY_SIZE(n2100_i2c_devices)); 319 320 pm_power_off = n2100_power_off; 321 322 init_timer(&power_button_poll_timer); 323 power_button_poll_timer.function = power_button_poll; 324 power_button_poll_timer.expires = jiffies + (HZ / 10); 325 add_timer(&power_button_poll_timer); 326} 327 328MACHINE_START(N2100, "Thecus N2100") 329 /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ 330 .phys_io = N2100_UART, 331 .io_pg_offst = ((N2100_UART) >> 18) & 0xfffc, 332 .boot_params = 0xa0000100, 333 .map_io = n2100_map_io, 334 .init_irq = iop32x_init_irq, 335 .timer = &n2100_timer, 336 .init_machine = n2100_init_machine, 337MACHINE_END 338