linux/arch/arm/mach-imx/generic.c
<<
>>
Prefs
   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/platform_device.h>
  26#include <linux/init.h>
  27#include <linux/kernel.h>
  28#include <linux/module.h>
  29#include <linux/string.h>
  30
  31#include <asm/errno.h>
  32#include <asm/arch/imxfb.h>
  33#include <asm/hardware.h>
  34#include <asm/arch/imx-regs.h>
  35
  36#include <asm/mach/map.h>
  37#include <asm/arch/mmc.h>
  38#include <asm/arch/gpio.h>
  39
  40unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG];
  41
  42void imx_gpio_mode(int gpio_mode)
  43{
  44        unsigned int pin = gpio_mode & GPIO_PIN_MASK;
  45        unsigned int port = (gpio_mode & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
  46        unsigned int ocr = (gpio_mode & GPIO_OCR_MASK) >> GPIO_OCR_SHIFT;
  47        unsigned int tmp;
  48
  49        /* Pullup enable */
  50        if(gpio_mode & GPIO_PUEN)
  51                PUEN(port) |= (1<<pin);
  52        else
  53                PUEN(port) &= ~(1<<pin);
  54
  55        /* Data direction */
  56        if(gpio_mode & GPIO_OUT)
  57                DDIR(port) |= 1<<pin;
  58        else
  59                DDIR(port) &= ~(1<<pin);
  60
  61        /* Primary / alternate function */
  62        if(gpio_mode & GPIO_AF)
  63                GPR(port) |= (1<<pin);
  64        else
  65                GPR(port) &= ~(1<<pin);
  66
  67        /* use as gpio? */
  68        if(gpio_mode &  GPIO_GIUS)
  69                GIUS(port) |= (1<<pin);
  70        else
  71                GIUS(port) &= ~(1<<pin);
  72
  73        /* Output / input configuration */
  74        /* FIXME: I'm not very sure about OCR and ICONF, someone
  75         * should have a look over it
  76         */
  77        if(pin<16) {
  78                tmp = OCR1(port);
  79                tmp &= ~( 3<<(pin*2));
  80                tmp |= (ocr << (pin*2));
  81                OCR1(port) = tmp;
  82
  83                ICONFA1(port) &= ~( 3<<(pin*2));
  84                ICONFA1(port) |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << (pin * 2);
  85                ICONFB1(port) &= ~( 3<<(pin*2));
  86                ICONFB1(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << (pin * 2);
  87        } else {
  88                tmp = OCR2(port);
  89                tmp &= ~( 3<<((pin-16)*2));
  90                tmp |= (ocr << ((pin-16)*2));
  91                OCR2(port) = tmp;
  92
  93                ICONFA2(port) &= ~( 3<<((pin-16)*2));
  94                ICONFA2(port) |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << ((pin-16) * 2);
  95                ICONFB2(port) &= ~( 3<<((pin-16)*2));
  96                ICONFB2(port) |= ((gpio_mode >> GPIO_BOUT_SHIFT) & 3) << ((pin-16) * 2);
  97        }
  98}
  99
 100EXPORT_SYMBOL(imx_gpio_mode);
 101
 102int imx_gpio_request(unsigned gpio, const char *label)
 103{
 104        if(gpio >= (GPIO_PORT_MAX + 1) * 32) {
 105                printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n",
 106                        gpio, label ? label : "?");
 107                return -EINVAL;
 108        }
 109
 110        if(test_and_set_bit(gpio, imx_gpio_alloc_map)) {
 111                printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n",
 112                        gpio, label ? label : "?");
 113                return -EBUSY;
 114        }
 115
 116        return 0;
 117}
 118
 119EXPORT_SYMBOL(imx_gpio_request);
 120
 121void imx_gpio_free(unsigned gpio)
 122{
 123        if(gpio >= (GPIO_PORT_MAX + 1) * 32)
 124                return;
 125
 126        clear_bit(gpio, imx_gpio_alloc_map);
 127}
 128
 129EXPORT_SYMBOL(imx_gpio_free);
 130
 131int imx_gpio_direction_input(unsigned gpio)
 132{
 133        imx_gpio_mode(gpio | GPIO_IN | GPIO_GIUS | GPIO_DR);
 134        return 0;
 135}
 136
 137EXPORT_SYMBOL(imx_gpio_direction_input);
 138
 139int imx_gpio_direction_output(unsigned gpio, int value)
 140{
 141        imx_gpio_set_value(gpio, value);
 142        imx_gpio_mode(gpio | GPIO_OUT | GPIO_GIUS | GPIO_DR);
 143        return 0;
 144}
 145
 146EXPORT_SYMBOL(imx_gpio_direction_output);
 147
 148int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
 149                                int alloc_mode, const char *label)
 150{
 151        const int *p = pin_list;
 152        int i;
 153        unsigned gpio;
 154        unsigned mode;
 155
 156        for (i = 0; i < count; i++) {
 157                gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
 158                mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK);
 159
 160                if (gpio >= (GPIO_PORT_MAX + 1) * 32)
 161                        goto setup_error;
 162
 163                if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE)
 164                        imx_gpio_free(gpio);
 165                else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC))
 166                        if (imx_gpio_request(gpio, label))
 167                                if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
 168                                        goto setup_error;
 169
 170                if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY |
 171                                    IMX_GPIO_ALLOC_MODE_RELEASE)))
 172                        imx_gpio_mode(gpio | mode);
 173
 174                p++;
 175        }
 176        return 0;
 177
 178setup_error:
 179        if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC |
 180                         IMX_GPIO_ALLOC_MODE_TRY_ALLOC))
 181                return -EINVAL;
 182
 183        while (p != pin_list) {
 184                p--;
 185                gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK);
 186                imx_gpio_free(gpio);
 187        }
 188
 189        return -EINVAL;
 190}
 191
 192EXPORT_SYMBOL(imx_gpio_setup_multiple_pins);
 193
 194void __imx_gpio_set_value(unsigned gpio, int value)
 195{
 196        imx_gpio_set_value_inline(gpio, value);
 197}
 198
 199EXPORT_SYMBOL(__imx_gpio_set_value);
 200
 201int imx_gpio_to_irq(unsigned gpio)
 202{
 203        return IRQ_GPIOA(0) + gpio;
 204}
 205
 206EXPORT_SYMBOL(imx_gpio_to_irq);
 207
 208int imx_irq_to_gpio(unsigned irq)
 209{
 210        if (irq < IRQ_GPIOA(0))
 211                return -EINVAL;
 212        return irq - IRQ_GPIOA(0);
 213}
 214
 215EXPORT_SYMBOL(imx_irq_to_gpio);
 216
 217/*
 218 *  get the system pll clock in Hz
 219 *
 220 *                  mfi + mfn / (mfd +1)
 221 *  f = 2 * f_ref * --------------------
 222 *                        pd + 1
 223 */
 224static unsigned int imx_decode_pll(unsigned int pll, u32 f_ref)
 225{
 226        unsigned long long ll;
 227        unsigned long quot;
 228
 229        u32 mfi = (pll >> 10) & 0xf;
 230        u32 mfn = pll & 0x3ff;
 231        u32 mfd = (pll >> 16) & 0x3ff;
 232        u32 pd =  (pll >> 26) & 0xf;
 233
 234        mfi = mfi <= 5 ? 5 : mfi;
 235
 236        ll = 2 * (unsigned long long)f_ref * ( (mfi<<16) + (mfn<<16) / (mfd+1) );
 237        quot = (pd+1) * (1<<16);
 238        ll += quot / 2;
 239        do_div(ll, quot);
 240        return (unsigned int) ll;
 241}
 242
 243unsigned int imx_get_system_clk(void)
 244{
 245        u32 f_ref = (CSCR & CSCR_SYSTEM_SEL) ? 16000000 : (CLK32 * 512);
 246
 247        return imx_decode_pll(SPCTL0, f_ref);
 248}
 249EXPORT_SYMBOL(imx_get_system_clk);
 250
 251unsigned int imx_get_mcu_clk(void)
 252{
 253        return imx_decode_pll(MPCTL0, CLK32 * 512);
 254}
 255EXPORT_SYMBOL(imx_get_mcu_clk);
 256
 257/*
 258 *  get peripheral clock 1 ( UART[12], Timer[12], PWM )
 259 */
 260unsigned int imx_get_perclk1(void)
 261{
 262        return imx_get_system_clk() / (((PCDR) & 0xf)+1);
 263}
 264EXPORT_SYMBOL(imx_get_perclk1);
 265
 266/*
 267 *  get peripheral clock 2 ( LCD, SD, SPI[12] )
 268 */
 269unsigned int imx_get_perclk2(void)
 270{
 271        return imx_get_system_clk() / (((PCDR>>4) & 0xf)+1);
 272}
 273EXPORT_SYMBOL(imx_get_perclk2);
 274
 275/*
 276 *  get peripheral clock 3 ( SSI )
 277 */
 278unsigned int imx_get_perclk3(void)
 279{
 280        return imx_get_system_clk() / (((PCDR>>16) & 0x7f)+1);
 281}
 282EXPORT_SYMBOL(imx_get_perclk3);
 283
 284/*
 285 *  get hclk ( SDRAM, CSI, Memory Stick, I2C, DMA )
 286 */
 287unsigned int imx_get_hclk(void)
 288{
 289        return imx_get_system_clk() / (((CSCR>>10) & 0xf)+1);
 290}
 291EXPORT_SYMBOL(imx_get_hclk);
 292
 293static struct resource imx_mmc_resources[] = {
 294        [0] = {
 295                .start  = 0x00214000,
 296                .end    = 0x002140FF,
 297                .flags  = IORESOURCE_MEM,
 298        },
 299        [1] = {
 300                .start  = (SDHC_INT),
 301                .end    = (SDHC_INT),
 302                .flags  = IORESOURCE_IRQ,
 303        },
 304};
 305
 306static u64 imxmmmc_dmamask = 0xffffffffUL;
 307
 308static struct platform_device imx_mmc_device = {
 309        .name           = "imx-mmc",
 310        .id             = 0,
 311        .dev            = {
 312                .dma_mask = &imxmmmc_dmamask,
 313                .coherent_dma_mask = 0xffffffff,
 314        },
 315        .num_resources  = ARRAY_SIZE(imx_mmc_resources),
 316        .resource       = imx_mmc_resources,
 317};
 318
 319void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
 320{
 321        imx_mmc_device.dev.platform_data = info;
 322}
 323
 324static struct imxfb_mach_info imx_fb_info;
 325
 326void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
 327{
 328        memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imxfb_mach_info));
 329}
 330EXPORT_SYMBOL(set_imx_fb_info);
 331
 332static struct resource imxfb_resources[] = {
 333        [0] = {
 334                .start  = 0x00205000,
 335                .end    = 0x002050FF,
 336                .flags  = IORESOURCE_MEM,
 337        },
 338        [1] = {
 339                .start  = LCDC_INT,
 340                .end    = LCDC_INT,
 341                .flags  = IORESOURCE_IRQ,
 342        },
 343};
 344
 345static u64 fb_dma_mask = ~(u64)0;
 346
 347static struct platform_device imxfb_device = {
 348        .name           = "imx-fb",
 349        .id             = 0,
 350        .dev            = {
 351                .platform_data  = &imx_fb_info,
 352                .dma_mask       = &fb_dma_mask,
 353                .coherent_dma_mask = 0xffffffff,
 354        },
 355        .num_resources  = ARRAY_SIZE(imxfb_resources),
 356        .resource       = imxfb_resources,
 357};
 358
 359static struct platform_device *devices[] __initdata = {
 360        &imx_mmc_device,
 361        &imxfb_device,
 362};
 363
 364static struct map_desc imx_io_desc[] __initdata = {
 365        {
 366                .virtual        = IMX_IO_BASE,
 367                .pfn            = __phys_to_pfn(IMX_IO_PHYS),
 368                .length         = IMX_IO_SIZE,
 369                .type           = MT_DEVICE
 370        }
 371};
 372
 373void __init
 374imx_map_io(void)
 375{
 376        iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
 377}
 378
 379static int __init imx_init(void)
 380{
 381        return platform_add_devices(devices, ARRAY_SIZE(devices));
 382}
 383
 384subsys_initcall(imx_init);
 385