Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/arm/mach-integrator/core.c | |
3 | * | |
4 | * Copyright (C) 2000-2003 Deep Blue Solutions Ltd | |
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 | #include <linux/types.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/device.h> | |
b434f5c9 | 14 | #include <linux/export.h> |
1da177e4 LT |
15 | #include <linux/spinlock.h> |
16 | #include <linux/interrupt.h> | |
a03d4d27 | 17 | #include <linux/irq.h> |
8d717a52 | 18 | #include <linux/memblock.h> |
1da177e4 | 19 | #include <linux/sched.h> |
20cf33ea | 20 | #include <linux/smp.h> |
a62c80e5 | 21 | #include <linux/amba/bus.h> |
fbb18a27 | 22 | #include <linux/amba/serial.h> |
fced80c7 | 23 | #include <linux/io.h> |
e67ae6be | 24 | #include <linux/stat.h> |
1da177e4 | 25 | |
a09e64fb | 26 | #include <mach/hardware.h> |
a285edcf | 27 | #include <mach/platform.h> |
a09e64fb | 28 | #include <mach/cm.h> |
695436e3 LW |
29 | #include <mach/irqs.h> |
30 | ||
ee35887e | 31 | #include <asm/mach-types.h> |
1da177e4 | 32 | #include <asm/mach/time.h> |
98c672cf | 33 | #include <asm/pgtable.h> |
1da177e4 | 34 | |
4672cddf LW |
35 | #include "common.h" |
36 | ||
37 | #ifdef CONFIG_ATAGS | |
fbb18a27 | 38 | |
2f64ccd9 RK |
39 | #define INTEGRATOR_RTC_IRQ { IRQ_RTCINT } |
40 | #define INTEGRATOR_UART0_IRQ { IRQ_UARTINT0 } | |
41 | #define INTEGRATOR_UART1_IRQ { IRQ_UARTINT1 } | |
42 | #define KMI0_IRQ { IRQ_KMIINT0 } | |
43 | #define KMI1_IRQ { IRQ_KMIINT1 } | |
1da177e4 | 44 | |
d59fdcfc | 45 | static AMBA_APB_DEVICE(rtc, "rtc", 0, |
2f64ccd9 | 46 | INTEGRATOR_RTC_BASE, INTEGRATOR_RTC_IRQ, NULL); |
1da177e4 | 47 | |
d59fdcfc | 48 | static AMBA_APB_DEVICE(uart0, "uart0", 0, |
379df279 | 49 | INTEGRATOR_UART0_BASE, INTEGRATOR_UART0_IRQ, NULL); |
1da177e4 | 50 | |
d59fdcfc | 51 | static AMBA_APB_DEVICE(uart1, "uart1", 0, |
379df279 | 52 | INTEGRATOR_UART1_BASE, INTEGRATOR_UART1_IRQ, NULL); |
1da177e4 | 53 | |
d59fdcfc LW |
54 | static AMBA_APB_DEVICE(kmi0, "kmi0", 0, KMI0_BASE, KMI0_IRQ, NULL); |
55 | static AMBA_APB_DEVICE(kmi1, "kmi1", 0, KMI1_BASE, KMI1_IRQ, NULL); | |
1da177e4 LT |
56 | |
57 | static struct amba_device *amba_devs[] __initdata = { | |
58 | &rtc_device, | |
59 | &uart0_device, | |
60 | &uart1_device, | |
61 | &kmi0_device, | |
62 | &kmi1_device, | |
63 | }; | |
64 | ||
9bf26a18 | 65 | int __init integrator_init(bool is_cp) |
1da177e4 LT |
66 | { |
67 | int i; | |
68 | ||
ee35887e LW |
69 | /* |
70 | * The Integrator/AP lacks necessary AMBA PrimeCell IDs, so we need to | |
71 | * hard-code them. The Integator/CP and forward have proper cell IDs. | |
72 | * Else we leave them undefined to the bus driver can autoprobe them. | |
73 | */ | |
a02e0a83 | 74 | if (!is_cp && IS_ENABLED(CONFIG_ARCH_INTEGRATOR_AP)) { |
ee35887e LW |
75 | rtc_device.periphid = 0x00041030; |
76 | uart0_device.periphid = 0x00041010; | |
77 | uart1_device.periphid = 0x00041010; | |
78 | kmi0_device.periphid = 0x00041050; | |
79 | kmi1_device.periphid = 0x00041050; | |
379df279 LW |
80 | uart0_device.dev.platform_data = &ap_uart_data; |
81 | uart1_device.dev.platform_data = &ap_uart_data; | |
ee35887e LW |
82 | } |
83 | ||
1da177e4 LT |
84 | for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { |
85 | struct amba_device *d = amba_devs[i]; | |
86 | amba_device_register(d, &iomem_resource); | |
87 | } | |
88 | ||
89 | return 0; | |
90 | } | |
91 | ||
4672cddf | 92 | #endif |
1da177e4 | 93 | |
bd31b859 | 94 | static DEFINE_RAW_SPINLOCK(cm_lock); |
1da177e4 LT |
95 | |
96 | /** | |
97 | * cm_control - update the CM_CTRL register. | |
98 | * @mask: bits to change | |
99 | * @set: bits to set | |
100 | */ | |
101 | void cm_control(u32 mask, u32 set) | |
102 | { | |
103 | unsigned long flags; | |
104 | u32 val; | |
105 | ||
bd31b859 | 106 | raw_spin_lock_irqsave(&cm_lock, flags); |
1da177e4 LT |
107 | val = readl(CM_CTRL) & ~mask; |
108 | writel(val | set, CM_CTRL); | |
bd31b859 | 109 | raw_spin_unlock_irqrestore(&cm_lock, flags); |
1da177e4 LT |
110 | } |
111 | ||
112 | EXPORT_SYMBOL(cm_control); | |
98c672cf RK |
113 | |
114 | /* | |
115 | * We need to stop things allocating the low memory; ideally we need a | |
116 | * better implementation of GFP_DMA which does not assume that DMA-able | |
117 | * memory starts at zero. | |
118 | */ | |
119 | void __init integrator_reserve(void) | |
120 | { | |
8d717a52 | 121 | memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); |
98c672cf | 122 | } |
6338b66f RK |
123 | |
124 | /* | |
125 | * To reset, we hit the on-board reset register in the system FPGA | |
126 | */ | |
7b6d864b | 127 | void integrator_restart(enum reboot_mode mode, const char *cmd) |
6338b66f RK |
128 | { |
129 | cm_control(CM_CTRL_RESET, CM_CTRL_RESET); | |
130 | } | |
e67ae6be LW |
131 | |
132 | static u32 integrator_id; | |
133 | ||
134 | static ssize_t intcp_get_manf(struct device *dev, | |
135 | struct device_attribute *attr, | |
136 | char *buf) | |
137 | { | |
138 | return sprintf(buf, "%02x\n", integrator_id >> 24); | |
139 | } | |
140 | ||
141 | static struct device_attribute intcp_manf_attr = | |
142 | __ATTR(manufacturer, S_IRUGO, intcp_get_manf, NULL); | |
143 | ||
144 | static ssize_t intcp_get_arch(struct device *dev, | |
145 | struct device_attribute *attr, | |
146 | char *buf) | |
147 | { | |
148 | const char *arch; | |
149 | ||
150 | switch ((integrator_id >> 16) & 0xff) { | |
151 | case 0x00: | |
152 | arch = "ASB little-endian"; | |
153 | break; | |
154 | case 0x01: | |
155 | arch = "AHB little-endian"; | |
156 | break; | |
157 | case 0x03: | |
158 | arch = "AHB-Lite system bus, bi-endian"; | |
159 | break; | |
160 | case 0x04: | |
161 | arch = "AHB"; | |
162 | break; | |
163 | default: | |
164 | arch = "Unknown"; | |
165 | break; | |
166 | } | |
167 | ||
168 | return sprintf(buf, "%s\n", arch); | |
169 | } | |
170 | ||
171 | static struct device_attribute intcp_arch_attr = | |
172 | __ATTR(architecture, S_IRUGO, intcp_get_arch, NULL); | |
173 | ||
174 | static ssize_t intcp_get_fpga(struct device *dev, | |
175 | struct device_attribute *attr, | |
176 | char *buf) | |
177 | { | |
178 | const char *fpga; | |
179 | ||
180 | switch ((integrator_id >> 12) & 0xf) { | |
181 | case 0x01: | |
182 | fpga = "XC4062"; | |
183 | break; | |
184 | case 0x02: | |
185 | fpga = "XC4085"; | |
186 | break; | |
187 | case 0x04: | |
188 | fpga = "EPM7256AE (Altera PLD)"; | |
189 | break; | |
190 | default: | |
191 | fpga = "Unknown"; | |
192 | break; | |
193 | } | |
194 | ||
195 | return sprintf(buf, "%s\n", fpga); | |
196 | } | |
197 | ||
198 | static struct device_attribute intcp_fpga_attr = | |
199 | __ATTR(fpga, S_IRUGO, intcp_get_fpga, NULL); | |
200 | ||
201 | static ssize_t intcp_get_build(struct device *dev, | |
202 | struct device_attribute *attr, | |
203 | char *buf) | |
204 | { | |
205 | return sprintf(buf, "%02x\n", (integrator_id >> 4) & 0xFF); | |
206 | } | |
207 | ||
208 | static struct device_attribute intcp_build_attr = | |
209 | __ATTR(build, S_IRUGO, intcp_get_build, NULL); | |
210 | ||
211 | ||
212 | ||
213 | void integrator_init_sysfs(struct device *parent, u32 id) | |
214 | { | |
215 | integrator_id = id; | |
216 | device_create_file(parent, &intcp_manf_attr); | |
217 | device_create_file(parent, &intcp_arch_attr); | |
218 | device_create_file(parent, &intcp_fpga_attr); | |
219 | device_create_file(parent, &intcp_build_attr); | |
220 | } |