diff options
| -rw-r--r-- | arch/arm/Kconfig | 2 | ||||
| -rw-r--r-- | arch/arm/mach-w90x900/clock.c | 6 | ||||
| -rw-r--r-- | arch/arm/mach-w90x900/time.c | 151 | ||||
| -rw-r--r-- | arch/arm/mach-w90x900/w90p910.c | 2 |
4 files changed, 137 insertions, 24 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c3fed1ee730..8c4f03d3412 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -495,6 +495,8 @@ config ARCH_W90X900 | |||
| 495 | select GENERIC_GPIO | 495 | select GENERIC_GPIO |
| 496 | select HAVE_CLK | 496 | select HAVE_CLK |
| 497 | select COMMON_CLKDEV | 497 | select COMMON_CLKDEV |
| 498 | select GENERIC_TIME | ||
| 499 | select GENERIC_CLOCKEVENTS | ||
| 498 | help | 500 | help |
| 499 | Support for Nuvoton (Winbond logic dept.) ARM9 processor,You | 501 | Support for Nuvoton (Winbond logic dept.) ARM9 processor,You |
| 500 | can login www.mcuos.com or www.nuvoton.com to know more. | 502 | can login www.mcuos.com or www.nuvoton.com to know more. |
diff --git a/arch/arm/mach-w90x900/clock.c b/arch/arm/mach-w90x900/clock.c index 49cf1fbc14e..70b67109637 100644 --- a/arch/arm/mach-w90x900/clock.c +++ b/arch/arm/mach-w90x900/clock.c | |||
| @@ -55,6 +55,12 @@ void clk_disable(struct clk *clk) | |||
| 55 | } | 55 | } |
| 56 | EXPORT_SYMBOL(clk_disable); | 56 | EXPORT_SYMBOL(clk_disable); |
| 57 | 57 | ||
| 58 | unsigned long clk_get_rate(struct clk *clk) | ||
| 59 | { | ||
| 60 | return 15000000; | ||
| 61 | } | ||
| 62 | EXPORT_SYMBOL(clk_get_rate); | ||
| 63 | |||
| 58 | void w90x900_clk_enable(struct clk *clk, int enable) | 64 | void w90x900_clk_enable(struct clk *clk, int enable) |
| 59 | { | 65 | { |
| 60 | unsigned int clocks = clk->cken; | 66 | unsigned int clocks = clk->cken; |
diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c index bcc838f6b39..5e06770e601 100644 --- a/arch/arm/mach-w90x900/time.c +++ b/arch/arm/mach-w90x900/time.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Based on linux/arch/arm/plat-s3c24xx/time.c by Ben Dooks | 4 | * Based on linux/arch/arm/plat-s3c24xx/time.c by Ben Dooks |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2008 Nuvoton technology corporation | 6 | * Copyright (c) 2009 Nuvoton technology corporation |
| 7 | * All rights reserved. | 7 | * All rights reserved. |
| 8 | * | 8 | * |
| 9 | * Wan ZongShun <mcuos.com@gmail.com> | 9 | * Wan ZongShun <mcuos.com@gmail.com> |
| @@ -23,6 +23,8 @@ | |||
| 23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
| 24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 25 | #include <linux/leds.h> | 25 | #include <linux/leds.h> |
| 26 | #include <linux/clocksource.h> | ||
| 27 | #include <linux/clockchips.h> | ||
| 26 | 28 | ||
| 27 | #include <asm/mach-types.h> | 29 | #include <asm/mach-types.h> |
| 28 | #include <asm/mach/irq.h> | 30 | #include <asm/mach/irq.h> |
| @@ -31,49 +33,150 @@ | |||
| 31 | #include <mach/map.h> | 33 | #include <mach/map.h> |
| 32 | #include <mach/regs-timer.h> | 34 | #include <mach/regs-timer.h> |
| 33 | 35 | ||
| 34 | static unsigned long w90x900_gettimeoffset(void) | 36 | #define RESETINT 0x1f |
| 37 | #define PERIOD (0x01 << 27) | ||
| 38 | #define ONESHOT (0x00 << 27) | ||
| 39 | #define COUNTEN (0x01 << 30) | ||
| 40 | #define INTEN (0x01 << 29) | ||
| 41 | |||
| 42 | #define TICKS_PER_SEC 100 | ||
| 43 | #define PRESCALE 0x63 /* Divider = prescale + 1 */ | ||
| 44 | |||
| 45 | unsigned int timer0_load; | ||
| 46 | |||
| 47 | static void w90p910_clockevent_setmode(enum clock_event_mode mode, | ||
| 48 | struct clock_event_device *clk) | ||
| 35 | { | 49 | { |
| 50 | unsigned int val; | ||
| 51 | |||
| 52 | val = __raw_readl(REG_TCSR0); | ||
| 53 | val &= ~(0x03 << 27); | ||
| 54 | |||
| 55 | switch (mode) { | ||
| 56 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 57 | __raw_writel(timer0_load, REG_TICR0); | ||
| 58 | val |= (PERIOD | COUNTEN | INTEN | PRESCALE); | ||
| 59 | break; | ||
| 60 | |||
| 61 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 62 | val |= (ONESHOT | COUNTEN | INTEN | PRESCALE); | ||
| 63 | break; | ||
| 64 | |||
| 65 | case CLOCK_EVT_MODE_UNUSED: | ||
| 66 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 67 | case CLOCK_EVT_MODE_RESUME: | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | |||
| 71 | __raw_writel(val, REG_TCSR0); | ||
| 72 | } | ||
| 73 | |||
| 74 | static int w90p910_clockevent_setnextevent(unsigned long evt, | ||
| 75 | struct clock_event_device *clk) | ||
| 76 | { | ||
| 77 | unsigned int val; | ||
| 78 | |||
| 79 | __raw_writel(evt, REG_TICR0); | ||
| 80 | |||
| 81 | val = __raw_readl(REG_TCSR0); | ||
| 82 | val |= (COUNTEN | INTEN | PRESCALE); | ||
| 83 | __raw_writel(val, REG_TCSR0); | ||
| 84 | |||
| 36 | return 0; | 85 | return 0; |
| 37 | } | 86 | } |
| 38 | 87 | ||
| 88 | static struct clock_event_device w90p910_clockevent_device = { | ||
| 89 | .name = "w90p910-timer0", | ||
| 90 | .shift = 32, | ||
| 91 | .features = CLOCK_EVT_MODE_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | ||
| 92 | .set_mode = w90p910_clockevent_setmode, | ||
| 93 | .set_next_event = w90p910_clockevent_setnextevent, | ||
| 94 | .rating = 300, | ||
| 95 | }; | ||
| 96 | |||
| 39 | /*IRQ handler for the timer*/ | 97 | /*IRQ handler for the timer*/ |
| 40 | 98 | ||
| 41 | static irqreturn_t | 99 | static irqreturn_t w90p910_timer0_interrupt(int irq, void *dev_id) |
| 42 | w90x900_timer_interrupt(int irq, void *dev_id) | ||
| 43 | { | 100 | { |
| 44 | timer_tick(); | 101 | struct clock_event_device *evt = &w90p910_clockevent_device; |
| 102 | |||
| 45 | __raw_writel(0x01, REG_TISR); /* clear TIF0 */ | 103 | __raw_writel(0x01, REG_TISR); /* clear TIF0 */ |
| 104 | |||
| 105 | evt->event_handler(evt); | ||
| 46 | return IRQ_HANDLED; | 106 | return IRQ_HANDLED; |
| 47 | } | 107 | } |
| 48 | 108 | ||
| 49 | static struct irqaction w90x900_timer_irq = { | 109 | static struct irqaction w90p910_timer0_irq = { |
| 50 | .name = "w90x900 Timer Tick", | 110 | .name = "w90p910-timer0", |
| 51 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, | 111 | .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, |
| 52 | .handler = w90x900_timer_interrupt, | 112 | .handler = w90p910_timer0_interrupt, |
| 53 | }; | 113 | }; |
| 54 | 114 | ||
| 55 | /*Set up timer reg.*/ | 115 | static void __init w90p910_clockevents_init(unsigned int rate) |
| 116 | { | ||
| 117 | w90p910_clockevent_device.mult = div_sc(rate, NSEC_PER_SEC, | ||
| 118 | w90p910_clockevent_device.shift); | ||
| 119 | w90p910_clockevent_device.max_delta_ns = clockevent_delta2ns(0xffffffff, | ||
| 120 | &w90p910_clockevent_device); | ||
| 121 | w90p910_clockevent_device.min_delta_ns = clockevent_delta2ns(0xf, | ||
| 122 | &w90p910_clockevent_device); | ||
| 123 | w90p910_clockevent_device.cpumask = cpumask_of(0); | ||
| 56 | 124 | ||
| 57 | static void w90x900_timer_setup(void) | 125 | clockevents_register_device(&w90p910_clockevent_device); |
| 126 | } | ||
| 127 | |||
| 128 | static cycle_t w90p910_get_cycles(struct clocksource *cs) | ||
| 58 | { | 129 | { |
| 59 | __raw_writel(0, REG_TCSR0); | 130 | return ~__raw_readl(REG_TDR1); |
| 60 | __raw_writel(0, REG_TCSR1); | ||
| 61 | __raw_writel(0, REG_TCSR2); | ||
| 62 | __raw_writel(0, REG_TCSR3); | ||
| 63 | __raw_writel(0, REG_TCSR4); | ||
| 64 | __raw_writel(0x1F, REG_TISR); | ||
| 65 | __raw_writel(15000000/(100 * 100), REG_TICR0); | ||
| 66 | __raw_writel(0x68000063, REG_TCSR0); | ||
| 67 | } | 131 | } |
| 68 | 132 | ||
| 69 | static void __init w90x900_timer_init(void) | 133 | static struct clocksource clocksource_w90p910 = { |
| 134 | .name = "w90p910-timer1", | ||
| 135 | .rating = 200, | ||
| 136 | .read = w90p910_get_cycles, | ||
| 137 | .mask = CLOCKSOURCE_MASK(32), | ||
| 138 | .shift = 20, | ||
| 139 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
| 140 | }; | ||
| 141 | |||
| 142 | static void __init w90p910_clocksource_init(unsigned int rate) | ||
| 70 | { | 143 | { |
| 71 | w90x900_timer_setup(); | 144 | unsigned int val; |
| 72 | setup_irq(IRQ_TIMER0, &w90x900_timer_irq); | 145 | |
| 146 | __raw_writel(0xffffffff, REG_TICR1); | ||
| 147 | |||
| 148 | val = __raw_readl(REG_TCSR1); | ||
| 149 | val |= (COUNTEN | PERIOD); | ||
| 150 | __raw_writel(val, REG_TCSR1); | ||
| 151 | |||
| 152 | clocksource_w90p910.mult = | ||
| 153 | clocksource_khz2mult((rate / 1000), clocksource_w90p910.shift); | ||
| 154 | clocksource_register(&clocksource_w90p910); | ||
| 155 | } | ||
| 156 | |||
| 157 | static void __init w90p910_timer_init(void) | ||
| 158 | { | ||
| 159 | struct clk *ck_ext = clk_get(NULL, "ext"); | ||
| 160 | unsigned int rate; | ||
| 161 | |||
| 162 | BUG_ON(IS_ERR(ck_ext)); | ||
| 163 | |||
| 164 | rate = clk_get_rate(ck_ext); | ||
| 165 | clk_put(ck_ext); | ||
| 166 | rate = rate / (PRESCALE + 0x01); | ||
| 167 | |||
| 168 | /* set a known state */ | ||
| 169 | __raw_writel(0x00, REG_TCSR0); | ||
| 170 | __raw_writel(0x00, REG_TCSR1); | ||
| 171 | __raw_writel(RESETINT, REG_TISR); | ||
| 172 | timer0_load = (rate / TICKS_PER_SEC); | ||
| 173 | |||
| 174 | setup_irq(IRQ_TIMER0, &w90p910_timer0_irq); | ||
| 175 | |||
| 176 | w90p910_clocksource_init(rate); | ||
| 177 | w90p910_clockevents_init(rate); | ||
| 73 | } | 178 | } |
| 74 | 179 | ||
| 75 | struct sys_timer w90x900_timer = { | 180 | struct sys_timer w90x900_timer = { |
| 76 | .init = w90x900_timer_init, | 181 | .init = w90p910_timer_init, |
| 77 | .offset = w90x900_gettimeoffset, | ||
| 78 | .resume = w90x900_timer_setup | ||
| 79 | }; | 182 | }; |
diff --git a/arch/arm/mach-w90x900/w90p910.c b/arch/arm/mach-w90x900/w90p910.c index 8444eababaa..d33723b69d1 100644 --- a/arch/arm/mach-w90x900/w90p910.c +++ b/arch/arm/mach-w90x900/w90p910.c | |||
| @@ -76,6 +76,7 @@ static DEFINE_CLK(wdt, 26); | |||
| 76 | static DEFINE_CLK(gdma, 27); | 76 | static DEFINE_CLK(gdma, 27); |
| 77 | static DEFINE_CLK(adc, 28); | 77 | static DEFINE_CLK(adc, 28); |
| 78 | static DEFINE_CLK(usi, 29); | 78 | static DEFINE_CLK(usi, 29); |
| 79 | static DEFINE_CLK(ext, 0); | ||
| 79 | 80 | ||
| 80 | static struct clk_lookup w90p910_clkregs[] = { | 81 | static struct clk_lookup w90p910_clkregs[] = { |
| 81 | DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL), | 82 | DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL), |
| @@ -97,6 +98,7 @@ static struct clk_lookup w90p910_clkregs[] = { | |||
| 97 | DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL), | 98 | DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL), |
| 98 | DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL), | 99 | DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL), |
| 99 | DEF_CLKLOOK(&clk_usi, "w90p910-spi", NULL), | 100 | DEF_CLKLOOK(&clk_usi, "w90p910-spi", NULL), |
| 101 | DEF_CLKLOOK(&clk_ext, NULL, "ext"), | ||
| 100 | }; | 102 | }; |
| 101 | 103 | ||
| 102 | /* Initial serial platform data */ | 104 | /* Initial serial platform data */ |
