linux/arch/mips/sni/a20r.c
<<
>>
Prefs
   1/*
   2 * A20R specific code
   3 *
   4 * This file is subject to the terms and conditions of the GNU General Public
   5 * License.  See the file "COPYING" in the main directory of this archive
   6 * for more details.
   7 *
   8 * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
   9 */
  10
  11#include <linux/init.h>
  12#include <linux/interrupt.h>
  13#include <linux/irq.h>
  14#include <linux/platform_device.h>
  15#include <linux/serial_8250.h>
  16
  17#include <asm/sni.h>
  18#include <asm/time.h>
  19
  20#define PORT(_base,_irq)                                \
  21        {                                               \
  22                .iobase         = _base,                \
  23                .irq            = _irq,                 \
  24                .uartclk        = 1843200,              \
  25                .iotype         = UPIO_PORT,            \
  26                .flags          = UPF_BOOT_AUTOCONF,    \
  27        }
  28
  29static struct plat_serial8250_port a20r_data[] = {
  30        PORT(0x3f8, 4),
  31        PORT(0x2f8, 3),
  32        { },
  33};
  34
  35static struct platform_device a20r_serial8250_device = {
  36        .name                   = "serial8250",
  37        .id                     = PLAT8250_DEV_PLATFORM,
  38        .dev                    = {
  39                .platform_data  = a20r_data,
  40        },
  41};
  42
  43static struct resource a20r_ds1216_rsrc[] = {
  44        {
  45                .start = 0x1c081ffc,
  46                .end   = 0x1c081fff,
  47                .flags = IORESOURCE_MEM
  48        }
  49};
  50
  51static struct platform_device a20r_ds1216_device = {
  52        .name           = "rtc-ds1216",
  53        .num_resources  = ARRAY_SIZE(a20r_ds1216_rsrc),
  54        .resource       = a20r_ds1216_rsrc
  55};
  56
  57static struct resource snirm_82596_rsrc[] = {
  58        {
  59                .start = 0x18000000,
  60                .end   = 0x18000004,
  61                .flags = IORESOURCE_MEM
  62        },
  63        {
  64                .start = 0x18010000,
  65                .end   = 0x18010004,
  66                .flags = IORESOURCE_MEM
  67        },
  68        {
  69                .start = 0x1ff00000,
  70                .end   = 0x1ff00020,
  71                .flags = IORESOURCE_MEM
  72        },
  73        {
  74                .start = 22,
  75                .end   = 22,
  76                .flags = IORESOURCE_IRQ
  77        },
  78        {
  79                .flags = 0x01                /* 16bit mpu port access */
  80        }
  81};
  82
  83static struct platform_device snirm_82596_pdev = {
  84        .name           = "snirm_82596",
  85        .num_resources  = ARRAY_SIZE(snirm_82596_rsrc),
  86        .resource       = snirm_82596_rsrc
  87};
  88
  89static struct resource snirm_53c710_rsrc[] = {
  90        {
  91                .start = 0x19000000,
  92                .end   = 0x190fffff,
  93                .flags = IORESOURCE_MEM
  94        },
  95        {
  96                .start = 19,
  97                .end   = 19,
  98                .flags = IORESOURCE_IRQ
  99        }
 100};
 101
 102static struct platform_device snirm_53c710_pdev = {
 103        .name           = "snirm_53c710",
 104        .num_resources  = ARRAY_SIZE(snirm_53c710_rsrc),
 105        .resource       = snirm_53c710_rsrc
 106};
 107
 108static struct resource sc26xx_rsrc[] = {
 109        {
 110                .start = 0x1c070000,
 111                .end   = 0x1c0700ff,
 112                .flags = IORESOURCE_MEM
 113        },
 114        {
 115                .start = 20,
 116                .end   = 20,
 117                .flags = IORESOURCE_IRQ
 118        }
 119};
 120
 121#include <linux/platform_data/serial-sccnxp.h>
 122
 123static struct sccnxp_pdata sccnxp_data = {
 124        .reg_shift      = 2,
 125        .mctrl_cfg[0]   = MCTRL_SIG(DTR_OP, LINE_OP7) |
 126                          MCTRL_SIG(RTS_OP, LINE_OP3) |
 127                          MCTRL_SIG(DSR_IP, LINE_IP5) |
 128                          MCTRL_SIG(DCD_IP, LINE_IP6),
 129        .mctrl_cfg[1]   = MCTRL_SIG(DTR_OP, LINE_OP2) |
 130                          MCTRL_SIG(RTS_OP, LINE_OP1) |
 131                          MCTRL_SIG(DSR_IP, LINE_IP0) |
 132                          MCTRL_SIG(CTS_IP, LINE_IP1) |
 133                          MCTRL_SIG(DCD_IP, LINE_IP2) |
 134                          MCTRL_SIG(RNG_IP, LINE_IP3),
 135};
 136
 137static struct platform_device sc26xx_pdev = {
 138        .name           = "sc2681",
 139        .resource       = sc26xx_rsrc,
 140        .num_resources  = ARRAY_SIZE(sc26xx_rsrc),
 141        .dev    = {
 142                .platform_data  = &sccnxp_data,
 143        },
 144};
 145
 146/*
 147 * Trigger chipset to update CPU's CAUSE IP field
 148 */
 149static u32 a20r_update_cause_ip(void)
 150{
 151        u32 status = read_c0_status();
 152
 153        write_c0_status(status | 0x00010000);
 154        asm volatile(
 155        "       .set    push                    \n"
 156        "       .set    noat                    \n"
 157        "       .set    noreorder               \n"
 158        "       lw      $1, 0(%0)               \n"
 159        "       sb      $0, 0(%1)               \n"
 160        "       sync                            \n"
 161        "       lb      %1, 0(%1)               \n"
 162        "       b       1f                      \n"
 163        "       ori     %1, $1, 2               \n"
 164        "       .align  8                       \n"
 165        "1:                                     \n"
 166        "       nop                             \n"
 167        "       sw      %1, 0(%0)               \n"
 168        "       sync                            \n"
 169        "       li      %1, 0x20                \n"
 170        "2:                                     \n"
 171        "       nop                             \n"
 172        "       bnez    %1,2b                   \n"
 173        "       addiu   %1, -1                  \n"
 174        "       sw      $1, 0(%0)               \n"
 175        "       sync                            \n"
 176                ".set   pop                     \n"
 177        :
 178        : "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
 179        write_c0_status(status);
 180
 181        return status;
 182}
 183
 184static inline void unmask_a20r_irq(struct irq_data *d)
 185{
 186        set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 187        irq_enable_hazard();
 188}
 189
 190static inline void mask_a20r_irq(struct irq_data *d)
 191{
 192        clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 193        irq_disable_hazard();
 194}
 195
 196static struct irq_chip a20r_irq_type = {
 197        .name           = "A20R",
 198        .irq_mask       = mask_a20r_irq,
 199        .irq_unmask     = unmask_a20r_irq,
 200};
 201
 202/*
 203 * hwint 0 receive all interrupts
 204 */
 205static void a20r_hwint(void)
 206{
 207        u32 cause, status;
 208        int irq;
 209
 210        clear_c0_status(IE_IRQ0);
 211        status = a20r_update_cause_ip();
 212        cause = read_c0_cause();
 213
 214        irq = ffs(((cause & status) >> 8) & 0xf8);
 215        if (likely(irq > 0))
 216                do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
 217
 218        a20r_update_cause_ip();
 219        set_c0_status(IE_IRQ0);
 220}
 221
 222void __init sni_a20r_irq_init(void)
 223{
 224        int i;
 225
 226        for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
 227                irq_set_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
 228        sni_hwint = a20r_hwint;
 229        change_c0_status(ST0_IM, IE_IRQ0);
 230        if (request_irq(SNI_A20R_IRQ_BASE + 3, sni_isa_irq_handler,
 231                        IRQF_SHARED, "ISA", sni_isa_irq_handler))
 232                pr_err("Failed to register ISA interrupt\n");
 233}
 234
 235void sni_a20r_init(void)
 236{
 237        /* FIXME, remove if not needed */
 238}
 239
 240static int __init snirm_a20r_setup_devinit(void)
 241{
 242        switch (sni_brd_type) {
 243        case SNI_BRD_TOWER_OASIC:
 244        case SNI_BRD_MINITOWER:
 245                platform_device_register(&snirm_82596_pdev);
 246                platform_device_register(&snirm_53c710_pdev);
 247                platform_device_register(&sc26xx_pdev);
 248                platform_device_register(&a20r_serial8250_device);
 249                platform_device_register(&a20r_ds1216_device);
 250                sni_eisa_root_init();
 251                break;
 252        }
 253        return 0;
 254}
 255
 256device_initcall(snirm_a20r_setup_devinit);
 257