uboot/drivers/gpio/sh_pfc.c
<<
>>
Prefs
   1/*
   2 * Pinmuxed GPIO support for SuperH.
   3 * Copy from linux kernel driver/sh/pfc.c
   4 *
   5 * Copyright (C) 2008 Magnus Damm
   6 *
   7 * This file is subject to the terms and conditions of the GNU General Public
   8 * License.  See the file "COPYING" in the main directory of this archive
   9 * for more details.
  10 */
  11
  12#include <common.h>
  13#include <asm/bitops.h>
  14#include <asm/io.h>
  15#include <sh_pfc.h>
  16
  17static struct pinmux_info *gpioc;
  18
  19#define pfc_phys_to_virt(p, a) ((void *)a)
  20
  21static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
  22{
  23        if (enum_id < r->begin)
  24                return 0;
  25
  26        if (enum_id > r->end)
  27                return 0;
  28
  29        return 1;
  30}
  31
  32static unsigned long gpio_read_raw_reg(void *mapped_reg,
  33                                       unsigned long reg_width)
  34{
  35        switch (reg_width) {
  36
  37        case 8:
  38                return readb(mapped_reg);
  39        case 16:
  40                return readw(mapped_reg);
  41        case 32:
  42                return readl(mapped_reg);
  43        }
  44
  45        BUG();
  46        return 0;
  47}
  48
  49static void gpio_write_raw_reg(void *mapped_reg,
  50                               unsigned long reg_width,
  51                               unsigned long data)
  52{
  53        switch (reg_width) {
  54        case 8:
  55                writeb(data, mapped_reg);
  56                return;
  57        case 16:
  58                writew(data, mapped_reg);
  59                return;
  60        case 32:
  61                writel(data, mapped_reg);
  62                return;
  63        }
  64
  65        BUG();
  66}
  67
  68static int gpio_read_bit(struct pinmux_data_reg *dr,
  69                         unsigned long in_pos)
  70{
  71        unsigned long pos;
  72
  73        pos = dr->reg_width - (in_pos + 1);
  74
  75        debug("read_bit: addr = %lx, pos = %ld, "
  76                 "r_width = %ld\n", dr->reg, pos, dr->reg_width);
  77
  78        return
  79            (gpio_read_raw_reg(dr->mapped_reg + 0x4, dr->reg_width) >> pos) & 1;
  80}
  81
  82static void gpio_write_bit(struct pinmux_data_reg *dr,
  83                           unsigned long in_pos, unsigned long value)
  84{
  85        unsigned long pos;
  86
  87        pos = dr->reg_width - (in_pos + 1);
  88
  89        debug("write_bit addr = %lx, value = %d, pos = %ld, "
  90                 "r_width = %ld\n",
  91                 dr->reg, !!value, pos, dr->reg_width);
  92
  93        if (value)
  94                __set_bit(pos, &dr->reg_shadow);
  95        else
  96                __clear_bit(pos, &dr->reg_shadow);
  97
  98        gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
  99}
 100
 101static void config_reg_helper(struct pinmux_info *gpioc,
 102                              struct pinmux_cfg_reg *crp,
 103                              unsigned long in_pos,
 104#if 0
 105                              void __iomem **mapped_regp,
 106#else
 107                              void **mapped_regp,
 108#endif
 109                              unsigned long *maskp,
 110                              unsigned long *posp)
 111{
 112        int k;
 113
 114        *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
 115
 116        if (crp->field_width) {
 117                *maskp = (1 << crp->field_width) - 1;
 118                *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
 119        } else {
 120                *maskp = (1 << crp->var_field_width[in_pos]) - 1;
 121                *posp = crp->reg_width;
 122                for (k = 0; k <= in_pos; k++)
 123                        *posp -= crp->var_field_width[k];
 124        }
 125}
 126
 127static int read_config_reg(struct pinmux_info *gpioc,
 128                           struct pinmux_cfg_reg *crp,
 129                           unsigned long field)
 130{
 131        void *mapped_reg;
 132
 133        unsigned long mask, pos;
 134
 135        config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
 136
 137        debug("read_reg: addr = %lx, field = %ld, "
 138                 "r_width = %ld, f_width = %ld\n",
 139                 crp->reg, field, crp->reg_width, crp->field_width);
 140
 141        return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
 142}
 143
 144static void write_config_reg(struct pinmux_info *gpioc,
 145                             struct pinmux_cfg_reg *crp,
 146                             unsigned long field, unsigned long value)
 147{
 148        void *mapped_reg;
 149        unsigned long mask, pos, data;
 150
 151        config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
 152
 153        debug("write_reg addr = %lx, value = %ld, field = %ld, "
 154                 "r_width = %ld, f_width = %ld\n",
 155                 crp->reg, value, field, crp->reg_width, crp->field_width);
 156
 157        mask = ~(mask << pos);
 158        value = value << pos;
 159
 160        data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
 161        data &= mask;
 162        data |= value;
 163
 164        if (gpioc->unlock_reg)
 165                gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
 166                                   32, ~data);
 167
 168        gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
 169}
 170
 171static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
 172{
 173        struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
 174        struct pinmux_data_reg *data_reg;
 175        int k, n;
 176
 177        if (!enum_in_range(gpiop->enum_id, &gpioc->data))
 178                return -1;
 179
 180        k = 0;
 181        while (1) {
 182                data_reg = gpioc->data_regs + k;
 183
 184                if (!data_reg->reg_width)
 185                        break;
 186
 187                data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
 188
 189                for (n = 0; n < data_reg->reg_width; n++) {
 190                        if (data_reg->enum_ids[n] == gpiop->enum_id) {
 191                                gpiop->flags &= ~PINMUX_FLAG_DREG;
 192                                gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
 193                                gpiop->flags &= ~PINMUX_FLAG_DBIT;
 194                                gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
 195                                return 0;
 196                        }
 197                }
 198                k++;
 199        }
 200
 201        BUG();
 202
 203        return -1;
 204}
 205
 206static void setup_data_regs(struct pinmux_info *gpioc)
 207{
 208        struct pinmux_data_reg *drp;
 209        int k;
 210
 211        for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++)
 212                setup_data_reg(gpioc, k);
 213
 214        k = 0;
 215        while (1) {
 216                drp = gpioc->data_regs + k;
 217
 218                if (!drp->reg_width)
 219                        break;
 220
 221                drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
 222                                                    drp->reg_width);
 223                k++;
 224        }
 225}
 226
 227static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
 228                        struct pinmux_data_reg **drp, int *bitp)
 229{
 230        struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
 231        int k, n;
 232
 233        if (!enum_in_range(gpiop->enum_id, &gpioc->data))
 234                return -1;
 235
 236        k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
 237        n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
 238        *drp = gpioc->data_regs + k;
 239        *bitp = n;
 240        return 0;
 241}
 242
 243static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
 244                          struct pinmux_cfg_reg **crp,
 245                          int *fieldp, int *valuep,
 246                          unsigned long **cntp)
 247{
 248        struct pinmux_cfg_reg *config_reg;
 249        unsigned long r_width, f_width, curr_width, ncomb;
 250        int k, m, n, pos, bit_pos;
 251
 252        k = 0;
 253        while (1) {
 254                config_reg = gpioc->cfg_regs + k;
 255
 256                r_width = config_reg->reg_width;
 257                f_width = config_reg->field_width;
 258
 259                if (!r_width)
 260                        break;
 261
 262                pos = 0;
 263                m = 0;
 264                for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
 265                        if (f_width)
 266                                curr_width = f_width;
 267                        else
 268                                curr_width = config_reg->var_field_width[m];
 269
 270                        ncomb = 1 << curr_width;
 271                        for (n = 0; n < ncomb; n++) {
 272                                if (config_reg->enum_ids[pos + n] == enum_id) {
 273                                        *crp = config_reg;
 274                                        *fieldp = m;
 275                                        *valuep = n;
 276                                        *cntp = &config_reg->cnt[m];
 277                                        return 0;
 278                                }
 279                        }
 280                        pos += ncomb;
 281                        m++;
 282                }
 283                k++;
 284        }
 285
 286        return -1;
 287}
 288
 289static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
 290                            int pos, pinmux_enum_t *enum_idp)
 291{
 292        pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
 293        pinmux_enum_t *data = gpioc->gpio_data;
 294        int k;
 295
 296        if (!enum_in_range(enum_id, &gpioc->data)) {
 297                if (!enum_in_range(enum_id, &gpioc->mark)) {
 298                        debug("non data/mark enum_id for gpio %d\n", gpio);
 299                        return -1;
 300                }
 301        }
 302
 303        if (pos) {
 304                *enum_idp = data[pos + 1];
 305                return pos + 1;
 306        }
 307
 308        for (k = 0; k < gpioc->gpio_data_size; k++) {
 309                if (data[k] == enum_id) {
 310                        *enum_idp = data[k + 1];
 311                        return k + 1;
 312                }
 313        }
 314
 315        debug("cannot locate data/mark enum_id for gpio %d\n", gpio);
 316        return -1;
 317}
 318
 319enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
 320
 321static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
 322                              int pinmux_type, int cfg_mode)
 323{
 324        struct pinmux_cfg_reg *cr = NULL;
 325        pinmux_enum_t enum_id;
 326        struct pinmux_range *range;
 327        int in_range, pos, field, value;
 328        unsigned long *cntp;
 329
 330        switch (pinmux_type) {
 331
 332        case PINMUX_TYPE_FUNCTION:
 333                range = NULL;
 334                break;
 335
 336        case PINMUX_TYPE_OUTPUT:
 337                range = &gpioc->output;
 338                break;
 339
 340        case PINMUX_TYPE_INPUT:
 341                range = &gpioc->input;
 342                break;
 343
 344        case PINMUX_TYPE_INPUT_PULLUP:
 345                range = &gpioc->input_pu;
 346                break;
 347
 348        case PINMUX_TYPE_INPUT_PULLDOWN:
 349                range = &gpioc->input_pd;
 350                break;
 351
 352        default:
 353                goto out_err;
 354        }
 355
 356        pos = 0;
 357        enum_id = 0;
 358        field = 0;
 359        value = 0;
 360        while (1) {
 361                pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
 362                if (pos <= 0)
 363                        goto out_err;
 364
 365                if (!enum_id)
 366                        break;
 367
 368                /* first check if this is a function enum */
 369                in_range = enum_in_range(enum_id, &gpioc->function);
 370                if (!in_range) {
 371                        /* not a function enum */
 372                        if (range) {
 373                                /*
 374                                 * other range exists, so this pin is
 375                                 * a regular GPIO pin that now is being
 376                                 * bound to a specific direction.
 377                                 *
 378                                 * for this case we only allow function enums
 379                                 * and the enums that match the other range.
 380                                 */
 381                                in_range = enum_in_range(enum_id, range);
 382
 383                                /*
 384                                 * special case pass through for fixed
 385                                 * input-only or output-only pins without
 386                                 * function enum register association.
 387                                 */
 388                                if (in_range && enum_id == range->force)
 389                                        continue;
 390                        } else {
 391                                /*
 392                                 * no other range exists, so this pin
 393                                 * must then be of the function type.
 394                                 *
 395                                 * allow function type pins to select
 396                                 * any combination of function/in/out
 397                                 * in their MARK lists.
 398                                 */
 399                                in_range = 1;
 400                        }
 401                }
 402
 403                if (!in_range)
 404                        continue;
 405
 406                if (get_config_reg(gpioc, enum_id, &cr,
 407                                   &field, &value, &cntp) != 0)
 408                        goto out_err;
 409
 410                switch (cfg_mode) {
 411                case GPIO_CFG_DRYRUN:
 412                        if (!*cntp ||
 413                            (read_config_reg(gpioc, cr, field) != value))
 414                                continue;
 415                        break;
 416
 417                case GPIO_CFG_REQ:
 418                        write_config_reg(gpioc, cr, field, value);
 419                        *cntp = *cntp + 1;
 420                        break;
 421
 422                case GPIO_CFG_FREE:
 423                        *cntp = *cntp - 1;
 424                        break;
 425                }
 426        }
 427
 428        return 0;
 429 out_err:
 430        return -1;
 431}
 432
 433#if 0
 434static DEFINE_SPINLOCK(gpio_lock);
 435static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip)
 436{
 437        return container_of(chip, struct pinmux_info, chip);
 438}
 439#endif
 440
 441static int sh_gpio_request(unsigned offset)
 442{
 443        struct pinmux_data_reg *dummy;
 444        int i, ret, pinmux_type;
 445
 446        ret = -1;
 447
 448        if (!gpioc)
 449                goto err_out;
 450
 451        if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
 452                goto err_out;
 453
 454        /* setup pin function here if no data is associated with pin */
 455
 456        if (get_data_reg(gpioc, offset, &dummy, &i) != 0)
 457                pinmux_type = PINMUX_TYPE_FUNCTION;
 458        else
 459                pinmux_type = PINMUX_TYPE_GPIO;
 460
 461        if (pinmux_type == PINMUX_TYPE_FUNCTION) {
 462                if (pinmux_config_gpio(gpioc, offset,
 463                                       pinmux_type,
 464                                       GPIO_CFG_DRYRUN) != 0)
 465                        goto err_out;
 466
 467                if (pinmux_config_gpio(gpioc, offset,
 468                                       pinmux_type,
 469                                       GPIO_CFG_REQ) != 0)
 470                        BUG();
 471        }
 472
 473        gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
 474        gpioc->gpios[offset].flags |= pinmux_type;
 475
 476        ret = 0;
 477err_out:
 478        return ret;
 479}
 480
 481static void sh_gpio_free(unsigned offset)
 482{
 483        int pinmux_type;
 484
 485        if (!gpioc)
 486                return;
 487
 488        pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE;
 489        pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE);
 490        gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
 491        gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE;
 492}
 493
 494static int pinmux_direction(struct pinmux_info *gpioc,
 495                            unsigned gpio, int new_pinmux_type)
 496{
 497        int pinmux_type;
 498        int ret = -1;
 499
 500        if (!gpioc)
 501                goto err_out;
 502
 503        pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
 504
 505        switch (pinmux_type) {
 506        case PINMUX_TYPE_GPIO:
 507                break;
 508        case PINMUX_TYPE_OUTPUT:
 509        case PINMUX_TYPE_INPUT:
 510        case PINMUX_TYPE_INPUT_PULLUP:
 511        case PINMUX_TYPE_INPUT_PULLDOWN:
 512                pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
 513                break;
 514        default:
 515                goto err_out;
 516        }
 517
 518        if (pinmux_config_gpio(gpioc, gpio,
 519                               new_pinmux_type,
 520                               GPIO_CFG_DRYRUN) != 0)
 521                goto err_out;
 522
 523        if (pinmux_config_gpio(gpioc, gpio,
 524                               new_pinmux_type,
 525                               GPIO_CFG_REQ) != 0)
 526                BUG();
 527
 528        gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
 529        gpioc->gpios[gpio].flags |= new_pinmux_type;
 530
 531        ret = 0;
 532 err_out:
 533        return ret;
 534}
 535
 536static int sh_gpio_direction_input(unsigned offset)
 537{
 538        return pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT);
 539}
 540
 541static void sh_gpio_set_value(struct pinmux_info *gpioc,
 542                             unsigned gpio, int value)
 543{
 544        struct pinmux_data_reg *dr = NULL;
 545        int bit = 0;
 546
 547        if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
 548                BUG();
 549        else
 550                gpio_write_bit(dr, bit, value);
 551}
 552
 553static int sh_gpio_direction_output(unsigned offset, int value)
 554{
 555        sh_gpio_set_value(gpioc, offset, value);
 556        return pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT);
 557}
 558
 559static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
 560{
 561        struct pinmux_data_reg *dr = NULL;
 562        int bit = 0;
 563
 564        if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
 565                return -1;
 566
 567        return gpio_read_bit(dr, bit);
 568}
 569
 570static int sh_gpio_get(unsigned offset)
 571{
 572        return sh_gpio_get_value(gpioc, offset);
 573}
 574
 575static void sh_gpio_set(unsigned offset, int value)
 576{
 577        sh_gpio_set_value(gpioc, offset, value);
 578}
 579
 580int register_pinmux(struct pinmux_info *pip)
 581{
 582        if (pip != NULL) {
 583                gpioc = pip;
 584                debug("%s deregistering\n", pip->name);
 585                setup_data_regs(gpioc);
 586        }
 587        return 0;
 588}
 589
 590int unregister_pinmux(struct pinmux_info *pip)
 591{
 592        debug("%s deregistering\n", pip->name);
 593        if (gpioc != pip)
 594                return -1;
 595
 596        gpioc = NULL;
 597        return 0;
 598}
 599
 600int gpio_request(unsigned gpio, const char *label)
 601{
 602        sh_gpio_request(gpio);
 603        return 0;
 604}
 605
 606int gpio_free(unsigned gpio)
 607{
 608        sh_gpio_free(gpio);
 609        return 0;
 610}
 611
 612int gpio_direction_input(unsigned gpio)
 613{
 614        return sh_gpio_direction_input(gpio);
 615}
 616
 617int gpio_direction_output(unsigned gpio, int value)
 618{
 619        return sh_gpio_direction_output(gpio, value);
 620}
 621
 622void gpio_set_value(unsigned gpio, int value)
 623{
 624        sh_gpio_set(gpio, value);
 625}
 626
 627int gpio_get_value(unsigned gpio)
 628{
 629        return sh_gpio_get(gpio);
 630}
 631