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/platform_device.h>
  14#include <linux/serial_8250.h>
  15
  16#include <asm/sni.h>
  17#include <asm/time.h>
  18
  19#define PORT(_base,_irq)                                \
  20        {                                               \
  21                .iobase         = _base,                \
  22                .irq            = _irq,                 \
  23                .uartclk        = 1843200,              \
  24                .iotype         = UPIO_PORT,            \
  25                .flags          = UPF_BOOT_AUTOCONF,    \
  26        }
  27
  28static struct plat_serial8250_port a20r_data[] = {
  29        PORT(0x3f8, 4),
  30        PORT(0x2f8, 3),
  31        { },
  32};
  33
  34static struct platform_device a20r_serial8250_device = {
  35        .name                   = "serial8250",
  36        .id                     = PLAT8250_DEV_PLATFORM,
  37        .dev                    = {
  38                .platform_data  = a20r_data,
  39        },
  40};
  41
  42static struct resource a20r_ds1216_rsrc[] = {
  43        {
  44                .start = 0x1c081ffc,
  45                .end   = 0x1c081fff,
  46                .flags = IORESOURCE_MEM
  47        }
  48};
  49
  50static struct platform_device a20r_ds1216_device = {
  51        .name           = "rtc-ds1216",
  52        .num_resources  = ARRAY_SIZE(a20r_ds1216_rsrc),
  53        .resource       = a20r_ds1216_rsrc
  54};
  55
  56static struct resource snirm_82596_rsrc[] = {
  57        {
  58                .start = 0x18000000,
  59                .end   = 0x18000004,
  60                .flags = IORESOURCE_MEM
  61        },
  62        {
  63                .start = 0x18010000,
  64                .end   = 0x18010004,
  65                .flags = IORESOURCE_MEM
  66        },
  67        {
  68                .start = 0x1ff00000,
  69                .end   = 0x1ff00020,
  70                .flags = IORESOURCE_MEM
  71        },
  72        {
  73                .start = 22,
  74                .end   = 22,
  75                .flags = IORESOURCE_IRQ
  76        },
  77        {
  78                .flags = 0x01                /* 16bit mpu port access */
  79        }
  80};
  81
  82static struct platform_device snirm_82596_pdev = {
  83        .name           = "snirm_82596",
  84        .num_resources  = ARRAY_SIZE(snirm_82596_rsrc),
  85        .resource       = snirm_82596_rsrc
  86};
  87
  88static struct resource snirm_53c710_rsrc[] = {
  89        {
  90                .start = 0x19000000,
  91                .end   = 0x190fffff,
  92                .flags = IORESOURCE_MEM
  93        },
  94        {
  95                .start = 19,
  96                .end   = 19,
  97                .flags = IORESOURCE_IRQ
  98        }
  99};
 100
 101static struct platform_device snirm_53c710_pdev = {
 102        .name           = "snirm_53c710",
 103        .num_resources  = ARRAY_SIZE(snirm_53c710_rsrc),
 104        .resource       = snirm_53c710_rsrc
 105};
 106
 107static struct resource sc26xx_rsrc[] = {
 108        {
 109                .start = 0x1c070000,
 110                .end   = 0x1c0700ff,
 111                .flags = IORESOURCE_MEM
 112        },
 113        {
 114                .start = 20,
 115                .end   = 20,
 116                .flags = IORESOURCE_IRQ
 117        }
 118};
 119
 120static unsigned int sc26xx_data[2] = {
 121        /* DTR   |   RTS    |   DSR    |   CTS     |   DCD     |   RI    */
 122        (8 << 0) | (4 << 4) | (6 << 8) | (0 << 12) | (6 << 16) | (0 << 20),
 123        (3 << 0) | (2 << 4) | (1 << 8) | (2 << 12) | (3 << 16) | (4 << 20)
 124};
 125
 126static struct platform_device sc26xx_pdev = {
 127        .name           = "SC26xx",
 128        .num_resources  = ARRAY_SIZE(sc26xx_rsrc),
 129        .resource       = sc26xx_rsrc,
 130        .dev                    = {
 131                .platform_data  = sc26xx_data,
 132        }
 133};
 134
 135static u32 a20r_ack_hwint(void)
 136{
 137        u32 status = read_c0_status();
 138
 139        write_c0_status(status | 0x00010000);
 140        asm volatile(
 141        "       .set    push                    \n"
 142        "       .set    noat                    \n"
 143        "       .set    noreorder               \n"
 144        "       lw      $1, 0(%0)               \n"
 145        "       sb      $0, 0(%1)               \n"
 146        "       sync                            \n"
 147        "       lb      %1, 0(%1)               \n"
 148        "       b       1f                      \n"
 149        "       ori     %1, $1, 2               \n"
 150        "       .align  8                       \n"
 151        "1:                                     \n"
 152        "       nop                             \n"
 153        "       sw      %1, 0(%0)               \n"
 154        "       sync                            \n"
 155        "       li      %1, 0x20                \n"
 156        "2:                                     \n"
 157        "       nop                             \n"
 158        "       bnez    %1,2b                   \n"
 159        "       addiu   %1, -1                  \n"
 160        "       sw      $1, 0(%0)               \n"
 161        "       sync                            \n"
 162                ".set   pop                     \n"
 163        :
 164        : "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
 165        write_c0_status(status);
 166
 167        return status;
 168}
 169
 170static inline void unmask_a20r_irq(unsigned int irq)
 171{
 172        set_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
 173        irq_enable_hazard();
 174}
 175
 176static inline void mask_a20r_irq(unsigned int irq)
 177{
 178        clear_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
 179        irq_disable_hazard();
 180}
 181
 182static void end_a20r_irq(unsigned int irq)
 183{
 184        if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
 185                a20r_ack_hwint();
 186                unmask_a20r_irq(irq);
 187        }
 188}
 189
 190static struct irq_chip a20r_irq_type = {
 191        .typename       = "A20R",
 192        .ack            = mask_a20r_irq,
 193        .mask           = mask_a20r_irq,
 194        .mask_ack       = mask_a20r_irq,
 195        .unmask         = unmask_a20r_irq,
 196        .end            = end_a20r_irq,
 197};
 198
 199/*
 200 * hwint 0 receive all interrupts
 201 */
 202static void a20r_hwint(void)
 203{
 204        u32 cause, status;
 205        int irq;
 206
 207        clear_c0_status(IE_IRQ0);
 208        status = a20r_ack_hwint();
 209        cause = read_c0_cause();
 210
 211        irq = ffs(((cause & status) >> 8) & 0xf8);
 212        if (likely(irq > 0))
 213                do_IRQ(SNI_A20R_IRQ_BASE + irq - 1);
 214        set_c0_status(IE_IRQ0);
 215}
 216
 217void __init sni_a20r_irq_init(void)
 218{
 219        int i;
 220
 221        for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
 222                set_irq_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
 223        sni_hwint = a20r_hwint;
 224        change_c0_status(ST0_IM, IE_IRQ0);
 225        setup_irq(SNI_A20R_IRQ_BASE + 3, &sni_isa_irq);
 226}
 227
 228void sni_a20r_init(void)
 229{
 230        /* FIXME, remove if not needed */
 231}
 232
 233static int __init snirm_a20r_setup_devinit(void)
 234{
 235        switch (sni_brd_type) {
 236        case SNI_BRD_TOWER_OASIC:
 237        case SNI_BRD_MINITOWER:
 238                platform_device_register(&snirm_82596_pdev);
 239                platform_device_register(&snirm_53c710_pdev);
 240                platform_device_register(&sc26xx_pdev);
 241                platform_device_register(&a20r_serial8250_device);
 242                platform_device_register(&a20r_ds1216_device);
 243                sni_eisa_root_init();
 244                break;
 245        }
 246        return 0;
 247}
 248
 249device_initcall(snirm_a20r_setup_devinit);
 250