diff options
Diffstat (limited to 'arch/arm/common')
-rw-r--r-- | arch/arm/common/sa1111.c | 8 | ||||
-rw-r--r-- | arch/arm/common/timer-sp.c | 82 | ||||
-rw-r--r-- | arch/arm/common/vic.c | 69 |
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 | ||
188 | void __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 | /* | 31 | static 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 | ||
35 | static 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 | ||
37 | static 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 | ||
42 | static 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 | ||
50 | void __init sp804_clocksource_init(void __iomem *base) | 61 | void __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 | ||
67 | static void __iomem *clkevt_base; | 80 | static void __iomem *clkevt_base; |
81 | static 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 | ||
122 | static struct clock_event_device sp804_clockevent = { | 136 | static 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 | ||
139 | void __init sp804_clockevents_init(void __iomem *base, unsigned int timer_irq) | 152 | void __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 | */ |
45 | struct vic_device { | 44 | struct 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 { | |||
59 | static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; | 56 | static struct vic_device vic_devices[CONFIG_ARM_VIC_NR]; |
60 | 57 | ||
61 | static int vic_id; | 58 | static int vic_id; |
62 | |||
63 | static 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 |
89 | static int vic_class_resume(struct sys_device *dev) | 81 | static 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; | 103 | static 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 | ||
114 | static int vic_class_suspend(struct sys_device *dev, pm_message_t state) | 111 | static 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 | |||
129 | static 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 | ||
135 | struct sysdev_class vic_class = { | 139 | struct 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 | */ |
148 | static int __init vic_pm_init(void) | 151 | static 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 | } |