1/*
2 * linux/arch/arm/mach-omap2/io.c
3 *
4 * OMAP2 I/O mapping code
5 *
6 * Copyright (C) 2005 Nokia Corporation
7 * Copyright (C) 2007-2009 Texas Instruments
8 *
9 * Author:
10 *	Juha Yrjola <juha.yrjola@nokia.com>
11 *	Syed Khasim <x0khasim@ti.com>
12 *
13 * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
18 */
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/init.h>
22#include <linux/io.h>
23#include <linux/clk.h>
24
25#include <asm/tlb.h>
26#include <asm/mach/map.h>
27
28#include <plat/sram.h>
29#include <plat/sdrc.h>
30#include <plat/serial.h>
31#include <plat/omap-pm.h>
32#include <plat/omap_hwmod.h>
33#include <plat/multi.h>
34
35#include "iomap.h"
36#include "voltage.h"
37#include "powerdomain.h"
38#include "clockdomain.h"
39#include "common.h"
40#include "clock2xxx.h"
41#include "clock3xxx.h"
42#include "clock44xx.h"
43
44/*
45 * The machine specific code may provide the extra mapping besides the
46 * default mapping provided here.
47 */
48
49#if defined(CONFIG_SOC_OMAP2420) || defined(CONFIG_SOC_OMAP2430)
50static struct map_desc omap24xx_io_desc[] __initdata = {
51	{
52		.virtual	= L3_24XX_VIRT,
53		.pfn		= __phys_to_pfn(L3_24XX_PHYS),
54		.length		= L3_24XX_SIZE,
55		.type		= MT_DEVICE
56	},
57	{
58		.virtual	= L4_24XX_VIRT,
59		.pfn		= __phys_to_pfn(L4_24XX_PHYS),
60		.length		= L4_24XX_SIZE,
61		.type		= MT_DEVICE
62	},
63};
64
65#ifdef CONFIG_SOC_OMAP2420
66static struct map_desc omap242x_io_desc[] __initdata = {
67	{
68		.virtual	= DSP_MEM_2420_VIRT,
69		.pfn		= __phys_to_pfn(DSP_MEM_2420_PHYS),
70		.length		= DSP_MEM_2420_SIZE,
71		.type		= MT_DEVICE
72	},
73	{
74		.virtual	= DSP_IPI_2420_VIRT,
75		.pfn		= __phys_to_pfn(DSP_IPI_2420_PHYS),
76		.length		= DSP_IPI_2420_SIZE,
77		.type		= MT_DEVICE
78	},
79	{
80		.virtual	= DSP_MMU_2420_VIRT,
81		.pfn		= __phys_to_pfn(DSP_MMU_2420_PHYS),
82		.length		= DSP_MMU_2420_SIZE,
83		.type		= MT_DEVICE
84	},
85};
86
87#endif
88
89#ifdef CONFIG_SOC_OMAP2430
90static struct map_desc omap243x_io_desc[] __initdata = {
91	{
92		.virtual	= L4_WK_243X_VIRT,
93		.pfn		= __phys_to_pfn(L4_WK_243X_PHYS),
94		.length		= L4_WK_243X_SIZE,
95		.type		= MT_DEVICE
96	},
97	{
98		.virtual	= OMAP243X_GPMC_VIRT,
99		.pfn		= __phys_to_pfn(OMAP243X_GPMC_PHYS),
100		.length		= OMAP243X_GPMC_SIZE,
101		.type		= MT_DEVICE
102	},
103	{
104		.virtual	= OMAP243X_SDRC_VIRT,
105		.pfn		= __phys_to_pfn(OMAP243X_SDRC_PHYS),
106		.length		= OMAP243X_SDRC_SIZE,
107		.type		= MT_DEVICE
108	},
109	{
110		.virtual	= OMAP243X_SMS_VIRT,
111		.pfn		= __phys_to_pfn(OMAP243X_SMS_PHYS),
112		.length		= OMAP243X_SMS_SIZE,
113		.type		= MT_DEVICE
114	},
115};
116#endif
117#endif
118
119#ifdef	CONFIG_ARCH_OMAP3
120static struct map_desc omap34xx_io_desc[] __initdata = {
121	{
122		.virtual	= L3_34XX_VIRT,
123		.pfn		= __phys_to_pfn(L3_34XX_PHYS),
124		.length		= L3_34XX_SIZE,
125		.type		= MT_DEVICE
126	},
127	{
128		.virtual	= L4_34XX_VIRT,
129		.pfn		= __phys_to_pfn(L4_34XX_PHYS),
130		.length		= L4_34XX_SIZE,
131		.type		= MT_DEVICE
132	},
133	{
134		.virtual	= OMAP34XX_GPMC_VIRT,
135		.pfn		= __phys_to_pfn(OMAP34XX_GPMC_PHYS),
136		.length		= OMAP34XX_GPMC_SIZE,
137		.type		= MT_DEVICE
138	},
139	{
140		.virtual	= OMAP343X_SMS_VIRT,
141		.pfn		= __phys_to_pfn(OMAP343X_SMS_PHYS),
142		.length		= OMAP343X_SMS_SIZE,
143		.type		= MT_DEVICE
144	},
145	{
146		.virtual	= OMAP343X_SDRC_VIRT,
147		.pfn		= __phys_to_pfn(OMAP343X_SDRC_PHYS),
148		.length		= OMAP343X_SDRC_SIZE,
149		.type		= MT_DEVICE
150	},
151	{
152		.virtual	= L4_PER_34XX_VIRT,
153		.pfn		= __phys_to_pfn(L4_PER_34XX_PHYS),
154		.length		= L4_PER_34XX_SIZE,
155		.type		= MT_DEVICE
156	},
157	{
158		.virtual	= L4_EMU_34XX_VIRT,
159		.pfn		= __phys_to_pfn(L4_EMU_34XX_PHYS),
160		.length		= L4_EMU_34XX_SIZE,
161		.type		= MT_DEVICE
162	},
163#if defined(CONFIG_DEBUG_LL) &&							\
164	(defined(CONFIG_MACH_OMAP_ZOOM2) || defined(CONFIG_MACH_OMAP_ZOOM3))
165	{
166		.virtual	= ZOOM_UART_VIRT,
167		.pfn		= __phys_to_pfn(ZOOM_UART_BASE),
168		.length		= SZ_1M,
169		.type		= MT_DEVICE
170	},
171#endif
172};
173#endif
174
175#ifdef CONFIG_SOC_OMAPTI81XX
176static struct map_desc omapti81xx_io_desc[] __initdata = {
177	{
178		.virtual	= L4_34XX_VIRT,
179		.pfn		= __phys_to_pfn(L4_34XX_PHYS),
180		.length		= L4_34XX_SIZE,
181		.type		= MT_DEVICE
182	}
183};
184#endif
185
186#ifdef CONFIG_SOC_OMAPAM33XX
187static struct map_desc omapam33xx_io_desc[] __initdata = {
188	{
189		.virtual	= L4_34XX_VIRT,
190		.pfn		= __phys_to_pfn(L4_34XX_PHYS),
191		.length		= L4_34XX_SIZE,
192		.type		= MT_DEVICE
193	},
194	{
195		.virtual	= L4_WK_AM33XX_VIRT,
196		.pfn		= __phys_to_pfn(L4_WK_AM33XX_PHYS),
197		.length		= L4_WK_AM33XX_SIZE,
198		.type		= MT_DEVICE
199	}
200};
201#endif
202
203#ifdef	CONFIG_ARCH_OMAP4
204static struct map_desc omap44xx_io_desc[] __initdata = {
205	{
206		.virtual	= L3_44XX_VIRT,
207		.pfn		= __phys_to_pfn(L3_44XX_PHYS),
208		.length		= L3_44XX_SIZE,
209		.type		= MT_DEVICE,
210	},
211	{
212		.virtual	= L4_44XX_VIRT,
213		.pfn		= __phys_to_pfn(L4_44XX_PHYS),
214		.length		= L4_44XX_SIZE,
215		.type		= MT_DEVICE,
216	},
217	{
218		.virtual	= OMAP44XX_GPMC_VIRT,
219		.pfn		= __phys_to_pfn(OMAP44XX_GPMC_PHYS),
220		.length		= OMAP44XX_GPMC_SIZE,
221		.type		= MT_DEVICE,
222	},
223	{
224		.virtual	= OMAP44XX_EMIF1_VIRT,
225		.pfn		= __phys_to_pfn(OMAP44XX_EMIF1_PHYS),
226		.length		= OMAP44XX_EMIF1_SIZE,
227		.type		= MT_DEVICE,
228	},
229	{
230		.virtual	= OMAP44XX_EMIF2_VIRT,
231		.pfn		= __phys_to_pfn(OMAP44XX_EMIF2_PHYS),
232		.length		= OMAP44XX_EMIF2_SIZE,
233		.type		= MT_DEVICE,
234	},
235	{
236		.virtual	= OMAP44XX_DMM_VIRT,
237		.pfn		= __phys_to_pfn(OMAP44XX_DMM_PHYS),
238		.length		= OMAP44XX_DMM_SIZE,
239		.type		= MT_DEVICE,
240	},
241	{
242		.virtual	= L4_PER_44XX_VIRT,
243		.pfn		= __phys_to_pfn(L4_PER_44XX_PHYS),
244		.length		= L4_PER_44XX_SIZE,
245		.type		= MT_DEVICE,
246	},
247	{
248		.virtual	= L4_EMU_44XX_VIRT,
249		.pfn		= __phys_to_pfn(L4_EMU_44XX_PHYS),
250		.length		= L4_EMU_44XX_SIZE,
251		.type		= MT_DEVICE,
252	},
253#ifdef CONFIG_OMAP4_ERRATA_I688
254	{
255		.virtual	= OMAP4_SRAM_VA,
256		.pfn		= __phys_to_pfn(OMAP4_SRAM_PA),
257		.length		= PAGE_SIZE,
258		.type		= MT_MEMORY_SO,
259	},
260#endif
261
262};
263#endif
264
265#ifdef CONFIG_SOC_OMAP2420
266void __init omap242x_map_common_io(void)
267{
268	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
269	iotable_init(omap242x_io_desc, ARRAY_SIZE(omap242x_io_desc));
270}
271#endif
272
273#ifdef CONFIG_SOC_OMAP2430
274void __init omap243x_map_common_io(void)
275{
276	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
277	iotable_init(omap243x_io_desc, ARRAY_SIZE(omap243x_io_desc));
278}
279#endif
280
281#ifdef CONFIG_ARCH_OMAP3
282void __init omap34xx_map_common_io(void)
283{
284	iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc));
285}
286#endif
287
288#ifdef CONFIG_SOC_OMAPTI81XX
289void __init omapti81xx_map_common_io(void)
290{
291	iotable_init(omapti81xx_io_desc, ARRAY_SIZE(omapti81xx_io_desc));
292}
293#endif
294
295#ifdef CONFIG_SOC_OMAPAM33XX
296void __init omapam33xx_map_common_io(void)
297{
298	iotable_init(omapam33xx_io_desc, ARRAY_SIZE(omapam33xx_io_desc));
299}
300#endif
301
302#ifdef CONFIG_ARCH_OMAP4
303void __init omap44xx_map_common_io(void)
304{
305	iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc));
306	omap_barriers_init();
307}
308#endif
309
310/*
311 * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters
312 *
313 * Sets the CORE DPLL3 M2 divider to the same value that it's at
314 * currently.  This has the effect of setting the SDRC SDRAM AC timing
315 * registers to the values currently defined by the kernel.  Currently
316 * only defined for OMAP3; will return 0 if called on OMAP2.  Returns
317 * -EINVAL if the dpll3_m2_ck cannot be found, 0 if called on OMAP2,
318 * or passes along the return value of clk_set_rate().
319 */
320static int __init _omap2_init_reprogram_sdrc(void)
321{
322	struct clk *dpll3_m2_ck;
323	int v = -EINVAL;
324	long rate;
325
326	if (!cpu_is_omap34xx())
327		return 0;
328
329	dpll3_m2_ck = clk_get(NULL, "dpll3_m2_ck");
330	if (IS_ERR(dpll3_m2_ck))
331		return -EINVAL;
332
333	rate = clk_get_rate(dpll3_m2_ck);
334	pr_info("Reprogramming SDRC clock to %ld Hz\n", rate);
335	v = clk_set_rate(dpll3_m2_ck, rate);
336	if (v)
337		pr_err("dpll3_m2_clk rate change failed: %d\n", v);
338
339	clk_put(dpll3_m2_ck);
340
341	return v;
342}
343
344static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data)
345{
346	return omap_hwmod_set_postsetup_state(oh, *(u8 *)data);
347}
348
349static void __init omap_common_init_early(void)
350{
351	omap_init_consistent_dma_size();
352}
353
354static void __init omap_hwmod_init_postsetup(void)
355{
356	u8 postsetup_state;
357
358	/* Set the default postsetup state for all hwmods */
359#ifdef CONFIG_PM_RUNTIME
360	postsetup_state = _HWMOD_STATE_IDLE;
361#else
362	postsetup_state = _HWMOD_STATE_ENABLED;
363#endif
364	omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
365
366	/*
367	 * Set the default postsetup state for unusual modules (like
368	 * MPU WDT).
369	 *
370	 * The postsetup_state is not actually used until
371	 * omap_hwmod_late_init(), so boards that desire full watchdog
372	 * coverage of kernel initialization can reprogram the
373	 * postsetup_state between the calls to
374	 * omap2_init_common_infra() and omap_sdrc_init().
375	 *
376	 * XXX ideally we could detect whether the MPU WDT was currently
377	 * enabled here and make this conditional
378	 */
379	postsetup_state = _HWMOD_STATE_DISABLED;
380	omap_hwmod_for_each_by_class("wd_timer",
381				     _set_hwmod_postsetup_state,
382				     &postsetup_state);
383
384	omap_pm_if_early_init();
385}
386
387#ifdef CONFIG_SOC_OMAP2420
388void __init omap2420_init_early(void)
389{
390	omap2_set_globals_242x();
391	omap2xxx_check_revision();
392	omap_common_init_early();
393	omap2xxx_voltagedomains_init();
394	omap242x_powerdomains_init();
395	omap242x_clockdomains_init();
396	omap2420_hwmod_init();
397	omap_hwmod_init_postsetup();
398	omap2420_clk_init();
399}
400#endif
401
402#ifdef CONFIG_SOC_OMAP2430
403void __init omap2430_init_early(void)
404{
405	omap2_set_globals_243x();
406	omap2xxx_check_revision();
407	omap_common_init_early();
408	omap2xxx_voltagedomains_init();
409	omap243x_powerdomains_init();
410	omap243x_clockdomains_init();
411	omap2430_hwmod_init();
412	omap_hwmod_init_postsetup();
413	omap2430_clk_init();
414}
415#endif
416
417/*
418 * Currently only board-omap3beagle.c should call this because of the
419 * same machine_id for 34xx and 36xx beagle.. Will get fixed with DT.
420 */
421#ifdef CONFIG_ARCH_OMAP3
422void __init omap3_init_early(void)
423{
424	omap2_set_globals_3xxx();
425	omap3xxx_check_revision();
426	omap3xxx_check_features();
427	omap_common_init_early();
428	omap3xxx_voltagedomains_init();
429	omap3xxx_powerdomains_init();
430	omap3xxx_clockdomains_init();
431	omap3xxx_hwmod_init();
432	omap_hwmod_init_postsetup();
433	omap3xxx_clk_init();
434}
435
436void __init omap3430_init_early(void)
437{
438	omap3_init_early();
439}
440
441void __init omap35xx_init_early(void)
442{
443	omap3_init_early();
444}
445
446void __init omap3630_init_early(void)
447{
448	omap3_init_early();
449}
450
451void __init am35xx_init_early(void)
452{
453	omap3_init_early();
454}
455
456void __init ti81xx_init_early(void)
457{
458	omap2_set_globals_ti81xx();
459	omap3xxx_check_revision();
460	ti81xx_check_features();
461	omap_common_init_early();
462	omap3xxx_voltagedomains_init();
463	omap3xxx_powerdomains_init();
464	omap3xxx_clockdomains_init();
465	omap3xxx_hwmod_init();
466	omap_hwmod_init_postsetup();
467	omap3xxx_clk_init();
468}
469#endif
470
471#ifdef CONFIG_ARCH_OMAP4
472void __init omap4430_init_early(void)
473{
474	omap2_set_globals_443x();
475	omap4xxx_check_revision();
476	omap4xxx_check_features();
477	omap_common_init_early();
478	omap44xx_voltagedomains_init();
479	omap44xx_powerdomains_init();
480	omap44xx_clockdomains_init();
481	omap44xx_hwmod_init();
482	omap_hwmod_init_postsetup();
483	omap4xxx_clk_init();
484}
485#endif
486
487void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
488				      struct omap_sdrc_params *sdrc_cs1)
489{
490	omap_sram_init();
491
492	if (cpu_is_omap24xx() || omap3_has_sdrc()) {
493		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
494		_omap2_init_reprogram_sdrc();
495	}
496}
497