13d0407baSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 23d0407baSopenharmony_ci/* 33d0407baSopenharmony_ci * Pinctrl driver for Rockchip RK805 PMIC 43d0407baSopenharmony_ci * 53d0407baSopenharmony_ci * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd 63d0407baSopenharmony_ci * 73d0407baSopenharmony_ci * Author: Joseph Chen <chenjh@rock-chips.com> 83d0407baSopenharmony_ci * 93d0407baSopenharmony_ci * Based on the pinctrl-as3722 driver 103d0407baSopenharmony_ci */ 113d0407baSopenharmony_ci 123d0407baSopenharmony_ci#include <linux/gpio/driver.h> 133d0407baSopenharmony_ci#include <linux/kernel.h> 143d0407baSopenharmony_ci#include <linux/module.h> 153d0407baSopenharmony_ci#include <linux/mfd/rk808.h> 163d0407baSopenharmony_ci#include <linux/of.h> 173d0407baSopenharmony_ci#include <linux/of_device.h> 183d0407baSopenharmony_ci#include <linux/platform_device.h> 193d0407baSopenharmony_ci#include <linux/pinctrl/consumer.h> 203d0407baSopenharmony_ci#include <linux/pinctrl/machine.h> 213d0407baSopenharmony_ci#include <linux/pinctrl/pinctrl.h> 223d0407baSopenharmony_ci#include <linux/pinctrl/pinconf-generic.h> 233d0407baSopenharmony_ci#include <linux/pinctrl/pinconf.h> 243d0407baSopenharmony_ci#include <linux/pinctrl/pinmux.h> 253d0407baSopenharmony_ci#include <linux/pm.h> 263d0407baSopenharmony_ci#include <linux/slab.h> 273d0407baSopenharmony_ci 283d0407baSopenharmony_ci#include "core.h" 293d0407baSopenharmony_ci#include "pinconf.h" 303d0407baSopenharmony_ci#include "pinctrl-utils.h" 313d0407baSopenharmony_ci 323d0407baSopenharmony_cistruct rk805_pin_function { 333d0407baSopenharmony_ci const char *name; 343d0407baSopenharmony_ci const char *const *groups; 353d0407baSopenharmony_ci unsigned int ngroups; 363d0407baSopenharmony_ci int mux_option; 373d0407baSopenharmony_ci}; 383d0407baSopenharmony_ci 393d0407baSopenharmony_cistruct rk805_pin_group { 403d0407baSopenharmony_ci const char *name; 413d0407baSopenharmony_ci const unsigned int pins[1]; 423d0407baSopenharmony_ci unsigned int npins; 433d0407baSopenharmony_ci}; 443d0407baSopenharmony_ci 453d0407baSopenharmony_ci/* 463d0407baSopenharmony_ci * @reg: gpio setting register; 473d0407baSopenharmony_ci * @fun_mask: functions select mask value, when set is gpio; 483d0407baSopenharmony_ci * @dir_mask: input or output mask value, when set is output, otherwise input; 493d0407baSopenharmony_ci * @val_mask: gpio set value, when set is level high, otherwise low; 503d0407baSopenharmony_ci * 513d0407baSopenharmony_ci * Different PMIC has different pin features, belowing 3 mask members are not 523d0407baSopenharmony_ci * all necessary for every PMIC. For example, RK805 has 2 pins that can be used 533d0407baSopenharmony_ci * as output only GPIOs, so func_mask and dir_mask are not needed. RK816 has 1 543d0407baSopenharmony_ci * pin that can be used as TS/GPIO, so fun_mask, dir_mask and val_mask are all 553d0407baSopenharmony_ci * necessary. 563d0407baSopenharmony_ci */ 573d0407baSopenharmony_cistruct rk805_pin_config { 583d0407baSopenharmony_ci u8 reg; 593d0407baSopenharmony_ci u8 fun_msk; 603d0407baSopenharmony_ci u8 dir_msk; 613d0407baSopenharmony_ci u8 val_msk; 623d0407baSopenharmony_ci}; 633d0407baSopenharmony_ci 643d0407baSopenharmony_cistruct rk805_pctrl_info { 653d0407baSopenharmony_ci struct rk808 *rk808; 663d0407baSopenharmony_ci struct device *dev; 673d0407baSopenharmony_ci struct pinctrl_dev *pctl; 683d0407baSopenharmony_ci struct gpio_chip gpio_chip; 693d0407baSopenharmony_ci struct pinctrl_desc pinctrl_desc; 703d0407baSopenharmony_ci const struct rk805_pin_function *functions; 713d0407baSopenharmony_ci unsigned int num_functions; 723d0407baSopenharmony_ci const struct rk805_pin_group *groups; 733d0407baSopenharmony_ci int num_pin_groups; 743d0407baSopenharmony_ci const struct pinctrl_pin_desc *pins; 753d0407baSopenharmony_ci unsigned int num_pins; 763d0407baSopenharmony_ci const struct rk805_pin_config *pin_cfg; 773d0407baSopenharmony_ci}; 783d0407baSopenharmony_ci 793d0407baSopenharmony_cienum rk805_pinmux_option { 803d0407baSopenharmony_ci RK805_PINMUX_GPIO, 813d0407baSopenharmony_ci RK805_PINMUX_TS, 823d0407baSopenharmony_ci}; 833d0407baSopenharmony_ci 843d0407baSopenharmony_cienum { 853d0407baSopenharmony_ci RK805_GPIO0, 863d0407baSopenharmony_ci RK805_GPIO1, 873d0407baSopenharmony_ci}; 883d0407baSopenharmony_ci 893d0407baSopenharmony_cistatic const char *const rk805_gpio_groups[] = { 903d0407baSopenharmony_ci "gpio0", 913d0407baSopenharmony_ci "gpio1", 923d0407baSopenharmony_ci}; 933d0407baSopenharmony_ci 943d0407baSopenharmony_ci/* RK805: 2 output only GPIOs */ 953d0407baSopenharmony_cistatic const struct pinctrl_pin_desc rk805_pins_desc[] = { 963d0407baSopenharmony_ci PINCTRL_PIN(RK805_GPIO0, "gpio0"), 973d0407baSopenharmony_ci PINCTRL_PIN(RK805_GPIO1, "gpio1"), 983d0407baSopenharmony_ci}; 993d0407baSopenharmony_ci 1003d0407baSopenharmony_cistatic const struct rk805_pin_function rk805_pin_functions[] = { 1013d0407baSopenharmony_ci { 1023d0407baSopenharmony_ci .name = "gpio", 1033d0407baSopenharmony_ci .groups = rk805_gpio_groups, 1043d0407baSopenharmony_ci .ngroups = ARRAY_SIZE(rk805_gpio_groups), 1053d0407baSopenharmony_ci .mux_option = RK805_PINMUX_GPIO, 1063d0407baSopenharmony_ci }, 1073d0407baSopenharmony_ci}; 1083d0407baSopenharmony_ci 1093d0407baSopenharmony_cistatic const struct rk805_pin_group rk805_pin_groups[] = { 1103d0407baSopenharmony_ci { 1113d0407baSopenharmony_ci .name = "gpio0", 1123d0407baSopenharmony_ci .pins = {RK805_GPIO0}, 1133d0407baSopenharmony_ci .npins = 1, 1143d0407baSopenharmony_ci }, 1153d0407baSopenharmony_ci { 1163d0407baSopenharmony_ci .name = "gpio1", 1173d0407baSopenharmony_ci .pins = {RK805_GPIO1}, 1183d0407baSopenharmony_ci .npins = 1, 1193d0407baSopenharmony_ci }, 1203d0407baSopenharmony_ci}; 1213d0407baSopenharmony_ci 1223d0407baSopenharmony_ci#define RK805_GPIO0_VAL_MSK BIT(0) 1233d0407baSopenharmony_ci#define RK805_GPIO1_VAL_MSK BIT(1) 1243d0407baSopenharmony_ci 1253d0407baSopenharmony_cistatic const struct rk805_pin_config rk805_gpio_cfgs[] = { 1263d0407baSopenharmony_ci { 1273d0407baSopenharmony_ci .reg = RK805_OUT_REG, 1283d0407baSopenharmony_ci .val_msk = RK805_GPIO0_VAL_MSK, 1293d0407baSopenharmony_ci }, 1303d0407baSopenharmony_ci { 1313d0407baSopenharmony_ci .reg = RK805_OUT_REG, 1323d0407baSopenharmony_ci .val_msk = RK805_GPIO1_VAL_MSK, 1333d0407baSopenharmony_ci }, 1343d0407baSopenharmony_ci}; 1353d0407baSopenharmony_ci 1363d0407baSopenharmony_ci#define RK816_FUN_MASK BIT(2) 1373d0407baSopenharmony_ci#define RK816_VAL_MASK BIT(3) 1383d0407baSopenharmony_ci#define RK816_DIR_MASK BIT(4) 1393d0407baSopenharmony_ci 1403d0407baSopenharmony_cienum { 1413d0407baSopenharmony_ci RK816_GPIO0, 1423d0407baSopenharmony_ci}; 1433d0407baSopenharmony_ci 1443d0407baSopenharmony_ci/* RK816: gpio/ts */ 1453d0407baSopenharmony_cistatic const char *const rk816_gpio_groups[] = { 1463d0407baSopenharmony_ci "gpio0", 1473d0407baSopenharmony_ci}; 1483d0407baSopenharmony_ci 1493d0407baSopenharmony_cistatic const struct pinctrl_pin_desc rk816_pins_desc[] = { 1503d0407baSopenharmony_ci PINCTRL_PIN(RK816_GPIO0, "gpio0"), 1513d0407baSopenharmony_ci}; 1523d0407baSopenharmony_ci 1533d0407baSopenharmony_cistatic const struct rk805_pin_function rk816_pin_functions[] = { 1543d0407baSopenharmony_ci { 1553d0407baSopenharmony_ci .name = "gpio", 1563d0407baSopenharmony_ci .groups = rk816_gpio_groups, 1573d0407baSopenharmony_ci .ngroups = ARRAY_SIZE(rk816_gpio_groups), 1583d0407baSopenharmony_ci .mux_option = RK805_PINMUX_GPIO, 1593d0407baSopenharmony_ci }, 1603d0407baSopenharmony_ci { 1613d0407baSopenharmony_ci .name = "ts", 1623d0407baSopenharmony_ci .groups = rk816_gpio_groups, 1633d0407baSopenharmony_ci .ngroups = ARRAY_SIZE(rk816_gpio_groups), 1643d0407baSopenharmony_ci .mux_option = RK805_PINMUX_TS, 1653d0407baSopenharmony_ci }, 1663d0407baSopenharmony_ci}; 1673d0407baSopenharmony_ci 1683d0407baSopenharmony_cistatic const struct rk805_pin_group rk816_pin_groups[] = { 1693d0407baSopenharmony_ci { 1703d0407baSopenharmony_ci .name = "gpio0", 1713d0407baSopenharmony_ci .pins = {RK816_GPIO0}, 1723d0407baSopenharmony_ci .npins = 1, 1733d0407baSopenharmony_ci }, 1743d0407baSopenharmony_ci}; 1753d0407baSopenharmony_ci 1763d0407baSopenharmony_cistatic struct rk805_pin_config rk816_gpio_cfgs[] = { 1773d0407baSopenharmony_ci { 1783d0407baSopenharmony_ci .reg = RK816_GPIO_IO_POL_REG, 1793d0407baSopenharmony_ci .val_msk = RK816_VAL_MASK, 1803d0407baSopenharmony_ci .fun_msk = RK816_FUN_MASK, 1813d0407baSopenharmony_ci .dir_msk = RK816_DIR_MASK, 1823d0407baSopenharmony_ci }, 1833d0407baSopenharmony_ci}; 1843d0407baSopenharmony_ci 1853d0407baSopenharmony_cienum rk817_pinmux_option { RK817_PINMUX_FUN0 = 0, RK817_PINMUX_FUN1, RK817_PINMUX_FUN2, RK817_PINMUX_FUN3 }; 1863d0407baSopenharmony_ci 1873d0407baSopenharmony_cienum { RK817_GPIO_SLP, RK817_GPIO_TS, RK817_GPIO_GT }; 1883d0407baSopenharmony_ci 1893d0407baSopenharmony_ci/* for rk809 only a sleep pin */ 1903d0407baSopenharmony_cistatic const char *const rk817_gpio_groups[] = { 1913d0407baSopenharmony_ci "gpio_slp", 1923d0407baSopenharmony_ci "gpio_ts", 1933d0407baSopenharmony_ci "gpio_gt", 1943d0407baSopenharmony_ci}; 1953d0407baSopenharmony_ci 1963d0407baSopenharmony_cistatic const struct pinctrl_pin_desc rk817_pins_desc[] = { 1973d0407baSopenharmony_ci PINCTRL_PIN(RK817_GPIO_SLP, "gpio_slp"), /* sleep pin */ 1983d0407baSopenharmony_ci PINCTRL_PIN(RK817_GPIO_TS, "gpio_ts"), /* ts pin */ 1993d0407baSopenharmony_ci PINCTRL_PIN(RK817_GPIO_GT, "gpio_gt") /* gate pin */ 2003d0407baSopenharmony_ci}; 2013d0407baSopenharmony_ci 2023d0407baSopenharmony_cistatic const struct rk805_pin_function rk817_pin_functions[] = { 2033d0407baSopenharmony_ci { 2043d0407baSopenharmony_ci .name = "pin_fun0", 2053d0407baSopenharmony_ci .groups = rk817_gpio_groups, 2063d0407baSopenharmony_ci .ngroups = ARRAY_SIZE(rk817_gpio_groups), 2073d0407baSopenharmony_ci .mux_option = RK817_PINMUX_FUN0, 2083d0407baSopenharmony_ci }, 2093d0407baSopenharmony_ci { 2103d0407baSopenharmony_ci .name = "pin_fun1", 2113d0407baSopenharmony_ci .groups = rk817_gpio_groups, 2123d0407baSopenharmony_ci .ngroups = ARRAY_SIZE(rk817_gpio_groups), 2133d0407baSopenharmony_ci .mux_option = RK817_PINMUX_FUN1, 2143d0407baSopenharmony_ci }, 2153d0407baSopenharmony_ci { 2163d0407baSopenharmony_ci .name = "pin_fun2", 2173d0407baSopenharmony_ci .groups = rk817_gpio_groups, 2183d0407baSopenharmony_ci .ngroups = ARRAY_SIZE(rk817_gpio_groups), 2193d0407baSopenharmony_ci .mux_option = RK817_PINMUX_FUN2, 2203d0407baSopenharmony_ci }, 2213d0407baSopenharmony_ci { 2223d0407baSopenharmony_ci .name = "pin_fun3", 2233d0407baSopenharmony_ci .groups = rk817_gpio_groups, 2243d0407baSopenharmony_ci .ngroups = ARRAY_SIZE(rk817_gpio_groups), 2253d0407baSopenharmony_ci .mux_option = RK817_PINMUX_FUN3, 2263d0407baSopenharmony_ci }, 2273d0407baSopenharmony_ci}; 2283d0407baSopenharmony_ci 2293d0407baSopenharmony_ci/* for rk809 only a sleep pin */ 2303d0407baSopenharmony_cistatic const struct rk805_pin_group rk817_pin_groups[] = { 2313d0407baSopenharmony_ci { 2323d0407baSopenharmony_ci .name = "gpio_slp", 2333d0407baSopenharmony_ci .pins = {RK817_GPIO_SLP}, 2343d0407baSopenharmony_ci .npins = 1, 2353d0407baSopenharmony_ci }, 2363d0407baSopenharmony_ci { 2373d0407baSopenharmony_ci .name = "gpio_ts", 2383d0407baSopenharmony_ci .pins = {RK817_GPIO_TS}, 2393d0407baSopenharmony_ci .npins = 1, 2403d0407baSopenharmony_ci }, 2413d0407baSopenharmony_ci { 2423d0407baSopenharmony_ci .name = "gpio_gt", 2433d0407baSopenharmony_ci .pins = {RK817_GPIO_GT}, 2443d0407baSopenharmony_ci .npins = 1, 2453d0407baSopenharmony_ci } 2463d0407baSopenharmony_ci}; 2473d0407baSopenharmony_ci 2483d0407baSopenharmony_ci#define RK817_GPIOTS_VAL_MSK BIT(3) 2493d0407baSopenharmony_ci#define RK817_GPIOGT_VAL_MSK BIT(6) 2503d0407baSopenharmony_ci#define RK817_GPIOTS_FUNC_MSK BIT(2) 2513d0407baSopenharmony_ci#define RK817_GPIOGT_FUNC_MSK BIT(5) 2523d0407baSopenharmony_ci#define RK817_GPIOTS_DIR_MSK BIT(4) 2533d0407baSopenharmony_ci#define RK817_GPIOGT_DIR_MSK BIT(7) 2543d0407baSopenharmony_ci 2553d0407baSopenharmony_cistatic struct rk805_pin_config rk817_gpio_cfgs[] = { 2563d0407baSopenharmony_ci {.reg = RK817_SYS_CFG(3), .val_msk = 0, .fun_msk = RK817_SLPPIN_FUNC_MSK, .dir_msk = 0}, 2573d0407baSopenharmony_ci {.reg = RK817_GPIO_INT_CFG, 2583d0407baSopenharmony_ci .val_msk = RK817_GPIOTS_VAL_MSK, 2593d0407baSopenharmony_ci .fun_msk = RK817_GPIOTS_FUNC_MSK, 2603d0407baSopenharmony_ci .dir_msk = RK817_GPIOTS_DIR_MSK}, 2613d0407baSopenharmony_ci {.reg = RK817_GPIO_INT_CFG, 2623d0407baSopenharmony_ci .val_msk = RK817_GPIOGT_VAL_MSK, 2633d0407baSopenharmony_ci .fun_msk = RK817_GPIOGT_FUNC_MSK, 2643d0407baSopenharmony_ci .dir_msk = RK817_GPIOGT_DIR_MSK}}; 2653d0407baSopenharmony_ci 2663d0407baSopenharmony_ci/* generic gpio chip */ 2673d0407baSopenharmony_cistatic int rk805_gpio_get(struct gpio_chip *chip, unsigned int offset) 2683d0407baSopenharmony_ci{ 2693d0407baSopenharmony_ci struct rk805_pctrl_info *pci = gpiochip_get_data(chip); 2703d0407baSopenharmony_ci int ret, val; 2713d0407baSopenharmony_ci 2723d0407baSopenharmony_ci if (!pci->pin_cfg[offset].val_msk) { 2733d0407baSopenharmony_ci dev_dbg(pci->dev, "getting gpio%d value is not support\n", offset); 2743d0407baSopenharmony_ci return -1; 2753d0407baSopenharmony_ci } 2763d0407baSopenharmony_ci 2773d0407baSopenharmony_ci ret = regmap_read(pci->rk808->regmap, pci->pin_cfg[offset].reg, &val); 2783d0407baSopenharmony_ci if (ret) { 2793d0407baSopenharmony_ci dev_err(pci->dev, "get gpio%d value failed\n", offset); 2803d0407baSopenharmony_ci return ret; 2813d0407baSopenharmony_ci } 2823d0407baSopenharmony_ci 2833d0407baSopenharmony_ci return !!(val & pci->pin_cfg[offset].val_msk); 2843d0407baSopenharmony_ci} 2853d0407baSopenharmony_ci 2863d0407baSopenharmony_cistatic void rk805_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) 2873d0407baSopenharmony_ci{ 2883d0407baSopenharmony_ci struct rk805_pctrl_info *pci = gpiochip_get_data(chip); 2893d0407baSopenharmony_ci int ret; 2903d0407baSopenharmony_ci if (!pci->pin_cfg[offset].val_msk) { 2913d0407baSopenharmony_ci return; 2923d0407baSopenharmony_ci } 2933d0407baSopenharmony_ci ret = regmap_update_bits(pci->rk808->regmap, pci->pin_cfg[offset].reg, pci->pin_cfg[offset].val_msk, 2943d0407baSopenharmony_ci value ? pci->pin_cfg[offset].val_msk : 0); 2953d0407baSopenharmony_ci if (ret) { 2963d0407baSopenharmony_ci dev_err(pci->dev, "set gpio%d value %d failed\n", offset, value); 2973d0407baSopenharmony_ci } 2983d0407baSopenharmony_ci} 2993d0407baSopenharmony_ci 3003d0407baSopenharmony_cistatic int rk805_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) 3013d0407baSopenharmony_ci{ 3023d0407baSopenharmony_ci return pinctrl_gpio_direction_input(chip->base + offset); 3033d0407baSopenharmony_ci} 3043d0407baSopenharmony_ci 3053d0407baSopenharmony_cistatic int rk805_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) 3063d0407baSopenharmony_ci{ 3073d0407baSopenharmony_ci rk805_gpio_set(chip, offset, value); 3083d0407baSopenharmony_ci return pinctrl_gpio_direction_output(chip->base + offset); 3093d0407baSopenharmony_ci} 3103d0407baSopenharmony_ci 3113d0407baSopenharmony_cistatic int rk805_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 3123d0407baSopenharmony_ci{ 3133d0407baSopenharmony_ci struct rk805_pctrl_info *pci = gpiochip_get_data(chip); 3143d0407baSopenharmony_ci unsigned int val; 3153d0407baSopenharmony_ci int ret; 3163d0407baSopenharmony_ci 3173d0407baSopenharmony_ci /* default output */ 3183d0407baSopenharmony_ci if (!pci->pin_cfg[offset].dir_msk) { 3193d0407baSopenharmony_ci return GPIO_LINE_DIRECTION_OUT; 3203d0407baSopenharmony_ci } 3213d0407baSopenharmony_ci 3223d0407baSopenharmony_ci ret = regmap_read(pci->rk808->regmap, pci->pin_cfg[offset].reg, &val); 3233d0407baSopenharmony_ci if (ret) { 3243d0407baSopenharmony_ci dev_err(pci->dev, "get gpio%d direction failed\n", offset); 3253d0407baSopenharmony_ci return ret; 3263d0407baSopenharmony_ci } 3273d0407baSopenharmony_ci 3283d0407baSopenharmony_ci if (val & pci->pin_cfg[offset].dir_msk) { 3293d0407baSopenharmony_ci return GPIO_LINE_DIRECTION_OUT; 3303d0407baSopenharmony_ci } 3313d0407baSopenharmony_ci 3323d0407baSopenharmony_ci return GPIO_LINE_DIRECTION_IN; 3333d0407baSopenharmony_ci} 3343d0407baSopenharmony_ci 3353d0407baSopenharmony_cistatic const struct gpio_chip rk805_gpio_chip = { 3363d0407baSopenharmony_ci .label = "rk805-gpio", 3373d0407baSopenharmony_ci .request = gpiochip_generic_request, 3383d0407baSopenharmony_ci .free = gpiochip_generic_free, 3393d0407baSopenharmony_ci .get_direction = rk805_gpio_get_direction, 3403d0407baSopenharmony_ci .get = rk805_gpio_get, 3413d0407baSopenharmony_ci .set = rk805_gpio_set, 3423d0407baSopenharmony_ci .direction_input = rk805_gpio_direction_input, 3433d0407baSopenharmony_ci .direction_output = rk805_gpio_direction_output, 3443d0407baSopenharmony_ci .can_sleep = true, 3453d0407baSopenharmony_ci .base = -1, 3463d0407baSopenharmony_ci .owner = THIS_MODULE, 3473d0407baSopenharmony_ci}; 3483d0407baSopenharmony_ci 3493d0407baSopenharmony_cistatic struct gpio_chip rk816_gpio_chip = { 3503d0407baSopenharmony_ci .label = "rk816-gpio", 3513d0407baSopenharmony_ci .request = gpiochip_generic_request, 3523d0407baSopenharmony_ci .free = gpiochip_generic_free, 3533d0407baSopenharmony_ci .get_direction = rk805_gpio_get_direction, 3543d0407baSopenharmony_ci .get = rk805_gpio_get, 3553d0407baSopenharmony_ci .set = rk805_gpio_set, 3563d0407baSopenharmony_ci .direction_input = rk805_gpio_direction_input, 3573d0407baSopenharmony_ci .direction_output = rk805_gpio_direction_output, 3583d0407baSopenharmony_ci .can_sleep = true, 3593d0407baSopenharmony_ci .base = -1, 3603d0407baSopenharmony_ci .owner = THIS_MODULE, 3613d0407baSopenharmony_ci}; 3623d0407baSopenharmony_ci 3633d0407baSopenharmony_cistatic struct gpio_chip rk817_gpio_chip = { 3643d0407baSopenharmony_ci .label = "rk817-gpio", 3653d0407baSopenharmony_ci .request = gpiochip_generic_request, 3663d0407baSopenharmony_ci .free = gpiochip_generic_free, 3673d0407baSopenharmony_ci .get_direction = rk805_gpio_get_direction, 3683d0407baSopenharmony_ci .get = rk805_gpio_get, 3693d0407baSopenharmony_ci .set = rk805_gpio_set, 3703d0407baSopenharmony_ci .direction_input = rk805_gpio_direction_input, 3713d0407baSopenharmony_ci .direction_output = rk805_gpio_direction_output, 3723d0407baSopenharmony_ci .can_sleep = true, 3733d0407baSopenharmony_ci .base = -1, 3743d0407baSopenharmony_ci .owner = THIS_MODULE, 3753d0407baSopenharmony_ci}; 3763d0407baSopenharmony_ci 3773d0407baSopenharmony_ci/* generic pinctrl */ 3783d0407baSopenharmony_cistatic int rk805_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) 3793d0407baSopenharmony_ci{ 3803d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 3813d0407baSopenharmony_ci 3823d0407baSopenharmony_ci return pci->num_pin_groups; 3833d0407baSopenharmony_ci} 3843d0407baSopenharmony_ci 3853d0407baSopenharmony_cistatic const char *rk805_pinctrl_get_group_name(struct pinctrl_dev *pctldev, unsigned int group) 3863d0407baSopenharmony_ci{ 3873d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 3883d0407baSopenharmony_ci 3893d0407baSopenharmony_ci return pci->groups[group].name; 3903d0407baSopenharmony_ci} 3913d0407baSopenharmony_ci 3923d0407baSopenharmony_cistatic int rk805_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group, const unsigned int **pins, 3933d0407baSopenharmony_ci unsigned int *num_pins) 3943d0407baSopenharmony_ci{ 3953d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 3963d0407baSopenharmony_ci 3973d0407baSopenharmony_ci *pins = pci->groups[group].pins; 3983d0407baSopenharmony_ci *num_pins = pci->groups[group].npins; 3993d0407baSopenharmony_ci 4003d0407baSopenharmony_ci return 0; 4013d0407baSopenharmony_ci} 4023d0407baSopenharmony_ci 4033d0407baSopenharmony_cistatic const struct pinctrl_ops rk805_pinctrl_ops = { 4043d0407baSopenharmony_ci .get_groups_count = rk805_pinctrl_get_groups_count, 4053d0407baSopenharmony_ci .get_group_name = rk805_pinctrl_get_group_name, 4063d0407baSopenharmony_ci .get_group_pins = rk805_pinctrl_get_group_pins, 4073d0407baSopenharmony_ci .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 4083d0407baSopenharmony_ci .dt_free_map = pinctrl_utils_free_map, 4093d0407baSopenharmony_ci}; 4103d0407baSopenharmony_ci 4113d0407baSopenharmony_cistatic int rk805_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) 4123d0407baSopenharmony_ci{ 4133d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 4143d0407baSopenharmony_ci 4153d0407baSopenharmony_ci return pci->num_functions; 4163d0407baSopenharmony_ci} 4173d0407baSopenharmony_ci 4183d0407baSopenharmony_cistatic const char *rk805_pinctrl_get_func_name(struct pinctrl_dev *pctldev, unsigned int function) 4193d0407baSopenharmony_ci{ 4203d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 4213d0407baSopenharmony_ci 4223d0407baSopenharmony_ci return pci->functions[function].name; 4233d0407baSopenharmony_ci} 4243d0407baSopenharmony_ci 4253d0407baSopenharmony_cistatic int rk805_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, unsigned int function, const char *const **groups, 4263d0407baSopenharmony_ci unsigned int *const num_groups) 4273d0407baSopenharmony_ci{ 4283d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 4293d0407baSopenharmony_ci 4303d0407baSopenharmony_ci *groups = pci->functions[function].groups; 4313d0407baSopenharmony_ci *num_groups = pci->functions[function].ngroups; 4323d0407baSopenharmony_ci 4333d0407baSopenharmony_ci return 0; 4343d0407baSopenharmony_ci} 4353d0407baSopenharmony_ci 4363d0407baSopenharmony_cistatic int _rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int offset, int mux) 4373d0407baSopenharmony_ci{ 4383d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 4393d0407baSopenharmony_ci int ret; 4403d0407baSopenharmony_ci 4413d0407baSopenharmony_ci if (!pci->pin_cfg[offset].fun_msk) { 4423d0407baSopenharmony_ci return 0; 4433d0407baSopenharmony_ci } 4443d0407baSopenharmony_ci 4453d0407baSopenharmony_ci if (mux == RK805_PINMUX_GPIO) { 4463d0407baSopenharmony_ci ret = regmap_update_bits(pci->rk808->regmap, pci->pin_cfg[offset].reg, pci->pin_cfg[offset].fun_msk, 4473d0407baSopenharmony_ci pci->pin_cfg[offset].fun_msk); 4483d0407baSopenharmony_ci if (ret) { 4493d0407baSopenharmony_ci dev_err(pci->dev, "set gpio%d GPIO failed\n", offset); 4503d0407baSopenharmony_ci return ret; 4513d0407baSopenharmony_ci } 4523d0407baSopenharmony_ci } else if (mux == RK805_PINMUX_TS) { 4533d0407baSopenharmony_ci ret = regmap_update_bits(pci->rk808->regmap, pci->pin_cfg[offset].reg, pci->pin_cfg[offset].fun_msk, 0); 4543d0407baSopenharmony_ci if (ret) { 4553d0407baSopenharmony_ci dev_err(pci->dev, "set gpio%d TS failed\n", offset); 4563d0407baSopenharmony_ci return ret; 4573d0407baSopenharmony_ci } 4583d0407baSopenharmony_ci } else { 4593d0407baSopenharmony_ci dev_err(pci->dev, "Couldn't find function mux %d\n", mux); 4603d0407baSopenharmony_ci return -EINVAL; 4613d0407baSopenharmony_ci } 4623d0407baSopenharmony_ci 4633d0407baSopenharmony_ci return 0; 4643d0407baSopenharmony_ci} 4653d0407baSopenharmony_ci 4663d0407baSopenharmony_cistatic int _rk817_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int offset, int mux) 4673d0407baSopenharmony_ci{ 4683d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 4693d0407baSopenharmony_ci int ret; 4703d0407baSopenharmony_ci 4713d0407baSopenharmony_ci if (!pci->pin_cfg[offset].fun_msk) { 4723d0407baSopenharmony_ci return 0; 4733d0407baSopenharmony_ci } 4743d0407baSopenharmony_ci 4753d0407baSopenharmony_ci mux <<= ffs(pci->pin_cfg[offset].fun_msk) - 1; 4763d0407baSopenharmony_ci ret = regmap_update_bits(pci->rk808->regmap, pci->pin_cfg[offset].reg, pci->pin_cfg[offset].fun_msk, mux); 4773d0407baSopenharmony_ci if (ret) { 4783d0407baSopenharmony_ci dev_err(pci->dev, "set gpio%d func%d failed\n", offset, mux); 4793d0407baSopenharmony_ci } 4803d0407baSopenharmony_ci 4813d0407baSopenharmony_ci return ret; 4823d0407baSopenharmony_ci} 4833d0407baSopenharmony_ci 4843d0407baSopenharmony_cistatic int rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned int function, unsigned int group) 4853d0407baSopenharmony_ci{ 4863d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 4873d0407baSopenharmony_ci int mux = pci->functions[function].mux_option; 4883d0407baSopenharmony_ci int offset = group; 4893d0407baSopenharmony_ci 4903d0407baSopenharmony_ci switch (pci->rk808->variant) { 4913d0407baSopenharmony_ci case RK805_ID: 4923d0407baSopenharmony_ci case RK816_ID: 4933d0407baSopenharmony_ci return _rk805_pinctrl_set_mux(pctldev, offset, mux); 4943d0407baSopenharmony_ci 4953d0407baSopenharmony_ci case RK809_ID: 4963d0407baSopenharmony_ci case RK817_ID: 4973d0407baSopenharmony_ci return _rk817_pinctrl_set_mux(pctldev, offset, mux); 4983d0407baSopenharmony_ci default: 4993d0407baSopenharmony_ci dev_err(pci->dev, "Couldn't find the variant id\n"); 5003d0407baSopenharmony_ci return -EINVAL; 5013d0407baSopenharmony_ci } 5023d0407baSopenharmony_ci} 5033d0407baSopenharmony_ci 5043d0407baSopenharmony_cistatic int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, 5053d0407baSopenharmony_ci unsigned int offset, bool input) 5063d0407baSopenharmony_ci{ 5073d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 5083d0407baSopenharmony_ci int ret; 5093d0407baSopenharmony_ci 5103d0407baSopenharmony_ci /* set direction */ 5113d0407baSopenharmony_ci if (!pci->pin_cfg[offset].dir_msk) { 5123d0407baSopenharmony_ci return 0; 5133d0407baSopenharmony_ci } 5143d0407baSopenharmony_ci 5153d0407baSopenharmony_ci ret = regmap_update_bits(pci->rk808->regmap, pci->pin_cfg[offset].reg, pci->pin_cfg[offset].dir_msk, 5163d0407baSopenharmony_ci input ? 0 : pci->pin_cfg[offset].dir_msk); 5173d0407baSopenharmony_ci if (ret) { 5183d0407baSopenharmony_ci dev_err(pci->dev, "set gpio%d direction failed\n", offset); 5193d0407baSopenharmony_ci return ret; 5203d0407baSopenharmony_ci } 5213d0407baSopenharmony_ci 5223d0407baSopenharmony_ci return ret; 5233d0407baSopenharmony_ci} 5243d0407baSopenharmony_ci 5253d0407baSopenharmony_cistatic int rk805_pinctrl_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, 5263d0407baSopenharmony_ci unsigned int offset) 5273d0407baSopenharmony_ci{ 5283d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 5293d0407baSopenharmony_ci 5303d0407baSopenharmony_ci /* switch to gpio function */ 5313d0407baSopenharmony_ci switch (pci->rk808->variant) { 5323d0407baSopenharmony_ci case RK805_ID: 5333d0407baSopenharmony_ci case RK816_ID: 5343d0407baSopenharmony_ci return _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO); 5353d0407baSopenharmony_ci default: 5363d0407baSopenharmony_ci return 0; 5373d0407baSopenharmony_ci } 5383d0407baSopenharmony_ci} 5393d0407baSopenharmony_ci 5403d0407baSopenharmony_cistatic const struct pinmux_ops rk805_pinmux_ops = { 5413d0407baSopenharmony_ci .gpio_request_enable = rk805_pinctrl_gpio_request_enable, 5423d0407baSopenharmony_ci .get_functions_count = rk805_pinctrl_get_funcs_count, 5433d0407baSopenharmony_ci .get_function_name = rk805_pinctrl_get_func_name, 5443d0407baSopenharmony_ci .get_function_groups = rk805_pinctrl_get_func_groups, 5453d0407baSopenharmony_ci .set_mux = rk805_pinctrl_set_mux, 5463d0407baSopenharmony_ci .gpio_set_direction = rk805_pmx_gpio_set_direction, 5473d0407baSopenharmony_ci}; 5483d0407baSopenharmony_ci 5493d0407baSopenharmony_cistatic int rk805_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config) 5503d0407baSopenharmony_ci{ 5513d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 5523d0407baSopenharmony_ci enum pin_config_param param = pinconf_to_config_param(*config); 5533d0407baSopenharmony_ci u32 arg = 0; 5543d0407baSopenharmony_ci 5553d0407baSopenharmony_ci switch (param) { 5563d0407baSopenharmony_ci case PIN_CONFIG_OUTPUT: 5573d0407baSopenharmony_ci case PIN_CONFIG_INPUT_ENABLE: 5583d0407baSopenharmony_ci arg = rk805_gpio_get(&pci->gpio_chip, pin); 5593d0407baSopenharmony_ci break; 5603d0407baSopenharmony_ci default: 5613d0407baSopenharmony_ci dev_err(pci->dev, "Properties not supported\n"); 5623d0407baSopenharmony_ci return -ENOTSUPP; 5633d0407baSopenharmony_ci } 5643d0407baSopenharmony_ci 5653d0407baSopenharmony_ci *config = pinconf_to_config_packed(param, (u16)arg); 5663d0407baSopenharmony_ci 5673d0407baSopenharmony_ci return 0; 5683d0407baSopenharmony_ci} 5693d0407baSopenharmony_ci 5703d0407baSopenharmony_cistatic int rk805_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs, 5713d0407baSopenharmony_ci unsigned int num_configs) 5723d0407baSopenharmony_ci{ 5733d0407baSopenharmony_ci struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 5743d0407baSopenharmony_ci enum pin_config_param param; 5753d0407baSopenharmony_ci u32 i, arg = 0; 5763d0407baSopenharmony_ci 5773d0407baSopenharmony_ci for (i = 0; i < num_configs; i++) { 5783d0407baSopenharmony_ci param = pinconf_to_config_param(configs[i]); 5793d0407baSopenharmony_ci arg = pinconf_to_config_argument(configs[i]); 5803d0407baSopenharmony_ci 5813d0407baSopenharmony_ci switch (param) { 5823d0407baSopenharmony_ci case PIN_CONFIG_OUTPUT: 5833d0407baSopenharmony_ci rk805_pmx_gpio_set_direction(pctldev, NULL, pin, false); 5843d0407baSopenharmony_ci rk805_gpio_set(&pci->gpio_chip, pin, arg); 5853d0407baSopenharmony_ci break; 5863d0407baSopenharmony_ci case PIN_CONFIG_INPUT_ENABLE: 5873d0407baSopenharmony_ci if (arg) { 5883d0407baSopenharmony_ci rk805_pmx_gpio_set_direction(pctldev, NULL, pin, true); 5893d0407baSopenharmony_ci } 5903d0407baSopenharmony_ci break; 5913d0407baSopenharmony_ci default: 5923d0407baSopenharmony_ci dev_err(pci->dev, "Properties not supported\n"); 5933d0407baSopenharmony_ci return -ENOTSUPP; 5943d0407baSopenharmony_ci } 5953d0407baSopenharmony_ci } 5963d0407baSopenharmony_ci 5973d0407baSopenharmony_ci return 0; 5983d0407baSopenharmony_ci} 5993d0407baSopenharmony_ci 6003d0407baSopenharmony_cistatic const struct pinconf_ops rk805_pinconf_ops = { 6013d0407baSopenharmony_ci .pin_config_get = rk805_pinconf_get, 6023d0407baSopenharmony_ci .pin_config_set = rk805_pinconf_set, 6033d0407baSopenharmony_ci}; 6043d0407baSopenharmony_ci 6053d0407baSopenharmony_cistatic const struct pinctrl_desc rk805_pinctrl_desc = { 6063d0407baSopenharmony_ci .name = "rk805-pinctrl", 6073d0407baSopenharmony_ci .pctlops = &rk805_pinctrl_ops, 6083d0407baSopenharmony_ci .pmxops = &rk805_pinmux_ops, 6093d0407baSopenharmony_ci .confops = &rk805_pinconf_ops, 6103d0407baSopenharmony_ci .owner = THIS_MODULE, 6113d0407baSopenharmony_ci}; 6123d0407baSopenharmony_ci 6133d0407baSopenharmony_cistatic struct pinctrl_desc rk816_pinctrl_desc = { 6143d0407baSopenharmony_ci .name = "rk816-pinctrl", 6153d0407baSopenharmony_ci .pctlops = &rk805_pinctrl_ops, 6163d0407baSopenharmony_ci .pmxops = &rk805_pinmux_ops, 6173d0407baSopenharmony_ci .confops = &rk805_pinconf_ops, 6183d0407baSopenharmony_ci .owner = THIS_MODULE, 6193d0407baSopenharmony_ci}; 6203d0407baSopenharmony_ci 6213d0407baSopenharmony_cistatic struct pinctrl_desc rk817_pinctrl_desc = { 6223d0407baSopenharmony_ci .name = "rk817-pinctrl", 6233d0407baSopenharmony_ci .pctlops = &rk805_pinctrl_ops, 6243d0407baSopenharmony_ci .pmxops = &rk805_pinmux_ops, 6253d0407baSopenharmony_ci .confops = &rk805_pinconf_ops, 6263d0407baSopenharmony_ci .owner = THIS_MODULE, 6273d0407baSopenharmony_ci}; 6283d0407baSopenharmony_ci 6293d0407baSopenharmony_cistatic int rk805_pinctrl_probe(struct platform_device *pdev) 6303d0407baSopenharmony_ci{ 6313d0407baSopenharmony_ci struct rk805_pctrl_info *pci; 6323d0407baSopenharmony_ci struct device_node *np; 6333d0407baSopenharmony_ci int ret; 6343d0407baSopenharmony_ci 6353d0407baSopenharmony_ci pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL); 6363d0407baSopenharmony_ci if (!pci) { 6373d0407baSopenharmony_ci return -ENOMEM; 6383d0407baSopenharmony_ci } 6393d0407baSopenharmony_ci 6403d0407baSopenharmony_ci pci->dev = &pdev->dev; 6413d0407baSopenharmony_ci np = of_get_child_by_name(pdev->dev.parent->of_node, "pinctrl_rk8xx"); 6423d0407baSopenharmony_ci if (np) { 6433d0407baSopenharmony_ci pci->dev->of_node = np; 6443d0407baSopenharmony_ci } else { 6453d0407baSopenharmony_ci pci->dev->of_node = pdev->dev.parent->of_node; 6463d0407baSopenharmony_ci } 6473d0407baSopenharmony_ci pci->rk808 = dev_get_drvdata(pdev->dev.parent); 6483d0407baSopenharmony_ci 6493d0407baSopenharmony_ci platform_set_drvdata(pdev, pci); 6503d0407baSopenharmony_ci 6513d0407baSopenharmony_ci switch (pci->rk808->variant) { 6523d0407baSopenharmony_ci case RK805_ID: 6533d0407baSopenharmony_ci pci->pinctrl_desc = rk805_pinctrl_desc; 6543d0407baSopenharmony_ci pci->gpio_chip = rk805_gpio_chip; 6553d0407baSopenharmony_ci pci->pins = rk805_pins_desc; 6563d0407baSopenharmony_ci pci->num_pins = ARRAY_SIZE(rk805_pins_desc); 6573d0407baSopenharmony_ci pci->functions = rk805_pin_functions; 6583d0407baSopenharmony_ci pci->num_functions = ARRAY_SIZE(rk805_pin_functions); 6593d0407baSopenharmony_ci pci->groups = rk805_pin_groups; 6603d0407baSopenharmony_ci pci->num_pin_groups = ARRAY_SIZE(rk805_pin_groups); 6613d0407baSopenharmony_ci pci->pinctrl_desc.pins = rk805_pins_desc; 6623d0407baSopenharmony_ci pci->pinctrl_desc.npins = ARRAY_SIZE(rk805_pins_desc); 6633d0407baSopenharmony_ci pci->pin_cfg = rk805_gpio_cfgs; 6643d0407baSopenharmony_ci pci->gpio_chip.ngpio = ARRAY_SIZE(rk805_gpio_cfgs); 6653d0407baSopenharmony_ci break; 6663d0407baSopenharmony_ci 6673d0407baSopenharmony_ci case RK816_ID: 6683d0407baSopenharmony_ci pci->pinctrl_desc = rk816_pinctrl_desc; 6693d0407baSopenharmony_ci pci->gpio_chip = rk816_gpio_chip; 6703d0407baSopenharmony_ci pci->pins = rk816_pins_desc; 6713d0407baSopenharmony_ci pci->num_pins = ARRAY_SIZE(rk816_pins_desc); 6723d0407baSopenharmony_ci pci->functions = rk816_pin_functions; 6733d0407baSopenharmony_ci pci->num_functions = ARRAY_SIZE(rk816_pin_functions); 6743d0407baSopenharmony_ci pci->groups = rk816_pin_groups; 6753d0407baSopenharmony_ci pci->num_pin_groups = ARRAY_SIZE(rk816_pin_groups); 6763d0407baSopenharmony_ci pci->pinctrl_desc.pins = rk816_pins_desc; 6773d0407baSopenharmony_ci pci->pinctrl_desc.npins = ARRAY_SIZE(rk816_pins_desc); 6783d0407baSopenharmony_ci pci->pin_cfg = rk816_gpio_cfgs; 6793d0407baSopenharmony_ci pci->gpio_chip.ngpio = ARRAY_SIZE(rk816_gpio_cfgs); 6803d0407baSopenharmony_ci break; 6813d0407baSopenharmony_ci 6823d0407baSopenharmony_ci case RK809_ID: 6833d0407baSopenharmony_ci case RK817_ID: 6843d0407baSopenharmony_ci pci->pinctrl_desc = rk817_pinctrl_desc; 6853d0407baSopenharmony_ci pci->gpio_chip = rk817_gpio_chip; 6863d0407baSopenharmony_ci pci->pins = rk817_pins_desc; 6873d0407baSopenharmony_ci pci->num_pins = ARRAY_SIZE(rk817_pins_desc); 6883d0407baSopenharmony_ci pci->functions = rk817_pin_functions; 6893d0407baSopenharmony_ci pci->num_functions = ARRAY_SIZE(rk817_pin_functions); 6903d0407baSopenharmony_ci pci->groups = rk817_pin_groups; 6913d0407baSopenharmony_ci pci->num_pin_groups = ARRAY_SIZE(rk817_pin_groups); 6923d0407baSopenharmony_ci pci->pinctrl_desc.pins = rk817_pins_desc; 6933d0407baSopenharmony_ci pci->pinctrl_desc.npins = ARRAY_SIZE(rk817_pins_desc); 6943d0407baSopenharmony_ci pci->pin_cfg = rk817_gpio_cfgs; 6953d0407baSopenharmony_ci pci->gpio_chip.ngpio = ARRAY_SIZE(rk817_gpio_cfgs); 6963d0407baSopenharmony_ci /* for rk809 only a sleep pin */ 6973d0407baSopenharmony_ci if (pci->rk808->variant == RK809_ID) { 6983d0407baSopenharmony_ci pci->pinctrl_desc.npins = 1; 6993d0407baSopenharmony_ci pci->num_pin_groups = 1; 7003d0407baSopenharmony_ci pci->num_pins = 1; 7013d0407baSopenharmony_ci pci->gpio_chip.ngpio = 1; 7023d0407baSopenharmony_ci } 7033d0407baSopenharmony_ci break; 7043d0407baSopenharmony_ci 7053d0407baSopenharmony_ci default: 7063d0407baSopenharmony_ci dev_err(&pdev->dev, "unsupported RK805 ID %lu\n", pci->rk808->variant); 7073d0407baSopenharmony_ci return -EINVAL; 7083d0407baSopenharmony_ci } 7093d0407baSopenharmony_ci 7103d0407baSopenharmony_ci pci->gpio_chip.parent = &pdev->dev; 7113d0407baSopenharmony_ci 7123d0407baSopenharmony_ci if (np) { 7133d0407baSopenharmony_ci pci->gpio_chip.of_node = np; 7143d0407baSopenharmony_ci } else { 7153d0407baSopenharmony_ci pci->gpio_chip.of_node = pdev->dev.parent->of_node; 7163d0407baSopenharmony_ci } 7173d0407baSopenharmony_ci 7183d0407baSopenharmony_ci /* Add gpiochip */ 7193d0407baSopenharmony_ci ret = devm_gpiochip_add_data(&pdev->dev, &pci->gpio_chip, pci); 7203d0407baSopenharmony_ci if (ret < 0) { 7213d0407baSopenharmony_ci dev_err(&pdev->dev, "Couldn't add gpiochip\n"); 7223d0407baSopenharmony_ci return ret; 7233d0407baSopenharmony_ci } 7243d0407baSopenharmony_ci 7253d0407baSopenharmony_ci /* Add pinctrl */ 7263d0407baSopenharmony_ci pci->pctl = devm_pinctrl_register(&pdev->dev, &pci->pinctrl_desc, pci); 7273d0407baSopenharmony_ci if (IS_ERR(pci->pctl)) { 7283d0407baSopenharmony_ci dev_err(&pdev->dev, "Couldn't add pinctrl\n"); 7293d0407baSopenharmony_ci return PTR_ERR(pci->pctl); 7303d0407baSopenharmony_ci } 7313d0407baSopenharmony_ci 7323d0407baSopenharmony_ci /* Add pin range */ 7333d0407baSopenharmony_ci ret = gpiochip_add_pin_range(&pci->gpio_chip, dev_name(&pdev->dev), 0, 0, pci->gpio_chip.ngpio); 7343d0407baSopenharmony_ci if (ret < 0) { 7353d0407baSopenharmony_ci dev_err(&pdev->dev, "Couldn't add gpiochip pin range\n"); 7363d0407baSopenharmony_ci return ret; 7373d0407baSopenharmony_ci } 7383d0407baSopenharmony_ci 7393d0407baSopenharmony_ci return 0; 7403d0407baSopenharmony_ci} 7413d0407baSopenharmony_ci 7423d0407baSopenharmony_cistatic struct platform_driver rk805_pinctrl_driver = { 7433d0407baSopenharmony_ci .probe = rk805_pinctrl_probe, 7443d0407baSopenharmony_ci .driver = 7453d0407baSopenharmony_ci { 7463d0407baSopenharmony_ci .name = "rk805-pinctrl", 7473d0407baSopenharmony_ci }, 7483d0407baSopenharmony_ci}; 7493d0407baSopenharmony_ci 7503d0407baSopenharmony_cistatic int __init rk805_pinctrl_driver_register(void) 7513d0407baSopenharmony_ci{ 7523d0407baSopenharmony_ci return platform_driver_register(&rk805_pinctrl_driver); 7533d0407baSopenharmony_ci} 7543d0407baSopenharmony_cifs_initcall_sync(rk805_pinctrl_driver_register); 7553d0407baSopenharmony_ci 7563d0407baSopenharmony_ciMODULE_DESCRIPTION("RK805 pin control and GPIO driver"); 7573d0407baSopenharmony_ciMODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>"); 7583d0407baSopenharmony_ciMODULE_LICENSE("GPL v2"); 759