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        .frequency      = 3686400,
 126        .mctrl_cfg[0]   = MCTRL_SIG(DTR_OP, LINE_OP7) |
 127                          MCTRL_SIG(RTS_OP, LINE_OP3) |
 128                          MCTRL_SIG(DSR_IP, LINE_IP5) |
 129                          MCTRL_SIG(DCD_IP, LINE_IP6),
 130        .mctrl_cfg[1]   = MCTRL_SIG(DTR_OP, LINE_OP2) |
 131                          MCTRL_SIG(RTS_OP, LINE_OP1) |
 132                          MCTRL_SIG(DSR_IP, LINE_IP0) |
 133                          MCTRL_SIG(CTS_IP, LINE_IP1) |
 134                          MCTRL_SIG(DCD_IP, LINE_IP2) |
 135                          MCTRL_SIG(RNG_IP, LINE_IP3),
 136};
 137
 138static struct platform_device sc26xx_pdev = {
 139        .name           = "sc2681",
 140        .resource       = sc26xx_rsrc,
 141        .num_resources  = ARRAY_SIZE(sc26xx_rsrc),
 142        .dev    = {
 143                .platform_data  = &sccnxp_data,
 144        },
 145};
 146
 147static u32 a20r_ack_hwint(void)
 148{
 149        u32 status = read_c0_status();
 150
 151        write_c0_status(status | 0x00010000);
 152        asm volatile(
 153        "       .set    push                    \n"
 154        "       .set    noat                    \n"
 155        "       .set    noreorder               \n"
 156        "       lw      $1, 0(%0)               \n"
 157        "       sb      $0, 0(%1)               \n"
 158        "       sync                            \n"
 159        "       lb      %1, 0(%1)               \n"
 160        "       b       1f                      \n"
 161        "       ori     %1, $1, 2               \n"
 162        "       .align  8                       \n"
 163        "1:                                     \n"
 164        "       nop                             \n"
 165        "       sw      %1, 0(%0)               \n"
 166        "       sync                            \n"
 167        "       li      %1, 0x20                \n"
 168        "2:                                     \n"
 169        "       nop                             \n"
 170        "       bnez    %1,2b                   \n"
 171        "       addiu   %1, -1                  \n"
 172        "       sw      $1, 0(%0)               \n"
 173        "       sync                            \n"
 174                ".set   pop                     \n"
 175        :
 176        : "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
 177        write_c0_status(status);
 178
 179        return status;
 180}
 181
 182static inline void unmask_a20r_irq(struct irq_data *d)
 183{
 184        set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 185        irq_enable_hazard();
 186}
 187
 188static inline void mask_a20r_irq(struct irq_data *d)
 189{
 190        clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 191        irq_disable_hazard();
 192}
 193
 194static struct irq_chip a20r_irq_type = {
 195        .name           = "A20R",
 196        .irq_mask       = mask_a20r_irq,
 197        .irq_unmask     = unmask_a20r_irq,
 198};
 199
 200/*
 201 * hwint 0 receive all interrupts
 202 */
 203static void a20r_hwint(void)
 204{
 205        u32 cause, status;
 206        int irq;
 207
 208        clear_c0_status(IE_IRQ0);
 209        status = a20r_ack_hwint();
 210        cause = read_c0_cause();
 211
 212        irq = ffs(((cause & status) >> 8) & 0xf8);
 213        if (likely(irq > 0))
 214                do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
 215        set_c0_status(IE_IRQ0);
 216}
 217
 218void __init sni_a20r_irq_init(void)
 219{
 220        int i;
 221
 222        for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
 223                irq_set_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
 224        sni_hwint = a20r_hwint;
 225        change_c0_status(ST0_IM, IE_IRQ0);
 226        setup_irq(SNI_A20R_IRQ_BASE + 3, &sni_isa_irq);
 227}
 228
 229void sni_a20r_init(void)
 230{
 231        /* FIXME, remove if not needed */
 232}
 233
 234static int __init snirm_a20r_setup_devinit(void)
 235{
 236        switch (sni_brd_type) {
 237        case SNI_BRD_TOWER_OASIC:
 238        case SNI_BRD_MINITOWER:
 239                platform_device_register(&snirm_82596_pdev);
 240                platform_device_register(&snirm_53c710_pdev);
 241                platform_device_register(&sc26xx_pdev);
 242                platform_device_register(&a20r_serial8250_device);
 243                platform_device_register(&a20r_ds1216_device);
 244                sni_eisa_root_init();
 245                break;
 246        }
 247        return 0;
 248}
 249
 250device_initcall(snirm_a20r_setup_devinit);
 251