Merge remote-tracking branch 'asoc/fix/intel' into asoc-linus
[cascardo/linux.git] / 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/of_irq.h>
27 #include <linux/of_address.h>
28 #include <linux/of_platform.h>
29 #include <linux/sched_clock.h>
30
31 #include <asm/setup.h>
32 #include <asm/mach-types.h>
33 #include <asm/mach/arch.h>
34 #include <asm/mach/irq.h>
35 #include <asm/mach/map.h>
36 #include <asm/mach/time.h>
37
38 #include "hardware.h"
39 #include "cm.h"
40 #include "common.h"
41
42 /* Base address to the CP controller */
43 static void __iomem *intcp_con_base;
44
45 #define INTCP_PA_CLCD_BASE              0xc0000000
46
47 /*
48  * Logical      Physical
49  * f1000000     10000000        Core module registers
50  * f1300000     13000000        Counter/Timer
51  * f1400000     14000000        Interrupt controller
52  * f1600000     16000000        UART 0
53  * f1700000     17000000        UART 1
54  * f1a00000     1a000000        Debug LEDs
55  * fc900000     c9000000        GPIO
56  * fca00000     ca000000        SIC
57  */
58
59 static struct map_desc intcp_io_desc[] __initdata __maybe_unused = {
60         {
61                 .virtual        = IO_ADDRESS(INTEGRATOR_HDR_BASE),
62                 .pfn            = __phys_to_pfn(INTEGRATOR_HDR_BASE),
63                 .length         = SZ_4K,
64                 .type           = MT_DEVICE
65         }, {
66                 .virtual        = IO_ADDRESS(INTEGRATOR_CT_BASE),
67                 .pfn            = __phys_to_pfn(INTEGRATOR_CT_BASE),
68                 .length         = SZ_4K,
69                 .type           = MT_DEVICE
70         }, {
71                 .virtual        = IO_ADDRESS(INTEGRATOR_IC_BASE),
72                 .pfn            = __phys_to_pfn(INTEGRATOR_IC_BASE),
73                 .length         = SZ_4K,
74                 .type           = MT_DEVICE
75         }, {
76                 .virtual        = IO_ADDRESS(INTEGRATOR_UART0_BASE),
77                 .pfn            = __phys_to_pfn(INTEGRATOR_UART0_BASE),
78                 .length         = SZ_4K,
79                 .type           = MT_DEVICE
80         }, {
81                 .virtual        = IO_ADDRESS(INTEGRATOR_DBG_BASE),
82                 .pfn            = __phys_to_pfn(INTEGRATOR_DBG_BASE),
83                 .length         = SZ_4K,
84                 .type           = MT_DEVICE
85         }, {
86                 .virtual        = IO_ADDRESS(INTEGRATOR_CP_GPIO_BASE),
87                 .pfn            = __phys_to_pfn(INTEGRATOR_CP_GPIO_BASE),
88                 .length         = SZ_4K,
89                 .type           = MT_DEVICE
90         }, {
91                 .virtual        = IO_ADDRESS(INTEGRATOR_CP_SIC_BASE),
92                 .pfn            = __phys_to_pfn(INTEGRATOR_CP_SIC_BASE),
93                 .length         = SZ_4K,
94                 .type           = MT_DEVICE
95         }
96 };
97
98 static void __init intcp_map_io(void)
99 {
100         iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
101 }
102
103 /*
104  * It seems that the card insertion interrupt remains active after
105  * we've acknowledged it.  We therefore ignore the interrupt, and
106  * rely on reading it from the SIC.  This also means that we must
107  * clear the latched interrupt.
108  */
109 static unsigned int mmc_status(struct device *dev)
110 {
111         unsigned int status = readl(__io_address(0xca000000 + 4));
112         writel(8, intcp_con_base + 8);
113
114         return status & 8;
115 }
116
117 static struct mmci_platform_data mmc_data = {
118         .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
119         .status         = mmc_status,
120         .gpio_wp        = -1,
121         .gpio_cd        = -1,
122 };
123
124 /*
125  * CLCD support
126  */
127 /*
128  * Ensure VGA is selected.
129  */
130 static void cp_clcd_enable(struct clcd_fb *fb)
131 {
132         struct fb_var_screeninfo *var = &fb->fb.var;
133         u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2
134                         | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1;
135
136         if (var->bits_per_pixel <= 8 ||
137             (var->bits_per_pixel == 16 && var->green.length == 5))
138                 /* Pseudocolor, RGB555, BGR555 */
139                 val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555;
140         else if (fb->fb.var.bits_per_pixel <= 16)
141                 /* truecolor RGB565 */
142                 val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555;
143         else
144                 val = 0; /* no idea for this, don't trust the docs */
145
146         cm_control(CM_CTRL_LCDMUXSEL_MASK|
147                    CM_CTRL_LCDEN0|
148                    CM_CTRL_LCDEN1|
149                    CM_CTRL_STATIC1|
150                    CM_CTRL_STATIC2|
151                    CM_CTRL_STATIC|
152                    CM_CTRL_n24BITEN, val);
153 }
154
155 static int cp_clcd_setup(struct clcd_fb *fb)
156 {
157         fb->panel = versatile_clcd_get_panel("VGA");
158         if (!fb->panel)
159                 return -EINVAL;
160
161         return versatile_clcd_setup_dma(fb, SZ_1M);
162 }
163
164 static struct clcd_board clcd_data = {
165         .name           = "Integrator/CP",
166         .caps           = CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888,
167         .check          = clcdfb_check,
168         .decode         = clcdfb_decode,
169         .enable         = cp_clcd_enable,
170         .setup          = cp_clcd_setup,
171         .mmap           = versatile_clcd_mmap_dma,
172         .remove         = versatile_clcd_remove_dma,
173 };
174
175 #define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
176
177 static u64 notrace intcp_read_sched_clock(void)
178 {
179         return readl(REFCOUNTER);
180 }
181
182 static void __init intcp_init_early(void)
183 {
184         sched_clock_register(intcp_read_sched_clock, 32, 24000000);
185 }
186
187 static void __init intcp_init_irq_of(void)
188 {
189         cm_init();
190         irqchip_init();
191 }
192
193 /*
194  * For the Device Tree, add in the UART, MMC and CLCD specifics as AUXDATA
195  * and enforce the bus names since these are used for clock lookups.
196  */
197 static struct of_dev_auxdata intcp_auxdata_lookup[] __initdata = {
198         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_RTC_BASE,
199                 "rtc", NULL),
200         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
201                 "uart0", NULL),
202         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
203                 "uart1", NULL),
204         OF_DEV_AUXDATA("arm,primecell", KMI0_BASE,
205                 "kmi0", NULL),
206         OF_DEV_AUXDATA("arm,primecell", KMI1_BASE,
207                 "kmi1", NULL),
208         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_MMC_BASE,
209                 "mmci", &mmc_data),
210         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_CP_AACI_BASE,
211                 "aaci", &mmc_data),
212         OF_DEV_AUXDATA("arm,primecell", INTCP_PA_CLCD_BASE,
213                 "clcd", &clcd_data),
214         { /* sentinel */ },
215 };
216
217 static const struct of_device_id intcp_syscon_match[] = {
218         { .compatible = "arm,integrator-cp-syscon"},
219         { },
220 };
221
222 static void __init intcp_init_of(void)
223 {
224         struct device_node *cpcon;
225
226         cpcon = of_find_matching_node(NULL, intcp_syscon_match);
227         if (!cpcon)
228                 return;
229
230         intcp_con_base = of_iomap(cpcon, 0);
231         if (!intcp_con_base)
232                 return;
233
234         of_platform_default_populate(NULL, intcp_auxdata_lookup, NULL);
235 }
236
237 static const char * intcp_dt_board_compat[] = {
238         "arm,integrator-cp",
239         NULL,
240 };
241
242 DT_MACHINE_START(INTEGRATOR_CP_DT, "ARM Integrator/CP (Device Tree)")
243         .reserve        = integrator_reserve,
244         .map_io         = intcp_map_io,
245         .init_early     = intcp_init_early,
246         .init_irq       = intcp_init_irq_of,
247         .init_machine   = intcp_init_of,
248         .dt_compat      = intcp_dt_board_compat,
249 MACHINE_END