linux/arch/arm/mach-orion5x/terastation_pro2-setup.c
<<
>>
Prefs
   1/*
   2 * Buffalo Terastation Pro II/Live Board Setup
   3 *
   4 * Maintainer: Sylver Bruneau <sylver.bruneau@googlemail.com>
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11#include <linux/gpio.h>
  12#include <linux/kernel.h>
  13#include <linux/init.h>
  14#include <linux/platform_device.h>
  15#include <linux/pci.h>
  16#include <linux/irq.h>
  17#include <linux/delay.h>
  18#include <linux/mtd/physmap.h>
  19#include <linux/mv643xx_eth.h>
  20#include <linux/i2c.h>
  21#include <linux/serial_reg.h>
  22#include <asm/mach-types.h>
  23#include <asm/mach/arch.h>
  24#include <asm/mach/pci.h>
  25#include "common.h"
  26#include "mpp.h"
  27#include "orion5x.h"
  28
  29/*****************************************************************************
  30 * Terastation Pro 2/Live Info
  31 ****************************************************************************/
  32
  33/*
  34 * Terastation Pro 2 hardware :
  35 * - Marvell 88F5281-D0
  36 * - Marvell 88SX6042 SATA controller (PCI)
  37 * - Marvell 88E1118 Gigabit Ethernet PHY
  38 * - 256KB NOR flash
  39 * - 128MB of DDR RAM
  40 * - PCIe port (not equipped)
  41 */
  42
  43/*
  44 * 256K NOR flash Device bus boot chip select
  45 */
  46
  47#define TSP2_NOR_BOOT_BASE      0xf4000000
  48#define TSP2_NOR_BOOT_SIZE      SZ_256K
  49
  50/*****************************************************************************
  51 * 256KB NOR Flash on BOOT Device
  52 ****************************************************************************/
  53
  54static struct physmap_flash_data tsp2_nor_flash_data = {
  55        .width    = 1,
  56};
  57
  58static struct resource tsp2_nor_flash_resource = {
  59        .flags = IORESOURCE_MEM,
  60        .start = TSP2_NOR_BOOT_BASE,
  61        .end   = TSP2_NOR_BOOT_BASE + TSP2_NOR_BOOT_SIZE - 1,
  62};
  63
  64static struct platform_device tsp2_nor_flash = {
  65        .name          = "physmap-flash",
  66        .id            = 0,
  67        .dev           = {
  68                .platform_data  = &tsp2_nor_flash_data,
  69        },
  70        .num_resources = 1,
  71        .resource      = &tsp2_nor_flash_resource,
  72};
  73
  74/*****************************************************************************
  75 * PCI
  76 ****************************************************************************/
  77#define TSP2_PCI_SLOT0_OFFS             7
  78#define TSP2_PCI_SLOT0_IRQ_PIN          11
  79
  80static void __init tsp2_pci_preinit(void)
  81{
  82        int pin;
  83
  84        /*
  85         * Configure PCI GPIO IRQ pins
  86         */
  87        pin = TSP2_PCI_SLOT0_IRQ_PIN;
  88        if (gpio_request(pin, "PCI Int1") == 0) {
  89                if (gpio_direction_input(pin) == 0) {
  90                        irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
  91                } else {
  92                        printk(KERN_ERR "tsp2_pci_preinit failed "
  93                                        "to set_irq_type pin %d\n", pin);
  94                        gpio_free(pin);
  95                }
  96        } else {
  97                printk(KERN_ERR "tsp2_pci_preinit failed to "
  98                                "gpio_request %d\n", pin);
  99        }
 100}
 101
 102static int __init tsp2_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 103{
 104        int irq;
 105
 106        /*
 107         * Check for devices with hard-wired IRQs.
 108         */
 109        irq = orion5x_pci_map_irq(dev, slot, pin);
 110        if (irq != -1)
 111                return irq;
 112
 113        /*
 114         * PCI IRQs are connected via GPIOs.
 115         */
 116        if (slot == TSP2_PCI_SLOT0_OFFS)
 117                return gpio_to_irq(TSP2_PCI_SLOT0_IRQ_PIN);
 118
 119        return -1;
 120}
 121
 122static struct hw_pci tsp2_pci __initdata = {
 123        .nr_controllers = 2,
 124        .preinit        = tsp2_pci_preinit,
 125        .setup          = orion5x_pci_sys_setup,
 126        .scan           = orion5x_pci_sys_scan_bus,
 127        .map_irq        = tsp2_pci_map_irq,
 128};
 129
 130static int __init tsp2_pci_init(void)
 131{
 132        if (machine_is_terastation_pro2())
 133                pci_common_init(&tsp2_pci);
 134
 135        return 0;
 136}
 137
 138subsys_initcall(tsp2_pci_init);
 139
 140/*****************************************************************************
 141 * Ethernet
 142 ****************************************************************************/
 143
 144static struct mv643xx_eth_platform_data tsp2_eth_data = {
 145        .phy_addr       = 0,
 146};
 147
 148/*****************************************************************************
 149 * RTC 5C372a on I2C bus
 150 ****************************************************************************/
 151
 152#define TSP2_RTC_GPIO   9
 153
 154static struct i2c_board_info __initdata tsp2_i2c_rtc = {
 155        I2C_BOARD_INFO("rs5c372a", 0x32),
 156};
 157
 158/*****************************************************************************
 159 * Terastation Pro II specific power off method via UART1-attached
 160 * microcontroller
 161 ****************************************************************************/
 162
 163#define UART1_REG(x)    (UART1_VIRT_BASE + ((UART_##x) << 2))
 164
 165static int tsp2_miconread(unsigned char *buf, int count)
 166{
 167        int i;
 168        int timeout;
 169
 170        for (i = 0; i < count; i++) {
 171                timeout = 10;
 172
 173                while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) {
 174                        if (--timeout == 0)
 175                                break;
 176                        udelay(1000);
 177                }
 178
 179                if (timeout == 0)
 180                        break;
 181                buf[i] = readl(UART1_REG(RX));
 182        }
 183
 184        /* return read bytes */
 185        return i;
 186}
 187
 188static int tsp2_miconwrite(const unsigned char *buf, int count)
 189{
 190        int i = 0;
 191
 192        while (count--) {
 193                while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE))
 194                        barrier();
 195                writel(buf[i++], UART1_REG(TX));
 196        }
 197
 198        return 0;
 199}
 200
 201static int tsp2_miconsend(const unsigned char *data, int count)
 202{
 203        int i;
 204        unsigned char checksum = 0;
 205        unsigned char recv_buf[40];
 206        unsigned char send_buf[40];
 207        unsigned char correct_ack[3];
 208        int retry = 2;
 209
 210        /* Generate checksum */
 211        for (i = 0; i < count; i++)
 212                checksum -=  data[i];
 213
 214        do {
 215                /* Send data */
 216                tsp2_miconwrite(data, count);
 217
 218                /* send checksum */
 219                tsp2_miconwrite(&checksum, 1);
 220
 221                if (tsp2_miconread(recv_buf, sizeof(recv_buf)) <= 3) {
 222                        printk(KERN_ERR ">%s: receive failed.\n", __func__);
 223
 224                        /* send preamble to clear the receive buffer */
 225                        memset(&send_buf, 0xff, sizeof(send_buf));
 226                        tsp2_miconwrite(send_buf, sizeof(send_buf));
 227
 228                        /* make dummy reads */
 229                        mdelay(100);
 230                        tsp2_miconread(recv_buf, sizeof(recv_buf));
 231                } else {
 232                        /* Generate expected ack */
 233                        correct_ack[0] = 0x01;
 234                        correct_ack[1] = data[1];
 235                        correct_ack[2] = 0x00;
 236
 237                        /* checksum Check */
 238                        if ((recv_buf[0] + recv_buf[1] + recv_buf[2] +
 239                             recv_buf[3]) & 0xFF) {
 240                                printk(KERN_ERR ">%s: Checksum Error : "
 241                                        "Received data[%02x, %02x, %02x, %02x]"
 242                                        "\n", __func__, recv_buf[0],
 243                                        recv_buf[1], recv_buf[2], recv_buf[3]);
 244                        } else {
 245                                /* Check Received Data */
 246                                if (correct_ack[0] == recv_buf[0] &&
 247                                    correct_ack[1] == recv_buf[1] &&
 248                                    correct_ack[2] == recv_buf[2]) {
 249                                        /* Interval for next command */
 250                                        mdelay(10);
 251
 252                                        /* Receive ACK */
 253                                        return 0;
 254                                }
 255                        }
 256                        /* Received NAK or illegal Data */
 257                        printk(KERN_ERR ">%s: Error : NAK or Illegal Data "
 258                                        "Received\n", __func__);
 259                }
 260        } while (retry--);
 261
 262        /* Interval for next command */
 263        mdelay(10);
 264
 265        return -1;
 266}
 267
 268static void tsp2_power_off(void)
 269{
 270        const unsigned char watchdogkill[]      = {0x01, 0x35, 0x00};
 271        const unsigned char shutdownwait[]      = {0x00, 0x0c};
 272        const unsigned char poweroff[]          = {0x00, 0x06};
 273        /* 38400 baud divisor */
 274        const unsigned divisor = ((orion5x_tclk + (8 * 38400)) / (16 * 38400));
 275
 276        pr_info("%s: triggering power-off...\n", __func__);
 277
 278        /* hijack uart1 and reset into sane state (38400,8n1,even parity) */
 279        writel(0x83, UART1_REG(LCR));
 280        writel(divisor & 0xff, UART1_REG(DLL));
 281        writel((divisor >> 8) & 0xff, UART1_REG(DLM));
 282        writel(0x1b, UART1_REG(LCR));
 283        writel(0x00, UART1_REG(IER));
 284        writel(0x07, UART1_REG(FCR));
 285        writel(0x00, UART1_REG(MCR));
 286
 287        /* Send the commands to shutdown the Terastation Pro II */
 288        tsp2_miconsend(watchdogkill, sizeof(watchdogkill)) ;
 289        tsp2_miconsend(shutdownwait, sizeof(shutdownwait)) ;
 290        tsp2_miconsend(poweroff, sizeof(poweroff));
 291}
 292
 293/*****************************************************************************
 294 * General Setup
 295 ****************************************************************************/
 296static unsigned int tsp2_mpp_modes[] __initdata = {
 297        MPP0_PCIE_RST_OUTn,
 298        MPP1_UNUSED,
 299        MPP2_UNUSED,
 300        MPP3_UNUSED,
 301        MPP4_NAND,              /* BOOT NAND Flash REn */
 302        MPP5_NAND,              /* BOOT NAND Flash WEn */
 303        MPP6_NAND,              /* BOOT NAND Flash HREn[0] */
 304        MPP7_NAND,              /* BOOT NAND Flash WEn[0] */
 305        MPP8_GPIO,              /* MICON int */
 306        MPP9_GPIO,              /* RTC int */
 307        MPP10_UNUSED,
 308        MPP11_GPIO,             /* PCI Int A */
 309        MPP12_UNUSED,
 310        MPP13_GPIO,             /* UPS on UART0 enable */
 311        MPP14_GPIO,             /* UPS low battery detection */
 312        MPP15_UNUSED,
 313        MPP16_UART,             /* UART1 RXD */
 314        MPP17_UART,             /* UART1 TXD */
 315        MPP18_UART,             /* UART1 CTSn */
 316        MPP19_UART,             /* UART1 RTSn */
 317        0,
 318};
 319
 320static void __init tsp2_init(void)
 321{
 322        /*
 323         * Setup basic Orion functions. Need to be called early.
 324         */
 325        orion5x_init();
 326
 327        orion5x_mpp_conf(tsp2_mpp_modes);
 328
 329        /*
 330         * Configure peripherals.
 331         */
 332        mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET,
 333                                    ORION_MBUS_DEVBUS_BOOT_ATTR,
 334                                    TSP2_NOR_BOOT_BASE,
 335                                    TSP2_NOR_BOOT_SIZE);
 336        platform_device_register(&tsp2_nor_flash);
 337
 338        orion5x_ehci0_init();
 339        orion5x_eth_init(&tsp2_eth_data);
 340        orion5x_i2c_init();
 341        orion5x_uart0_init();
 342        orion5x_uart1_init();
 343
 344        /* Get RTC IRQ and register the chip */
 345        if (gpio_request(TSP2_RTC_GPIO, "rtc") == 0) {
 346                if (gpio_direction_input(TSP2_RTC_GPIO) == 0)
 347                        tsp2_i2c_rtc.irq = gpio_to_irq(TSP2_RTC_GPIO);
 348                else
 349                        gpio_free(TSP2_RTC_GPIO);
 350        }
 351        if (tsp2_i2c_rtc.irq == 0)
 352                pr_warn("tsp2_init: failed to get RTC IRQ\n");
 353        i2c_register_board_info(0, &tsp2_i2c_rtc, 1);
 354
 355        /* register Terastation Pro II specific power-off method */
 356        pm_power_off = tsp2_power_off;
 357}
 358
 359MACHINE_START(TERASTATION_PRO2, "Buffalo Terastation Pro II/Live")
 360        /* Maintainer:  Sylver Bruneau <sylver.bruneau@googlemail.com> */
 361        .atag_offset    = 0x100,
 362        .nr_irqs        = ORION5X_NR_IRQS,
 363        .init_machine   = tsp2_init,
 364        .map_io         = orion5x_map_io,
 365        .init_early     = orion5x_init_early,
 366        .init_irq       = orion5x_init_irq,
 367        .init_time      = orion5x_timer_init,
 368        .fixup          = tag_fixup_mem32,
 369        .restart        = orion5x_restart,
 370MACHINE_END
 371