uboot/arch/arm/mach-tegra/tegra20/funcmux.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2011 The Chromium OS Authors.
   4 */
   5
   6/* Tegra20 high-level function multiplexing */
   7#include <common.h>
   8#include <log.h>
   9#include <asm/arch/clock.h>
  10#include <asm/arch/funcmux.h>
  11#include <asm/arch/pinmux.h>
  12
  13/*
  14 * The PINMUX macro is used to set up pinmux tables.
  15 */
  16#define PINMUX(grp, mux, pupd, tri)                   \
  17        {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri}
  18
  19static const struct pmux_pingrp_config disp1_default[] = {
  20        PINMUX(LDI,   DISPA,      NORMAL,    NORMAL),
  21        PINMUX(LHP0,  DISPA,      NORMAL,    NORMAL),
  22        PINMUX(LHP1,  DISPA,      NORMAL,    NORMAL),
  23        PINMUX(LHP2,  DISPA,      NORMAL,    NORMAL),
  24        PINMUX(LHS,   DISPA,      NORMAL,    NORMAL),
  25        PINMUX(LM0,   RSVD4,      NORMAL,    NORMAL),
  26        PINMUX(LPP,   DISPA,      NORMAL,    NORMAL),
  27        PINMUX(LPW0,  DISPA,      NORMAL,    NORMAL),
  28        PINMUX(LPW2,  DISPA,      NORMAL,    NORMAL),
  29        PINMUX(LSC0,  DISPA,      NORMAL,    NORMAL),
  30        PINMUX(LSPI,  DISPA,      NORMAL,    NORMAL),
  31        PINMUX(LVP1,  DISPA,      NORMAL,    NORMAL),
  32        PINMUX(LVS,   DISPA,      NORMAL,    NORMAL),
  33        PINMUX(SLXD,  SPDIF,      NORMAL,    NORMAL),
  34};
  35
  36
  37int funcmux_select(enum periph_id id, int config)
  38{
  39        int bad_config = config != FUNCMUX_DEFAULT;
  40
  41        switch (id) {
  42        case PERIPH_ID_UART1:
  43                switch (config) {
  44                case FUNCMUX_UART1_IRRX_IRTX:
  45                        pinmux_set_func(PMUX_PINGRP_IRRX, PMUX_FUNC_UARTA);
  46                        pinmux_set_func(PMUX_PINGRP_IRTX, PMUX_FUNC_UARTA);
  47                        pinmux_tristate_disable(PMUX_PINGRP_IRRX);
  48                        pinmux_tristate_disable(PMUX_PINGRP_IRTX);
  49                        break;
  50                case FUNCMUX_UART1_UAA_UAB:
  51                        pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_UARTA);
  52                        pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_UARTA);
  53                        pinmux_tristate_disable(PMUX_PINGRP_UAA);
  54                        pinmux_tristate_disable(PMUX_PINGRP_UAB);
  55                        bad_config = 0;
  56                        break;
  57                case FUNCMUX_UART1_GPU:
  58                        pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA);
  59                        pinmux_tristate_disable(PMUX_PINGRP_GPU);
  60                        bad_config = 0;
  61                        break;
  62                case FUNCMUX_UART1_SDIO1:
  63                        pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA);
  64                        pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
  65                        bad_config = 0;
  66                        break;
  67                }
  68                if (!bad_config) {
  69                        /*
  70                         * Tegra appears to boot with function UARTA pre-
  71                         * selected on mux group SDB. If two mux groups are
  72                         * both set to the same function, it's unclear which
  73                         * group's pins drive the RX signals into the HW.
  74                         * For UARTA, SDB certainly overrides group IRTX in
  75                         * practice. To solve this, configure some alternative
  76                         * function on SDB to avoid the conflict. Also, tri-
  77                         * state the group to avoid driving any signal onto it
  78                         * until we know what's connected.
  79                         */
  80                        pinmux_tristate_enable(PMUX_PINGRP_SDB);
  81                        pinmux_set_func(PMUX_PINGRP_SDB,  PMUX_FUNC_SDIO3);
  82                }
  83                break;
  84
  85        case PERIPH_ID_UART2:
  86                if (config == FUNCMUX_UART2_UAD) {
  87                        pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB);
  88                        pinmux_tristate_disable(PMUX_PINGRP_UAD);
  89                }
  90                break;
  91
  92        case PERIPH_ID_UART4:
  93                if (config == FUNCMUX_UART4_GMC) {
  94                        pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD);
  95                        pinmux_tristate_disable(PMUX_PINGRP_GMC);
  96                }
  97                break;
  98
  99        case PERIPH_ID_DVC_I2C:
 100                /* there is only one selection, pinmux_config is ignored */
 101                if (config == FUNCMUX_DVC_I2CP) {
 102                        pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C);
 103                        pinmux_tristate_disable(PMUX_PINGRP_I2CP);
 104                }
 105                break;
 106
 107        case PERIPH_ID_I2C1:
 108                /* support pinmux_config of 0 for now, */
 109                if (config == FUNCMUX_I2C1_RM) {
 110                        pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C);
 111                        pinmux_tristate_disable(PMUX_PINGRP_RM);
 112                }
 113                break;
 114        case PERIPH_ID_I2C2: /* I2C2 */
 115                switch (config) {
 116                case FUNCMUX_I2C2_DDC:  /* DDC pin group, select I2C2 */
 117                        pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2);
 118                        /* PTA to HDMI */
 119                        pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI);
 120                        pinmux_tristate_disable(PMUX_PINGRP_DDC);
 121                        break;
 122                case FUNCMUX_I2C2_PTA:  /* PTA pin group, select I2C2 */
 123                        pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2);
 124                        /* set DDC_SEL to RSVDx (RSVD2 works for now) */
 125                        pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2);
 126                        pinmux_tristate_disable(PMUX_PINGRP_PTA);
 127                        bad_config = 0;
 128                        break;
 129                }
 130                break;
 131        case PERIPH_ID_I2C3: /* I2C3 */
 132                /* support pinmux_config of 0 for now */
 133                if (config == FUNCMUX_I2C3_DTF) {
 134                        pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3);
 135                        pinmux_tristate_disable(PMUX_PINGRP_DTF);
 136                }
 137                break;
 138
 139        case PERIPH_ID_SDMMC1:
 140                if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) {
 141                        pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1);
 142                        pinmux_tristate_disable(PMUX_PINGRP_SDIO1);
 143                }
 144                break;
 145
 146        case PERIPH_ID_SDMMC2:
 147                if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) {
 148                        pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2);
 149                        pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2);
 150
 151                        pinmux_tristate_disable(PMUX_PINGRP_DTA);
 152                        pinmux_tristate_disable(PMUX_PINGRP_DTD);
 153                }
 154                break;
 155
 156        case PERIPH_ID_SDMMC3:
 157                switch (config) {
 158                case FUNCMUX_SDMMC3_SDB_SLXA_8BIT:
 159                        pinmux_set_func(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3);
 160                        pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3);
 161                        pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3);
 162                        pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3);
 163
 164                        pinmux_tristate_disable(PMUX_PINGRP_SLXA);
 165                        pinmux_tristate_disable(PMUX_PINGRP_SLXC);
 166                        pinmux_tristate_disable(PMUX_PINGRP_SLXD);
 167                        pinmux_tristate_disable(PMUX_PINGRP_SLXK);
 168                        /* fall through */
 169
 170                case FUNCMUX_SDMMC3_SDB_4BIT:
 171                        pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3);
 172                        pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3);
 173                        pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3);
 174
 175                        pinmux_tristate_disable(PMUX_PINGRP_SDB);
 176                        pinmux_tristate_disable(PMUX_PINGRP_SDC);
 177                        pinmux_tristate_disable(PMUX_PINGRP_SDD);
 178                        bad_config = 0;
 179                        break;
 180                }
 181                break;
 182
 183        case PERIPH_ID_SDMMC4:
 184                switch (config) {
 185                case FUNCMUX_SDMMC4_ATC_ATD_8BIT:
 186                        pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4);
 187                        pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4);
 188
 189                        pinmux_tristate_disable(PMUX_PINGRP_ATC);
 190                        pinmux_tristate_disable(PMUX_PINGRP_ATD);
 191                        break;
 192
 193                case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT:
 194                        pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4);
 195                        pinmux_tristate_disable(PMUX_PINGRP_GME);
 196                        /* fall through */
 197
 198                case FUNCMUX_SDMMC4_ATB_GMA_4_BIT:
 199                        pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4);
 200                        pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4);
 201
 202                        pinmux_tristate_disable(PMUX_PINGRP_ATB);
 203                        pinmux_tristate_disable(PMUX_PINGRP_GMA);
 204                        bad_config = 0;
 205                        break;
 206                }
 207                break;
 208
 209        case PERIPH_ID_KBC:
 210                if (config == FUNCMUX_DEFAULT) {
 211                        enum pmux_pingrp grp[] = {PMUX_PINGRP_KBCA,
 212                                PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC,
 213                                PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE,
 214                                PMUX_PINGRP_KBCF};
 215                        int i;
 216
 217                        for (i = 0; i < ARRAY_SIZE(grp); i++) {
 218                                pinmux_tristate_disable(grp[i]);
 219                                pinmux_set_func(grp[i], PMUX_FUNC_KBC);
 220                                pinmux_set_pullupdown(grp[i], PMUX_PULL_UP);
 221                        }
 222                }
 223                break;
 224
 225        case PERIPH_ID_USB2:
 226                if (config == FUNCMUX_USB2_ULPI) {
 227                        pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI);
 228                        pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI);
 229                        pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI);
 230
 231                        pinmux_tristate_disable(PMUX_PINGRP_UAA);
 232                        pinmux_tristate_disable(PMUX_PINGRP_UAB);
 233                        pinmux_tristate_disable(PMUX_PINGRP_UDA);
 234                }
 235                break;
 236
 237        case PERIPH_ID_SPI1:
 238                if (config == FUNCMUX_SPI1_GMC_GMD) {
 239                        pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
 240                        pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
 241
 242                        pinmux_tristate_disable(PMUX_PINGRP_GMC);
 243                        pinmux_tristate_disable(PMUX_PINGRP_GMD);
 244                }
 245                break;
 246
 247        case PERIPH_ID_NDFLASH:
 248                switch (config) {
 249                case FUNCMUX_NDFLASH_ATC:
 250                        pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND);
 251                        pinmux_tristate_disable(PMUX_PINGRP_ATC);
 252                        break;
 253                case FUNCMUX_NDFLASH_KBC_8_BIT:
 254                        pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND);
 255                        pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND);
 256                        pinmux_set_func(PMUX_PINGRP_KBCC, PMUX_FUNC_NAND);
 257                        pinmux_set_func(PMUX_PINGRP_KBCD, PMUX_FUNC_NAND);
 258                        pinmux_set_func(PMUX_PINGRP_KBCE, PMUX_FUNC_NAND);
 259                        pinmux_set_func(PMUX_PINGRP_KBCF, PMUX_FUNC_NAND);
 260
 261                        pinmux_tristate_disable(PMUX_PINGRP_KBCA);
 262                        pinmux_tristate_disable(PMUX_PINGRP_KBCB);
 263                        pinmux_tristate_disable(PMUX_PINGRP_KBCC);
 264                        pinmux_tristate_disable(PMUX_PINGRP_KBCD);
 265                        pinmux_tristate_disable(PMUX_PINGRP_KBCE);
 266                        pinmux_tristate_disable(PMUX_PINGRP_KBCF);
 267
 268                        bad_config = 0;
 269                        break;
 270                }
 271                break;
 272        case PERIPH_ID_DISP1:
 273                if (config == FUNCMUX_DEFAULT) {
 274                        int i;
 275
 276                        for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) {
 277                                pinmux_set_func(i, PMUX_FUNC_DISPA);
 278                                pinmux_tristate_disable(i);
 279                                pinmux_set_pullupdown(i, PMUX_PULL_NORMAL);
 280                        }
 281                        pinmux_config_pingrp_table(disp1_default,
 282                                                   ARRAY_SIZE(disp1_default));
 283                }
 284                break;
 285
 286        default:
 287                debug("%s: invalid periph_id %d", __func__, id);
 288                return -1;
 289        }
 290
 291        if (bad_config) {
 292                debug("%s: invalid config %d for periph_id %d", __func__,
 293                      config, id);
 294                return -1;
 295        }
 296
 297        return 0;
 298}
 299