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 (u32 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
 151/*
 152 * unmask multiplexed timer IRQs
 153 */
 154static void inline unmask_timerx_irq (u32 irq)
 155{
 156        unsigned int bit;
 157        bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
 158        CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) |= bit;
 159}
 160
 161static struct irq_chip h7202_timerx_chip = {
 162        .ack = mask_timerx_irq,
 163        .mask = mask_timerx_irq,
 164        .unmask = unmask_timerx_irq,
 165};
 166
 167static struct irqaction h7202_timer_irq = {
 168        .name           = "h7202 Timer Tick",
 169        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
 170        .handler        = h7202_timer_interrupt,
 171};
 172
 173/*
 174 * Setup TIMER0 as system timer
 175 */
 176void __init h7202_init_time(void)
 177{
 178        CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
 179        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
 180        CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
 181        CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) = ENABLE_TM0_INTR | TIMER_ENABLE_BIT;
 182
 183        setup_irq(IRQ_TIMER0, &h7202_timer_irq);
 184}
 185
 186struct sys_timer h7202_timer = {
 187        .init           = h7202_init_time,
 188        .offset         = h720x_gettimeoffset,
 189};
 190
 191void __init h7202_init_irq (void)
 192{
 193        int     irq;
 194
 195        CPU_REG (GPIO_E_VIRT, GPIO_MASK) = 0x0;
 196
 197        for (irq = IRQ_TIMER1;
 198                          irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
 199                mask_timerx_irq(irq);
 200                set_irq_chip(irq, &h7202_timerx_chip);
 201                set_irq_handler(irq, handle_edge_irq);
 202                set_irq_flags(irq, IRQF_VALID );
 203        }
 204        set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
 205
 206        h720x_init_irq();
 207}
 208
 209void __init init_hw_h7202(void)
 210{
 211        /* Enable clocks */
 212        CPU_REG (PMU_BASE, PMU_PLL_CTRL) |= PLL_2_EN | PLL_1_EN | PLL_3_MUTE;
 213
 214        CPU_REG (SERIAL0_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 215        CPU_REG (SERIAL1_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 216#ifdef CONFIG_H7202_SERIAL23
 217        CPU_REG (SERIAL2_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 218        CPU_REG (SERIAL3_VIRT, SERIAL_ENABLE) = SERIAL_ENABLE_EN;
 219        CPU_IO (GPIO_AMULSEL) = AMULSEL_USIN2 | AMULSEL_USOUT2 |
 220                                AMULSEL_USIN3 | AMULSEL_USOUT3;
 221#endif
 222        (void) platform_add_devices(devices, ARRAY_SIZE(devices));
 223}
 224