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