Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * arch/arm/mach-imx/generic.c | |
3 | * | |
4 | * author: Sascha Hauer | |
5 | * Created: april 20th, 2004 | |
6 | * Copyright: Synertronixx GmbH | |
7 | * | |
8 | * Common code for i.MX machines | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * (at your option) any later version. | |
14 | * | |
15 | * This program is distributed in the hope that it will be useful, | |
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | * GNU General Public License for more details. | |
19 | * | |
20 | * You should have received a copy of the GNU General Public License | |
21 | * along with this program; if not, write to the Free Software | |
22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 | * | |
24 | */ | |
25 | #include <linux/device.h> | |
26 | #include <linux/init.h> | |
27 | #include <linux/kernel.h> | |
28 | #include <linux/module.h> | |
4e57b681 TS |
29 | #include <linux/string.h> |
30 | ||
a493820d | 31 | #include <asm/arch/imxfb.h> |
1da177e4 | 32 | #include <asm/hardware.h> |
0a5b0aa8 | 33 | #include <asm/arch/imx-regs.h> |
1da177e4 LT |
34 | |
35 | #include <asm/mach/map.h> | |
36 | ||
37 | void imx_gpio_mode(int gpio_mode) | |
38 | { | |
39 | unsigned int pin = gpio_mode & GPIO_PIN_MASK; | |
0a5b0aa8 SH |
40 | unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; |
41 | unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT; | |
1da177e4 LT |
42 | unsigned int tmp; |
43 | ||
44 | /* Pullup enable */ | |
45 | if(gpio_mode & GPIO_PUEN) | |
46 | PUEN(port) |= (1<<pin); | |
47 | else | |
48 | PUEN(port) &= ~(1<<pin); | |
49 | ||
50 | /* Data direction */ | |
51 | if(gpio_mode & GPIO_OUT) | |
52 | DDIR(port) |= 1<<pin; | |
53 | else | |
54 | DDIR(port) &= ~(1<<pin); | |
55 | ||
56 | /* Primary / alternate function */ | |
57 | if(gpio_mode & GPIO_AF) | |
58 | GPR(port) |= (1<<pin); | |
59 | else | |
60 | GPR(port) &= ~(1<<pin); | |
61 | ||
62 | /* use as gpio? */ | |
0a5b0aa8 | 63 | if(gpio_mode & GPIO_GIUS) |
1da177e4 LT |
64 | GIUS(port) |= (1<<pin); |
65 | else | |
66 | GIUS(port) &= ~(1<<pin); | |
67 | ||
68 | /* Output / input configuration */ | |
69 | /* FIXME: I'm not very sure about OCR and ICONF, someone | |
70 | * should have a look over it | |
71 | */ | |
72 | if(pin<16) { | |
73 | tmp = OCR1(port); | |
74 | tmp &= ~( 3<<(pin*2)); | |
75 | tmp |= (ocr << (pin*2)); | |
76 | OCR1(port) = tmp; | |
77 | ||
0a5b0aa8 SH |
78 | ICONFA1(port) &= ~( 3<<(pin*2)); |
79 | ICONFA1(port) |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << (pin * 2); | |
80 | ICONFB1(port) &= ~( 3<<(pin*2)); | |
81 | ICONFB1(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << (pin * 2); | |
1da177e4 LT |
82 | } else { |
83 | tmp = OCR2(port); | |
84 | tmp &= ~( 3<<((pin-16)*2)); | |
85 | tmp |= (ocr << ((pin-16)*2)); | |
86 | OCR2(port) = tmp; | |
87 | ||
0a5b0aa8 SH |
88 | ICONFA2(port) &= ~( 3<<((pin-16)*2)); |
89 | ICONFA2(port) |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << ((pin-16) * 2); | |
90 | ICONFB2(port) &= ~( 3<<((pin-16)*2)); | |
91 | ICONFB2(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << ((pin-16) * 2); | |
1da177e4 LT |
92 | } |
93 | } | |
94 | ||
95 | EXPORT_SYMBOL(imx_gpio_mode); | |
96 | ||
97 | /* | |
98 | * get the system pll clock in Hz | |
99 | * | |
100 | * mfi + mfn / (mfd +1) | |
101 | * f = 2 * f_ref * -------------------- | |
102 | * pd + 1 | |
103 | */ | |
104 | static unsigned int imx_decode_pll(unsigned int pll) | |
105 | { | |
106 | u32 mfi = (pll >> 10) & 0xf; | |
107 | u32 mfn = pll & 0x3ff; | |
108 | u32 mfd = (pll >> 16) & 0x3ff; | |
109 | u32 pd = (pll >> 26) & 0xf; | |
110 | u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512); | |
111 | ||
112 | mfi = mfi <= 5 ? 5 : mfi; | |
113 | ||
114 | return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1); | |
115 | } | |
116 | ||
117 | unsigned int imx_get_system_clk(void) | |
118 | { | |
119 | return imx_decode_pll(SPCTL0); | |
120 | } | |
121 | EXPORT_SYMBOL(imx_get_system_clk); | |
122 | ||
123 | unsigned int imx_get_mcu_clk(void) | |
124 | { | |
125 | return imx_decode_pll(MPCTL0); | |
126 | } | |
127 | EXPORT_SYMBOL(imx_get_mcu_clk); | |
128 | ||
129 | /* | |
130 | * get peripheral clock 1 ( UART[12], Timer[12], PWM ) | |
131 | */ | |
132 | unsigned int imx_get_perclk1(void) | |
133 | { | |
134 | return imx_get_system_clk() / (((PCDR) & 0xf)+1); | |
135 | } | |
136 | EXPORT_SYMBOL(imx_get_perclk1); | |
137 | ||
138 | /* | |
139 | * get peripheral clock 2 ( LCD, SD, SPI[12] ) | |
140 | */ | |
141 | unsigned int imx_get_perclk2(void) | |
142 | { | |
143 | return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1); | |
144 | } | |
145 | EXPORT_SYMBOL(imx_get_perclk2); | |
146 | ||
147 | /* | |
148 | * get peripheral clock 3 ( SSI ) | |
149 | */ | |
150 | unsigned int imx_get_perclk3(void) | |
151 | { | |
152 | return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1); | |
153 | } | |
154 | EXPORT_SYMBOL(imx_get_perclk3); | |
155 | ||
156 | /* | |
157 | * get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA ) | |
158 | */ | |
159 | unsigned int imx_get_hclk(void) | |
160 | { | |
161 | return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1); | |
162 | } | |
163 | EXPORT_SYMBOL(imx_get_hclk); | |
164 | ||
165 | static struct resource imx_mmc_resources[] = { | |
166 | [0] = { | |
167 | .start = 0x00214000, | |
168 | .end = 0x002140FF, | |
169 | .flags = IORESOURCE_MEM, | |
170 | }, | |
171 | [1] = { | |
172 | .start = (SDHC_INT), | |
173 | .end = (SDHC_INT), | |
174 | .flags = IORESOURCE_IRQ, | |
175 | }, | |
176 | }; | |
177 | ||
178 | static struct platform_device imx_mmc_device = { | |
179 | .name = "imx-mmc", | |
180 | .id = 0, | |
181 | .num_resources = ARRAY_SIZE(imx_mmc_resources), | |
182 | .resource = imx_mmc_resources, | |
183 | }; | |
184 | ||
185 | static struct resource imx_uart1_resources[] = { | |
186 | [0] = { | |
187 | .start = 0x00206000, | |
188 | .end = 0x002060FF, | |
189 | .flags = IORESOURCE_MEM, | |
190 | }, | |
191 | [1] = { | |
192 | .start = (UART1_MINT_RX), | |
193 | .end = (UART1_MINT_RX), | |
194 | .flags = IORESOURCE_IRQ, | |
195 | }, | |
196 | [2] = { | |
197 | .start = (UART1_MINT_TX), | |
198 | .end = (UART1_MINT_TX), | |
199 | .flags = IORESOURCE_IRQ, | |
200 | }, | |
201 | }; | |
202 | ||
203 | static struct platform_device imx_uart1_device = { | |
204 | .name = "imx-uart", | |
205 | .id = 0, | |
206 | .num_resources = ARRAY_SIZE(imx_uart1_resources), | |
207 | .resource = imx_uart1_resources, | |
208 | }; | |
209 | ||
210 | static struct resource imx_uart2_resources[] = { | |
211 | [0] = { | |
212 | .start = 0x00207000, | |
213 | .end = 0x002070FF, | |
214 | .flags = IORESOURCE_MEM, | |
215 | }, | |
216 | [1] = { | |
217 | .start = (UART2_MINT_RX), | |
218 | .end = (UART2_MINT_RX), | |
219 | .flags = IORESOURCE_IRQ, | |
220 | }, | |
221 | [2] = { | |
222 | .start = (UART2_MINT_TX), | |
223 | .end = (UART2_MINT_TX), | |
224 | .flags = IORESOURCE_IRQ, | |
225 | }, | |
226 | }; | |
227 | ||
228 | static struct platform_device imx_uart2_device = { | |
229 | .name = "imx-uart", | |
230 | .id = 1, | |
231 | .num_resources = ARRAY_SIZE(imx_uart2_resources), | |
232 | .resource = imx_uart2_resources, | |
233 | }; | |
234 | ||
a493820d SH |
235 | static struct imxfb_mach_info imx_fb_info; |
236 | ||
237 | void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info) | |
238 | { | |
239 | memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imxfb_mach_info)); | |
240 | } | |
241 | EXPORT_SYMBOL(set_imx_fb_info); | |
242 | ||
1da177e4 LT |
243 | static struct resource imxfb_resources[] = { |
244 | [0] = { | |
245 | .start = 0x00205000, | |
246 | .end = 0x002050FF, | |
247 | .flags = IORESOURCE_MEM, | |
248 | }, | |
249 | [1] = { | |
250 | .start = LCDC_INT, | |
251 | .end = LCDC_INT, | |
252 | .flags = IORESOURCE_IRQ, | |
253 | }, | |
254 | }; | |
255 | ||
a493820d SH |
256 | static u64 fb_dma_mask = ~(u64)0; |
257 | ||
1da177e4 LT |
258 | static struct platform_device imxfb_device = { |
259 | .name = "imx-fb", | |
260 | .id = 0, | |
a493820d SH |
261 | .dev = { |
262 | .platform_data = &imx_fb_info, | |
263 | .dma_mask = &fb_dma_mask, | |
264 | .coherent_dma_mask = 0xffffffff, | |
265 | }, | |
1da177e4 LT |
266 | .num_resources = ARRAY_SIZE(imxfb_resources), |
267 | .resource = imxfb_resources, | |
268 | }; | |
269 | ||
270 | static struct platform_device *devices[] __initdata = { | |
271 | &imx_mmc_device, | |
272 | &imxfb_device, | |
273 | &imx_uart1_device, | |
274 | &imx_uart2_device, | |
275 | }; | |
276 | ||
277 | static struct map_desc imx_io_desc[] __initdata = { | |
adecef74 DS |
278 | { |
279 | .virtual = IMX_IO_BASE, | |
280 | .pfn = __phys_to_pfn(IMX_IO_PHYS), | |
281 | .length = IMX_IO_SIZE, | |
282 | .type = MT_DEVICE | |
283 | } | |
1da177e4 LT |
284 | }; |
285 | ||
286 | void __init | |
287 | imx_map_io(void) | |
288 | { | |
289 | iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc)); | |
290 | } | |
291 | ||
292 | static int __init imx_init(void) | |
293 | { | |
294 | return platform_add_devices(devices, ARRAY_SIZE(devices)); | |
295 | } | |
296 | ||
297 | subsys_initcall(imx_init); |