aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/sa1111.c8
-rw-r--r--arch/arm/common/timer-sp.c82
-rw-r--r--arch/arm/common/vic.c69
3 files changed, 76 insertions, 83 deletions
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index a12b33c0dc42..9c49a46a2b7a 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -185,14 +185,6 @@ static struct sa1111_dev_info sa1111_devices[] = {
185 }, 185 },
186}; 186};
187 187
188void __init sa1111_adjust_zones(unsigned long *size, unsigned long *holes)
189{
190 unsigned int sz = SZ_1M >> PAGE_SHIFT;
191
192 size[1] = size[0] - sz;
193 size[0] = sz;
194}
195
196/* 188/*
197 * SA1111 interrupt support. Since clearing an IRQ while there are 189 * SA1111 interrupt support. Since clearing an IRQ while there are
198 * active IRQs causes the interrupt output to pulse, the upper levels 190 * active IRQs causes the interrupt output to pulse, the upper levels
diff --git a/arch/arm/common/timer-sp.c b/arch/arm/common/timer-sp.c
index 6ef3342153b9..41df47875122 100644
--- a/arch/arm/common/timer-sp.c
+++ b/arch/arm/common/timer-sp.c
@@ -18,53 +18,67 @@
18 * along with this program; if not, write to the Free Software 18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21#include <linux/clk.h>
21#include <linux/clocksource.h> 22#include <linux/clocksource.h>
22#include <linux/clockchips.h> 23#include <linux/clockchips.h>
24#include <linux/err.h>
23#include <linux/interrupt.h> 25#include <linux/interrupt.h>
24#include <linux/irq.h> 26#include <linux/irq.h>
25#include <linux/io.h> 27#include <linux/io.h>
26 28
27#include <asm/hardware/arm_timer.h> 29#include <asm/hardware/arm_timer.h>
28 30
29/* 31static long __init sp804_get_clock_rate(const char *name)
30 * These timers are currently always setup to be clocked at 1MHz. 32{
31 */ 33 struct clk *clk;
32#define TIMER_FREQ_KHZ (1000) 34 long rate;
33#define TIMER_RELOAD (TIMER_FREQ_KHZ * 1000 / HZ) 35 int err;
36
37 clk = clk_get_sys("sp804", name);
38 if (IS_ERR(clk)) {
39 pr_err("sp804: %s clock not found: %d\n", name,
40 (int)PTR_ERR(clk));
41 return PTR_ERR(clk);
42 }
34 43
35static void __iomem *clksrc_base; 44 err = clk_enable(clk);
45 if (err) {
46 pr_err("sp804: %s clock failed to enable: %d\n", name, err);
47 clk_put(clk);
48 return err;
49 }
36 50
37static cycle_t sp804_read(struct clocksource *cs) 51 rate = clk_get_rate(clk);
38{ 52 if (rate < 0) {
39 return ~readl(clksrc_base + TIMER_VALUE); 53 pr_err("sp804: %s clock failed to get rate: %ld\n", name, rate);
40} 54 clk_disable(clk);
55 clk_put(clk);
56 }
41 57
42static struct clocksource clocksource_sp804 = { 58 return rate;
43 .name = "timer3", 59}
44 .rating = 200,
45 .read = sp804_read,
46 .mask = CLOCKSOURCE_MASK(32),
47 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
48};
49 60
50void __init sp804_clocksource_init(void __iomem *base) 61void __init sp804_clocksource_init(void __iomem *base, const char *name)
51{ 62{
52 struct clocksource *cs = &clocksource_sp804; 63 long rate = sp804_get_clock_rate(name);
53 64
54 clksrc_base = base; 65 if (rate < 0)
66 return;
55 67
56 /* setup timer 0 as free-running clocksource */ 68 /* setup timer 0 as free-running clocksource */
57 writel(0, clksrc_base + TIMER_CTRL); 69 writel(0, base + TIMER_CTRL);
58 writel(0xffffffff, clksrc_base + TIMER_LOAD); 70 writel(0xffffffff, base + TIMER_LOAD);
59 writel(0xffffffff, clksrc_base + TIMER_VALUE); 71 writel(0xffffffff, base + TIMER_VALUE);
60 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC, 72 writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
61 clksrc_base + TIMER_CTRL); 73 base + TIMER_CTRL);
62 74
63 clocksource_register_khz(cs, TIMER_FREQ_KHZ); 75 clocksource_mmio_init(base + TIMER_VALUE, name,
76 rate, 200, 32, clocksource_mmio_readl_down);
64} 77}
65 78
66 79
67static void __iomem *clkevt_base; 80static void __iomem *clkevt_base;
81static unsigned long clkevt_reload;
68 82
69/* 83/*
70 * IRQ handler for the timer 84 * IRQ handler for the timer
@@ -90,7 +104,7 @@ static void sp804_set_mode(enum clock_event_mode mode,
90 104
91 switch (mode) { 105 switch (mode) {
92 case CLOCK_EVT_MODE_PERIODIC: 106 case CLOCK_EVT_MODE_PERIODIC:
93 writel(TIMER_RELOAD, clkevt_base + TIMER_LOAD); 107 writel(clkevt_reload, clkevt_base + TIMER_LOAD);
94 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE; 108 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
95 break; 109 break;
96 110
@@ -120,7 +134,6 @@ static int sp804_set_next_event(unsigned long next,
120} 134}
121 135
122static struct clock_event_device sp804_clockevent = { 136static struct clock_event_device sp804_clockevent = {
123 .name = "timer0",
124 .shift = 32, 137 .shift = 32,
125 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, 138 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
126 .set_mode = sp804_set_mode, 139 .set_mode = sp804_set_mode,
@@ -136,17 +149,24 @@ static struct irqaction sp804_timer_irq = {
136 .dev_id = &sp804_clockevent, 149 .dev_id = &sp804_clockevent,
137}; 150};
138 151
139void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq) 152void __init sp804_clockevents_init(void __iomem *base, unsigned int irq,
153 const char *name)
140{ 154{
141 struct clock_event_device *evt = &sp804_clockevent; 155 struct clock_event_device *evt = &sp804_clockevent;
156 long rate = sp804_get_clock_rate(name);
157
158 if (rate < 0)
159 return;
142 160
143 clkevt_base = base; 161 clkevt_base = base;
162 clkevt_reload = DIV_ROUND_CLOSEST(rate, HZ);
144 163
145 evt->irq = timer_irq; 164 evt->name = name;
146 evt->mult = div_sc(TIMER_FREQ_KHZ, NSEC_PER_MSEC, evt->shift); 165 evt->irq = irq;
166 evt->mult = div_sc(rate, NSEC_PER_SEC, evt->shift);
147 evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt); 167 evt->max_delta_ns = clockevent_delta2ns(0xffffffff, evt);
148 evt->min_delta_ns = clockevent_delta2ns(0xf, evt); 168 evt->min_delta_ns = clockevent_delta2ns(0xf, evt);
149 169
150 setup_irq(timer_irq, &sp804_timer_irq); 170 setup_irq(irq, &sp804_timer_irq);
151 clockevents_register_device(evt); 171 clockevents_register_device(evt);
152} 172}
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index 113085a77123..7aa4262ada7a 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -22,17 +22,16 @@
22#include <linux/init.h> 22#include <linux/init.h>
23#include <linux/list.h> 23#include <linux/list.h>
24#include <linux/io.h> 24#include <linux/io.h>
25#include <linux/sysdev.h> 25#include <linux/syscore_ops.h>
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/amba/bus.h> 27#include <linux/amba/bus.h>
28 28
29#include <asm/mach/irq.h> 29#include <asm/mach/irq.h>
30#include <asm/hardware/vic.h> 30#include <asm/hardware/vic.h>
31 31
32#if defined(CONFIG_PM) 32#ifdef CONFIG_PM
33/** 33/**
34 * struct vic_device - VIC PM device 34 * struct vic_device - VIC PM device
35 * @sysdev: The system device which is registered.
36 * @irq: The IRQ number for the base of the VIC. 35 * @irq: The IRQ number for the base of the VIC.
37 * @base: The register base for the VIC. 36 * @base: The register base for the VIC.
38 * @resume_sources: A bitmask of interrupts for resume. 37 * @resume_sources: A bitmask of interrupts for resume.
@@ -43,8 +42,6 @@
43 * @protect: Save for VIC_PROTECT. 42 * @protect: Save for VIC_PROTECT.
44 */ 43 */
45struct vic_device { 44struct vic_device {
46 struct sys_device sysdev;
47
48 void __iomem *base; 45 void __iomem *base;
49 int irq; 46 int irq;
50 u32 resume_sources; 47 u32 resume_sources;
@@ -59,11 +56,6 @@ struct vic_device {
59static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; 56static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];
60 57
61static int vic_id; 58static int vic_id;
62
63static inline struct vic_device *to_vic(struct sys_device *sys)
64{
65 return container_of(sys, struct vic_device, sysdev);
66}
67#endif /* CONFIG_PM */ 59#endif /* CONFIG_PM */
68 60
69/** 61/**
@@ -85,10 +77,9 @@ static void vic_init2(void __iomem *base)
85 writel(32, base + VIC_PL190_DEF_VECT_ADDR); 77 writel(32, base + VIC_PL190_DEF_VECT_ADDR);
86} 78}
87 79
88#if defined(CONFIG_PM) 80#ifdef CONFIG_PM
89static int vic_class_resume(struct sys_device *dev) 81static void resume_one_vic(struct vic_device *vic)
90{ 82{
91 struct vic_device *vic = to_vic(dev);
92 void __iomem *base = vic->base; 83 void __iomem *base = vic->base;
93 84
94 printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base); 85 printk(KERN_DEBUG "%s: resuming vic at %p\n", __func__, base);
@@ -107,13 +98,18 @@ static int vic_class_resume(struct sys_device *dev)
107 98
108 writel(vic->soft_int, base + VIC_INT_SOFT); 99 writel(vic->soft_int, base + VIC_INT_SOFT);
109 writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR); 100 writel(~vic->soft_int, base + VIC_INT_SOFT_CLEAR);
101}
110 102
111 return 0; 103static void vic_resume(void)
104{
105 int id;
106
107 for (id = vic_id - 1; id >= 0; id--)
108 resume_one_vic(vic_devices + id);
112} 109}
113 110
114static int vic_class_suspend(struct sys_device *dev, pm_message_t state) 111static void suspend_one_vic(struct vic_device *vic)
115{ 112{
116 struct vic_device *vic = to_vic(dev);
117 void __iomem *base = vic->base; 113 void __iomem *base = vic->base;
118 114
119 printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base); 115 printk(KERN_DEBUG "%s: suspending vic at %p\n", __func__, base);
@@ -128,14 +124,21 @@ static int vic_class_suspend(struct sys_device *dev, pm_message_t state)
128 124
129 writel(vic->resume_irqs, base + VIC_INT_ENABLE); 125 writel(vic->resume_irqs, base + VIC_INT_ENABLE);
130 writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR); 126 writel(~vic->resume_irqs, base + VIC_INT_ENABLE_CLEAR);
127}
128
129static int vic_suspend(void)
130{
131 int id;
132
133 for (id = 0; id < vic_id; id++)
134 suspend_one_vic(vic_devices + id);
131 135
132 return 0; 136 return 0;
133} 137}
134 138
135struct sysdev_class vic_class = { 139struct syscore_ops vic_syscore_ops = {
136 .name = "vic", 140 .suspend = vic_suspend,
137 .suspend = vic_class_suspend, 141 .resume = vic_resume,
138 .resume = vic_class_resume,
139}; 142};
140 143
141/** 144/**
@@ -147,30 +150,8 @@ struct sysdev_class vic_class = {
147*/ 150*/
148static int __init vic_pm_init(void) 151static int __init vic_pm_init(void)
149{ 152{
150 struct vic_device *dev = vic_devices; 153 if (vic_id > 0)
151 int err; 154 register_syscore_ops(&vic_syscore_ops);
152 int id;
153
154 if (vic_id == 0)
155 return 0;
156
157 err = sysdev_class_register(&vic_class);
158 if (err) {
159 printk(KERN_ERR "%s: cannot register class\n", __func__);
160 return err;
161 }
162
163 for (id = 0; id < vic_id; id++, dev++) {
164 dev->sysdev.id = id;
165 dev->sysdev.cls = &vic_class;
166
167 err = sysdev_register(&dev->sysdev);
168 if (err) {
169 printk(KERN_ERR "%s: failed to register device\n",
170 __func__);
171 return err;
172 }
173 }
174 155
175 return 0; 156 return 0;
176} 157}