aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2014-11-20 11:13:55 -0500
committerArnd Bergmann <arnd@arndb.de>2014-11-20 11:13:55 -0500
commit4eca459bc10d8400407d0fc04e90dac45b571c87 (patch)
tree02dac5128653db41bc732c3649402b99d70d4c41
parentd686ce4204c5dc131396f1fca81beebc46cb8cdb (diff)
parentf956a785a282f6b5a3e7d59937548f8b7c04d1ac (diff)
Merge tag 'integrator-v3.19-arm-soc-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator into next/soc
Pull "ARM SoC Integrator updates for v3.19" from Linus Walleij: Integrator updates for the v3.19 merge cycle on top of the multiplatform patches, this moves out some drivers and reduced the amount of code carried in arch/arm/mach-integrator. - Move the Integrator/AP timer to drivers/clocksource - Move the restart functionality to the device tree, patches to enable restart for the Integrator have been merged to the reset tree (orthogonal) - Move debug LEDs to device tree (using the syscon LED driver merged for v3.18) - Move core module LEDs to device tree (using the syscon LED driver merged for v3.18) - Move the SoC driver (chip ID etc) to drivers/soc/versatile/soc-integrator.c * tag 'integrator-v3.19-arm-soc-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator: soc: move SoC driver for the ARM Integrator ARM: integrator: move core module LED to device tree ARM: integrator: move debug LEDs to syscon LED driver ARM: integrator: move restart to the device tree ARM: integrator: move AP timer to clocksource Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--arch/arm/boot/dts/integrator.dtsi48
-rw-r--r--arch/arm/mach-integrator/Kconfig5
-rw-r--r--arch/arm/mach-integrator/Makefile2
-rw-r--r--arch/arm/mach-integrator/cm.h1
-rw-r--r--arch/arm/mach-integrator/common.h2
-rw-r--r--arch/arm/mach-integrator/core.c103
-rw-r--r--arch/arm/mach-integrator/integrator_ap.c218
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c28
-rw-r--r--arch/arm/mach-integrator/leds.c124
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/timer-integrator-ap.c210
-rw-r--r--drivers/soc/versatile/Kconfig9
-rw-r--r--drivers/soc/versatile/Makefile1
-rw-r--r--drivers/soc/versatile/soc-integrator.c154
14 files changed, 428 insertions, 478 deletions
diff --git a/arch/arm/boot/dts/integrator.dtsi b/arch/arm/boot/dts/integrator.dtsi
index 88e3d477bf16..28e38f8c6b0f 100644
--- a/arch/arm/boot/dts/integrator.dtsi
+++ b/arch/arm/boot/dts/integrator.dtsi
@@ -6,8 +6,18 @@
6 6
7/ { 7/ {
8 core-module@10000000 { 8 core-module@10000000 {
9 compatible = "arm,core-module-integrator"; 9 compatible = "arm,core-module-integrator", "syscon";
10 reg = <0x10000000 0x200>; 10 reg = <0x10000000 0x200>;
11
12 /* Use core module LED to indicate CPU load */
13 led@0c.0 {
14 compatible = "register-bit-led";
15 offset = <0x0c>;
16 mask = <0x01>;
17 label = "integrator:core_module";
18 linux,default-trigger = "cpu0";
19 default-state = "on";
20 };
11 }; 21 };
12 22
13 ebi@12000000 { 23 ebi@12000000 {
@@ -82,5 +92,41 @@
82 reg = <0x19000000 0x1000>; 92 reg = <0x19000000 0x1000>;
83 interrupts = <4>; 93 interrupts = <4>;
84 }; 94 };
95
96 syscon {
97 /* Debug registers mapped as syscon */
98 compatible = "syscon";
99 reg = <0x1a000000 0x10>;
100
101 led@04.0 {
102 compatible = "register-bit-led";
103 offset = <0x04>;
104 mask = <0x01>;
105 label = "integrator:green0";
106 linux,default-trigger = "heartbeat";
107 default-state = "on";
108 };
109 led@04.1 {
110 compatible = "register-bit-led";
111 offset = <0x04>;
112 mask = <0x02>;
113 label = "integrator:yellow";
114 default-state = "off";
115 };
116 led@04.2 {
117 compatible = "register-bit-led";
118 offset = <0x04>;
119 mask = <0x04>;
120 label = "integrator:red";
121 default-state = "off";
122 };
123 led@04.3 {
124 compatible = "register-bit-led";
125 offset = <0x04>;
126 mask = <0x08>;
127 label = "integrator:green1";
128 default-state = "off";
129 };
130 };
85 }; 131 };
86}; 132};
diff --git a/arch/arm/mach-integrator/Kconfig b/arch/arm/mach-integrator/Kconfig
index aa7eb272e602..02d083489a26 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -8,8 +8,13 @@ config ARCH_INTEGRATOR
8 select GENERIC_CLOCKEVENTS 8 select GENERIC_CLOCKEVENTS
9 select HAVE_TCM 9 select HAVE_TCM
10 select ICST 10 select ICST
11 select MFD_SYSCON
11 select MULTI_IRQ_HANDLER 12 select MULTI_IRQ_HANDLER
12 select PLAT_VERSATILE 13 select PLAT_VERSATILE
14 select POWER_RESET
15 select POWER_RESET_VERSATILE
16 select POWER_SUPPLY
17 select SOC_INTEGRATOR_CM
13 select SPARSE_IRQ 18 select SPARSE_IRQ
14 select USE_OF 19 select USE_OF
15 select VERSATILE_FPGA_IRQ 20 select VERSATILE_FPGA_IRQ
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
index ec759ded7b60..1ebe45356b09 100644
--- a/arch/arm/mach-integrator/Makefile
+++ b/arch/arm/mach-integrator/Makefile
@@ -4,7 +4,7 @@
4 4
5# Object file lists. 5# Object file lists.
6 6
7obj-y := core.o lm.o leds.o 7obj-y := core.o lm.o
8obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o 8obj-$(CONFIG_ARCH_INTEGRATOR_AP) += integrator_ap.o
9obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o 9obj-$(CONFIG_ARCH_INTEGRATOR_CP) += integrator_cp.o
10 10
diff --git a/arch/arm/mach-integrator/cm.h b/arch/arm/mach-integrator/cm.h
index 4ecff7bff482..5b8ba8247f45 100644
--- a/arch/arm/mach-integrator/cm.h
+++ b/arch/arm/mach-integrator/cm.h
@@ -11,7 +11,6 @@ void cm_clear_irqs(void);
11#define CM_CTRL_LED (1 << 0) 11#define CM_CTRL_LED (1 << 0)
12#define CM_CTRL_nMBDET (1 << 1) 12#define CM_CTRL_nMBDET (1 << 1)
13#define CM_CTRL_REMAP (1 << 2) 13#define CM_CTRL_REMAP (1 << 2)
14#define CM_CTRL_RESET (1 << 3)
15 14
16/* 15/*
17 * Integrator/AP,PP2 specific 16 * Integrator/AP,PP2 specific
diff --git a/arch/arm/mach-integrator/common.h b/arch/arm/mach-integrator/common.h
index ad0ac5547b2c..96c9dc56cabf 100644
--- a/arch/arm/mach-integrator/common.h
+++ b/arch/arm/mach-integrator/common.h
@@ -4,5 +4,3 @@ extern struct amba_pl010_data ap_uart_data;
4void integrator_init_early(void); 4void integrator_init_early(void);
5int integrator_init(bool is_cp); 5int integrator_init(bool is_cp);
6void integrator_reserve(void); 6void integrator_reserve(void);
7void integrator_restart(enum reboot_mode, const char *);
8void integrator_init_sysfs(struct device *parent, u32 id);
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index e3f3aca43efb..948872a419c1 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -60,40 +60,6 @@ void cm_control(u32 mask, u32 set)
60 raw_spin_unlock_irqrestore(&cm_lock, flags); 60 raw_spin_unlock_irqrestore(&cm_lock, flags);
61} 61}
62 62
63static const char *integrator_arch_str(u32 id)
64{
65 switch ((id >> 16) & 0xff) {
66 case 0x00:
67 return "ASB little-endian";
68 case 0x01:
69 return "AHB little-endian";
70 case 0x03:
71 return "AHB-Lite system bus, bi-endian";
72 case 0x04:
73 return "AHB";
74 case 0x08:
75 return "AHB system bus, ASB processor bus";
76 default:
77 return "Unknown";
78 }
79}
80
81static const char *integrator_fpga_str(u32 id)
82{
83 switch ((id >> 12) & 0xf) {
84 case 0x01:
85 return "XC4062";
86 case 0x02:
87 return "XC4085";
88 case 0x03:
89 return "XVC600";
90 case 0x04:
91 return "EPM7256AE (Altera PLD)";
92 default:
93 return "Unknown";
94 }
95}
96
97void cm_clear_irqs(void) 63void cm_clear_irqs(void)
98{ 64{
99 /* disable core module IRQs */ 65 /* disable core module IRQs */
@@ -109,7 +75,6 @@ static const struct of_device_id cm_match[] = {
109void cm_init(void) 75void cm_init(void)
110{ 76{
111 struct device_node *cm = of_find_matching_node(NULL, cm_match); 77 struct device_node *cm = of_find_matching_node(NULL, cm_match);
112 u32 val;
113 78
114 if (!cm) { 79 if (!cm) {
115 pr_crit("no core module node found in device tree\n"); 80 pr_crit("no core module node found in device tree\n");
@@ -121,13 +86,6 @@ void cm_init(void)
121 return; 86 return;
122 } 87 }
123 cm_clear_irqs(); 88 cm_clear_irqs();
124 val = readl(cm_base + INTEGRATOR_HDR_ID_OFFSET);
125 pr_info("Detected ARM core module:\n");
126 pr_info(" Manufacturer: %02x\n", (val >> 24));
127 pr_info(" Architecture: %s\n", integrator_arch_str(val));
128 pr_info(" FPGA: %s\n", integrator_fpga_str(val));
129 pr_info(" Build: %02x\n", (val >> 4) & 0xFF);
130 pr_info(" Rev: %c\n", ('A' + (val & 0x03)));
131} 89}
132 90
133/* 91/*
@@ -139,64 +97,3 @@ void __init integrator_reserve(void)
139{ 97{
140 memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); 98 memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
141} 99}
142
143/*
144 * To reset, we hit the on-board reset register in the system FPGA
145 */
146void integrator_restart(enum reboot_mode mode, const char *cmd)
147{
148 cm_control(CM_CTRL_RESET, CM_CTRL_RESET);
149}
150
151static u32 integrator_id;
152
153static ssize_t intcp_get_manf(struct device *dev,
154 struct device_attribute *attr,
155 char *buf)
156{
157 return sprintf(buf, "%02x\n", integrator_id >> 24);
158}
159
160static struct device_attribute intcp_manf_attr =
161 __ATTR(manufacturer, S_IRUGO, intcp_get_manf, NULL);
162
163static ssize_t intcp_get_arch(struct device *dev,
164 struct device_attribute *attr,
165 char *buf)
166{
167 return sprintf(buf, "%s\n", integrator_arch_str(integrator_id));
168}
169
170static struct device_attribute intcp_arch_attr =
171 __ATTR(architecture, S_IRUGO, intcp_get_arch, NULL);
172
173static ssize_t intcp_get_fpga(struct device *dev,
174 struct device_attribute *attr,
175 char *buf)
176{
177 return sprintf(buf, "%s\n", integrator_fpga_str(integrator_id));
178}
179
180static struct device_attribute intcp_fpga_attr =
181 __ATTR(fpga, S_IRUGO, intcp_get_fpga, NULL);
182
183static ssize_t intcp_get_build(struct device *dev,
184 struct device_attribute *attr,
185 char *buf)
186{
187 return sprintf(buf, "%02x\n", (integrator_id >> 4) & 0xFF);
188}
189
190static struct device_attribute intcp_build_attr =
191 __ATTR(build, S_IRUGO, intcp_get_build, NULL);
192
193
194
195void integrator_init_sysfs(struct device *parent, u32 id)
196{
197 integrator_id = id;
198 device_create_file(parent, &intcp_manf_attr);
199 device_create_file(parent, &intcp_arch_attr);
200 device_create_file(parent, &intcp_fpga_attr);
201 device_create_file(parent, &intcp_build_attr);
202}
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 8ca290b479b1..30003ba447a5 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -27,22 +27,15 @@
27#include <linux/syscore_ops.h> 27#include <linux/syscore_ops.h>
28#include <linux/amba/bus.h> 28#include <linux/amba/bus.h>
29#include <linux/amba/kmi.h> 29#include <linux/amba/kmi.h>
30#include <linux/clocksource.h>
31#include <linux/clockchips.h>
32#include <linux/interrupt.h>
33#include <linux/io.h> 30#include <linux/io.h>
34#include <linux/irqchip.h> 31#include <linux/irqchip.h>
35#include <linux/mtd/physmap.h> 32#include <linux/mtd/physmap.h>
36#include <linux/clk.h>
37#include <linux/platform_data/clk-integrator.h> 33#include <linux/platform_data/clk-integrator.h>
38#include <linux/of_irq.h> 34#include <linux/of_irq.h>
39#include <linux/of_address.h> 35#include <linux/of_address.h>
40#include <linux/of_platform.h> 36#include <linux/of_platform.h>
41#include <linux/stat.h> 37#include <linux/stat.h>
42#include <linux/sys_soc.h>
43#include <linux/termios.h> 38#include <linux/termios.h>
44#include <linux/sched_clock.h>
45#include <linux/clk-provider.h>
46 39
47#include <asm/hardware/arm_timer.h> 40#include <asm/hardware/arm_timer.h>
48#include <asm/setup.h> 41#include <asm/setup.h>
@@ -89,11 +82,6 @@ static void __iomem *ebi_base;
89 82
90static struct map_desc ap_io_desc[] __initdata __maybe_unused = { 83static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
91 { 84 {
92 .virtual = IO_ADDRESS(INTEGRATOR_CT_BASE),
93 .pfn = __phys_to_pfn(INTEGRATOR_CT_BASE),
94 .length = SZ_4K,
95 .type = MT_DEVICE
96 }, {
97 .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE), 85 .virtual = IO_ADDRESS(INTEGRATOR_IC_BASE),
98 .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE), 86 .pfn = __phys_to_pfn(INTEGRATOR_IC_BASE),
99 .length = SZ_4K, 87 .length = SZ_4K,
@@ -257,188 +245,10 @@ struct amba_pl010_data ap_uart_data = {
257 .set_mctrl = integrator_uart_set_mctrl, 245 .set_mctrl = integrator_uart_set_mctrl,
258}; 246};
259 247
260/*
261 * Where is the timer (VA)?
262 */
263#define TIMER0_VA_BASE __io_address(INTEGRATOR_TIMER0_BASE)
264#define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
265#define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
266
267static unsigned long timer_reload;
268
269static u64 notrace integrator_read_sched_clock(void)
270{
271 return -readl((void __iomem *) TIMER2_VA_BASE + TIMER_VALUE);
272}
273
274static void integrator_clocksource_init(unsigned long inrate,
275 void __iomem *base)
276{
277 u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
278 unsigned long rate = inrate;
279
280 if (rate >= 1500000) {
281 rate /= 16;
282 ctrl |= TIMER_CTRL_DIV16;
283 }
284
285 writel(0xffff, base + TIMER_LOAD);
286 writel(ctrl, base + TIMER_CTRL);
287
288 clocksource_mmio_init(base + TIMER_VALUE, "timer2",
289 rate, 200, 16, clocksource_mmio_readl_down);
290 sched_clock_register(integrator_read_sched_clock, 16, rate);
291}
292
293static void __iomem * clkevt_base;
294
295/*
296 * IRQ handler for the timer
297 */
298static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
299{
300 struct clock_event_device *evt = dev_id;
301
302 /* clear the interrupt */
303 writel(1, clkevt_base + TIMER_INTCLR);
304
305 evt->event_handler(evt);
306
307 return IRQ_HANDLED;
308}
309
310static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
311{
312 u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
313
314 /* Disable timer */
315 writel(ctrl, clkevt_base + TIMER_CTRL);
316
317 switch (mode) {
318 case CLOCK_EVT_MODE_PERIODIC:
319 /* Enable the timer and start the periodic tick */
320 writel(timer_reload, clkevt_base + TIMER_LOAD);
321 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
322 writel(ctrl, clkevt_base + TIMER_CTRL);
323 break;
324 case CLOCK_EVT_MODE_ONESHOT:
325 /* Leave the timer disabled, .set_next_event will enable it */
326 ctrl &= ~TIMER_CTRL_PERIODIC;
327 writel(ctrl, clkevt_base + TIMER_CTRL);
328 break;
329 case CLOCK_EVT_MODE_UNUSED:
330 case CLOCK_EVT_MODE_SHUTDOWN:
331 case CLOCK_EVT_MODE_RESUME:
332 default:
333 /* Just leave in disabled state */
334 break;
335 }
336
337}
338
339static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
340{
341 unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
342
343 writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
344 writel(next, clkevt_base + TIMER_LOAD);
345 writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
346
347 return 0;
348}
349
350static struct clock_event_device integrator_clockevent = {
351 .name = "timer1",
352 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
353 .set_mode = clkevt_set_mode,
354 .set_next_event = clkevt_set_next_event,
355 .rating = 300,
356};
357
358static struct irqaction integrator_timer_irq = {
359 .name = "timer",
360 .flags = IRQF_TIMER | IRQF_IRQPOLL,
361 .handler = integrator_timer_interrupt,
362 .dev_id = &integrator_clockevent,
363};
364
365static void integrator_clockevent_init(unsigned long inrate,
366 void __iomem *base, int irq)
367{
368 unsigned long rate = inrate;
369 unsigned int ctrl = 0;
370
371 clkevt_base = base;
372 /* Calculate and program a divisor */
373 if (rate > 0x100000 * HZ) {
374 rate /= 256;
375 ctrl |= TIMER_CTRL_DIV256;
376 } else if (rate > 0x10000 * HZ) {
377 rate /= 16;
378 ctrl |= TIMER_CTRL_DIV16;
379 }
380 timer_reload = rate / HZ;
381 writel(ctrl, clkevt_base + TIMER_CTRL);
382
383 setup_irq(irq, &integrator_timer_irq);
384 clockevents_config_and_register(&integrator_clockevent,
385 rate,
386 1,
387 0xffffU);
388}
389
390void __init ap_init_early(void) 248void __init ap_init_early(void)
391{ 249{
392} 250}
393 251
394static void __init ap_of_timer_init(void)
395{
396 struct device_node *node;
397 const char *path;
398 void __iomem *base;
399 int err;
400 int irq;
401 struct clk *clk;
402 unsigned long rate;
403
404 of_clk_init(NULL);
405
406 err = of_property_read_string(of_aliases,
407 "arm,timer-primary", &path);
408 if (WARN_ON(err))
409 return;
410 node = of_find_node_by_path(path);
411 base = of_iomap(node, 0);
412 if (WARN_ON(!base))
413 return;
414
415 clk = of_clk_get(node, 0);
416 BUG_ON(IS_ERR(clk));
417 clk_prepare_enable(clk);
418 rate = clk_get_rate(clk);
419
420 writel(0, base + TIMER_CTRL);
421 integrator_clocksource_init(rate, base);
422
423 err = of_property_read_string(of_aliases,
424 "arm,timer-secondary", &path);
425 if (WARN_ON(err))
426 return;
427 node = of_find_node_by_path(path);
428 base = of_iomap(node, 0);
429 if (WARN_ON(!base))
430 return;
431 irq = irq_of_parse_and_map(node, 0);
432
433 clk = of_clk_get(node, 0);
434 BUG_ON(IS_ERR(clk));
435 clk_prepare_enable(clk);
436 rate = clk_get_rate(clk);
437
438 writel(0, base + TIMER_CTRL);
439 integrator_clockevent_init(rate, base, irq);
440}
441
442static void __init ap_init_irq_of(void) 252static void __init ap_init_irq_of(void)
443{ 253{
444 cm_init(); 254 cm_init();
@@ -477,10 +287,6 @@ static void __init ap_init_of(void)
477 unsigned long sc_dec; 287 unsigned long sc_dec;
478 struct device_node *syscon; 288 struct device_node *syscon;
479 struct device_node *ebi; 289 struct device_node *ebi;
480 struct device *parent;
481 struct soc_device *soc_dev;
482 struct soc_device_attribute *soc_dev_attr;
483 u32 ap_sc_id;
484 int i; 290 int i;
485 291
486 syscon = of_find_matching_node(NULL, ap_syscon_match); 292 syscon = of_find_matching_node(NULL, ap_syscon_match);
@@ -500,28 +306,6 @@ static void __init ap_init_of(void)
500 of_platform_populate(NULL, of_default_bus_match_table, 306 of_platform_populate(NULL, of_default_bus_match_table,
501 ap_auxdata_lookup, NULL); 307 ap_auxdata_lookup, NULL);
502 308
503 ap_sc_id = readl(ap_syscon_base);
504
505 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
506 if (!soc_dev_attr)
507 return;
508
509 soc_dev_attr->soc_id = "XVC";
510 soc_dev_attr->machine = "Integrator/AP";
511 soc_dev_attr->family = "Integrator";
512 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
513 'A' + (ap_sc_id & 0x0f));
514
515 soc_dev = soc_device_register(soc_dev_attr);
516 if (IS_ERR(soc_dev)) {
517 kfree(soc_dev_attr->revision);
518 kfree(soc_dev_attr);
519 return;
520 }
521
522 parent = soc_device_to_device(soc_dev);
523 integrator_init_sysfs(parent, ap_sc_id);
524
525 sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET); 309 sc_dec = readl(ap_syscon_base + INTEGRATOR_SC_DEC_OFFSET);
526 for (i = 0; i < 4; i++) { 310 for (i = 0; i < 4; i++) {
527 struct lm_device *lmdev; 311 struct lm_device *lmdev;
@@ -553,8 +337,6 @@ DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
553 .map_io = ap_map_io, 337 .map_io = ap_map_io,
554 .init_early = ap_init_early, 338 .init_early = ap_init_early,
555 .init_irq = ap_init_irq_of, 339 .init_irq = ap_init_irq_of,
556 .init_time = ap_of_timer_init,
557 .init_machine = ap_init_of, 340 .init_machine = ap_init_of,
558 .restart = integrator_restart,
559 .dt_compat = ap_dt_board_compat, 341 .dt_compat = ap_dt_board_compat,
560MACHINE_END 342MACHINE_END
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index cca02eb75eb5..b5fb71a36ee6 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -27,7 +27,6 @@
27#include <linux/of_irq.h> 27#include <linux/of_irq.h>
28#include <linux/of_address.h> 28#include <linux/of_address.h>
29#include <linux/of_platform.h> 29#include <linux/of_platform.h>
30#include <linux/sys_soc.h>
31#include <linux/sched_clock.h> 30#include <linux/sched_clock.h>
32 31
33#include <asm/setup.h> 32#include <asm/setup.h>
@@ -274,10 +273,6 @@ static const struct of_device_id intcp_syscon_match[] = {
274static void __init intcp_init_of(void) 273static void __init intcp_init_of(void)
275{ 274{
276 struct device_node *cpcon; 275 struct device_node *cpcon;
277 struct device *parent;
278 struct soc_device *soc_dev;
279 struct soc_device_attribute *soc_dev_attr;
280 u32 intcp_sc_id;
281 276
282 cpcon = of_find_matching_node(NULL, intcp_syscon_match); 277 cpcon = of_find_matching_node(NULL, intcp_syscon_match);
283 if (!cpcon) 278 if (!cpcon)
@@ -289,28 +284,6 @@ static void __init intcp_init_of(void)
289 284
290 of_platform_populate(NULL, of_default_bus_match_table, 285 of_platform_populate(NULL, of_default_bus_match_table,
291 intcp_auxdata_lookup, NULL); 286 intcp_auxdata_lookup, NULL);
292
293 intcp_sc_id = readl(intcp_con_base);
294
295 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
296 if (!soc_dev_attr)
297 return;
298
299 soc_dev_attr->soc_id = "XCV";
300 soc_dev_attr->machine = "Integrator/CP";
301 soc_dev_attr->family = "Integrator";
302 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c",
303 'A' + (intcp_sc_id & 0x0f));
304
305 soc_dev = soc_device_register(soc_dev_attr);
306 if (IS_ERR(soc_dev)) {
307 kfree(soc_dev_attr->revision);
308 kfree(soc_dev_attr);
309 return;
310 }
311
312 parent = soc_device_to_device(soc_dev);
313 integrator_init_sysfs(parent, intcp_sc_id);
314} 287}
315 288
316static const char * intcp_dt_board_compat[] = { 289static const char * intcp_dt_board_compat[] = {
@@ -324,6 +297,5 @@ DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
324 .init_early = intcp_init_early, 297 .init_early = intcp_init_early,
325 .init_irq = intcp_init_irq_of, 298 .init_irq = intcp_init_irq_of,
326 .init_machine = intcp_init_of, 299 .init_machine = intcp_init_of,
327 .restart = integrator_restart,
328 .dt_compat = intcp_dt_board_compat, 300 .dt_compat = intcp_dt_board_compat,
329MACHINE_END 301MACHINE_END
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
deleted file mode 100644
index f1dcb57a59e2..000000000000
--- a/arch/arm/mach-integrator/leds.c
+++ /dev/null
@@ -1,124 +0,0 @@
1/*
2 * Driver for the 4 user LEDs found on the Integrator AP/CP baseboard
3 * Based on Versatile and RealView machine LED code
4 *
5 * License terms: GNU General Public License (GPL) version 2
6 * Author: Bryan Wu <bryan.wu@canonical.com>
7 */
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <linux/io.h>
11#include <linux/slab.h>
12#include <linux/leds.h>
13
14#include "hardware.h"
15#include "cm.h"
16
17#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS)
18
19#define ALPHA_REG __io_address(INTEGRATOR_DBG_BASE)
20#define LEDREG (__io_address(INTEGRATOR_DBG_BASE) + INTEGRATOR_DBG_LEDS_OFFSET)
21
22struct integrator_led {
23 struct led_classdev cdev;
24 u8 mask;
25};
26
27/*
28 * The triggers lines up below will only be used if the
29 * LED triggers are compiled in.
30 */
31static const struct {
32 const char *name;
33 const char *trigger;
34} integrator_leds[] = {
35 { "integrator:green0", "heartbeat", },
36 { "integrator:yellow", },
37 { "integrator:red", },
38 { "integrator:green1", },
39 { "integrator:core_module", "cpu0", },
40};
41
42static void integrator_led_set(struct led_classdev *cdev,
43 enum led_brightness b)
44{
45 struct integrator_led *led = container_of(cdev,
46 struct integrator_led, cdev);
47 u32 reg = __raw_readl(LEDREG);
48
49 if (b != LED_OFF)
50 reg |= led->mask;
51 else
52 reg &= ~led->mask;
53
54 while (__raw_readl(ALPHA_REG) & 1)
55 cpu_relax();
56
57 __raw_writel(reg, LEDREG);
58}
59
60static enum led_brightness integrator_led_get(struct led_classdev *cdev)
61{
62 struct integrator_led *led = container_of(cdev,
63 struct integrator_led, cdev);
64 u32 reg = __raw_readl(LEDREG);
65
66 return (reg & led->mask) ? LED_FULL : LED_OFF;
67}
68
69static void cm_led_set(struct led_classdev *cdev,
70 enum led_brightness b)
71{
72 if (b != LED_OFF)
73 cm_control(CM_CTRL_LED, CM_CTRL_LED);
74 else
75 cm_control(CM_CTRL_LED, 0);
76}
77
78static enum led_brightness cm_led_get(struct led_classdev *cdev)
79{
80 u32 reg = cm_get();
81
82 return (reg & CM_CTRL_LED) ? LED_FULL : LED_OFF;
83}
84
85static int __init integrator_leds_init(void)
86{
87 int i;
88
89 for (i = 0; i < ARRAY_SIZE(integrator_leds); i++) {
90 struct integrator_led *led;
91
92 led = kzalloc(sizeof(*led), GFP_KERNEL);
93 if (!led)
94 break;
95
96
97 led->cdev.name = integrator_leds[i].name;
98
99 if (i == 4) { /* Setting for LED in core module */
100 led->cdev.brightness_set = cm_led_set;
101 led->cdev.brightness_get = cm_led_get;
102 } else {
103 led->cdev.brightness_set = integrator_led_set;
104 led->cdev.brightness_get = integrator_led_get;
105 }
106
107 led->cdev.default_trigger = integrator_leds[i].trigger;
108 led->mask = BIT(i);
109
110 if (led_classdev_register(NULL, &led->cdev) < 0) {
111 kfree(led);
112 break;
113 }
114 }
115
116 return 0;
117}
118
119/*
120 * Since we may have triggers on any subsystem, defer registration
121 * until after subsystem_init.
122 */
123fs_initcall(integrator_leds_init);
124#endif
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 756f6f10efa0..fae0435cc23d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -45,4 +45,5 @@ obj-$(CONFIG_ARM_GLOBAL_TIMER) += arm_global_timer.o
45obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o 45obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o
46obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o 46obj-$(CONFIG_ARCH_HAS_TICK_BROADCAST) += dummy_timer.o
47obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o 47obj-$(CONFIG_ARCH_KEYSTONE) += timer-keystone.o
48obj-$(CONFIG_ARCH_INTEGRATOR_AP) += timer-integrator-ap.o
48obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o 49obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
diff --git a/drivers/clocksource/timer-integrator-ap.c b/drivers/clocksource/timer-integrator-ap.c
new file mode 100644
index 000000000000..b9efd30513d5
--- /dev/null
+++ b/drivers/clocksource/timer-integrator-ap.c
@@ -0,0 +1,210 @@
1/*
2 * Integrator/AP timer driver
3 * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
4 * Copyright (c) 2014, Linaro Limited
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/clk.h>
22#include <linux/clocksource.h>
23#include <linux/of_irq.h>
24#include <linux/of_address.h>
25#include <linux/of_platform.h>
26#include <linux/clockchips.h>
27#include <linux/interrupt.h>
28#include <linux/sched_clock.h>
29#include <asm/hardware/arm_timer.h>
30
31static void __iomem * sched_clk_base;
32
33static u64 notrace integrator_read_sched_clock(void)
34{
35 return -readl(sched_clk_base + TIMER_VALUE);
36}
37
38static void integrator_clocksource_init(unsigned long inrate,
39 void __iomem *base)
40{
41 u32 ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
42 unsigned long rate = inrate;
43
44 if (rate >= 1500000) {
45 rate /= 16;
46 ctrl |= TIMER_CTRL_DIV16;
47 }
48
49 writel(0xffff, base + TIMER_LOAD);
50 writel(ctrl, base + TIMER_CTRL);
51
52 clocksource_mmio_init(base + TIMER_VALUE, "timer2",
53 rate, 200, 16, clocksource_mmio_readl_down);
54
55 sched_clk_base = base;
56 sched_clock_register(integrator_read_sched_clock, 16, rate);
57}
58
59static unsigned long timer_reload;
60static void __iomem * clkevt_base;
61
62/*
63 * IRQ handler for the timer
64 */
65static irqreturn_t integrator_timer_interrupt(int irq, void *dev_id)
66{
67 struct clock_event_device *evt = dev_id;
68
69 /* clear the interrupt */
70 writel(1, clkevt_base + TIMER_INTCLR);
71
72 evt->event_handler(evt);
73
74 return IRQ_HANDLED;
75}
76
77static void clkevt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt)
78{
79 u32 ctrl = readl(clkevt_base + TIMER_CTRL) & ~TIMER_CTRL_ENABLE;
80
81 /* Disable timer */
82 writel(ctrl, clkevt_base + TIMER_CTRL);
83
84 switch (mode) {
85 case CLOCK_EVT_MODE_PERIODIC:
86 /* Enable the timer and start the periodic tick */
87 writel(timer_reload, clkevt_base + TIMER_LOAD);
88 ctrl |= TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
89 writel(ctrl, clkevt_base + TIMER_CTRL);
90 break;
91 case CLOCK_EVT_MODE_ONESHOT:
92 /* Leave the timer disabled, .set_next_event will enable it */
93 ctrl &= ~TIMER_CTRL_PERIODIC;
94 writel(ctrl, clkevt_base + TIMER_CTRL);
95 break;
96 case CLOCK_EVT_MODE_UNUSED:
97 case CLOCK_EVT_MODE_SHUTDOWN:
98 case CLOCK_EVT_MODE_RESUME:
99 default:
100 /* Just leave in disabled state */
101 break;
102 }
103
104}
105
106static int clkevt_set_next_event(unsigned long next, struct clock_event_device *evt)
107{
108 unsigned long ctrl = readl(clkevt_base + TIMER_CTRL);
109
110 writel(ctrl & ~TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
111 writel(next, clkevt_base + TIMER_LOAD);
112 writel(ctrl | TIMER_CTRL_ENABLE, clkevt_base + TIMER_CTRL);
113
114 return 0;
115}
116
117static struct clock_event_device integrator_clockevent = {
118 .name = "timer1",
119 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
120 .set_mode = clkevt_set_mode,
121 .set_next_event = clkevt_set_next_event,
122 .rating = 300,
123};
124
125static struct irqaction integrator_timer_irq = {
126 .name = "timer",
127 .flags = IRQF_TIMER | IRQF_IRQPOLL,
128 .handler = integrator_timer_interrupt,
129 .dev_id = &integrator_clockevent,
130};
131
132static void integrator_clockevent_init(unsigned long inrate,
133 void __iomem *base, int irq)
134{
135 unsigned long rate = inrate;
136 unsigned int ctrl = 0;
137
138 clkevt_base = base;
139 /* Calculate and program a divisor */
140 if (rate > 0x100000 * HZ) {
141 rate /= 256;
142 ctrl |= TIMER_CTRL_DIV256;
143 } else if (rate > 0x10000 * HZ) {
144 rate /= 16;
145 ctrl |= TIMER_CTRL_DIV16;
146 }
147 timer_reload = rate / HZ;
148 writel(ctrl, clkevt_base + TIMER_CTRL);
149
150 setup_irq(irq, &integrator_timer_irq);
151 clockevents_config_and_register(&integrator_clockevent,
152 rate,
153 1,
154 0xffffU);
155}
156
157static void __init integrator_ap_timer_init_of(struct device_node *node)
158{
159 const char *path;
160 void __iomem *base;
161 int err;
162 int irq;
163 struct clk *clk;
164 unsigned long rate;
165 struct device_node *pri_node;
166 struct device_node *sec_node;
167
168 base = of_io_request_and_map(node, 0, "integrator-timer");
169 if (!base)
170 return;
171
172 clk = of_clk_get(node, 0);
173 if (IS_ERR(clk)) {
174 pr_err("No clock for %s\n", node->name);
175 return;
176 }
177 clk_prepare_enable(clk);
178 rate = clk_get_rate(clk);
179 writel(0, base + TIMER_CTRL);
180
181 err = of_property_read_string(of_aliases,
182 "arm,timer-primary", &path);
183 if (WARN_ON(err))
184 return;
185 pri_node = of_find_node_by_path(path);
186 err = of_property_read_string(of_aliases,
187 "arm,timer-secondary", &path);
188 if (WARN_ON(err))
189 return;
190 sec_node = of_find_node_by_path(path);
191
192 if (node == pri_node) {
193 /* The primary timer lacks IRQ, use as clocksource */
194 integrator_clocksource_init(rate, base);
195 return;
196 }
197
198 if (node == sec_node) {
199 /* The secondary timer will drive the clock event */
200 irq = irq_of_parse_and_map(node, 0);
201 integrator_clockevent_init(rate, base, irq);
202 return;
203 }
204
205 pr_info("Timer @%p unused\n", base);
206 clk_disable_unprepare(clk);
207}
208
209CLOCKSOURCE_OF_DECLARE(integrator_ap_timer, "arm,integrator-timer",
210 integrator_ap_timer_init_of);
diff --git a/drivers/soc/versatile/Kconfig b/drivers/soc/versatile/Kconfig
index bf5ee9c85330..a928a7fc6be4 100644
--- a/drivers/soc/versatile/Kconfig
+++ b/drivers/soc/versatile/Kconfig
@@ -1,6 +1,15 @@
1# 1#
2# ARM Versatile SoC drivers 2# ARM Versatile SoC drivers
3# 3#
4config SOC_INTEGRATOR_CM
5 bool "SoC bus device for the ARM Integrator platform core modules"
6 depends on ARCH_INTEGRATOR
7 select SOC_BUS
8 help
9 Include support for the SoC bus on the ARM Integrator platform
10 core modules providing some sysfs information about the ASIC
11 variant.
12
4config SOC_REALVIEW 13config SOC_REALVIEW
5 bool "SoC bus device for the ARM RealView platforms" 14 bool "SoC bus device for the ARM RealView platforms"
6 depends on ARCH_REALVIEW 15 depends on ARCH_REALVIEW
diff --git a/drivers/soc/versatile/Makefile b/drivers/soc/versatile/Makefile
index ad547435648e..cf612fe3a659 100644
--- a/drivers/soc/versatile/Makefile
+++ b/drivers/soc/versatile/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_SOC_INTEGRATOR_CM) += soc-integrator.o
1obj-$(CONFIG_SOC_REALVIEW) += soc-realview.o 2obj-$(CONFIG_SOC_REALVIEW) += soc-realview.o
diff --git a/drivers/soc/versatile/soc-integrator.c b/drivers/soc/versatile/soc-integrator.c
new file mode 100644
index 000000000000..ccaa53739ab4
--- /dev/null
+++ b/drivers/soc/versatile/soc-integrator.c
@@ -0,0 +1,154 @@
1/*
2 * Copyright (C) 2014 Linaro Ltd.
3 *
4 * Author: Linus Walleij <linus.walleij@linaro.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 */
11#include <linux/init.h>
12#include <linux/io.h>
13#include <linux/slab.h>
14#include <linux/sys_soc.h>
15#include <linux/platform_device.h>
16#include <linux/mfd/syscon.h>
17#include <linux/regmap.h>
18#include <linux/of.h>
19
20#define INTEGRATOR_HDR_ID_OFFSET 0x00
21
22static u32 integrator_coreid;
23
24static const struct of_device_id integrator_cm_match[] = {
25 { .compatible = "arm,core-module-integrator", },
26};
27
28static const char *integrator_arch_str(u32 id)
29{
30 switch ((id >> 16) & 0xff) {
31 case 0x00:
32 return "ASB little-endian";
33 case 0x01:
34 return "AHB little-endian";
35 case 0x03:
36 return "AHB-Lite system bus, bi-endian";
37 case 0x04:
38 return "AHB";
39 case 0x08:
40 return "AHB system bus, ASB processor bus";
41 default:
42 return "Unknown";
43 }
44}
45
46static const char *integrator_fpga_str(u32 id)
47{
48 switch ((id >> 12) & 0xf) {
49 case 0x01:
50 return "XC4062";
51 case 0x02:
52 return "XC4085";
53 case 0x03:
54 return "XVC600";
55 case 0x04:
56 return "EPM7256AE (Altera PLD)";
57 default:
58 return "Unknown";
59 }
60}
61
62static ssize_t integrator_get_manf(struct device *dev,
63 struct device_attribute *attr,
64 char *buf)
65{
66 return sprintf(buf, "%02x\n", integrator_coreid >> 24);
67}
68
69static struct device_attribute integrator_manf_attr =
70 __ATTR(manufacturer, S_IRUGO, integrator_get_manf, NULL);
71
72static ssize_t integrator_get_arch(struct device *dev,
73 struct device_attribute *attr,
74 char *buf)
75{
76 return sprintf(buf, "%s\n", integrator_arch_str(integrator_coreid));
77}
78
79static struct device_attribute integrator_arch_attr =
80 __ATTR(arch, S_IRUGO, integrator_get_arch, NULL);
81
82static ssize_t integrator_get_fpga(struct device *dev,
83 struct device_attribute *attr,
84 char *buf)
85{
86 return sprintf(buf, "%s\n", integrator_fpga_str(integrator_coreid));
87}
88
89static struct device_attribute integrator_fpga_attr =
90 __ATTR(fpga, S_IRUGO, integrator_get_fpga, NULL);
91
92static ssize_t integrator_get_build(struct device *dev,
93 struct device_attribute *attr,
94 char *buf)
95{
96 return sprintf(buf, "%02x\n", (integrator_coreid >> 4) & 0xFF);
97}
98
99static struct device_attribute integrator_build_attr =
100 __ATTR(build, S_IRUGO, integrator_get_build, NULL);
101
102static int __init integrator_soc_init(void)
103{
104 static struct regmap *syscon_regmap;
105 struct soc_device *soc_dev;
106 struct soc_device_attribute *soc_dev_attr;
107 struct device_node *np;
108 struct device *dev;
109 u32 val;
110 int ret;
111
112 np = of_find_matching_node(NULL, integrator_cm_match);
113 if (!np)
114 return -ENODEV;
115
116 syscon_regmap = syscon_node_to_regmap(np);
117 if (IS_ERR(syscon_regmap))
118 return PTR_ERR(syscon_regmap);
119
120 ret = regmap_read(syscon_regmap, INTEGRATOR_HDR_ID_OFFSET,
121 &val);
122 if (ret)
123 return -ENODEV;
124 integrator_coreid = val;
125
126 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
127 if (!soc_dev_attr)
128 return -ENOMEM;
129
130 soc_dev_attr->soc_id = "Integrator";
131 soc_dev_attr->machine = "Integrator";
132 soc_dev_attr->family = "Versatile";
133 soc_dev = soc_device_register(soc_dev_attr);
134 if (IS_ERR(soc_dev)) {
135 kfree(soc_dev_attr);
136 return -ENODEV;
137 }
138 dev = soc_device_to_device(soc_dev);
139
140 device_create_file(dev, &integrator_manf_attr);
141 device_create_file(dev, &integrator_arch_attr);
142 device_create_file(dev, &integrator_fpga_attr);
143 device_create_file(dev, &integrator_build_attr);
144
145 dev_info(dev, "Detected ARM core module:\n");
146 dev_info(dev, " Manufacturer: %02x\n", (val >> 24));
147 dev_info(dev, " Architecture: %s\n", integrator_arch_str(val));
148 dev_info(dev, " FPGA: %s\n", integrator_fpga_str(val));
149 dev_info(dev, " Build: %02x\n", (val >> 4) & 0xFF);
150 dev_info(dev, " Rev: %c\n", ('A' + (val & 0x03)));
151
152 return 0;
153}
154device_initcall(integrator_soc_init);