Merge branch 'fix/intel' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[deliverable/linux.git] / arch / arm / mach-versatile / versatile_dt.c
1 /*
2 * Versatile board support using the device tree
3 *
4 * Copyright (C) 2010 Secret Lab Technologies Ltd.
5 * Copyright (C) 2009 Jeremy Kerr <jeremy.kerr@canonical.com>
6 * Copyright (C) 2004 ARM Limited
7 * Copyright (C) 2000 Deep Blue Solutions Ltd
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #include <linux/init.h>
25 #include <linux/io.h>
26 #include <linux/of.h>
27 #include <linux/of_address.h>
28 #include <linux/of_irq.h>
29 #include <linux/of_platform.h>
30 #include <linux/slab.h>
31 #include <linux/amba/bus.h>
32 #include <linux/amba/clcd.h>
33 #include <linux/platform_data/video-clcd-versatile.h>
34 #include <linux/amba/mmci.h>
35 #include <linux/mtd/physmap.h>
36 #include <asm/mach-types.h>
37 #include <asm/mach/arch.h>
38 #include <asm/mach/map.h>
39
40 /* macro to get at MMIO space when running virtually */
41 #define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
42 #define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n))
43
44 /*
45 * Memory definitions
46 */
47 #define VERSATILE_FLASH_BASE 0x34000000
48 #define VERSATILE_FLASH_SIZE SZ_64M
49
50 /*
51 * ------------------------------------------------------------------------
52 * Versatile Registers
53 * ------------------------------------------------------------------------
54 */
55 #define VERSATILE_SYS_LOCK_OFFSET 0x20
56 #define VERSATILE_SYS_RESETCTL_OFFSET 0x40
57 #define VERSATILE_SYS_PCICTL_OFFSET 0x44
58 #define VERSATILE_SYS_MCI_OFFSET 0x48
59 #define VERSATILE_SYS_FLASH_OFFSET 0x4C
60 #define VERSATILE_SYS_CLCD_OFFSET 0x50
61
62 /*
63 * VERSATILE_SYS_FLASH
64 */
65 #define VERSATILE_FLASHPROG_FLVPPEN (1 << 0) /* Enable writing to flash */
66
67 /*
68 * VERSATILE peripheral addresses
69 */
70 #define VERSATILE_MMCI0_BASE 0x10005000 /* MMC interface */
71 #define VERSATILE_MMCI1_BASE 0x1000B000 /* MMC Interface */
72 #define VERSATILE_CLCD_BASE 0x10120000 /* CLCD */
73 #define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */
74 #define VERSATILE_IB2_BASE 0x24000000 /* IB2 module */
75 #define VERSATILE_IB2_CTL_BASE (VERSATILE_IB2_BASE + 0x03000000)
76
77 /*
78 * System controller bit assignment
79 */
80 #define VERSATILE_REFCLK 0
81 #define VERSATILE_TIMCLK 1
82
83 #define VERSATILE_TIMER1_EnSel 15
84 #define VERSATILE_TIMER2_EnSel 17
85 #define VERSATILE_TIMER3_EnSel 19
86 #define VERSATILE_TIMER4_EnSel 21
87
88 static void __iomem *versatile_sys_base;
89 static void __iomem *versatile_ib2_ctrl;
90
91 static void versatile_flash_set_vpp(struct platform_device *pdev, int on)
92 {
93 u32 val;
94
95 val = readl(versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET);
96 if (on)
97 val |= VERSATILE_FLASHPROG_FLVPPEN;
98 else
99 val &= ~VERSATILE_FLASHPROG_FLVPPEN;
100 writel(val, versatile_sys_base + VERSATILE_SYS_FLASH_OFFSET);
101 }
102
103 static struct physmap_flash_data versatile_flash_data = {
104 .width = 4,
105 .set_vpp = versatile_flash_set_vpp,
106 };
107
108 static struct resource versatile_flash_resource = {
109 .start = VERSATILE_FLASH_BASE,
110 .end = VERSATILE_FLASH_BASE + VERSATILE_FLASH_SIZE - 1,
111 .flags = IORESOURCE_MEM,
112 };
113
114 struct platform_device versatile_flash_device = {
115 .name = "physmap-flash",
116 .id = 0,
117 .dev = {
118 .platform_data = &versatile_flash_data,
119 },
120 .num_resources = 1,
121 .resource = &versatile_flash_resource,
122 };
123
124 unsigned int mmc_status(struct device *dev)
125 {
126 struct amba_device *adev = container_of(dev, struct amba_device, dev);
127 u32 mask;
128
129 if (adev->res.start == VERSATILE_MMCI0_BASE)
130 mask = 1;
131 else
132 mask = 2;
133
134 return readl(versatile_sys_base + VERSATILE_SYS_MCI_OFFSET) & mask;
135 }
136
137 static struct mmci_platform_data mmc0_plat_data = {
138 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
139 .status = mmc_status,
140 .gpio_wp = -1,
141 .gpio_cd = -1,
142 };
143
144 static struct mmci_platform_data mmc1_plat_data = {
145 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
146 .status = mmc_status,
147 .gpio_wp = -1,
148 .gpio_cd = -1,
149 };
150
151 /*
152 * CLCD support.
153 */
154 #define SYS_CLCD_MODE_MASK (3 << 0)
155 #define SYS_CLCD_MODE_888 (0 << 0)
156 #define SYS_CLCD_MODE_5551 (1 << 0)
157 #define SYS_CLCD_MODE_565_RLSB (2 << 0)
158 #define SYS_CLCD_MODE_565_BLSB (3 << 0)
159 #define SYS_CLCD_NLCDIOON (1 << 2)
160 #define SYS_CLCD_VDDPOSSWITCH (1 << 3)
161 #define SYS_CLCD_PWR3V5SWITCH (1 << 4)
162 #define SYS_CLCD_ID_MASK (0x1f << 8)
163 #define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8)
164 #define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8)
165 #define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8)
166 #define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8)
167 #define SYS_CLCD_ID_VGA (0x1f << 8)
168
169 static bool is_sanyo_2_5_lcd;
170
171 /*
172 * Disable all display connectors on the interface module.
173 */
174 static void versatile_clcd_disable(struct clcd_fb *fb)
175 {
176 void __iomem *sys_clcd = versatile_sys_base + VERSATILE_SYS_CLCD_OFFSET;
177 u32 val;
178
179 val = readl(sys_clcd);
180 val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
181 writel(val, sys_clcd);
182
183 /*
184 * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off
185 */
186 if (of_machine_is_compatible("arm,versatile-ab") && is_sanyo_2_5_lcd) {
187 unsigned long ctrl;
188
189 ctrl = readl(versatile_ib2_ctrl);
190 ctrl &= ~0x01;
191 writel(ctrl, versatile_ib2_ctrl);
192 }
193 }
194
195 /*
196 * Enable the relevant connector on the interface module.
197 */
198 static void versatile_clcd_enable(struct clcd_fb *fb)
199 {
200 struct fb_var_screeninfo *var = &fb->fb.var;
201 void __iomem *sys_clcd = versatile_sys_base + VERSATILE_SYS_CLCD_OFFSET;
202 u32 val;
203
204 val = readl(sys_clcd);
205 val &= ~SYS_CLCD_MODE_MASK;
206
207 switch (var->green.length) {
208 case 5:
209 val |= SYS_CLCD_MODE_5551;
210 break;
211 case 6:
212 if (var->red.offset == 0)
213 val |= SYS_CLCD_MODE_565_RLSB;
214 else
215 val |= SYS_CLCD_MODE_565_BLSB;
216 break;
217 case 8:
218 val |= SYS_CLCD_MODE_888;
219 break;
220 }
221
222 /*
223 * Set the MUX
224 */
225 writel(val, sys_clcd);
226
227 /*
228 * And now enable the PSUs
229 */
230 val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH;
231 writel(val, sys_clcd);
232
233 /*
234 * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on
235 */
236 if (of_machine_is_compatible("arm,versatile-ab") && is_sanyo_2_5_lcd) {
237 unsigned long ctrl;
238
239 ctrl = readl(versatile_ib2_ctrl);
240 ctrl |= 0x01;
241 writel(ctrl, versatile_ib2_ctrl);
242 }
243 }
244
245 /*
246 * Detect which LCD panel is connected, and return the appropriate
247 * clcd_panel structure. Note: we do not have any information on
248 * the required timings for the 8.4in panel, so we presently assume
249 * VGA timings.
250 */
251 static int versatile_clcd_setup(struct clcd_fb *fb)
252 {
253 void __iomem *sys_clcd = versatile_sys_base + VERSATILE_SYS_CLCD_OFFSET;
254 const char *panel_name;
255 u32 val;
256
257 is_sanyo_2_5_lcd = false;
258
259 val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
260 if (val == SYS_CLCD_ID_SANYO_3_8)
261 panel_name = "Sanyo TM38QV67A02A";
262 else if (val == SYS_CLCD_ID_SANYO_2_5) {
263 panel_name = "Sanyo QVGA Portrait";
264 is_sanyo_2_5_lcd = true;
265 } else if (val == SYS_CLCD_ID_EPSON_2_2)
266 panel_name = "Epson L2F50113T00";
267 else if (val == SYS_CLCD_ID_VGA)
268 panel_name = "VGA";
269 else {
270 printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
271 val);
272 panel_name = "VGA";
273 }
274
275 fb->panel = versatile_clcd_get_panel(panel_name);
276 if (!fb->panel)
277 return -EINVAL;
278
279 return versatile_clcd_setup_dma(fb, SZ_1M);
280 }
281
282 static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs)
283 {
284 clcdfb_decode(fb, regs);
285
286 /* Always clear BGR for RGB565: we do the routing externally */
287 if (fb->fb.var.green.length == 6)
288 regs->cntl &= ~CNTL_BGR;
289 }
290
291 static struct clcd_board clcd_plat_data = {
292 .name = "Versatile",
293 .caps = CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
294 .check = clcdfb_check,
295 .decode = versatile_clcd_decode,
296 .disable = versatile_clcd_disable,
297 .enable = versatile_clcd_enable,
298 .setup = versatile_clcd_setup,
299 .mmap = versatile_clcd_mmap_dma,
300 .remove = versatile_clcd_remove_dma,
301 };
302
303 /*
304 * Lookup table for attaching a specific name and platform_data pointer to
305 * devices as they get created by of_platform_populate(). Ideally this table
306 * would not exist, but the current clock implementation depends on some devices
307 * having a specific name.
308 */
309 struct of_dev_auxdata versatile_auxdata_lookup[] __initdata = {
310 OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI0_BASE, "fpga:05", &mmc0_plat_data),
311 OF_DEV_AUXDATA("arm,primecell", VERSATILE_MMCI1_BASE, "fpga:0b", &mmc1_plat_data),
312 OF_DEV_AUXDATA("arm,primecell", VERSATILE_CLCD_BASE, "dev:20", &clcd_plat_data),
313 {}
314 };
315
316 static struct map_desc versatile_io_desc[] __initdata __maybe_unused = {
317 {
318 .virtual = IO_ADDRESS(VERSATILE_SCTL_BASE),
319 .pfn = __phys_to_pfn(VERSATILE_SCTL_BASE),
320 .length = SZ_4K * 9,
321 .type = MT_DEVICE
322 }
323 };
324
325 static void __init versatile_map_io(void)
326 {
327 debug_ll_io_init();
328 iotable_init(versatile_io_desc, ARRAY_SIZE(versatile_io_desc));
329 }
330
331 static void __init versatile_init_early(void)
332 {
333 u32 val;
334
335 /*
336 * set clock frequency:
337 * VERSATILE_REFCLK is 32KHz
338 * VERSATILE_TIMCLK is 1MHz
339 */
340 val = readl(__io_address(VERSATILE_SCTL_BASE));
341 writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
342 (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) |
343 (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
344 (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
345 __io_address(VERSATILE_SCTL_BASE));
346 }
347
348 static void versatile_restart(enum reboot_mode mode, const char *cmd)
349 {
350 u32 val;
351
352 val = readl(versatile_sys_base + VERSATILE_SYS_RESETCTL_OFFSET);
353 val |= 0x105;
354
355 writel(0xa05f, versatile_sys_base + VERSATILE_SYS_LOCK_OFFSET);
356 writel(val, versatile_sys_base + VERSATILE_SYS_RESETCTL_OFFSET);
357 writel(0, versatile_sys_base + VERSATILE_SYS_LOCK_OFFSET);
358 }
359
360 static void __init versatile_dt_pci_init(void)
361 {
362 u32 val;
363 struct device_node *np;
364 struct property *newprop;
365
366 np = of_find_compatible_node(NULL, NULL, "arm,versatile-pci");
367 if (!np)
368 return;
369
370 /* Check if PCI backplane is detected */
371 val = readl(versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET);
372 if (val & 1) {
373 /*
374 * Enable PCI accesses. Note that the documentaton is
375 * inconsistent whether or not this is needed, but the old
376 * driver had it so we will keep it.
377 */
378 writel(1, versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET);
379 return;
380 }
381
382 newprop = kzalloc(sizeof(*newprop), GFP_KERNEL);
383 if (!newprop)
384 return;
385
386 newprop->name = kstrdup("status", GFP_KERNEL);
387 newprop->value = kstrdup("disabled", GFP_KERNEL);
388 newprop->length = sizeof("disabled");
389 of_update_property(np, newprop);
390
391 pr_info("Not plugged into PCI backplane!\n");
392 }
393
394 static void __init versatile_dt_init(void)
395 {
396 struct device_node *np;
397
398 np = of_find_compatible_node(NULL, NULL, "arm,core-module-versatile");
399 if (np)
400 versatile_sys_base = of_iomap(np, 0);
401 WARN_ON(!versatile_sys_base);
402
403 versatile_ib2_ctrl = ioremap(VERSATILE_IB2_CTL_BASE, SZ_4K);
404
405 versatile_dt_pci_init();
406
407 platform_device_register(&versatile_flash_device);
408 of_platform_populate(NULL, of_default_bus_match_table,
409 versatile_auxdata_lookup, NULL);
410 }
411
412 static const char *const versatile_dt_match[] __initconst = {
413 "arm,versatile-ab",
414 "arm,versatile-pb",
415 NULL,
416 };
417
418 DT_MACHINE_START(VERSATILE_PB, "ARM-Versatile (Device Tree Support)")
419 .map_io = versatile_map_io,
420 .init_early = versatile_init_early,
421 .init_machine = versatile_dt_init,
422 .dt_compat = versatile_dt_match,
423 .restart = versatile_restart,
424 MACHINE_END
This page took 0.061753 seconds and 6 git commands to generate.