linux/arch/arm/mach-netx/generic.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-netx/generic.c
   3 *
   4 * Copyright (C) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2
   8 * as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 */
  19
  20#include <linux/device.h>
  21#include <linux/init.h>
  22#include <linux/kernel.h>
  23#include <linux/module.h>
  24#include <linux/platform_device.h>
  25#include <linux/io.h>
  26#include <mach/hardware.h>
  27#include <asm/mach/map.h>
  28#include <asm/hardware/vic.h>
  29#include <mach/netx-regs.h>
  30#include <asm/mach/irq.h>
  31
  32static struct map_desc netx_io_desc[] __initdata = {
  33        {
  34                .virtual        = NETX_IO_VIRT,
  35                .pfn            = __phys_to_pfn(NETX_IO_PHYS),
  36                .length         = NETX_IO_SIZE,
  37                .type           = MT_DEVICE
  38        }
  39};
  40
  41void __init netx_map_io(void)
  42{
  43        iotable_init(netx_io_desc, ARRAY_SIZE(netx_io_desc));
  44}
  45
  46static struct resource netx_rtc_resources[] = {
  47        [0] = {
  48                .start  = 0x00101200,
  49                .end    = 0x00101220,
  50                .flags  = IORESOURCE_MEM,
  51        },
  52};
  53
  54static struct platform_device netx_rtc_device = {
  55        .name           = "netx-rtc",
  56        .id             = 0,
  57        .num_resources  = ARRAY_SIZE(netx_rtc_resources),
  58        .resource       = netx_rtc_resources,
  59};
  60
  61static struct platform_device *devices[] __initdata = {
  62        &netx_rtc_device,
  63};
  64
  65#if 0
  66#define DEBUG_IRQ(fmt...)       printk(fmt)
  67#else
  68#define DEBUG_IRQ(fmt...)       while (0) {}
  69#endif
  70
  71static void
  72netx_hif_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
  73{
  74        unsigned int irq = NETX_IRQ_HIF_CHAINED(0);
  75        unsigned int stat;
  76
  77        stat = ((readl(NETX_DPMAS_INT_EN) &
  78                readl(NETX_DPMAS_INT_STAT)) >> 24) & 0x1f;
  79
  80        while (stat) {
  81                if (stat & 1) {
  82                        DEBUG_IRQ("handling irq %d\n", irq);
  83                        generic_handle_irq(irq);
  84                }
  85                irq++;
  86                stat >>= 1;
  87        }
  88}
  89
  90static int
  91netx_hif_irq_type(unsigned int _irq, unsigned int type)
  92{
  93        unsigned int val, irq;
  94
  95        val = readl(NETX_DPMAS_IF_CONF1);
  96
  97        irq = _irq - NETX_IRQ_HIF_CHAINED(0);
  98
  99        if (type & IRQ_TYPE_EDGE_RISING) {
 100                DEBUG_IRQ("rising edges\n");
 101                val |= (1 << 26) << irq;
 102        }
 103        if (type & IRQ_TYPE_EDGE_FALLING) {
 104                DEBUG_IRQ("falling edges\n");
 105                val &= ~((1 << 26) << irq);
 106        }
 107        if (type & IRQ_TYPE_LEVEL_LOW) {
 108                DEBUG_IRQ("low level\n");
 109                val &= ~((1 << 26) << irq);
 110        }
 111        if (type & IRQ_TYPE_LEVEL_HIGH) {
 112                DEBUG_IRQ("high level\n");
 113                val |= (1 << 26) << irq;
 114        }
 115
 116        writel(val, NETX_DPMAS_IF_CONF1);
 117
 118        return 0;
 119}
 120
 121static void
 122netx_hif_ack_irq(unsigned int _irq)
 123{
 124        unsigned int val, irq;
 125
 126        irq = _irq - NETX_IRQ_HIF_CHAINED(0);
 127        writel((1 << 24) << irq, NETX_DPMAS_INT_STAT);
 128
 129        val = readl(NETX_DPMAS_INT_EN);
 130        val &= ~((1 << 24) << irq);
 131        writel(val, NETX_DPMAS_INT_EN);
 132
 133        DEBUG_IRQ("%s: irq %d\n", __func__, _irq);
 134}
 135
 136static void
 137netx_hif_mask_irq(unsigned int _irq)
 138{
 139        unsigned int val, irq;
 140
 141        irq = _irq - NETX_IRQ_HIF_CHAINED(0);
 142        val = readl(NETX_DPMAS_INT_EN);
 143        val &= ~((1 << 24) << irq);
 144        writel(val, NETX_DPMAS_INT_EN);
 145        DEBUG_IRQ("%s: irq %d\n", __func__, _irq);
 146}
 147
 148static void
 149netx_hif_unmask_irq(unsigned int _irq)
 150{
 151        unsigned int val, irq;
 152
 153        irq = _irq - NETX_IRQ_HIF_CHAINED(0);
 154        val = readl(NETX_DPMAS_INT_EN);
 155        val |= (1 << 24) << irq;
 156        writel(val, NETX_DPMAS_INT_EN);
 157        DEBUG_IRQ("%s: irq %d\n", __func__, _irq);
 158}
 159
 160static struct irq_chip netx_hif_chip = {
 161        .ack = netx_hif_ack_irq,
 162        .mask = netx_hif_mask_irq,
 163        .unmask = netx_hif_unmask_irq,
 164        .set_type = netx_hif_irq_type,
 165};
 166
 167void __init netx_init_irq(void)
 168{
 169        int irq;
 170
 171        vic_init(__io(io_p2v(NETX_PA_VIC)), 0, ~0, 0);
 172
 173        for (irq = NETX_IRQ_HIF_CHAINED(0); irq <= NETX_IRQ_HIF_LAST; irq++) {
 174                set_irq_chip(irq, &netx_hif_chip);
 175                set_irq_handler(irq, handle_level_irq);
 176                set_irq_flags(irq, IRQF_VALID);
 177        }
 178
 179        writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
 180        set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
 181}
 182
 183static int __init netx_init(void)
 184{
 185        return platform_add_devices(devices, ARRAY_SIZE(devices));
 186}
 187
 188subsys_initcall(netx_init);
 189
 190