12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2ea479996SJoseph Chen /* 3ea479996SJoseph Chen * Pinctrl driver for Rockchip RK805 PMIC 4ea479996SJoseph Chen * 5ea479996SJoseph Chen * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd 6ea479996SJoseph Chen * 7ea479996SJoseph Chen * Author: Joseph Chen <chenjh@rock-chips.com> 8ea479996SJoseph Chen * 9ea479996SJoseph Chen * Based on the pinctrl-as3722 driver 10ea479996SJoseph Chen */ 11ea479996SJoseph Chen 12ea479996SJoseph Chen #include <linux/gpio/driver.h> 13ea479996SJoseph Chen #include <linux/kernel.h> 14ea479996SJoseph Chen #include <linux/module.h> 15ea479996SJoseph Chen #include <linux/mfd/rk808.h> 16ea479996SJoseph Chen #include <linux/of.h> 17ea479996SJoseph Chen #include <linux/of_device.h> 18ea479996SJoseph Chen #include <linux/platform_device.h> 19ea479996SJoseph Chen #include <linux/pinctrl/consumer.h> 20ea479996SJoseph Chen #include <linux/pinctrl/machine.h> 21ea479996SJoseph Chen #include <linux/pinctrl/pinctrl.h> 22ea479996SJoseph Chen #include <linux/pinctrl/pinconf-generic.h> 23ea479996SJoseph Chen #include <linux/pinctrl/pinconf.h> 24ea479996SJoseph Chen #include <linux/pinctrl/pinmux.h> 25ea479996SJoseph Chen #include <linux/pm.h> 26ea479996SJoseph Chen #include <linux/slab.h> 27ea479996SJoseph Chen 28ea479996SJoseph Chen #include "core.h" 29ea479996SJoseph Chen #include "pinconf.h" 30ea479996SJoseph Chen #include "pinctrl-utils.h" 31ea479996SJoseph Chen 32ea479996SJoseph Chen struct rk805_pin_function { 33ea479996SJoseph Chen const char *name; 34ea479996SJoseph Chen const char *const *groups; 35ea479996SJoseph Chen unsigned int ngroups; 36ea479996SJoseph Chen int mux_option; 37ea479996SJoseph Chen }; 38ea479996SJoseph Chen 39ea479996SJoseph Chen struct rk805_pin_group { 40ea479996SJoseph Chen const char *name; 41ea479996SJoseph Chen const unsigned int pins[1]; 42ea479996SJoseph Chen unsigned int npins; 43ea479996SJoseph Chen }; 44ea479996SJoseph Chen 45ea479996SJoseph Chen /* 46ea479996SJoseph Chen * @reg: gpio setting register; 47ea479996SJoseph Chen * @fun_mask: functions select mask value, when set is gpio; 48ea479996SJoseph Chen * @dir_mask: input or output mask value, when set is output, otherwise input; 49ea479996SJoseph Chen * @val_mask: gpio set value, when set is level high, otherwise low; 50ea479996SJoseph Chen * 51ea479996SJoseph Chen * Different PMIC has different pin features, belowing 3 mask members are not 52ea479996SJoseph Chen * all necessary for every PMIC. For example, RK805 has 2 pins that can be used 53ea479996SJoseph Chen * as output only GPIOs, so func_mask and dir_mask are not needed. RK816 has 1 54ea479996SJoseph Chen * pin that can be used as TS/GPIO, so fun_mask, dir_mask and val_mask are all 55ea479996SJoseph Chen * necessary. 56ea479996SJoseph Chen */ 57ea479996SJoseph Chen struct rk805_pin_config { 58ea479996SJoseph Chen u8 reg; 59ea479996SJoseph Chen u8 fun_msk; 60ea479996SJoseph Chen u8 dir_msk; 61ea479996SJoseph Chen u8 val_msk; 62ea479996SJoseph Chen }; 63ea479996SJoseph Chen 64ea479996SJoseph Chen struct rk805_pctrl_info { 65ea479996SJoseph Chen struct rk808 *rk808; 66ea479996SJoseph Chen struct device *dev; 67ea479996SJoseph Chen struct pinctrl_dev *pctl; 68ea479996SJoseph Chen struct gpio_chip gpio_chip; 69ea479996SJoseph Chen struct pinctrl_desc pinctrl_desc; 70ea479996SJoseph Chen const struct rk805_pin_function *functions; 71ea479996SJoseph Chen unsigned int num_functions; 72ea479996SJoseph Chen const struct rk805_pin_group *groups; 73ea479996SJoseph Chen int num_pin_groups; 74ea479996SJoseph Chen const struct pinctrl_pin_desc *pins; 75ea479996SJoseph Chen unsigned int num_pins; 76ea479996SJoseph Chen struct rk805_pin_config *pin_cfg; 77ea479996SJoseph Chen }; 78ea479996SJoseph Chen 79ea479996SJoseph Chen enum rk805_pinmux_option { 80ea479996SJoseph Chen RK805_PINMUX_GPIO, 81ea479996SJoseph Chen }; 82ea479996SJoseph Chen 83ea479996SJoseph Chen enum { 84ea479996SJoseph Chen RK805_GPIO0, 85ea479996SJoseph Chen RK805_GPIO1, 86ea479996SJoseph Chen }; 87ea479996SJoseph Chen 88ea479996SJoseph Chen static const char *const rk805_gpio_groups[] = { 89ea479996SJoseph Chen "gpio0", 90ea479996SJoseph Chen "gpio1", 91ea479996SJoseph Chen }; 92ea479996SJoseph Chen 93ea479996SJoseph Chen /* RK805: 2 output only GPIOs */ 94ea479996SJoseph Chen static const struct pinctrl_pin_desc rk805_pins_desc[] = { 95ea479996SJoseph Chen PINCTRL_PIN(RK805_GPIO0, "gpio0"), 96ea479996SJoseph Chen PINCTRL_PIN(RK805_GPIO1, "gpio1"), 97ea479996SJoseph Chen }; 98ea479996SJoseph Chen 99ea479996SJoseph Chen static const struct rk805_pin_function rk805_pin_functions[] = { 100ea479996SJoseph Chen { 101ea479996SJoseph Chen .name = "gpio", 102ea479996SJoseph Chen .groups = rk805_gpio_groups, 103ea479996SJoseph Chen .ngroups = ARRAY_SIZE(rk805_gpio_groups), 104ea479996SJoseph Chen .mux_option = RK805_PINMUX_GPIO, 105ea479996SJoseph Chen }, 106ea479996SJoseph Chen }; 107ea479996SJoseph Chen 108ea479996SJoseph Chen static const struct rk805_pin_group rk805_pin_groups[] = { 109ea479996SJoseph Chen { 110ea479996SJoseph Chen .name = "gpio0", 111ea479996SJoseph Chen .pins = { RK805_GPIO0 }, 112ea479996SJoseph Chen .npins = 1, 113ea479996SJoseph Chen }, 114ea479996SJoseph Chen { 115ea479996SJoseph Chen .name = "gpio1", 116ea479996SJoseph Chen .pins = { RK805_GPIO1 }, 117ea479996SJoseph Chen .npins = 1, 118ea479996SJoseph Chen }, 119ea479996SJoseph Chen }; 120ea479996SJoseph Chen 121ea479996SJoseph Chen #define RK805_GPIO0_VAL_MSK BIT(0) 122ea479996SJoseph Chen #define RK805_GPIO1_VAL_MSK BIT(1) 123ea479996SJoseph Chen 124ea479996SJoseph Chen static struct rk805_pin_config rk805_gpio_cfgs[] = { 125ea479996SJoseph Chen { 126ea479996SJoseph Chen .reg = RK805_OUT_REG, 127ea479996SJoseph Chen .val_msk = RK805_GPIO0_VAL_MSK, 128ea479996SJoseph Chen }, 129ea479996SJoseph Chen { 130ea479996SJoseph Chen .reg = RK805_OUT_REG, 131ea479996SJoseph Chen .val_msk = RK805_GPIO1_VAL_MSK, 132ea479996SJoseph Chen }, 133ea479996SJoseph Chen }; 134ea479996SJoseph Chen 135ea479996SJoseph Chen /* generic gpio chip */ 136ea479996SJoseph Chen static int rk805_gpio_get(struct gpio_chip *chip, unsigned int offset) 137ea479996SJoseph Chen { 138ea479996SJoseph Chen struct rk805_pctrl_info *pci = gpiochip_get_data(chip); 139ea479996SJoseph Chen int ret, val; 140ea479996SJoseph Chen 141ea479996SJoseph Chen ret = regmap_read(pci->rk808->regmap, pci->pin_cfg[offset].reg, &val); 142ea479996SJoseph Chen if (ret) { 143ea479996SJoseph Chen dev_err(pci->dev, "get gpio%d value failed\n", offset); 144ea479996SJoseph Chen return ret; 145ea479996SJoseph Chen } 146ea479996SJoseph Chen 147ea479996SJoseph Chen return !!(val & pci->pin_cfg[offset].val_msk); 148ea479996SJoseph Chen } 149ea479996SJoseph Chen 150ea479996SJoseph Chen static void rk805_gpio_set(struct gpio_chip *chip, 151ea479996SJoseph Chen unsigned int offset, 152ea479996SJoseph Chen int value) 153ea479996SJoseph Chen { 154ea479996SJoseph Chen struct rk805_pctrl_info *pci = gpiochip_get_data(chip); 155ea479996SJoseph Chen int ret; 156ea479996SJoseph Chen 157ea479996SJoseph Chen ret = regmap_update_bits(pci->rk808->regmap, 158ea479996SJoseph Chen pci->pin_cfg[offset].reg, 159ea479996SJoseph Chen pci->pin_cfg[offset].val_msk, 160ea479996SJoseph Chen value ? pci->pin_cfg[offset].val_msk : 0); 161ea479996SJoseph Chen if (ret) 162ea479996SJoseph Chen dev_err(pci->dev, "set gpio%d value %d failed\n", 163ea479996SJoseph Chen offset, value); 164ea479996SJoseph Chen } 165ea479996SJoseph Chen 166ea479996SJoseph Chen static int rk805_gpio_direction_input(struct gpio_chip *chip, 167ea479996SJoseph Chen unsigned int offset) 168ea479996SJoseph Chen { 169ea479996SJoseph Chen return pinctrl_gpio_direction_input(chip->base + offset); 170ea479996SJoseph Chen } 171ea479996SJoseph Chen 172ea479996SJoseph Chen static int rk805_gpio_direction_output(struct gpio_chip *chip, 173ea479996SJoseph Chen unsigned int offset, int value) 174ea479996SJoseph Chen { 175ea479996SJoseph Chen rk805_gpio_set(chip, offset, value); 176ea479996SJoseph Chen return pinctrl_gpio_direction_output(chip->base + offset); 177ea479996SJoseph Chen } 178ea479996SJoseph Chen 179ea479996SJoseph Chen static int rk805_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) 180ea479996SJoseph Chen { 181ea479996SJoseph Chen struct rk805_pctrl_info *pci = gpiochip_get_data(chip); 182ea479996SJoseph Chen unsigned int val; 183ea479996SJoseph Chen int ret; 184ea479996SJoseph Chen 185ea479996SJoseph Chen /* default output*/ 186ea479996SJoseph Chen if (!pci->pin_cfg[offset].dir_msk) 187ea479996SJoseph Chen return 0; 188ea479996SJoseph Chen 189ea479996SJoseph Chen ret = regmap_read(pci->rk808->regmap, 190ea479996SJoseph Chen pci->pin_cfg[offset].reg, 191ea479996SJoseph Chen &val); 192ea479996SJoseph Chen if (ret) { 193ea479996SJoseph Chen dev_err(pci->dev, "get gpio%d direction failed\n", offset); 194ea479996SJoseph Chen return ret; 195ea479996SJoseph Chen } 196ea479996SJoseph Chen 197ea479996SJoseph Chen return !(val & pci->pin_cfg[offset].dir_msk); 198ea479996SJoseph Chen } 199ea479996SJoseph Chen 2006e28aaabSNishka Dasgupta static const struct gpio_chip rk805_gpio_chip = { 201ea479996SJoseph Chen .label = "rk805-gpio", 202ea479996SJoseph Chen .request = gpiochip_generic_request, 203ea479996SJoseph Chen .free = gpiochip_generic_free, 204ea479996SJoseph Chen .get_direction = rk805_gpio_get_direction, 205ea479996SJoseph Chen .get = rk805_gpio_get, 206ea479996SJoseph Chen .set = rk805_gpio_set, 207ea479996SJoseph Chen .direction_input = rk805_gpio_direction_input, 208ea479996SJoseph Chen .direction_output = rk805_gpio_direction_output, 209ea479996SJoseph Chen .can_sleep = true, 210ea479996SJoseph Chen .base = -1, 211ea479996SJoseph Chen .owner = THIS_MODULE, 212ea479996SJoseph Chen }; 213ea479996SJoseph Chen 214ea479996SJoseph Chen /* generic pinctrl */ 215ea479996SJoseph Chen static int rk805_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) 216ea479996SJoseph Chen { 217ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 218ea479996SJoseph Chen 219ea479996SJoseph Chen return pci->num_pin_groups; 220ea479996SJoseph Chen } 221ea479996SJoseph Chen 222ea479996SJoseph Chen static const char *rk805_pinctrl_get_group_name(struct pinctrl_dev *pctldev, 223ea479996SJoseph Chen unsigned int group) 224ea479996SJoseph Chen { 225ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 226ea479996SJoseph Chen 227ea479996SJoseph Chen return pci->groups[group].name; 228ea479996SJoseph Chen } 229ea479996SJoseph Chen 230ea479996SJoseph Chen static int rk805_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, 231ea479996SJoseph Chen unsigned int group, 232ea479996SJoseph Chen const unsigned int **pins, 233ea479996SJoseph Chen unsigned int *num_pins) 234ea479996SJoseph Chen { 235ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 236ea479996SJoseph Chen 237ea479996SJoseph Chen *pins = pci->groups[group].pins; 238ea479996SJoseph Chen *num_pins = pci->groups[group].npins; 239ea479996SJoseph Chen 240ea479996SJoseph Chen return 0; 241ea479996SJoseph Chen } 242ea479996SJoseph Chen 243ea479996SJoseph Chen static const struct pinctrl_ops rk805_pinctrl_ops = { 244ea479996SJoseph Chen .get_groups_count = rk805_pinctrl_get_groups_count, 245ea479996SJoseph Chen .get_group_name = rk805_pinctrl_get_group_name, 246ea479996SJoseph Chen .get_group_pins = rk805_pinctrl_get_group_pins, 247ea479996SJoseph Chen .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, 248ea479996SJoseph Chen .dt_free_map = pinctrl_utils_free_map, 249ea479996SJoseph Chen }; 250ea479996SJoseph Chen 251ea479996SJoseph Chen static int rk805_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev) 252ea479996SJoseph Chen { 253ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 254ea479996SJoseph Chen 255ea479996SJoseph Chen return pci->num_functions; 256ea479996SJoseph Chen } 257ea479996SJoseph Chen 258ea479996SJoseph Chen static const char *rk805_pinctrl_get_func_name(struct pinctrl_dev *pctldev, 259ea479996SJoseph Chen unsigned int function) 260ea479996SJoseph Chen { 261ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 262ea479996SJoseph Chen 263ea479996SJoseph Chen return pci->functions[function].name; 264ea479996SJoseph Chen } 265ea479996SJoseph Chen 266ea479996SJoseph Chen static int rk805_pinctrl_get_func_groups(struct pinctrl_dev *pctldev, 267ea479996SJoseph Chen unsigned int function, 268ea479996SJoseph Chen const char *const **groups, 269ea479996SJoseph Chen unsigned int *const num_groups) 270ea479996SJoseph Chen { 271ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 272ea479996SJoseph Chen 273ea479996SJoseph Chen *groups = pci->functions[function].groups; 274ea479996SJoseph Chen *num_groups = pci->functions[function].ngroups; 275ea479996SJoseph Chen 276ea479996SJoseph Chen return 0; 277ea479996SJoseph Chen } 278ea479996SJoseph Chen 279ea479996SJoseph Chen static int _rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, 280ea479996SJoseph Chen unsigned int offset, 281ea479996SJoseph Chen int mux) 282ea479996SJoseph Chen { 283ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 284ea479996SJoseph Chen int ret; 285ea479996SJoseph Chen 286ea479996SJoseph Chen if (!pci->pin_cfg[offset].fun_msk) 287ea479996SJoseph Chen return 0; 288ea479996SJoseph Chen 289ea479996SJoseph Chen if (mux == RK805_PINMUX_GPIO) { 290ea479996SJoseph Chen ret = regmap_update_bits(pci->rk808->regmap, 291ea479996SJoseph Chen pci->pin_cfg[offset].reg, 292ea479996SJoseph Chen pci->pin_cfg[offset].fun_msk, 293ea479996SJoseph Chen pci->pin_cfg[offset].fun_msk); 294ea479996SJoseph Chen if (ret) { 295ea479996SJoseph Chen dev_err(pci->dev, "set gpio%d GPIO failed\n", offset); 296ea479996SJoseph Chen return ret; 297ea479996SJoseph Chen } 298ea479996SJoseph Chen } else { 299ea479996SJoseph Chen dev_err(pci->dev, "Couldn't find function mux %d\n", mux); 300ea479996SJoseph Chen return -EINVAL; 301ea479996SJoseph Chen } 302ea479996SJoseph Chen 303ea479996SJoseph Chen return 0; 304ea479996SJoseph Chen } 305ea479996SJoseph Chen 306ea479996SJoseph Chen static int rk805_pinctrl_set_mux(struct pinctrl_dev *pctldev, 307ea479996SJoseph Chen unsigned int function, 308ea479996SJoseph Chen unsigned int group) 309ea479996SJoseph Chen { 310ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 311ea479996SJoseph Chen int mux = pci->functions[function].mux_option; 312ea479996SJoseph Chen int offset = group; 313ea479996SJoseph Chen 314ea479996SJoseph Chen return _rk805_pinctrl_set_mux(pctldev, offset, mux); 315ea479996SJoseph Chen } 316ea479996SJoseph Chen 317ea479996SJoseph Chen static int rk805_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, 318ea479996SJoseph Chen struct pinctrl_gpio_range *range, 319ea479996SJoseph Chen unsigned int offset, bool input) 320ea479996SJoseph Chen { 321ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 322ea479996SJoseph Chen int ret; 323ea479996SJoseph Chen 324ea479996SJoseph Chen /* switch to gpio function */ 325ea479996SJoseph Chen ret = _rk805_pinctrl_set_mux(pctldev, offset, RK805_PINMUX_GPIO); 326ea479996SJoseph Chen if (ret) { 327ea479996SJoseph Chen dev_err(pci->dev, "set gpio%d mux failed\n", offset); 328ea479996SJoseph Chen return ret; 329ea479996SJoseph Chen } 330ea479996SJoseph Chen 331ea479996SJoseph Chen /* set direction */ 332ea479996SJoseph Chen if (!pci->pin_cfg[offset].dir_msk) 333ea479996SJoseph Chen return 0; 334ea479996SJoseph Chen 335ea479996SJoseph Chen ret = regmap_update_bits(pci->rk808->regmap, 336ea479996SJoseph Chen pci->pin_cfg[offset].reg, 337ea479996SJoseph Chen pci->pin_cfg[offset].dir_msk, 338ea479996SJoseph Chen input ? 0 : pci->pin_cfg[offset].dir_msk); 339ea479996SJoseph Chen if (ret) { 340ea479996SJoseph Chen dev_err(pci->dev, "set gpio%d direction failed\n", offset); 341ea479996SJoseph Chen return ret; 342ea479996SJoseph Chen } 343ea479996SJoseph Chen 344ea479996SJoseph Chen return ret; 345ea479996SJoseph Chen } 346ea479996SJoseph Chen 347ea479996SJoseph Chen static const struct pinmux_ops rk805_pinmux_ops = { 348ea479996SJoseph Chen .get_functions_count = rk805_pinctrl_get_funcs_count, 349ea479996SJoseph Chen .get_function_name = rk805_pinctrl_get_func_name, 350ea479996SJoseph Chen .get_function_groups = rk805_pinctrl_get_func_groups, 351ea479996SJoseph Chen .set_mux = rk805_pinctrl_set_mux, 352ea479996SJoseph Chen .gpio_set_direction = rk805_pmx_gpio_set_direction, 353ea479996SJoseph Chen }; 354ea479996SJoseph Chen 355ea479996SJoseph Chen static int rk805_pinconf_get(struct pinctrl_dev *pctldev, 356ea479996SJoseph Chen unsigned int pin, unsigned long *config) 357ea479996SJoseph Chen { 358ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 359ea479996SJoseph Chen enum pin_config_param param = pinconf_to_config_param(*config); 360ea479996SJoseph Chen u32 arg = 0; 361ea479996SJoseph Chen 362ea479996SJoseph Chen switch (param) { 363ea479996SJoseph Chen case PIN_CONFIG_OUTPUT: 364ea479996SJoseph Chen arg = rk805_gpio_get(&pci->gpio_chip, pin); 365ea479996SJoseph Chen break; 366ea479996SJoseph Chen default: 367ea479996SJoseph Chen dev_err(pci->dev, "Properties not supported\n"); 368ea479996SJoseph Chen return -ENOTSUPP; 369ea479996SJoseph Chen } 370ea479996SJoseph Chen 371ea479996SJoseph Chen *config = pinconf_to_config_packed(param, (u16)arg); 372ea479996SJoseph Chen 373ea479996SJoseph Chen return 0; 374ea479996SJoseph Chen } 375ea479996SJoseph Chen 376ea479996SJoseph Chen static int rk805_pinconf_set(struct pinctrl_dev *pctldev, 377ea479996SJoseph Chen unsigned int pin, unsigned long *configs, 378ea479996SJoseph Chen unsigned int num_configs) 379ea479996SJoseph Chen { 380ea479996SJoseph Chen struct rk805_pctrl_info *pci = pinctrl_dev_get_drvdata(pctldev); 381ea479996SJoseph Chen enum pin_config_param param; 382ea479996SJoseph Chen u32 i, arg = 0; 383ea479996SJoseph Chen 384ea479996SJoseph Chen for (i = 0; i < num_configs; i++) { 385ea479996SJoseph Chen param = pinconf_to_config_param(configs[i]); 386ea479996SJoseph Chen arg = pinconf_to_config_argument(configs[i]); 387ea479996SJoseph Chen 388ea479996SJoseph Chen switch (param) { 389ea479996SJoseph Chen case PIN_CONFIG_OUTPUT: 390ea479996SJoseph Chen rk805_gpio_set(&pci->gpio_chip, pin, arg); 391ea479996SJoseph Chen rk805_pmx_gpio_set_direction(pctldev, NULL, pin, false); 392ea479996SJoseph Chen break; 393ea479996SJoseph Chen default: 394ea479996SJoseph Chen dev_err(pci->dev, "Properties not supported\n"); 395ea479996SJoseph Chen return -ENOTSUPP; 396ea479996SJoseph Chen } 397ea479996SJoseph Chen } 398ea479996SJoseph Chen 399ea479996SJoseph Chen return 0; 400ea479996SJoseph Chen } 401ea479996SJoseph Chen 402ea479996SJoseph Chen static const struct pinconf_ops rk805_pinconf_ops = { 403ea479996SJoseph Chen .pin_config_get = rk805_pinconf_get, 404ea479996SJoseph Chen .pin_config_set = rk805_pinconf_set, 405ea479996SJoseph Chen }; 406ea479996SJoseph Chen 4076e28aaabSNishka Dasgupta static const struct pinctrl_desc rk805_pinctrl_desc = { 408ea479996SJoseph Chen .name = "rk805-pinctrl", 409ea479996SJoseph Chen .pctlops = &rk805_pinctrl_ops, 410ea479996SJoseph Chen .pmxops = &rk805_pinmux_ops, 411ea479996SJoseph Chen .confops = &rk805_pinconf_ops, 412ea479996SJoseph Chen .owner = THIS_MODULE, 413ea479996SJoseph Chen }; 414ea479996SJoseph Chen 415ea479996SJoseph Chen static int rk805_pinctrl_probe(struct platform_device *pdev) 416ea479996SJoseph Chen { 417ea479996SJoseph Chen struct rk805_pctrl_info *pci; 418ea479996SJoseph Chen int ret; 419ea479996SJoseph Chen 420ea479996SJoseph Chen pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL); 421ea479996SJoseph Chen if (!pci) 422ea479996SJoseph Chen return -ENOMEM; 423ea479996SJoseph Chen 424ea479996SJoseph Chen pci->dev = &pdev->dev; 425ea479996SJoseph Chen pci->dev->of_node = pdev->dev.parent->of_node; 426ea479996SJoseph Chen pci->rk808 = dev_get_drvdata(pdev->dev.parent); 427ea479996SJoseph Chen 428ea479996SJoseph Chen pci->pinctrl_desc = rk805_pinctrl_desc; 429ea479996SJoseph Chen pci->gpio_chip = rk805_gpio_chip; 430ea479996SJoseph Chen pci->gpio_chip.parent = &pdev->dev; 431ea479996SJoseph Chen pci->gpio_chip.of_node = pdev->dev.parent->of_node; 432ea479996SJoseph Chen 433ea479996SJoseph Chen platform_set_drvdata(pdev, pci); 434ea479996SJoseph Chen 435ea479996SJoseph Chen switch (pci->rk808->variant) { 436ea479996SJoseph Chen case RK805_ID: 437ea479996SJoseph Chen pci->pins = rk805_pins_desc; 438ea479996SJoseph Chen pci->num_pins = ARRAY_SIZE(rk805_pins_desc); 439ea479996SJoseph Chen pci->functions = rk805_pin_functions; 440ea479996SJoseph Chen pci->num_functions = ARRAY_SIZE(rk805_pin_functions); 441ea479996SJoseph Chen pci->groups = rk805_pin_groups; 442ea479996SJoseph Chen pci->num_pin_groups = ARRAY_SIZE(rk805_pin_groups); 443ea479996SJoseph Chen pci->pinctrl_desc.pins = rk805_pins_desc; 444ea479996SJoseph Chen pci->pinctrl_desc.npins = ARRAY_SIZE(rk805_pins_desc); 445ea479996SJoseph Chen pci->pin_cfg = rk805_gpio_cfgs; 446ea479996SJoseph Chen pci->gpio_chip.ngpio = ARRAY_SIZE(rk805_gpio_cfgs); 447ea479996SJoseph Chen break; 448ea479996SJoseph Chen default: 449ea479996SJoseph Chen dev_err(&pdev->dev, "unsupported RK805 ID %lu\n", 450ea479996SJoseph Chen pci->rk808->variant); 451ea479996SJoseph Chen return -EINVAL; 452ea479996SJoseph Chen } 453ea479996SJoseph Chen 454ea479996SJoseph Chen /* Add gpio chip */ 455ea479996SJoseph Chen ret = devm_gpiochip_add_data(&pdev->dev, &pci->gpio_chip, pci); 456ea479996SJoseph Chen if (ret < 0) { 457ea479996SJoseph Chen dev_err(&pdev->dev, "Couldn't add gpiochip\n"); 458ea479996SJoseph Chen return ret; 459ea479996SJoseph Chen } 460ea479996SJoseph Chen 461ea479996SJoseph Chen /* Add pinctrl */ 462ea479996SJoseph Chen pci->pctl = devm_pinctrl_register(&pdev->dev, &pci->pinctrl_desc, pci); 463ea479996SJoseph Chen if (IS_ERR(pci->pctl)) { 464ea479996SJoseph Chen dev_err(&pdev->dev, "Couldn't add pinctrl\n"); 465ea479996SJoseph Chen return PTR_ERR(pci->pctl); 466ea479996SJoseph Chen } 467ea479996SJoseph Chen 468ea479996SJoseph Chen /* Add pin range */ 469ea479996SJoseph Chen ret = gpiochip_add_pin_range(&pci->gpio_chip, dev_name(&pdev->dev), 470ea479996SJoseph Chen 0, 0, pci->gpio_chip.ngpio); 471ea479996SJoseph Chen if (ret < 0) { 472ea479996SJoseph Chen dev_err(&pdev->dev, "Couldn't add gpiochip pin range\n"); 473ea479996SJoseph Chen return ret; 474ea479996SJoseph Chen } 475ea479996SJoseph Chen 476ea479996SJoseph Chen return 0; 477ea479996SJoseph Chen } 478ea479996SJoseph Chen 479ea479996SJoseph Chen static struct platform_driver rk805_pinctrl_driver = { 480ea479996SJoseph Chen .probe = rk805_pinctrl_probe, 481ea479996SJoseph Chen .driver = { 482ea479996SJoseph Chen .name = "rk805-pinctrl", 483ea479996SJoseph Chen }, 484ea479996SJoseph Chen }; 485ea479996SJoseph Chen module_platform_driver(rk805_pinctrl_driver); 486ea479996SJoseph Chen 487ea479996SJoseph Chen MODULE_DESCRIPTION("RK805 pin control and GPIO driver"); 488ea479996SJoseph Chen MODULE_AUTHOR("Joseph Chen <chenjh@rock-chips.com>"); 489ea479996SJoseph Chen MODULE_LICENSE("GPL v2"); 490