linux/drivers/pinctrl/pinctrl-tegra.c
<<
>>
Prefs
   1/*
   2 * Driver for the NVIDIA Tegra pinmux
   3 *
   4 * Copyright (c) 2011-2012, NVIDIA CORPORATION.  All rights reserved.
   5 *
   6 * Derived from code:
   7 * Copyright (C) 2010 Google, Inc.
   8 * Copyright (C) 2010 NVIDIA Corporation
   9 * Copyright (C) 2009-2011 ST-Ericsson AB
  10 *
  11 * This program is free software; you can redistribute it and/or modify it
  12 * under the terms and conditions of the GNU General Public License,
  13 * version 2, as published by the Free Software Foundation.
  14 *
  15 * This program is distributed in the hope it will be useful, but WITHOUT
  16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  18 * more details.
  19 */
  20
  21#include <linux/err.h>
  22#include <linux/init.h>
  23#include <linux/io.h>
  24#include <linux/module.h>
  25#include <linux/of.h>
  26#include <linux/platform_device.h>
  27#include <linux/pinctrl/machine.h>
  28#include <linux/pinctrl/pinctrl.h>
  29#include <linux/pinctrl/pinmux.h>
  30#include <linux/pinctrl/pinconf.h>
  31#include <linux/slab.h>
  32
  33#include "core.h"
  34#include "pinctrl-tegra.h"
  35#include "pinctrl-utils.h"
  36
  37struct tegra_pmx {
  38        struct device *dev;
  39        struct pinctrl_dev *pctl;
  40
  41        const struct tegra_pinctrl_soc_data *soc;
  42
  43        int nbanks;
  44        void __iomem **regs;
  45};
  46
  47static inline u32 pmx_readl(struct tegra_pmx *pmx, u32 bank, u32 reg)
  48{
  49        return readl(pmx->regs[bank] + reg);
  50}
  51
  52static inline void pmx_writel(struct tegra_pmx *pmx, u32 val, u32 bank, u32 reg)
  53{
  54        writel(val, pmx->regs[bank] + reg);
  55}
  56
  57static int tegra_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
  58{
  59        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
  60
  61        return pmx->soc->ngroups;
  62}
  63
  64static const char *tegra_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
  65                                                unsigned group)
  66{
  67        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
  68
  69        return pmx->soc->groups[group].name;
  70}
  71
  72static int tegra_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
  73                                        unsigned group,
  74                                        const unsigned **pins,
  75                                        unsigned *num_pins)
  76{
  77        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
  78
  79        *pins = pmx->soc->groups[group].pins;
  80        *num_pins = pmx->soc->groups[group].npins;
  81
  82        return 0;
  83}
  84
  85#ifdef CONFIG_DEBUG_FS
  86static void tegra_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
  87                                       struct seq_file *s,
  88                                       unsigned offset)
  89{
  90        seq_printf(s, " %s", dev_name(pctldev->dev));
  91}
  92#endif
  93
  94static const struct cfg_param {
  95        const char *property;
  96        enum tegra_pinconf_param param;
  97} cfg_params[] = {
  98        {"nvidia,pull",                 TEGRA_PINCONF_PARAM_PULL},
  99        {"nvidia,tristate",             TEGRA_PINCONF_PARAM_TRISTATE},
 100        {"nvidia,enable-input",         TEGRA_PINCONF_PARAM_ENABLE_INPUT},
 101        {"nvidia,open-drain",           TEGRA_PINCONF_PARAM_OPEN_DRAIN},
 102        {"nvidia,lock",                 TEGRA_PINCONF_PARAM_LOCK},
 103        {"nvidia,io-reset",             TEGRA_PINCONF_PARAM_IORESET},
 104        {"nvidia,rcv-sel",              TEGRA_PINCONF_PARAM_RCV_SEL},
 105        {"nvidia,high-speed-mode",      TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE},
 106        {"nvidia,schmitt",              TEGRA_PINCONF_PARAM_SCHMITT},
 107        {"nvidia,low-power-mode",       TEGRA_PINCONF_PARAM_LOW_POWER_MODE},
 108        {"nvidia,pull-down-strength",   TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH},
 109        {"nvidia,pull-up-strength",     TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH},
 110        {"nvidia,slew-rate-falling",    TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING},
 111        {"nvidia,slew-rate-rising",     TEGRA_PINCONF_PARAM_SLEW_RATE_RISING},
 112        {"nvidia,drive-type",           TEGRA_PINCONF_PARAM_DRIVE_TYPE},
 113};
 114
 115static int tegra_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
 116                                           struct device_node *np,
 117                                           struct pinctrl_map **map,
 118                                           unsigned *reserved_maps,
 119                                           unsigned *num_maps)
 120{
 121        struct device *dev = pctldev->dev;
 122        int ret, i;
 123        const char *function;
 124        u32 val;
 125        unsigned long config;
 126        unsigned long *configs = NULL;
 127        unsigned num_configs = 0;
 128        unsigned reserve;
 129        struct property *prop;
 130        const char *group;
 131
 132        ret = of_property_read_string(np, "nvidia,function", &function);
 133        if (ret < 0) {
 134                /* EINVAL=missing, which is fine since it's optional */
 135                if (ret != -EINVAL)
 136                        dev_err(dev,
 137                                "could not parse property nvidia,function\n");
 138                function = NULL;
 139        }
 140
 141        for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
 142                ret = of_property_read_u32(np, cfg_params[i].property, &val);
 143                if (!ret) {
 144                        config = TEGRA_PINCONF_PACK(cfg_params[i].param, val);
 145                        ret = pinctrl_utils_add_config(pctldev, &configs,
 146                                        &num_configs, config);
 147                        if (ret < 0)
 148                                goto exit;
 149                /* EINVAL=missing, which is fine since it's optional */
 150                } else if (ret != -EINVAL) {
 151                        dev_err(dev, "could not parse property %s\n",
 152                                cfg_params[i].property);
 153                }
 154        }
 155
 156        reserve = 0;
 157        if (function != NULL)
 158                reserve++;
 159        if (num_configs)
 160                reserve++;
 161        ret = of_property_count_strings(np, "nvidia,pins");
 162        if (ret < 0) {
 163                dev_err(dev, "could not parse property nvidia,pins\n");
 164                goto exit;
 165        }
 166        reserve *= ret;
 167
 168        ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps,
 169                                        num_maps, reserve);
 170        if (ret < 0)
 171                goto exit;
 172
 173        of_property_for_each_string(np, "nvidia,pins", prop, group) {
 174                if (function) {
 175                        ret = pinctrl_utils_add_map_mux(pctldev, map,
 176                                        reserved_maps, num_maps, group,
 177                                        function);
 178                        if (ret < 0)
 179                                goto exit;
 180                }
 181
 182                if (num_configs) {
 183                        ret = pinctrl_utils_add_map_configs(pctldev, map,
 184                                        reserved_maps, num_maps, group,
 185                                        configs, num_configs,
 186                                        PIN_MAP_TYPE_CONFIGS_GROUP);
 187                        if (ret < 0)
 188                                goto exit;
 189                }
 190        }
 191
 192        ret = 0;
 193
 194exit:
 195        kfree(configs);
 196        return ret;
 197}
 198
 199static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
 200                                        struct device_node *np_config,
 201                                        struct pinctrl_map **map,
 202                                        unsigned *num_maps)
 203{
 204        unsigned reserved_maps;
 205        struct device_node *np;
 206        int ret;
 207
 208        reserved_maps = 0;
 209        *map = NULL;
 210        *num_maps = 0;
 211
 212        for_each_child_of_node(np_config, np) {
 213                ret = tegra_pinctrl_dt_subnode_to_map(pctldev, np, map,
 214                                                      &reserved_maps, num_maps);
 215                if (ret < 0) {
 216                        pinctrl_utils_dt_free_map(pctldev, *map,
 217                                *num_maps);
 218                        return ret;
 219                }
 220        }
 221
 222        return 0;
 223}
 224
 225static const struct pinctrl_ops tegra_pinctrl_ops = {
 226        .get_groups_count = tegra_pinctrl_get_groups_count,
 227        .get_group_name = tegra_pinctrl_get_group_name,
 228        .get_group_pins = tegra_pinctrl_get_group_pins,
 229#ifdef CONFIG_DEBUG_FS
 230        .pin_dbg_show = tegra_pinctrl_pin_dbg_show,
 231#endif
 232        .dt_node_to_map = tegra_pinctrl_dt_node_to_map,
 233        .dt_free_map = pinctrl_utils_dt_free_map,
 234};
 235
 236static int tegra_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
 237{
 238        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 239
 240        return pmx->soc->nfunctions;
 241}
 242
 243static const char *tegra_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
 244                                               unsigned function)
 245{
 246        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 247
 248        return pmx->soc->functions[function].name;
 249}
 250
 251static int tegra_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
 252                                         unsigned function,
 253                                         const char * const **groups,
 254                                         unsigned * const num_groups)
 255{
 256        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 257
 258        *groups = pmx->soc->functions[function].groups;
 259        *num_groups = pmx->soc->functions[function].ngroups;
 260
 261        return 0;
 262}
 263
 264static int tegra_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned function,
 265                               unsigned group)
 266{
 267        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 268        const struct tegra_pingroup *g;
 269        int i;
 270        u32 val;
 271
 272        g = &pmx->soc->groups[group];
 273
 274        if (WARN_ON(g->mux_reg < 0))
 275                return -EINVAL;
 276
 277        for (i = 0; i < ARRAY_SIZE(g->funcs); i++) {
 278                if (g->funcs[i] == function)
 279                        break;
 280        }
 281        if (WARN_ON(i == ARRAY_SIZE(g->funcs)))
 282                return -EINVAL;
 283
 284        val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
 285        val &= ~(0x3 << g->mux_bit);
 286        val |= i << g->mux_bit;
 287        pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
 288
 289        return 0;
 290}
 291
 292static void tegra_pinctrl_disable(struct pinctrl_dev *pctldev,
 293                                  unsigned function, unsigned group)
 294{
 295        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 296        const struct tegra_pingroup *g;
 297        u32 val;
 298
 299        g = &pmx->soc->groups[group];
 300
 301        if (WARN_ON(g->mux_reg < 0))
 302                return;
 303
 304        val = pmx_readl(pmx, g->mux_bank, g->mux_reg);
 305        val &= ~(0x3 << g->mux_bit);
 306        val |= g->func_safe << g->mux_bit;
 307        pmx_writel(pmx, val, g->mux_bank, g->mux_reg);
 308}
 309
 310static const struct pinmux_ops tegra_pinmux_ops = {
 311        .get_functions_count = tegra_pinctrl_get_funcs_count,
 312        .get_function_name = tegra_pinctrl_get_func_name,
 313        .get_function_groups = tegra_pinctrl_get_func_groups,
 314        .enable = tegra_pinctrl_enable,
 315        .disable = tegra_pinctrl_disable,
 316};
 317
 318static int tegra_pinconf_reg(struct tegra_pmx *pmx,
 319                             const struct tegra_pingroup *g,
 320                             enum tegra_pinconf_param param,
 321                             bool report_err,
 322                             s8 *bank, s16 *reg, s8 *bit, s8 *width)
 323{
 324        switch (param) {
 325        case TEGRA_PINCONF_PARAM_PULL:
 326                *bank = g->pupd_bank;
 327                *reg = g->pupd_reg;
 328                *bit = g->pupd_bit;
 329                *width = 2;
 330                break;
 331        case TEGRA_PINCONF_PARAM_TRISTATE:
 332                *bank = g->tri_bank;
 333                *reg = g->tri_reg;
 334                *bit = g->tri_bit;
 335                *width = 1;
 336                break;
 337        case TEGRA_PINCONF_PARAM_ENABLE_INPUT:
 338                *bank = g->einput_bank;
 339                *reg = g->einput_reg;
 340                *bit = g->einput_bit;
 341                *width = 1;
 342                break;
 343        case TEGRA_PINCONF_PARAM_OPEN_DRAIN:
 344                *bank = g->odrain_bank;
 345                *reg = g->odrain_reg;
 346                *bit = g->odrain_bit;
 347                *width = 1;
 348                break;
 349        case TEGRA_PINCONF_PARAM_LOCK:
 350                *bank = g->lock_bank;
 351                *reg = g->lock_reg;
 352                *bit = g->lock_bit;
 353                *width = 1;
 354                break;
 355        case TEGRA_PINCONF_PARAM_IORESET:
 356                *bank = g->ioreset_bank;
 357                *reg = g->ioreset_reg;
 358                *bit = g->ioreset_bit;
 359                *width = 1;
 360                break;
 361        case TEGRA_PINCONF_PARAM_RCV_SEL:
 362                *bank = g->rcv_sel_bank;
 363                *reg = g->rcv_sel_reg;
 364                *bit = g->rcv_sel_bit;
 365                *width = 1;
 366                break;
 367        case TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE:
 368                *bank = g->drv_bank;
 369                *reg = g->drv_reg;
 370                *bit = g->hsm_bit;
 371                *width = 1;
 372                break;
 373        case TEGRA_PINCONF_PARAM_SCHMITT:
 374                *bank = g->drv_bank;
 375                *reg = g->drv_reg;
 376                *bit = g->schmitt_bit;
 377                *width = 1;
 378                break;
 379        case TEGRA_PINCONF_PARAM_LOW_POWER_MODE:
 380                *bank = g->drv_bank;
 381                *reg = g->drv_reg;
 382                *bit = g->lpmd_bit;
 383                *width = 2;
 384                break;
 385        case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
 386                *bank = g->drv_bank;
 387                *reg = g->drv_reg;
 388                *bit = g->drvdn_bit;
 389                *width = g->drvdn_width;
 390                break;
 391        case TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH:
 392                *bank = g->drv_bank;
 393                *reg = g->drv_reg;
 394                *bit = g->drvup_bit;
 395                *width = g->drvup_width;
 396                break;
 397        case TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING:
 398                *bank = g->drv_bank;
 399                *reg = g->drv_reg;
 400                *bit = g->slwf_bit;
 401                *width = g->slwf_width;
 402                break;
 403        case TEGRA_PINCONF_PARAM_SLEW_RATE_RISING:
 404                *bank = g->drv_bank;
 405                *reg = g->drv_reg;
 406                *bit = g->slwr_bit;
 407                *width = g->slwr_width;
 408                break;
 409        case TEGRA_PINCONF_PARAM_DRIVE_TYPE:
 410                *bank = g->drvtype_bank;
 411                *reg = g->drvtype_reg;
 412                *bit = g->drvtype_bit;
 413                *width = 2;
 414                break;
 415        default:
 416                dev_err(pmx->dev, "Invalid config param %04x\n", param);
 417                return -ENOTSUPP;
 418        }
 419
 420        if (*reg < 0) {
 421                if (report_err)
 422                        dev_err(pmx->dev,
 423                                "Config param %04x not supported on group %s\n",
 424                                param, g->name);
 425                return -ENOTSUPP;
 426        }
 427
 428        return 0;
 429}
 430
 431static int tegra_pinconf_get(struct pinctrl_dev *pctldev,
 432                             unsigned pin, unsigned long *config)
 433{
 434        dev_err(pctldev->dev, "pin_config_get op not supported\n");
 435        return -ENOTSUPP;
 436}
 437
 438static int tegra_pinconf_set(struct pinctrl_dev *pctldev,
 439                             unsigned pin, unsigned long *configs,
 440                             unsigned num_configs)
 441{
 442        dev_err(pctldev->dev, "pin_config_set op not supported\n");
 443        return -ENOTSUPP;
 444}
 445
 446static int tegra_pinconf_group_get(struct pinctrl_dev *pctldev,
 447                                   unsigned group, unsigned long *config)
 448{
 449        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 450        enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(*config);
 451        u16 arg;
 452        const struct tegra_pingroup *g;
 453        int ret;
 454        s8 bank, bit, width;
 455        s16 reg;
 456        u32 val, mask;
 457
 458        g = &pmx->soc->groups[group];
 459
 460        ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
 461                                &width);
 462        if (ret < 0)
 463                return ret;
 464
 465        val = pmx_readl(pmx, bank, reg);
 466        mask = (1 << width) - 1;
 467        arg = (val >> bit) & mask;
 468
 469        *config = TEGRA_PINCONF_PACK(param, arg);
 470
 471        return 0;
 472}
 473
 474static int tegra_pinconf_group_set(struct pinctrl_dev *pctldev,
 475                                   unsigned group, unsigned long *configs,
 476                                   unsigned num_configs)
 477{
 478        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 479        enum tegra_pinconf_param param;
 480        u16 arg;
 481        const struct tegra_pingroup *g;
 482        int ret, i;
 483        s8 bank, bit, width;
 484        s16 reg;
 485        u32 val, mask;
 486
 487        g = &pmx->soc->groups[group];
 488
 489        for (i = 0; i < num_configs; i++) {
 490                param = TEGRA_PINCONF_UNPACK_PARAM(configs[i]);
 491                arg = TEGRA_PINCONF_UNPACK_ARG(configs[i]);
 492
 493                ret = tegra_pinconf_reg(pmx, g, param, true, &bank, &reg, &bit,
 494                                        &width);
 495                if (ret < 0)
 496                        return ret;
 497
 498                val = pmx_readl(pmx, bank, reg);
 499
 500                /* LOCK can't be cleared */
 501                if (param == TEGRA_PINCONF_PARAM_LOCK) {
 502                        if ((val & BIT(bit)) && !arg) {
 503                                dev_err(pctldev->dev, "LOCK bit cannot be cleared\n");
 504                                return -EINVAL;
 505                        }
 506                }
 507
 508                /* Special-case Boolean values; allow any non-zero as true */
 509                if (width == 1)
 510                        arg = !!arg;
 511
 512                /* Range-check user-supplied value */
 513                mask = (1 << width) - 1;
 514                if (arg & ~mask) {
 515                        dev_err(pctldev->dev,
 516                                "config %lx: %x too big for %d bit register\n",
 517                                configs[i], arg, width);
 518                        return -EINVAL;
 519                }
 520
 521                /* Update register */
 522                val &= ~(mask << bit);
 523                val |= arg << bit;
 524                pmx_writel(pmx, val, bank, reg);
 525        } /* for each config */
 526
 527        return 0;
 528}
 529
 530#ifdef CONFIG_DEBUG_FS
 531static void tegra_pinconf_dbg_show(struct pinctrl_dev *pctldev,
 532                                   struct seq_file *s, unsigned offset)
 533{
 534}
 535
 536static const char *strip_prefix(const char *s)
 537{
 538        const char *comma = strchr(s, ',');
 539        if (!comma)
 540                return s;
 541
 542        return comma + 1;
 543}
 544
 545static void tegra_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
 546                                         struct seq_file *s, unsigned group)
 547{
 548        struct tegra_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 549        const struct tegra_pingroup *g;
 550        int i, ret;
 551        s8 bank, bit, width;
 552        s16 reg;
 553        u32 val;
 554
 555        g = &pmx->soc->groups[group];
 556
 557        for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
 558                ret = tegra_pinconf_reg(pmx, g, cfg_params[i].param, false,
 559                                        &bank, &reg, &bit, &width);
 560                if (ret < 0)
 561                        continue;
 562
 563                val = pmx_readl(pmx, bank, reg);
 564                val >>= bit;
 565                val &= (1 << width) - 1;
 566
 567                seq_printf(s, "\n\t%s=%u",
 568                           strip_prefix(cfg_params[i].property), val);
 569        }
 570}
 571
 572static void tegra_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
 573                                          struct seq_file *s,
 574                                          unsigned long config)
 575{
 576        enum tegra_pinconf_param param = TEGRA_PINCONF_UNPACK_PARAM(config);
 577        u16 arg = TEGRA_PINCONF_UNPACK_ARG(config);
 578        const char *pname = "unknown";
 579        int i;
 580
 581        for (i = 0; i < ARRAY_SIZE(cfg_params); i++) {
 582                if (cfg_params[i].param == param) {
 583                        pname = cfg_params[i].property;
 584                        break;
 585                }
 586        }
 587
 588        seq_printf(s, "%s=%d", strip_prefix(pname), arg);
 589}
 590#endif
 591
 592static const struct pinconf_ops tegra_pinconf_ops = {
 593        .pin_config_get = tegra_pinconf_get,
 594        .pin_config_set = tegra_pinconf_set,
 595        .pin_config_group_get = tegra_pinconf_group_get,
 596        .pin_config_group_set = tegra_pinconf_group_set,
 597#ifdef CONFIG_DEBUG_FS
 598        .pin_config_dbg_show = tegra_pinconf_dbg_show,
 599        .pin_config_group_dbg_show = tegra_pinconf_group_dbg_show,
 600        .pin_config_config_dbg_show = tegra_pinconf_config_dbg_show,
 601#endif
 602};
 603
 604static struct pinctrl_gpio_range tegra_pinctrl_gpio_range = {
 605        .name = "Tegra GPIOs",
 606        .id = 0,
 607        .base = 0,
 608};
 609
 610static struct pinctrl_desc tegra_pinctrl_desc = {
 611        .pctlops = &tegra_pinctrl_ops,
 612        .pmxops = &tegra_pinmux_ops,
 613        .confops = &tegra_pinconf_ops,
 614        .owner = THIS_MODULE,
 615};
 616
 617int tegra_pinctrl_probe(struct platform_device *pdev,
 618                        const struct tegra_pinctrl_soc_data *soc_data)
 619{
 620        struct tegra_pmx *pmx;
 621        struct resource *res;
 622        int i;
 623
 624        pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
 625        if (!pmx) {
 626                dev_err(&pdev->dev, "Can't alloc tegra_pmx\n");
 627                return -ENOMEM;
 628        }
 629        pmx->dev = &pdev->dev;
 630        pmx->soc = soc_data;
 631
 632        tegra_pinctrl_gpio_range.npins = pmx->soc->ngpios;
 633        tegra_pinctrl_desc.name = dev_name(&pdev->dev);
 634        tegra_pinctrl_desc.pins = pmx->soc->pins;
 635        tegra_pinctrl_desc.npins = pmx->soc->npins;
 636
 637        for (i = 0; ; i++) {
 638                res = platform_get_resource(pdev, IORESOURCE_MEM, i);
 639                if (!res)
 640                        break;
 641        }
 642        pmx->nbanks = i;
 643
 644        pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs),
 645                                 GFP_KERNEL);
 646        if (!pmx->regs) {
 647                dev_err(&pdev->dev, "Can't alloc regs pointer\n");
 648                return -ENODEV;
 649        }
 650
 651        for (i = 0; i < pmx->nbanks; i++) {
 652                res = platform_get_resource(pdev, IORESOURCE_MEM, i);
 653                pmx->regs[i] = devm_ioremap_resource(&pdev->dev, res);
 654                if (IS_ERR(pmx->regs[i]))
 655                        return PTR_ERR(pmx->regs[i]);
 656        }
 657
 658        pmx->pctl = pinctrl_register(&tegra_pinctrl_desc, &pdev->dev, pmx);
 659        if (!pmx->pctl) {
 660                dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
 661                return -ENODEV;
 662        }
 663
 664        pinctrl_add_gpio_range(pmx->pctl, &tegra_pinctrl_gpio_range);
 665
 666        platform_set_drvdata(pdev, pmx);
 667
 668        dev_dbg(&pdev->dev, "Probed Tegra pinctrl driver\n");
 669
 670        return 0;
 671}
 672EXPORT_SYMBOL_GPL(tegra_pinctrl_probe);
 673
 674int tegra_pinctrl_remove(struct platform_device *pdev)
 675{
 676        struct tegra_pmx *pmx = platform_get_drvdata(pdev);
 677
 678        pinctrl_unregister(pmx->pctl);
 679
 680        return 0;
 681}
 682EXPORT_SYMBOL_GPL(tegra_pinctrl_remove);
 683
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.