Linux-2.6.12-rc2
[linux-2.6.git] / arch / arm / mach-imx / generic.c
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>
29 #include <asm/hardware.h>
30
31 #include <asm/mach/map.h>
32
33 void imx_gpio_mode(int gpio_mode)
34 {
35         unsigned int pin = gpio_mode & GPIO_PIN_MASK;
36         unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> 5;
37         unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> 10;
38         unsigned int tmp;
39
40         /* Pullup enable */
41         if(gpio_mode & GPIO_PUEN)
42                 PUEN(port) |= (1<<pin);
43         else
44                 PUEN(port) &= ~(1<<pin);
45
46         /* Data direction */
47         if(gpio_mode & GPIO_OUT)
48                 DDIR(port) |= 1<<pin;
49         else
50                 DDIR(port) &= ~(1<<pin);
51
52         /* Primary / alternate function */
53         if(gpio_mode & GPIO_AF)
54                 GPR(port) |= (1<<pin);
55         else
56                 GPR(port) &= ~(1<<pin);
57
58         /* use as gpio? */
59         if( ocr == 3 )
60                 GIUS(port) |= (1<<pin);
61         else
62                 GIUS(port) &= ~(1<<pin);
63
64         /* Output / input configuration */
65         /* FIXME: I'm not very sure about OCR and ICONF, someone
66          * should have a look over it
67          */
68         if(pin<16) {
69                 tmp = OCR1(port);
70                 tmp &= ~( 3<<(pin*2));
71                 tmp |= (ocr << (pin*2));
72                 OCR1(port) = tmp;
73
74                 if( gpio_mode & GPIO_AOUT )
75                         ICONFA1(port) &= ~( 3<<(pin*2));
76                 if( gpio_mode & GPIO_BOUT )
77                         ICONFB1(port) &= ~( 3<<(pin*2));
78         } else {
79                 tmp = OCR2(port);
80                 tmp &= ~( 3<<((pin-16)*2));
81                 tmp |= (ocr << ((pin-16)*2));
82                 OCR2(port) = tmp;
83
84                 if( gpio_mode & GPIO_AOUT )
85                         ICONFA2(port) &= ~( 3<<((pin-16)*2));
86                 if( gpio_mode & GPIO_BOUT )
87                         ICONFB2(port) &= ~( 3<<((pin-16)*2));
88         }
89 }
90
91 EXPORT_SYMBOL(imx_gpio_mode);
92
93 /*
94  *  get the system pll clock in Hz
95  *
96  *                  mfi + mfn / (mfd +1)
97  *  f = 2 * f_ref * --------------------
98  *                        pd + 1
99  */
100 static unsigned int imx_decode_pll(unsigned int pll)
101 {
102         u32 mfi = (pll >> 10) & 0xf;
103         u32 mfn = pll & 0x3ff;
104         u32 mfd = (pll >> 16) & 0x3ff;
105         u32 pd =  (pll >> 26) & 0xf;
106         u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
107
108         mfi = mfi <= 5 ? 5 : mfi;
109
110         return (2 * (f_ref>>10) * ( (mfi<<10) + (mfn<<10) / (mfd+1) )) / (pd+1);
111 }
112
113 unsigned int imx_get_system_clk(void)
114 {
115         return imx_decode_pll(SPCTL0);
116 }
117 EXPORT_SYMBOL(imx_get_system_clk);
118
119 unsigned int imx_get_mcu_clk(void)
120 {
121         return imx_decode_pll(MPCTL0);
122 }
123 EXPORT_SYMBOL(imx_get_mcu_clk);
124
125 /*
126  *  get peripheral clock 1 ( UART[12], Timer[12], PWM )
127  */
128 unsigned int imx_get_perclk1(void)
129 {
130         return imx_get_system_clk() / (((PCDR) & 0xf)+1);
131 }
132 EXPORT_SYMBOL(imx_get_perclk1);
133
134 /*
135  *  get peripheral clock 2 ( LCD, SD, SPI[12] )
136  */
137 unsigned int imx_get_perclk2(void)
138 {
139         return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
140 }
141 EXPORT_SYMBOL(imx_get_perclk2);
142
143 /*
144  *  get peripheral clock 3 ( SSI )
145  */
146 unsigned int imx_get_perclk3(void)
147 {
148         return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
149 }
150 EXPORT_SYMBOL(imx_get_perclk3);
151
152 /*
153  *  get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
154  */
155 unsigned int imx_get_hclk(void)
156 {
157         return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
158 }
159 EXPORT_SYMBOL(imx_get_hclk);
160
161 static struct resource imx_mmc_resources[] = {
162         [0] = {
163                 .start  = 0x00214000,
164                 .end    = 0x002140FF,
165                 .flags  = IORESOURCE_MEM,
166         },
167         [1] = {
168                 .start  = (SDHC_INT),
169                 .end    = (SDHC_INT),
170                 .flags  = IORESOURCE_IRQ,
171         },
172 };
173
174 static struct platform_device imx_mmc_device = {
175         .name           = "imx-mmc",
176         .id             = 0,
177         .num_resources  = ARRAY_SIZE(imx_mmc_resources),
178         .resource       = imx_mmc_resources,
179 };
180
181 static struct resource imx_uart1_resources[] = {
182         [0] = {
183                 .start  = 0x00206000,
184                 .end    = 0x002060FF,
185                 .flags  = IORESOURCE_MEM,
186         },
187         [1] = {
188                 .start  = (UART1_MINT_RX),
189                 .end    = (UART1_MINT_RX),
190                 .flags  = IORESOURCE_IRQ,
191         },
192         [2] = {
193                 .start  = (UART1_MINT_TX),
194                 .end    = (UART1_MINT_TX),
195                 .flags  = IORESOURCE_IRQ,
196         },
197 };
198
199 static struct platform_device imx_uart1_device = {
200         .name           = "imx-uart",
201         .id             = 0,
202         .num_resources  = ARRAY_SIZE(imx_uart1_resources),
203         .resource       = imx_uart1_resources,
204 };
205
206 static struct resource imx_uart2_resources[] = {
207         [0] = {
208                 .start  = 0x00207000,
209                 .end    = 0x002070FF,
210                 .flags  = IORESOURCE_MEM,
211         },
212         [1] = {
213                 .start  = (UART2_MINT_RX),
214                 .end    = (UART2_MINT_RX),
215                 .flags  = IORESOURCE_IRQ,
216         },
217         [2] = {
218                 .start  = (UART2_MINT_TX),
219                 .end    = (UART2_MINT_TX),
220                 .flags  = IORESOURCE_IRQ,
221         },
222 };
223
224 static struct platform_device imx_uart2_device = {
225         .name           = "imx-uart",
226         .id             = 1,
227         .num_resources  = ARRAY_SIZE(imx_uart2_resources),
228         .resource       = imx_uart2_resources,
229 };
230
231 static struct resource imxfb_resources[] = {
232         [0] = {
233                 .start  = 0x00205000,
234                 .end    = 0x002050FF,
235                 .flags  = IORESOURCE_MEM,
236         },
237         [1] = {
238                 .start  = LCDC_INT,
239                 .end    = LCDC_INT,
240                 .flags  = IORESOURCE_IRQ,
241         },
242 };
243
244 static struct platform_device imxfb_device = {
245         .name           = "imx-fb",
246         .id             = 0,
247         .num_resources  = ARRAY_SIZE(imxfb_resources),
248         .resource       = imxfb_resources,
249 };
250
251 static struct platform_device *devices[] __initdata = {
252         &imx_mmc_device,
253         &imxfb_device,
254         &imx_uart1_device,
255         &imx_uart2_device,
256 };
257
258 static struct map_desc imx_io_desc[] __initdata = {
259         /* virtual     physical    length      type */
260         {IMX_IO_BASE, IMX_IO_PHYS, IMX_IO_SIZE, MT_DEVICE},
261 };
262
263 void __init
264 imx_map_io(void)
265 {
266         iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
267 }
268
269 static int __init imx_init(void)
270 {
271         return platform_add_devices(devices, ARRAY_SIZE(devices));
272 }
273
274 subsys_initcall(imx_init);