7ec80ddf |
1 | /* |
2 | * linux/arch/arm/mach-w90x900/w90p910.c |
3 | * |
4 | * Based on linux/arch/arm/plat-s3c24xx/s3c244x.c by Ben Dooks |
5 | * |
604f766f |
6 | * Copyright (c) 2008 Nuvoton technology corporation. |
7ec80ddf |
7 | * |
8 | * Wan ZongShun <mcuos.com@gmail.com> |
9 | * |
10 | * W90P910 cpu support |
11 | * |
12 | * This program is free software; you can redistribute it and/or modify |
13 | * it under the terms of the GNU General Public License as published by |
604f766f |
14 | * the Free Software Foundation;version 2 of the License. |
7ec80ddf |
15 | * |
16 | */ |
17 | |
18 | #include <linux/kernel.h> |
19 | #include <linux/types.h> |
20 | #include <linux/interrupt.h> |
21 | #include <linux/list.h> |
22 | #include <linux/timer.h> |
23 | #include <linux/init.h> |
24 | #include <linux/platform_device.h> |
25 | #include <linux/io.h> |
17198f2d |
26 | #include <linux/serial_8250.h> |
ae45b1c6 |
27 | #include <linux/delay.h> |
7ec80ddf |
28 | |
29 | #include <asm/mach/arch.h> |
30 | #include <asm/mach/map.h> |
31 | #include <asm/mach/irq.h> |
32 | #include <asm/irq.h> |
33 | |
34 | #include <mach/hardware.h> |
35 | #include <mach/regs-serial.h> |
ae45b1c6 |
36 | #include <mach/regs-clock.h> |
37 | #include <mach/regs-ebi.h> |
7ec80ddf |
38 | |
39 | #include "cpu.h" |
0e4a34bb |
40 | #include "clock.h" |
7ec80ddf |
41 | |
7ec80ddf |
42 | /* Initial IO mappings */ |
43 | |
44 | static struct map_desc w90p910_iodesc[] __initdata = { |
45 | IODESC_ENT(IRQ), |
46 | IODESC_ENT(GCR), |
47 | IODESC_ENT(UART), |
48 | IODESC_ENT(TIMER), |
49 | IODESC_ENT(EBI), |
604f766f |
50 | IODESC_ENT(USBEHCIHOST), |
51 | IODESC_ENT(USBOHCIHOST), |
52 | IODESC_ENT(ADC), |
0351c506 |
53 | IODESC_ENT(RTC), |
54 | IODESC_ENT(KPI), |
55 | IODESC_ENT(USBDEV), |
7ec80ddf |
56 | /*IODESC_ENT(LCD),*/ |
57 | }; |
58 | |
0e4a34bb |
59 | /* Initial clock declarations. */ |
60 | static DEFINE_CLK(lcd, 0); |
61 | static DEFINE_CLK(audio, 1); |
62 | static DEFINE_CLK(fmi, 4); |
db58e90f |
63 | static DEFINE_SUBCLK(ms, 0); |
64 | static DEFINE_SUBCLK(sd, 1); |
0e4a34bb |
65 | static DEFINE_CLK(dmac, 5); |
66 | static DEFINE_CLK(atapi, 6); |
67 | static DEFINE_CLK(emc, 7); |
db58e90f |
68 | static DEFINE_SUBCLK(rmii, 2); |
0e4a34bb |
69 | static DEFINE_CLK(usbd, 8); |
70 | static DEFINE_CLK(usbh, 9); |
71 | static DEFINE_CLK(g2d, 10);; |
72 | static DEFINE_CLK(pwm, 18); |
73 | static DEFINE_CLK(ps2, 24); |
74 | static DEFINE_CLK(kpi, 25); |
75 | static DEFINE_CLK(wdt, 26); |
76 | static DEFINE_CLK(gdma, 27); |
77 | static DEFINE_CLK(adc, 28); |
78 | static DEFINE_CLK(usi, 29); |
58b5369e |
79 | static DEFINE_CLK(ext, 0); |
0e4a34bb |
80 | |
81 | static struct clk_lookup w90p910_clkregs[] = { |
82 | DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL), |
83 | DEF_CLKLOOK(&clk_audio, "w90p910-audio", NULL), |
84 | DEF_CLKLOOK(&clk_fmi, "w90p910-fmi", NULL), |
db58e90f |
85 | DEF_CLKLOOK(&clk_ms, "w90p910-fmi", "MS"), |
86 | DEF_CLKLOOK(&clk_sd, "w90p910-fmi", "SD"), |
0e4a34bb |
87 | DEF_CLKLOOK(&clk_dmac, "w90p910-dmac", NULL), |
88 | DEF_CLKLOOK(&clk_atapi, "w90p910-atapi", NULL), |
89 | DEF_CLKLOOK(&clk_emc, "w90p910-emc", NULL), |
db58e90f |
90 | DEF_CLKLOOK(&clk_rmii, "w90p910-emc", "RMII"), |
0e4a34bb |
91 | DEF_CLKLOOK(&clk_usbd, "w90p910-usbd", NULL), |
92 | DEF_CLKLOOK(&clk_usbh, "w90p910-usbh", NULL), |
93 | DEF_CLKLOOK(&clk_g2d, "w90p910-g2d", NULL), |
94 | DEF_CLKLOOK(&clk_pwm, "w90p910-pwm", NULL), |
95 | DEF_CLKLOOK(&clk_ps2, "w90p910-ps2", NULL), |
96 | DEF_CLKLOOK(&clk_kpi, "w90p910-kpi", NULL), |
97 | DEF_CLKLOOK(&clk_wdt, "w90p910-wdt", NULL), |
98 | DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL), |
99 | DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL), |
b4814766 |
100 | DEF_CLKLOOK(&clk_usi, "w90p910-spi", NULL), |
58b5369e |
101 | DEF_CLKLOOK(&clk_ext, NULL, "ext"), |
0e4a34bb |
102 | }; |
103 | |
17198f2d |
104 | /* Initial serial platform data */ |
7ec80ddf |
105 | |
17198f2d |
106 | struct plat_serial8250_port w90p910_uart_data[] = { |
107 | W90X900_8250PORT(UART0), |
108 | }; |
7ec80ddf |
109 | |
17198f2d |
110 | struct platform_device w90p910_serial_device = { |
111 | .name = "serial8250", |
112 | .id = PLAT8250_DEV_PLATFORM, |
113 | .dev = { |
114 | .platform_data = w90p910_uart_data, |
115 | }, |
116 | }; |
7ec80ddf |
117 | |
118 | /*Init W90P910 evb io*/ |
119 | |
120 | void __init w90p910_map_io(struct map_desc *mach_desc, int mach_size) |
121 | { |
122 | unsigned long idcode = 0x0; |
123 | |
124 | iotable_init(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc)); |
125 | |
126 | idcode = __raw_readl(W90X900PDID); |
127 | if (idcode != W90P910_CPUID) |
128 | printk(KERN_ERR "CPU type 0x%08lx is not W90P910\n", idcode); |
129 | } |
130 | |
ae45b1c6 |
131 | /*Set W90P910 cpu frequence*/ |
132 | static int __init w90p910_set_clkval(unsigned int cpufreq) |
133 | { |
134 | unsigned int pllclk, ahbclk, apbclk, val; |
135 | |
136 | pllclk = 0; |
137 | ahbclk = 0; |
138 | apbclk = 0; |
139 | |
140 | switch (cpufreq) { |
141 | case 66: |
142 | pllclk = PLL_66MHZ; |
143 | ahbclk = AHB_CPUCLK_1_1; |
144 | apbclk = APB_AHB_1_2; |
145 | break; |
146 | |
147 | case 100: |
148 | pllclk = PLL_100MHZ; |
149 | ahbclk = AHB_CPUCLK_1_1; |
150 | apbclk = APB_AHB_1_2; |
151 | break; |
152 | |
153 | case 120: |
154 | pllclk = PLL_120MHZ; |
155 | ahbclk = AHB_CPUCLK_1_2; |
156 | apbclk = APB_AHB_1_2; |
157 | break; |
158 | |
159 | case 166: |
160 | pllclk = PLL_166MHZ; |
161 | ahbclk = AHB_CPUCLK_1_2; |
162 | apbclk = APB_AHB_1_2; |
163 | break; |
164 | |
165 | case 200: |
166 | pllclk = PLL_200MHZ; |
167 | ahbclk = AHB_CPUCLK_1_2; |
168 | apbclk = APB_AHB_1_2; |
169 | break; |
170 | } |
171 | |
172 | __raw_writel(pllclk, REG_PLLCON0); |
173 | |
174 | val = __raw_readl(REG_CLKDIV); |
175 | val &= ~(0x03 << 24 | 0x03 << 26); |
176 | val |= (ahbclk << 24 | apbclk << 26); |
177 | __raw_writel(val, REG_CLKDIV); |
178 | |
179 | return 0; |
180 | } |
181 | static int __init w90p910_set_cpufreq(char *str) |
182 | { |
183 | unsigned long cpufreq, val; |
184 | |
185 | if (!*str) |
186 | return 0; |
187 | |
188 | strict_strtoul(str, 0, &cpufreq); |
189 | |
190 | w90p910_clock_source(NULL, "ext"); |
191 | |
192 | w90p910_set_clkval(cpufreq); |
193 | |
194 | mdelay(1); |
195 | |
196 | val = __raw_readl(REG_CKSKEW); |
197 | val &= ~0xff; |
198 | val |= DEFAULTSKEW; |
199 | __raw_writel(val, REG_CKSKEW); |
200 | |
201 | w90p910_clock_source(NULL, "pll0"); |
202 | |
203 | return 1; |
204 | } |
205 | |
206 | __setup("cpufreq=", w90p910_set_cpufreq); |
207 | |
7ec80ddf |
208 | /*Init W90P910 clock*/ |
209 | |
0e4a34bb |
210 | void __init w90p910_init_clocks(void) |
7ec80ddf |
211 | { |
0e4a34bb |
212 | clks_register(w90p910_clkregs, ARRAY_SIZE(w90p910_clkregs)); |
7ec80ddf |
213 | } |
214 | |
215 | static int __init w90p910_init_cpu(void) |
216 | { |
217 | return 0; |
218 | } |
219 | |
220 | static int __init w90x900_arch_init(void) |
221 | { |
17198f2d |
222 | return w90p910_init_cpu(); |
7ec80ddf |
223 | } |
224 | arch_initcall(w90x900_arch_init); |