uboot/board/st-ericsson/u8500/gpio.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) ST-Ericsson SA 2009
   3 *
   4 * See file CREDITS for list of people who contributed to this
   5 * project.
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License as
   9 * published by the Free Software Foundation; either version 2 of
  10 * the License, or (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 * MA 02111-1307 USA
  21 */
  22
  23#include <common.h>
  24#include <asm/arch/gpio.h>
  25
  26static struct gpio_register *addr_gpio_register[] = {
  27        (void *)U8500_GPIO_0_BASE,
  28        (void *)U8500_GPIO_1_BASE,
  29        (void *)U8500_GPIO_2_BASE,
  30        (void *)U8500_GPIO_3_BASE,
  31        (void *)U8500_GPIO_4_BASE,
  32        (void *)U8500_GPIO_5_BASE,
  33        (void *)U8500_GPIO_6_BASE,
  34        (void *)U8500_GPIO_7_BASE,
  35        (void *)U8500_GPIO_8_BASE,
  36};
  37
  38struct gpio_altfun_data altfun_table[] = {
  39        {
  40                .altfun = GPIO_ALT_I2C_0,
  41                .start = 147,
  42                .end = 148,
  43                .cont = 0,
  44                .type = GPIO_ALTF_A,
  45        },
  46        {
  47                .altfun = GPIO_ALT_I2C_1,
  48                .start = 16,
  49                .end = 17,
  50                .cont = 0,
  51                .type = GPIO_ALTF_B,
  52        },
  53        {
  54                .altfun = GPIO_ALT_I2C_2,
  55                .start = 10,
  56                .end = 11,
  57                .cont = 0,
  58                .type = GPIO_ALTF_B,
  59        },
  60        {
  61                .altfun = GPIO_ALT_I2C_3,
  62                .start = 229,
  63                .end = 230,
  64                .cont = 0,
  65                .type = GPIO_ALTF_C,
  66        },
  67        {
  68                .altfun = GPIO_ALT_UART_0_MODEM,
  69                .start = 0,
  70                .end = 3,
  71                .cont = 1,
  72                .type = GPIO_ALTF_A,
  73        },
  74        {
  75                .altfun = GPIO_ALT_UART_0_MODEM,
  76                .start = 33,
  77                .end = 36,
  78                .cont = 0,
  79                .type = GPIO_ALTF_C,
  80        },
  81        {
  82                .altfun = GPIO_ALT_UART_1,
  83                .start = 4,
  84                .end = 7,
  85                .cont = 0,
  86                .type =
  87                        GPIO_ALTF_A,
  88        },
  89        {
  90                .altfun = GPIO_ALT_UART_2,
  91                .start = 18,
  92                .end = 19,
  93                .cont = 1,
  94                .type = GPIO_ALTF_B,
  95        },
  96        {
  97                .altfun = GPIO_ALT_UART_2,
  98                .start = 29,
  99                .end = 32,
 100                .cont = 0,
 101                .type = GPIO_ALTF_C,
 102        },
 103        {
 104                .altfun = GPIO_ALT_MSP_0,
 105                .start = 12,
 106                .end = 17,
 107                .cont = 1,
 108                .type = GPIO_ALTF_A,
 109        },
 110        {
 111                .altfun = GPIO_ALT_MSP_0,
 112                .start = 21,
 113                .end = 21,
 114                .cont = 0,
 115                .type = GPIO_ALTF_B,
 116        },
 117        {
 118                .altfun = GPIO_ALT_MSP_1,
 119                .start = 33,
 120                .end = 36,
 121                .cont = 0,
 122                .type = GPIO_ALTF_A,
 123        },
 124        {
 125                .altfun = GPIO_ALT_MSP_2,
 126                .start = 192,
 127                .end = 196,
 128                .cont = 0,
 129                .type = GPIO_ALTF_A,
 130        },
 131        {
 132                .altfun = GPIO_ALT_LCD_PANEL,
 133                .start = 64,
 134                .end = 93,
 135                .cont = 1,
 136                .type = GPIO_ALTF_A,
 137        },
 138        {
 139                .altfun = GPIO_ALT_LCD_PANEL,
 140                .start = 150,
 141                .end = 171,
 142                .cont = 0,
 143                .type = GPIO_ALTF_B,
 144        },
 145        {
 146                .altfun = GPIO_ALT_SD_CARD0,
 147                .start = 18,
 148                .end = 28,
 149                .cont = 0,
 150                .type = GPIO_ALTF_A,
 151        },
 152        {
 153                .altfun = GPIO_ALT_MM_CARD0,
 154                .start = 18,
 155                .end = 32,
 156                .cont = 0,
 157                .type = GPIO_ALTF_A,
 158        },
 159        {
 160                .altfun = GPIO_ALT_USB_OTG,
 161                .start = 256,
 162                .end = 267,
 163                .cont = 0,
 164                .type = GPIO_ALTF_A,
 165        },
 166        {
 167                .altfun = GPIO_ALT_EMMC,
 168                .start = 197,
 169                .end = 207,
 170                .cont = 0,
 171                .type = GPIO_ALTF_A,
 172        },
 173        {
 174                .altfun = GPIO_ALT_POP_EMMC,
 175                .start = 128,
 176                .end = 138,
 177                .cont = 0,
 178                .type = GPIO_ALTF_A,
 179        },
 180};
 181
 182/*
 183 * Static Function declarations
 184 */
 185enum gpio_error gpio_setpinconfig(int pin_id, struct gpio_config *config)
 186{
 187        struct gpio_register *p_gpio_register =
 188            addr_gpio_register[GPIO_BLOCK(pin_id)];
 189        u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
 190        enum gpio_error error = GPIO_OK;
 191        u32 temp_reg;
 192
 193        switch (config->mode) {
 194        case GPIO_ALTF_A:
 195                temp_reg = readl(&p_gpio_register->gpio_afsa);
 196                temp_reg |= mask;
 197                writel(temp_reg, &p_gpio_register->gpio_afsa);
 198                temp_reg = readl(&p_gpio_register->gpio_afsb);
 199                temp_reg &= ~mask;
 200                writel(temp_reg, &p_gpio_register->gpio_afsb);
 201                break;
 202        case GPIO_ALTF_B:
 203                temp_reg = readl(&p_gpio_register->gpio_afsa);
 204                temp_reg &= ~mask;
 205                writel(temp_reg, &p_gpio_register->gpio_afsa);
 206                temp_reg = readl(&p_gpio_register->gpio_afsb);
 207                temp_reg |= mask;
 208                writel(temp_reg, &p_gpio_register->gpio_afsb);
 209                break;
 210        case GPIO_ALTF_C:
 211                temp_reg = readl(&p_gpio_register->gpio_afsa);
 212                temp_reg |= mask;
 213                writel(temp_reg, &p_gpio_register->gpio_afsa);
 214                temp_reg = readl(&p_gpio_register->gpio_afsb);
 215                temp_reg |= mask;
 216                writel(temp_reg, &p_gpio_register->gpio_afsb);
 217                break;
 218        case GPIO_MODE_SOFTWARE:
 219                temp_reg = readl(&p_gpio_register->gpio_afsa);
 220                temp_reg &= ~mask;
 221                writel(temp_reg, &p_gpio_register->gpio_afsa);
 222                temp_reg = readl(&p_gpio_register->gpio_afsb);
 223                temp_reg &= ~mask;
 224                writel(temp_reg, &p_gpio_register->gpio_afsb);
 225
 226                switch (config->direction) {
 227                case GPIO_DIR_INPUT:
 228                        writel(mask, &p_gpio_register->gpio_dirc);
 229                        break;
 230                case GPIO_DIR_OUTPUT:
 231                        writel(mask, &p_gpio_register->gpio_dirs);
 232                        break;
 233                case GPIO_DIR_LEAVE_UNCHANGED:
 234                        break;
 235                default:
 236                        return GPIO_INVALID_PARAMETER;
 237                }
 238
 239                break;
 240        case GPIO_MODE_LEAVE_UNCHANGED:
 241                break;
 242        default:
 243                return GPIO_INVALID_PARAMETER;
 244        }
 245        return error;
 246}
 247
 248enum gpio_error gpio_resetgpiopin(int pin_id, char *dev_name)
 249{
 250        struct gpio_register *p_gpio_register =
 251            addr_gpio_register[GPIO_BLOCK(pin_id)];
 252        u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
 253        enum gpio_error error = GPIO_OK;
 254        u32 temp_reg;
 255
 256        temp_reg = readl(&p_gpio_register->gpio_afsa);
 257        temp_reg &= ~mask;
 258        writel(temp_reg, &p_gpio_register->gpio_afsa);
 259        temp_reg = readl(&p_gpio_register->gpio_afsb);
 260        temp_reg &= ~mask;
 261        writel(temp_reg, &p_gpio_register->gpio_afsb);
 262        writel(mask, &p_gpio_register->gpio_dirc);
 263
 264        return error;
 265}
 266
 267struct gpio_config altfun_pinconfig;
 268enum gpio_error gpio_altfunction(enum gpio_alt_function alt_func,
 269                            int which_altfunc, char *dev_name)
 270{
 271        int i, j, start, end;
 272        enum gpio_error error = -1;
 273
 274        for (i = 0; i < ARRAY_SIZE(altfun_table); i++) {
 275                if (altfun_table[i].altfun != alt_func)
 276                        continue;
 277
 278                start = altfun_table[i].start;
 279                end = altfun_table[i].end;
 280                for (j = start; j <= end; j++) {
 281                        if (which_altfunc == GPIO_ALTF_FIND)
 282                                altfun_pinconfig.mode = altfun_table[i].type;
 283                        else
 284                                altfun_pinconfig.mode = which_altfunc;
 285                        altfun_pinconfig.direction = GPIO_DIR_OUTPUT;
 286                        altfun_pinconfig.dev_name = dev_name;
 287
 288                        if (which_altfunc != GPIO_ALTF_DISABLE)
 289                                error = gpio_setpinconfig(j, &altfun_pinconfig);
 290                        else
 291                                error = gpio_resetgpiopin(j, dev_name);
 292                        if (!error)
 293                                continue;
 294                        printf("GPIO %d configuration failure (nmdk_error:%d)",
 295                                j, error);
 296                        error = GPIO_INVALID_PARAMETER;
 297                        return error;
 298                }
 299
 300                if (!altfun_table[i].cont)
 301                        break;
 302        }
 303        return error;
 304}
 305
 306int gpio_writepin(int pin_id, enum gpio_data value, char *dev_name)
 307{
 308        struct gpio_register *p_gpio_register =
 309            addr_gpio_register[GPIO_BLOCK(pin_id)];
 310        u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
 311
 312        switch (value) {
 313        case GPIO_DATA_HIGH:
 314                writel(mask, &p_gpio_register->gpio_dats);
 315                break;
 316        case GPIO_DATA_LOW:
 317                writel(mask, &p_gpio_register->gpio_datc);
 318                break;
 319        default:
 320                printf("Invalid value passed in %s", __FUNCTION__);
 321                return GPIO_INVALID_PARAMETER;
 322        }
 323        return GPIO_OK;
 324}
 325
 326int gpio_readpin(int pin_id, enum gpio_data *rv)
 327{
 328        struct gpio_register *p_gpio_register =
 329            addr_gpio_register[GPIO_BLOCK(pin_id)];
 330        u32 mask = 1UL << (pin_id % GPIO_PINS_PER_BLOCK);
 331
 332        if ((readl(&p_gpio_register->gpio_dat) & mask) != 0)
 333                *rv = GPIO_DATA_HIGH;
 334        else
 335                *rv = GPIO_DATA_LOW;
 336        return GPIO_OK;
 337}
 338
 339int gpio_altfuncenable(enum gpio_alt_function altfunc, char *dev_name)
 340{
 341        return (int)gpio_altfunction(altfunc, GPIO_ALTF_FIND, dev_name);
 342}
 343
 344int gpio_altfuncdisable(enum gpio_alt_function altfunc, char *dev_name)
 345{
 346        return (int)gpio_altfunction(altfunc, GPIO_ALTF_DISABLE, dev_name);
 347}
 348