599 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ams AS3722 pin control and GPIO driver.4 *5 * Copyright (c) 2013, NVIDIA Corporation.6 *7 * Author: Laxman Dewangan <ldewangan@nvidia.com>8 */9 10#include <linux/delay.h>11#include <linux/gpio/driver.h>12#include <linux/kernel.h>13#include <linux/mod_devicetable.h>14#include <linux/module.h>15#include <linux/mfd/as3722.h>16#include <linux/platform_device.h>17#include <linux/pm.h>18#include <linux/property.h>19#include <linux/slab.h>20 21#include <linux/pinctrl/consumer.h>22#include <linux/pinctrl/machine.h>23#include <linux/pinctrl/pinctrl.h>24#include <linux/pinctrl/pinconf-generic.h>25#include <linux/pinctrl/pinconf.h>26#include <linux/pinctrl/pinmux.h>27 28#include "core.h"29#include "pinconf.h"30#include "pinctrl-utils.h"31 32#define AS3722_PIN_GPIO0 033#define AS3722_PIN_GPIO1 134#define AS3722_PIN_GPIO2 235#define AS3722_PIN_GPIO3 336#define AS3722_PIN_GPIO4 437#define AS3722_PIN_GPIO5 538#define AS3722_PIN_GPIO6 639#define AS3722_PIN_GPIO7 740#define AS3722_PIN_NUM (AS3722_PIN_GPIO7 + 1)41 42#define AS3722_GPIO_MODE_PULL_UP BIT(PIN_CONFIG_BIAS_PULL_UP)43#define AS3722_GPIO_MODE_PULL_DOWN BIT(PIN_CONFIG_BIAS_PULL_DOWN)44#define AS3722_GPIO_MODE_HIGH_IMPED BIT(PIN_CONFIG_BIAS_HIGH_IMPEDANCE)45#define AS3722_GPIO_MODE_OPEN_DRAIN BIT(PIN_CONFIG_DRIVE_OPEN_DRAIN)46 47struct as3722_pin_function {48 const char *name;49 const char * const *groups;50 unsigned ngroups;51 int mux_option;52};53 54struct as3722_gpio_pin_control {55 unsigned mode_prop;56 int io_function;57};58 59struct as3722_pingroup {60 const char *name;61 const unsigned pins[1];62 unsigned npins;63};64 65struct as3722_pctrl_info {66 struct device *dev;67 struct pinctrl_dev *pctl;68 struct as3722 *as3722;69 struct gpio_chip gpio_chip;70 int pins_current_opt[AS3722_PIN_NUM];71 const struct as3722_pin_function *functions;72 unsigned num_functions;73 const struct as3722_pingroup *pin_groups;74 int num_pin_groups;75 const struct pinctrl_pin_desc *pins;76 unsigned num_pins;77 struct as3722_gpio_pin_control gpio_control[AS3722_PIN_NUM];78};79 80static const struct pinctrl_pin_desc as3722_pins_desc[] = {81 PINCTRL_PIN(AS3722_PIN_GPIO0, "gpio0"),82 PINCTRL_PIN(AS3722_PIN_GPIO1, "gpio1"),83 PINCTRL_PIN(AS3722_PIN_GPIO2, "gpio2"),84 PINCTRL_PIN(AS3722_PIN_GPIO3, "gpio3"),85 PINCTRL_PIN(AS3722_PIN_GPIO4, "gpio4"),86 PINCTRL_PIN(AS3722_PIN_GPIO5, "gpio5"),87 PINCTRL_PIN(AS3722_PIN_GPIO6, "gpio6"),88 PINCTRL_PIN(AS3722_PIN_GPIO7, "gpio7"),89};90 91static const char * const gpio_groups[] = {92 "gpio0",93 "gpio1",94 "gpio2",95 "gpio3",96 "gpio4",97 "gpio5",98 "gpio6",99 "gpio7",100};101 102enum as3722_pinmux_option {103 AS3722_PINMUX_GPIO = 0,104 AS3722_PINMUX_INTERRUPT_OUT = 1,105 AS3722_PINMUX_VSUB_VBAT_UNDEB_LOW_OUT = 2,106 AS3722_PINMUX_GPIO_INTERRUPT = 3,107 AS3722_PINMUX_PWM_INPUT = 4,108 AS3722_PINMUX_VOLTAGE_IN_STBY = 5,109 AS3722_PINMUX_OC_PG_SD0 = 6,110 AS3722_PINMUX_PG_OUT = 7,111 AS3722_PINMUX_CLK32K_OUT = 8,112 AS3722_PINMUX_WATCHDOG_INPUT = 9,113 AS3722_PINMUX_SOFT_RESET_IN = 11,114 AS3722_PINMUX_PWM_OUTPUT = 12,115 AS3722_PINMUX_VSUB_VBAT_LOW_DEB_OUT = 13,116 AS3722_PINMUX_OC_PG_SD6 = 14,117};118 119#define FUNCTION_GROUP(fname, mux) \120 { \121 .name = #fname, \122 .groups = gpio_groups, \123 .ngroups = ARRAY_SIZE(gpio_groups), \124 .mux_option = AS3722_PINMUX_##mux, \125 }126 127static const struct as3722_pin_function as3722_pin_function[] = {128 FUNCTION_GROUP(gpio, GPIO),129 FUNCTION_GROUP(interrupt-out, INTERRUPT_OUT),130 FUNCTION_GROUP(gpio-in-interrupt, GPIO_INTERRUPT),131 FUNCTION_GROUP(vsup-vbat-low-undebounce-out, VSUB_VBAT_UNDEB_LOW_OUT),132 FUNCTION_GROUP(vsup-vbat-low-debounce-out, VSUB_VBAT_LOW_DEB_OUT),133 FUNCTION_GROUP(voltage-in-standby, VOLTAGE_IN_STBY),134 FUNCTION_GROUP(oc-pg-sd0, OC_PG_SD0),135 FUNCTION_GROUP(oc-pg-sd6, OC_PG_SD6),136 FUNCTION_GROUP(powergood-out, PG_OUT),137 FUNCTION_GROUP(pwm-in, PWM_INPUT),138 FUNCTION_GROUP(pwm-out, PWM_OUTPUT),139 FUNCTION_GROUP(clk32k-out, CLK32K_OUT),140 FUNCTION_GROUP(watchdog-in, WATCHDOG_INPUT),141 FUNCTION_GROUP(soft-reset-in, SOFT_RESET_IN),142};143 144#define AS3722_PINGROUP(pg_name, pin_id) \145 { \146 .name = #pg_name, \147 .pins = {AS3722_PIN_##pin_id}, \148 .npins = 1, \149 }150 151static const struct as3722_pingroup as3722_pingroups[] = {152 AS3722_PINGROUP(gpio0, GPIO0),153 AS3722_PINGROUP(gpio1, GPIO1),154 AS3722_PINGROUP(gpio2, GPIO2),155 AS3722_PINGROUP(gpio3, GPIO3),156 AS3722_PINGROUP(gpio4, GPIO4),157 AS3722_PINGROUP(gpio5, GPIO5),158 AS3722_PINGROUP(gpio6, GPIO6),159 AS3722_PINGROUP(gpio7, GPIO7),160};161 162static int as3722_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)163{164 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);165 166 return as_pci->num_pin_groups;167}168 169static const char *as3722_pinctrl_get_group_name(struct pinctrl_dev *pctldev,170 unsigned group)171{172 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);173 174 return as_pci->pin_groups[group].name;175}176 177static int as3722_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,178 unsigned group, const unsigned **pins, unsigned *num_pins)179{180 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);181 182 *pins = as_pci->pin_groups[group].pins;183 *num_pins = as_pci->pin_groups[group].npins;184 return 0;185}186 187static const struct pinctrl_ops as3722_pinctrl_ops = {188 .get_groups_count = as3722_pinctrl_get_groups_count,189 .get_group_name = as3722_pinctrl_get_group_name,190 .get_group_pins = as3722_pinctrl_get_group_pins,191 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,192 .dt_free_map = pinctrl_utils_free_map,193};194 195static int as3722_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)196{197 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);198 199 return as_pci->num_functions;200}201 202static const char *as3722_pinctrl_get_func_name(struct pinctrl_dev *pctldev,203 unsigned function)204{205 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);206 207 return as_pci->functions[function].name;208}209 210static int as3722_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,211 unsigned function, const char * const **groups,212 unsigned * const num_groups)213{214 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);215 216 *groups = as_pci->functions[function].groups;217 *num_groups = as_pci->functions[function].ngroups;218 return 0;219}220 221static int as3722_pinctrl_set(struct pinctrl_dev *pctldev, unsigned function,222 unsigned group)223{224 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);225 int gpio_cntr_reg = AS3722_GPIOn_CONTROL_REG(group);226 u8 val = AS3722_GPIO_IOSF_VAL(as_pci->functions[function].mux_option);227 int ret;228 229 dev_dbg(as_pci->dev, "%s(): GPIO %u pin to function %u and val %u\n",230 __func__, group, function, val);231 232 ret = as3722_update_bits(as_pci->as3722, gpio_cntr_reg,233 AS3722_GPIO_IOSF_MASK, val);234 if (ret < 0) {235 dev_err(as_pci->dev, "GPIO%d_CTRL_REG update failed %d\n",236 group, ret);237 return ret;238 }239 as_pci->gpio_control[group].io_function = function;240 241 switch (val) {242 case AS3722_GPIO_IOSF_SD0_OUT:243 case AS3722_GPIO_IOSF_PWR_GOOD_OUT:244 case AS3722_GPIO_IOSF_Q32K_OUT:245 case AS3722_GPIO_IOSF_PWM_OUT:246 case AS3722_GPIO_IOSF_SD6_LOW_VOLT_LOW:247 ret = as3722_update_bits(as_pci->as3722, gpio_cntr_reg,248 AS3722_GPIO_MODE_MASK, AS3722_GPIO_MODE_OUTPUT_VDDH);249 if (ret < 0) {250 dev_err(as_pci->dev, "GPIO%d_CTRL update failed %d\n",251 group, ret);252 return ret;253 }254 as_pci->gpio_control[group].mode_prop =255 AS3722_GPIO_MODE_OUTPUT_VDDH;256 break;257 default:258 break;259 }260 return ret;261}262 263static int as3722_pinctrl_gpio_get_mode(unsigned gpio_mode_prop, bool input)264{265 if (gpio_mode_prop & AS3722_GPIO_MODE_HIGH_IMPED)266 return -EINVAL;267 268 if (gpio_mode_prop & AS3722_GPIO_MODE_OPEN_DRAIN) {269 if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP)270 return AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP;271 return AS3722_GPIO_MODE_IO_OPEN_DRAIN;272 }273 if (input) {274 if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP)275 return AS3722_GPIO_MODE_INPUT_PULL_UP;276 else if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN)277 return AS3722_GPIO_MODE_INPUT_PULL_DOWN;278 return AS3722_GPIO_MODE_INPUT;279 }280 if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN)281 return AS3722_GPIO_MODE_OUTPUT_VDDL;282 return AS3722_GPIO_MODE_OUTPUT_VDDH;283}284 285static int as3722_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev,286 struct pinctrl_gpio_range *range, unsigned offset)287{288 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);289 290 if (as_pci->gpio_control[offset].io_function)291 return -EBUSY;292 return 0;293}294 295static int as3722_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev,296 struct pinctrl_gpio_range *range, unsigned offset, bool input)297{298 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);299 struct as3722 *as3722 = as_pci->as3722;300 int mode;301 302 mode = as3722_pinctrl_gpio_get_mode(303 as_pci->gpio_control[offset].mode_prop, input);304 if (mode < 0) {305 dev_err(as_pci->dev, "%s direction for GPIO %d not supported\n",306 (input) ? "Input" : "Output", offset);307 return mode;308 }309 310 return as3722_update_bits(as3722, AS3722_GPIOn_CONTROL_REG(offset),311 AS3722_GPIO_MODE_MASK, mode);312}313 314static const struct pinmux_ops as3722_pinmux_ops = {315 .get_functions_count = as3722_pinctrl_get_funcs_count,316 .get_function_name = as3722_pinctrl_get_func_name,317 .get_function_groups = as3722_pinctrl_get_func_groups,318 .set_mux = as3722_pinctrl_set,319 .gpio_request_enable = as3722_pinctrl_gpio_request_enable,320 .gpio_set_direction = as3722_pinctrl_gpio_set_direction,321};322 323static int as3722_pinconf_get(struct pinctrl_dev *pctldev,324 unsigned pin, unsigned long *config)325{326 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);327 enum pin_config_param param = pinconf_to_config_param(*config);328 int arg = 0;329 u16 prop;330 331 switch (param) {332 case PIN_CONFIG_BIAS_DISABLE:333 prop = AS3722_GPIO_MODE_PULL_UP |334 AS3722_GPIO_MODE_PULL_DOWN;335 if (!(as_pci->gpio_control[pin].mode_prop & prop))336 arg = 1;337 prop = 0;338 break;339 340 case PIN_CONFIG_BIAS_PULL_UP:341 prop = AS3722_GPIO_MODE_PULL_UP;342 break;343 344 case PIN_CONFIG_BIAS_PULL_DOWN:345 prop = AS3722_GPIO_MODE_PULL_DOWN;346 break;347 348 case PIN_CONFIG_DRIVE_OPEN_DRAIN:349 prop = AS3722_GPIO_MODE_OPEN_DRAIN;350 break;351 352 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:353 prop = AS3722_GPIO_MODE_HIGH_IMPED;354 break;355 356 default:357 dev_err(as_pci->dev, "Properties not supported\n");358 return -ENOTSUPP;359 }360 361 if (as_pci->gpio_control[pin].mode_prop & prop)362 arg = 1;363 364 *config = pinconf_to_config_packed(param, (u16)arg);365 return 0;366}367 368static int as3722_pinconf_set(struct pinctrl_dev *pctldev,369 unsigned pin, unsigned long *configs,370 unsigned num_configs)371{372 struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev);373 enum pin_config_param param;374 int mode_prop;375 int i;376 377 for (i = 0; i < num_configs; i++) {378 param = pinconf_to_config_param(configs[i]);379 mode_prop = as_pci->gpio_control[pin].mode_prop;380 381 switch (param) {382 case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT:383 break;384 385 case PIN_CONFIG_BIAS_DISABLE:386 mode_prop &= ~(AS3722_GPIO_MODE_PULL_UP |387 AS3722_GPIO_MODE_PULL_DOWN);388 break;389 case PIN_CONFIG_BIAS_PULL_UP:390 mode_prop |= AS3722_GPIO_MODE_PULL_UP;391 break;392 393 case PIN_CONFIG_BIAS_PULL_DOWN:394 mode_prop |= AS3722_GPIO_MODE_PULL_DOWN;395 break;396 397 case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:398 mode_prop |= AS3722_GPIO_MODE_HIGH_IMPED;399 break;400 401 case PIN_CONFIG_DRIVE_OPEN_DRAIN:402 mode_prop |= AS3722_GPIO_MODE_OPEN_DRAIN;403 break;404 405 default:406 dev_err(as_pci->dev, "Properties not supported\n");407 return -ENOTSUPP;408 }409 410 as_pci->gpio_control[pin].mode_prop = mode_prop;411 }412 return 0;413}414 415static const struct pinconf_ops as3722_pinconf_ops = {416 .pin_config_get = as3722_pinconf_get,417 .pin_config_set = as3722_pinconf_set,418};419 420static struct pinctrl_desc as3722_pinctrl_desc = {421 .pctlops = &as3722_pinctrl_ops,422 .pmxops = &as3722_pinmux_ops,423 .confops = &as3722_pinconf_ops,424 .owner = THIS_MODULE,425};426 427static int as3722_gpio_get(struct gpio_chip *chip, unsigned offset)428{429 struct as3722_pctrl_info *as_pci = gpiochip_get_data(chip);430 struct as3722 *as3722 = as_pci->as3722;431 int ret;432 u32 reg;433 u32 control;434 u32 val;435 int mode;436 int invert_enable;437 438 ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &control);439 if (ret < 0) {440 dev_err(as_pci->dev,441 "GPIO_CONTROL%d_REG read failed: %d\n", offset, ret);442 return ret;443 }444 445 invert_enable = !!(control & AS3722_GPIO_INV);446 mode = control & AS3722_GPIO_MODE_MASK;447 switch (mode) {448 case AS3722_GPIO_MODE_INPUT:449 case AS3722_GPIO_MODE_INPUT_PULL_UP:450 case AS3722_GPIO_MODE_INPUT_PULL_DOWN:451 case AS3722_GPIO_MODE_IO_OPEN_DRAIN:452 case AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP:453 reg = AS3722_GPIO_SIGNAL_IN_REG;454 break;455 case AS3722_GPIO_MODE_OUTPUT_VDDH:456 case AS3722_GPIO_MODE_OUTPUT_VDDL:457 reg = AS3722_GPIO_SIGNAL_OUT_REG;458 break;459 default:460 return -EINVAL;461 }462 463 ret = as3722_read(as3722, reg, &val);464 if (ret < 0) {465 dev_err(as_pci->dev,466 "GPIO_SIGNAL_IN_REG read failed: %d\n", ret);467 return ret;468 }469 470 val = !!(val & AS3722_GPIOn_SIGNAL(offset));471 return (invert_enable) ? !val : val;472}473 474static void as3722_gpio_set(struct gpio_chip *chip, unsigned offset,475 int value)476{477 struct as3722_pctrl_info *as_pci = gpiochip_get_data(chip);478 struct as3722 *as3722 = as_pci->as3722;479 int en_invert;480 u32 val;481 int ret;482 483 ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &val);484 if (ret < 0) {485 dev_err(as_pci->dev,486 "GPIO_CONTROL%d_REG read failed: %d\n", offset, ret);487 return;488 }489 en_invert = !!(val & AS3722_GPIO_INV);490 491 if (value)492 val = (en_invert) ? 0 : AS3722_GPIOn_SIGNAL(offset);493 else494 val = (en_invert) ? AS3722_GPIOn_SIGNAL(offset) : 0;495 496 ret = as3722_update_bits(as3722, AS3722_GPIO_SIGNAL_OUT_REG,497 AS3722_GPIOn_SIGNAL(offset), val);498 if (ret < 0)499 dev_err(as_pci->dev,500 "GPIO_SIGNAL_OUT_REG update failed: %d\n", ret);501}502 503static int as3722_gpio_direction_output(struct gpio_chip *chip,504 unsigned offset, int value)505{506 as3722_gpio_set(chip, offset, value);507 return pinctrl_gpio_direction_output(chip, offset);508}509 510static int as3722_gpio_to_irq(struct gpio_chip *chip, unsigned offset)511{512 struct as3722_pctrl_info *as_pci = gpiochip_get_data(chip);513 514 return as3722_irq_get_virq(as_pci->as3722, offset);515}516 517static const struct gpio_chip as3722_gpio_chip = {518 .label = "as3722-gpio",519 .owner = THIS_MODULE,520 .request = gpiochip_generic_request,521 .free = gpiochip_generic_free,522 .get = as3722_gpio_get,523 .set = as3722_gpio_set,524 .direction_input = pinctrl_gpio_direction_input,525 .direction_output = as3722_gpio_direction_output,526 .to_irq = as3722_gpio_to_irq,527 .can_sleep = true,528 .ngpio = AS3722_PIN_NUM,529 .base = -1,530};531 532static int as3722_pinctrl_probe(struct platform_device *pdev)533{534 struct as3722_pctrl_info *as_pci;535 int ret;536 537 device_set_node(&pdev->dev, dev_fwnode(pdev->dev.parent));538 539 as_pci = devm_kzalloc(&pdev->dev, sizeof(*as_pci), GFP_KERNEL);540 if (!as_pci)541 return -ENOMEM;542 543 as_pci->dev = &pdev->dev;544 as_pci->as3722 = dev_get_drvdata(pdev->dev.parent);545 546 as_pci->pins = as3722_pins_desc;547 as_pci->num_pins = ARRAY_SIZE(as3722_pins_desc);548 as_pci->functions = as3722_pin_function;549 as_pci->num_functions = ARRAY_SIZE(as3722_pin_function);550 as_pci->pin_groups = as3722_pingroups;551 as_pci->num_pin_groups = ARRAY_SIZE(as3722_pingroups);552 as3722_pinctrl_desc.name = dev_name(&pdev->dev);553 as3722_pinctrl_desc.pins = as3722_pins_desc;554 as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc);555 as_pci->pctl = devm_pinctrl_register(&pdev->dev, &as3722_pinctrl_desc,556 as_pci);557 if (IS_ERR(as_pci->pctl)) {558 dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");559 return PTR_ERR(as_pci->pctl);560 }561 562 as_pci->gpio_chip = as3722_gpio_chip;563 as_pci->gpio_chip.parent = &pdev->dev;564 ret = devm_gpiochip_add_data(&pdev->dev, &as_pci->gpio_chip, as_pci);565 if (ret < 0) {566 dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret);567 return ret;568 }569 570 ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev),571 0, 0, AS3722_PIN_NUM);572 if (ret < 0) {573 dev_err(&pdev->dev, "Couldn't add pin range, %d\n", ret);574 return ret;575 }576 577 return 0;578}579 580static const struct of_device_id as3722_pinctrl_of_match[] = {581 { .compatible = "ams,as3722-pinctrl", },582 { },583};584MODULE_DEVICE_TABLE(of, as3722_pinctrl_of_match);585 586static struct platform_driver as3722_pinctrl_driver = {587 .driver = {588 .name = "as3722-pinctrl",589 .of_match_table = as3722_pinctrl_of_match,590 },591 .probe = as3722_pinctrl_probe,592};593module_platform_driver(as3722_pinctrl_driver);594 595MODULE_ALIAS("platform:as3722-pinctrl");596MODULE_DESCRIPTION("AS3722 pin control and GPIO driver");597MODULE_AUTHOR("Laxman Dewangan<ldewangan@nvidia.com>");598MODULE_LICENSE("GPL v2");599