uboot/arch/arm/mach-tegra/pinmux-common.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved.
   3 * Copyright (c) 2011 The Chromium OS Authors.
   4 *
   5 * SPDX-License-Identifier: GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <asm/io.h>
  10#include <asm/arch/pinmux.h>
  11
  12/* return 1 if a pingrp is in range */
  13#define pmux_pingrp_isvalid(pin) (((pin) >= 0) && ((pin) < PMUX_PINGRP_COUNT))
  14
  15/* return 1 if a pmux_func is in range */
  16#define pmux_func_isvalid(func) \
  17        (((func) >= 0) && ((func) < PMUX_FUNC_COUNT))
  18
  19/* return 1 if a pin_pupd_is in range */
  20#define pmux_pin_pupd_isvalid(pupd) \
  21        (((pupd) >= PMUX_PULL_NORMAL) && ((pupd) <= PMUX_PULL_UP))
  22
  23/* return 1 if a pin_tristate_is in range */
  24#define pmux_pin_tristate_isvalid(tristate) \
  25        (((tristate) >= PMUX_TRI_NORMAL) && ((tristate) <= PMUX_TRI_TRISTATE))
  26
  27#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
  28/* return 1 if a pin_io_is in range */
  29#define pmux_pin_io_isvalid(io) \
  30        (((io) >= PMUX_PIN_OUTPUT) && ((io) <= PMUX_PIN_INPUT))
  31#endif
  32
  33#ifdef TEGRA_PMX_PINS_HAVE_LOCK
  34/* return 1 if a pin_lock is in range */
  35#define pmux_pin_lock_isvalid(lock) \
  36        (((lock) >= PMUX_PIN_LOCK_DISABLE) && ((lock) <= PMUX_PIN_LOCK_ENABLE))
  37#endif
  38
  39#ifdef TEGRA_PMX_PINS_HAVE_OD
  40/* return 1 if a pin_od is in range */
  41#define pmux_pin_od_isvalid(od) \
  42        (((od) >= PMUX_PIN_OD_DISABLE) && ((od) <= PMUX_PIN_OD_ENABLE))
  43#endif
  44
  45#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
  46/* return 1 if a pin_ioreset_is in range */
  47#define pmux_pin_ioreset_isvalid(ioreset) \
  48        (((ioreset) >= PMUX_PIN_IO_RESET_DISABLE) && \
  49         ((ioreset) <= PMUX_PIN_IO_RESET_ENABLE))
  50#endif
  51
  52#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
  53/* return 1 if a pin_rcv_sel_is in range */
  54#define pmux_pin_rcv_sel_isvalid(rcv_sel) \
  55        (((rcv_sel) >= PMUX_PIN_RCV_SEL_NORMAL) && \
  56         ((rcv_sel) <= PMUX_PIN_RCV_SEL_HIGH))
  57#endif
  58
  59#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
  60/* return 1 if a pin_e_io_hv is in range */
  61#define pmux_pin_e_io_hv_isvalid(e_io_hv) \
  62        (((e_io_hv) >= PMUX_PIN_E_IO_HV_NORMAL) && \
  63         ((e_io_hv) <= PMUX_PIN_E_IO_HV_HIGH))
  64#endif
  65
  66#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
  67#define pmux_lpmd_isvalid(lpm) \
  68        (((lpm) >= PMUX_LPMD_X8) && ((lpm) <= PMUX_LPMD_X))
  69#endif
  70
  71#if defined(TEGRA_PMX_PINS_HAVE_SCHMT) || defined(TEGRA_PMX_GRPS_HAVE_SCHMT)
  72#define pmux_schmt_isvalid(schmt) \
  73        (((schmt) >= PMUX_SCHMT_DISABLE) && ((schmt) <= PMUX_SCHMT_ENABLE))
  74#endif
  75
  76#if defined(TEGRA_PMX_PINS_HAVE_HSM) || defined(TEGRA_PMX_GRPS_HAVE_HSM)
  77#define pmux_hsm_isvalid(hsm) \
  78        (((hsm) >= PMUX_HSM_DISABLE) && ((hsm) <= PMUX_HSM_ENABLE))
  79#endif
  80
  81#define _R(offset)      (u32 *)((unsigned long)NV_PA_APB_MISC_BASE + (offset))
  82
  83#if defined(CONFIG_TEGRA20)
  84
  85#define MUX_REG(grp)    _R(0x80 + ((tegra_soc_pingroups[grp].ctl_id / 16) * 4))
  86#define MUX_SHIFT(grp)  ((tegra_soc_pingroups[grp].ctl_id % 16) * 2)
  87
  88#define PULL_REG(grp)   _R(0xa0 + ((tegra_soc_pingroups[grp].pull_id / 16) * 4))
  89#define PULL_SHIFT(grp) ((tegra_soc_pingroups[grp].pull_id % 16) * 2)
  90
  91#define TRI_REG(grp)    _R(0x14 + (((grp) / 32) * 4))
  92#define TRI_SHIFT(grp)  ((grp) % 32)
  93
  94#else
  95
  96#define REG(pin)        _R(0x3000 + ((pin) * 4))
  97
  98#define MUX_REG(pin)    REG(pin)
  99#define MUX_SHIFT(pin)  0
 100
 101#define PULL_REG(pin)   REG(pin)
 102#define PULL_SHIFT(pin) 2
 103
 104#define TRI_REG(pin)    REG(pin)
 105#define TRI_SHIFT(pin)  4
 106
 107#endif /* CONFIG_TEGRA20 */
 108
 109#define DRV_REG(group)  _R(TEGRA_PMX_SOC_DRV_GROUP_BASE_REG + ((group) * 4))
 110
 111#define MIPIPADCTRL_REG(group)  _R(TEGRA_PMX_SOC_MIPIPADCTRL_BASE_REG + ((group) * 4))
 112
 113/*
 114 * We could force arch-tegraNN/pinmux.h to define all of these. However,
 115 * that's a lot of defines, and for now it's manageable to just put a
 116 * special case here. It's possible this decision will change with future
 117 * SoCs.
 118 */
 119#ifdef CONFIG_TEGRA210
 120#define IO_SHIFT        6
 121#define LOCK_SHIFT      7
 122#ifdef TEGRA_PMX_PINS_HAVE_HSM
 123#define HSM_SHIFT       9
 124#endif
 125#define E_IO_HV_SHIFT   10
 126#define OD_SHIFT        11
 127#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
 128#define SCHMT_SHIFT     12
 129#endif
 130#else
 131#define IO_SHIFT        5
 132#define OD_SHIFT        6
 133#define LOCK_SHIFT      7
 134#define IO_RESET_SHIFT  8
 135#define RCV_SEL_SHIFT   9
 136#endif
 137
 138#ifdef TEGRA_PMX_SOC_HAS_IO_CLAMPING
 139/* This register/field only exists on Tegra114 and later */
 140#define APB_MISC_PP_PINMUX_GLOBAL_0 0x40
 141#define CLAMP_INPUTS_WHEN_TRISTATED 1
 142
 143void pinmux_set_tristate_input_clamping(void)
 144{
 145        u32 *reg = _R(APB_MISC_PP_PINMUX_GLOBAL_0);
 146
 147        setbits_le32(reg, CLAMP_INPUTS_WHEN_TRISTATED);
 148}
 149
 150void pinmux_clear_tristate_input_clamping(void)
 151{
 152        u32 *reg = _R(APB_MISC_PP_PINMUX_GLOBAL_0);
 153
 154        clrbits_le32(reg, CLAMP_INPUTS_WHEN_TRISTATED);
 155}
 156#endif
 157
 158void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func)
 159{
 160        u32 *reg = MUX_REG(pin);
 161        int i, mux = -1;
 162        u32 val;
 163
 164        if (func == PMUX_FUNC_DEFAULT)
 165                return;
 166
 167        /* Error check on pin and func */
 168        assert(pmux_pingrp_isvalid(pin));
 169        assert(pmux_func_isvalid(func));
 170
 171        if (func >= PMUX_FUNC_RSVD1) {
 172                mux = (func - PMUX_FUNC_RSVD1) & 3;
 173        } else {
 174                /* Search for the appropriate function */
 175                for (i = 0; i < 4; i++) {
 176                        if (tegra_soc_pingroups[pin].funcs[i] == func) {
 177                                mux = i;
 178                                break;
 179                        }
 180                }
 181        }
 182        assert(mux != -1);
 183
 184        val = readl(reg);
 185        val &= ~(3 << MUX_SHIFT(pin));
 186        val |= (mux << MUX_SHIFT(pin));
 187        writel(val, reg);
 188}
 189
 190void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd)
 191{
 192        u32 *reg = PULL_REG(pin);
 193        u32 val;
 194
 195        /* Error check on pin and pupd */
 196        assert(pmux_pingrp_isvalid(pin));
 197        assert(pmux_pin_pupd_isvalid(pupd));
 198
 199        val = readl(reg);
 200        val &= ~(3 << PULL_SHIFT(pin));
 201        val |= (pupd << PULL_SHIFT(pin));
 202        writel(val, reg);
 203}
 204
 205static void pinmux_set_tristate(enum pmux_pingrp pin, int tri)
 206{
 207        u32 *reg = TRI_REG(pin);
 208        u32 val;
 209
 210        /* Error check on pin */
 211        assert(pmux_pingrp_isvalid(pin));
 212        assert(pmux_pin_tristate_isvalid(tri));
 213
 214        val = readl(reg);
 215        if (tri == PMUX_TRI_TRISTATE)
 216                val |= (1 << TRI_SHIFT(pin));
 217        else
 218                val &= ~(1 << TRI_SHIFT(pin));
 219        writel(val, reg);
 220}
 221
 222void pinmux_tristate_enable(enum pmux_pingrp pin)
 223{
 224        pinmux_set_tristate(pin, PMUX_TRI_TRISTATE);
 225}
 226
 227void pinmux_tristate_disable(enum pmux_pingrp pin)
 228{
 229        pinmux_set_tristate(pin, PMUX_TRI_NORMAL);
 230}
 231
 232#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
 233void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io)
 234{
 235        u32 *reg = REG(pin);
 236        u32 val;
 237
 238        if (io == PMUX_PIN_NONE)
 239                return;
 240
 241        /* Error check on pin and io */
 242        assert(pmux_pingrp_isvalid(pin));
 243        assert(pmux_pin_io_isvalid(io));
 244
 245        val = readl(reg);
 246        if (io == PMUX_PIN_INPUT)
 247                val |= (io & 1) << IO_SHIFT;
 248        else
 249                val &= ~(1 << IO_SHIFT);
 250        writel(val, reg);
 251}
 252#endif
 253
 254#ifdef TEGRA_PMX_PINS_HAVE_LOCK
 255static void pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock)
 256{
 257        u32 *reg = REG(pin);
 258        u32 val;
 259
 260        if (lock == PMUX_PIN_LOCK_DEFAULT)
 261                return;
 262
 263        /* Error check on pin and lock */
 264        assert(pmux_pingrp_isvalid(pin));
 265        assert(pmux_pin_lock_isvalid(lock));
 266
 267        val = readl(reg);
 268        if (lock == PMUX_PIN_LOCK_ENABLE) {
 269                val |= (1 << LOCK_SHIFT);
 270        } else {
 271                if (val & (1 << LOCK_SHIFT))
 272                        printf("%s: Cannot clear LOCK bit!\n", __func__);
 273                val &= ~(1 << LOCK_SHIFT);
 274        }
 275        writel(val, reg);
 276
 277        return;
 278}
 279#endif
 280
 281#ifdef TEGRA_PMX_PINS_HAVE_OD
 282static void pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od)
 283{
 284        u32 *reg = REG(pin);
 285        u32 val;
 286
 287        if (od == PMUX_PIN_OD_DEFAULT)
 288                return;
 289
 290        /* Error check on pin and od */
 291        assert(pmux_pingrp_isvalid(pin));
 292        assert(pmux_pin_od_isvalid(od));
 293
 294        val = readl(reg);
 295        if (od == PMUX_PIN_OD_ENABLE)
 296                val |= (1 << OD_SHIFT);
 297        else
 298                val &= ~(1 << OD_SHIFT);
 299        writel(val, reg);
 300
 301        return;
 302}
 303#endif
 304
 305#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
 306static void pinmux_set_ioreset(enum pmux_pingrp pin,
 307                                enum pmux_pin_ioreset ioreset)
 308{
 309        u32 *reg = REG(pin);
 310        u32 val;
 311
 312        if (ioreset == PMUX_PIN_IO_RESET_DEFAULT)
 313                return;
 314
 315        /* Error check on pin and ioreset */
 316        assert(pmux_pingrp_isvalid(pin));
 317        assert(pmux_pin_ioreset_isvalid(ioreset));
 318
 319        val = readl(reg);
 320        if (ioreset == PMUX_PIN_IO_RESET_ENABLE)
 321                val |= (1 << IO_RESET_SHIFT);
 322        else
 323                val &= ~(1 << IO_RESET_SHIFT);
 324        writel(val, reg);
 325
 326        return;
 327}
 328#endif
 329
 330#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
 331static void pinmux_set_rcv_sel(enum pmux_pingrp pin,
 332                                enum pmux_pin_rcv_sel rcv_sel)
 333{
 334        u32 *reg = REG(pin);
 335        u32 val;
 336
 337        if (rcv_sel == PMUX_PIN_RCV_SEL_DEFAULT)
 338                return;
 339
 340        /* Error check on pin and rcv_sel */
 341        assert(pmux_pingrp_isvalid(pin));
 342        assert(pmux_pin_rcv_sel_isvalid(rcv_sel));
 343
 344        val = readl(reg);
 345        if (rcv_sel == PMUX_PIN_RCV_SEL_HIGH)
 346                val |= (1 << RCV_SEL_SHIFT);
 347        else
 348                val &= ~(1 << RCV_SEL_SHIFT);
 349        writel(val, reg);
 350
 351        return;
 352}
 353#endif
 354
 355#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
 356static void pinmux_set_e_io_hv(enum pmux_pingrp pin,
 357                                enum pmux_pin_e_io_hv e_io_hv)
 358{
 359        u32 *reg = REG(pin);
 360        u32 val;
 361
 362        if (e_io_hv == PMUX_PIN_E_IO_HV_DEFAULT)
 363                return;
 364
 365        /* Error check on pin and e_io_hv */
 366        assert(pmux_pingrp_isvalid(pin));
 367        assert(pmux_pin_e_io_hv_isvalid(e_io_hv));
 368
 369        val = readl(reg);
 370        if (e_io_hv == PMUX_PIN_E_IO_HV_HIGH)
 371                val |= (1 << E_IO_HV_SHIFT);
 372        else
 373                val &= ~(1 << E_IO_HV_SHIFT);
 374        writel(val, reg);
 375
 376        return;
 377}
 378#endif
 379
 380#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
 381static void pinmux_set_schmt(enum pmux_pingrp pin, enum pmux_schmt schmt)
 382{
 383        u32 *reg = REG(grp);
 384        u32 val;
 385
 386        /* NONE means unspecified/do not change/use POR value */
 387        if (schmt == PMUX_SCHMT_NONE)
 388                return;
 389
 390        /* Error check pad */
 391        assert(pmux_pingrp_isvalid(pin));
 392        assert(pmux_schmt_isvalid(schmt));
 393
 394        val = readl(reg);
 395        if (schmt == PMUX_SCHMT_ENABLE)
 396                val |= (1 << SCHMT_SHIFT);
 397        else
 398                val &= ~(1 << SCHMT_SHIFT);
 399        writel(val, reg);
 400
 401        return;
 402}
 403#endif
 404
 405#ifdef TEGRA_PMX_PINS_HAVE_HSM
 406static void pinmux_set_hsm(enum pmux_pingrp pin, enum pmux_hsm hsm)
 407{
 408        u32 *reg = REG(grp);
 409        u32 val;
 410
 411        /* NONE means unspecified/do not change/use POR value */
 412        if (hsm == PMUX_HSM_NONE)
 413                return;
 414
 415        /* Error check pad */
 416        assert(pmux_pingrp_isvalid(pin));
 417        assert(pmux_hsm_isvalid(hsm));
 418
 419        val = readl(reg);
 420        if (hsm == PMUX_HSM_ENABLE)
 421                val |= (1 << HSM_SHIFT);
 422        else
 423                val &= ~(1 << HSM_SHIFT);
 424        writel(val, reg);
 425
 426        return;
 427}
 428#endif
 429
 430static void pinmux_config_pingrp(const struct pmux_pingrp_config *config)
 431{
 432        enum pmux_pingrp pin = config->pingrp;
 433
 434        pinmux_set_func(pin, config->func);
 435        pinmux_set_pullupdown(pin, config->pull);
 436        pinmux_set_tristate(pin, config->tristate);
 437#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT
 438        pinmux_set_io(pin, config->io);
 439#endif
 440#ifdef TEGRA_PMX_PINS_HAVE_LOCK
 441        pinmux_set_lock(pin, config->lock);
 442#endif
 443#ifdef TEGRA_PMX_PINS_HAVE_OD
 444        pinmux_set_od(pin, config->od);
 445#endif
 446#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET
 447        pinmux_set_ioreset(pin, config->ioreset);
 448#endif
 449#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
 450        pinmux_set_rcv_sel(pin, config->rcv_sel);
 451#endif
 452#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
 453        pinmux_set_e_io_hv(pin, config->e_io_hv);
 454#endif
 455#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
 456        pinmux_set_schmt(pin, config->schmt);
 457#endif
 458#ifdef TEGRA_PMX_PINS_HAVE_HSM
 459        pinmux_set_hsm(pin, config->hsm);
 460#endif
 461}
 462
 463void pinmux_config_pingrp_table(const struct pmux_pingrp_config *config,
 464                                int len)
 465{
 466        int i;
 467
 468        for (i = 0; i < len; i++)
 469                pinmux_config_pingrp(&config[i]);
 470}
 471
 472#ifdef TEGRA_PMX_SOC_HAS_DRVGRPS
 473
 474#define pmux_drvgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_DRVGRP_COUNT))
 475
 476#define pmux_slw_isvalid(slw) \
 477        (((slw) >= PMUX_SLWF_MIN) && ((slw) <= PMUX_SLWF_MAX))
 478
 479#define pmux_drv_isvalid(drv) \
 480        (((drv) >= PMUX_DRVUP_MIN) && ((drv) <= PMUX_DRVUP_MAX))
 481
 482#ifdef TEGRA_PMX_GRPS_HAVE_HSM
 483#define HSM_SHIFT       2
 484#endif
 485#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
 486#define SCHMT_SHIFT     3
 487#endif
 488#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
 489#define LPMD_SHIFT      4
 490#define LPMD_MASK       (3 << LPMD_SHIFT)
 491#endif
 492/*
 493 * Note that the following DRV* and SLW* defines are accurate for many drive
 494 * groups on many SoCs. We really need a per-group data structure to solve
 495 * this, since the fields are in different positions/sizes in different
 496 * registers (for different groups).
 497 *
 498 * On Tegra30/114/124, the DRV*_SHIFT values vary.
 499 * On Tegra30, the SLW*_SHIFT values vary.
 500 * On Tegra30/114/124/210, the DRV*_MASK values vary, although the values
 501 *   below are wide enough to cover the widest fields, and hopefully don't
 502 *   interfere with any other fields.
 503 * On Tegra30, the SLW*_MASK values vary, but we can't use a value that's
 504 *   wide enough to cover all cases, since that would cause the field to
 505 *   overlap with other fields in the narrower cases.
 506 */
 507#define DRVDN_SHIFT     12
 508#define DRVDN_MASK      (0x7F << DRVDN_SHIFT)
 509#define DRVUP_SHIFT     20
 510#define DRVUP_MASK      (0x7F << DRVUP_SHIFT)
 511#define SLWR_SHIFT      28
 512#define SLWR_MASK       (3 << SLWR_SHIFT)
 513#define SLWF_SHIFT      30
 514#define SLWF_MASK       (3 << SLWF_SHIFT)
 515
 516static void pinmux_set_drvup_slwf(enum pmux_drvgrp grp, int slwf)
 517{
 518        u32 *reg = DRV_REG(grp);
 519        u32 val;
 520
 521        /* NONE means unspecified/do not change/use POR value */
 522        if (slwf == PMUX_SLWF_NONE)
 523                return;
 524
 525        /* Error check on pad and slwf */
 526        assert(pmux_drvgrp_isvalid(grp));
 527        assert(pmux_slw_isvalid(slwf));
 528
 529        val = readl(reg);
 530        val &= ~SLWF_MASK;
 531        val |= (slwf << SLWF_SHIFT);
 532        writel(val, reg);
 533
 534        return;
 535}
 536
 537static void pinmux_set_drvdn_slwr(enum pmux_drvgrp grp, int slwr)
 538{
 539        u32 *reg = DRV_REG(grp);
 540        u32 val;
 541
 542        /* NONE means unspecified/do not change/use POR value */
 543        if (slwr == PMUX_SLWR_NONE)
 544                return;
 545
 546        /* Error check on pad and slwr */
 547        assert(pmux_drvgrp_isvalid(grp));
 548        assert(pmux_slw_isvalid(slwr));
 549
 550        val = readl(reg);
 551        val &= ~SLWR_MASK;
 552        val |= (slwr << SLWR_SHIFT);
 553        writel(val, reg);
 554
 555        return;
 556}
 557
 558static void pinmux_set_drvup(enum pmux_drvgrp grp, int drvup)
 559{
 560        u32 *reg = DRV_REG(grp);
 561        u32 val;
 562
 563        /* NONE means unspecified/do not change/use POR value */
 564        if (drvup == PMUX_DRVUP_NONE)
 565                return;
 566
 567        /* Error check on pad and drvup */
 568        assert(pmux_drvgrp_isvalid(grp));
 569        assert(pmux_drv_isvalid(drvup));
 570
 571        val = readl(reg);
 572        val &= ~DRVUP_MASK;
 573        val |= (drvup << DRVUP_SHIFT);
 574        writel(val, reg);
 575
 576        return;
 577}
 578
 579static void pinmux_set_drvdn(enum pmux_drvgrp grp, int drvdn)
 580{
 581        u32 *reg = DRV_REG(grp);
 582        u32 val;
 583
 584        /* NONE means unspecified/do not change/use POR value */
 585        if (drvdn == PMUX_DRVDN_NONE)
 586                return;
 587
 588        /* Error check on pad and drvdn */
 589        assert(pmux_drvgrp_isvalid(grp));
 590        assert(pmux_drv_isvalid(drvdn));
 591
 592        val = readl(reg);
 593        val &= ~DRVDN_MASK;
 594        val |= (drvdn << DRVDN_SHIFT);
 595        writel(val, reg);
 596
 597        return;
 598}
 599
 600#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
 601static void pinmux_set_lpmd(enum pmux_drvgrp grp, enum pmux_lpmd lpmd)
 602{
 603        u32 *reg = DRV_REG(grp);
 604        u32 val;
 605
 606        /* NONE means unspecified/do not change/use POR value */
 607        if (lpmd == PMUX_LPMD_NONE)
 608                return;
 609
 610        /* Error check pad and lpmd value */
 611        assert(pmux_drvgrp_isvalid(grp));
 612        assert(pmux_lpmd_isvalid(lpmd));
 613
 614        val = readl(reg);
 615        val &= ~LPMD_MASK;
 616        val |= (lpmd << LPMD_SHIFT);
 617        writel(val, reg);
 618
 619        return;
 620}
 621#endif
 622
 623#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
 624static void pinmux_set_schmt(enum pmux_drvgrp grp, enum pmux_schmt schmt)
 625{
 626        u32 *reg = DRV_REG(grp);
 627        u32 val;
 628
 629        /* NONE means unspecified/do not change/use POR value */
 630        if (schmt == PMUX_SCHMT_NONE)
 631                return;
 632
 633        /* Error check pad */
 634        assert(pmux_drvgrp_isvalid(grp));
 635        assert(pmux_schmt_isvalid(schmt));
 636
 637        val = readl(reg);
 638        if (schmt == PMUX_SCHMT_ENABLE)
 639                val |= (1 << SCHMT_SHIFT);
 640        else
 641                val &= ~(1 << SCHMT_SHIFT);
 642        writel(val, reg);
 643
 644        return;
 645}
 646#endif
 647
 648#ifdef TEGRA_PMX_GRPS_HAVE_HSM
 649static void pinmux_set_hsm(enum pmux_drvgrp grp, enum pmux_hsm hsm)
 650{
 651        u32 *reg = DRV_REG(grp);
 652        u32 val;
 653
 654        /* NONE means unspecified/do not change/use POR value */
 655        if (hsm == PMUX_HSM_NONE)
 656                return;
 657
 658        /* Error check pad */
 659        assert(pmux_drvgrp_isvalid(grp));
 660        assert(pmux_hsm_isvalid(hsm));
 661
 662        val = readl(reg);
 663        if (hsm == PMUX_HSM_ENABLE)
 664                val |= (1 << HSM_SHIFT);
 665        else
 666                val &= ~(1 << HSM_SHIFT);
 667        writel(val, reg);
 668
 669        return;
 670}
 671#endif
 672
 673static void pinmux_config_drvgrp(const struct pmux_drvgrp_config *config)
 674{
 675        enum pmux_drvgrp grp = config->drvgrp;
 676
 677        pinmux_set_drvup_slwf(grp, config->slwf);
 678        pinmux_set_drvdn_slwr(grp, config->slwr);
 679        pinmux_set_drvup(grp, config->drvup);
 680        pinmux_set_drvdn(grp, config->drvdn);
 681#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
 682        pinmux_set_lpmd(grp, config->lpmd);
 683#endif
 684#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
 685        pinmux_set_schmt(grp, config->schmt);
 686#endif
 687#ifdef TEGRA_PMX_GRPS_HAVE_HSM
 688        pinmux_set_hsm(grp, config->hsm);
 689#endif
 690}
 691
 692void pinmux_config_drvgrp_table(const struct pmux_drvgrp_config *config,
 693                                int len)
 694{
 695        int i;
 696
 697        for (i = 0; i < len; i++)
 698                pinmux_config_drvgrp(&config[i]);
 699}
 700#endif /* TEGRA_PMX_SOC_HAS_DRVGRPS */
 701
 702#ifdef TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS
 703
 704#define pmux_mipipadctrlgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_MIPIPADCTRLGRP_COUNT))
 705
 706static void pinmux_mipipadctrl_set_func(enum pmux_mipipadctrlgrp grp,
 707        enum pmux_func func)
 708{
 709        u32 *reg = MIPIPADCTRL_REG(grp);
 710        int i, mux = -1;
 711        u32 val;
 712
 713        if (func == PMUX_FUNC_DEFAULT)
 714                return;
 715
 716        /* Error check grp and func */
 717        assert(pmux_mipipadctrlgrp_isvalid(grp));
 718        assert(pmux_func_isvalid(func));
 719
 720        if (func >= PMUX_FUNC_RSVD1) {
 721                mux = (func - PMUX_FUNC_RSVD1) & 1;
 722        } else {
 723                /* Search for the appropriate function */
 724                for (i = 0; i < 2; i++) {
 725                        if (tegra_soc_mipipadctrl_groups[grp].funcs[i]
 726                            == func) {
 727                                mux = i;
 728                                break;
 729                        }
 730                }
 731        }
 732        assert(mux != -1);
 733
 734        val = readl(reg);
 735        val &= ~(1 << 1);
 736        val |= (mux << 1);
 737        writel(val, reg);
 738}
 739
 740static void pinmux_config_mipipadctrlgrp(const struct pmux_mipipadctrlgrp_config *config)
 741{
 742        enum pmux_mipipadctrlgrp grp = config->grp;
 743
 744        pinmux_mipipadctrl_set_func(grp, config->func);
 745}
 746
 747void pinmux_config_mipipadctrlgrp_table(
 748        const struct pmux_mipipadctrlgrp_config *config, int len)
 749{
 750        int i;
 751
 752        for (i = 0; i < len; i++)
 753                pinmux_config_mipipadctrlgrp(&config[i]);
 754}
 755#endif /* TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS */
 756