]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - arch/arm/mach-imx/generic.c
IMX: introduce clock API
[mv-sheeva.git] / arch / arm / mach-imx / generic.c
index 7a7fa51ec62c11882e8833c94368536e3c77be2d..98ddd8a6d05fb1a6b6da716abff67b11036f39d4 100644 (file)
 #include <linux/module.h>
 #include <linux/string.h>
 
+#include <asm/errno.h>
 #include <asm/arch/imxfb.h>
 #include <asm/hardware.h>
 #include <asm/arch/imx-regs.h>
 
 #include <asm/mach/map.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/gpio.h>
+
+unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
 
 void imx_gpio_mode(int gpio_mode)
 {
@@ -95,81 +99,120 @@ void imx_gpio_mode(int gpio_mode)
 
 EXPORT_SYMBOL(imx_gpio_mode);
 
-/*
- *  get the system pll clock in Hz
- *
- *                  mfi + mfn / (mfd +1)
- *  f = 2 * f_ref * --------------------
- *                        pd + 1
- */
-static unsigned int imx_decode_pll(unsigned int pll, u32 f_ref)
+int imx_gpio_request(unsigned gpio, const char *label)
 {
-       unsigned long long ll;
-       unsigned long quot;
-
-       u32 mfi = (pll >> 10) & 0xf;
-       u32 mfn = pll & 0x3ff;
-       u32 mfd = (pll >> 16) & 0x3ff;
-       u32 pd =  (pll >> 26) & 0xf;
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32) {
+               printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
+                       gpio, label ? label : "?");
+               return -EINVAL;
+       }
 
-       mfi = mfi <= 5 ? 5 : mfi;
+       if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
+               printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
+                       gpio, label ? label : "?");
+               return -EBUSY;
+       }
 
-       ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) );
-       quot = (pd+1) * (1<<16);
-       ll += quot / 2;
-       do_div(ll, quot);
-       return (unsigned int) ll;
+       return 0;
 }
 
-unsigned int imx_get_system_clk(void)
+EXPORT_SYMBOL(imx_gpio_request);
+
+void imx_gpio_free(unsigned gpio)
 {
-       u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
+       if(gpio >= (GPIO_PORT_MAX + 1) * 32)
+               return;
 
-       return imx_decode_pll(SPCTL0, f_ref);
+       clear_bit(gpio, imx_gpio_alloc_map);
 }
-EXPORT_SYMBOL(imx_get_system_clk);
 
-unsigned int imx_get_mcu_clk(void)
+EXPORT_SYMBOL(imx_gpio_free);
+
+int imx_gpio_direction_input(unsigned gpio)
 {
-       return imx_decode_pll(MPCTL0, CLK32 * 512);
+       imx_gpio_mode(gpio | GPIO_IN | GPIO_GIUS | GPIO_DR);
+       return 0;
 }
-EXPORT_SYMBOL(imx_get_mcu_clk);
 
-/*
- *  get peripheral clock 1 ( UART[12], Timer[12], PWM )
- */
-unsigned int imx_get_perclk1(void)
+EXPORT_SYMBOL(imx_gpio_direction_input);
+
+int imx_gpio_direction_output(unsigned gpio, int value)
 {
-       return imx_get_system_clk() / (((PCDR) & 0xf)+1);
+       imx_gpio_set_value(gpio, value);
+       imx_gpio_mode(gpio | GPIO_OUT | GPIO_GIUS | GPIO_DR);
+       return 0;
 }
-EXPORT_SYMBOL(imx_get_perclk1);
 
-/*
- *  get peripheral clock 2 ( LCD, SD, SPI[12] )
- */
-unsigned int imx_get_perclk2(void)
+EXPORT_SYMBOL(imx_gpio_direction_output);
+
+int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
+                               int alloc_mode, const char *label)
 {
-       return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
+       const int *p = pin_list;
+       int i;
+       unsigned gpio;
+       unsigned mode;
+
+       for (i = 0; i < count; i++) {
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
+
+               if (gpio >= (GPIO_PORT_MAX + 1) * 32)
+                       goto setup_error;
+
+               if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
+                       imx_gpio_free(gpio);
+               else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
+                       if (imx_gpio_request(gpio, label))
+                               if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+                                       goto setup_error;
+
+               if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
+                                   IMX_GPIO_ALLOC_MODE_RELEASE)))
+                       imx_gpio_mode(gpio | mode);
+
+               p++;
+       }
+       return 0;
+
+setup_error:
+       if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
+                        IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
+               return -EINVAL;
+
+       while (p != pin_list) {
+               p--;
+               gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
+               imx_gpio_free(gpio);
+       }
+
+       return -EINVAL;
 }
-EXPORT_SYMBOL(imx_get_perclk2);
 
-/*
- *  get peripheral clock 3 ( SSI )
- */
-unsigned int imx_get_perclk3(void)
+EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
+
+void __imx_gpio_set_value(unsigned gpio, int value)
 {
-       return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
+       imx_gpio_set_value_inline(gpio, value);
 }
-EXPORT_SYMBOL(imx_get_perclk3);
 
-/*
- *  get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
- */
-unsigned int imx_get_hclk(void)
+EXPORT_SYMBOL(__imx_gpio_set_value);
+
+int imx_gpio_to_irq(unsigned gpio)
 {
-       return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
+       return IRQ_GPIOA(0) + gpio;
 }
-EXPORT_SYMBOL(imx_get_hclk);
+
+EXPORT_SYMBOL(imx_gpio_to_irq);
+
+int imx_irq_to_gpio(unsigned irq)
+{
+       if (irq < IRQ_GPIOA(0))
+               return -EINVAL;
+       return irq - IRQ_GPIOA(0);
+}
+
+EXPORT_SYMBOL(imx_irq_to_gpio);
 
 static struct resource imx_mmc_resources[] = {
        [0] = {
@@ -201,7 +244,6 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
 {
        imx_mmc_device.dev.platform_data = info;
 }
-EXPORT_SYMBOL(imx_set_mmc_info);
 
 static struct imxfb_mach_info imx_fb_info;