Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / arm / mach-integrator / integrator_cp.c
1 /*
2  *  linux/arch/arm/mach-integrator/integrator_cp.c
3  *
4  *  Copyright (C) 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 as published by
8  * the Free Software Foundation; either version 2 of the License.
9  */
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/list.h>
14 #include <linux/platform_device.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/string.h>
17 #include <linux/device.h>
18 #include <linux/amba/bus.h>
19 #include <linux/amba/kmi.h>
20 #include <linux/amba/clcd.h>
21 #include <linux/platform_data/video-clcd-versatile.h>
22 #include <linux/amba/mmci.h>
23 #include <linux/io.h>
24 #include <linux/irqchip.h>
25 #include <linux/gfp.h>
26 #include <linux/mtd/physmap.h>
27 #include <linux/of_irq.h>
28 #include <linux/of_address.h>
29 #include <linux/of_platform.h>
30 #include <linux/sched_clock.h>
31
32 #include <asm/setup.h>
33 #include <asm/mach-types.h>
34 #include <asm/mach/arch.h>
35 #include <asm/mach/irq.h>
36 #include <asm/mach/map.h>
37 #include <asm/mach/time.h>
38
39 #include "hardware.h"
40 #include "cm.h"
41 #include "common.h"
42
43 /* Base address to the CP controller */
44 static void __iomem *intcp_con_base;
45
46 #define INTCP_PA_FLASH_BASE             0x24000000
47
48 #define INTCP_PA_CLCD_BASE              0xc0000000
49
50 #define INTCP_FLASHPROG                 0x04
51 #define CINTEGRATOR_FLASHPROG_FLVPPEN   (1 << 0)
52 #define CINTEGRATOR_FLASHPROG_FLWREN    (1 << 1)
53
54 /*
55  * Logical      Physical
56  * f1000000     10000000        Core module registers
57  * f1300000     13000000        Counter/Timer
58  * f1400000     14000000        Interrupt controller
59  * f1600000     16000000        UART 0
60  * f1700000     17000000        UART 1
61  * f1a00000     1a000000        Debug LEDs
62  * fc900000     c9000000        GPIO
63  * fca00000     ca000000        SIC
64  */
65
66 static struct map_desc intcp_io_desc[] __initdata __maybe_unused = {
67         {
68                 .virtual        = IO_ADDRESS(INTEGRATOR_HDR_BASE),
69                 .pfn            = __phys_to_pfn(INTEGRATOR_HDR_BASE),
70                 .length         = SZ_4K,
71                 .type           = MT_DEVICE
72         }, {
73                 .virtual        = IO_ADDRESS(INTEGRATOR_CT_BASE),
74                 .pfn            = __phys_to_pfn(INTEGRATOR_CT_BASE),
75                 .length         = SZ_4K,
76                 .type           = MT_DEVICE
77         }, {
78                 .virtual        = IO_ADDRESS(INTEGRATOR_IC_BASE),
79                 .pfn            = __phys_to_pfn(INTEGRATOR_IC_BASE),
80                 .length         = SZ_4K,
81                 .type           = MT_DEVICE
82         }, {
83                 .virtual        = IO_ADDRESS(INTEGRATOR_UART0_BASE),
84                 .pfn            = __phys_to_pfn(INTEGRATOR_UART0_BASE),
85                 .length         = SZ_4K,
86                 .type           = MT_DEVICE
87         }, {
88                 .virtual        = IO_ADDRESS(INTEGRATOR_DBG_BASE),
89                 .pfn            = __phys_to_pfn(INTEGRATOR_DBG_BASE),
90                 .length         = SZ_4K,
91                 .type           = MT_DEVICE
92         }, {
93                 .virtual        = IO_ADDRESS(INTEGRATOR_CP_GPIO_BASE),
94                 .pfn            = __phys_to_pfn(INTEGRATOR_CP_GPIO_BASE),
95                 .length         = SZ_4K,
96                 .type           = MT_DEVICE
97         }, {
98                 .virtual        = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),
99                 .pfn            = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
100                 .length         = SZ_4K,
101                 .type           = MT_DEVICE
102         }
103 };
104
105 static void __init intcp_map_io(void)
106 {
107         iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
108 }
109
110 /*
111  * Flash handling.
112  */
113 static int intcp_flash_init(struct platform_device *dev)
114 {
115         u32 val;
116
117         val = readl(intcp_con_base + INTCP_FLASHPROG);
118         val |= CINTEGRATOR_FLASHPROG_FLWREN;
119         writel(val, intcp_con_base + INTCP_FLASHPROG);
120
121         return 0;
122 }
123
124 static void intcp_flash_exit(struct platform_device *dev)
125 {
126         u32 val;
127
128         val = readl(intcp_con_base + INTCP_FLASHPROG);
129         val &= ~(CINTEGRATOR_FLASHPROG_FLVPPEN|CINTEGRATOR_FLASHPROG_FLWREN);
130         writel(val, intcp_con_base + INTCP_FLASHPROG);
131 }
132
133 static void intcp_flash_set_vpp(struct platform_device *pdev, int on)
134 {
135         u32 val;
136
137         val = readl(intcp_con_base + INTCP_FLASHPROG);
138         if (on)
139                 val |= CINTEGRATOR_FLASHPROG_FLVPPEN;
140         else
141                 val &= ~CINTEGRATOR_FLASHPROG_FLVPPEN;
142         writel(val, intcp_con_base + INTCP_FLASHPROG);
143 }
144
145 static struct physmap_flash_data intcp_flash_data = {
146         .width          = 4,
147         .init           = intcp_flash_init,
148         .exit           = intcp_flash_exit,
149         .set_vpp        = intcp_flash_set_vpp,
150 };
151
152 /*
153  * It seems that the card insertion interrupt remains active after
154  * we've acknowledged it.  We therefore ignore the interrupt, and
155  * rely on reading it from the SIC.  This also means that we must
156  * clear the latched interrupt.
157  */
158 static unsigned int mmc_status(struct device *dev)
159 {
160         unsigned int status = readl(__io_address(0xca000000 + 4));
161         writel(8, intcp_con_base + 8);
162
163         return status & 8;
164 }
165
166 static struct mmci_platform_data mmc_data = {
167         .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
168         .status         = mmc_status,
169         .gpio_wp        = -1,
170         .gpio_cd        = -1,
171 };
172
173 /*
174  * CLCD support
175  */
176 /*
177  * Ensure VGA is selected.
178  */
179 static void cp_clcd_enable(struct clcd_fb *fb)
180 {
181         struct fb_var_screeninfo *var = &fb->fb.var;
182         u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2
183                         | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1;
184
185         if (var->bits_per_pixel <= 8 ||
186             (var->bits_per_pixel == 16 && var->green.length == 5))
187                 /* Pseudocolor, RGB555, BGR555 */
188                 val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555;
189         else if (fb->fb.var.bits_per_pixel <= 16)
190                 /* truecolor RGB565 */
191                 val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555;
192         else
193                 val = 0; /* no idea for this, don't trust the docs */
194
195         cm_control(CM_CTRL_LCDMUXSEL_MASK|
196                    CM_CTRL_LCDEN0|
197                    CM_CTRL_LCDEN1|
198                    CM_CTRL_STATIC1|
199                    CM_CTRL_STATIC2|
200                    CM_CTRL_STATIC|
201                    CM_CTRL_n24BITEN, val);
202 }
203
204 static int cp_clcd_setup(struct clcd_fb *fb)
205 {
206         fb->panel = versatile_clcd_get_panel("VGA");
207         if (!fb->panel)
208                 return -EINVAL;
209
210         return versatile_clcd_setup_dma(fb, SZ_1M);
211 }
212
213 static struct clcd_board clcd_data = {
214         .name           = "Integrator/CP",
215         .caps           = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888,
216         .check          = clcdfb_check,
217         .decode         = clcdfb_decode,
218         .enable         = cp_clcd_enable,
219         .setup          = cp_clcd_setup,
220         .mmap           = versatile_clcd_mmap_dma,
221         .remove         = versatile_clcd_remove_dma,
222 };
223
224 #define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
225
226 static u64 notrace intcp_read_sched_clock(void)
227 {
228         return readl(REFCOUNTER);
229 }
230
231 static void __init intcp_init_early(void)
232 {
233         sched_clock_register(intcp_read_sched_clock, 32, 24000000);
234 }
235
236 static void __init intcp_init_irq_of(void)
237 {
238         cm_init();
239         irqchip_init();
240 }
241
242 /*
243  * For the Device Tree, add in the UART, MMC and CLCD specifics as AUXDATA
244  * and enforce the bus names since these are used for clock lookups.
245  */
246 static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
247         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
248                 "rtc", NULL),
249         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
250                 "uart0", NULL),
251         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
252                 "uart1", NULL),
253         OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
254                 "kmi0", NULL),
255         OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
256                 "kmi1", NULL),
257         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_MMC_BASE,
258                 "mmci", &mmc_data),
259         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_AACI_BASE,
260                 "aaci", &mmc_data),
261         OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE,
262                 "clcd", &clcd_data),
263         OF_DEV_AUXDATA("cfi-flash", INTCP_PA_FLASH_BASE,
264                 "physmap-flash", &intcp_flash_data),
265         { /* sentinel */ },
266 };
267
268 static const struct of_device_id intcp_syscon_match[] = {
269         { .compatible = "arm,integrator-cp-syscon"},
270         { },
271 };
272
273 static void __init intcp_init_of(void)
274 {
275         struct device_node *cpcon;
276
277         cpcon = of_find_matching_node(NULL, intcp_syscon_match);
278         if (!cpcon)
279                 return;
280
281         intcp_con_base = of_iomap(cpcon, 0);
282         if (!intcp_con_base)
283                 return;
284
285         of_platform_populate(NULL, of_default_bus_match_table,
286                              intcp_auxdata_lookup, NULL);
287 }
288
289 static const char * intcp_dt_board_compat[] = {
290         "arm,integrator-cp",
291         NULL,
292 };
293
294 DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
295         .reserve        = integrator_reserve,
296         .map_io         = intcp_map_io,
297         .init_early     = intcp_init_early,
298         .init_irq       = intcp_init_irq_of,
299         .init_machine   = intcp_init_of,
300         .dt_compat      = intcp_dt_board_compat,
301 MACHINE_END