linux/arch/arm/mach-h720x/cpu-h7202.c
<<
>>
Prefs
   1/*
   2 * linux/arch/arm/mach-h720x/cpu-h7202.c
   3 *
   4 * Copyright (C) 2003 Thomas Gleixner <tglx@linutronix.de>
   5 *               2003 Robert Schwebel <r.schwebel@pengutronix.de>
   6 *               2004 Sascha Hauer    <s.hauer@pengutronix.de>
   7 *
   8 * processor specific stuff for the Hynix h7202
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 */
  15
  16#include <linux/init.h>
  17#include <linux/interrupt.h>
  18#include <linux/module.h>
  19#include <asm/types.h>
  20#include <mach/hardware.h>
  21#include <asm/irq.h>
  22#include <mach/irqs.h>
  23#include <asm/mach/irq.h>
  24#include <asm/mach/time.h>
  25#include <linux/device.h>
  26#include <linux/serial_8250.h>
  27#include "common.h"
  28
  29static struct resource h7202ps2_resources[] = {
  30        [0] = {
  31                .start  = 0x8002c000,
  32                .end    = 0x8002c040,
  33                .flags  = IORESOURCE_MEM,
  34        },
  35        [1] = {
  36                .start  = IRQ_PS2,
  37                .end    = IRQ_PS2,
  38                .flags  = IORESOURCE_IRQ,
  39        },
  40};
  41
  42static struct platform_device h7202ps2_device = {
  43        .name           = "h7202ps2",
  44        .id             = -1,
  45        .num_resources  = ARRAY_SIZE(h7202ps2_resources),
  46        .resource       = h7202ps2_resources,
  47};
  48
  49static struct plat_serial8250_port serial_platform_data[] = {
  50        {
  51                .membase        = (void*)SERIAL0_VIRT,
  52                .mapbase        = SERIAL0_BASE,
  53                .irq            = IRQ_UART0,
  54                .uartclk        = 2*1843200,
  55                .regshift       = 2,
  56                .iotype         = UPIO_MEM,
  57                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  58        },
  59        {
  60                .membase        = (void*)SERIAL1_VIRT,
  61                .mapbase        = SERIAL1_BASE,
  62                .irq            = IRQ_UART1,
  63                .uartclk        = 2*1843200,
  64                .regshift       = 2,
  65                .iotype         = UPIO_MEM,
  66                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  67        },
  68#ifdef CONFIG_H7202_SERIAL23
  69        {
  70                .membase        = (void*)SERIAL2_VIRT,
  71                .mapbase        = SERIAL2_BASE,
  72                .irq            = IRQ_UART2,
  73                .uartclk        = 2*1843200,
  74                .regshift       = 2,
  75                .iotype         = UPIO_MEM,
  76                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  77        },
  78        {
  79                .membase        = (void*)SERIAL3_VIRT,
  80                .mapbase        = SERIAL3_BASE,
  81                .irq            = IRQ_UART3,
  82                .uartclk        = 2*1843200,
  83                .regshift       = 2,
  84                .iotype         = UPIO_MEM,
  85                .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
  86        },
  87#endif
  88        { },
  89};
  90
  91static struct platform_device serial_device = {
  92        .name                   = "serial8250",
  93        .id                     = PLAT8250_DEV_PLATFORM,
  94        .dev                    = {
  95                .platform_data  = serial_platform_data,
  96        },
  97};
  98
  99static struct platform_device *devices[] __initdata = {
 100        &h7202ps2_device,
 101        &serial_device,
 102};
 103
 104/* Although we have two interrupt lines for the timers, we only have one
 105 * status register which clears all pending timer interrupts on reading. So
 106 * we have to handle all timer interrupts in one place.
 107 */
 108static void
 109h7202_timerx_demux_handler(unsigned int irq_unused, struct irq_desc *desc)
 110{
 111        unsigned int mask, irq;
 112
 113        mask = CPU_REG (TIMER_VIRT, TIMER_TOPSTAT);
 114
 115        if ( mask & TSTAT_T0INT ) {
 116                timer_tick();
 117                if( mask == TSTAT_T0INT )
 118                        return;
 119        }
 120
 121        mask >>= 1;
 122        irq = IRQ_TIMER1;
 123        while (mask) {
 124                if (mask & 1)
 125                        generic_handle_irq(irq);
 126                irq++;
 127                mask >>= 1;
 128        }
 129}
 130
 131/*
 132 * Timer interrupt handler
 133 */
 134static irqreturn_t
 135h7202_timer_interrupt(int irq, void *dev_id)
 136{
 137        h7202_timerx_demux_handler(0, NULL);
 138        return IRQ_HANDLED;
 139}
 140
 141/*
 142 * mask multiplexed timer IRQs
 143 */
 144static void inline __mask_timerx_irq(unsigned int irq)
 145{
 146        unsigned int bit;
 147        bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
 148        CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) &= ~bit;
 149}
 150
 151static void inline mask_timerx_irq(struct irq_data *d)
 152{
 153        __mask_timerx_irq(d->irq);
 154}
 155
 156/*
 157 * unmask multiplexed timer IRQs
 158 */
 159static void inline unmask_timerx_irq(struct irq_data *d)
 160{
 161        unsigned int bit;
 162        bit = 2 << ((d->irq == IRQ_TIMER64B) ? 4 : (d->irq - IRQ_TIMER1));
 163        CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit;
 164}
 165
 166static struct irq_chip h7202_timerx_chip = {
 167        .irq_ack = mask_timerx_irq,
 168        .irq_mask = mask_timerx_irq,
 169        .irq_unmask = unmask_timerx_irq,
 170};
 171
 172static struct irqaction h7202_timer_irq = {
 173        .name           = "h7202 Timer Tick",
 174        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 175        .handler        = h7202_timer_interrupt,
 176};
 177
 178/*
 179 * Setup TIMER0 as system timer
 180 */
 181void __init h7202_init_time(void)
 182{
 183        CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
 184        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
 185        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
 186        CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
 187
 188        setup_irq(IRQ_TIMER0, &h7202_timer_irq);
 189}
 190
 191struct sys_timer h7202_timer = {
 192        .init           = h7202_init_time,
 193        .offset         = h720x_gettimeoffset,
 194};
 195
 196void __init h7202_init_irq (void)
 197{
 198        int     irq;
 199
 200        CPU_REG (GPIO_E_VIRT, GPIO_MASK) = 0x0;
 201
 202        for (irq = IRQ_TIMER1;
 203                          irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
 204                __mask_timerx_irq(irq);
 205                irq_set_chip_and_handler(irq, &h7202_timerx_chip,
 206                                         handle_edge_irq);
 207                set_irq_flags(irq, IRQF_VALID );
 208        }
 209        irq_set_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
 210
 211        h720x_init_irq();
 212}
 213
 214void __init init_hw_h7202(void)
 215{
 216        /* Enable clocks */
 217        CPU_REG (PMU_BASE, PMU_PLL_CTRL) |= PLL_2_EN | PLL_1_EN | PLL_3_MUTE;
 218
 219        CPU_REG (SERIAL0_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 220        CPU_REG (SERIAL1_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 221#ifdef CONFIG_H7202_SERIAL23
 222        CPU_REG (SERIAL2_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 223        CPU_REG (SERIAL3_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 224        CPU_IO (GPIO_AMULSEL) = AMULSEL_USIN2 | AMULSEL_USOUT2 |
 225                                AMULSEL_USIN3 | AMULSEL_USOUT3;
 226#endif
 227        (void) platform_add_devices(devices, ARRAY_SIZE(devices));
 228}
 229