uboot/drivers/pinctrl/rockchip/pinctrl-rv1108.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2019 Rockchip Electronics Co., Ltd
   4 */
   5
   6#include <common.h>
   7#include <dm.h>
   8#include <dm/pinctrl.h>
   9#include <regmap.h>
  10#include <syscon.h>
  11
  12#include "pinctrl-rockchip.h"
  13
  14static struct rockchip_mux_recalced_data rv1108_mux_recalced_data[] = {
  15        {
  16                .num = 1,
  17                .pin = 0,
  18                .reg = 0x418,
  19                .bit = 0,
  20                .mask = 0x3
  21        }, {
  22                .num = 1,
  23                .pin = 1,
  24                .reg = 0x418,
  25                .bit = 2,
  26                .mask = 0x3
  27        }, {
  28                .num = 1,
  29                .pin = 2,
  30                .reg = 0x418,
  31                .bit = 4,
  32                .mask = 0x3
  33        }, {
  34                .num = 1,
  35                .pin = 3,
  36                .reg = 0x418,
  37                .bit = 6,
  38                .mask = 0x3
  39        }, {
  40                .num = 1,
  41                .pin = 4,
  42                .reg = 0x418,
  43                .bit = 8,
  44                .mask = 0x3
  45        }, {
  46                .num = 1,
  47                .pin = 5,
  48                .reg = 0x418,
  49                .bit = 10,
  50                .mask = 0x3
  51        }, {
  52                .num = 1,
  53                .pin = 6,
  54                .reg = 0x418,
  55                .bit = 12,
  56                .mask = 0x3
  57        }, {
  58                .num = 1,
  59                .pin = 7,
  60                .reg = 0x418,
  61                .bit = 14,
  62                .mask = 0x3
  63        }, {
  64                .num = 1,
  65                .pin = 8,
  66                .reg = 0x41c,
  67                .bit = 0,
  68                .mask = 0x3
  69        }, {
  70                .num = 1,
  71                .pin = 9,
  72                .reg = 0x41c,
  73                .bit = 2,
  74                .mask = 0x3
  75        },
  76};
  77
  78static int rv1108_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
  79{
  80        struct rockchip_pinctrl_priv *priv = bank->priv;
  81        int iomux_num = (pin / 8);
  82        struct regmap *regmap;
  83        int reg, ret, mask, mux_type;
  84        u8 bit;
  85        u32 data;
  86
  87        regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU)
  88                                ? priv->regmap_pmu : priv->regmap_base;
  89
  90        /* get basic quadrupel of mux registers and the correct reg inside */
  91        mux_type = bank->iomux[iomux_num].type;
  92        reg = bank->iomux[iomux_num].offset;
  93        reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask);
  94
  95        if (bank->recalced_mask & BIT(pin))
  96                rockchip_get_recalced_mux(bank, pin, &reg, &bit, &mask);
  97
  98        data = (mask << (bit + 16));
  99        data |= (mux & mask) << bit;
 100        ret = regmap_write(regmap, reg, data);
 101
 102        return ret;
 103}
 104
 105#define RV1108_PULL_PMU_OFFSET          0x10
 106#define RV1108_PULL_OFFSET              0x110
 107
 108static void rv1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
 109                                         int pin_num, struct regmap **regmap,
 110                                         int *reg, u8 *bit)
 111{
 112        struct rockchip_pinctrl_priv *priv = bank->priv;
 113
 114        /* The first 24 pins of the first bank are located in PMU */
 115        if (bank->bank_num == 0) {
 116                *regmap = priv->regmap_pmu;
 117                *reg = RV1108_PULL_PMU_OFFSET;
 118        } else {
 119                *reg = RV1108_PULL_OFFSET;
 120                *regmap = priv->regmap_base;
 121                /* correct the offset, as we're starting with the 2nd bank */
 122                *reg -= 0x10;
 123                *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE;
 124        }
 125
 126        *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4);
 127        *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG);
 128        *bit *= ROCKCHIP_PULL_BITS_PER_PIN;
 129}
 130
 131static int rv1108_set_pull(struct rockchip_pin_bank *bank,
 132                           int pin_num, int pull)
 133{
 134        struct regmap *regmap;
 135        int reg, ret;
 136        u8 bit, type;
 137        u32 data;
 138
 139        if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT)
 140                return -ENOTSUPP;
 141
 142        rv1108_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
 143        type = bank->pull_type[pin_num / 8];
 144        ret = rockchip_translate_pull_value(type, pull);
 145        if (ret < 0) {
 146                debug("unsupported pull setting %d\n", pull);
 147                return ret;
 148        }
 149
 150        /* enable the write to the equivalent lower bits */
 151        data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
 152
 153        data |= (ret << bit);
 154        ret = regmap_write(regmap, reg, data);
 155
 156        return ret;
 157}
 158
 159#define RV1108_DRV_PMU_OFFSET           0x20
 160#define RV1108_DRV_GRF_OFFSET           0x210
 161
 162static void rv1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
 163                                        int pin_num, struct regmap **regmap,
 164                                        int *reg, u8 *bit)
 165{
 166        struct rockchip_pinctrl_priv *priv = bank->priv;
 167
 168        /* The first 24 pins of the first bank are located in PMU */
 169        if (bank->bank_num == 0) {
 170                *regmap = priv->regmap_pmu;
 171                *reg = RV1108_DRV_PMU_OFFSET;
 172        } else {
 173                *regmap = priv->regmap_base;
 174                *reg = RV1108_DRV_GRF_OFFSET;
 175
 176                /* correct the offset, as we're starting with the 2nd bank */
 177                *reg -= 0x10;
 178                *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE;
 179        }
 180
 181        *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4);
 182        *bit = pin_num % ROCKCHIP_DRV_PINS_PER_REG;
 183        *bit *= ROCKCHIP_DRV_BITS_PER_PIN;
 184}
 185
 186static int rv1108_set_drive(struct rockchip_pin_bank *bank,
 187                            int pin_num, int strength)
 188{
 189        struct regmap *regmap;
 190        int reg, ret;
 191        u32 data;
 192        u8 bit;
 193        int type = bank->drv[pin_num / 8].drv_type;
 194
 195        rv1108_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
 196        ret = rockchip_translate_drive_value(type, strength);
 197        if (ret < 0) {
 198                debug("unsupported driver strength %d\n", strength);
 199                return ret;
 200        }
 201
 202        /* enable the write to the equivalent lower bits */
 203        data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16);
 204
 205        data |= (ret << bit);
 206        ret = regmap_write(regmap, reg, data);
 207        return ret;
 208}
 209
 210#define RV1108_SCHMITT_PMU_OFFSET               0x30
 211#define RV1108_SCHMITT_GRF_OFFSET               0x388
 212#define RV1108_SCHMITT_BANK_STRIDE              8
 213#define RV1108_SCHMITT_PINS_PER_GRF_REG         16
 214#define RV1108_SCHMITT_PINS_PER_PMU_REG         8
 215
 216static int rv1108_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
 217                                           int pin_num,
 218                                           struct regmap **regmap,
 219                                           int *reg, u8 *bit)
 220{
 221        struct rockchip_pinctrl_priv *priv = bank->priv;
 222        int pins_per_reg;
 223
 224        if (bank->bank_num == 0) {
 225                *regmap = priv->regmap_pmu;
 226                *reg = RV1108_SCHMITT_PMU_OFFSET;
 227                pins_per_reg = RV1108_SCHMITT_PINS_PER_PMU_REG;
 228        } else {
 229                *regmap = priv->regmap_base;
 230                *reg = RV1108_SCHMITT_GRF_OFFSET;
 231                pins_per_reg = RV1108_SCHMITT_PINS_PER_GRF_REG;
 232                *reg += (bank->bank_num  - 1) * RV1108_SCHMITT_BANK_STRIDE;
 233        }
 234        *reg += ((pin_num / pins_per_reg) * 4);
 235        *bit = pin_num % pins_per_reg;
 236
 237        return 0;
 238}
 239
 240static int rv1108_set_schmitt(struct rockchip_pin_bank *bank,
 241                              int pin_num, int enable)
 242{
 243        struct regmap *regmap;
 244        int reg;
 245        u8 bit;
 246        u32 data;
 247
 248        rv1108_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
 249        /* enable the write to the equivalent lower bits */
 250        data = BIT(bit + 16) | (enable << bit);
 251
 252        return regmap_write(regmap, reg, data);
 253}
 254
 255static struct rockchip_pin_bank rv1108_pin_banks[] = {
 256        PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU,
 257                                             IOMUX_SOURCE_PMU,
 258                                             IOMUX_SOURCE_PMU,
 259                                             IOMUX_SOURCE_PMU),
 260        PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0),
 261        PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0),
 262        PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0),
 263};
 264
 265static struct rockchip_pin_ctrl rv1108_pin_ctrl = {
 266        .pin_banks              = rv1108_pin_banks,
 267        .nr_banks               = ARRAY_SIZE(rv1108_pin_banks),
 268        .grf_mux_offset         = 0x10,
 269        .pmu_mux_offset         = 0x0,
 270        .iomux_recalced         = rv1108_mux_recalced_data,
 271        .niomux_recalced        = ARRAY_SIZE(rv1108_mux_recalced_data),
 272        .set_mux                = rv1108_set_mux,
 273        .set_pull               = rv1108_set_pull,
 274        .set_drive              = rv1108_set_drive,
 275        .set_schmitt            = rv1108_set_schmitt,
 276};
 277
 278static const struct udevice_id rv1108_pinctrl_ids[] = {
 279        {
 280                .compatible = "rockchip,rv1108-pinctrl",
 281                .data = (ulong)&rv1108_pin_ctrl
 282        },
 283        { }
 284};
 285
 286U_BOOT_DRIVER(pinctrl_rv1108) = {
 287        .name           = "pinctrl_rv1108",
 288        .id             = UCLASS_PINCTRL,
 289        .of_match       = rv1108_pinctrl_ids,
 290        .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv),
 291        .ops            = &rockchip_pinctrl_ops,
 292#if !CONFIG_IS_ENABLED(OF_PLATDATA)
 293        .bind           = dm_scan_fdt_dev,
 294#endif
 295        .probe          = rockchip_pinctrl_probe,
 296};
 297