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
 121static unsigned int sc26xx_data[2] = {
 122        /* DTR   |   RTS    |   DSR    |   CTS     |   DCD     |   RI    */
 123        (8 << 0) | (4 << 4) | (6 << 8) | (0 << 12) | (6 << 16) | (0 << 20),
 124        (3 << 0) | (2 << 4) | (1 << 8) | (2 << 12) | (3 << 16) | (4 << 20)
 125};
 126
 127static struct platform_device sc26xx_pdev = {
 128        .name           = "SC26xx",
 129        .num_resources  = ARRAY_SIZE(sc26xx_rsrc),
 130        .resource       = sc26xx_rsrc,
 131        .dev                    = {
 132                .platform_data  = sc26xx_data,
 133        }
 134};
 135
 136static u32 a20r_ack_hwint(void)
 137{
 138        u32 status = read_c0_status();
 139
 140        write_c0_status(status | 0x00010000);
 141        asm volatile(
 142        "       .set    push                    \n"
 143        "       .set    noat                    \n"
 144        "       .set    noreorder               \n"
 145        "       lw      $1, 0(%0)               \n"
 146        "       sb      $0, 0(%1)               \n"
 147        "       sync                            \n"
 148        "       lb      %1, 0(%1)               \n"
 149        "       b       1f                      \n"
 150        "       ori     %1, $1, 2               \n"
 151        "       .align  8                       \n"
 152        "1:                                     \n"
 153        "       nop                             \n"
 154        "       sw      %1, 0(%0)               \n"
 155        "       sync                            \n"
 156        "       li      %1, 0x20                \n"
 157        "2:                                     \n"
 158        "       nop                             \n"
 159        "       bnez    %1,2b                   \n"
 160        "       addiu   %1, -1                  \n"
 161        "       sw      $1, 0(%0)               \n"
 162        "       sync                            \n"
 163                ".set   pop                     \n"
 164        :
 165        : "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
 166        write_c0_status(status);
 167
 168        return status;
 169}
 170
 171static inline void unmask_a20r_irq(unsigned int irq)
 172{
 173        set_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
 174        irq_enable_hazard();
 175}
 176
 177static inline void mask_a20r_irq(unsigned int irq)
 178{
 179        clear_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
 180        irq_disable_hazard();
 181}
 182
 183static void end_a20r_irq(unsigned int irq)
 184{
 185        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 186                a20r_ack_hwint();
 187                unmask_a20r_irq(irq);
 188        }
 189}
 190
 191static struct irq_chip a20r_irq_type = {
 192        .name           = "A20R",
 193        .ack            = mask_a20r_irq,
 194        .mask           = mask_a20r_irq,
 195        .mask_ack       = mask_a20r_irq,
 196        .unmask         = unmask_a20r_irq,
 197        .end            = end_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                set_irq_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