1*488d704eSConor Dooley // SPDX-License-Identifier: GPL-2.0 2*488d704eSConor Dooley 3*488d704eSConor Dooley #include <linux/bitfield.h> 4*488d704eSConor Dooley #include <linux/module.h> 5*488d704eSConor Dooley #include <linux/mfd/syscon.h> 6*488d704eSConor Dooley #include <linux/mod_devicetable.h> 7*488d704eSConor Dooley #include <linux/of.h> 8*488d704eSConor Dooley #include <linux/platform_device.h> 9*488d704eSConor Dooley #include <linux/regmap.h> 10*488d704eSConor Dooley #include <linux/seq_file.h> 11*488d704eSConor Dooley 12*488d704eSConor Dooley #include <linux/pinctrl/pinconf-generic.h> 13*488d704eSConor Dooley #include <linux/pinctrl/pinconf.h> 14*488d704eSConor Dooley #include <linux/pinctrl/pinctrl.h> 15*488d704eSConor Dooley #include <linux/pinctrl/pinmux.h> 16*488d704eSConor Dooley 17*488d704eSConor Dooley #include "../core.h" 18*488d704eSConor Dooley #include "../pinctrl-utils.h" 19*488d704eSConor Dooley #include "../pinconf.h" 20*488d704eSConor Dooley #include "../pinmux.h" 21*488d704eSConor Dooley 22*488d704eSConor Dooley #define MPFS_PINCTRL_PAD_MUX_MASK GENMASK(3, 0) 23*488d704eSConor Dooley 24*488d704eSConor Dooley #define MPFS_PINCTRL_IOCFG_MASK GENMASK(14, 0) 25*488d704eSConor Dooley #define MPFS_PINCTRL_IBUFMD_MASK GENMASK(2, 0) 26*488d704eSConor Dooley #define MPFS_PINCTRL_DRV_MASK GENMASK(6, 3) 27*488d704eSConor Dooley #define MPFS_PINCTRL_CLAMP BIT(7) 28*488d704eSConor Dooley #define MPFS_PINCTRL_ENHYST BIT(8) 29*488d704eSConor Dooley #define MPFS_PINCTRL_LOCKDN BIT(9) 30*488d704eSConor Dooley #define MPFS_PINCTRL_WPD BIT(10) 31*488d704eSConor Dooley #define MPFS_PINCTRL_WPU BIT(11) 32*488d704eSConor Dooley #define MPFS_PINCTRL_PULL_MASK GENMASK(11, 10) 33*488d704eSConor Dooley #define MPFS_PINCTRL_LP_PERSIST_EN BIT(12) 34*488d704eSConor Dooley #define MPFS_PINCTRL_LP_BYPASS_EN BIT(13) 35*488d704eSConor Dooley 36*488d704eSConor Dooley #define MPFS_PINCTRL_MSSIO_BANK2_CFG_CR 0x1c4 37*488d704eSConor Dooley #define MPFS_PINCTRL_MSSIO_BANK4_CFG_CR 0x1c8 38*488d704eSConor Dooley #define MPFS_PINCTRL_BANK_VOLTAGE_MASK GENMASK(19, 16) 39*488d704eSConor Dooley 40*488d704eSConor Dooley #define MPFS_PINCTRL_IOCFG01_REG 0x234 41*488d704eSConor Dooley 42*488d704eSConor Dooley #define MPFS_PINCTRL_INTER_BANK_GAP 0x4 43*488d704eSConor Dooley 44*488d704eSConor Dooley #define MPFS_PINCTRL_BANK2_START 14 45*488d704eSConor Dooley 46*488d704eSConor Dooley #define MPFS_PINCTRL_LOCKDOWN (PIN_CONFIG_END + 1) 47*488d704eSConor Dooley #define MPFS_PINCTRL_CLAMP_DIODE (PIN_CONFIG_END + 2) 48*488d704eSConor Dooley #define MPFS_PINCTRL_IBUFMD (PIN_CONFIG_END + 3) 49*488d704eSConor Dooley 50*488d704eSConor Dooley struct mpfs_pinctrl_mux_config { 51*488d704eSConor Dooley u8 pin; 52*488d704eSConor Dooley u8 function; 53*488d704eSConor Dooley }; 54*488d704eSConor Dooley 55*488d704eSConor Dooley struct mpfs_pinctrl { 56*488d704eSConor Dooley struct pinctrl_dev *pctrl; 57*488d704eSConor Dooley struct device *dev; 58*488d704eSConor Dooley struct regmap *regmap; 59*488d704eSConor Dooley struct regmap *sysreg_regmap; 60*488d704eSConor Dooley struct mutex mutex; 61*488d704eSConor Dooley struct pinctrl_desc desc; 62*488d704eSConor Dooley }; 63*488d704eSConor Dooley 64*488d704eSConor Dooley struct mpfs_pinctrl_drive_strength { 65*488d704eSConor Dooley u8 ma; 66*488d704eSConor Dooley u8 val; 67*488d704eSConor Dooley }; 68*488d704eSConor Dooley 69*488d704eSConor Dooley struct mpfs_pinctrl_bank_voltage { 70*488d704eSConor Dooley u32 uv; 71*488d704eSConor Dooley u8 val; 72*488d704eSConor Dooley }; 73*488d704eSConor Dooley 74*488d704eSConor Dooley static struct mpfs_pinctrl_drive_strength mpfs_pinctrl_drive_strengths[8] = { 75*488d704eSConor Dooley { .ma = 2, .val = 2 }, 76*488d704eSConor Dooley { .ma = 4, .val = 3 }, 77*488d704eSConor Dooley { .ma = 6, .val = 4 }, 78*488d704eSConor Dooley { .ma = 8, .val = 5 }, 79*488d704eSConor Dooley { .ma = 10, .val = 6 }, 80*488d704eSConor Dooley { .ma = 12, .val = 7 }, 81*488d704eSConor Dooley { .ma = 16, .val = 10 }, 82*488d704eSConor Dooley { .ma = 20, .val = 12 }, 83*488d704eSConor Dooley }; 84*488d704eSConor Dooley static struct mpfs_pinctrl_bank_voltage mpfs_pinctrl_bank_voltages[8] = { 85*488d704eSConor Dooley { .uv = 1200000, .val = 0 }, 86*488d704eSConor Dooley { .uv = 1500000, .val = 2 }, 87*488d704eSConor Dooley { .uv = 1800000, .val = 4 }, 88*488d704eSConor Dooley { .uv = 2500000, .val = 6 }, 89*488d704eSConor Dooley { .uv = 3300000, .val = 8 }, 90*488d704eSConor Dooley { .uv = 0, .val = 0x3f }, // pin unused 91*488d704eSConor Dooley }; 92*488d704eSConor Dooley 93*488d704eSConor Dooley static int mpfs_pinctrl_get_drive_strength_ma(u32 drive_strength) 94*488d704eSConor Dooley { 95*488d704eSConor Dooley size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths); 96*488d704eSConor Dooley 97*488d704eSConor Dooley for (int i = 0; i < num; i++) 98*488d704eSConor Dooley if (drive_strength == mpfs_pinctrl_drive_strengths[i].val) 99*488d704eSConor Dooley return mpfs_pinctrl_drive_strengths[i].ma; 100*488d704eSConor Dooley 101*488d704eSConor Dooley return -EINVAL; 102*488d704eSConor Dooley } 103*488d704eSConor Dooley 104*488d704eSConor Dooley static int mpfs_pinctrl_get_drive_strength_val(u32 drive_strength_ma) 105*488d704eSConor Dooley { 106*488d704eSConor Dooley size_t num = ARRAY_SIZE(mpfs_pinctrl_drive_strengths); 107*488d704eSConor Dooley 108*488d704eSConor Dooley if (!drive_strength_ma) 109*488d704eSConor Dooley return -EINVAL; 110*488d704eSConor Dooley 111*488d704eSConor Dooley for (int i = 0; i < num; i++) 112*488d704eSConor Dooley if (drive_strength_ma <= mpfs_pinctrl_drive_strengths[i].ma) 113*488d704eSConor Dooley return mpfs_pinctrl_drive_strengths[i].val; 114*488d704eSConor Dooley 115*488d704eSConor Dooley return mpfs_pinctrl_drive_strengths[num - 1].val; 116*488d704eSConor Dooley } 117*488d704eSConor Dooley 118*488d704eSConor Dooley static int mpfs_pinctrl_get_bank_voltage_uv(u32 bank_voltage) 119*488d704eSConor Dooley { 120*488d704eSConor Dooley size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages); 121*488d704eSConor Dooley 122*488d704eSConor Dooley for (int i = 0; i < num; i++) 123*488d704eSConor Dooley if (bank_voltage == mpfs_pinctrl_bank_voltages[i].val) 124*488d704eSConor Dooley return mpfs_pinctrl_bank_voltages[i].uv; 125*488d704eSConor Dooley 126*488d704eSConor Dooley return -EINVAL; 127*488d704eSConor Dooley } 128*488d704eSConor Dooley 129*488d704eSConor Dooley static int mpfs_pinctrl_get_bank_voltage_val(u32 bank_voltage_uv) 130*488d704eSConor Dooley { 131*488d704eSConor Dooley size_t num = ARRAY_SIZE(mpfs_pinctrl_bank_voltages); 132*488d704eSConor Dooley 133*488d704eSConor Dooley for (int i = 0; i < num; i++) 134*488d704eSConor Dooley if (bank_voltage_uv <= mpfs_pinctrl_bank_voltages[i].uv) 135*488d704eSConor Dooley return mpfs_pinctrl_bank_voltages[i].val; 136*488d704eSConor Dooley 137*488d704eSConor Dooley return -EINVAL; 138*488d704eSConor Dooley } 139*488d704eSConor Dooley 140*488d704eSConor Dooley static u32 mpfs_pinctrl_pin_to_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin) 141*488d704eSConor Dooley { 142*488d704eSConor Dooley u32 bank_voltage, val; 143*488d704eSConor Dooley 144*488d704eSConor Dooley if (pin < MPFS_PINCTRL_BANK2_START) 145*488d704eSConor Dooley regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR, &val); 146*488d704eSConor Dooley else 147*488d704eSConor Dooley regmap_read(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR, &val); 148*488d704eSConor Dooley 149*488d704eSConor Dooley bank_voltage = FIELD_GET(MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); 150*488d704eSConor Dooley 151*488d704eSConor Dooley return mpfs_pinctrl_get_bank_voltage_uv(bank_voltage); 152*488d704eSConor Dooley } 153*488d704eSConor Dooley 154*488d704eSConor Dooley static void mpfs_pinctrl_set_bank_voltage(struct mpfs_pinctrl *pctrl, unsigned int pin, 155*488d704eSConor Dooley u32 bank_voltage) 156*488d704eSConor Dooley { 157*488d704eSConor Dooley u32 val = FIELD_PREP(MPFS_PINCTRL_BANK_VOLTAGE_MASK, bank_voltage); 158*488d704eSConor Dooley 159*488d704eSConor Dooley if (pin < MPFS_PINCTRL_BANK2_START) 160*488d704eSConor Dooley regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK4_CFG_CR, 161*488d704eSConor Dooley MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); 162*488d704eSConor Dooley else 163*488d704eSConor Dooley regmap_assign_bits(pctrl->sysreg_regmap, MPFS_PINCTRL_MSSIO_BANK2_CFG_CR, 164*488d704eSConor Dooley MPFS_PINCTRL_BANK_VOLTAGE_MASK, val); 165*488d704eSConor Dooley } 166*488d704eSConor Dooley 167*488d704eSConor Dooley static char *mpfs_pinctrl_function_names[] = { 168*488d704eSConor Dooley "sd", 169*488d704eSConor Dooley "emmc", 170*488d704eSConor Dooley "qspi", 171*488d704eSConor Dooley "spi", 172*488d704eSConor Dooley "usb", 173*488d704eSConor Dooley "uart", 174*488d704eSConor Dooley "i2c", 175*488d704eSConor Dooley "can", 176*488d704eSConor Dooley "mdio", 177*488d704eSConor Dooley "misc", 178*488d704eSConor Dooley "reserved", 179*488d704eSConor Dooley "gpio", 180*488d704eSConor Dooley "fabric test", 181*488d704eSConor Dooley "tied-low", 182*488d704eSConor Dooley "tied-high", 183*488d704eSConor Dooley "tristate" 184*488d704eSConor Dooley }; 185*488d704eSConor Dooley 186*488d704eSConor Dooley static int mpfs_pinctrl_function_map(const char *function) 187*488d704eSConor Dooley { 188*488d704eSConor Dooley size_t num = ARRAY_SIZE(mpfs_pinctrl_function_names); 189*488d704eSConor Dooley 190*488d704eSConor Dooley for (int i = 0; i < num; i++) 191*488d704eSConor Dooley if (!strcmp(function, mpfs_pinctrl_function_names[i])) 192*488d704eSConor Dooley return i; 193*488d704eSConor Dooley 194*488d704eSConor Dooley return -EINVAL; 195*488d704eSConor Dooley } 196*488d704eSConor Dooley 197*488d704eSConor Dooley static const struct pinconf_generic_params mpfs_pinctrl_custom_bindings[] = { 198*488d704eSConor Dooley { "microchip,clamp-diode", MPFS_PINCTRL_CLAMP_DIODE, 1 }, 199*488d704eSConor Dooley { "microchip,ibufmd", MPFS_PINCTRL_IBUFMD, 0x0 }, 200*488d704eSConor Dooley }; 201*488d704eSConor Dooley 202*488d704eSConor Dooley static int mpfs_pinctrl_pin_to_iomux_offset(unsigned int pin) 203*488d704eSConor Dooley { 204*488d704eSConor Dooley int offset; 205*488d704eSConor Dooley 206*488d704eSConor Dooley switch (pin) { 207*488d704eSConor Dooley case 0 ... 7: 208*488d704eSConor Dooley offset = pin * 4; 209*488d704eSConor Dooley break; 210*488d704eSConor Dooley case 8 ... 13: 211*488d704eSConor Dooley offset = (pin - 8) * 4; 212*488d704eSConor Dooley break; 213*488d704eSConor Dooley case 14 ... 21: 214*488d704eSConor Dooley offset = (pin - 14) * 4; 215*488d704eSConor Dooley break; 216*488d704eSConor Dooley case 22 ... 29: 217*488d704eSConor Dooley offset = (pin - 22) * 4; 218*488d704eSConor Dooley break; 219*488d704eSConor Dooley case 30 ... 37: 220*488d704eSConor Dooley offset = (pin - 30) * 4; 221*488d704eSConor Dooley break; 222*488d704eSConor Dooley default: 223*488d704eSConor Dooley offset = -EINVAL; 224*488d704eSConor Dooley } 225*488d704eSConor Dooley 226*488d704eSConor Dooley return offset; 227*488d704eSConor Dooley } 228*488d704eSConor Dooley 229*488d704eSConor Dooley static int mpfs_pinctrl_pin_to_iomux_reg(unsigned int pin) 230*488d704eSConor Dooley { 231*488d704eSConor Dooley int reg; 232*488d704eSConor Dooley 233*488d704eSConor Dooley switch (pin) { 234*488d704eSConor Dooley case 0 ... 7: 235*488d704eSConor Dooley reg = 0x204; 236*488d704eSConor Dooley break; 237*488d704eSConor Dooley case 8 ... 13: 238*488d704eSConor Dooley reg = 0x208; 239*488d704eSConor Dooley break; 240*488d704eSConor Dooley case 14 ... 21: 241*488d704eSConor Dooley reg = 0x20c; 242*488d704eSConor Dooley break; 243*488d704eSConor Dooley case 22 ... 29: 244*488d704eSConor Dooley reg = 0x210; 245*488d704eSConor Dooley break; 246*488d704eSConor Dooley case 30 ... 37: 247*488d704eSConor Dooley reg = 0x214; 248*488d704eSConor Dooley break; 249*488d704eSConor Dooley default: 250*488d704eSConor Dooley reg = -EINVAL; 251*488d704eSConor Dooley } 252*488d704eSConor Dooley 253*488d704eSConor Dooley return reg; 254*488d704eSConor Dooley } 255*488d704eSConor Dooley 256*488d704eSConor Dooley static int mpfs_pinctrl_pin_to_iocfg_reg(unsigned int pin) 257*488d704eSConor Dooley { 258*488d704eSConor Dooley u32 reg = MPFS_PINCTRL_IOCFG01_REG; 259*488d704eSConor Dooley 260*488d704eSConor Dooley if (pin >= MPFS_PINCTRL_BANK2_START) 261*488d704eSConor Dooley reg += MPFS_PINCTRL_INTER_BANK_GAP; 262*488d704eSConor Dooley 263*488d704eSConor Dooley // 2 pins per 32-bit register 264*488d704eSConor Dooley reg += (pin / 2) * 0x4; 265*488d704eSConor Dooley 266*488d704eSConor Dooley return reg; 267*488d704eSConor Dooley } 268*488d704eSConor Dooley 269*488d704eSConor Dooley static int mpfs_pinctrl_pin_to_iocfg_offset(unsigned int pin) 270*488d704eSConor Dooley { 271*488d704eSConor Dooley return 16 * (pin % 2); 272*488d704eSConor Dooley } 273*488d704eSConor Dooley 274*488d704eSConor Dooley static void mpfs_pinctrl_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, 275*488d704eSConor Dooley unsigned int pin) 276*488d704eSConor Dooley { 277*488d704eSConor Dooley struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 278*488d704eSConor Dooley u32 func; 279*488d704eSConor Dooley int reg, offset; 280*488d704eSConor Dooley 281*488d704eSConor Dooley reg = mpfs_pinctrl_pin_to_iomux_reg(pin); 282*488d704eSConor Dooley offset = mpfs_pinctrl_pin_to_iomux_offset(pin); 283*488d704eSConor Dooley 284*488d704eSConor Dooley seq_printf(seq, "reg: %x, offset: %u ", reg, offset); 285*488d704eSConor Dooley seq_printf(seq, "pin: %u ", pin); 286*488d704eSConor Dooley 287*488d704eSConor Dooley if (reg < 0 || offset < 0) 288*488d704eSConor Dooley return; 289*488d704eSConor Dooley 290*488d704eSConor Dooley regmap_read(pctrl->regmap, reg, &func); 291*488d704eSConor Dooley func = (func >> offset) & MPFS_PINCTRL_PAD_MUX_MASK; 292*488d704eSConor Dooley seq_printf(seq, "func: %s (%x)\n", mpfs_pinctrl_function_names[func], func); 293*488d704eSConor Dooley } 294*488d704eSConor Dooley 295*488d704eSConor Dooley static const struct pinctrl_ops mpfs_pinctrl_ops = { 296*488d704eSConor Dooley .get_groups_count = pinctrl_generic_get_group_count, 297*488d704eSConor Dooley .get_group_name = pinctrl_generic_get_group_name, 298*488d704eSConor Dooley .get_group_pins = pinctrl_generic_get_group_pins, 299*488d704eSConor Dooley .pin_dbg_show = mpfs_pinctrl_dbg_show, 300*488d704eSConor Dooley .dt_node_to_map = pinctrl_generic_pins_function_dt_node_to_map, 301*488d704eSConor Dooley .dt_free_map = pinctrl_utils_free_map, 302*488d704eSConor Dooley }; 303*488d704eSConor Dooley 304*488d704eSConor Dooley static int mpfs_pinctrl_set_pin_func(struct mpfs_pinctrl *pctrl, u8 pin, u8 function) 305*488d704eSConor Dooley { 306*488d704eSConor Dooley struct device *dev = pctrl->dev; 307*488d704eSConor Dooley int reg, offset; 308*488d704eSConor Dooley u32 func, mask; 309*488d704eSConor Dooley 310*488d704eSConor Dooley reg = mpfs_pinctrl_pin_to_iomux_reg(pin); 311*488d704eSConor Dooley offset = mpfs_pinctrl_pin_to_iomux_offset(pin); 312*488d704eSConor Dooley 313*488d704eSConor Dooley func = function << offset; 314*488d704eSConor Dooley mask = MPFS_PINCTRL_PAD_MUX_MASK << offset; 315*488d704eSConor Dooley 316*488d704eSConor Dooley dev_dbg(dev, "Setting pin %u. reg: %x offset %u func %x\n", pin, reg, offset, func); 317*488d704eSConor Dooley 318*488d704eSConor Dooley if (reg < 0 || offset < 0) 319*488d704eSConor Dooley return -EINVAL; 320*488d704eSConor Dooley 321*488d704eSConor Dooley regmap_update_bits(pctrl->regmap, reg, mask, func); 322*488d704eSConor Dooley 323*488d704eSConor Dooley return 0; 324*488d704eSConor Dooley } 325*488d704eSConor Dooley 326*488d704eSConor Dooley static int mpfs_pinctrl_set_mux(struct pinctrl_dev *pctrl_dev, unsigned int fsel, 327*488d704eSConor Dooley unsigned int gsel) 328*488d704eSConor Dooley { 329*488d704eSConor Dooley struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 330*488d704eSConor Dooley const struct group_desc *group; 331*488d704eSConor Dooley const char **functions; 332*488d704eSConor Dooley 333*488d704eSConor Dooley group = pinctrl_generic_get_group(pctrl_dev, gsel); 334*488d704eSConor Dooley if (!group) 335*488d704eSConor Dooley return -EINVAL; 336*488d704eSConor Dooley 337*488d704eSConor Dooley functions = group->data; 338*488d704eSConor Dooley 339*488d704eSConor Dooley for (int i = 0; i < group->grp.npins; i++) { 340*488d704eSConor Dooley int function; 341*488d704eSConor Dooley 342*488d704eSConor Dooley function = mpfs_pinctrl_function_map(functions[i]); 343*488d704eSConor Dooley if (function < 0) { 344*488d704eSConor Dooley dev_err(pctrl->dev, "invalid function %s\n", functions[i]); 345*488d704eSConor Dooley return function; 346*488d704eSConor Dooley } 347*488d704eSConor Dooley 348*488d704eSConor Dooley mpfs_pinctrl_set_pin_func(pctrl, group->grp.pins[i], function); 349*488d704eSConor Dooley } 350*488d704eSConor Dooley 351*488d704eSConor Dooley return 0; 352*488d704eSConor Dooley } 353*488d704eSConor Dooley 354*488d704eSConor Dooley static const struct pinmux_ops mpfs_pinctrl_pinmux_ops = { 355*488d704eSConor Dooley .get_functions_count = pinmux_generic_get_function_count, 356*488d704eSConor Dooley .get_function_name = pinmux_generic_get_function_name, 357*488d704eSConor Dooley .get_function_groups = pinmux_generic_get_function_groups, 358*488d704eSConor Dooley .set_mux = mpfs_pinctrl_set_mux, 359*488d704eSConor Dooley }; 360*488d704eSConor Dooley 361*488d704eSConor Dooley static int mpfs_pinctrl_pinconf_get(struct pinctrl_dev *pctrl_dev, unsigned int pin, 362*488d704eSConor Dooley unsigned long *config) 363*488d704eSConor Dooley { 364*488d704eSConor Dooley struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 365*488d704eSConor Dooley int param = pinconf_to_config_param(*config); 366*488d704eSConor Dooley int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); 367*488d704eSConor Dooley int val; 368*488d704eSConor Dooley u32 arg; 369*488d704eSConor Dooley u8 str; 370*488d704eSConor Dooley 371*488d704eSConor Dooley regmap_read(pctrl->regmap, reg, &val); 372*488d704eSConor Dooley 373*488d704eSConor Dooley val = val >> mpfs_pinctrl_pin_to_iocfg_offset(pin); 374*488d704eSConor Dooley val = val & MPFS_PINCTRL_IOCFG_MASK; 375*488d704eSConor Dooley 376*488d704eSConor Dooley switch (param) { 377*488d704eSConor Dooley case PIN_CONFIG_BIAS_BUS_HOLD: 378*488d704eSConor Dooley if (!(val & MPFS_PINCTRL_WPD)) 379*488d704eSConor Dooley return -EINVAL; 380*488d704eSConor Dooley 381*488d704eSConor Dooley if (!(val & MPFS_PINCTRL_WPU)) 382*488d704eSConor Dooley return -EINVAL; 383*488d704eSConor Dooley 384*488d704eSConor Dooley arg = 1; 385*488d704eSConor Dooley break; 386*488d704eSConor Dooley case PIN_CONFIG_BIAS_PULL_DOWN: 387*488d704eSConor Dooley if (!(val & MPFS_PINCTRL_WPD)) 388*488d704eSConor Dooley return -EINVAL; 389*488d704eSConor Dooley 390*488d704eSConor Dooley if (val & MPFS_PINCTRL_WPU) 391*488d704eSConor Dooley return -EINVAL; 392*488d704eSConor Dooley 393*488d704eSConor Dooley arg = 1; 394*488d704eSConor Dooley break; 395*488d704eSConor Dooley case PIN_CONFIG_BIAS_PULL_UP: 396*488d704eSConor Dooley if (!(val & MPFS_PINCTRL_WPU)) 397*488d704eSConor Dooley return -EINVAL; 398*488d704eSConor Dooley 399*488d704eSConor Dooley if (val & MPFS_PINCTRL_WPD) 400*488d704eSConor Dooley return -EINVAL; 401*488d704eSConor Dooley 402*488d704eSConor Dooley arg = 1; 403*488d704eSConor Dooley break; 404*488d704eSConor Dooley case PIN_CONFIG_BIAS_DISABLE: 405*488d704eSConor Dooley if (val & MPFS_PINCTRL_PULL_MASK) 406*488d704eSConor Dooley return -EINVAL; 407*488d704eSConor Dooley 408*488d704eSConor Dooley arg = 1; 409*488d704eSConor Dooley break; 410*488d704eSConor Dooley case PIN_CONFIG_DRIVE_STRENGTH: 411*488d704eSConor Dooley str = FIELD_GET(MPFS_PINCTRL_DRV_MASK, val); 412*488d704eSConor Dooley if (!str) 413*488d704eSConor Dooley return -EINVAL; 414*488d704eSConor Dooley 415*488d704eSConor Dooley arg = mpfs_pinctrl_get_drive_strength_ma(str); 416*488d704eSConor Dooley break; 417*488d704eSConor Dooley case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 418*488d704eSConor Dooley if (!FIELD_GET(MPFS_PINCTRL_ENHYST, val)) 419*488d704eSConor Dooley return -EINVAL; 420*488d704eSConor Dooley 421*488d704eSConor Dooley arg = 1; 422*488d704eSConor Dooley break; 423*488d704eSConor Dooley case PIN_CONFIG_PERSIST_STATE: 424*488d704eSConor Dooley if (!FIELD_GET(MPFS_PINCTRL_LP_PERSIST_EN, val)) 425*488d704eSConor Dooley return -EINVAL; 426*488d704eSConor Dooley 427*488d704eSConor Dooley arg = 1; 428*488d704eSConor Dooley break; 429*488d704eSConor Dooley case PIN_CONFIG_MODE_LOW_POWER: 430*488d704eSConor Dooley if (!FIELD_GET(MPFS_PINCTRL_LP_BYPASS_EN, val)) 431*488d704eSConor Dooley return -EINVAL; 432*488d704eSConor Dooley 433*488d704eSConor Dooley arg = 1; 434*488d704eSConor Dooley break; 435*488d704eSConor Dooley case PIN_CONFIG_POWER_SOURCE: 436*488d704eSConor Dooley arg = mpfs_pinctrl_pin_to_bank_voltage(pctrl, pin); 437*488d704eSConor Dooley break; 438*488d704eSConor Dooley case MPFS_PINCTRL_CLAMP_DIODE: 439*488d704eSConor Dooley if (!FIELD_GET(MPFS_PINCTRL_CLAMP, val)) 440*488d704eSConor Dooley return -EINVAL; 441*488d704eSConor Dooley 442*488d704eSConor Dooley arg = 1; 443*488d704eSConor Dooley break; 444*488d704eSConor Dooley case MPFS_PINCTRL_LOCKDOWN: 445*488d704eSConor Dooley /* 446*488d704eSConor Dooley * Lockdown is a read-only configuration, it'll get set if the 447*488d704eSConor Dooley * tamper unit triggers global lockdown and lockdown has been 448*488d704eSConor Dooley * set in the MSS Configurator for the bank a pin belongs to. 449*488d704eSConor Dooley */ 450*488d704eSConor Dooley if (!FIELD_GET(MPFS_PINCTRL_LOCKDN, val)) 451*488d704eSConor Dooley return -EINVAL; 452*488d704eSConor Dooley 453*488d704eSConor Dooley arg = 1; 454*488d704eSConor Dooley break; 455*488d704eSConor Dooley case MPFS_PINCTRL_IBUFMD: 456*488d704eSConor Dooley arg = FIELD_GET(MPFS_PINCTRL_IBUFMD_MASK, val); 457*488d704eSConor Dooley break; 458*488d704eSConor Dooley default: 459*488d704eSConor Dooley return -ENOTSUPP; 460*488d704eSConor Dooley } 461*488d704eSConor Dooley 462*488d704eSConor Dooley *config = pinconf_to_config_packed(param, arg); 463*488d704eSConor Dooley 464*488d704eSConor Dooley return 0; 465*488d704eSConor Dooley } 466*488d704eSConor Dooley 467*488d704eSConor Dooley static int mpfs_pinctrl_pinconf_generate_config(struct mpfs_pinctrl *pctrl, unsigned int pin, 468*488d704eSConor Dooley unsigned long *configs, unsigned int num_configs, 469*488d704eSConor Dooley u32 *value, u32 *bank_voltage) 470*488d704eSConor Dooley { 471*488d704eSConor Dooley u32 val = 0; 472*488d704eSConor Dooley 473*488d704eSConor Dooley for (int i = 0; i < num_configs; i++) { 474*488d704eSConor Dooley int param, tmp; 475*488d704eSConor Dooley u32 arg; 476*488d704eSConor Dooley 477*488d704eSConor Dooley param = pinconf_to_config_param(configs[i]); 478*488d704eSConor Dooley arg = pinconf_to_config_argument(configs[i]); 479*488d704eSConor Dooley 480*488d704eSConor Dooley switch (param) { 481*488d704eSConor Dooley case PIN_CONFIG_BIAS_BUS_HOLD: 482*488d704eSConor Dooley val |= MPFS_PINCTRL_PULL_MASK; 483*488d704eSConor Dooley break; 484*488d704eSConor Dooley case PIN_CONFIG_BIAS_PULL_DOWN: 485*488d704eSConor Dooley val &= ~MPFS_PINCTRL_PULL_MASK; 486*488d704eSConor Dooley val |= MPFS_PINCTRL_WPD; 487*488d704eSConor Dooley break; 488*488d704eSConor Dooley case PIN_CONFIG_BIAS_PULL_UP: 489*488d704eSConor Dooley val &= ~MPFS_PINCTRL_PULL_MASK; 490*488d704eSConor Dooley val |= MPFS_PINCTRL_WPU; 491*488d704eSConor Dooley break; 492*488d704eSConor Dooley case PIN_CONFIG_BIAS_DISABLE: 493*488d704eSConor Dooley val &= ~MPFS_PINCTRL_PULL_MASK; 494*488d704eSConor Dooley break; 495*488d704eSConor Dooley case PIN_CONFIG_DRIVE_STRENGTH: 496*488d704eSConor Dooley tmp = mpfs_pinctrl_get_drive_strength_val(arg); 497*488d704eSConor Dooley if (tmp < 0) 498*488d704eSConor Dooley return tmp; 499*488d704eSConor Dooley 500*488d704eSConor Dooley val |= FIELD_PREP(MPFS_PINCTRL_DRV_MASK, tmp); 501*488d704eSConor Dooley break; 502*488d704eSConor Dooley case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 503*488d704eSConor Dooley if (!arg) 504*488d704eSConor Dooley break; 505*488d704eSConor Dooley val |= MPFS_PINCTRL_ENHYST; 506*488d704eSConor Dooley break; 507*488d704eSConor Dooley case PIN_CONFIG_PERSIST_STATE: 508*488d704eSConor Dooley val |= MPFS_PINCTRL_LP_PERSIST_EN; 509*488d704eSConor Dooley break; 510*488d704eSConor Dooley case PIN_CONFIG_MODE_LOW_POWER: 511*488d704eSConor Dooley if (arg) 512*488d704eSConor Dooley val |= MPFS_PINCTRL_LP_BYPASS_EN; 513*488d704eSConor Dooley break; 514*488d704eSConor Dooley case PIN_CONFIG_POWER_SOURCE: 515*488d704eSConor Dooley tmp = mpfs_pinctrl_get_bank_voltage_val(arg); 516*488d704eSConor Dooley if (tmp < 0) 517*488d704eSConor Dooley return tmp; 518*488d704eSConor Dooley 519*488d704eSConor Dooley *bank_voltage = tmp; 520*488d704eSConor Dooley break; 521*488d704eSConor Dooley case MPFS_PINCTRL_CLAMP_DIODE: 522*488d704eSConor Dooley val |= MPFS_PINCTRL_CLAMP; 523*488d704eSConor Dooley break; 524*488d704eSConor Dooley case MPFS_PINCTRL_IBUFMD: 525*488d704eSConor Dooley val |= FIELD_PREP(MPFS_PINCTRL_IBUFMD_MASK, arg); 526*488d704eSConor Dooley break; 527*488d704eSConor Dooley default: 528*488d704eSConor Dooley dev_err(pctrl->dev, "config %u not supported\n", param); 529*488d704eSConor Dooley return -ENOTSUPP; 530*488d704eSConor Dooley } 531*488d704eSConor Dooley } 532*488d704eSConor Dooley 533*488d704eSConor Dooley *value = val; 534*488d704eSConor Dooley return 0; 535*488d704eSConor Dooley } 536*488d704eSConor Dooley 537*488d704eSConor Dooley static int mpfs_pinctrl_pin_set_config(struct mpfs_pinctrl *pctrl, unsigned int pin, u32 config) 538*488d704eSConor Dooley { 539*488d704eSConor Dooley int reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); 540*488d704eSConor Dooley int offset = mpfs_pinctrl_pin_to_iocfg_offset(pin); 541*488d704eSConor Dooley u32 val, mask; 542*488d704eSConor Dooley 543*488d704eSConor Dooley mask = MPFS_PINCTRL_IOCFG_MASK << offset; 544*488d704eSConor Dooley val = config << offset; 545*488d704eSConor Dooley 546*488d704eSConor Dooley regmap_update_bits(pctrl->regmap, reg, mask, val); 547*488d704eSConor Dooley 548*488d704eSConor Dooley return 0; 549*488d704eSConor Dooley } 550*488d704eSConor Dooley 551*488d704eSConor Dooley static int mpfs_pinctrl_pinconf_set(struct pinctrl_dev *pctrl_dev, unsigned int pin, 552*488d704eSConor Dooley unsigned long *configs, unsigned int num_configs) 553*488d704eSConor Dooley { 554*488d704eSConor Dooley struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 555*488d704eSConor Dooley u32 val, bank_voltage = 0; 556*488d704eSConor Dooley int ret; 557*488d704eSConor Dooley 558*488d704eSConor Dooley ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val, 559*488d704eSConor Dooley &bank_voltage); 560*488d704eSConor Dooley if (ret) 561*488d704eSConor Dooley return ret; 562*488d704eSConor Dooley 563*488d704eSConor Dooley ret = mpfs_pinctrl_pin_set_config(pctrl, pin, val); 564*488d704eSConor Dooley if (ret) 565*488d704eSConor Dooley return ret; 566*488d704eSConor Dooley 567*488d704eSConor Dooley if (bank_voltage) 568*488d704eSConor Dooley mpfs_pinctrl_set_bank_voltage(pctrl, pin, bank_voltage); 569*488d704eSConor Dooley 570*488d704eSConor Dooley return 0; 571*488d704eSConor Dooley } 572*488d704eSConor Dooley 573*488d704eSConor Dooley static int mpfs_pinctrl_pinconf_group_set(struct pinctrl_dev *pctrl_dev, unsigned int gsel, 574*488d704eSConor Dooley unsigned long *configs, unsigned int num_configs) 575*488d704eSConor Dooley { 576*488d704eSConor Dooley struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 577*488d704eSConor Dooley const struct group_desc *group; 578*488d704eSConor Dooley unsigned int pin; 579*488d704eSConor Dooley u32 val, bank_voltage = 0; 580*488d704eSConor Dooley int ret; 581*488d704eSConor Dooley 582*488d704eSConor Dooley group = pinctrl_generic_get_group(pctrl_dev, gsel); 583*488d704eSConor Dooley if (!group) 584*488d704eSConor Dooley return -EINVAL; 585*488d704eSConor Dooley 586*488d704eSConor Dooley /* 587*488d704eSConor Dooley * Assume that the first pin in a group is representative, as the mss 588*488d704eSConor Dooley * configurator doesn't allow splitting a function between two banks. 589*488d704eSConor Dooley */ 590*488d704eSConor Dooley pin = group->grp.pins[0]; 591*488d704eSConor Dooley 592*488d704eSConor Dooley ret = mpfs_pinctrl_pinconf_generate_config(pctrl, pin, configs, num_configs, &val, 593*488d704eSConor Dooley &bank_voltage); 594*488d704eSConor Dooley if (ret) 595*488d704eSConor Dooley return ret; 596*488d704eSConor Dooley 597*488d704eSConor Dooley for (int i = 0; i < group->grp.npins; i++) 598*488d704eSConor Dooley mpfs_pinctrl_pin_set_config(pctrl, group->grp.pins[i], val); 599*488d704eSConor Dooley 600*488d704eSConor Dooley if (bank_voltage) 601*488d704eSConor Dooley mpfs_pinctrl_set_bank_voltage(pctrl, group->grp.pins[0], bank_voltage); 602*488d704eSConor Dooley 603*488d704eSConor Dooley return 0; 604*488d704eSConor Dooley } 605*488d704eSConor Dooley 606*488d704eSConor Dooley static void mpfs_pinctrl_pinconf_dbg_show(struct pinctrl_dev *pctrl_dev, struct seq_file *seq, 607*488d704eSConor Dooley unsigned int pin) 608*488d704eSConor Dooley { 609*488d704eSConor Dooley struct mpfs_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); 610*488d704eSConor Dooley u32 val; 611*488d704eSConor Dooley int reg, offset; 612*488d704eSConor Dooley 613*488d704eSConor Dooley reg = mpfs_pinctrl_pin_to_iocfg_reg(pin); 614*488d704eSConor Dooley offset = mpfs_pinctrl_pin_to_iocfg_offset(pin); 615*488d704eSConor Dooley 616*488d704eSConor Dooley seq_printf(seq, "pin: %u ", pin); 617*488d704eSConor Dooley seq_printf(seq, "reg: %x offset: %u ", reg, offset); 618*488d704eSConor Dooley 619*488d704eSConor Dooley if (reg < 0 || offset < 0) 620*488d704eSConor Dooley return; 621*488d704eSConor Dooley 622*488d704eSConor Dooley regmap_read(pctrl->regmap, reg, &val); 623*488d704eSConor Dooley val = (val & (MPFS_PINCTRL_IOCFG_MASK << offset)) >> offset; 624*488d704eSConor Dooley seq_printf(seq, "val: %x\n", val); 625*488d704eSConor Dooley } 626*488d704eSConor Dooley 627*488d704eSConor Dooley static const struct pinconf_ops mpfs_pinctrl_pinconf_ops = { 628*488d704eSConor Dooley .pin_config_get = mpfs_pinctrl_pinconf_get, 629*488d704eSConor Dooley .pin_config_set = mpfs_pinctrl_pinconf_set, 630*488d704eSConor Dooley .pin_config_group_set = mpfs_pinctrl_pinconf_group_set, 631*488d704eSConor Dooley .pin_config_dbg_show = mpfs_pinctrl_pinconf_dbg_show, 632*488d704eSConor Dooley .is_generic = true, 633*488d704eSConor Dooley }; 634*488d704eSConor Dooley 635*488d704eSConor Dooley static const struct pinctrl_pin_desc mpfs_pinctrl_pins[] = { 636*488d704eSConor Dooley PINCTRL_PIN(0, "bank 4 0"), 637*488d704eSConor Dooley PINCTRL_PIN(1, "bank 4 1"), 638*488d704eSConor Dooley PINCTRL_PIN(2, "bank 4 2"), 639*488d704eSConor Dooley PINCTRL_PIN(3, "bank 4 3"), 640*488d704eSConor Dooley PINCTRL_PIN(4, "bank 4 4"), 641*488d704eSConor Dooley PINCTRL_PIN(5, "bank 4 5"), 642*488d704eSConor Dooley PINCTRL_PIN(6, "bank 4 6"), 643*488d704eSConor Dooley PINCTRL_PIN(7, "bank 4 7"), 644*488d704eSConor Dooley PINCTRL_PIN(8, "bank 4 8"), 645*488d704eSConor Dooley PINCTRL_PIN(9, "bank 4 9"), 646*488d704eSConor Dooley PINCTRL_PIN(10, "bank 4 10"), 647*488d704eSConor Dooley PINCTRL_PIN(11, "bank 4 11"), 648*488d704eSConor Dooley PINCTRL_PIN(12, "bank 4 12"), 649*488d704eSConor Dooley PINCTRL_PIN(13, "bank 4 13"), 650*488d704eSConor Dooley 651*488d704eSConor Dooley PINCTRL_PIN(14, "bank 2 0"), 652*488d704eSConor Dooley PINCTRL_PIN(15, "bank 2 1"), 653*488d704eSConor Dooley PINCTRL_PIN(16, "bank 2 2"), 654*488d704eSConor Dooley PINCTRL_PIN(17, "bank 2 3"), 655*488d704eSConor Dooley PINCTRL_PIN(18, "bank 2 4"), 656*488d704eSConor Dooley PINCTRL_PIN(19, "bank 2 5"), 657*488d704eSConor Dooley PINCTRL_PIN(20, "bank 2 6"), 658*488d704eSConor Dooley PINCTRL_PIN(21, "bank 2 7"), 659*488d704eSConor Dooley PINCTRL_PIN(22, "bank 2 8"), 660*488d704eSConor Dooley PINCTRL_PIN(23, "bank 2 9"), 661*488d704eSConor Dooley PINCTRL_PIN(24, "bank 2 10"), 662*488d704eSConor Dooley PINCTRL_PIN(25, "bank 2 11"), 663*488d704eSConor Dooley PINCTRL_PIN(26, "bank 2 12"), 664*488d704eSConor Dooley PINCTRL_PIN(27, "bank 2 13"), 665*488d704eSConor Dooley PINCTRL_PIN(28, "bank 2 14"), 666*488d704eSConor Dooley PINCTRL_PIN(29, "bank 2 15"), 667*488d704eSConor Dooley PINCTRL_PIN(30, "bank 2 16"), 668*488d704eSConor Dooley PINCTRL_PIN(31, "bank 2 17"), 669*488d704eSConor Dooley PINCTRL_PIN(32, "bank 2 18"), 670*488d704eSConor Dooley PINCTRL_PIN(33, "bank 2 19"), 671*488d704eSConor Dooley PINCTRL_PIN(34, "bank 2 20"), 672*488d704eSConor Dooley PINCTRL_PIN(35, "bank 2 21"), 673*488d704eSConor Dooley PINCTRL_PIN(36, "bank 2 22"), 674*488d704eSConor Dooley PINCTRL_PIN(37, "bank 2 23"), 675*488d704eSConor Dooley }; 676*488d704eSConor Dooley 677*488d704eSConor Dooley static int mpfs_pinctrl_probe(struct platform_device *pdev) 678*488d704eSConor Dooley { 679*488d704eSConor Dooley struct device *dev = &pdev->dev; 680*488d704eSConor Dooley struct mpfs_pinctrl *pctrl; 681*488d704eSConor Dooley int ret; 682*488d704eSConor Dooley 683*488d704eSConor Dooley pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); 684*488d704eSConor Dooley if (!pctrl) 685*488d704eSConor Dooley return -ENOMEM; 686*488d704eSConor Dooley 687*488d704eSConor Dooley pctrl->regmap = device_node_to_regmap(pdev->dev.parent->of_node); 688*488d704eSConor Dooley if (IS_ERR(pctrl->regmap)) 689*488d704eSConor Dooley dev_err_probe(dev, PTR_ERR(pctrl->regmap), "Failed to find syscon regmap\n"); 690*488d704eSConor Dooley 691*488d704eSConor Dooley pctrl->sysreg_regmap = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb"); 692*488d704eSConor Dooley if (IS_ERR(pctrl->sysreg_regmap)) 693*488d704eSConor Dooley return PTR_ERR(pctrl->sysreg_regmap); 694*488d704eSConor Dooley 695*488d704eSConor Dooley pctrl->desc.name = dev_name(dev); 696*488d704eSConor Dooley pctrl->desc.pins = mpfs_pinctrl_pins; 697*488d704eSConor Dooley pctrl->desc.npins = ARRAY_SIZE(mpfs_pinctrl_pins); 698*488d704eSConor Dooley pctrl->desc.pctlops = &mpfs_pinctrl_ops; 699*488d704eSConor Dooley pctrl->desc.pmxops = &mpfs_pinctrl_pinmux_ops; 700*488d704eSConor Dooley pctrl->desc.confops = &mpfs_pinctrl_pinconf_ops; 701*488d704eSConor Dooley pctrl->desc.owner = THIS_MODULE; 702*488d704eSConor Dooley pctrl->desc.num_custom_params = ARRAY_SIZE(mpfs_pinctrl_custom_bindings); 703*488d704eSConor Dooley pctrl->desc.custom_params = mpfs_pinctrl_custom_bindings; 704*488d704eSConor Dooley 705*488d704eSConor Dooley pctrl->dev = dev; 706*488d704eSConor Dooley 707*488d704eSConor Dooley ret = devm_mutex_init(dev, &pctrl->mutex); 708*488d704eSConor Dooley if (ret) 709*488d704eSConor Dooley return ret; 710*488d704eSConor Dooley 711*488d704eSConor Dooley platform_set_drvdata(pdev, pctrl); 712*488d704eSConor Dooley 713*488d704eSConor Dooley pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl); 714*488d704eSConor Dooley if (IS_ERR(pctrl->pctrl)) 715*488d704eSConor Dooley return PTR_ERR(pctrl->pctrl); 716*488d704eSConor Dooley 717*488d704eSConor Dooley return 0; 718*488d704eSConor Dooley } 719*488d704eSConor Dooley 720*488d704eSConor Dooley static const struct of_device_id mpfs_pinctrl_of_match[] = { 721*488d704eSConor Dooley { .compatible = "microchip,mpfs-pinctrl-mssio" }, 722*488d704eSConor Dooley { } 723*488d704eSConor Dooley }; 724*488d704eSConor Dooley MODULE_DEVICE_TABLE(of, mpfs_pinctrl_of_match); 725*488d704eSConor Dooley 726*488d704eSConor Dooley static struct platform_driver mpfs_pinctrl_driver = { 727*488d704eSConor Dooley .driver = { 728*488d704eSConor Dooley .name = "mpfs-pinctrl", 729*488d704eSConor Dooley .of_match_table = mpfs_pinctrl_of_match, 730*488d704eSConor Dooley }, 731*488d704eSConor Dooley .probe = mpfs_pinctrl_probe, 732*488d704eSConor Dooley }; 733*488d704eSConor Dooley module_platform_driver(mpfs_pinctrl_driver); 734*488d704eSConor Dooley 735*488d704eSConor Dooley MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>"); 736*488d704eSConor Dooley MODULE_DESCRIPTION("Polarfire SoC mssio pinctrl driver"); 737*488d704eSConor Dooley MODULE_LICENSE("GPL"); 738