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