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
 146static u32 a20r_ack_hwint(void)
 147{
 148        u32 status = read_c0_status();
 149
 150        write_c0_status(status | 0x00010000);
 151        asm volatile(
 152        "       .set    push                    \n"
 153        "       .set    noat                    \n"
 154        "       .set    noreorder               \n"
 155        "       lw      $1, 0(%0)               \n"
 156        "       sb      $0, 0(%1)               \n"
 157        "       sync                            \n"
 158        "       lb      %1, 0(%1)               \n"
 159        "       b       1f                      \n"
 160        "       ori     %1, $1, 2               \n"
 161        "       .align  8                       \n"
 162        "1:                                     \n"
 163        "       nop                             \n"
 164        "       sw      %1, 0(%0)               \n"
 165        "       sync                            \n"
 166        "       li      %1, 0x20                \n"
 167        "2:                                     \n"
 168        "       nop                             \n"
 169        "       bnez    %1,2b                   \n"
 170        "       addiu   %1, -1                  \n"
 171        "       sw      $1, 0(%0)               \n"
 172        "       sync                            \n"
 173                ".set   pop                     \n"
 174        :
 175        : "Jr" (PCIMT_UCONF), "Jr" (0xbc000000));
 176        write_c0_status(status);
 177
 178        return status;
 179}
 180
 181static inline void unmask_a20r_irq(struct irq_data *d)
 182{
 183        set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 184        irq_enable_hazard();
 185}
 186
 187static inline void mask_a20r_irq(struct irq_data *d)
 188{
 189        clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 190        irq_disable_hazard();
 191}
 192
 193static struct irq_chip a20r_irq_type = {
 194        .name           = "A20R",
 195        .irq_mask       = mask_a20r_irq,
 196        .irq_unmask     = unmask_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                irq_set_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