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