1a68a7844SNobuhiro Iwamatsu // SPDX-License-Identifier: GPL-2.0 2a68a7844SNobuhiro Iwamatsu /* 3a68a7844SNobuhiro Iwamatsu * Copyright (c) 2020 TOSHIBA CORPORATION 4a68a7844SNobuhiro Iwamatsu * Copyright (c) 2020 Toshiba Electronic Devices & Storage Corporation 5a68a7844SNobuhiro Iwamatsu * Copyright (c) 2020 Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> 6a68a7844SNobuhiro Iwamatsu */ 7a68a7844SNobuhiro Iwamatsu 8a68a7844SNobuhiro Iwamatsu #include <linux/init.h> 9a68a7844SNobuhiro Iwamatsu #include <linux/of.h> 10a68a7844SNobuhiro Iwamatsu #include <linux/io.h> 11a68a7844SNobuhiro Iwamatsu #include <linux/platform_device.h> 12a68a7844SNobuhiro Iwamatsu #include <linux/pinctrl/pinctrl.h> 13a68a7844SNobuhiro Iwamatsu #include <linux/pinctrl/pinmux.h> 14a68a7844SNobuhiro Iwamatsu #include <linux/pinctrl/pinconf.h> 15a68a7844SNobuhiro Iwamatsu #include <linux/pinctrl/pinconf-generic.h> 16a68a7844SNobuhiro Iwamatsu #include "pinctrl-common.h" 17a68a7844SNobuhiro Iwamatsu #include "../core.h" 18a68a7844SNobuhiro Iwamatsu #include "../pinconf.h" 19a68a7844SNobuhiro Iwamatsu #include "../pinctrl-utils.h" 20a68a7844SNobuhiro Iwamatsu 21a68a7844SNobuhiro Iwamatsu #define DSEL_MASK GENMASK(3, 0) 22a68a7844SNobuhiro Iwamatsu 23a68a7844SNobuhiro Iwamatsu /* private data */ 24a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl { 25a68a7844SNobuhiro Iwamatsu void __iomem *base; 26a68a7844SNobuhiro Iwamatsu struct device *dev; 27a68a7844SNobuhiro Iwamatsu struct pinctrl_dev *pctl; 28a68a7844SNobuhiro Iwamatsu struct pinctrl_desc pctl_desc; 29a68a7844SNobuhiro Iwamatsu 30a68a7844SNobuhiro Iwamatsu const struct visconti_pinctrl_devdata *devdata; 31a68a7844SNobuhiro Iwamatsu 32a68a7844SNobuhiro Iwamatsu spinlock_t lock; /* protect pinctrl register */ 33a68a7844SNobuhiro Iwamatsu }; 34a68a7844SNobuhiro Iwamatsu 35a68a7844SNobuhiro Iwamatsu /* pinconf */ 36a68a7844SNobuhiro Iwamatsu static int visconti_pin_config_set(struct pinctrl_dev *pctldev, 37a68a7844SNobuhiro Iwamatsu unsigned int _pin, 38a68a7844SNobuhiro Iwamatsu unsigned long *configs, 39a68a7844SNobuhiro Iwamatsu unsigned int num_configs) 40a68a7844SNobuhiro Iwamatsu { 41a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 42a68a7844SNobuhiro Iwamatsu const struct visconti_desc_pin *pin = &priv->devdata->pins[_pin]; 43a68a7844SNobuhiro Iwamatsu enum pin_config_param param; 44a68a7844SNobuhiro Iwamatsu unsigned int arg; 45a68a7844SNobuhiro Iwamatsu int i, ret = 0; 46a68a7844SNobuhiro Iwamatsu unsigned int val, set_val, pude_val; 47a68a7844SNobuhiro Iwamatsu unsigned long flags; 48a68a7844SNobuhiro Iwamatsu 49a68a7844SNobuhiro Iwamatsu dev_dbg(priv->dev, "%s: pin = %d (%s)\n", __func__, _pin, pin->pin.name); 50a68a7844SNobuhiro Iwamatsu 51a68a7844SNobuhiro Iwamatsu spin_lock_irqsave(&priv->lock, flags); 52a68a7844SNobuhiro Iwamatsu 53a68a7844SNobuhiro Iwamatsu for (i = 0; i < num_configs; i++) { 54a68a7844SNobuhiro Iwamatsu set_val = 0; 55a68a7844SNobuhiro Iwamatsu pude_val = 0; 56a68a7844SNobuhiro Iwamatsu 57a68a7844SNobuhiro Iwamatsu param = pinconf_to_config_param(configs[i]); 58a68a7844SNobuhiro Iwamatsu switch (param) { 59a68a7844SNobuhiro Iwamatsu case PIN_CONFIG_BIAS_PULL_UP: 60a68a7844SNobuhiro Iwamatsu set_val = 1; 61a68a7844SNobuhiro Iwamatsu fallthrough; 62a68a7844SNobuhiro Iwamatsu case PIN_CONFIG_BIAS_PULL_DOWN: 63a68a7844SNobuhiro Iwamatsu /* update pudsel setting */ 64a68a7844SNobuhiro Iwamatsu val = readl(priv->base + pin->pudsel_offset); 65a68a7844SNobuhiro Iwamatsu val &= ~BIT(pin->pud_shift); 66a68a7844SNobuhiro Iwamatsu val |= set_val << pin->pud_shift; 67a68a7844SNobuhiro Iwamatsu writel(val, priv->base + pin->pudsel_offset); 68a68a7844SNobuhiro Iwamatsu pude_val = 1; 69a68a7844SNobuhiro Iwamatsu fallthrough; 70a68a7844SNobuhiro Iwamatsu case PIN_CONFIG_BIAS_DISABLE: 71a68a7844SNobuhiro Iwamatsu /* update pude setting */ 72a68a7844SNobuhiro Iwamatsu val = readl(priv->base + pin->pude_offset); 73a68a7844SNobuhiro Iwamatsu val &= ~BIT(pin->pud_shift); 74a68a7844SNobuhiro Iwamatsu val |= pude_val << pin->pud_shift; 75a68a7844SNobuhiro Iwamatsu writel(val, priv->base + pin->pude_offset); 76a68a7844SNobuhiro Iwamatsu dev_dbg(priv->dev, "BIAS(%d): off = 0x%x val = 0x%x\n", 77a68a7844SNobuhiro Iwamatsu param, pin->pude_offset, val); 78a68a7844SNobuhiro Iwamatsu break; 79a68a7844SNobuhiro Iwamatsu 80a68a7844SNobuhiro Iwamatsu case PIN_CONFIG_DRIVE_STRENGTH: 81a68a7844SNobuhiro Iwamatsu arg = pinconf_to_config_argument(configs[i]); 82a68a7844SNobuhiro Iwamatsu dev_dbg(priv->dev, "DRV_STR arg = %d\n", arg); 83a68a7844SNobuhiro Iwamatsu switch (arg) { 84a68a7844SNobuhiro Iwamatsu case 2: 85a68a7844SNobuhiro Iwamatsu case 4: 86a68a7844SNobuhiro Iwamatsu case 8: 87a68a7844SNobuhiro Iwamatsu case 16: 88a68a7844SNobuhiro Iwamatsu case 24: 89a68a7844SNobuhiro Iwamatsu case 32: 90a68a7844SNobuhiro Iwamatsu /* 91a68a7844SNobuhiro Iwamatsu * I/O drive capacity setting: 92a68a7844SNobuhiro Iwamatsu * 2mA: 0 93a68a7844SNobuhiro Iwamatsu * 4mA: 1 94a68a7844SNobuhiro Iwamatsu * 8mA: 3 95a68a7844SNobuhiro Iwamatsu * 16mA: 7 96a68a7844SNobuhiro Iwamatsu * 24mA: 11 97a68a7844SNobuhiro Iwamatsu * 32mA: 15 98a68a7844SNobuhiro Iwamatsu */ 99a68a7844SNobuhiro Iwamatsu set_val = DIV_ROUND_CLOSEST(arg, 2) - 1; 100a68a7844SNobuhiro Iwamatsu break; 101a68a7844SNobuhiro Iwamatsu default: 102a68a7844SNobuhiro Iwamatsu ret = -EINVAL; 103a68a7844SNobuhiro Iwamatsu goto err; 104a68a7844SNobuhiro Iwamatsu } 105a68a7844SNobuhiro Iwamatsu /* update drive setting */ 106a68a7844SNobuhiro Iwamatsu val = readl(priv->base + pin->dsel_offset); 107a68a7844SNobuhiro Iwamatsu val &= ~(DSEL_MASK << pin->dsel_shift); 108a68a7844SNobuhiro Iwamatsu val |= set_val << pin->dsel_shift; 109a68a7844SNobuhiro Iwamatsu writel(val, priv->base + pin->dsel_offset); 110a68a7844SNobuhiro Iwamatsu break; 111a68a7844SNobuhiro Iwamatsu 112a68a7844SNobuhiro Iwamatsu default: 113a68a7844SNobuhiro Iwamatsu ret = -EOPNOTSUPP; 114a68a7844SNobuhiro Iwamatsu goto err; 115a68a7844SNobuhiro Iwamatsu } 116a68a7844SNobuhiro Iwamatsu } 117a68a7844SNobuhiro Iwamatsu err: 118a68a7844SNobuhiro Iwamatsu spin_unlock_irqrestore(&priv->lock, flags); 119a68a7844SNobuhiro Iwamatsu return ret; 120a68a7844SNobuhiro Iwamatsu } 121a68a7844SNobuhiro Iwamatsu 122a68a7844SNobuhiro Iwamatsu static int visconti_pin_config_group_set(struct pinctrl_dev *pctldev, 123a68a7844SNobuhiro Iwamatsu unsigned int selector, 124a68a7844SNobuhiro Iwamatsu unsigned long *configs, 125a68a7844SNobuhiro Iwamatsu unsigned int num_configs) 126a68a7844SNobuhiro Iwamatsu { 127a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 128a68a7844SNobuhiro Iwamatsu const unsigned int *pins; 129a68a7844SNobuhiro Iwamatsu unsigned int num_pins; 130a68a7844SNobuhiro Iwamatsu int i, ret; 131a68a7844SNobuhiro Iwamatsu 132a68a7844SNobuhiro Iwamatsu pins = priv->devdata->groups[selector].pins; 133a68a7844SNobuhiro Iwamatsu num_pins = priv->devdata->groups[selector].nr_pins; 134a68a7844SNobuhiro Iwamatsu 135a68a7844SNobuhiro Iwamatsu dev_dbg(priv->dev, "%s: select = %d, n_pin = %d, n_config = %d\n", 136a68a7844SNobuhiro Iwamatsu __func__, selector, num_pins, num_configs); 137a68a7844SNobuhiro Iwamatsu 138a68a7844SNobuhiro Iwamatsu for (i = 0; i < num_pins; i++) { 139a68a7844SNobuhiro Iwamatsu ret = visconti_pin_config_set(pctldev, pins[i], 140a68a7844SNobuhiro Iwamatsu configs, num_configs); 141a68a7844SNobuhiro Iwamatsu if (ret) 142a68a7844SNobuhiro Iwamatsu return ret; 143a68a7844SNobuhiro Iwamatsu } 144a68a7844SNobuhiro Iwamatsu 145a68a7844SNobuhiro Iwamatsu return 0; 146a68a7844SNobuhiro Iwamatsu } 147a68a7844SNobuhiro Iwamatsu static const struct pinconf_ops visconti_pinconf_ops = { 148a68a7844SNobuhiro Iwamatsu .is_generic = true, 149a68a7844SNobuhiro Iwamatsu .pin_config_set = visconti_pin_config_set, 150a68a7844SNobuhiro Iwamatsu .pin_config_group_set = visconti_pin_config_group_set, 151a68a7844SNobuhiro Iwamatsu .pin_config_config_dbg_show = pinconf_generic_dump_config, 152a68a7844SNobuhiro Iwamatsu }; 153a68a7844SNobuhiro Iwamatsu 154a68a7844SNobuhiro Iwamatsu /* pinctrl */ 155a68a7844SNobuhiro Iwamatsu static int visconti_get_groups_count(struct pinctrl_dev *pctldev) 156a68a7844SNobuhiro Iwamatsu { 157a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 158a68a7844SNobuhiro Iwamatsu 159a68a7844SNobuhiro Iwamatsu return priv->devdata->nr_groups; 160a68a7844SNobuhiro Iwamatsu } 161a68a7844SNobuhiro Iwamatsu 162a68a7844SNobuhiro Iwamatsu static const char *visconti_get_group_name(struct pinctrl_dev *pctldev, 163a68a7844SNobuhiro Iwamatsu unsigned int selector) 164a68a7844SNobuhiro Iwamatsu { 165a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 166a68a7844SNobuhiro Iwamatsu 167a68a7844SNobuhiro Iwamatsu return priv->devdata->groups[selector].name; 168a68a7844SNobuhiro Iwamatsu } 169a68a7844SNobuhiro Iwamatsu 170a68a7844SNobuhiro Iwamatsu static int visconti_get_group_pins(struct pinctrl_dev *pctldev, 171a68a7844SNobuhiro Iwamatsu unsigned int selector, 172a68a7844SNobuhiro Iwamatsu const unsigned int **pins, 173a68a7844SNobuhiro Iwamatsu unsigned int *num_pins) 174a68a7844SNobuhiro Iwamatsu { 175a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 176a68a7844SNobuhiro Iwamatsu 177a68a7844SNobuhiro Iwamatsu *pins = priv->devdata->groups[selector].pins; 178a68a7844SNobuhiro Iwamatsu *num_pins = priv->devdata->groups[selector].nr_pins; 179a68a7844SNobuhiro Iwamatsu 180a68a7844SNobuhiro Iwamatsu return 0; 181a68a7844SNobuhiro Iwamatsu } 182a68a7844SNobuhiro Iwamatsu 183a68a7844SNobuhiro Iwamatsu static const struct pinctrl_ops visconti_pinctrl_ops = { 184a68a7844SNobuhiro Iwamatsu .get_groups_count = visconti_get_groups_count, 185a68a7844SNobuhiro Iwamatsu .get_group_name = visconti_get_group_name, 186a68a7844SNobuhiro Iwamatsu .get_group_pins = visconti_get_group_pins, 187a68a7844SNobuhiro Iwamatsu .dt_node_to_map = pinconf_generic_dt_node_to_map_group, 188a68a7844SNobuhiro Iwamatsu .dt_free_map = pinctrl_utils_free_map, 189a68a7844SNobuhiro Iwamatsu }; 190a68a7844SNobuhiro Iwamatsu 191a68a7844SNobuhiro Iwamatsu /* pinmux */ 192a68a7844SNobuhiro Iwamatsu static int visconti_get_functions_count(struct pinctrl_dev *pctldev) 193a68a7844SNobuhiro Iwamatsu { 194a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 195a68a7844SNobuhiro Iwamatsu 196a68a7844SNobuhiro Iwamatsu return priv->devdata->nr_functions; 197a68a7844SNobuhiro Iwamatsu } 198a68a7844SNobuhiro Iwamatsu 199a68a7844SNobuhiro Iwamatsu static const char *visconti_get_function_name(struct pinctrl_dev *pctldev, 200a68a7844SNobuhiro Iwamatsu unsigned int selector) 201a68a7844SNobuhiro Iwamatsu { 202a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 203a68a7844SNobuhiro Iwamatsu 204a68a7844SNobuhiro Iwamatsu return priv->devdata->functions[selector].name; 205a68a7844SNobuhiro Iwamatsu } 206a68a7844SNobuhiro Iwamatsu 207a68a7844SNobuhiro Iwamatsu static int visconti_get_function_groups(struct pinctrl_dev *pctldev, 208a68a7844SNobuhiro Iwamatsu unsigned int selector, 209a68a7844SNobuhiro Iwamatsu const char * const **groups, 210a68a7844SNobuhiro Iwamatsu unsigned * const num_groups) 211a68a7844SNobuhiro Iwamatsu { 212a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 213a68a7844SNobuhiro Iwamatsu 214a68a7844SNobuhiro Iwamatsu *groups = priv->devdata->functions[selector].groups; 215a68a7844SNobuhiro Iwamatsu *num_groups = priv->devdata->functions[selector].nr_groups; 216a68a7844SNobuhiro Iwamatsu 217a68a7844SNobuhiro Iwamatsu return 0; 218a68a7844SNobuhiro Iwamatsu } 219a68a7844SNobuhiro Iwamatsu 220a68a7844SNobuhiro Iwamatsu static int visconti_set_mux(struct pinctrl_dev *pctldev, 221a68a7844SNobuhiro Iwamatsu unsigned int function, unsigned int group) 222a68a7844SNobuhiro Iwamatsu { 223a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); 224a68a7844SNobuhiro Iwamatsu const struct visconti_pin_function *func = &priv->devdata->functions[function]; 225a68a7844SNobuhiro Iwamatsu const struct visconti_pin_group *grp = &priv->devdata->groups[group]; 226a68a7844SNobuhiro Iwamatsu const struct visconti_mux *mux = &grp->mux; 227a68a7844SNobuhiro Iwamatsu unsigned int val; 228a68a7844SNobuhiro Iwamatsu unsigned long flags; 229a68a7844SNobuhiro Iwamatsu 230a68a7844SNobuhiro Iwamatsu dev_dbg(priv->dev, "%s: function = %d(%s) group = %d(%s)\n", __func__, 231a68a7844SNobuhiro Iwamatsu function, func->name, group, grp->name); 232a68a7844SNobuhiro Iwamatsu 233a68a7844SNobuhiro Iwamatsu spin_lock_irqsave(&priv->lock, flags); 234a68a7844SNobuhiro Iwamatsu 235a68a7844SNobuhiro Iwamatsu /* update mux */ 236a68a7844SNobuhiro Iwamatsu val = readl(priv->base + mux->offset); 237a68a7844SNobuhiro Iwamatsu val &= ~mux->mask; 238a68a7844SNobuhiro Iwamatsu val |= mux->val; 239a68a7844SNobuhiro Iwamatsu writel(val, priv->base + mux->offset); 240a68a7844SNobuhiro Iwamatsu 241a68a7844SNobuhiro Iwamatsu spin_unlock_irqrestore(&priv->lock, flags); 242a68a7844SNobuhiro Iwamatsu 243a68a7844SNobuhiro Iwamatsu dev_dbg(priv->dev, "[%x]: 0x%x\n", mux->offset, val); 244a68a7844SNobuhiro Iwamatsu 245a68a7844SNobuhiro Iwamatsu return 0; 246a68a7844SNobuhiro Iwamatsu } 247a68a7844SNobuhiro Iwamatsu 248a68a7844SNobuhiro Iwamatsu static const struct pinmux_ops visconti_pinmux_ops = { 249a68a7844SNobuhiro Iwamatsu .get_functions_count = visconti_get_functions_count, 250a68a7844SNobuhiro Iwamatsu .get_function_name = visconti_get_function_name, 251a68a7844SNobuhiro Iwamatsu .get_function_groups = visconti_get_function_groups, 252a68a7844SNobuhiro Iwamatsu .set_mux = visconti_set_mux, 253a68a7844SNobuhiro Iwamatsu .strict = true, 254a68a7844SNobuhiro Iwamatsu }; 255a68a7844SNobuhiro Iwamatsu 256a68a7844SNobuhiro Iwamatsu int visconti_pinctrl_probe(struct platform_device *pdev, 257a68a7844SNobuhiro Iwamatsu const struct visconti_pinctrl_devdata *devdata) 258a68a7844SNobuhiro Iwamatsu { 259a68a7844SNobuhiro Iwamatsu struct device *dev = &pdev->dev; 260a68a7844SNobuhiro Iwamatsu struct visconti_pinctrl *priv; 261a68a7844SNobuhiro Iwamatsu struct pinctrl_pin_desc *pins; 262a68a7844SNobuhiro Iwamatsu int i, ret; 263a68a7844SNobuhiro Iwamatsu 264a68a7844SNobuhiro Iwamatsu priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 265a68a7844SNobuhiro Iwamatsu if (!priv) 266a68a7844SNobuhiro Iwamatsu return -ENOMEM; 267a68a7844SNobuhiro Iwamatsu 268a68a7844SNobuhiro Iwamatsu priv->dev = dev; 269a68a7844SNobuhiro Iwamatsu priv->devdata = devdata; 270a68a7844SNobuhiro Iwamatsu spin_lock_init(&priv->lock); 271a68a7844SNobuhiro Iwamatsu 272a68a7844SNobuhiro Iwamatsu priv->base = devm_platform_ioremap_resource(pdev, 0); 273a68a7844SNobuhiro Iwamatsu if (IS_ERR(priv->base)) { 274a68a7844SNobuhiro Iwamatsu dev_err(dev, "unable to map I/O space\n"); 275a68a7844SNobuhiro Iwamatsu return PTR_ERR(priv->base); 276a68a7844SNobuhiro Iwamatsu } 277a68a7844SNobuhiro Iwamatsu 278a68a7844SNobuhiro Iwamatsu pins = devm_kcalloc(dev, devdata->nr_pins, 279a68a7844SNobuhiro Iwamatsu sizeof(*pins), GFP_KERNEL); 280a68a7844SNobuhiro Iwamatsu if (!pins) 281a68a7844SNobuhiro Iwamatsu return -ENOMEM; 282a68a7844SNobuhiro Iwamatsu 283a68a7844SNobuhiro Iwamatsu for (i = 0; i < devdata->nr_pins; i++) 284a68a7844SNobuhiro Iwamatsu pins[i] = devdata->pins[i].pin; 285a68a7844SNobuhiro Iwamatsu 286a68a7844SNobuhiro Iwamatsu priv->pctl_desc.name = dev_name(dev); 287a68a7844SNobuhiro Iwamatsu priv->pctl_desc.owner = THIS_MODULE; 288a68a7844SNobuhiro Iwamatsu priv->pctl_desc.pins = pins; 289a68a7844SNobuhiro Iwamatsu priv->pctl_desc.npins = devdata->nr_pins; 290a68a7844SNobuhiro Iwamatsu priv->pctl_desc.confops = &visconti_pinconf_ops; 291a68a7844SNobuhiro Iwamatsu priv->pctl_desc.pctlops = &visconti_pinctrl_ops; 292a68a7844SNobuhiro Iwamatsu priv->pctl_desc.pmxops = &visconti_pinmux_ops; 293a68a7844SNobuhiro Iwamatsu 294a68a7844SNobuhiro Iwamatsu ret = devm_pinctrl_register_and_init(dev, &priv->pctl_desc, 295a68a7844SNobuhiro Iwamatsu priv, &priv->pctl); 296a68a7844SNobuhiro Iwamatsu if (ret) { 297a68a7844SNobuhiro Iwamatsu dev_err(dev, "couldn't register pinctrl: %d\n", ret); 298a68a7844SNobuhiro Iwamatsu return ret; 299a68a7844SNobuhiro Iwamatsu } 300a68a7844SNobuhiro Iwamatsu 301a68a7844SNobuhiro Iwamatsu if (devdata->unlock) 302a68a7844SNobuhiro Iwamatsu devdata->unlock(priv->base); 303a68a7844SNobuhiro Iwamatsu 304a68a7844SNobuhiro Iwamatsu return pinctrl_enable(priv->pctl); 305a68a7844SNobuhiro Iwamatsu } 306