18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * ams AS3722 pin control and GPIO driver. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (c) 2013, NVIDIA Corporation. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author: Laxman Dewangan <ldewangan@nvidia.com> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This program is free software; you can redistribute it and/or 98c2ecf20Sopenharmony_ci * modify it under the terms of the GNU General Public License as 108c2ecf20Sopenharmony_ci * published by the Free Software Foundation version 2. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, 138c2ecf20Sopenharmony_ci * whether express or implied; without even the implied warranty of 148c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 158c2ecf20Sopenharmony_ci * General Public License for more details. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 188c2ecf20Sopenharmony_ci * along with this program; if not, write to the Free Software 198c2ecf20Sopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 208c2ecf20Sopenharmony_ci * 02111-1307, USA 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <linux/delay.h> 248c2ecf20Sopenharmony_ci#include <linux/gpio/driver.h> 258c2ecf20Sopenharmony_ci#include <linux/kernel.h> 268c2ecf20Sopenharmony_ci#include <linux/module.h> 278c2ecf20Sopenharmony_ci#include <linux/mfd/as3722.h> 288c2ecf20Sopenharmony_ci#include <linux/of.h> 298c2ecf20Sopenharmony_ci#include <linux/of_device.h> 308c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 318c2ecf20Sopenharmony_ci#include <linux/pinctrl/consumer.h> 328c2ecf20Sopenharmony_ci#include <linux/pinctrl/machine.h> 338c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinctrl.h> 348c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 358c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinconf.h> 368c2ecf20Sopenharmony_ci#include <linux/pinctrl/pinmux.h> 378c2ecf20Sopenharmony_ci#include <linux/pm.h> 388c2ecf20Sopenharmony_ci#include <linux/slab.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#include "core.h" 418c2ecf20Sopenharmony_ci#include "pinconf.h" 428c2ecf20Sopenharmony_ci#include "pinctrl-utils.h" 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO0 0 458c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO1 1 468c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO2 2 478c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO3 3 488c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO4 4 498c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO5 5 508c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO6 6 518c2ecf20Sopenharmony_ci#define AS3722_PIN_GPIO7 7 528c2ecf20Sopenharmony_ci#define AS3722_PIN_NUM (AS3722_PIN_GPIO7 + 1) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define AS3722_GPIO_MODE_PULL_UP BIT(PIN_CONFIG_BIAS_PULL_UP) 558c2ecf20Sopenharmony_ci#define AS3722_GPIO_MODE_PULL_DOWN BIT(PIN_CONFIG_BIAS_PULL_DOWN) 568c2ecf20Sopenharmony_ci#define AS3722_GPIO_MODE_HIGH_IMPED BIT(PIN_CONFIG_BIAS_HIGH_IMPEDANCE) 578c2ecf20Sopenharmony_ci#define AS3722_GPIO_MODE_OPEN_DRAIN BIT(PIN_CONFIG_DRIVE_OPEN_DRAIN) 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistruct as3722_pin_function { 608c2ecf20Sopenharmony_ci const char *name; 618c2ecf20Sopenharmony_ci const char * const *groups; 628c2ecf20Sopenharmony_ci unsigned ngroups; 638c2ecf20Sopenharmony_ci int mux_option; 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistruct as3722_gpio_pin_control { 678c2ecf20Sopenharmony_ci unsigned mode_prop; 688c2ecf20Sopenharmony_ci int io_function; 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistruct as3722_pingroup { 728c2ecf20Sopenharmony_ci const char *name; 738c2ecf20Sopenharmony_ci const unsigned pins[1]; 748c2ecf20Sopenharmony_ci unsigned npins; 758c2ecf20Sopenharmony_ci}; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistruct as3722_pctrl_info { 788c2ecf20Sopenharmony_ci struct device *dev; 798c2ecf20Sopenharmony_ci struct pinctrl_dev *pctl; 808c2ecf20Sopenharmony_ci struct as3722 *as3722; 818c2ecf20Sopenharmony_ci struct gpio_chip gpio_chip; 828c2ecf20Sopenharmony_ci int pins_current_opt[AS3722_PIN_NUM]; 838c2ecf20Sopenharmony_ci const struct as3722_pin_function *functions; 848c2ecf20Sopenharmony_ci unsigned num_functions; 858c2ecf20Sopenharmony_ci const struct as3722_pingroup *pin_groups; 868c2ecf20Sopenharmony_ci int num_pin_groups; 878c2ecf20Sopenharmony_ci const struct pinctrl_pin_desc *pins; 888c2ecf20Sopenharmony_ci unsigned num_pins; 898c2ecf20Sopenharmony_ci struct as3722_gpio_pin_control gpio_control[AS3722_PIN_NUM]; 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic const struct pinctrl_pin_desc as3722_pins_desc[] = { 938c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO0, "gpio0"), 948c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO1, "gpio1"), 958c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO2, "gpio2"), 968c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO3, "gpio3"), 978c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO4, "gpio4"), 988c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO5, "gpio5"), 998c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO6, "gpio6"), 1008c2ecf20Sopenharmony_ci PINCTRL_PIN(AS3722_PIN_GPIO7, "gpio7"), 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic const char * const gpio_groups[] = { 1048c2ecf20Sopenharmony_ci "gpio0", 1058c2ecf20Sopenharmony_ci "gpio1", 1068c2ecf20Sopenharmony_ci "gpio2", 1078c2ecf20Sopenharmony_ci "gpio3", 1088c2ecf20Sopenharmony_ci "gpio4", 1098c2ecf20Sopenharmony_ci "gpio5", 1108c2ecf20Sopenharmony_ci "gpio6", 1118c2ecf20Sopenharmony_ci "gpio7", 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cienum as3722_pinmux_option { 1158c2ecf20Sopenharmony_ci AS3722_PINMUX_GPIO = 0, 1168c2ecf20Sopenharmony_ci AS3722_PINMUX_INTERRUPT_OUT = 1, 1178c2ecf20Sopenharmony_ci AS3722_PINMUX_VSUB_VBAT_UNDEB_LOW_OUT = 2, 1188c2ecf20Sopenharmony_ci AS3722_PINMUX_GPIO_INTERRUPT = 3, 1198c2ecf20Sopenharmony_ci AS3722_PINMUX_PWM_INPUT = 4, 1208c2ecf20Sopenharmony_ci AS3722_PINMUX_VOLTAGE_IN_STBY = 5, 1218c2ecf20Sopenharmony_ci AS3722_PINMUX_OC_PG_SD0 = 6, 1228c2ecf20Sopenharmony_ci AS3722_PINMUX_PG_OUT = 7, 1238c2ecf20Sopenharmony_ci AS3722_PINMUX_CLK32K_OUT = 8, 1248c2ecf20Sopenharmony_ci AS3722_PINMUX_WATCHDOG_INPUT = 9, 1258c2ecf20Sopenharmony_ci AS3722_PINMUX_SOFT_RESET_IN = 11, 1268c2ecf20Sopenharmony_ci AS3722_PINMUX_PWM_OUTPUT = 12, 1278c2ecf20Sopenharmony_ci AS3722_PINMUX_VSUB_VBAT_LOW_DEB_OUT = 13, 1288c2ecf20Sopenharmony_ci AS3722_PINMUX_OC_PG_SD6 = 14, 1298c2ecf20Sopenharmony_ci}; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci#define FUNCTION_GROUP(fname, mux) \ 1328c2ecf20Sopenharmony_ci { \ 1338c2ecf20Sopenharmony_ci .name = #fname, \ 1348c2ecf20Sopenharmony_ci .groups = gpio_groups, \ 1358c2ecf20Sopenharmony_ci .ngroups = ARRAY_SIZE(gpio_groups), \ 1368c2ecf20Sopenharmony_ci .mux_option = AS3722_PINMUX_##mux, \ 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic const struct as3722_pin_function as3722_pin_function[] = { 1408c2ecf20Sopenharmony_ci FUNCTION_GROUP(gpio, GPIO), 1418c2ecf20Sopenharmony_ci FUNCTION_GROUP(interrupt-out, INTERRUPT_OUT), 1428c2ecf20Sopenharmony_ci FUNCTION_GROUP(gpio-in-interrupt, GPIO_INTERRUPT), 1438c2ecf20Sopenharmony_ci FUNCTION_GROUP(vsup-vbat-low-undebounce-out, VSUB_VBAT_UNDEB_LOW_OUT), 1448c2ecf20Sopenharmony_ci FUNCTION_GROUP(vsup-vbat-low-debounce-out, VSUB_VBAT_LOW_DEB_OUT), 1458c2ecf20Sopenharmony_ci FUNCTION_GROUP(voltage-in-standby, VOLTAGE_IN_STBY), 1468c2ecf20Sopenharmony_ci FUNCTION_GROUP(oc-pg-sd0, OC_PG_SD0), 1478c2ecf20Sopenharmony_ci FUNCTION_GROUP(oc-pg-sd6, OC_PG_SD6), 1488c2ecf20Sopenharmony_ci FUNCTION_GROUP(powergood-out, PG_OUT), 1498c2ecf20Sopenharmony_ci FUNCTION_GROUP(pwm-in, PWM_INPUT), 1508c2ecf20Sopenharmony_ci FUNCTION_GROUP(pwm-out, PWM_OUTPUT), 1518c2ecf20Sopenharmony_ci FUNCTION_GROUP(clk32k-out, CLK32K_OUT), 1528c2ecf20Sopenharmony_ci FUNCTION_GROUP(watchdog-in, WATCHDOG_INPUT), 1538c2ecf20Sopenharmony_ci FUNCTION_GROUP(soft-reset-in, SOFT_RESET_IN), 1548c2ecf20Sopenharmony_ci}; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci#define AS3722_PINGROUP(pg_name, pin_id) \ 1578c2ecf20Sopenharmony_ci { \ 1588c2ecf20Sopenharmony_ci .name = #pg_name, \ 1598c2ecf20Sopenharmony_ci .pins = {AS3722_PIN_##pin_id}, \ 1608c2ecf20Sopenharmony_ci .npins = 1, \ 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic const struct as3722_pingroup as3722_pingroups[] = { 1648c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio0, GPIO0), 1658c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio1, GPIO1), 1668c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio2, GPIO2), 1678c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio3, GPIO3), 1688c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio4, GPIO4), 1698c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio5, GPIO5), 1708c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio6, GPIO6), 1718c2ecf20Sopenharmony_ci AS3722_PINGROUP(gpio7, GPIO7), 1728c2ecf20Sopenharmony_ci}; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_cistatic int as3722_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return as_pci->num_pin_groups; 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic const char *as3722_pinctrl_get_group_name(struct pinctrl_dev *pctldev, 1828c2ecf20Sopenharmony_ci unsigned group) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci return as_pci->pin_groups[group].name; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_cistatic int as3722_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, 1908c2ecf20Sopenharmony_ci unsigned group, const unsigned **pins, unsigned *num_pins) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci *pins = as_pci->pin_groups[group].pins; 1958c2ecf20Sopenharmony_ci *num_pins = as_pci->pin_groups[group].npins; 1968c2ecf20Sopenharmony_ci return 0; 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_cistatic const struct pinctrl_ops as3722_pinctrl_ops = { 2008c2ecf20Sopenharmony_ci .get_groups_count = as3722_pinctrl_get_groups_count, 2018c2ecf20Sopenharmony_ci .get_group_name = as3722_pinctrl_get_group_name, 2028c2ecf20Sopenharmony_ci .get_group_pins = as3722_pinctrl_get_group_pins, 2038c2ecf20Sopenharmony_ci .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 2048c2ecf20Sopenharmony_ci .dt_free_map = pinctrl_utils_free_map, 2058c2ecf20Sopenharmony_ci}; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic int as3722_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return as_pci->num_functions; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic const char *as3722_pinctrl_get_func_name(struct pinctrl_dev *pctldev, 2158c2ecf20Sopenharmony_ci unsigned function) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci return as_pci->functions[function].name; 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic int as3722_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, 2238c2ecf20Sopenharmony_ci unsigned function, const char * const **groups, 2248c2ecf20Sopenharmony_ci unsigned * const num_groups) 2258c2ecf20Sopenharmony_ci{ 2268c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci *groups = as_pci->functions[function].groups; 2298c2ecf20Sopenharmony_ci *num_groups = as_pci->functions[function].ngroups; 2308c2ecf20Sopenharmony_ci return 0; 2318c2ecf20Sopenharmony_ci} 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_cistatic int as3722_pinctrl_set(struct pinctrl_dev *pctldev, unsigned function, 2348c2ecf20Sopenharmony_ci unsigned group) 2358c2ecf20Sopenharmony_ci{ 2368c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 2378c2ecf20Sopenharmony_ci int gpio_cntr_reg = AS3722_GPIOn_CONTROL_REG(group); 2388c2ecf20Sopenharmony_ci u8 val = AS3722_GPIO_IOSF_VAL(as_pci->functions[function].mux_option); 2398c2ecf20Sopenharmony_ci int ret; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci dev_dbg(as_pci->dev, "%s(): GPIO %u pin to function %u and val %u\n", 2428c2ecf20Sopenharmony_ci __func__, group, function, val); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci ret = as3722_update_bits(as_pci->as3722, gpio_cntr_reg, 2458c2ecf20Sopenharmony_ci AS3722_GPIO_IOSF_MASK, val); 2468c2ecf20Sopenharmony_ci if (ret < 0) { 2478c2ecf20Sopenharmony_ci dev_err(as_pci->dev, "GPIO%d_CTRL_REG update failed %d\n", 2488c2ecf20Sopenharmony_ci group, ret); 2498c2ecf20Sopenharmony_ci return ret; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci as_pci->gpio_control[group].io_function = function; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci switch (val) { 2548c2ecf20Sopenharmony_ci case AS3722_GPIO_IOSF_SD0_OUT: 2558c2ecf20Sopenharmony_ci case AS3722_GPIO_IOSF_PWR_GOOD_OUT: 2568c2ecf20Sopenharmony_ci case AS3722_GPIO_IOSF_Q32K_OUT: 2578c2ecf20Sopenharmony_ci case AS3722_GPIO_IOSF_PWM_OUT: 2588c2ecf20Sopenharmony_ci case AS3722_GPIO_IOSF_SD6_LOW_VOLT_LOW: 2598c2ecf20Sopenharmony_ci ret = as3722_update_bits(as_pci->as3722, gpio_cntr_reg, 2608c2ecf20Sopenharmony_ci AS3722_GPIO_MODE_MASK, AS3722_GPIO_MODE_OUTPUT_VDDH); 2618c2ecf20Sopenharmony_ci if (ret < 0) { 2628c2ecf20Sopenharmony_ci dev_err(as_pci->dev, "GPIO%d_CTRL update failed %d\n", 2638c2ecf20Sopenharmony_ci group, ret); 2648c2ecf20Sopenharmony_ci return ret; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci as_pci->gpio_control[group].mode_prop = 2678c2ecf20Sopenharmony_ci AS3722_GPIO_MODE_OUTPUT_VDDH; 2688c2ecf20Sopenharmony_ci break; 2698c2ecf20Sopenharmony_ci default: 2708c2ecf20Sopenharmony_ci break; 2718c2ecf20Sopenharmony_ci } 2728c2ecf20Sopenharmony_ci return ret; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic int as3722_pinctrl_gpio_get_mode(unsigned gpio_mode_prop, bool input) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci if (gpio_mode_prop & AS3722_GPIO_MODE_HIGH_IMPED) 2788c2ecf20Sopenharmony_ci return -EINVAL; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci if (gpio_mode_prop & AS3722_GPIO_MODE_OPEN_DRAIN) { 2818c2ecf20Sopenharmony_ci if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP) 2828c2ecf20Sopenharmony_ci return AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP; 2838c2ecf20Sopenharmony_ci return AS3722_GPIO_MODE_IO_OPEN_DRAIN; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci if (input) { 2868c2ecf20Sopenharmony_ci if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_UP) 2878c2ecf20Sopenharmony_ci return AS3722_GPIO_MODE_INPUT_PULL_UP; 2888c2ecf20Sopenharmony_ci else if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN) 2898c2ecf20Sopenharmony_ci return AS3722_GPIO_MODE_INPUT_PULL_DOWN; 2908c2ecf20Sopenharmony_ci return AS3722_GPIO_MODE_INPUT; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci if (gpio_mode_prop & AS3722_GPIO_MODE_PULL_DOWN) 2938c2ecf20Sopenharmony_ci return AS3722_GPIO_MODE_OUTPUT_VDDL; 2948c2ecf20Sopenharmony_ci return AS3722_GPIO_MODE_OUTPUT_VDDH; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic int as3722_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, 2988c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, unsigned offset) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (as_pci->gpio_control[offset].io_function) 3038c2ecf20Sopenharmony_ci return -EBUSY; 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic int as3722_pinctrl_gpio_set_direction(struct pinctrl_dev *pctldev, 3088c2ecf20Sopenharmony_ci struct pinctrl_gpio_range *range, unsigned offset, bool input) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 3118c2ecf20Sopenharmony_ci struct as3722 *as3722 = as_pci->as3722; 3128c2ecf20Sopenharmony_ci int mode; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci mode = as3722_pinctrl_gpio_get_mode( 3158c2ecf20Sopenharmony_ci as_pci->gpio_control[offset].mode_prop, input); 3168c2ecf20Sopenharmony_ci if (mode < 0) { 3178c2ecf20Sopenharmony_ci dev_err(as_pci->dev, "%s direction for GPIO %d not supported\n", 3188c2ecf20Sopenharmony_ci (input) ? "Input" : "Output", offset); 3198c2ecf20Sopenharmony_ci return mode; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci return as3722_update_bits(as3722, AS3722_GPIOn_CONTROL_REG(offset), 3238c2ecf20Sopenharmony_ci AS3722_GPIO_MODE_MASK, mode); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic const struct pinmux_ops as3722_pinmux_ops = { 3278c2ecf20Sopenharmony_ci .get_functions_count = as3722_pinctrl_get_funcs_count, 3288c2ecf20Sopenharmony_ci .get_function_name = as3722_pinctrl_get_func_name, 3298c2ecf20Sopenharmony_ci .get_function_groups = as3722_pinctrl_get_func_groups, 3308c2ecf20Sopenharmony_ci .set_mux = as3722_pinctrl_set, 3318c2ecf20Sopenharmony_ci .gpio_request_enable = as3722_pinctrl_gpio_request_enable, 3328c2ecf20Sopenharmony_ci .gpio_set_direction = as3722_pinctrl_gpio_set_direction, 3338c2ecf20Sopenharmony_ci}; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic int as3722_pinconf_get(struct pinctrl_dev *pctldev, 3368c2ecf20Sopenharmony_ci unsigned pin, unsigned long *config) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 3398c2ecf20Sopenharmony_ci enum pin_config_param param = pinconf_to_config_param(*config); 3408c2ecf20Sopenharmony_ci int arg = 0; 3418c2ecf20Sopenharmony_ci u16 prop; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci switch (param) { 3448c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 3458c2ecf20Sopenharmony_ci prop = AS3722_GPIO_MODE_PULL_UP | 3468c2ecf20Sopenharmony_ci AS3722_GPIO_MODE_PULL_DOWN; 3478c2ecf20Sopenharmony_ci if (!(as_pci->gpio_control[pin].mode_prop & prop)) 3488c2ecf20Sopenharmony_ci arg = 1; 3498c2ecf20Sopenharmony_ci prop = 0; 3508c2ecf20Sopenharmony_ci break; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 3538c2ecf20Sopenharmony_ci prop = AS3722_GPIO_MODE_PULL_UP; 3548c2ecf20Sopenharmony_ci break; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 3578c2ecf20Sopenharmony_ci prop = AS3722_GPIO_MODE_PULL_DOWN; 3588c2ecf20Sopenharmony_ci break; 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci case PIN_CONFIG_DRIVE_OPEN_DRAIN: 3618c2ecf20Sopenharmony_ci prop = AS3722_GPIO_MODE_OPEN_DRAIN; 3628c2ecf20Sopenharmony_ci break; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 3658c2ecf20Sopenharmony_ci prop = AS3722_GPIO_MODE_HIGH_IMPED; 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci default: 3698c2ecf20Sopenharmony_ci dev_err(as_pci->dev, "Properties not supported\n"); 3708c2ecf20Sopenharmony_ci return -ENOTSUPP; 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci if (as_pci->gpio_control[pin].mode_prop & prop) 3748c2ecf20Sopenharmony_ci arg = 1; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci *config = pinconf_to_config_packed(param, (u16)arg); 3778c2ecf20Sopenharmony_ci return 0; 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_cistatic int as3722_pinconf_set(struct pinctrl_dev *pctldev, 3818c2ecf20Sopenharmony_ci unsigned pin, unsigned long *configs, 3828c2ecf20Sopenharmony_ci unsigned num_configs) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = pinctrl_dev_get_drvdata(pctldev); 3858c2ecf20Sopenharmony_ci enum pin_config_param param; 3868c2ecf20Sopenharmony_ci int mode_prop; 3878c2ecf20Sopenharmony_ci int i; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci for (i = 0; i < num_configs; i++) { 3908c2ecf20Sopenharmony_ci param = pinconf_to_config_param(configs[i]); 3918c2ecf20Sopenharmony_ci mode_prop = as_pci->gpio_control[pin].mode_prop; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci switch (param) { 3948c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_DISABLE: 3988c2ecf20Sopenharmony_ci mode_prop &= ~(AS3722_GPIO_MODE_PULL_UP | 3998c2ecf20Sopenharmony_ci AS3722_GPIO_MODE_PULL_DOWN); 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_UP: 4028c2ecf20Sopenharmony_ci mode_prop |= AS3722_GPIO_MODE_PULL_UP; 4038c2ecf20Sopenharmony_ci break; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_PULL_DOWN: 4068c2ecf20Sopenharmony_ci mode_prop |= AS3722_GPIO_MODE_PULL_DOWN; 4078c2ecf20Sopenharmony_ci break; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ci case PIN_CONFIG_BIAS_HIGH_IMPEDANCE: 4108c2ecf20Sopenharmony_ci mode_prop |= AS3722_GPIO_MODE_HIGH_IMPED; 4118c2ecf20Sopenharmony_ci break; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci case PIN_CONFIG_DRIVE_OPEN_DRAIN: 4148c2ecf20Sopenharmony_ci mode_prop |= AS3722_GPIO_MODE_OPEN_DRAIN; 4158c2ecf20Sopenharmony_ci break; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci default: 4188c2ecf20Sopenharmony_ci dev_err(as_pci->dev, "Properties not supported\n"); 4198c2ecf20Sopenharmony_ci return -ENOTSUPP; 4208c2ecf20Sopenharmony_ci } 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci as_pci->gpio_control[pin].mode_prop = mode_prop; 4238c2ecf20Sopenharmony_ci } 4248c2ecf20Sopenharmony_ci return 0; 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic const struct pinconf_ops as3722_pinconf_ops = { 4288c2ecf20Sopenharmony_ci .pin_config_get = as3722_pinconf_get, 4298c2ecf20Sopenharmony_ci .pin_config_set = as3722_pinconf_set, 4308c2ecf20Sopenharmony_ci}; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic struct pinctrl_desc as3722_pinctrl_desc = { 4338c2ecf20Sopenharmony_ci .pctlops = &as3722_pinctrl_ops, 4348c2ecf20Sopenharmony_ci .pmxops = &as3722_pinmux_ops, 4358c2ecf20Sopenharmony_ci .confops = &as3722_pinconf_ops, 4368c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 4378c2ecf20Sopenharmony_ci}; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_cistatic int as3722_gpio_get(struct gpio_chip *chip, unsigned offset) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = gpiochip_get_data(chip); 4428c2ecf20Sopenharmony_ci struct as3722 *as3722 = as_pci->as3722; 4438c2ecf20Sopenharmony_ci int ret; 4448c2ecf20Sopenharmony_ci u32 reg; 4458c2ecf20Sopenharmony_ci u32 control; 4468c2ecf20Sopenharmony_ci u32 val; 4478c2ecf20Sopenharmony_ci int mode; 4488c2ecf20Sopenharmony_ci int invert_enable; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &control); 4518c2ecf20Sopenharmony_ci if (ret < 0) { 4528c2ecf20Sopenharmony_ci dev_err(as_pci->dev, 4538c2ecf20Sopenharmony_ci "GPIO_CONTROL%d_REG read failed: %d\n", offset, ret); 4548c2ecf20Sopenharmony_ci return ret; 4558c2ecf20Sopenharmony_ci } 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci invert_enable = !!(control & AS3722_GPIO_INV); 4588c2ecf20Sopenharmony_ci mode = control & AS3722_GPIO_MODE_MASK; 4598c2ecf20Sopenharmony_ci switch (mode) { 4608c2ecf20Sopenharmony_ci case AS3722_GPIO_MODE_INPUT: 4618c2ecf20Sopenharmony_ci case AS3722_GPIO_MODE_INPUT_PULL_UP: 4628c2ecf20Sopenharmony_ci case AS3722_GPIO_MODE_INPUT_PULL_DOWN: 4638c2ecf20Sopenharmony_ci case AS3722_GPIO_MODE_IO_OPEN_DRAIN: 4648c2ecf20Sopenharmony_ci case AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULL_UP: 4658c2ecf20Sopenharmony_ci reg = AS3722_GPIO_SIGNAL_IN_REG; 4668c2ecf20Sopenharmony_ci break; 4678c2ecf20Sopenharmony_ci case AS3722_GPIO_MODE_OUTPUT_VDDH: 4688c2ecf20Sopenharmony_ci case AS3722_GPIO_MODE_OUTPUT_VDDL: 4698c2ecf20Sopenharmony_ci reg = AS3722_GPIO_SIGNAL_OUT_REG; 4708c2ecf20Sopenharmony_ci break; 4718c2ecf20Sopenharmony_ci default: 4728c2ecf20Sopenharmony_ci return -EINVAL; 4738c2ecf20Sopenharmony_ci } 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci ret = as3722_read(as3722, reg, &val); 4768c2ecf20Sopenharmony_ci if (ret < 0) { 4778c2ecf20Sopenharmony_ci dev_err(as_pci->dev, 4788c2ecf20Sopenharmony_ci "GPIO_SIGNAL_IN_REG read failed: %d\n", ret); 4798c2ecf20Sopenharmony_ci return ret; 4808c2ecf20Sopenharmony_ci } 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci val = !!(val & AS3722_GPIOn_SIGNAL(offset)); 4838c2ecf20Sopenharmony_ci return (invert_enable) ? !val : val; 4848c2ecf20Sopenharmony_ci} 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_cistatic void as3722_gpio_set(struct gpio_chip *chip, unsigned offset, 4878c2ecf20Sopenharmony_ci int value) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = gpiochip_get_data(chip); 4908c2ecf20Sopenharmony_ci struct as3722 *as3722 = as_pci->as3722; 4918c2ecf20Sopenharmony_ci int en_invert; 4928c2ecf20Sopenharmony_ci u32 val; 4938c2ecf20Sopenharmony_ci int ret; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci ret = as3722_read(as3722, AS3722_GPIOn_CONTROL_REG(offset), &val); 4968c2ecf20Sopenharmony_ci if (ret < 0) { 4978c2ecf20Sopenharmony_ci dev_err(as_pci->dev, 4988c2ecf20Sopenharmony_ci "GPIO_CONTROL%d_REG read failed: %d\n", offset, ret); 4998c2ecf20Sopenharmony_ci return; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci en_invert = !!(val & AS3722_GPIO_INV); 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (value) 5048c2ecf20Sopenharmony_ci val = (en_invert) ? 0 : AS3722_GPIOn_SIGNAL(offset); 5058c2ecf20Sopenharmony_ci else 5068c2ecf20Sopenharmony_ci val = (en_invert) ? AS3722_GPIOn_SIGNAL(offset) : 0; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci ret = as3722_update_bits(as3722, AS3722_GPIO_SIGNAL_OUT_REG, 5098c2ecf20Sopenharmony_ci AS3722_GPIOn_SIGNAL(offset), val); 5108c2ecf20Sopenharmony_ci if (ret < 0) 5118c2ecf20Sopenharmony_ci dev_err(as_pci->dev, 5128c2ecf20Sopenharmony_ci "GPIO_SIGNAL_OUT_REG update failed: %d\n", ret); 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic int as3722_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 5168c2ecf20Sopenharmony_ci{ 5178c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_input(chip->base + offset); 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic int as3722_gpio_direction_output(struct gpio_chip *chip, 5218c2ecf20Sopenharmony_ci unsigned offset, int value) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci as3722_gpio_set(chip, offset, value); 5248c2ecf20Sopenharmony_ci return pinctrl_gpio_direction_output(chip->base + offset); 5258c2ecf20Sopenharmony_ci} 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_cistatic int as3722_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 5288c2ecf20Sopenharmony_ci{ 5298c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = gpiochip_get_data(chip); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci return as3722_irq_get_virq(as_pci->as3722, offset); 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic const struct gpio_chip as3722_gpio_chip = { 5358c2ecf20Sopenharmony_ci .label = "as3722-gpio", 5368c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 5378c2ecf20Sopenharmony_ci .request = gpiochip_generic_request, 5388c2ecf20Sopenharmony_ci .free = gpiochip_generic_free, 5398c2ecf20Sopenharmony_ci .get = as3722_gpio_get, 5408c2ecf20Sopenharmony_ci .set = as3722_gpio_set, 5418c2ecf20Sopenharmony_ci .direction_input = as3722_gpio_direction_input, 5428c2ecf20Sopenharmony_ci .direction_output = as3722_gpio_direction_output, 5438c2ecf20Sopenharmony_ci .to_irq = as3722_gpio_to_irq, 5448c2ecf20Sopenharmony_ci .can_sleep = true, 5458c2ecf20Sopenharmony_ci .ngpio = AS3722_PIN_NUM, 5468c2ecf20Sopenharmony_ci .base = -1, 5478c2ecf20Sopenharmony_ci}; 5488c2ecf20Sopenharmony_ci 5498c2ecf20Sopenharmony_cistatic int as3722_pinctrl_probe(struct platform_device *pdev) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci; 5528c2ecf20Sopenharmony_ci int ret; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci as_pci = devm_kzalloc(&pdev->dev, sizeof(*as_pci), GFP_KERNEL); 5558c2ecf20Sopenharmony_ci if (!as_pci) 5568c2ecf20Sopenharmony_ci return -ENOMEM; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci as_pci->dev = &pdev->dev; 5598c2ecf20Sopenharmony_ci as_pci->dev->of_node = pdev->dev.parent->of_node; 5608c2ecf20Sopenharmony_ci as_pci->as3722 = dev_get_drvdata(pdev->dev.parent); 5618c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, as_pci); 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci as_pci->pins = as3722_pins_desc; 5648c2ecf20Sopenharmony_ci as_pci->num_pins = ARRAY_SIZE(as3722_pins_desc); 5658c2ecf20Sopenharmony_ci as_pci->functions = as3722_pin_function; 5668c2ecf20Sopenharmony_ci as_pci->num_functions = ARRAY_SIZE(as3722_pin_function); 5678c2ecf20Sopenharmony_ci as_pci->pin_groups = as3722_pingroups; 5688c2ecf20Sopenharmony_ci as_pci->num_pin_groups = ARRAY_SIZE(as3722_pingroups); 5698c2ecf20Sopenharmony_ci as3722_pinctrl_desc.name = dev_name(&pdev->dev); 5708c2ecf20Sopenharmony_ci as3722_pinctrl_desc.pins = as3722_pins_desc; 5718c2ecf20Sopenharmony_ci as3722_pinctrl_desc.npins = ARRAY_SIZE(as3722_pins_desc); 5728c2ecf20Sopenharmony_ci as_pci->pctl = devm_pinctrl_register(&pdev->dev, &as3722_pinctrl_desc, 5738c2ecf20Sopenharmony_ci as_pci); 5748c2ecf20Sopenharmony_ci if (IS_ERR(as_pci->pctl)) { 5758c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); 5768c2ecf20Sopenharmony_ci return PTR_ERR(as_pci->pctl); 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci as_pci->gpio_chip = as3722_gpio_chip; 5808c2ecf20Sopenharmony_ci as_pci->gpio_chip.parent = &pdev->dev; 5818c2ecf20Sopenharmony_ci as_pci->gpio_chip.of_node = pdev->dev.parent->of_node; 5828c2ecf20Sopenharmony_ci ret = gpiochip_add_data(&as_pci->gpio_chip, as_pci); 5838c2ecf20Sopenharmony_ci if (ret < 0) { 5848c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Couldn't register gpiochip, %d\n", ret); 5858c2ecf20Sopenharmony_ci return ret; 5868c2ecf20Sopenharmony_ci } 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci ret = gpiochip_add_pin_range(&as_pci->gpio_chip, dev_name(&pdev->dev), 5898c2ecf20Sopenharmony_ci 0, 0, AS3722_PIN_NUM); 5908c2ecf20Sopenharmony_ci if (ret < 0) { 5918c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "Couldn't add pin range, %d\n", ret); 5928c2ecf20Sopenharmony_ci goto fail_range_add; 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci return 0; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cifail_range_add: 5988c2ecf20Sopenharmony_ci gpiochip_remove(&as_pci->gpio_chip); 5998c2ecf20Sopenharmony_ci return ret; 6008c2ecf20Sopenharmony_ci} 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_cistatic int as3722_pinctrl_remove(struct platform_device *pdev) 6038c2ecf20Sopenharmony_ci{ 6048c2ecf20Sopenharmony_ci struct as3722_pctrl_info *as_pci = platform_get_drvdata(pdev); 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci gpiochip_remove(&as_pci->gpio_chip); 6078c2ecf20Sopenharmony_ci return 0; 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_cistatic const struct of_device_id as3722_pinctrl_of_match[] = { 6118c2ecf20Sopenharmony_ci { .compatible = "ams,as3722-pinctrl", }, 6128c2ecf20Sopenharmony_ci { }, 6138c2ecf20Sopenharmony_ci}; 6148c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, as3722_pinctrl_of_match); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_cistatic struct platform_driver as3722_pinctrl_driver = { 6178c2ecf20Sopenharmony_ci .driver = { 6188c2ecf20Sopenharmony_ci .name = "as3722-pinctrl", 6198c2ecf20Sopenharmony_ci .of_match_table = as3722_pinctrl_of_match, 6208c2ecf20Sopenharmony_ci }, 6218c2ecf20Sopenharmony_ci .probe = as3722_pinctrl_probe, 6228c2ecf20Sopenharmony_ci .remove = as3722_pinctrl_remove, 6238c2ecf20Sopenharmony_ci}; 6248c2ecf20Sopenharmony_cimodule_platform_driver(as3722_pinctrl_driver); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:as3722-pinctrl"); 6278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("AS3722 pin control and GPIO driver"); 6288c2ecf20Sopenharmony_ciMODULE_AUTHOR("Laxman Dewangan<ldewangan@nvidia.com>"); 6298c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 630