1d3e51161SHeiko Stübner /* 2d3e51161SHeiko Stübner * Pinctrl driver for Rockchip SoCs 3d3e51161SHeiko Stübner * 4d3e51161SHeiko Stübner * Copyright (c) 2013 MundoReader S.L. 5d3e51161SHeiko Stübner * Author: Heiko Stuebner <heiko@sntech.de> 6d3e51161SHeiko Stübner * 7d3e51161SHeiko Stübner * With some ideas taken from pinctrl-samsung: 8d3e51161SHeiko Stübner * Copyright (c) 2012 Samsung Electronics Co., Ltd. 9d3e51161SHeiko Stübner * http://www.samsung.com 10d3e51161SHeiko Stübner * Copyright (c) 2012 Linaro Ltd 11d3e51161SHeiko Stübner * http://www.linaro.org 12d3e51161SHeiko Stübner * 13d3e51161SHeiko Stübner * and pinctrl-at91: 14d3e51161SHeiko Stübner * Copyright (C) 2011-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> 15d3e51161SHeiko Stübner * 16d3e51161SHeiko Stübner * This program is free software; you can redistribute it and/or modify 17d3e51161SHeiko Stübner * it under the terms of the GNU General Public License version 2 as published 18d3e51161SHeiko Stübner * by the Free Software Foundation. 19d3e51161SHeiko Stübner * 20d3e51161SHeiko Stübner * This program is distributed in the hope that it will be useful, 21d3e51161SHeiko Stübner * but WITHOUT ANY WARRANTY; without even the implied warranty of 22d3e51161SHeiko Stübner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23d3e51161SHeiko Stübner * GNU General Public License for more details. 24d3e51161SHeiko Stübner */ 25d3e51161SHeiko Stübner 26d3e51161SHeiko Stübner #include <linux/module.h> 27d3e51161SHeiko Stübner #include <linux/platform_device.h> 28d3e51161SHeiko Stübner #include <linux/io.h> 29d3e51161SHeiko Stübner #include <linux/bitops.h> 30d3e51161SHeiko Stübner #include <linux/gpio.h> 31d3e51161SHeiko Stübner #include <linux/of_address.h> 32d3e51161SHeiko Stübner #include <linux/of_irq.h> 33d3e51161SHeiko Stübner #include <linux/pinctrl/machine.h> 34d3e51161SHeiko Stübner #include <linux/pinctrl/pinconf.h> 35d3e51161SHeiko Stübner #include <linux/pinctrl/pinctrl.h> 36d3e51161SHeiko Stübner #include <linux/pinctrl/pinmux.h> 37d3e51161SHeiko Stübner #include <linux/pinctrl/pinconf-generic.h> 38d3e51161SHeiko Stübner #include <linux/irqchip/chained_irq.h> 397e865abbSHeiko Stübner #include <linux/clk.h> 40751a99abSHeiko Stübner #include <linux/regmap.h> 4114dee867SHeiko Stübner #include <linux/mfd/syscon.h> 42d3e51161SHeiko Stübner #include <dt-bindings/pinctrl/rockchip.h> 43d3e51161SHeiko Stübner 44d3e51161SHeiko Stübner #include "core.h" 45d3e51161SHeiko Stübner #include "pinconf.h" 46d3e51161SHeiko Stübner 47d3e51161SHeiko Stübner /* GPIO control registers */ 48d3e51161SHeiko Stübner #define GPIO_SWPORT_DR 0x00 49d3e51161SHeiko Stübner #define GPIO_SWPORT_DDR 0x04 50d3e51161SHeiko Stübner #define GPIO_INTEN 0x30 51d3e51161SHeiko Stübner #define GPIO_INTMASK 0x34 52d3e51161SHeiko Stübner #define GPIO_INTTYPE_LEVEL 0x38 53d3e51161SHeiko Stübner #define GPIO_INT_POLARITY 0x3c 54d3e51161SHeiko Stübner #define GPIO_INT_STATUS 0x40 55d3e51161SHeiko Stübner #define GPIO_INT_RAWSTATUS 0x44 56d3e51161SHeiko Stübner #define GPIO_DEBOUNCE 0x48 57d3e51161SHeiko Stübner #define GPIO_PORTS_EOI 0x4c 58d3e51161SHeiko Stübner #define GPIO_EXT_PORT 0x50 59d3e51161SHeiko Stübner #define GPIO_LS_SYNC 0x60 60d3e51161SHeiko Stübner 61a282926dSHeiko Stübner enum rockchip_pinctrl_type { 62a282926dSHeiko Stübner RK2928, 63a282926dSHeiko Stübner RK3066B, 64a282926dSHeiko Stübner RK3188, 6566d750e1SHeiko Stübner RK3288, 66daecdc66SHeiko Stübner RK3368, 67a282926dSHeiko Stübner }; 68a282926dSHeiko Stübner 69fc72c923SHeiko Stübner /** 70fc72c923SHeiko Stübner * Encode variants of iomux registers into a type variable 71fc72c923SHeiko Stübner */ 72fc72c923SHeiko Stübner #define IOMUX_GPIO_ONLY BIT(0) 7303716e1dSHeiko Stübner #define IOMUX_WIDTH_4BIT BIT(1) 7495ec8ae4SHeiko Stübner #define IOMUX_SOURCE_PMU BIT(2) 7562f49226SHeiko Stübner #define IOMUX_UNROUTED BIT(3) 76fc72c923SHeiko Stübner 77fc72c923SHeiko Stübner /** 78fc72c923SHeiko Stübner * @type: iomux variant using IOMUX_* constants 796bc0d121SHeiko Stübner * @offset: if initialized to -1 it will be autocalculated, by specifying 806bc0d121SHeiko Stübner * an initial offset value the relevant source offset can be reset 816bc0d121SHeiko Stübner * to a new value for autocalculating the following iomux registers. 82fc72c923SHeiko Stübner */ 83fc72c923SHeiko Stübner struct rockchip_iomux { 84fc72c923SHeiko Stübner int type; 856bc0d121SHeiko Stübner int offset; 8665fca613SHeiko Stübner }; 8765fca613SHeiko Stübner 88d3e51161SHeiko Stübner /** 89d3e51161SHeiko Stübner * @reg_base: register base of the gpio bank 906ca5274dSHeiko Stübner * @reg_pull: optional separate register for additional pull settings 91d3e51161SHeiko Stübner * @clk: clock of the gpio bank 92d3e51161SHeiko Stübner * @irq: interrupt of the gpio bank 935ae0c7adSDoug Anderson * @saved_masks: Saved content of GPIO_INTEN at suspend time. 94d3e51161SHeiko Stübner * @pin_base: first pin number 95d3e51161SHeiko Stübner * @nr_pins: number of pins in this bank 96d3e51161SHeiko Stübner * @name: name of the bank 97d3e51161SHeiko Stübner * @bank_num: number of the bank, to account for holes 98fc72c923SHeiko Stübner * @iomux: array describing the 4 iomux sources of the bank 99d3e51161SHeiko Stübner * @valid: are all necessary informations present 100d3e51161SHeiko Stübner * @of_node: dt node of this bank 101d3e51161SHeiko Stübner * @drvdata: common pinctrl basedata 102d3e51161SHeiko Stübner * @domain: irqdomain of the gpio bank 103d3e51161SHeiko Stübner * @gpio_chip: gpiolib chip 104d3e51161SHeiko Stübner * @grange: gpio range 105d3e51161SHeiko Stübner * @slock: spinlock for the gpio bank 106d3e51161SHeiko Stübner */ 107d3e51161SHeiko Stübner struct rockchip_pin_bank { 108d3e51161SHeiko Stübner void __iomem *reg_base; 109751a99abSHeiko Stübner struct regmap *regmap_pull; 110d3e51161SHeiko Stübner struct clk *clk; 111d3e51161SHeiko Stübner int irq; 1125ae0c7adSDoug Anderson u32 saved_masks; 113d3e51161SHeiko Stübner u32 pin_base; 114d3e51161SHeiko Stübner u8 nr_pins; 115d3e51161SHeiko Stübner char *name; 116d3e51161SHeiko Stübner u8 bank_num; 117fc72c923SHeiko Stübner struct rockchip_iomux iomux[4]; 118d3e51161SHeiko Stübner bool valid; 119d3e51161SHeiko Stübner struct device_node *of_node; 120d3e51161SHeiko Stübner struct rockchip_pinctrl *drvdata; 121d3e51161SHeiko Stübner struct irq_domain *domain; 122d3e51161SHeiko Stübner struct gpio_chip gpio_chip; 123d3e51161SHeiko Stübner struct pinctrl_gpio_range grange; 124d3e51161SHeiko Stübner spinlock_t slock; 1255a927501SHeiko Stübner u32 toggle_edge_mode; 126d3e51161SHeiko Stübner }; 127d3e51161SHeiko Stübner 128d3e51161SHeiko Stübner #define PIN_BANK(id, pins, label) \ 129d3e51161SHeiko Stübner { \ 130d3e51161SHeiko Stübner .bank_num = id, \ 131d3e51161SHeiko Stübner .nr_pins = pins, \ 132d3e51161SHeiko Stübner .name = label, \ 1336bc0d121SHeiko Stübner .iomux = { \ 1346bc0d121SHeiko Stübner { .offset = -1 }, \ 1356bc0d121SHeiko Stübner { .offset = -1 }, \ 1366bc0d121SHeiko Stübner { .offset = -1 }, \ 1376bc0d121SHeiko Stübner { .offset = -1 }, \ 1386bc0d121SHeiko Stübner }, \ 139d3e51161SHeiko Stübner } 140d3e51161SHeiko Stübner 141fc72c923SHeiko Stübner #define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3) \ 142fc72c923SHeiko Stübner { \ 143fc72c923SHeiko Stübner .bank_num = id, \ 144fc72c923SHeiko Stübner .nr_pins = pins, \ 145fc72c923SHeiko Stübner .name = label, \ 146fc72c923SHeiko Stübner .iomux = { \ 1476bc0d121SHeiko Stübner { .type = iom0, .offset = -1 }, \ 1486bc0d121SHeiko Stübner { .type = iom1, .offset = -1 }, \ 1496bc0d121SHeiko Stübner { .type = iom2, .offset = -1 }, \ 1506bc0d121SHeiko Stübner { .type = iom3, .offset = -1 }, \ 151fc72c923SHeiko Stübner }, \ 152fc72c923SHeiko Stübner } 153fc72c923SHeiko Stübner 154d3e51161SHeiko Stübner /** 155d3e51161SHeiko Stübner */ 156d3e51161SHeiko Stübner struct rockchip_pin_ctrl { 157d3e51161SHeiko Stübner struct rockchip_pin_bank *pin_banks; 158d3e51161SHeiko Stübner u32 nr_banks; 159d3e51161SHeiko Stübner u32 nr_pins; 160d3e51161SHeiko Stübner char *label; 161a282926dSHeiko Stübner enum rockchip_pinctrl_type type; 16295ec8ae4SHeiko Stübner int grf_mux_offset; 16395ec8ae4SHeiko Stübner int pmu_mux_offset; 164751a99abSHeiko Stübner void (*pull_calc_reg)(struct rockchip_pin_bank *bank, 165751a99abSHeiko Stübner int pin_num, struct regmap **regmap, 166751a99abSHeiko Stübner int *reg, u8 *bit); 167ef17f69fSHeiko Stübner void (*drv_calc_reg)(struct rockchip_pin_bank *bank, 168ef17f69fSHeiko Stübner int pin_num, struct regmap **regmap, 169ef17f69fSHeiko Stübner int *reg, u8 *bit); 170d3e51161SHeiko Stübner }; 171d3e51161SHeiko Stübner 172d3e51161SHeiko Stübner struct rockchip_pin_config { 173d3e51161SHeiko Stübner unsigned int func; 174d3e51161SHeiko Stübner unsigned long *configs; 175d3e51161SHeiko Stübner unsigned int nconfigs; 176d3e51161SHeiko Stübner }; 177d3e51161SHeiko Stübner 178d3e51161SHeiko Stübner /** 179d3e51161SHeiko Stübner * struct rockchip_pin_group: represent group of pins of a pinmux function. 180d3e51161SHeiko Stübner * @name: name of the pin group, used to lookup the group. 181d3e51161SHeiko Stübner * @pins: the pins included in this group. 182d3e51161SHeiko Stübner * @npins: number of pins included in this group. 183d3e51161SHeiko Stübner * @func: the mux function number to be programmed when selected. 184d3e51161SHeiko Stübner * @configs: the config values to be set for each pin 185d3e51161SHeiko Stübner * @nconfigs: number of configs for each pin 186d3e51161SHeiko Stübner */ 187d3e51161SHeiko Stübner struct rockchip_pin_group { 188d3e51161SHeiko Stübner const char *name; 189d3e51161SHeiko Stübner unsigned int npins; 190d3e51161SHeiko Stübner unsigned int *pins; 191d3e51161SHeiko Stübner struct rockchip_pin_config *data; 192d3e51161SHeiko Stübner }; 193d3e51161SHeiko Stübner 194d3e51161SHeiko Stübner /** 195d3e51161SHeiko Stübner * struct rockchip_pmx_func: represent a pin function. 196d3e51161SHeiko Stübner * @name: name of the pin function, used to lookup the function. 197d3e51161SHeiko Stübner * @groups: one or more names of pin groups that provide this function. 198d3e51161SHeiko Stübner * @num_groups: number of groups included in @groups. 199d3e51161SHeiko Stübner */ 200d3e51161SHeiko Stübner struct rockchip_pmx_func { 201d3e51161SHeiko Stübner const char *name; 202d3e51161SHeiko Stübner const char **groups; 203d3e51161SHeiko Stübner u8 ngroups; 204d3e51161SHeiko Stübner }; 205d3e51161SHeiko Stübner 206d3e51161SHeiko Stübner struct rockchip_pinctrl { 207751a99abSHeiko Stübner struct regmap *regmap_base; 208bfc7a42aSHeiko Stübner int reg_size; 209751a99abSHeiko Stübner struct regmap *regmap_pull; 21014dee867SHeiko Stübner struct regmap *regmap_pmu; 211d3e51161SHeiko Stübner struct device *dev; 212d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl; 213d3e51161SHeiko Stübner struct pinctrl_desc pctl; 214d3e51161SHeiko Stübner struct pinctrl_dev *pctl_dev; 215d3e51161SHeiko Stübner struct rockchip_pin_group *groups; 216d3e51161SHeiko Stübner unsigned int ngroups; 217d3e51161SHeiko Stübner struct rockchip_pmx_func *functions; 218d3e51161SHeiko Stübner unsigned int nfunctions; 219d3e51161SHeiko Stübner }; 220d3e51161SHeiko Stübner 221751a99abSHeiko Stübner static struct regmap_config rockchip_regmap_config = { 222751a99abSHeiko Stübner .reg_bits = 32, 223751a99abSHeiko Stübner .val_bits = 32, 224751a99abSHeiko Stübner .reg_stride = 4, 225751a99abSHeiko Stübner }; 226751a99abSHeiko Stübner 227d3e51161SHeiko Stübner static inline struct rockchip_pin_bank *gc_to_pin_bank(struct gpio_chip *gc) 228d3e51161SHeiko Stübner { 229d3e51161SHeiko Stübner return container_of(gc, struct rockchip_pin_bank, gpio_chip); 230d3e51161SHeiko Stübner } 231d3e51161SHeiko Stübner 232d3e51161SHeiko Stübner static const inline struct rockchip_pin_group *pinctrl_name_to_group( 233d3e51161SHeiko Stübner const struct rockchip_pinctrl *info, 234d3e51161SHeiko Stübner const char *name) 235d3e51161SHeiko Stübner { 236d3e51161SHeiko Stübner int i; 237d3e51161SHeiko Stübner 238d3e51161SHeiko Stübner for (i = 0; i < info->ngroups; i++) { 2391cb95395SAxel Lin if (!strcmp(info->groups[i].name, name)) 2401cb95395SAxel Lin return &info->groups[i]; 241d3e51161SHeiko Stübner } 242d3e51161SHeiko Stübner 2431cb95395SAxel Lin return NULL; 244d3e51161SHeiko Stübner } 245d3e51161SHeiko Stübner 246d3e51161SHeiko Stübner /* 247d3e51161SHeiko Stübner * given a pin number that is local to a pin controller, find out the pin bank 248d3e51161SHeiko Stübner * and the register base of the pin bank. 249d3e51161SHeiko Stübner */ 250d3e51161SHeiko Stübner static struct rockchip_pin_bank *pin_to_bank(struct rockchip_pinctrl *info, 251d3e51161SHeiko Stübner unsigned pin) 252d3e51161SHeiko Stübner { 253d3e51161SHeiko Stübner struct rockchip_pin_bank *b = info->ctrl->pin_banks; 254d3e51161SHeiko Stübner 25551578b9bSAxel Lin while (pin >= (b->pin_base + b->nr_pins)) 256d3e51161SHeiko Stübner b++; 257d3e51161SHeiko Stübner 258d3e51161SHeiko Stübner return b; 259d3e51161SHeiko Stübner } 260d3e51161SHeiko Stübner 261d3e51161SHeiko Stübner static struct rockchip_pin_bank *bank_num_to_bank( 262d3e51161SHeiko Stübner struct rockchip_pinctrl *info, 263d3e51161SHeiko Stübner unsigned num) 264d3e51161SHeiko Stübner { 265d3e51161SHeiko Stübner struct rockchip_pin_bank *b = info->ctrl->pin_banks; 266d3e51161SHeiko Stübner int i; 267d3e51161SHeiko Stübner 2681cb95395SAxel Lin for (i = 0; i < info->ctrl->nr_banks; i++, b++) { 269d3e51161SHeiko Stübner if (b->bank_num == num) 2701cb95395SAxel Lin return b; 271d3e51161SHeiko Stübner } 272d3e51161SHeiko Stübner 273d3e51161SHeiko Stübner return ERR_PTR(-EINVAL); 274d3e51161SHeiko Stübner } 275d3e51161SHeiko Stübner 276d3e51161SHeiko Stübner /* 277d3e51161SHeiko Stübner * Pinctrl_ops handling 278d3e51161SHeiko Stübner */ 279d3e51161SHeiko Stübner 280d3e51161SHeiko Stübner static int rockchip_get_groups_count(struct pinctrl_dev *pctldev) 281d3e51161SHeiko Stübner { 282d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 283d3e51161SHeiko Stübner 284d3e51161SHeiko Stübner return info->ngroups; 285d3e51161SHeiko Stübner } 286d3e51161SHeiko Stübner 287d3e51161SHeiko Stübner static const char *rockchip_get_group_name(struct pinctrl_dev *pctldev, 288d3e51161SHeiko Stübner unsigned selector) 289d3e51161SHeiko Stübner { 290d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 291d3e51161SHeiko Stübner 292d3e51161SHeiko Stübner return info->groups[selector].name; 293d3e51161SHeiko Stübner } 294d3e51161SHeiko Stübner 295d3e51161SHeiko Stübner static int rockchip_get_group_pins(struct pinctrl_dev *pctldev, 296d3e51161SHeiko Stübner unsigned selector, const unsigned **pins, 297d3e51161SHeiko Stübner unsigned *npins) 298d3e51161SHeiko Stübner { 299d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 300d3e51161SHeiko Stübner 301d3e51161SHeiko Stübner if (selector >= info->ngroups) 302d3e51161SHeiko Stübner return -EINVAL; 303d3e51161SHeiko Stübner 304d3e51161SHeiko Stübner *pins = info->groups[selector].pins; 305d3e51161SHeiko Stübner *npins = info->groups[selector].npins; 306d3e51161SHeiko Stübner 307d3e51161SHeiko Stübner return 0; 308d3e51161SHeiko Stübner } 309d3e51161SHeiko Stübner 310d3e51161SHeiko Stübner static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, 311d3e51161SHeiko Stübner struct device_node *np, 312d3e51161SHeiko Stübner struct pinctrl_map **map, unsigned *num_maps) 313d3e51161SHeiko Stübner { 314d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 315d3e51161SHeiko Stübner const struct rockchip_pin_group *grp; 316d3e51161SHeiko Stübner struct pinctrl_map *new_map; 317d3e51161SHeiko Stübner struct device_node *parent; 318d3e51161SHeiko Stübner int map_num = 1; 319d3e51161SHeiko Stübner int i; 320d3e51161SHeiko Stübner 321d3e51161SHeiko Stübner /* 322d3e51161SHeiko Stübner * first find the group of this node and check if we need to create 323d3e51161SHeiko Stübner * config maps for pins 324d3e51161SHeiko Stübner */ 325d3e51161SHeiko Stübner grp = pinctrl_name_to_group(info, np->name); 326d3e51161SHeiko Stübner if (!grp) { 327d3e51161SHeiko Stübner dev_err(info->dev, "unable to find group for node %s\n", 328d3e51161SHeiko Stübner np->name); 329d3e51161SHeiko Stübner return -EINVAL; 330d3e51161SHeiko Stübner } 331d3e51161SHeiko Stübner 332d3e51161SHeiko Stübner map_num += grp->npins; 333d3e51161SHeiko Stübner new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, 334d3e51161SHeiko Stübner GFP_KERNEL); 335d3e51161SHeiko Stübner if (!new_map) 336d3e51161SHeiko Stübner return -ENOMEM; 337d3e51161SHeiko Stübner 338d3e51161SHeiko Stübner *map = new_map; 339d3e51161SHeiko Stübner *num_maps = map_num; 340d3e51161SHeiko Stübner 341d3e51161SHeiko Stübner /* create mux map */ 342d3e51161SHeiko Stübner parent = of_get_parent(np); 343d3e51161SHeiko Stübner if (!parent) { 344d3e51161SHeiko Stübner devm_kfree(pctldev->dev, new_map); 345d3e51161SHeiko Stübner return -EINVAL; 346d3e51161SHeiko Stübner } 347d3e51161SHeiko Stübner new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; 348d3e51161SHeiko Stübner new_map[0].data.mux.function = parent->name; 349d3e51161SHeiko Stübner new_map[0].data.mux.group = np->name; 350d3e51161SHeiko Stübner of_node_put(parent); 351d3e51161SHeiko Stübner 352d3e51161SHeiko Stübner /* create config map */ 353d3e51161SHeiko Stübner new_map++; 354d3e51161SHeiko Stübner for (i = 0; i < grp->npins; i++) { 355d3e51161SHeiko Stübner new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN; 356d3e51161SHeiko Stübner new_map[i].data.configs.group_or_pin = 357d3e51161SHeiko Stübner pin_get_name(pctldev, grp->pins[i]); 358d3e51161SHeiko Stübner new_map[i].data.configs.configs = grp->data[i].configs; 359d3e51161SHeiko Stübner new_map[i].data.configs.num_configs = grp->data[i].nconfigs; 360d3e51161SHeiko Stübner } 361d3e51161SHeiko Stübner 362d3e51161SHeiko Stübner dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", 363d3e51161SHeiko Stübner (*map)->data.mux.function, (*map)->data.mux.group, map_num); 364d3e51161SHeiko Stübner 365d3e51161SHeiko Stübner return 0; 366d3e51161SHeiko Stübner } 367d3e51161SHeiko Stübner 368d3e51161SHeiko Stübner static void rockchip_dt_free_map(struct pinctrl_dev *pctldev, 369d3e51161SHeiko Stübner struct pinctrl_map *map, unsigned num_maps) 370d3e51161SHeiko Stübner { 371d3e51161SHeiko Stübner } 372d3e51161SHeiko Stübner 373d3e51161SHeiko Stübner static const struct pinctrl_ops rockchip_pctrl_ops = { 374d3e51161SHeiko Stübner .get_groups_count = rockchip_get_groups_count, 375d3e51161SHeiko Stübner .get_group_name = rockchip_get_group_name, 376d3e51161SHeiko Stübner .get_group_pins = rockchip_get_group_pins, 377d3e51161SHeiko Stübner .dt_node_to_map = rockchip_dt_node_to_map, 378d3e51161SHeiko Stübner .dt_free_map = rockchip_dt_free_map, 379d3e51161SHeiko Stübner }; 380d3e51161SHeiko Stübner 381d3e51161SHeiko Stübner /* 382d3e51161SHeiko Stübner * Hardware access 383d3e51161SHeiko Stübner */ 384d3e51161SHeiko Stübner 385a076e2edSHeiko Stübner static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) 386a076e2edSHeiko Stübner { 387a076e2edSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 388fc72c923SHeiko Stübner int iomux_num = (pin / 8); 38995ec8ae4SHeiko Stübner struct regmap *regmap; 390751a99abSHeiko Stübner unsigned int val; 39103716e1dSHeiko Stübner int reg, ret, mask; 392a076e2edSHeiko Stübner u8 bit; 393a076e2edSHeiko Stübner 394fc72c923SHeiko Stübner if (iomux_num > 3) 395fc72c923SHeiko Stübner return -EINVAL; 396fc72c923SHeiko Stübner 39762f49226SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) { 39862f49226SHeiko Stübner dev_err(info->dev, "pin %d is unrouted\n", pin); 39962f49226SHeiko Stübner return -EINVAL; 40062f49226SHeiko Stübner } 40162f49226SHeiko Stübner 402fc72c923SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) 403a076e2edSHeiko Stübner return RK_FUNC_GPIO; 404a076e2edSHeiko Stübner 40595ec8ae4SHeiko Stübner regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) 40695ec8ae4SHeiko Stübner ? info->regmap_pmu : info->regmap_base; 40795ec8ae4SHeiko Stübner 408a076e2edSHeiko Stübner /* get basic quadrupel of mux registers and the correct reg inside */ 40903716e1dSHeiko Stübner mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3; 4106bc0d121SHeiko Stübner reg = bank->iomux[iomux_num].offset; 41103716e1dSHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) { 41203716e1dSHeiko Stübner if ((pin % 8) >= 4) 41303716e1dSHeiko Stübner reg += 0x4; 41403716e1dSHeiko Stübner bit = (pin % 4) * 4; 41503716e1dSHeiko Stübner } else { 416a076e2edSHeiko Stübner bit = (pin % 8) * 2; 41703716e1dSHeiko Stübner } 418a076e2edSHeiko Stübner 41995ec8ae4SHeiko Stübner ret = regmap_read(regmap, reg, &val); 420751a99abSHeiko Stübner if (ret) 421751a99abSHeiko Stübner return ret; 422751a99abSHeiko Stübner 42303716e1dSHeiko Stübner return ((val >> bit) & mask); 424a076e2edSHeiko Stübner } 425a076e2edSHeiko Stübner 426d3e51161SHeiko Stübner /* 427d3e51161SHeiko Stübner * Set a new mux function for a pin. 428d3e51161SHeiko Stübner * 429d3e51161SHeiko Stübner * The register is divided into the upper and lower 16 bit. When changing 430d3e51161SHeiko Stübner * a value, the previous register value is not read and changed. Instead 431d3e51161SHeiko Stübner * it seems the changed bits are marked in the upper 16 bit, while the 432d3e51161SHeiko Stübner * changed value gets set in the same offset in the lower 16 bit. 433d3e51161SHeiko Stübner * All pin settings seem to be 2 bit wide in both the upper and lower 434d3e51161SHeiko Stübner * parts. 435d3e51161SHeiko Stübner * @bank: pin bank to change 436d3e51161SHeiko Stübner * @pin: pin to change 437d3e51161SHeiko Stübner * @mux: new mux function to set 438d3e51161SHeiko Stübner */ 43914797189SHeiko Stübner static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) 440d3e51161SHeiko Stübner { 441d3e51161SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 442fc72c923SHeiko Stübner int iomux_num = (pin / 8); 44395ec8ae4SHeiko Stübner struct regmap *regmap; 44403716e1dSHeiko Stübner int reg, ret, mask; 445d3e51161SHeiko Stübner unsigned long flags; 446d3e51161SHeiko Stübner u8 bit; 44799e872d9SSonny Rao u32 data, rmask; 448d3e51161SHeiko Stübner 449fc72c923SHeiko Stübner if (iomux_num > 3) 450fc72c923SHeiko Stübner return -EINVAL; 451fc72c923SHeiko Stübner 45262f49226SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) { 45362f49226SHeiko Stübner dev_err(info->dev, "pin %d is unrouted\n", pin); 45462f49226SHeiko Stübner return -EINVAL; 45562f49226SHeiko Stübner } 45662f49226SHeiko Stübner 457fc72c923SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) { 458c4a532deSHeiko Stübner if (mux != RK_FUNC_GPIO) { 459c4a532deSHeiko Stübner dev_err(info->dev, 460c4a532deSHeiko Stübner "pin %d only supports a gpio mux\n", pin); 461c4a532deSHeiko Stübner return -ENOTSUPP; 462c4a532deSHeiko Stübner } else { 463c4a532deSHeiko Stübner return 0; 464c4a532deSHeiko Stübner } 465c4a532deSHeiko Stübner } 466c4a532deSHeiko Stübner 467d3e51161SHeiko Stübner dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n", 468d3e51161SHeiko Stübner bank->bank_num, pin, mux); 469d3e51161SHeiko Stübner 47095ec8ae4SHeiko Stübner regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) 47195ec8ae4SHeiko Stübner ? info->regmap_pmu : info->regmap_base; 47295ec8ae4SHeiko Stübner 473d3e51161SHeiko Stübner /* get basic quadrupel of mux registers and the correct reg inside */ 47403716e1dSHeiko Stübner mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3; 4756bc0d121SHeiko Stübner reg = bank->iomux[iomux_num].offset; 47603716e1dSHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) { 47703716e1dSHeiko Stübner if ((pin % 8) >= 4) 47803716e1dSHeiko Stübner reg += 0x4; 47903716e1dSHeiko Stübner bit = (pin % 4) * 4; 48003716e1dSHeiko Stübner } else { 481d3e51161SHeiko Stübner bit = (pin % 8) * 2; 48203716e1dSHeiko Stübner } 483d3e51161SHeiko Stübner 484d3e51161SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 485d3e51161SHeiko Stübner 48603716e1dSHeiko Stübner data = (mask << (bit + 16)); 48799e872d9SSonny Rao rmask = data | (data >> 16); 48803716e1dSHeiko Stübner data |= (mux & mask) << bit; 48999e872d9SSonny Rao ret = regmap_update_bits(regmap, reg, rmask, data); 490d3e51161SHeiko Stübner 491d3e51161SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 49214797189SHeiko Stübner 493751a99abSHeiko Stübner return ret; 494d3e51161SHeiko Stübner } 495d3e51161SHeiko Stübner 496a282926dSHeiko Stübner #define RK2928_PULL_OFFSET 0x118 497a282926dSHeiko Stübner #define RK2928_PULL_PINS_PER_REG 16 498a282926dSHeiko Stübner #define RK2928_PULL_BANK_STRIDE 8 499a282926dSHeiko Stübner 500a282926dSHeiko Stübner static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 501751a99abSHeiko Stübner int pin_num, struct regmap **regmap, 502751a99abSHeiko Stübner int *reg, u8 *bit) 503a282926dSHeiko Stübner { 504a282926dSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 505a282926dSHeiko Stübner 506751a99abSHeiko Stübner *regmap = info->regmap_base; 507751a99abSHeiko Stübner *reg = RK2928_PULL_OFFSET; 508a282926dSHeiko Stübner *reg += bank->bank_num * RK2928_PULL_BANK_STRIDE; 509a282926dSHeiko Stübner *reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4; 510a282926dSHeiko Stübner 511a282926dSHeiko Stübner *bit = pin_num % RK2928_PULL_PINS_PER_REG; 512a282926dSHeiko Stübner }; 513a282926dSHeiko Stübner 514bfc7a42aSHeiko Stübner #define RK3188_PULL_OFFSET 0x164 5156ca5274dSHeiko Stübner #define RK3188_PULL_BITS_PER_PIN 2 5166ca5274dSHeiko Stübner #define RK3188_PULL_PINS_PER_REG 8 5176ca5274dSHeiko Stübner #define RK3188_PULL_BANK_STRIDE 16 51814dee867SHeiko Stübner #define RK3188_PULL_PMU_OFFSET 0x64 5196ca5274dSHeiko Stübner 5206ca5274dSHeiko Stübner static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 521751a99abSHeiko Stübner int pin_num, struct regmap **regmap, 522751a99abSHeiko Stübner int *reg, u8 *bit) 5236ca5274dSHeiko Stübner { 5246ca5274dSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 5256ca5274dSHeiko Stübner 5266ca5274dSHeiko Stübner /* The first 12 pins of the first bank are located elsewhere */ 527fc72c923SHeiko Stübner if (bank->bank_num == 0 && pin_num < 12) { 52814dee867SHeiko Stübner *regmap = info->regmap_pmu ? info->regmap_pmu 52914dee867SHeiko Stübner : bank->regmap_pull; 53014dee867SHeiko Stübner *reg = info->regmap_pmu ? RK3188_PULL_PMU_OFFSET : 0; 531751a99abSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 5326ca5274dSHeiko Stübner *bit = pin_num % RK3188_PULL_PINS_PER_REG; 5336ca5274dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 5346ca5274dSHeiko Stübner } else { 535751a99abSHeiko Stübner *regmap = info->regmap_pull ? info->regmap_pull 536751a99abSHeiko Stübner : info->regmap_base; 537751a99abSHeiko Stübner *reg = info->regmap_pull ? 0 : RK3188_PULL_OFFSET; 538751a99abSHeiko Stübner 539bfc7a42aSHeiko Stübner /* correct the offset, as it is the 2nd pull register */ 540bfc7a42aSHeiko Stübner *reg -= 4; 5416ca5274dSHeiko Stübner *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; 5426ca5274dSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 5436ca5274dSHeiko Stübner 5446ca5274dSHeiko Stübner /* 5456ca5274dSHeiko Stübner * The bits in these registers have an inverse ordering 5466ca5274dSHeiko Stübner * with the lowest pin being in bits 15:14 and the highest 5476ca5274dSHeiko Stübner * pin in bits 1:0 5486ca5274dSHeiko Stübner */ 5496ca5274dSHeiko Stübner *bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG); 5506ca5274dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 5516ca5274dSHeiko Stübner } 5526ca5274dSHeiko Stübner } 5536ca5274dSHeiko Stübner 554304f077dSHeiko Stübner #define RK3288_PULL_OFFSET 0x140 555304f077dSHeiko Stübner static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 556304f077dSHeiko Stübner int pin_num, struct regmap **regmap, 557304f077dSHeiko Stübner int *reg, u8 *bit) 558304f077dSHeiko Stübner { 559304f077dSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 560304f077dSHeiko Stübner 561304f077dSHeiko Stübner /* The first 24 pins of the first bank are located in PMU */ 562304f077dSHeiko Stübner if (bank->bank_num == 0) { 563304f077dSHeiko Stübner *regmap = info->regmap_pmu; 564304f077dSHeiko Stübner *reg = RK3188_PULL_PMU_OFFSET; 565304f077dSHeiko Stübner 566304f077dSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 567304f077dSHeiko Stübner *bit = pin_num % RK3188_PULL_PINS_PER_REG; 568304f077dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 569304f077dSHeiko Stübner } else { 570304f077dSHeiko Stübner *regmap = info->regmap_base; 571304f077dSHeiko Stübner *reg = RK3288_PULL_OFFSET; 572304f077dSHeiko Stübner 573304f077dSHeiko Stübner /* correct the offset, as we're starting with the 2nd bank */ 574304f077dSHeiko Stübner *reg -= 0x10; 575304f077dSHeiko Stübner *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; 576304f077dSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 577304f077dSHeiko Stübner 578304f077dSHeiko Stübner *bit = (pin_num % RK3188_PULL_PINS_PER_REG); 579304f077dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 580304f077dSHeiko Stübner } 581304f077dSHeiko Stübner } 582304f077dSHeiko Stübner 583b547c800SHeiko Stübner #define RK3288_DRV_PMU_OFFSET 0x70 584b547c800SHeiko Stübner #define RK3288_DRV_GRF_OFFSET 0x1c0 585b547c800SHeiko Stübner #define RK3288_DRV_BITS_PER_PIN 2 586b547c800SHeiko Stübner #define RK3288_DRV_PINS_PER_REG 8 587b547c800SHeiko Stübner #define RK3288_DRV_BANK_STRIDE 16 588b547c800SHeiko Stübner 589b547c800SHeiko Stübner static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, 590b547c800SHeiko Stübner int pin_num, struct regmap **regmap, 591b547c800SHeiko Stübner int *reg, u8 *bit) 592b547c800SHeiko Stübner { 593b547c800SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 594b547c800SHeiko Stübner 595b547c800SHeiko Stübner /* The first 24 pins of the first bank are located in PMU */ 596b547c800SHeiko Stübner if (bank->bank_num == 0) { 597b547c800SHeiko Stübner *regmap = info->regmap_pmu; 598b547c800SHeiko Stübner *reg = RK3288_DRV_PMU_OFFSET; 599b547c800SHeiko Stübner 600b547c800SHeiko Stübner *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4); 601b547c800SHeiko Stübner *bit = pin_num % RK3288_DRV_PINS_PER_REG; 602b547c800SHeiko Stübner *bit *= RK3288_DRV_BITS_PER_PIN; 603b547c800SHeiko Stübner } else { 604b547c800SHeiko Stübner *regmap = info->regmap_base; 605b547c800SHeiko Stübner *reg = RK3288_DRV_GRF_OFFSET; 606b547c800SHeiko Stübner 607b547c800SHeiko Stübner /* correct the offset, as we're starting with the 2nd bank */ 608b547c800SHeiko Stübner *reg -= 0x10; 609b547c800SHeiko Stübner *reg += bank->bank_num * RK3288_DRV_BANK_STRIDE; 610b547c800SHeiko Stübner *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4); 611b547c800SHeiko Stübner 612b547c800SHeiko Stübner *bit = (pin_num % RK3288_DRV_PINS_PER_REG); 613b547c800SHeiko Stübner *bit *= RK3288_DRV_BITS_PER_PIN; 614b547c800SHeiko Stübner } 615b547c800SHeiko Stübner } 616b547c800SHeiko Stübner 617daecdc66SHeiko Stübner #define RK3368_PULL_GRF_OFFSET 0x100 618daecdc66SHeiko Stübner #define RK3368_PULL_PMU_OFFSET 0x10 619daecdc66SHeiko Stübner 620daecdc66SHeiko Stübner static void rk3368_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 621daecdc66SHeiko Stübner int pin_num, struct regmap **regmap, 622daecdc66SHeiko Stübner int *reg, u8 *bit) 623daecdc66SHeiko Stübner { 624daecdc66SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 625daecdc66SHeiko Stübner 626daecdc66SHeiko Stübner /* The first 32 pins of the first bank are located in PMU */ 627daecdc66SHeiko Stübner if (bank->bank_num == 0) { 628daecdc66SHeiko Stübner *regmap = info->regmap_pmu; 629daecdc66SHeiko Stübner *reg = RK3368_PULL_PMU_OFFSET; 630daecdc66SHeiko Stübner 631daecdc66SHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 632daecdc66SHeiko Stübner *bit = pin_num % RK3188_PULL_PINS_PER_REG; 633daecdc66SHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 634daecdc66SHeiko Stübner } else { 635daecdc66SHeiko Stübner *regmap = info->regmap_base; 636daecdc66SHeiko Stübner *reg = RK3368_PULL_GRF_OFFSET; 637daecdc66SHeiko Stübner 638daecdc66SHeiko Stübner /* correct the offset, as we're starting with the 2nd bank */ 639daecdc66SHeiko Stübner *reg -= 0x10; 640daecdc66SHeiko Stübner *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; 641daecdc66SHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 642daecdc66SHeiko Stübner 643daecdc66SHeiko Stübner *bit = (pin_num % RK3188_PULL_PINS_PER_REG); 644daecdc66SHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 645daecdc66SHeiko Stübner } 646daecdc66SHeiko Stübner } 647daecdc66SHeiko Stübner 648daecdc66SHeiko Stübner #define RK3368_DRV_PMU_OFFSET 0x20 649daecdc66SHeiko Stübner #define RK3368_DRV_GRF_OFFSET 0x200 650daecdc66SHeiko Stübner 651daecdc66SHeiko Stübner static void rk3368_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, 652daecdc66SHeiko Stübner int pin_num, struct regmap **regmap, 653daecdc66SHeiko Stübner int *reg, u8 *bit) 654daecdc66SHeiko Stübner { 655daecdc66SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 656daecdc66SHeiko Stübner 657daecdc66SHeiko Stübner /* The first 32 pins of the first bank are located in PMU */ 658daecdc66SHeiko Stübner if (bank->bank_num == 0) { 659daecdc66SHeiko Stübner *regmap = info->regmap_pmu; 660daecdc66SHeiko Stübner *reg = RK3368_DRV_PMU_OFFSET; 661daecdc66SHeiko Stübner 662daecdc66SHeiko Stübner *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4); 663daecdc66SHeiko Stübner *bit = pin_num % RK3288_DRV_PINS_PER_REG; 664daecdc66SHeiko Stübner *bit *= RK3288_DRV_BITS_PER_PIN; 665daecdc66SHeiko Stübner } else { 666daecdc66SHeiko Stübner *regmap = info->regmap_base; 667daecdc66SHeiko Stübner *reg = RK3368_DRV_GRF_OFFSET; 668daecdc66SHeiko Stübner 669daecdc66SHeiko Stübner /* correct the offset, as we're starting with the 2nd bank */ 670daecdc66SHeiko Stübner *reg -= 0x10; 671daecdc66SHeiko Stübner *reg += bank->bank_num * RK3288_DRV_BANK_STRIDE; 672daecdc66SHeiko Stübner *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4); 673daecdc66SHeiko Stübner 674daecdc66SHeiko Stübner *bit = (pin_num % RK3288_DRV_PINS_PER_REG); 675daecdc66SHeiko Stübner *bit *= RK3288_DRV_BITS_PER_PIN; 676daecdc66SHeiko Stübner } 677daecdc66SHeiko Stübner } 678daecdc66SHeiko Stübner 679ef17f69fSHeiko Stübner static int rockchip_perpin_drv_list[] = { 2, 4, 8, 12 }; 680ef17f69fSHeiko Stübner 681ef17f69fSHeiko Stübner static int rockchip_get_drive_perpin(struct rockchip_pin_bank *bank, 682ef17f69fSHeiko Stübner int pin_num) 683b547c800SHeiko Stübner { 684ef17f69fSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 685ef17f69fSHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 686b547c800SHeiko Stübner struct regmap *regmap; 687b547c800SHeiko Stübner int reg, ret; 688b547c800SHeiko Stübner u32 data; 689b547c800SHeiko Stübner u8 bit; 690b547c800SHeiko Stübner 691ef17f69fSHeiko Stübner ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); 692b547c800SHeiko Stübner 693b547c800SHeiko Stübner ret = regmap_read(regmap, reg, &data); 694b547c800SHeiko Stübner if (ret) 695b547c800SHeiko Stübner return ret; 696b547c800SHeiko Stübner 697b547c800SHeiko Stübner data >>= bit; 698b547c800SHeiko Stübner data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1; 699b547c800SHeiko Stübner 700ef17f69fSHeiko Stübner return rockchip_perpin_drv_list[data]; 701b547c800SHeiko Stübner } 702b547c800SHeiko Stübner 703ef17f69fSHeiko Stübner static int rockchip_set_drive_perpin(struct rockchip_pin_bank *bank, 704ef17f69fSHeiko Stübner int pin_num, int strength) 705b547c800SHeiko Stübner { 706b547c800SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 707ef17f69fSHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 708b547c800SHeiko Stübner struct regmap *regmap; 709b547c800SHeiko Stübner unsigned long flags; 710b547c800SHeiko Stübner int reg, ret, i; 71199e872d9SSonny Rao u32 data, rmask; 712b547c800SHeiko Stübner u8 bit; 713b547c800SHeiko Stübner 714ef17f69fSHeiko Stübner ctrl->drv_calc_reg(bank, pin_num, ®map, ®, &bit); 715b547c800SHeiko Stübner 716b547c800SHeiko Stübner ret = -EINVAL; 717ef17f69fSHeiko Stübner for (i = 0; i < ARRAY_SIZE(rockchip_perpin_drv_list); i++) { 718ef17f69fSHeiko Stübner if (rockchip_perpin_drv_list[i] == strength) { 719b547c800SHeiko Stübner ret = i; 720b547c800SHeiko Stübner break; 721b547c800SHeiko Stübner } 722b547c800SHeiko Stübner } 723b547c800SHeiko Stübner 724b547c800SHeiko Stübner if (ret < 0) { 725b547c800SHeiko Stübner dev_err(info->dev, "unsupported driver strength %d\n", 726b547c800SHeiko Stübner strength); 727b547c800SHeiko Stübner return ret; 728b547c800SHeiko Stübner } 729b547c800SHeiko Stübner 730b547c800SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 731b547c800SHeiko Stübner 732b547c800SHeiko Stübner /* enable the write to the equivalent lower bits */ 733b547c800SHeiko Stübner data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16); 73499e872d9SSonny Rao rmask = data | (data >> 16); 735b547c800SHeiko Stübner data |= (ret << bit); 736b547c800SHeiko Stübner 73799e872d9SSonny Rao ret = regmap_update_bits(regmap, reg, rmask, data); 738b547c800SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 739b547c800SHeiko Stübner 740b547c800SHeiko Stübner return ret; 741b547c800SHeiko Stübner } 742b547c800SHeiko Stübner 743d3e51161SHeiko Stübner static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) 744d3e51161SHeiko Stübner { 745d3e51161SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 746d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 747751a99abSHeiko Stübner struct regmap *regmap; 748751a99abSHeiko Stübner int reg, ret; 749d3e51161SHeiko Stübner u8 bit; 7506ca5274dSHeiko Stübner u32 data; 751d3e51161SHeiko Stübner 752d3e51161SHeiko Stübner /* rk3066b does support any pulls */ 753a282926dSHeiko Stübner if (ctrl->type == RK3066B) 754d3e51161SHeiko Stübner return PIN_CONFIG_BIAS_DISABLE; 755d3e51161SHeiko Stübner 756751a99abSHeiko Stübner ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); 757751a99abSHeiko Stübner 758751a99abSHeiko Stübner ret = regmap_read(regmap, reg, &data); 759751a99abSHeiko Stübner if (ret) 760751a99abSHeiko Stübner return ret; 7616ca5274dSHeiko Stübner 762a282926dSHeiko Stübner switch (ctrl->type) { 763a282926dSHeiko Stübner case RK2928: 764751a99abSHeiko Stübner return !(data & BIT(bit)) 765d3e51161SHeiko Stübner ? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT 766d3e51161SHeiko Stübner : PIN_CONFIG_BIAS_DISABLE; 767a282926dSHeiko Stübner case RK3188: 76866d750e1SHeiko Stübner case RK3288: 769daecdc66SHeiko Stübner case RK3368: 770751a99abSHeiko Stübner data >>= bit; 7716ca5274dSHeiko Stübner data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1; 7726ca5274dSHeiko Stübner 7736ca5274dSHeiko Stübner switch (data) { 7746ca5274dSHeiko Stübner case 0: 7756ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_DISABLE; 7766ca5274dSHeiko Stübner case 1: 7776ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_PULL_UP; 7786ca5274dSHeiko Stübner case 2: 7796ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_PULL_DOWN; 7806ca5274dSHeiko Stübner case 3: 7816ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_BUS_HOLD; 7826ca5274dSHeiko Stübner } 7836ca5274dSHeiko Stübner 7846ca5274dSHeiko Stübner dev_err(info->dev, "unknown pull setting\n"); 785d3e51161SHeiko Stübner return -EIO; 786a282926dSHeiko Stübner default: 787a282926dSHeiko Stübner dev_err(info->dev, "unsupported pinctrl type\n"); 788a282926dSHeiko Stübner return -EINVAL; 789a282926dSHeiko Stübner }; 790d3e51161SHeiko Stübner } 791d3e51161SHeiko Stübner 792d3e51161SHeiko Stübner static int rockchip_set_pull(struct rockchip_pin_bank *bank, 793d3e51161SHeiko Stübner int pin_num, int pull) 794d3e51161SHeiko Stübner { 795d3e51161SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 796d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 797751a99abSHeiko Stübner struct regmap *regmap; 798751a99abSHeiko Stübner int reg, ret; 799d3e51161SHeiko Stübner unsigned long flags; 800d3e51161SHeiko Stübner u8 bit; 80199e872d9SSonny Rao u32 data, rmask; 802d3e51161SHeiko Stübner 803d3e51161SHeiko Stübner dev_dbg(info->dev, "setting pull of GPIO%d-%d to %d\n", 804d3e51161SHeiko Stübner bank->bank_num, pin_num, pull); 805d3e51161SHeiko Stübner 806d3e51161SHeiko Stübner /* rk3066b does support any pulls */ 807a282926dSHeiko Stübner if (ctrl->type == RK3066B) 808d3e51161SHeiko Stübner return pull ? -EINVAL : 0; 809d3e51161SHeiko Stübner 810751a99abSHeiko Stübner ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); 811d3e51161SHeiko Stübner 8126ca5274dSHeiko Stübner switch (ctrl->type) { 8136ca5274dSHeiko Stübner case RK2928: 814d3e51161SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 815d3e51161SHeiko Stübner 816d3e51161SHeiko Stübner data = BIT(bit + 16); 817d3e51161SHeiko Stübner if (pull == PIN_CONFIG_BIAS_DISABLE) 818d3e51161SHeiko Stübner data |= BIT(bit); 819751a99abSHeiko Stübner ret = regmap_write(regmap, reg, data); 820d3e51161SHeiko Stübner 821d3e51161SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 822a282926dSHeiko Stübner break; 823a282926dSHeiko Stübner case RK3188: 82466d750e1SHeiko Stübner case RK3288: 825daecdc66SHeiko Stübner case RK3368: 8266ca5274dSHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 8276ca5274dSHeiko Stübner 8286ca5274dSHeiko Stübner /* enable the write to the equivalent lower bits */ 8296ca5274dSHeiko Stübner data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16); 83099e872d9SSonny Rao rmask = data | (data >> 16); 8316ca5274dSHeiko Stübner 8326ca5274dSHeiko Stübner switch (pull) { 8336ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_DISABLE: 8346ca5274dSHeiko Stübner break; 8356ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_PULL_UP: 8366ca5274dSHeiko Stübner data |= (1 << bit); 8376ca5274dSHeiko Stübner break; 8386ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_PULL_DOWN: 8396ca5274dSHeiko Stübner data |= (2 << bit); 8406ca5274dSHeiko Stübner break; 8416ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_BUS_HOLD: 8426ca5274dSHeiko Stübner data |= (3 << bit); 8436ca5274dSHeiko Stübner break; 8446ca5274dSHeiko Stübner default: 845d32c3e26SDan Carpenter spin_unlock_irqrestore(&bank->slock, flags); 8466ca5274dSHeiko Stübner dev_err(info->dev, "unsupported pull setting %d\n", 8476ca5274dSHeiko Stübner pull); 8486ca5274dSHeiko Stübner return -EINVAL; 8496ca5274dSHeiko Stübner } 8506ca5274dSHeiko Stübner 85199e872d9SSonny Rao ret = regmap_update_bits(regmap, reg, rmask, data); 8526ca5274dSHeiko Stübner 8536ca5274dSHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 8546ca5274dSHeiko Stübner break; 855a282926dSHeiko Stübner default: 856a282926dSHeiko Stübner dev_err(info->dev, "unsupported pinctrl type\n"); 857a282926dSHeiko Stübner return -EINVAL; 858d3e51161SHeiko Stübner } 859d3e51161SHeiko Stübner 860751a99abSHeiko Stübner return ret; 861d3e51161SHeiko Stübner } 862d3e51161SHeiko Stübner 863d3e51161SHeiko Stübner /* 864d3e51161SHeiko Stübner * Pinmux_ops handling 865d3e51161SHeiko Stübner */ 866d3e51161SHeiko Stübner 867d3e51161SHeiko Stübner static int rockchip_pmx_get_funcs_count(struct pinctrl_dev *pctldev) 868d3e51161SHeiko Stübner { 869d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 870d3e51161SHeiko Stübner 871d3e51161SHeiko Stübner return info->nfunctions; 872d3e51161SHeiko Stübner } 873d3e51161SHeiko Stübner 874d3e51161SHeiko Stübner static const char *rockchip_pmx_get_func_name(struct pinctrl_dev *pctldev, 875d3e51161SHeiko Stübner unsigned selector) 876d3e51161SHeiko Stübner { 877d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 878d3e51161SHeiko Stübner 879d3e51161SHeiko Stübner return info->functions[selector].name; 880d3e51161SHeiko Stübner } 881d3e51161SHeiko Stübner 882d3e51161SHeiko Stübner static int rockchip_pmx_get_groups(struct pinctrl_dev *pctldev, 883d3e51161SHeiko Stübner unsigned selector, const char * const **groups, 884d3e51161SHeiko Stübner unsigned * const num_groups) 885d3e51161SHeiko Stübner { 886d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 887d3e51161SHeiko Stübner 888d3e51161SHeiko Stübner *groups = info->functions[selector].groups; 889d3e51161SHeiko Stübner *num_groups = info->functions[selector].ngroups; 890d3e51161SHeiko Stübner 891d3e51161SHeiko Stübner return 0; 892d3e51161SHeiko Stübner } 893d3e51161SHeiko Stübner 89403e9f0caSLinus Walleij static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, 895d3e51161SHeiko Stübner unsigned group) 896d3e51161SHeiko Stübner { 897d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 898d3e51161SHeiko Stübner const unsigned int *pins = info->groups[group].pins; 899d3e51161SHeiko Stübner const struct rockchip_pin_config *data = info->groups[group].data; 900d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 90114797189SHeiko Stübner int cnt, ret = 0; 902d3e51161SHeiko Stübner 903d3e51161SHeiko Stübner dev_dbg(info->dev, "enable function %s group %s\n", 904d3e51161SHeiko Stübner info->functions[selector].name, info->groups[group].name); 905d3e51161SHeiko Stübner 906d3e51161SHeiko Stübner /* 907d3e51161SHeiko Stübner * for each pin in the pin group selected, program the correspoding pin 908d3e51161SHeiko Stübner * pin function number in the config register. 909d3e51161SHeiko Stübner */ 910d3e51161SHeiko Stübner for (cnt = 0; cnt < info->groups[group].npins; cnt++) { 911d3e51161SHeiko Stübner bank = pin_to_bank(info, pins[cnt]); 91214797189SHeiko Stübner ret = rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 913d3e51161SHeiko Stübner data[cnt].func); 91414797189SHeiko Stübner if (ret) 91514797189SHeiko Stübner break; 91614797189SHeiko Stübner } 91714797189SHeiko Stübner 91814797189SHeiko Stübner if (ret) { 91914797189SHeiko Stübner /* revert the already done pin settings */ 92014797189SHeiko Stübner for (cnt--; cnt >= 0; cnt--) 92114797189SHeiko Stübner rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0); 92214797189SHeiko Stübner 92314797189SHeiko Stübner return ret; 924d3e51161SHeiko Stübner } 925d3e51161SHeiko Stübner 926d3e51161SHeiko Stübner return 0; 927d3e51161SHeiko Stübner } 928d3e51161SHeiko Stübner 929d3e51161SHeiko Stübner /* 930d3e51161SHeiko Stübner * The calls to gpio_direction_output() and gpio_direction_input() 931d3e51161SHeiko Stübner * leads to this function call (via the pinctrl_gpio_direction_{input|output}() 932d3e51161SHeiko Stübner * function called from the gpiolib interface). 933d3e51161SHeiko Stübner */ 934e5c2c9dbSDoug Anderson static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, 935e5c2c9dbSDoug Anderson int pin, bool input) 936d3e51161SHeiko Stübner { 937d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 938e5c2c9dbSDoug Anderson int ret; 939fab262f5SDoug Anderson unsigned long flags; 940d3e51161SHeiko Stübner u32 data; 941d3e51161SHeiko Stübner 942d3e51161SHeiko Stübner bank = gc_to_pin_bank(chip); 943d3e51161SHeiko Stübner 94414797189SHeiko Stübner ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO); 94514797189SHeiko Stübner if (ret < 0) 94614797189SHeiko Stübner return ret; 947d3e51161SHeiko Stübner 948*07a06ae9SLin Huang clk_enable(bank->clk); 949fab262f5SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 950fab262f5SDoug Anderson 951d3e51161SHeiko Stübner data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); 952d3e51161SHeiko Stübner /* set bit to 1 for output, 0 for input */ 953d3e51161SHeiko Stübner if (!input) 954d3e51161SHeiko Stübner data |= BIT(pin); 955d3e51161SHeiko Stübner else 956d3e51161SHeiko Stübner data &= ~BIT(pin); 957d3e51161SHeiko Stübner writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); 958d3e51161SHeiko Stübner 959fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 960*07a06ae9SLin Huang clk_disable(bank->clk); 961fab262f5SDoug Anderson 962d3e51161SHeiko Stübner return 0; 963d3e51161SHeiko Stübner } 964d3e51161SHeiko Stübner 965e5c2c9dbSDoug Anderson static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, 966e5c2c9dbSDoug Anderson struct pinctrl_gpio_range *range, 967e5c2c9dbSDoug Anderson unsigned offset, bool input) 968e5c2c9dbSDoug Anderson { 969e5c2c9dbSDoug Anderson struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 970e5c2c9dbSDoug Anderson struct gpio_chip *chip; 971e5c2c9dbSDoug Anderson int pin; 972e5c2c9dbSDoug Anderson 973e5c2c9dbSDoug Anderson chip = range->gc; 974e5c2c9dbSDoug Anderson pin = offset - chip->base; 975e5c2c9dbSDoug Anderson dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n", 976e5c2c9dbSDoug Anderson offset, range->name, pin, input ? "input" : "output"); 977e5c2c9dbSDoug Anderson 978e5c2c9dbSDoug Anderson return _rockchip_pmx_gpio_set_direction(chip, offset - chip->base, 979e5c2c9dbSDoug Anderson input); 980e5c2c9dbSDoug Anderson } 981e5c2c9dbSDoug Anderson 982d3e51161SHeiko Stübner static const struct pinmux_ops rockchip_pmx_ops = { 983d3e51161SHeiko Stübner .get_functions_count = rockchip_pmx_get_funcs_count, 984d3e51161SHeiko Stübner .get_function_name = rockchip_pmx_get_func_name, 985d3e51161SHeiko Stübner .get_function_groups = rockchip_pmx_get_groups, 98603e9f0caSLinus Walleij .set_mux = rockchip_pmx_set, 987d3e51161SHeiko Stübner .gpio_set_direction = rockchip_pmx_gpio_set_direction, 988d3e51161SHeiko Stübner }; 989d3e51161SHeiko Stübner 990d3e51161SHeiko Stübner /* 991d3e51161SHeiko Stübner * Pinconf_ops handling 992d3e51161SHeiko Stübner */ 993d3e51161SHeiko Stübner 99444b6d930SHeiko Stübner static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, 99544b6d930SHeiko Stübner enum pin_config_param pull) 99644b6d930SHeiko Stübner { 997a282926dSHeiko Stübner switch (ctrl->type) { 998a282926dSHeiko Stübner case RK2928: 999a282926dSHeiko Stübner return (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT || 1000a282926dSHeiko Stübner pull == PIN_CONFIG_BIAS_DISABLE); 1001a282926dSHeiko Stübner case RK3066B: 100244b6d930SHeiko Stübner return pull ? false : true; 1003a282926dSHeiko Stübner case RK3188: 100466d750e1SHeiko Stübner case RK3288: 1005daecdc66SHeiko Stübner case RK3368: 1006a282926dSHeiko Stübner return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT); 100744b6d930SHeiko Stübner } 100844b6d930SHeiko Stübner 1009a282926dSHeiko Stübner return false; 101044b6d930SHeiko Stübner } 101144b6d930SHeiko Stübner 1012e5c2c9dbSDoug Anderson static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value); 1013a076e2edSHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset); 1014a076e2edSHeiko Stübner 1015d3e51161SHeiko Stübner /* set the pin config settings for a specified pin */ 1016d3e51161SHeiko Stübner static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 101703b054e9SSherman Yin unsigned long *configs, unsigned num_configs) 1018d3e51161SHeiko Stübner { 1019d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 1020d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = pin_to_bank(info, pin); 102103b054e9SSherman Yin enum pin_config_param param; 102203b054e9SSherman Yin u16 arg; 102303b054e9SSherman Yin int i; 102403b054e9SSherman Yin int rc; 102503b054e9SSherman Yin 102603b054e9SSherman Yin for (i = 0; i < num_configs; i++) { 102703b054e9SSherman Yin param = pinconf_to_config_param(configs[i]); 102803b054e9SSherman Yin arg = pinconf_to_config_argument(configs[i]); 1029d3e51161SHeiko Stübner 1030d3e51161SHeiko Stübner switch (param) { 1031d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_DISABLE: 103203b054e9SSherman Yin rc = rockchip_set_pull(bank, pin - bank->pin_base, 103303b054e9SSherman Yin param); 103403b054e9SSherman Yin if (rc) 103503b054e9SSherman Yin return rc; 103644b6d930SHeiko Stübner break; 1037d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_PULL_UP: 1038d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_PULL_DOWN: 1039d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 10406ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_BUS_HOLD: 104144b6d930SHeiko Stübner if (!rockchip_pinconf_pull_valid(info->ctrl, param)) 104244b6d930SHeiko Stübner return -ENOTSUPP; 104344b6d930SHeiko Stübner 104444b6d930SHeiko Stübner if (!arg) 104544b6d930SHeiko Stübner return -EINVAL; 104644b6d930SHeiko Stübner 104703b054e9SSherman Yin rc = rockchip_set_pull(bank, pin - bank->pin_base, 104803b054e9SSherman Yin param); 104903b054e9SSherman Yin if (rc) 105003b054e9SSherman Yin return rc; 1051d3e51161SHeiko Stübner break; 1052a076e2edSHeiko Stübner case PIN_CONFIG_OUTPUT: 1053e5c2c9dbSDoug Anderson rockchip_gpio_set(&bank->gpio_chip, 1054e5c2c9dbSDoug Anderson pin - bank->pin_base, arg); 1055e5c2c9dbSDoug Anderson rc = _rockchip_pmx_gpio_set_direction(&bank->gpio_chip, 1056e5c2c9dbSDoug Anderson pin - bank->pin_base, false); 1057a076e2edSHeiko Stübner if (rc) 1058a076e2edSHeiko Stübner return rc; 1059a076e2edSHeiko Stübner break; 1060b547c800SHeiko Stübner case PIN_CONFIG_DRIVE_STRENGTH: 1061b547c800SHeiko Stübner /* rk3288 is the first with per-pin drive-strength */ 1062ef17f69fSHeiko Stübner if (!info->ctrl->drv_calc_reg) 1063b547c800SHeiko Stübner return -ENOTSUPP; 1064b547c800SHeiko Stübner 1065ef17f69fSHeiko Stübner rc = rockchip_set_drive_perpin(bank, 1066ef17f69fSHeiko Stübner pin - bank->pin_base, arg); 1067b547c800SHeiko Stübner if (rc < 0) 1068b547c800SHeiko Stübner return rc; 1069b547c800SHeiko Stübner break; 1070d3e51161SHeiko Stübner default: 1071d3e51161SHeiko Stübner return -ENOTSUPP; 1072d3e51161SHeiko Stübner break; 1073d3e51161SHeiko Stübner } 107403b054e9SSherman Yin } /* for each config */ 1075d3e51161SHeiko Stübner 1076d3e51161SHeiko Stübner return 0; 1077d3e51161SHeiko Stübner } 1078d3e51161SHeiko Stübner 1079d3e51161SHeiko Stübner /* get the pin config settings for a specified pin */ 1080d3e51161SHeiko Stübner static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, 1081d3e51161SHeiko Stübner unsigned long *config) 1082d3e51161SHeiko Stübner { 1083d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 1084d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = pin_to_bank(info, pin); 1085d3e51161SHeiko Stübner enum pin_config_param param = pinconf_to_config_param(*config); 1086dab3eba7SHeiko Stübner u16 arg; 1087a076e2edSHeiko Stübner int rc; 1088d3e51161SHeiko Stübner 1089d3e51161SHeiko Stübner switch (param) { 1090d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_DISABLE: 109144b6d930SHeiko Stübner if (rockchip_get_pull(bank, pin - bank->pin_base) != param) 1092d3e51161SHeiko Stübner return -EINVAL; 1093d3e51161SHeiko Stübner 1094dab3eba7SHeiko Stübner arg = 0; 1095d3e51161SHeiko Stübner break; 109644b6d930SHeiko Stübner case PIN_CONFIG_BIAS_PULL_UP: 109744b6d930SHeiko Stübner case PIN_CONFIG_BIAS_PULL_DOWN: 109844b6d930SHeiko Stübner case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 10996ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_BUS_HOLD: 110044b6d930SHeiko Stübner if (!rockchip_pinconf_pull_valid(info->ctrl, param)) 110144b6d930SHeiko Stübner return -ENOTSUPP; 110244b6d930SHeiko Stübner 110344b6d930SHeiko Stübner if (rockchip_get_pull(bank, pin - bank->pin_base) != param) 110444b6d930SHeiko Stübner return -EINVAL; 110544b6d930SHeiko Stübner 1106dab3eba7SHeiko Stübner arg = 1; 110744b6d930SHeiko Stübner break; 1108a076e2edSHeiko Stübner case PIN_CONFIG_OUTPUT: 1109a076e2edSHeiko Stübner rc = rockchip_get_mux(bank, pin - bank->pin_base); 1110a076e2edSHeiko Stübner if (rc != RK_FUNC_GPIO) 1111a076e2edSHeiko Stübner return -EINVAL; 1112a076e2edSHeiko Stübner 1113a076e2edSHeiko Stübner rc = rockchip_gpio_get(&bank->gpio_chip, pin - bank->pin_base); 1114a076e2edSHeiko Stübner if (rc < 0) 1115a076e2edSHeiko Stübner return rc; 1116a076e2edSHeiko Stübner 1117a076e2edSHeiko Stübner arg = rc ? 1 : 0; 1118a076e2edSHeiko Stübner break; 1119b547c800SHeiko Stübner case PIN_CONFIG_DRIVE_STRENGTH: 1120b547c800SHeiko Stübner /* rk3288 is the first with per-pin drive-strength */ 1121ef17f69fSHeiko Stübner if (!info->ctrl->drv_calc_reg) 1122b547c800SHeiko Stübner return -ENOTSUPP; 1123b547c800SHeiko Stübner 1124ef17f69fSHeiko Stübner rc = rockchip_get_drive_perpin(bank, pin - bank->pin_base); 1125b547c800SHeiko Stübner if (rc < 0) 1126b547c800SHeiko Stübner return rc; 1127b547c800SHeiko Stübner 1128b547c800SHeiko Stübner arg = rc; 1129b547c800SHeiko Stübner break; 1130d3e51161SHeiko Stübner default: 1131d3e51161SHeiko Stübner return -ENOTSUPP; 1132d3e51161SHeiko Stübner break; 1133d3e51161SHeiko Stübner } 1134d3e51161SHeiko Stübner 1135dab3eba7SHeiko Stübner *config = pinconf_to_config_packed(param, arg); 1136dab3eba7SHeiko Stübner 1137d3e51161SHeiko Stübner return 0; 1138d3e51161SHeiko Stübner } 1139d3e51161SHeiko Stübner 1140d3e51161SHeiko Stübner static const struct pinconf_ops rockchip_pinconf_ops = { 1141d3e51161SHeiko Stübner .pin_config_get = rockchip_pinconf_get, 1142d3e51161SHeiko Stübner .pin_config_set = rockchip_pinconf_set, 1143ed62f2f2SHeiko Stübner .is_generic = true, 1144d3e51161SHeiko Stübner }; 1145d3e51161SHeiko Stübner 114665fca613SHeiko Stübner static const struct of_device_id rockchip_bank_match[] = { 114765fca613SHeiko Stübner { .compatible = "rockchip,gpio-bank" }, 11486ca5274dSHeiko Stübner { .compatible = "rockchip,rk3188-gpio-bank0" }, 114965fca613SHeiko Stübner {}, 115065fca613SHeiko Stübner }; 1151d3e51161SHeiko Stübner 1152d3e51161SHeiko Stübner static void rockchip_pinctrl_child_count(struct rockchip_pinctrl *info, 1153d3e51161SHeiko Stübner struct device_node *np) 1154d3e51161SHeiko Stübner { 1155d3e51161SHeiko Stübner struct device_node *child; 1156d3e51161SHeiko Stübner 1157d3e51161SHeiko Stübner for_each_child_of_node(np, child) { 115865fca613SHeiko Stübner if (of_match_node(rockchip_bank_match, child)) 1159d3e51161SHeiko Stübner continue; 1160d3e51161SHeiko Stübner 1161d3e51161SHeiko Stübner info->nfunctions++; 1162d3e51161SHeiko Stübner info->ngroups += of_get_child_count(child); 1163d3e51161SHeiko Stübner } 1164d3e51161SHeiko Stübner } 1165d3e51161SHeiko Stübner 1166d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_groups(struct device_node *np, 1167d3e51161SHeiko Stübner struct rockchip_pin_group *grp, 1168d3e51161SHeiko Stübner struct rockchip_pinctrl *info, 1169d3e51161SHeiko Stübner u32 index) 1170d3e51161SHeiko Stübner { 1171d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 1172d3e51161SHeiko Stübner int size; 1173d3e51161SHeiko Stübner const __be32 *list; 1174d3e51161SHeiko Stübner int num; 1175d3e51161SHeiko Stübner int i, j; 1176d3e51161SHeiko Stübner int ret; 1177d3e51161SHeiko Stübner 1178d3e51161SHeiko Stübner dev_dbg(info->dev, "group(%d): %s\n", index, np->name); 1179d3e51161SHeiko Stübner 1180d3e51161SHeiko Stübner /* Initialise group */ 1181d3e51161SHeiko Stübner grp->name = np->name; 1182d3e51161SHeiko Stübner 1183d3e51161SHeiko Stübner /* 1184d3e51161SHeiko Stübner * the binding format is rockchip,pins = <bank pin mux CONFIG>, 1185d3e51161SHeiko Stübner * do sanity check and calculate pins number 1186d3e51161SHeiko Stübner */ 1187d3e51161SHeiko Stübner list = of_get_property(np, "rockchip,pins", &size); 1188d3e51161SHeiko Stübner /* we do not check return since it's safe node passed down */ 1189d3e51161SHeiko Stübner size /= sizeof(*list); 1190d3e51161SHeiko Stübner if (!size || size % 4) { 1191d3e51161SHeiko Stübner dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n"); 1192d3e51161SHeiko Stübner return -EINVAL; 1193d3e51161SHeiko Stübner } 1194d3e51161SHeiko Stübner 1195d3e51161SHeiko Stübner grp->npins = size / 4; 1196d3e51161SHeiko Stübner 1197d3e51161SHeiko Stübner grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), 1198d3e51161SHeiko Stübner GFP_KERNEL); 1199d3e51161SHeiko Stübner grp->data = devm_kzalloc(info->dev, grp->npins * 1200d3e51161SHeiko Stübner sizeof(struct rockchip_pin_config), 1201d3e51161SHeiko Stübner GFP_KERNEL); 1202d3e51161SHeiko Stübner if (!grp->pins || !grp->data) 1203d3e51161SHeiko Stübner return -ENOMEM; 1204d3e51161SHeiko Stübner 1205d3e51161SHeiko Stübner for (i = 0, j = 0; i < size; i += 4, j++) { 1206d3e51161SHeiko Stübner const __be32 *phandle; 1207d3e51161SHeiko Stübner struct device_node *np_config; 1208d3e51161SHeiko Stübner 1209d3e51161SHeiko Stübner num = be32_to_cpu(*list++); 1210d3e51161SHeiko Stübner bank = bank_num_to_bank(info, num); 1211d3e51161SHeiko Stübner if (IS_ERR(bank)) 1212d3e51161SHeiko Stübner return PTR_ERR(bank); 1213d3e51161SHeiko Stübner 1214d3e51161SHeiko Stübner grp->pins[j] = bank->pin_base + be32_to_cpu(*list++); 1215d3e51161SHeiko Stübner grp->data[j].func = be32_to_cpu(*list++); 1216d3e51161SHeiko Stübner 1217d3e51161SHeiko Stübner phandle = list++; 1218d3e51161SHeiko Stübner if (!phandle) 1219d3e51161SHeiko Stübner return -EINVAL; 1220d3e51161SHeiko Stübner 1221d3e51161SHeiko Stübner np_config = of_find_node_by_phandle(be32_to_cpup(phandle)); 1222dd4d01f7SSoren Brinkmann ret = pinconf_generic_parse_dt_config(np_config, NULL, 1223d3e51161SHeiko Stübner &grp->data[j].configs, &grp->data[j].nconfigs); 1224d3e51161SHeiko Stübner if (ret) 1225d3e51161SHeiko Stübner return ret; 1226d3e51161SHeiko Stübner } 1227d3e51161SHeiko Stübner 1228d3e51161SHeiko Stübner return 0; 1229d3e51161SHeiko Stübner } 1230d3e51161SHeiko Stübner 1231d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_functions(struct device_node *np, 1232d3e51161SHeiko Stübner struct rockchip_pinctrl *info, 1233d3e51161SHeiko Stübner u32 index) 1234d3e51161SHeiko Stübner { 1235d3e51161SHeiko Stübner struct device_node *child; 1236d3e51161SHeiko Stübner struct rockchip_pmx_func *func; 1237d3e51161SHeiko Stübner struct rockchip_pin_group *grp; 1238d3e51161SHeiko Stübner int ret; 1239d3e51161SHeiko Stübner static u32 grp_index; 1240d3e51161SHeiko Stübner u32 i = 0; 1241d3e51161SHeiko Stübner 1242d3e51161SHeiko Stübner dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name); 1243d3e51161SHeiko Stübner 1244d3e51161SHeiko Stübner func = &info->functions[index]; 1245d3e51161SHeiko Stübner 1246d3e51161SHeiko Stübner /* Initialise function */ 1247d3e51161SHeiko Stübner func->name = np->name; 1248d3e51161SHeiko Stübner func->ngroups = of_get_child_count(np); 1249d3e51161SHeiko Stübner if (func->ngroups <= 0) 1250d3e51161SHeiko Stübner return 0; 1251d3e51161SHeiko Stübner 1252d3e51161SHeiko Stübner func->groups = devm_kzalloc(info->dev, 1253d3e51161SHeiko Stübner func->ngroups * sizeof(char *), GFP_KERNEL); 1254d3e51161SHeiko Stübner if (!func->groups) 1255d3e51161SHeiko Stübner return -ENOMEM; 1256d3e51161SHeiko Stübner 1257d3e51161SHeiko Stübner for_each_child_of_node(np, child) { 1258d3e51161SHeiko Stübner func->groups[i] = child->name; 1259d3e51161SHeiko Stübner grp = &info->groups[grp_index++]; 1260d3e51161SHeiko Stübner ret = rockchip_pinctrl_parse_groups(child, grp, info, i++); 1261d3e51161SHeiko Stübner if (ret) 1262d3e51161SHeiko Stübner return ret; 1263d3e51161SHeiko Stübner } 1264d3e51161SHeiko Stübner 1265d3e51161SHeiko Stübner return 0; 1266d3e51161SHeiko Stübner } 1267d3e51161SHeiko Stübner 1268d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_dt(struct platform_device *pdev, 1269d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1270d3e51161SHeiko Stübner { 1271d3e51161SHeiko Stübner struct device *dev = &pdev->dev; 1272d3e51161SHeiko Stübner struct device_node *np = dev->of_node; 1273d3e51161SHeiko Stübner struct device_node *child; 1274d3e51161SHeiko Stübner int ret; 1275d3e51161SHeiko Stübner int i; 1276d3e51161SHeiko Stübner 1277d3e51161SHeiko Stübner rockchip_pinctrl_child_count(info, np); 1278d3e51161SHeiko Stübner 1279d3e51161SHeiko Stübner dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); 1280d3e51161SHeiko Stübner dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); 1281d3e51161SHeiko Stübner 1282d3e51161SHeiko Stübner info->functions = devm_kzalloc(dev, info->nfunctions * 1283d3e51161SHeiko Stübner sizeof(struct rockchip_pmx_func), 1284d3e51161SHeiko Stübner GFP_KERNEL); 1285d3e51161SHeiko Stübner if (!info->functions) { 1286d3e51161SHeiko Stübner dev_err(dev, "failed to allocate memory for function list\n"); 1287d3e51161SHeiko Stübner return -EINVAL; 1288d3e51161SHeiko Stübner } 1289d3e51161SHeiko Stübner 1290d3e51161SHeiko Stübner info->groups = devm_kzalloc(dev, info->ngroups * 1291d3e51161SHeiko Stübner sizeof(struct rockchip_pin_group), 1292d3e51161SHeiko Stübner GFP_KERNEL); 1293d3e51161SHeiko Stübner if (!info->groups) { 1294d3e51161SHeiko Stübner dev_err(dev, "failed allocate memory for ping group list\n"); 1295d3e51161SHeiko Stübner return -EINVAL; 1296d3e51161SHeiko Stübner } 1297d3e51161SHeiko Stübner 1298d3e51161SHeiko Stübner i = 0; 1299d3e51161SHeiko Stübner 1300d3e51161SHeiko Stübner for_each_child_of_node(np, child) { 130165fca613SHeiko Stübner if (of_match_node(rockchip_bank_match, child)) 1302d3e51161SHeiko Stübner continue; 130365fca613SHeiko Stübner 1304d3e51161SHeiko Stübner ret = rockchip_pinctrl_parse_functions(child, info, i++); 1305d3e51161SHeiko Stübner if (ret) { 1306d3e51161SHeiko Stübner dev_err(&pdev->dev, "failed to parse function\n"); 1307d3e51161SHeiko Stübner return ret; 1308d3e51161SHeiko Stübner } 1309d3e51161SHeiko Stübner } 1310d3e51161SHeiko Stübner 1311d3e51161SHeiko Stübner return 0; 1312d3e51161SHeiko Stübner } 1313d3e51161SHeiko Stübner 1314d3e51161SHeiko Stübner static int rockchip_pinctrl_register(struct platform_device *pdev, 1315d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1316d3e51161SHeiko Stübner { 1317d3e51161SHeiko Stübner struct pinctrl_desc *ctrldesc = &info->pctl; 1318d3e51161SHeiko Stübner struct pinctrl_pin_desc *pindesc, *pdesc; 1319d3e51161SHeiko Stübner struct rockchip_pin_bank *pin_bank; 1320d3e51161SHeiko Stübner int pin, bank, ret; 1321d3e51161SHeiko Stübner int k; 1322d3e51161SHeiko Stübner 1323d3e51161SHeiko Stübner ctrldesc->name = "rockchip-pinctrl"; 1324d3e51161SHeiko Stübner ctrldesc->owner = THIS_MODULE; 1325d3e51161SHeiko Stübner ctrldesc->pctlops = &rockchip_pctrl_ops; 1326d3e51161SHeiko Stübner ctrldesc->pmxops = &rockchip_pmx_ops; 1327d3e51161SHeiko Stübner ctrldesc->confops = &rockchip_pinconf_ops; 1328d3e51161SHeiko Stübner 1329d3e51161SHeiko Stübner pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * 1330d3e51161SHeiko Stübner info->ctrl->nr_pins, GFP_KERNEL); 1331d3e51161SHeiko Stübner if (!pindesc) { 1332d3e51161SHeiko Stübner dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n"); 1333d3e51161SHeiko Stübner return -ENOMEM; 1334d3e51161SHeiko Stübner } 1335d3e51161SHeiko Stübner ctrldesc->pins = pindesc; 1336d3e51161SHeiko Stübner ctrldesc->npins = info->ctrl->nr_pins; 1337d3e51161SHeiko Stübner 1338d3e51161SHeiko Stübner pdesc = pindesc; 1339d3e51161SHeiko Stübner for (bank = 0 , k = 0; bank < info->ctrl->nr_banks; bank++) { 1340d3e51161SHeiko Stübner pin_bank = &info->ctrl->pin_banks[bank]; 1341d3e51161SHeiko Stübner for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) { 1342d3e51161SHeiko Stübner pdesc->number = k; 1343d3e51161SHeiko Stübner pdesc->name = kasprintf(GFP_KERNEL, "%s-%d", 1344d3e51161SHeiko Stübner pin_bank->name, pin); 1345d3e51161SHeiko Stübner pdesc++; 1346d3e51161SHeiko Stübner } 1347d3e51161SHeiko Stübner } 1348d3e51161SHeiko Stübner 13490fb7dcb1SDoug Anderson ret = rockchip_pinctrl_parse_dt(pdev, info); 13500fb7dcb1SDoug Anderson if (ret) 13510fb7dcb1SDoug Anderson return ret; 13520fb7dcb1SDoug Anderson 1353d3e51161SHeiko Stübner info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info); 1354323de9efSMasahiro Yamada if (IS_ERR(info->pctl_dev)) { 1355d3e51161SHeiko Stübner dev_err(&pdev->dev, "could not register pinctrl driver\n"); 1356323de9efSMasahiro Yamada return PTR_ERR(info->pctl_dev); 1357d3e51161SHeiko Stübner } 1358d3e51161SHeiko Stübner 1359d3e51161SHeiko Stübner for (bank = 0; bank < info->ctrl->nr_banks; ++bank) { 1360d3e51161SHeiko Stübner pin_bank = &info->ctrl->pin_banks[bank]; 1361d3e51161SHeiko Stübner pin_bank->grange.name = pin_bank->name; 1362d3e51161SHeiko Stübner pin_bank->grange.id = bank; 1363d3e51161SHeiko Stübner pin_bank->grange.pin_base = pin_bank->pin_base; 1364d3e51161SHeiko Stübner pin_bank->grange.base = pin_bank->gpio_chip.base; 1365d3e51161SHeiko Stübner pin_bank->grange.npins = pin_bank->gpio_chip.ngpio; 1366d3e51161SHeiko Stübner pin_bank->grange.gc = &pin_bank->gpio_chip; 1367d3e51161SHeiko Stübner pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange); 1368d3e51161SHeiko Stübner } 1369d3e51161SHeiko Stübner 1370d3e51161SHeiko Stübner return 0; 1371d3e51161SHeiko Stübner } 1372d3e51161SHeiko Stübner 1373d3e51161SHeiko Stübner /* 1374d3e51161SHeiko Stübner * GPIO handling 1375d3e51161SHeiko Stübner */ 1376d3e51161SHeiko Stübner 13770351c287SAxel Lin static int rockchip_gpio_request(struct gpio_chip *chip, unsigned offset) 13780351c287SAxel Lin { 13790351c287SAxel Lin return pinctrl_request_gpio(chip->base + offset); 13800351c287SAxel Lin } 13810351c287SAxel Lin 13820351c287SAxel Lin static void rockchip_gpio_free(struct gpio_chip *chip, unsigned offset) 13830351c287SAxel Lin { 13840351c287SAxel Lin pinctrl_free_gpio(chip->base + offset); 13850351c287SAxel Lin } 13860351c287SAxel Lin 1387d3e51161SHeiko Stübner static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 1388d3e51161SHeiko Stübner { 1389d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); 1390d3e51161SHeiko Stübner void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR; 1391d3e51161SHeiko Stübner unsigned long flags; 1392d3e51161SHeiko Stübner u32 data; 1393d3e51161SHeiko Stübner 1394*07a06ae9SLin Huang clk_enable(bank->clk); 1395d3e51161SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 1396d3e51161SHeiko Stübner 1397d3e51161SHeiko Stübner data = readl(reg); 1398d3e51161SHeiko Stübner data &= ~BIT(offset); 1399d3e51161SHeiko Stübner if (value) 1400d3e51161SHeiko Stübner data |= BIT(offset); 1401d3e51161SHeiko Stübner writel(data, reg); 1402d3e51161SHeiko Stübner 1403d3e51161SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 1404*07a06ae9SLin Huang clk_disable(bank->clk); 1405d3e51161SHeiko Stübner } 1406d3e51161SHeiko Stübner 1407d3e51161SHeiko Stübner /* 1408d3e51161SHeiko Stübner * Returns the level of the pin for input direction and setting of the DR 1409d3e51161SHeiko Stübner * register for output gpios. 1410d3e51161SHeiko Stübner */ 1411d3e51161SHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset) 1412d3e51161SHeiko Stübner { 1413d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); 1414d3e51161SHeiko Stübner u32 data; 1415d3e51161SHeiko Stübner 1416*07a06ae9SLin Huang clk_enable(bank->clk); 1417d3e51161SHeiko Stübner data = readl(bank->reg_base + GPIO_EXT_PORT); 1418*07a06ae9SLin Huang clk_disable(bank->clk); 1419d3e51161SHeiko Stübner data >>= offset; 1420d3e51161SHeiko Stübner data &= 1; 1421d3e51161SHeiko Stübner return data; 1422d3e51161SHeiko Stübner } 1423d3e51161SHeiko Stübner 1424d3e51161SHeiko Stübner /* 1425d3e51161SHeiko Stübner * gpiolib gpio_direction_input callback function. The setting of the pin 1426d3e51161SHeiko Stübner * mux function as 'gpio input' will be handled by the pinctrl susbsystem 1427d3e51161SHeiko Stübner * interface. 1428d3e51161SHeiko Stübner */ 1429d3e51161SHeiko Stübner static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset) 1430d3e51161SHeiko Stübner { 1431d3e51161SHeiko Stübner return pinctrl_gpio_direction_input(gc->base + offset); 1432d3e51161SHeiko Stübner } 1433d3e51161SHeiko Stübner 1434d3e51161SHeiko Stübner /* 1435d3e51161SHeiko Stübner * gpiolib gpio_direction_output callback function. The setting of the pin 1436d3e51161SHeiko Stübner * mux function as 'gpio output' will be handled by the pinctrl susbsystem 1437d3e51161SHeiko Stübner * interface. 1438d3e51161SHeiko Stübner */ 1439d3e51161SHeiko Stübner static int rockchip_gpio_direction_output(struct gpio_chip *gc, 1440d3e51161SHeiko Stübner unsigned offset, int value) 1441d3e51161SHeiko Stübner { 1442d3e51161SHeiko Stübner rockchip_gpio_set(gc, offset, value); 1443d3e51161SHeiko Stübner return pinctrl_gpio_direction_output(gc->base + offset); 1444d3e51161SHeiko Stübner } 1445d3e51161SHeiko Stübner 1446d3e51161SHeiko Stübner /* 1447d3e51161SHeiko Stübner * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin 1448d3e51161SHeiko Stübner * and a virtual IRQ, if not already present. 1449d3e51161SHeiko Stübner */ 1450d3e51161SHeiko Stübner static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 1451d3e51161SHeiko Stübner { 1452d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); 1453d3e51161SHeiko Stübner unsigned int virq; 1454d3e51161SHeiko Stübner 1455d3e51161SHeiko Stübner if (!bank->domain) 1456d3e51161SHeiko Stübner return -ENXIO; 1457d3e51161SHeiko Stübner 1458d3e51161SHeiko Stübner virq = irq_create_mapping(bank->domain, offset); 1459d3e51161SHeiko Stübner 1460d3e51161SHeiko Stübner return (virq) ? : -ENXIO; 1461d3e51161SHeiko Stübner } 1462d3e51161SHeiko Stübner 1463d3e51161SHeiko Stübner static const struct gpio_chip rockchip_gpiolib_chip = { 14640351c287SAxel Lin .request = rockchip_gpio_request, 14650351c287SAxel Lin .free = rockchip_gpio_free, 1466d3e51161SHeiko Stübner .set = rockchip_gpio_set, 1467d3e51161SHeiko Stübner .get = rockchip_gpio_get, 1468d3e51161SHeiko Stübner .direction_input = rockchip_gpio_direction_input, 1469d3e51161SHeiko Stübner .direction_output = rockchip_gpio_direction_output, 1470d3e51161SHeiko Stübner .to_irq = rockchip_gpio_to_irq, 1471d3e51161SHeiko Stübner .owner = THIS_MODULE, 1472d3e51161SHeiko Stübner }; 1473d3e51161SHeiko Stübner 1474d3e51161SHeiko Stübner /* 1475d3e51161SHeiko Stübner * Interrupt handling 1476d3e51161SHeiko Stübner */ 1477d3e51161SHeiko Stübner 1478415f748cSThomas Gleixner static void rockchip_irq_demux(unsigned int __irq, struct irq_desc *desc) 1479d3e51161SHeiko Stübner { 14805663bb27SJiang Liu struct irq_chip *chip = irq_desc_get_chip(desc); 14815663bb27SJiang Liu struct rockchip_pin_bank *bank = irq_desc_get_handler_data(desc); 1482d3e51161SHeiko Stübner u32 pend; 1483d3e51161SHeiko Stübner 1484d3e51161SHeiko Stübner dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); 1485d3e51161SHeiko Stübner 1486d3e51161SHeiko Stübner chained_irq_enter(chip, desc); 1487d3e51161SHeiko Stübner 1488d3e51161SHeiko Stübner pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); 1489d3e51161SHeiko Stübner 1490d3e51161SHeiko Stübner while (pend) { 1491415f748cSThomas Gleixner unsigned int irq, virq; 1492d3e51161SHeiko Stübner 1493d3e51161SHeiko Stübner irq = __ffs(pend); 1494d3e51161SHeiko Stübner pend &= ~BIT(irq); 1495d3e51161SHeiko Stübner virq = irq_linear_revmap(bank->domain, irq); 1496d3e51161SHeiko Stübner 1497d3e51161SHeiko Stübner if (!virq) { 1498d3e51161SHeiko Stübner dev_err(bank->drvdata->dev, "unmapped irq %d\n", irq); 1499d3e51161SHeiko Stübner continue; 1500d3e51161SHeiko Stübner } 1501d3e51161SHeiko Stübner 1502d3e51161SHeiko Stübner dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq); 1503d3e51161SHeiko Stübner 15045a927501SHeiko Stübner /* 15055a927501SHeiko Stübner * Triggering IRQ on both rising and falling edge 15065a927501SHeiko Stübner * needs manual intervention. 15075a927501SHeiko Stübner */ 15085a927501SHeiko Stübner if (bank->toggle_edge_mode & BIT(irq)) { 150953b1bfc7SDoug Anderson u32 data, data_old, polarity; 151053b1bfc7SDoug Anderson unsigned long flags; 151153b1bfc7SDoug Anderson 151253b1bfc7SDoug Anderson data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT); 151353b1bfc7SDoug Anderson do { 151453b1bfc7SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 151553b1bfc7SDoug Anderson 151653b1bfc7SDoug Anderson polarity = readl_relaxed(bank->reg_base + 151753b1bfc7SDoug Anderson GPIO_INT_POLARITY); 15185a927501SHeiko Stübner if (data & BIT(irq)) 15195a927501SHeiko Stübner polarity &= ~BIT(irq); 15205a927501SHeiko Stübner else 15215a927501SHeiko Stübner polarity |= BIT(irq); 152253b1bfc7SDoug Anderson writel(polarity, 152353b1bfc7SDoug Anderson bank->reg_base + GPIO_INT_POLARITY); 15245a927501SHeiko Stübner 152553b1bfc7SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 152653b1bfc7SDoug Anderson 152753b1bfc7SDoug Anderson data_old = data; 152853b1bfc7SDoug Anderson data = readl_relaxed(bank->reg_base + 152953b1bfc7SDoug Anderson GPIO_EXT_PORT); 153053b1bfc7SDoug Anderson } while ((data & BIT(irq)) != (data_old & BIT(irq))); 15315a927501SHeiko Stübner } 15325a927501SHeiko Stübner 1533d3e51161SHeiko Stübner generic_handle_irq(virq); 1534d3e51161SHeiko Stübner } 1535d3e51161SHeiko Stübner 1536d3e51161SHeiko Stübner chained_irq_exit(chip, desc); 1537d3e51161SHeiko Stübner } 1538d3e51161SHeiko Stübner 1539d3e51161SHeiko Stübner static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) 1540d3e51161SHeiko Stübner { 1541d3e51161SHeiko Stübner struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 1542d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc->private; 1543d3e51161SHeiko Stübner u32 mask = BIT(d->hwirq); 1544d3e51161SHeiko Stübner u32 polarity; 1545d3e51161SHeiko Stübner u32 level; 1546d3e51161SHeiko Stübner u32 data; 1547fab262f5SDoug Anderson unsigned long flags; 154814797189SHeiko Stübner int ret; 1549d3e51161SHeiko Stübner 15505a927501SHeiko Stübner /* make sure the pin is configured as gpio input */ 155114797189SHeiko Stübner ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO); 155214797189SHeiko Stübner if (ret < 0) 155314797189SHeiko Stübner return ret; 155414797189SHeiko Stübner 1555*07a06ae9SLin Huang clk_enable(bank->clk); 1556fab262f5SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 1557fab262f5SDoug Anderson 15585a927501SHeiko Stübner data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); 15595a927501SHeiko Stübner data &= ~mask; 15605a927501SHeiko Stübner writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); 15615a927501SHeiko Stübner 1562fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 1563fab262f5SDoug Anderson 1564d3e51161SHeiko Stübner if (type & IRQ_TYPE_EDGE_BOTH) 15652dbf1bc5SThomas Gleixner irq_set_handler_locked(d, handle_edge_irq); 1566d3e51161SHeiko Stübner else 15672dbf1bc5SThomas Gleixner irq_set_handler_locked(d, handle_level_irq); 1568d3e51161SHeiko Stübner 1569fab262f5SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 1570d3e51161SHeiko Stübner irq_gc_lock(gc); 1571d3e51161SHeiko Stübner 1572d3e51161SHeiko Stübner level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); 1573d3e51161SHeiko Stübner polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY); 1574d3e51161SHeiko Stübner 1575d3e51161SHeiko Stübner switch (type) { 15765a927501SHeiko Stübner case IRQ_TYPE_EDGE_BOTH: 15775a927501SHeiko Stübner bank->toggle_edge_mode |= mask; 15785a927501SHeiko Stübner level |= mask; 15795a927501SHeiko Stübner 15805a927501SHeiko Stübner /* 15815a927501SHeiko Stübner * Determine gpio state. If 1 next interrupt should be falling 15825a927501SHeiko Stübner * otherwise rising. 15835a927501SHeiko Stübner */ 15845a927501SHeiko Stübner data = readl(bank->reg_base + GPIO_EXT_PORT); 15855a927501SHeiko Stübner if (data & mask) 15865a927501SHeiko Stübner polarity &= ~mask; 15875a927501SHeiko Stübner else 15885a927501SHeiko Stübner polarity |= mask; 15895a927501SHeiko Stübner break; 1590d3e51161SHeiko Stübner case IRQ_TYPE_EDGE_RISING: 15915a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1592d3e51161SHeiko Stübner level |= mask; 1593d3e51161SHeiko Stübner polarity |= mask; 1594d3e51161SHeiko Stübner break; 1595d3e51161SHeiko Stübner case IRQ_TYPE_EDGE_FALLING: 15965a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1597d3e51161SHeiko Stübner level |= mask; 1598d3e51161SHeiko Stübner polarity &= ~mask; 1599d3e51161SHeiko Stübner break; 1600d3e51161SHeiko Stübner case IRQ_TYPE_LEVEL_HIGH: 16015a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1602d3e51161SHeiko Stübner level &= ~mask; 1603d3e51161SHeiko Stübner polarity |= mask; 1604d3e51161SHeiko Stübner break; 1605d3e51161SHeiko Stübner case IRQ_TYPE_LEVEL_LOW: 16065a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1607d3e51161SHeiko Stübner level &= ~mask; 1608d3e51161SHeiko Stübner polarity &= ~mask; 1609d3e51161SHeiko Stübner break; 1610d3e51161SHeiko Stübner default: 16117cc5f970SAxel Lin irq_gc_unlock(gc); 1612fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 1613*07a06ae9SLin Huang clk_disable(bank->clk); 1614d3e51161SHeiko Stübner return -EINVAL; 1615d3e51161SHeiko Stübner } 1616d3e51161SHeiko Stübner 1617d3e51161SHeiko Stübner writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL); 1618d3e51161SHeiko Stübner writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); 1619d3e51161SHeiko Stübner 1620d3e51161SHeiko Stübner irq_gc_unlock(gc); 1621fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 1622*07a06ae9SLin Huang clk_disable(bank->clk); 1623d3e51161SHeiko Stübner 1624d3e51161SHeiko Stübner return 0; 1625d3e51161SHeiko Stübner } 1626d3e51161SHeiko Stübner 162768bda47cSDoug Anderson static void rockchip_irq_suspend(struct irq_data *d) 162868bda47cSDoug Anderson { 162968bda47cSDoug Anderson struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 163068bda47cSDoug Anderson struct rockchip_pin_bank *bank = gc->private; 163168bda47cSDoug Anderson 1632*07a06ae9SLin Huang clk_enable(bank->clk); 16335ae0c7adSDoug Anderson bank->saved_masks = irq_reg_readl(gc, GPIO_INTMASK); 16345ae0c7adSDoug Anderson irq_reg_writel(gc, ~gc->wake_active, GPIO_INTMASK); 1635*07a06ae9SLin Huang clk_disable(bank->clk); 163668bda47cSDoug Anderson } 163768bda47cSDoug Anderson 163868bda47cSDoug Anderson static void rockchip_irq_resume(struct irq_data *d) 163968bda47cSDoug Anderson { 164068bda47cSDoug Anderson struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 164168bda47cSDoug Anderson struct rockchip_pin_bank *bank = gc->private; 164268bda47cSDoug Anderson 1643*07a06ae9SLin Huang clk_enable(bank->clk); 16445ae0c7adSDoug Anderson irq_reg_writel(gc, bank->saved_masks, GPIO_INTMASK); 1645*07a06ae9SLin Huang clk_disable(bank->clk); 1646*07a06ae9SLin Huang } 1647*07a06ae9SLin Huang 1648*07a06ae9SLin Huang static void rockchip_irq_gc_mask_clr_bit(struct irq_data *d) 1649*07a06ae9SLin Huang { 1650*07a06ae9SLin Huang struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 1651*07a06ae9SLin Huang struct rockchip_pin_bank *bank = gc->private; 1652*07a06ae9SLin Huang 1653*07a06ae9SLin Huang clk_enable(bank->clk); 1654*07a06ae9SLin Huang irq_gc_mask_clr_bit(d); 1655*07a06ae9SLin Huang } 1656*07a06ae9SLin Huang 1657*07a06ae9SLin Huang void rockchip_irq_gc_mask_set_bit(struct irq_data *d) 1658*07a06ae9SLin Huang { 1659*07a06ae9SLin Huang struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 1660*07a06ae9SLin Huang struct rockchip_pin_bank *bank = gc->private; 1661*07a06ae9SLin Huang 1662*07a06ae9SLin Huang irq_gc_mask_set_bit(d); 1663*07a06ae9SLin Huang clk_disable(bank->clk); 1664f2dd028cSDoug Anderson } 1665f2dd028cSDoug Anderson 1666d3e51161SHeiko Stübner static int rockchip_interrupts_register(struct platform_device *pdev, 1667d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1668d3e51161SHeiko Stübner { 1669d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 1670d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = ctrl->pin_banks; 1671d3e51161SHeiko Stübner unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; 1672d3e51161SHeiko Stübner struct irq_chip_generic *gc; 1673d3e51161SHeiko Stübner int ret; 1674*07a06ae9SLin Huang int i, j; 1675d3e51161SHeiko Stübner 1676d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1677d3e51161SHeiko Stübner if (!bank->valid) { 1678d3e51161SHeiko Stübner dev_warn(&pdev->dev, "bank %s is not valid\n", 1679d3e51161SHeiko Stübner bank->name); 1680d3e51161SHeiko Stübner continue; 1681d3e51161SHeiko Stübner } 1682d3e51161SHeiko Stübner 1683*07a06ae9SLin Huang ret = clk_enable(bank->clk); 1684*07a06ae9SLin Huang if (ret) { 1685*07a06ae9SLin Huang dev_err(&pdev->dev, "failed to enable clock for bank %s\n", 1686*07a06ae9SLin Huang bank->name); 1687*07a06ae9SLin Huang continue; 1688*07a06ae9SLin Huang } 1689*07a06ae9SLin Huang 1690d3e51161SHeiko Stübner bank->domain = irq_domain_add_linear(bank->of_node, 32, 1691d3e51161SHeiko Stübner &irq_generic_chip_ops, NULL); 1692d3e51161SHeiko Stübner if (!bank->domain) { 1693d3e51161SHeiko Stübner dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n", 1694d3e51161SHeiko Stübner bank->name); 1695*07a06ae9SLin Huang clk_disable(bank->clk); 1696d3e51161SHeiko Stübner continue; 1697d3e51161SHeiko Stübner } 1698d3e51161SHeiko Stübner 1699d3e51161SHeiko Stübner ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1, 1700d3e51161SHeiko Stübner "rockchip_gpio_irq", handle_level_irq, 1701d3e51161SHeiko Stübner clr, 0, IRQ_GC_INIT_MASK_CACHE); 1702d3e51161SHeiko Stübner if (ret) { 1703d3e51161SHeiko Stübner dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n", 1704d3e51161SHeiko Stübner bank->name); 1705d3e51161SHeiko Stübner irq_domain_remove(bank->domain); 1706*07a06ae9SLin Huang clk_disable(bank->clk); 1707d3e51161SHeiko Stübner continue; 1708d3e51161SHeiko Stübner } 1709d3e51161SHeiko Stübner 17105ae0c7adSDoug Anderson /* 17115ae0c7adSDoug Anderson * Linux assumes that all interrupts start out disabled/masked. 17125ae0c7adSDoug Anderson * Our driver only uses the concept of masked and always keeps 17135ae0c7adSDoug Anderson * things enabled, so for us that's all masked and all enabled. 17145ae0c7adSDoug Anderson */ 17155ae0c7adSDoug Anderson writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTMASK); 17165ae0c7adSDoug Anderson writel_relaxed(0xffffffff, bank->reg_base + GPIO_INTEN); 17175ae0c7adSDoug Anderson 1718d3e51161SHeiko Stübner gc = irq_get_domain_generic_chip(bank->domain, 0); 1719d3e51161SHeiko Stübner gc->reg_base = bank->reg_base; 1720d3e51161SHeiko Stübner gc->private = bank; 1721f2dd028cSDoug Anderson gc->chip_types[0].regs.mask = GPIO_INTMASK; 1722d3e51161SHeiko Stübner gc->chip_types[0].regs.ack = GPIO_PORTS_EOI; 1723d3e51161SHeiko Stübner gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; 1724*07a06ae9SLin Huang gc->chip_types[0].chip.irq_mask = rockchip_irq_gc_mask_set_bit; 1725*07a06ae9SLin Huang gc->chip_types[0].chip.irq_unmask = 1726*07a06ae9SLin Huang rockchip_irq_gc_mask_clr_bit; 1727d3e51161SHeiko Stübner gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake; 172868bda47cSDoug Anderson gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend; 172968bda47cSDoug Anderson gc->chip_types[0].chip.irq_resume = rockchip_irq_resume; 1730d3e51161SHeiko Stübner gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type; 1731876d716bSDoug Anderson gc->wake_enabled = IRQ_MSK(bank->nr_pins); 1732d3e51161SHeiko Stübner 173303051bc2SThomas Gleixner irq_set_chained_handler_and_data(bank->irq, 173403051bc2SThomas Gleixner rockchip_irq_demux, bank); 1735*07a06ae9SLin Huang 1736*07a06ae9SLin Huang /* map the gpio irqs here, when the clock is still running */ 1737*07a06ae9SLin Huang for (j = 0 ; j < 32 ; j++) 1738*07a06ae9SLin Huang irq_create_mapping(bank->domain, j); 1739*07a06ae9SLin Huang 1740*07a06ae9SLin Huang clk_disable(bank->clk); 1741d3e51161SHeiko Stübner } 1742d3e51161SHeiko Stübner 1743d3e51161SHeiko Stübner return 0; 1744d3e51161SHeiko Stübner } 1745d3e51161SHeiko Stübner 1746d3e51161SHeiko Stübner static int rockchip_gpiolib_register(struct platform_device *pdev, 1747d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1748d3e51161SHeiko Stübner { 1749d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 1750d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = ctrl->pin_banks; 1751d3e51161SHeiko Stübner struct gpio_chip *gc; 1752d3e51161SHeiko Stübner int ret; 1753d3e51161SHeiko Stübner int i; 1754d3e51161SHeiko Stübner 1755d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1756d3e51161SHeiko Stübner if (!bank->valid) { 1757d3e51161SHeiko Stübner dev_warn(&pdev->dev, "bank %s is not valid\n", 1758d3e51161SHeiko Stübner bank->name); 1759d3e51161SHeiko Stübner continue; 1760d3e51161SHeiko Stübner } 1761d3e51161SHeiko Stübner 1762d3e51161SHeiko Stübner bank->gpio_chip = rockchip_gpiolib_chip; 1763d3e51161SHeiko Stübner 1764d3e51161SHeiko Stübner gc = &bank->gpio_chip; 1765d3e51161SHeiko Stübner gc->base = bank->pin_base; 1766d3e51161SHeiko Stübner gc->ngpio = bank->nr_pins; 1767d3e51161SHeiko Stübner gc->dev = &pdev->dev; 1768d3e51161SHeiko Stübner gc->of_node = bank->of_node; 1769d3e51161SHeiko Stübner gc->label = bank->name; 1770d3e51161SHeiko Stübner 1771d3e51161SHeiko Stübner ret = gpiochip_add(gc); 1772d3e51161SHeiko Stübner if (ret) { 1773d3e51161SHeiko Stübner dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n", 1774d3e51161SHeiko Stübner gc->label, ret); 1775d3e51161SHeiko Stübner goto fail; 1776d3e51161SHeiko Stübner } 1777d3e51161SHeiko Stübner } 1778d3e51161SHeiko Stübner 1779d3e51161SHeiko Stübner rockchip_interrupts_register(pdev, info); 1780d3e51161SHeiko Stübner 1781d3e51161SHeiko Stübner return 0; 1782d3e51161SHeiko Stübner 1783d3e51161SHeiko Stübner fail: 1784d3e51161SHeiko Stübner for (--i, --bank; i >= 0; --i, --bank) { 1785d3e51161SHeiko Stübner if (!bank->valid) 1786d3e51161SHeiko Stübner continue; 1787b4e7c55dSabdoulaye berthe gpiochip_remove(&bank->gpio_chip); 1788d3e51161SHeiko Stübner } 1789d3e51161SHeiko Stübner return ret; 1790d3e51161SHeiko Stübner } 1791d3e51161SHeiko Stübner 1792d3e51161SHeiko Stübner static int rockchip_gpiolib_unregister(struct platform_device *pdev, 1793d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1794d3e51161SHeiko Stübner { 1795d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 1796d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = ctrl->pin_banks; 1797d3e51161SHeiko Stübner int i; 1798d3e51161SHeiko Stübner 1799b4e7c55dSabdoulaye berthe for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1800d3e51161SHeiko Stübner if (!bank->valid) 1801d3e51161SHeiko Stübner continue; 1802b4e7c55dSabdoulaye berthe gpiochip_remove(&bank->gpio_chip); 1803d3e51161SHeiko Stübner } 1804d3e51161SHeiko Stübner 1805b4e7c55dSabdoulaye berthe return 0; 1806d3e51161SHeiko Stübner } 1807d3e51161SHeiko Stübner 1808d3e51161SHeiko Stübner static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, 1809622f3237SHeiko Stübner struct rockchip_pinctrl *info) 1810d3e51161SHeiko Stübner { 1811d3e51161SHeiko Stübner struct resource res; 1812751a99abSHeiko Stübner void __iomem *base; 1813d3e51161SHeiko Stübner 1814d3e51161SHeiko Stübner if (of_address_to_resource(bank->of_node, 0, &res)) { 1815622f3237SHeiko Stübner dev_err(info->dev, "cannot find IO resource for bank\n"); 1816d3e51161SHeiko Stübner return -ENOENT; 1817d3e51161SHeiko Stübner } 1818d3e51161SHeiko Stübner 1819622f3237SHeiko Stübner bank->reg_base = devm_ioremap_resource(info->dev, &res); 1820d3e51161SHeiko Stübner if (IS_ERR(bank->reg_base)) 1821d3e51161SHeiko Stübner return PTR_ERR(bank->reg_base); 1822d3e51161SHeiko Stübner 18236ca5274dSHeiko Stübner /* 18246ca5274dSHeiko Stübner * special case, where parts of the pull setting-registers are 18256ca5274dSHeiko Stübner * part of the PMU register space 18266ca5274dSHeiko Stübner */ 18276ca5274dSHeiko Stübner if (of_device_is_compatible(bank->of_node, 18286ca5274dSHeiko Stübner "rockchip,rk3188-gpio-bank0")) { 1829a658efaaSHeiko Stübner struct device_node *node; 1830bfc7a42aSHeiko Stübner 1831a658efaaSHeiko Stübner node = of_parse_phandle(bank->of_node->parent, 1832a658efaaSHeiko Stübner "rockchip,pmu", 0); 1833a658efaaSHeiko Stübner if (!node) { 18346ca5274dSHeiko Stübner if (of_address_to_resource(bank->of_node, 1, &res)) { 1835622f3237SHeiko Stübner dev_err(info->dev, "cannot find IO resource for bank\n"); 18366ca5274dSHeiko Stübner return -ENOENT; 18376ca5274dSHeiko Stübner } 18386ca5274dSHeiko Stübner 1839622f3237SHeiko Stübner base = devm_ioremap_resource(info->dev, &res); 1840751a99abSHeiko Stübner if (IS_ERR(base)) 1841751a99abSHeiko Stübner return PTR_ERR(base); 1842a658efaaSHeiko Stübner rockchip_regmap_config.max_register = 1843a658efaaSHeiko Stübner resource_size(&res) - 4; 1844a658efaaSHeiko Stübner rockchip_regmap_config.name = 1845a658efaaSHeiko Stübner "rockchip,rk3188-gpio-bank0-pull"; 1846a658efaaSHeiko Stübner bank->regmap_pull = devm_regmap_init_mmio(info->dev, 1847a658efaaSHeiko Stübner base, 1848751a99abSHeiko Stübner &rockchip_regmap_config); 1849a658efaaSHeiko Stübner } 18506ca5274dSHeiko Stübner } 185165fca613SHeiko Stübner 1852d3e51161SHeiko Stübner bank->irq = irq_of_parse_and_map(bank->of_node, 0); 1853d3e51161SHeiko Stübner 1854d3e51161SHeiko Stübner bank->clk = of_clk_get(bank->of_node, 0); 1855d3e51161SHeiko Stübner if (IS_ERR(bank->clk)) 1856d3e51161SHeiko Stübner return PTR_ERR(bank->clk); 1857d3e51161SHeiko Stübner 1858*07a06ae9SLin Huang return clk_prepare(bank->clk); 1859d3e51161SHeiko Stübner } 1860d3e51161SHeiko Stübner 1861d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[]; 1862d3e51161SHeiko Stübner 1863d3e51161SHeiko Stübner /* retrieve the soc specific data */ 1864d3e51161SHeiko Stübner static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( 1865d3e51161SHeiko Stübner struct rockchip_pinctrl *d, 1866d3e51161SHeiko Stübner struct platform_device *pdev) 1867d3e51161SHeiko Stübner { 1868d3e51161SHeiko Stübner const struct of_device_id *match; 1869d3e51161SHeiko Stübner struct device_node *node = pdev->dev.of_node; 1870d3e51161SHeiko Stübner struct device_node *np; 1871d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl; 1872d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 187395ec8ae4SHeiko Stübner int grf_offs, pmu_offs, i, j; 1874d3e51161SHeiko Stübner 1875d3e51161SHeiko Stübner match = of_match_node(rockchip_pinctrl_dt_match, node); 1876d3e51161SHeiko Stübner ctrl = (struct rockchip_pin_ctrl *)match->data; 1877d3e51161SHeiko Stübner 1878d3e51161SHeiko Stübner for_each_child_of_node(node, np) { 1879d3e51161SHeiko Stübner if (!of_find_property(np, "gpio-controller", NULL)) 1880d3e51161SHeiko Stübner continue; 1881d3e51161SHeiko Stübner 1882d3e51161SHeiko Stübner bank = ctrl->pin_banks; 1883d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1884d3e51161SHeiko Stübner if (!strcmp(bank->name, np->name)) { 1885d3e51161SHeiko Stübner bank->of_node = np; 1886d3e51161SHeiko Stübner 1887622f3237SHeiko Stübner if (!rockchip_get_bank_data(bank, d)) 1888d3e51161SHeiko Stübner bank->valid = true; 1889d3e51161SHeiko Stübner 1890d3e51161SHeiko Stübner break; 1891d3e51161SHeiko Stübner } 1892d3e51161SHeiko Stübner } 1893d3e51161SHeiko Stübner } 1894d3e51161SHeiko Stübner 189595ec8ae4SHeiko Stübner grf_offs = ctrl->grf_mux_offset; 189695ec8ae4SHeiko Stübner pmu_offs = ctrl->pmu_mux_offset; 1897d3e51161SHeiko Stübner bank = ctrl->pin_banks; 1898d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 18996bc0d121SHeiko Stübner int bank_pins = 0; 19006bc0d121SHeiko Stübner 1901d3e51161SHeiko Stübner spin_lock_init(&bank->slock); 1902d3e51161SHeiko Stübner bank->drvdata = d; 1903d3e51161SHeiko Stübner bank->pin_base = ctrl->nr_pins; 1904d3e51161SHeiko Stübner ctrl->nr_pins += bank->nr_pins; 19056bc0d121SHeiko Stübner 19066bc0d121SHeiko Stübner /* calculate iomux offsets */ 19076bc0d121SHeiko Stübner for (j = 0; j < 4; j++) { 19086bc0d121SHeiko Stübner struct rockchip_iomux *iom = &bank->iomux[j]; 190903716e1dSHeiko Stübner int inc; 19106bc0d121SHeiko Stübner 19116bc0d121SHeiko Stübner if (bank_pins >= bank->nr_pins) 19126bc0d121SHeiko Stübner break; 19136bc0d121SHeiko Stübner 19146bc0d121SHeiko Stübner /* preset offset value, set new start value */ 19156bc0d121SHeiko Stübner if (iom->offset >= 0) { 191695ec8ae4SHeiko Stübner if (iom->type & IOMUX_SOURCE_PMU) 191795ec8ae4SHeiko Stübner pmu_offs = iom->offset; 191895ec8ae4SHeiko Stübner else 19196bc0d121SHeiko Stübner grf_offs = iom->offset; 19206bc0d121SHeiko Stübner } else { /* set current offset */ 192195ec8ae4SHeiko Stübner iom->offset = (iom->type & IOMUX_SOURCE_PMU) ? 192295ec8ae4SHeiko Stübner pmu_offs : grf_offs; 19236bc0d121SHeiko Stübner } 19246bc0d121SHeiko Stübner 19256bc0d121SHeiko Stübner dev_dbg(d->dev, "bank %d, iomux %d has offset 0x%x\n", 19266bc0d121SHeiko Stübner i, j, iom->offset); 19276bc0d121SHeiko Stübner 19286bc0d121SHeiko Stübner /* 19296bc0d121SHeiko Stübner * Increase offset according to iomux width. 193003716e1dSHeiko Stübner * 4bit iomux'es are spread over two registers. 19316bc0d121SHeiko Stübner */ 193203716e1dSHeiko Stübner inc = (iom->type & IOMUX_WIDTH_4BIT) ? 8 : 4; 193395ec8ae4SHeiko Stübner if (iom->type & IOMUX_SOURCE_PMU) 193495ec8ae4SHeiko Stübner pmu_offs += inc; 193595ec8ae4SHeiko Stübner else 193603716e1dSHeiko Stübner grf_offs += inc; 19376bc0d121SHeiko Stübner 19386bc0d121SHeiko Stübner bank_pins += 8; 19396bc0d121SHeiko Stübner } 1940d3e51161SHeiko Stübner } 1941d3e51161SHeiko Stübner 1942d3e51161SHeiko Stübner return ctrl; 1943d3e51161SHeiko Stübner } 1944d3e51161SHeiko Stübner 19458dca9331SChris Zhong #define RK3288_GRF_GPIO6C_IOMUX 0x64 19468dca9331SChris Zhong #define GPIO6C6_SEL_WRITE_ENABLE BIT(28) 19478dca9331SChris Zhong 19488dca9331SChris Zhong static u32 rk3288_grf_gpio6c_iomux; 19498dca9331SChris Zhong 19509198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev) 19519198f509SChris Zhong { 19529198f509SChris Zhong struct rockchip_pinctrl *info = dev_get_drvdata(dev); 19538dca9331SChris Zhong int ret = pinctrl_force_sleep(info->pctl_dev); 19549198f509SChris Zhong 19558dca9331SChris Zhong if (ret) 19568dca9331SChris Zhong return ret; 19578dca9331SChris Zhong 19588dca9331SChris Zhong /* 19598dca9331SChris Zhong * RK3288 GPIO6_C6 mux would be modified by Maskrom when resume, so save 19608dca9331SChris Zhong * the setting here, and restore it at resume. 19618dca9331SChris Zhong */ 19628dca9331SChris Zhong if (info->ctrl->type == RK3288) { 19638dca9331SChris Zhong ret = regmap_read(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, 19648dca9331SChris Zhong &rk3288_grf_gpio6c_iomux); 19658dca9331SChris Zhong if (ret) { 19668dca9331SChris Zhong pinctrl_force_default(info->pctl_dev); 19678dca9331SChris Zhong return ret; 19688dca9331SChris Zhong } 19698dca9331SChris Zhong } 19708dca9331SChris Zhong 19718dca9331SChris Zhong return 0; 19729198f509SChris Zhong } 19739198f509SChris Zhong 19749198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_resume(struct device *dev) 19759198f509SChris Zhong { 19769198f509SChris Zhong struct rockchip_pinctrl *info = dev_get_drvdata(dev); 19778dca9331SChris Zhong int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, 19788dca9331SChris Zhong rk3288_grf_gpio6c_iomux | 19798dca9331SChris Zhong GPIO6C6_SEL_WRITE_ENABLE); 19808dca9331SChris Zhong 19818dca9331SChris Zhong if (ret) 19828dca9331SChris Zhong return ret; 19839198f509SChris Zhong 19849198f509SChris Zhong return pinctrl_force_default(info->pctl_dev); 19859198f509SChris Zhong } 19869198f509SChris Zhong 19879198f509SChris Zhong static SIMPLE_DEV_PM_OPS(rockchip_pinctrl_dev_pm_ops, rockchip_pinctrl_suspend, 19889198f509SChris Zhong rockchip_pinctrl_resume); 19899198f509SChris Zhong 1990d3e51161SHeiko Stübner static int rockchip_pinctrl_probe(struct platform_device *pdev) 1991d3e51161SHeiko Stübner { 1992d3e51161SHeiko Stübner struct rockchip_pinctrl *info; 1993d3e51161SHeiko Stübner struct device *dev = &pdev->dev; 1994d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl; 199514dee867SHeiko Stübner struct device_node *np = pdev->dev.of_node, *node; 1996d3e51161SHeiko Stübner struct resource *res; 1997751a99abSHeiko Stübner void __iomem *base; 1998d3e51161SHeiko Stübner int ret; 1999d3e51161SHeiko Stübner 2000d3e51161SHeiko Stübner if (!dev->of_node) { 2001d3e51161SHeiko Stübner dev_err(dev, "device tree node not found\n"); 2002d3e51161SHeiko Stübner return -ENODEV; 2003d3e51161SHeiko Stübner } 2004d3e51161SHeiko Stübner 2005d3e51161SHeiko Stübner info = devm_kzalloc(dev, sizeof(struct rockchip_pinctrl), GFP_KERNEL); 2006d3e51161SHeiko Stübner if (!info) 2007d3e51161SHeiko Stübner return -ENOMEM; 2008d3e51161SHeiko Stübner 2009622f3237SHeiko Stübner info->dev = dev; 2010622f3237SHeiko Stübner 2011d3e51161SHeiko Stübner ctrl = rockchip_pinctrl_get_soc_data(info, pdev); 2012d3e51161SHeiko Stübner if (!ctrl) { 2013d3e51161SHeiko Stübner dev_err(dev, "driver data not available\n"); 2014d3e51161SHeiko Stübner return -EINVAL; 2015d3e51161SHeiko Stübner } 2016d3e51161SHeiko Stübner info->ctrl = ctrl; 2017d3e51161SHeiko Stübner 20181e747e59SHeiko Stübner node = of_parse_phandle(np, "rockchip,grf", 0); 20191e747e59SHeiko Stübner if (node) { 20201e747e59SHeiko Stübner info->regmap_base = syscon_node_to_regmap(node); 20211e747e59SHeiko Stübner if (IS_ERR(info->regmap_base)) 20221e747e59SHeiko Stübner return PTR_ERR(info->regmap_base); 20231e747e59SHeiko Stübner } else { 2024d3e51161SHeiko Stübner res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2025751a99abSHeiko Stübner base = devm_ioremap_resource(&pdev->dev, res); 2026751a99abSHeiko Stübner if (IS_ERR(base)) 2027751a99abSHeiko Stübner return PTR_ERR(base); 2028751a99abSHeiko Stübner 2029751a99abSHeiko Stübner rockchip_regmap_config.max_register = resource_size(res) - 4; 2030751a99abSHeiko Stübner rockchip_regmap_config.name = "rockchip,pinctrl"; 2031751a99abSHeiko Stübner info->regmap_base = devm_regmap_init_mmio(&pdev->dev, base, 2032751a99abSHeiko Stübner &rockchip_regmap_config); 2033d3e51161SHeiko Stübner 2034bfc7a42aSHeiko Stübner /* to check for the old dt-bindings */ 2035bfc7a42aSHeiko Stübner info->reg_size = resource_size(res); 2036bfc7a42aSHeiko Stübner 2037bfc7a42aSHeiko Stübner /* Honor the old binding, with pull registers as 2nd resource */ 2038bfc7a42aSHeiko Stübner if (ctrl->type == RK3188 && info->reg_size < 0x200) { 20396ca5274dSHeiko Stübner res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 2040751a99abSHeiko Stübner base = devm_ioremap_resource(&pdev->dev, res); 2041751a99abSHeiko Stübner if (IS_ERR(base)) 2042751a99abSHeiko Stübner return PTR_ERR(base); 2043751a99abSHeiko Stübner 20441e747e59SHeiko Stübner rockchip_regmap_config.max_register = 20451e747e59SHeiko Stübner resource_size(res) - 4; 2046751a99abSHeiko Stübner rockchip_regmap_config.name = "rockchip,pinctrl-pull"; 20471e747e59SHeiko Stübner info->regmap_pull = devm_regmap_init_mmio(&pdev->dev, 20481e747e59SHeiko Stübner base, 2049751a99abSHeiko Stübner &rockchip_regmap_config); 20506ca5274dSHeiko Stübner } 20511e747e59SHeiko Stübner } 20526ca5274dSHeiko Stübner 205314dee867SHeiko Stübner /* try to find the optional reference to the pmu syscon */ 205414dee867SHeiko Stübner node = of_parse_phandle(np, "rockchip,pmu", 0); 205514dee867SHeiko Stübner if (node) { 205614dee867SHeiko Stübner info->regmap_pmu = syscon_node_to_regmap(node); 205714dee867SHeiko Stübner if (IS_ERR(info->regmap_pmu)) 205814dee867SHeiko Stübner return PTR_ERR(info->regmap_pmu); 205914dee867SHeiko Stübner } 206014dee867SHeiko Stübner 2061d3e51161SHeiko Stübner ret = rockchip_gpiolib_register(pdev, info); 2062d3e51161SHeiko Stübner if (ret) 2063d3e51161SHeiko Stübner return ret; 2064d3e51161SHeiko Stübner 2065d3e51161SHeiko Stübner ret = rockchip_pinctrl_register(pdev, info); 2066d3e51161SHeiko Stübner if (ret) { 2067d3e51161SHeiko Stübner rockchip_gpiolib_unregister(pdev, info); 2068d3e51161SHeiko Stübner return ret; 2069d3e51161SHeiko Stübner } 2070d3e51161SHeiko Stübner 2071d3e51161SHeiko Stübner platform_set_drvdata(pdev, info); 2072d3e51161SHeiko Stübner 2073d3e51161SHeiko Stübner return 0; 2074d3e51161SHeiko Stübner } 2075d3e51161SHeiko Stübner 2076d3e51161SHeiko Stübner static struct rockchip_pin_bank rk2928_pin_banks[] = { 2077d3e51161SHeiko Stübner PIN_BANK(0, 32, "gpio0"), 2078d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 2079d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 2080d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 2081d3e51161SHeiko Stübner }; 2082d3e51161SHeiko Stübner 2083d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk2928_pin_ctrl = { 2084d3e51161SHeiko Stübner .pin_banks = rk2928_pin_banks, 2085d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk2928_pin_banks), 2086d3e51161SHeiko Stübner .label = "RK2928-GPIO", 2087a282926dSHeiko Stübner .type = RK2928, 208895ec8ae4SHeiko Stübner .grf_mux_offset = 0xa8, 2089a282926dSHeiko Stübner .pull_calc_reg = rk2928_calc_pull_reg_and_bit, 2090d3e51161SHeiko Stübner }; 2091d3e51161SHeiko Stübner 2092d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066a_pin_banks[] = { 2093d3e51161SHeiko Stübner PIN_BANK(0, 32, "gpio0"), 2094d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 2095d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 2096d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 2097d3e51161SHeiko Stübner PIN_BANK(4, 32, "gpio4"), 2098d3e51161SHeiko Stübner PIN_BANK(6, 16, "gpio6"), 2099d3e51161SHeiko Stübner }; 2100d3e51161SHeiko Stübner 2101d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066a_pin_ctrl = { 2102d3e51161SHeiko Stübner .pin_banks = rk3066a_pin_banks, 2103d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk3066a_pin_banks), 2104d3e51161SHeiko Stübner .label = "RK3066a-GPIO", 2105a282926dSHeiko Stübner .type = RK2928, 210695ec8ae4SHeiko Stübner .grf_mux_offset = 0xa8, 2107a282926dSHeiko Stübner .pull_calc_reg = rk2928_calc_pull_reg_and_bit, 2108d3e51161SHeiko Stübner }; 2109d3e51161SHeiko Stübner 2110d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066b_pin_banks[] = { 2111d3e51161SHeiko Stübner PIN_BANK(0, 32, "gpio0"), 2112d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 2113d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 2114d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 2115d3e51161SHeiko Stübner }; 2116d3e51161SHeiko Stübner 2117d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066b_pin_ctrl = { 2118d3e51161SHeiko Stübner .pin_banks = rk3066b_pin_banks, 2119d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk3066b_pin_banks), 2120d3e51161SHeiko Stübner .label = "RK3066b-GPIO", 2121a282926dSHeiko Stübner .type = RK3066B, 212295ec8ae4SHeiko Stübner .grf_mux_offset = 0x60, 2123d3e51161SHeiko Stübner }; 2124d3e51161SHeiko Stübner 2125d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3188_pin_banks[] = { 2126fc72c923SHeiko Stübner PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0), 2127d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 2128d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 2129d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 2130d3e51161SHeiko Stübner }; 2131d3e51161SHeiko Stübner 2132d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3188_pin_ctrl = { 2133d3e51161SHeiko Stübner .pin_banks = rk3188_pin_banks, 2134d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk3188_pin_banks), 2135d3e51161SHeiko Stübner .label = "RK3188-GPIO", 2136a282926dSHeiko Stübner .type = RK3188, 213795ec8ae4SHeiko Stübner .grf_mux_offset = 0x60, 21386ca5274dSHeiko Stübner .pull_calc_reg = rk3188_calc_pull_reg_and_bit, 2139d3e51161SHeiko Stübner }; 2140d3e51161SHeiko Stübner 2141304f077dSHeiko Stübner static struct rockchip_pin_bank rk3288_pin_banks[] = { 2142304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU, 2143304f077dSHeiko Stübner IOMUX_SOURCE_PMU, 2144304f077dSHeiko Stübner IOMUX_SOURCE_PMU, 2145304f077dSHeiko Stübner IOMUX_UNROUTED 2146304f077dSHeiko Stübner ), 2147304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED, 2148304f077dSHeiko Stübner IOMUX_UNROUTED, 2149304f077dSHeiko Stübner IOMUX_UNROUTED, 2150304f077dSHeiko Stübner 0 2151304f077dSHeiko Stübner ), 2152304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED), 2153304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT), 2154304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT, 2155304f077dSHeiko Stübner IOMUX_WIDTH_4BIT, 2156304f077dSHeiko Stübner 0, 2157304f077dSHeiko Stübner 0 2158304f077dSHeiko Stübner ), 2159304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED, 2160304f077dSHeiko Stübner 0, 2161304f077dSHeiko Stübner 0, 2162304f077dSHeiko Stübner IOMUX_UNROUTED 2163304f077dSHeiko Stübner ), 2164304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED), 2165304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0, 2166304f077dSHeiko Stübner 0, 2167304f077dSHeiko Stübner IOMUX_WIDTH_4BIT, 2168304f077dSHeiko Stübner IOMUX_UNROUTED 2169304f077dSHeiko Stübner ), 2170304f077dSHeiko Stübner PIN_BANK(8, 16, "gpio8"), 2171304f077dSHeiko Stübner }; 2172304f077dSHeiko Stübner 2173304f077dSHeiko Stübner static struct rockchip_pin_ctrl rk3288_pin_ctrl = { 2174304f077dSHeiko Stübner .pin_banks = rk3288_pin_banks, 2175304f077dSHeiko Stübner .nr_banks = ARRAY_SIZE(rk3288_pin_banks), 2176304f077dSHeiko Stübner .label = "RK3288-GPIO", 217766d750e1SHeiko Stübner .type = RK3288, 2178304f077dSHeiko Stübner .grf_mux_offset = 0x0, 2179304f077dSHeiko Stübner .pmu_mux_offset = 0x84, 2180304f077dSHeiko Stübner .pull_calc_reg = rk3288_calc_pull_reg_and_bit, 2181ef17f69fSHeiko Stübner .drv_calc_reg = rk3288_calc_drv_reg_and_bit, 2182304f077dSHeiko Stübner }; 2183304f077dSHeiko Stübner 2184daecdc66SHeiko Stübner static struct rockchip_pin_bank rk3368_pin_banks[] = { 2185daecdc66SHeiko Stübner PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU, 2186daecdc66SHeiko Stübner IOMUX_SOURCE_PMU, 2187daecdc66SHeiko Stübner IOMUX_SOURCE_PMU, 2188daecdc66SHeiko Stübner IOMUX_SOURCE_PMU 2189daecdc66SHeiko Stübner ), 2190daecdc66SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 2191daecdc66SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 2192daecdc66SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 2193daecdc66SHeiko Stübner }; 2194daecdc66SHeiko Stübner 2195daecdc66SHeiko Stübner static struct rockchip_pin_ctrl rk3368_pin_ctrl = { 2196daecdc66SHeiko Stübner .pin_banks = rk3368_pin_banks, 2197daecdc66SHeiko Stübner .nr_banks = ARRAY_SIZE(rk3368_pin_banks), 2198daecdc66SHeiko Stübner .label = "RK3368-GPIO", 2199daecdc66SHeiko Stübner .type = RK3368, 2200daecdc66SHeiko Stübner .grf_mux_offset = 0x0, 2201daecdc66SHeiko Stübner .pmu_mux_offset = 0x0, 2202daecdc66SHeiko Stübner .pull_calc_reg = rk3368_calc_pull_reg_and_bit, 2203daecdc66SHeiko Stübner .drv_calc_reg = rk3368_calc_drv_reg_and_bit, 2204daecdc66SHeiko Stübner }; 2205daecdc66SHeiko Stübner 2206daecdc66SHeiko Stübner 2207d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[] = { 2208d3e51161SHeiko Stübner { .compatible = "rockchip,rk2928-pinctrl", 2209d3e51161SHeiko Stübner .data = (void *)&rk2928_pin_ctrl }, 2210d3e51161SHeiko Stübner { .compatible = "rockchip,rk3066a-pinctrl", 2211d3e51161SHeiko Stübner .data = (void *)&rk3066a_pin_ctrl }, 2212d3e51161SHeiko Stübner { .compatible = "rockchip,rk3066b-pinctrl", 2213d3e51161SHeiko Stübner .data = (void *)&rk3066b_pin_ctrl }, 2214d3e51161SHeiko Stübner { .compatible = "rockchip,rk3188-pinctrl", 2215d3e51161SHeiko Stübner .data = (void *)&rk3188_pin_ctrl }, 2216304f077dSHeiko Stübner { .compatible = "rockchip,rk3288-pinctrl", 2217304f077dSHeiko Stübner .data = (void *)&rk3288_pin_ctrl }, 2218daecdc66SHeiko Stübner { .compatible = "rockchip,rk3368-pinctrl", 2219daecdc66SHeiko Stübner .data = (void *)&rk3368_pin_ctrl }, 2220d3e51161SHeiko Stübner {}, 2221d3e51161SHeiko Stübner }; 2222d3e51161SHeiko Stübner MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match); 2223d3e51161SHeiko Stübner 2224d3e51161SHeiko Stübner static struct platform_driver rockchip_pinctrl_driver = { 2225d3e51161SHeiko Stübner .probe = rockchip_pinctrl_probe, 2226d3e51161SHeiko Stübner .driver = { 2227d3e51161SHeiko Stübner .name = "rockchip-pinctrl", 22289198f509SChris Zhong .pm = &rockchip_pinctrl_dev_pm_ops, 22290be9e70dSAxel Lin .of_match_table = rockchip_pinctrl_dt_match, 2230d3e51161SHeiko Stübner }, 2231d3e51161SHeiko Stübner }; 2232d3e51161SHeiko Stübner 2233d3e51161SHeiko Stübner static int __init rockchip_pinctrl_drv_register(void) 2234d3e51161SHeiko Stübner { 2235d3e51161SHeiko Stübner return platform_driver_register(&rockchip_pinctrl_driver); 2236d3e51161SHeiko Stübner } 2237d3e51161SHeiko Stübner postcore_initcall(rockchip_pinctrl_drv_register); 2238d3e51161SHeiko Stübner 2239d3e51161SHeiko Stübner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 2240d3e51161SHeiko Stübner MODULE_DESCRIPTION("Rockchip pinctrl driver"); 2241d3e51161SHeiko Stübner MODULE_LICENSE("GPL v2"); 2242