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, 66a282926dSHeiko Stübner }; 67a282926dSHeiko Stübner 68fc72c923SHeiko Stübner /** 69fc72c923SHeiko Stübner * Encode variants of iomux registers into a type variable 70fc72c923SHeiko Stübner */ 71fc72c923SHeiko Stübner #define IOMUX_GPIO_ONLY BIT(0) 7203716e1dSHeiko Stübner #define IOMUX_WIDTH_4BIT BIT(1) 7395ec8ae4SHeiko Stübner #define IOMUX_SOURCE_PMU BIT(2) 7462f49226SHeiko Stübner #define IOMUX_UNROUTED BIT(3) 75fc72c923SHeiko Stübner 76fc72c923SHeiko Stübner /** 77fc72c923SHeiko Stübner * @type: iomux variant using IOMUX_* constants 786bc0d121SHeiko Stübner * @offset: if initialized to -1 it will be autocalculated, by specifying 796bc0d121SHeiko Stübner * an initial offset value the relevant source offset can be reset 806bc0d121SHeiko Stübner * to a new value for autocalculating the following iomux registers. 81fc72c923SHeiko Stübner */ 82fc72c923SHeiko Stübner struct rockchip_iomux { 83fc72c923SHeiko Stübner int type; 846bc0d121SHeiko Stübner int offset; 8565fca613SHeiko Stübner }; 8665fca613SHeiko Stübner 87d3e51161SHeiko Stübner /** 88d3e51161SHeiko Stübner * @reg_base: register base of the gpio bank 896ca5274dSHeiko Stübner * @reg_pull: optional separate register for additional pull settings 90d3e51161SHeiko Stübner * @clk: clock of the gpio bank 91d3e51161SHeiko Stübner * @irq: interrupt of the gpio bank 9268bda47cSDoug Anderson * @saved_enables: Saved content of GPIO_INTEN at suspend time. 93d3e51161SHeiko Stübner * @pin_base: first pin number 94d3e51161SHeiko Stübner * @nr_pins: number of pins in this bank 95d3e51161SHeiko Stübner * @name: name of the bank 96d3e51161SHeiko Stübner * @bank_num: number of the bank, to account for holes 97fc72c923SHeiko Stübner * @iomux: array describing the 4 iomux sources of the bank 98d3e51161SHeiko Stübner * @valid: are all necessary informations present 99d3e51161SHeiko Stübner * @of_node: dt node of this bank 100d3e51161SHeiko Stübner * @drvdata: common pinctrl basedata 101d3e51161SHeiko Stübner * @domain: irqdomain of the gpio bank 102d3e51161SHeiko Stübner * @gpio_chip: gpiolib chip 103d3e51161SHeiko Stübner * @grange: gpio range 104d3e51161SHeiko Stübner * @slock: spinlock for the gpio bank 105d3e51161SHeiko Stübner */ 106d3e51161SHeiko Stübner struct rockchip_pin_bank { 107d3e51161SHeiko Stübner void __iomem *reg_base; 108751a99abSHeiko Stübner struct regmap *regmap_pull; 109d3e51161SHeiko Stübner struct clk *clk; 110d3e51161SHeiko Stübner int irq; 11168bda47cSDoug Anderson u32 saved_enables; 112d3e51161SHeiko Stübner u32 pin_base; 113d3e51161SHeiko Stübner u8 nr_pins; 114d3e51161SHeiko Stübner char *name; 115d3e51161SHeiko Stübner u8 bank_num; 116fc72c923SHeiko Stübner struct rockchip_iomux iomux[4]; 117d3e51161SHeiko Stübner bool valid; 118d3e51161SHeiko Stübner struct device_node *of_node; 119d3e51161SHeiko Stübner struct rockchip_pinctrl *drvdata; 120d3e51161SHeiko Stübner struct irq_domain *domain; 121d3e51161SHeiko Stübner struct gpio_chip gpio_chip; 122d3e51161SHeiko Stübner struct pinctrl_gpio_range grange; 123d3e51161SHeiko Stübner spinlock_t slock; 1245a927501SHeiko Stübner u32 toggle_edge_mode; 125d3e51161SHeiko Stübner }; 126d3e51161SHeiko Stübner 127d3e51161SHeiko Stübner #define PIN_BANK(id, pins, label) \ 128d3e51161SHeiko Stübner { \ 129d3e51161SHeiko Stübner .bank_num = id, \ 130d3e51161SHeiko Stübner .nr_pins = pins, \ 131d3e51161SHeiko Stübner .name = label, \ 1326bc0d121SHeiko Stübner .iomux = { \ 1336bc0d121SHeiko Stübner { .offset = -1 }, \ 1346bc0d121SHeiko Stübner { .offset = -1 }, \ 1356bc0d121SHeiko Stübner { .offset = -1 }, \ 1366bc0d121SHeiko Stübner { .offset = -1 }, \ 1376bc0d121SHeiko Stübner }, \ 138d3e51161SHeiko Stübner } 139d3e51161SHeiko Stübner 140fc72c923SHeiko Stübner #define PIN_BANK_IOMUX_FLAGS(id, pins, label, iom0, iom1, iom2, iom3) \ 141fc72c923SHeiko Stübner { \ 142fc72c923SHeiko Stübner .bank_num = id, \ 143fc72c923SHeiko Stübner .nr_pins = pins, \ 144fc72c923SHeiko Stübner .name = label, \ 145fc72c923SHeiko Stübner .iomux = { \ 1466bc0d121SHeiko Stübner { .type = iom0, .offset = -1 }, \ 1476bc0d121SHeiko Stübner { .type = iom1, .offset = -1 }, \ 1486bc0d121SHeiko Stübner { .type = iom2, .offset = -1 }, \ 1496bc0d121SHeiko Stübner { .type = iom3, .offset = -1 }, \ 150fc72c923SHeiko Stübner }, \ 151fc72c923SHeiko Stübner } 152fc72c923SHeiko Stübner 153d3e51161SHeiko Stübner /** 154d3e51161SHeiko Stübner */ 155d3e51161SHeiko Stübner struct rockchip_pin_ctrl { 156d3e51161SHeiko Stübner struct rockchip_pin_bank *pin_banks; 157d3e51161SHeiko Stübner u32 nr_banks; 158d3e51161SHeiko Stübner u32 nr_pins; 159d3e51161SHeiko Stübner char *label; 160a282926dSHeiko Stübner enum rockchip_pinctrl_type type; 16195ec8ae4SHeiko Stübner int grf_mux_offset; 16295ec8ae4SHeiko Stübner int pmu_mux_offset; 163751a99abSHeiko Stübner void (*pull_calc_reg)(struct rockchip_pin_bank *bank, 164751a99abSHeiko Stübner int pin_num, struct regmap **regmap, 165751a99abSHeiko Stübner int *reg, u8 *bit); 166d3e51161SHeiko Stübner }; 167d3e51161SHeiko Stübner 168d3e51161SHeiko Stübner struct rockchip_pin_config { 169d3e51161SHeiko Stübner unsigned int func; 170d3e51161SHeiko Stübner unsigned long *configs; 171d3e51161SHeiko Stübner unsigned int nconfigs; 172d3e51161SHeiko Stübner }; 173d3e51161SHeiko Stübner 174d3e51161SHeiko Stübner /** 175d3e51161SHeiko Stübner * struct rockchip_pin_group: represent group of pins of a pinmux function. 176d3e51161SHeiko Stübner * @name: name of the pin group, used to lookup the group. 177d3e51161SHeiko Stübner * @pins: the pins included in this group. 178d3e51161SHeiko Stübner * @npins: number of pins included in this group. 179d3e51161SHeiko Stübner * @func: the mux function number to be programmed when selected. 180d3e51161SHeiko Stübner * @configs: the config values to be set for each pin 181d3e51161SHeiko Stübner * @nconfigs: number of configs for each pin 182d3e51161SHeiko Stübner */ 183d3e51161SHeiko Stübner struct rockchip_pin_group { 184d3e51161SHeiko Stübner const char *name; 185d3e51161SHeiko Stübner unsigned int npins; 186d3e51161SHeiko Stübner unsigned int *pins; 187d3e51161SHeiko Stübner struct rockchip_pin_config *data; 188d3e51161SHeiko Stübner }; 189d3e51161SHeiko Stübner 190d3e51161SHeiko Stübner /** 191d3e51161SHeiko Stübner * struct rockchip_pmx_func: represent a pin function. 192d3e51161SHeiko Stübner * @name: name of the pin function, used to lookup the function. 193d3e51161SHeiko Stübner * @groups: one or more names of pin groups that provide this function. 194d3e51161SHeiko Stübner * @num_groups: number of groups included in @groups. 195d3e51161SHeiko Stübner */ 196d3e51161SHeiko Stübner struct rockchip_pmx_func { 197d3e51161SHeiko Stübner const char *name; 198d3e51161SHeiko Stübner const char **groups; 199d3e51161SHeiko Stübner u8 ngroups; 200d3e51161SHeiko Stübner }; 201d3e51161SHeiko Stübner 202d3e51161SHeiko Stübner struct rockchip_pinctrl { 203751a99abSHeiko Stübner struct regmap *regmap_base; 204bfc7a42aSHeiko Stübner int reg_size; 205751a99abSHeiko Stübner struct regmap *regmap_pull; 20614dee867SHeiko Stübner struct regmap *regmap_pmu; 207d3e51161SHeiko Stübner struct device *dev; 208d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl; 209d3e51161SHeiko Stübner struct pinctrl_desc pctl; 210d3e51161SHeiko Stübner struct pinctrl_dev *pctl_dev; 211d3e51161SHeiko Stübner struct rockchip_pin_group *groups; 212d3e51161SHeiko Stübner unsigned int ngroups; 213d3e51161SHeiko Stübner struct rockchip_pmx_func *functions; 214d3e51161SHeiko Stübner unsigned int nfunctions; 215d3e51161SHeiko Stübner }; 216d3e51161SHeiko Stübner 217751a99abSHeiko Stübner static struct regmap_config rockchip_regmap_config = { 218751a99abSHeiko Stübner .reg_bits = 32, 219751a99abSHeiko Stübner .val_bits = 32, 220751a99abSHeiko Stübner .reg_stride = 4, 221751a99abSHeiko Stübner }; 222751a99abSHeiko Stübner 223d3e51161SHeiko Stübner static inline struct rockchip_pin_bank *gc_to_pin_bank(struct gpio_chip *gc) 224d3e51161SHeiko Stübner { 225d3e51161SHeiko Stübner return container_of(gc, struct rockchip_pin_bank, gpio_chip); 226d3e51161SHeiko Stübner } 227d3e51161SHeiko Stübner 228d3e51161SHeiko Stübner static const inline struct rockchip_pin_group *pinctrl_name_to_group( 229d3e51161SHeiko Stübner const struct rockchip_pinctrl *info, 230d3e51161SHeiko Stübner const char *name) 231d3e51161SHeiko Stübner { 232d3e51161SHeiko Stübner int i; 233d3e51161SHeiko Stübner 234d3e51161SHeiko Stübner for (i = 0; i < info->ngroups; i++) { 2351cb95395SAxel Lin if (!strcmp(info->groups[i].name, name)) 2361cb95395SAxel Lin return &info->groups[i]; 237d3e51161SHeiko Stübner } 238d3e51161SHeiko Stübner 2391cb95395SAxel Lin return NULL; 240d3e51161SHeiko Stübner } 241d3e51161SHeiko Stübner 242d3e51161SHeiko Stübner /* 243d3e51161SHeiko Stübner * given a pin number that is local to a pin controller, find out the pin bank 244d3e51161SHeiko Stübner * and the register base of the pin bank. 245d3e51161SHeiko Stübner */ 246d3e51161SHeiko Stübner static struct rockchip_pin_bank *pin_to_bank(struct rockchip_pinctrl *info, 247d3e51161SHeiko Stübner unsigned pin) 248d3e51161SHeiko Stübner { 249d3e51161SHeiko Stübner struct rockchip_pin_bank *b = info->ctrl->pin_banks; 250d3e51161SHeiko Stübner 25151578b9bSAxel Lin while (pin >= (b->pin_base + b->nr_pins)) 252d3e51161SHeiko Stübner b++; 253d3e51161SHeiko Stübner 254d3e51161SHeiko Stübner return b; 255d3e51161SHeiko Stübner } 256d3e51161SHeiko Stübner 257d3e51161SHeiko Stübner static struct rockchip_pin_bank *bank_num_to_bank( 258d3e51161SHeiko Stübner struct rockchip_pinctrl *info, 259d3e51161SHeiko Stübner unsigned num) 260d3e51161SHeiko Stübner { 261d3e51161SHeiko Stübner struct rockchip_pin_bank *b = info->ctrl->pin_banks; 262d3e51161SHeiko Stübner int i; 263d3e51161SHeiko Stübner 2641cb95395SAxel Lin for (i = 0; i < info->ctrl->nr_banks; i++, b++) { 265d3e51161SHeiko Stübner if (b->bank_num == num) 2661cb95395SAxel Lin return b; 267d3e51161SHeiko Stübner } 268d3e51161SHeiko Stübner 269d3e51161SHeiko Stübner return ERR_PTR(-EINVAL); 270d3e51161SHeiko Stübner } 271d3e51161SHeiko Stübner 272d3e51161SHeiko Stübner /* 273d3e51161SHeiko Stübner * Pinctrl_ops handling 274d3e51161SHeiko Stübner */ 275d3e51161SHeiko Stübner 276d3e51161SHeiko Stübner static int rockchip_get_groups_count(struct pinctrl_dev *pctldev) 277d3e51161SHeiko Stübner { 278d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 279d3e51161SHeiko Stübner 280d3e51161SHeiko Stübner return info->ngroups; 281d3e51161SHeiko Stübner } 282d3e51161SHeiko Stübner 283d3e51161SHeiko Stübner static const char *rockchip_get_group_name(struct pinctrl_dev *pctldev, 284d3e51161SHeiko Stübner unsigned selector) 285d3e51161SHeiko Stübner { 286d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 287d3e51161SHeiko Stübner 288d3e51161SHeiko Stübner return info->groups[selector].name; 289d3e51161SHeiko Stübner } 290d3e51161SHeiko Stübner 291d3e51161SHeiko Stübner static int rockchip_get_group_pins(struct pinctrl_dev *pctldev, 292d3e51161SHeiko Stübner unsigned selector, const unsigned **pins, 293d3e51161SHeiko Stübner unsigned *npins) 294d3e51161SHeiko Stübner { 295d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 296d3e51161SHeiko Stübner 297d3e51161SHeiko Stübner if (selector >= info->ngroups) 298d3e51161SHeiko Stübner return -EINVAL; 299d3e51161SHeiko Stübner 300d3e51161SHeiko Stübner *pins = info->groups[selector].pins; 301d3e51161SHeiko Stübner *npins = info->groups[selector].npins; 302d3e51161SHeiko Stübner 303d3e51161SHeiko Stübner return 0; 304d3e51161SHeiko Stübner } 305d3e51161SHeiko Stübner 306d3e51161SHeiko Stübner static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev, 307d3e51161SHeiko Stübner struct device_node *np, 308d3e51161SHeiko Stübner struct pinctrl_map **map, unsigned *num_maps) 309d3e51161SHeiko Stübner { 310d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 311d3e51161SHeiko Stübner const struct rockchip_pin_group *grp; 312d3e51161SHeiko Stübner struct pinctrl_map *new_map; 313d3e51161SHeiko Stübner struct device_node *parent; 314d3e51161SHeiko Stübner int map_num = 1; 315d3e51161SHeiko Stübner int i; 316d3e51161SHeiko Stübner 317d3e51161SHeiko Stübner /* 318d3e51161SHeiko Stübner * first find the group of this node and check if we need to create 319d3e51161SHeiko Stübner * config maps for pins 320d3e51161SHeiko Stübner */ 321d3e51161SHeiko Stübner grp = pinctrl_name_to_group(info, np->name); 322d3e51161SHeiko Stübner if (!grp) { 323d3e51161SHeiko Stübner dev_err(info->dev, "unable to find group for node %s\n", 324d3e51161SHeiko Stübner np->name); 325d3e51161SHeiko Stübner return -EINVAL; 326d3e51161SHeiko Stübner } 327d3e51161SHeiko Stübner 328d3e51161SHeiko Stübner map_num += grp->npins; 329d3e51161SHeiko Stübner new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, 330d3e51161SHeiko Stübner GFP_KERNEL); 331d3e51161SHeiko Stübner if (!new_map) 332d3e51161SHeiko Stübner return -ENOMEM; 333d3e51161SHeiko Stübner 334d3e51161SHeiko Stübner *map = new_map; 335d3e51161SHeiko Stübner *num_maps = map_num; 336d3e51161SHeiko Stübner 337d3e51161SHeiko Stübner /* create mux map */ 338d3e51161SHeiko Stübner parent = of_get_parent(np); 339d3e51161SHeiko Stübner if (!parent) { 340d3e51161SHeiko Stübner devm_kfree(pctldev->dev, new_map); 341d3e51161SHeiko Stübner return -EINVAL; 342d3e51161SHeiko Stübner } 343d3e51161SHeiko Stübner new_map[0].type = PIN_MAP_TYPE_MUX_GROUP; 344d3e51161SHeiko Stübner new_map[0].data.mux.function = parent->name; 345d3e51161SHeiko Stübner new_map[0].data.mux.group = np->name; 346d3e51161SHeiko Stübner of_node_put(parent); 347d3e51161SHeiko Stübner 348d3e51161SHeiko Stübner /* create config map */ 349d3e51161SHeiko Stübner new_map++; 350d3e51161SHeiko Stübner for (i = 0; i < grp->npins; i++) { 351d3e51161SHeiko Stübner new_map[i].type = PIN_MAP_TYPE_CONFIGS_PIN; 352d3e51161SHeiko Stübner new_map[i].data.configs.group_or_pin = 353d3e51161SHeiko Stübner pin_get_name(pctldev, grp->pins[i]); 354d3e51161SHeiko Stübner new_map[i].data.configs.configs = grp->data[i].configs; 355d3e51161SHeiko Stübner new_map[i].data.configs.num_configs = grp->data[i].nconfigs; 356d3e51161SHeiko Stübner } 357d3e51161SHeiko Stübner 358d3e51161SHeiko Stübner dev_dbg(pctldev->dev, "maps: function %s group %s num %d\n", 359d3e51161SHeiko Stübner (*map)->data.mux.function, (*map)->data.mux.group, map_num); 360d3e51161SHeiko Stübner 361d3e51161SHeiko Stübner return 0; 362d3e51161SHeiko Stübner } 363d3e51161SHeiko Stübner 364d3e51161SHeiko Stübner static void rockchip_dt_free_map(struct pinctrl_dev *pctldev, 365d3e51161SHeiko Stübner struct pinctrl_map *map, unsigned num_maps) 366d3e51161SHeiko Stübner { 367d3e51161SHeiko Stübner } 368d3e51161SHeiko Stübner 369d3e51161SHeiko Stübner static const struct pinctrl_ops rockchip_pctrl_ops = { 370d3e51161SHeiko Stübner .get_groups_count = rockchip_get_groups_count, 371d3e51161SHeiko Stübner .get_group_name = rockchip_get_group_name, 372d3e51161SHeiko Stübner .get_group_pins = rockchip_get_group_pins, 373d3e51161SHeiko Stübner .dt_node_to_map = rockchip_dt_node_to_map, 374d3e51161SHeiko Stübner .dt_free_map = rockchip_dt_free_map, 375d3e51161SHeiko Stübner }; 376d3e51161SHeiko Stübner 377d3e51161SHeiko Stübner /* 378d3e51161SHeiko Stübner * Hardware access 379d3e51161SHeiko Stübner */ 380d3e51161SHeiko Stübner 381a076e2edSHeiko Stübner static int rockchip_get_mux(struct rockchip_pin_bank *bank, int pin) 382a076e2edSHeiko Stübner { 383a076e2edSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 384fc72c923SHeiko Stübner int iomux_num = (pin / 8); 38595ec8ae4SHeiko Stübner struct regmap *regmap; 386751a99abSHeiko Stübner unsigned int val; 38703716e1dSHeiko Stübner int reg, ret, mask; 388a076e2edSHeiko Stübner u8 bit; 389a076e2edSHeiko Stübner 390fc72c923SHeiko Stübner if (iomux_num > 3) 391fc72c923SHeiko Stübner return -EINVAL; 392fc72c923SHeiko Stübner 39362f49226SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) { 39462f49226SHeiko Stübner dev_err(info->dev, "pin %d is unrouted\n", pin); 39562f49226SHeiko Stübner return -EINVAL; 39662f49226SHeiko Stübner } 39762f49226SHeiko Stübner 398fc72c923SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) 399a076e2edSHeiko Stübner return RK_FUNC_GPIO; 400a076e2edSHeiko Stübner 40195ec8ae4SHeiko Stübner regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) 40295ec8ae4SHeiko Stübner ? info->regmap_pmu : info->regmap_base; 40395ec8ae4SHeiko Stübner 404a076e2edSHeiko Stübner /* get basic quadrupel of mux registers and the correct reg inside */ 40503716e1dSHeiko Stübner mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3; 4066bc0d121SHeiko Stübner reg = bank->iomux[iomux_num].offset; 40703716e1dSHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) { 40803716e1dSHeiko Stübner if ((pin % 8) >= 4) 40903716e1dSHeiko Stübner reg += 0x4; 41003716e1dSHeiko Stübner bit = (pin % 4) * 4; 41103716e1dSHeiko Stübner } else { 412a076e2edSHeiko Stübner bit = (pin % 8) * 2; 41303716e1dSHeiko Stübner } 414a076e2edSHeiko Stübner 41595ec8ae4SHeiko Stübner ret = regmap_read(regmap, reg, &val); 416751a99abSHeiko Stübner if (ret) 417751a99abSHeiko Stübner return ret; 418751a99abSHeiko Stübner 41903716e1dSHeiko Stübner return ((val >> bit) & mask); 420a076e2edSHeiko Stübner } 421a076e2edSHeiko Stübner 422d3e51161SHeiko Stübner /* 423d3e51161SHeiko Stübner * Set a new mux function for a pin. 424d3e51161SHeiko Stübner * 425d3e51161SHeiko Stübner * The register is divided into the upper and lower 16 bit. When changing 426d3e51161SHeiko Stübner * a value, the previous register value is not read and changed. Instead 427d3e51161SHeiko Stübner * it seems the changed bits are marked in the upper 16 bit, while the 428d3e51161SHeiko Stübner * changed value gets set in the same offset in the lower 16 bit. 429d3e51161SHeiko Stübner * All pin settings seem to be 2 bit wide in both the upper and lower 430d3e51161SHeiko Stübner * parts. 431d3e51161SHeiko Stübner * @bank: pin bank to change 432d3e51161SHeiko Stübner * @pin: pin to change 433d3e51161SHeiko Stübner * @mux: new mux function to set 434d3e51161SHeiko Stübner */ 43514797189SHeiko Stübner static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) 436d3e51161SHeiko Stübner { 437d3e51161SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 438fc72c923SHeiko Stübner int iomux_num = (pin / 8); 43995ec8ae4SHeiko Stübner struct regmap *regmap; 44003716e1dSHeiko Stübner int reg, ret, mask; 441d3e51161SHeiko Stübner unsigned long flags; 442d3e51161SHeiko Stübner u8 bit; 44399e872d9SSonny Rao u32 data, rmask; 444d3e51161SHeiko Stübner 445fc72c923SHeiko Stübner if (iomux_num > 3) 446fc72c923SHeiko Stübner return -EINVAL; 447fc72c923SHeiko Stübner 44862f49226SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_UNROUTED) { 44962f49226SHeiko Stübner dev_err(info->dev, "pin %d is unrouted\n", pin); 45062f49226SHeiko Stübner return -EINVAL; 45162f49226SHeiko Stübner } 45262f49226SHeiko Stübner 453fc72c923SHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_GPIO_ONLY) { 454c4a532deSHeiko Stübner if (mux != RK_FUNC_GPIO) { 455c4a532deSHeiko Stübner dev_err(info->dev, 456c4a532deSHeiko Stübner "pin %d only supports a gpio mux\n", pin); 457c4a532deSHeiko Stübner return -ENOTSUPP; 458c4a532deSHeiko Stübner } else { 459c4a532deSHeiko Stübner return 0; 460c4a532deSHeiko Stübner } 461c4a532deSHeiko Stübner } 462c4a532deSHeiko Stübner 463d3e51161SHeiko Stübner dev_dbg(info->dev, "setting mux of GPIO%d-%d to %d\n", 464d3e51161SHeiko Stübner bank->bank_num, pin, mux); 465d3e51161SHeiko Stübner 46695ec8ae4SHeiko Stübner regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) 46795ec8ae4SHeiko Stübner ? info->regmap_pmu : info->regmap_base; 46895ec8ae4SHeiko Stübner 469d3e51161SHeiko Stübner /* get basic quadrupel of mux registers and the correct reg inside */ 47003716e1dSHeiko Stübner mask = (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) ? 0xf : 0x3; 4716bc0d121SHeiko Stübner reg = bank->iomux[iomux_num].offset; 47203716e1dSHeiko Stübner if (bank->iomux[iomux_num].type & IOMUX_WIDTH_4BIT) { 47303716e1dSHeiko Stübner if ((pin % 8) >= 4) 47403716e1dSHeiko Stübner reg += 0x4; 47503716e1dSHeiko Stübner bit = (pin % 4) * 4; 47603716e1dSHeiko Stübner } else { 477d3e51161SHeiko Stübner bit = (pin % 8) * 2; 47803716e1dSHeiko Stübner } 479d3e51161SHeiko Stübner 480d3e51161SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 481d3e51161SHeiko Stübner 48203716e1dSHeiko Stübner data = (mask << (bit + 16)); 48399e872d9SSonny Rao rmask = data | (data >> 16); 48403716e1dSHeiko Stübner data |= (mux & mask) << bit; 48599e872d9SSonny Rao ret = regmap_update_bits(regmap, reg, rmask, data); 486d3e51161SHeiko Stübner 487d3e51161SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 48814797189SHeiko Stübner 489751a99abSHeiko Stübner return ret; 490d3e51161SHeiko Stübner } 491d3e51161SHeiko Stübner 492a282926dSHeiko Stübner #define RK2928_PULL_OFFSET 0x118 493a282926dSHeiko Stübner #define RK2928_PULL_PINS_PER_REG 16 494a282926dSHeiko Stübner #define RK2928_PULL_BANK_STRIDE 8 495a282926dSHeiko Stübner 496a282926dSHeiko Stübner static void rk2928_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 497751a99abSHeiko Stübner int pin_num, struct regmap **regmap, 498751a99abSHeiko Stübner int *reg, u8 *bit) 499a282926dSHeiko Stübner { 500a282926dSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 501a282926dSHeiko Stübner 502751a99abSHeiko Stübner *regmap = info->regmap_base; 503751a99abSHeiko Stübner *reg = RK2928_PULL_OFFSET; 504a282926dSHeiko Stübner *reg += bank->bank_num * RK2928_PULL_BANK_STRIDE; 505a282926dSHeiko Stübner *reg += (pin_num / RK2928_PULL_PINS_PER_REG) * 4; 506a282926dSHeiko Stübner 507a282926dSHeiko Stübner *bit = pin_num % RK2928_PULL_PINS_PER_REG; 508a282926dSHeiko Stübner }; 509a282926dSHeiko Stübner 510bfc7a42aSHeiko Stübner #define RK3188_PULL_OFFSET 0x164 5116ca5274dSHeiko Stübner #define RK3188_PULL_BITS_PER_PIN 2 5126ca5274dSHeiko Stübner #define RK3188_PULL_PINS_PER_REG 8 5136ca5274dSHeiko Stübner #define RK3188_PULL_BANK_STRIDE 16 51414dee867SHeiko Stübner #define RK3188_PULL_PMU_OFFSET 0x64 5156ca5274dSHeiko Stübner 5166ca5274dSHeiko Stübner static void rk3188_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 517751a99abSHeiko Stübner int pin_num, struct regmap **regmap, 518751a99abSHeiko Stübner int *reg, u8 *bit) 5196ca5274dSHeiko Stübner { 5206ca5274dSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 5216ca5274dSHeiko Stübner 5226ca5274dSHeiko Stübner /* The first 12 pins of the first bank are located elsewhere */ 523fc72c923SHeiko Stübner if (bank->bank_num == 0 && pin_num < 12) { 52414dee867SHeiko Stübner *regmap = info->regmap_pmu ? info->regmap_pmu 52514dee867SHeiko Stübner : bank->regmap_pull; 52614dee867SHeiko Stübner *reg = info->regmap_pmu ? RK3188_PULL_PMU_OFFSET : 0; 527751a99abSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 5286ca5274dSHeiko Stübner *bit = pin_num % RK3188_PULL_PINS_PER_REG; 5296ca5274dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 5306ca5274dSHeiko Stübner } else { 531751a99abSHeiko Stübner *regmap = info->regmap_pull ? info->regmap_pull 532751a99abSHeiko Stübner : info->regmap_base; 533751a99abSHeiko Stübner *reg = info->regmap_pull ? 0 : RK3188_PULL_OFFSET; 534751a99abSHeiko Stübner 535bfc7a42aSHeiko Stübner /* correct the offset, as it is the 2nd pull register */ 536bfc7a42aSHeiko Stübner *reg -= 4; 5376ca5274dSHeiko Stübner *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; 5386ca5274dSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 5396ca5274dSHeiko Stübner 5406ca5274dSHeiko Stübner /* 5416ca5274dSHeiko Stübner * The bits in these registers have an inverse ordering 5426ca5274dSHeiko Stübner * with the lowest pin being in bits 15:14 and the highest 5436ca5274dSHeiko Stübner * pin in bits 1:0 5446ca5274dSHeiko Stübner */ 5456ca5274dSHeiko Stübner *bit = 7 - (pin_num % RK3188_PULL_PINS_PER_REG); 5466ca5274dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 5476ca5274dSHeiko Stübner } 5486ca5274dSHeiko Stübner } 5496ca5274dSHeiko Stübner 550304f077dSHeiko Stübner #define RK3288_PULL_OFFSET 0x140 551304f077dSHeiko Stübner static void rk3288_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, 552304f077dSHeiko Stübner int pin_num, struct regmap **regmap, 553304f077dSHeiko Stübner int *reg, u8 *bit) 554304f077dSHeiko Stübner { 555304f077dSHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 556304f077dSHeiko Stübner 557304f077dSHeiko Stübner /* The first 24 pins of the first bank are located in PMU */ 558304f077dSHeiko Stübner if (bank->bank_num == 0) { 559304f077dSHeiko Stübner *regmap = info->regmap_pmu; 560304f077dSHeiko Stübner *reg = RK3188_PULL_PMU_OFFSET; 561304f077dSHeiko Stübner 562304f077dSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 563304f077dSHeiko Stübner *bit = pin_num % RK3188_PULL_PINS_PER_REG; 564304f077dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 565304f077dSHeiko Stübner } else { 566304f077dSHeiko Stübner *regmap = info->regmap_base; 567304f077dSHeiko Stübner *reg = RK3288_PULL_OFFSET; 568304f077dSHeiko Stübner 569304f077dSHeiko Stübner /* correct the offset, as we're starting with the 2nd bank */ 570304f077dSHeiko Stübner *reg -= 0x10; 571304f077dSHeiko Stübner *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE; 572304f077dSHeiko Stübner *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4); 573304f077dSHeiko Stübner 574304f077dSHeiko Stübner *bit = (pin_num % RK3188_PULL_PINS_PER_REG); 575304f077dSHeiko Stübner *bit *= RK3188_PULL_BITS_PER_PIN; 576304f077dSHeiko Stübner } 577304f077dSHeiko Stübner } 578304f077dSHeiko Stübner 579b547c800SHeiko Stübner #define RK3288_DRV_PMU_OFFSET 0x70 580b547c800SHeiko Stübner #define RK3288_DRV_GRF_OFFSET 0x1c0 581b547c800SHeiko Stübner #define RK3288_DRV_BITS_PER_PIN 2 582b547c800SHeiko Stübner #define RK3288_DRV_PINS_PER_REG 8 583b547c800SHeiko Stübner #define RK3288_DRV_BANK_STRIDE 16 584b547c800SHeiko Stübner static int rk3288_drv_list[] = { 2, 4, 8, 12 }; 585b547c800SHeiko Stübner 586b547c800SHeiko Stübner static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, 587b547c800SHeiko Stübner int pin_num, struct regmap **regmap, 588b547c800SHeiko Stübner int *reg, u8 *bit) 589b547c800SHeiko Stübner { 590b547c800SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 591b547c800SHeiko Stübner 592b547c800SHeiko Stübner /* The first 24 pins of the first bank are located in PMU */ 593b547c800SHeiko Stübner if (bank->bank_num == 0) { 594b547c800SHeiko Stübner *regmap = info->regmap_pmu; 595b547c800SHeiko Stübner *reg = RK3288_DRV_PMU_OFFSET; 596b547c800SHeiko Stübner 597b547c800SHeiko Stübner *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4); 598b547c800SHeiko Stübner *bit = pin_num % RK3288_DRV_PINS_PER_REG; 599b547c800SHeiko Stübner *bit *= RK3288_DRV_BITS_PER_PIN; 600b547c800SHeiko Stübner } else { 601b547c800SHeiko Stübner *regmap = info->regmap_base; 602b547c800SHeiko Stübner *reg = RK3288_DRV_GRF_OFFSET; 603b547c800SHeiko Stübner 604b547c800SHeiko Stübner /* correct the offset, as we're starting with the 2nd bank */ 605b547c800SHeiko Stübner *reg -= 0x10; 606b547c800SHeiko Stübner *reg += bank->bank_num * RK3288_DRV_BANK_STRIDE; 607b547c800SHeiko Stübner *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4); 608b547c800SHeiko Stübner 609b547c800SHeiko Stübner *bit = (pin_num % RK3288_DRV_PINS_PER_REG); 610b547c800SHeiko Stübner *bit *= RK3288_DRV_BITS_PER_PIN; 611b547c800SHeiko Stübner } 612b547c800SHeiko Stübner } 613b547c800SHeiko Stübner 614b547c800SHeiko Stübner static int rk3288_get_drive(struct rockchip_pin_bank *bank, int pin_num) 615b547c800SHeiko Stübner { 616b547c800SHeiko Stübner struct regmap *regmap; 617b547c800SHeiko Stübner int reg, ret; 618b547c800SHeiko Stübner u32 data; 619b547c800SHeiko Stübner u8 bit; 620b547c800SHeiko Stübner 621b547c800SHeiko Stübner rk3288_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); 622b547c800SHeiko Stübner 623b547c800SHeiko Stübner ret = regmap_read(regmap, reg, &data); 624b547c800SHeiko Stübner if (ret) 625b547c800SHeiko Stübner return ret; 626b547c800SHeiko Stübner 627b547c800SHeiko Stübner data >>= bit; 628b547c800SHeiko Stübner data &= (1 << RK3288_DRV_BITS_PER_PIN) - 1; 629b547c800SHeiko Stübner 630b547c800SHeiko Stübner return rk3288_drv_list[data]; 631b547c800SHeiko Stübner } 632b547c800SHeiko Stübner 633b547c800SHeiko Stübner static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num, 634b547c800SHeiko Stübner int strength) 635b547c800SHeiko Stübner { 636b547c800SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 637b547c800SHeiko Stübner struct regmap *regmap; 638b547c800SHeiko Stübner unsigned long flags; 639b547c800SHeiko Stübner int reg, ret, i; 64099e872d9SSonny Rao u32 data, rmask; 641b547c800SHeiko Stübner u8 bit; 642b547c800SHeiko Stübner 643b547c800SHeiko Stübner rk3288_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); 644b547c800SHeiko Stübner 645b547c800SHeiko Stübner ret = -EINVAL; 646b547c800SHeiko Stübner for (i = 0; i < ARRAY_SIZE(rk3288_drv_list); i++) { 647b547c800SHeiko Stübner if (rk3288_drv_list[i] == strength) { 648b547c800SHeiko Stübner ret = i; 649b547c800SHeiko Stübner break; 650b547c800SHeiko Stübner } 651b547c800SHeiko Stübner } 652b547c800SHeiko Stübner 653b547c800SHeiko Stübner if (ret < 0) { 654b547c800SHeiko Stübner dev_err(info->dev, "unsupported driver strength %d\n", 655b547c800SHeiko Stübner strength); 656b547c800SHeiko Stübner return ret; 657b547c800SHeiko Stübner } 658b547c800SHeiko Stübner 659b547c800SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 660b547c800SHeiko Stübner 661b547c800SHeiko Stübner /* enable the write to the equivalent lower bits */ 662b547c800SHeiko Stübner data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16); 66399e872d9SSonny Rao rmask = data | (data >> 16); 664b547c800SHeiko Stübner data |= (ret << bit); 665b547c800SHeiko Stübner 66699e872d9SSonny Rao ret = regmap_update_bits(regmap, reg, rmask, data); 667b547c800SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 668b547c800SHeiko Stübner 669b547c800SHeiko Stübner return ret; 670b547c800SHeiko Stübner } 671b547c800SHeiko Stübner 672d3e51161SHeiko Stübner static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) 673d3e51161SHeiko Stübner { 674d3e51161SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 675d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 676751a99abSHeiko Stübner struct regmap *regmap; 677751a99abSHeiko Stübner int reg, ret; 678d3e51161SHeiko Stübner u8 bit; 6796ca5274dSHeiko Stübner u32 data; 680d3e51161SHeiko Stübner 681d3e51161SHeiko Stübner /* rk3066b does support any pulls */ 682a282926dSHeiko Stübner if (ctrl->type == RK3066B) 683d3e51161SHeiko Stübner return PIN_CONFIG_BIAS_DISABLE; 684d3e51161SHeiko Stübner 685751a99abSHeiko Stübner ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); 686751a99abSHeiko Stübner 687751a99abSHeiko Stübner ret = regmap_read(regmap, reg, &data); 688751a99abSHeiko Stübner if (ret) 689751a99abSHeiko Stübner return ret; 6906ca5274dSHeiko Stübner 691a282926dSHeiko Stübner switch (ctrl->type) { 692a282926dSHeiko Stübner case RK2928: 693751a99abSHeiko Stübner return !(data & BIT(bit)) 694d3e51161SHeiko Stübner ? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT 695d3e51161SHeiko Stübner : PIN_CONFIG_BIAS_DISABLE; 696a282926dSHeiko Stübner case RK3188: 69766d750e1SHeiko Stübner case RK3288: 698751a99abSHeiko Stübner data >>= bit; 6996ca5274dSHeiko Stübner data &= (1 << RK3188_PULL_BITS_PER_PIN) - 1; 7006ca5274dSHeiko Stübner 7016ca5274dSHeiko Stübner switch (data) { 7026ca5274dSHeiko Stübner case 0: 7036ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_DISABLE; 7046ca5274dSHeiko Stübner case 1: 7056ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_PULL_UP; 7066ca5274dSHeiko Stübner case 2: 7076ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_PULL_DOWN; 7086ca5274dSHeiko Stübner case 3: 7096ca5274dSHeiko Stübner return PIN_CONFIG_BIAS_BUS_HOLD; 7106ca5274dSHeiko Stübner } 7116ca5274dSHeiko Stübner 7126ca5274dSHeiko Stübner dev_err(info->dev, "unknown pull setting\n"); 713d3e51161SHeiko Stübner return -EIO; 714a282926dSHeiko Stübner default: 715a282926dSHeiko Stübner dev_err(info->dev, "unsupported pinctrl type\n"); 716a282926dSHeiko Stübner return -EINVAL; 717a282926dSHeiko Stübner }; 718d3e51161SHeiko Stübner } 719d3e51161SHeiko Stübner 720d3e51161SHeiko Stübner static int rockchip_set_pull(struct rockchip_pin_bank *bank, 721d3e51161SHeiko Stübner int pin_num, int pull) 722d3e51161SHeiko Stübner { 723d3e51161SHeiko Stübner struct rockchip_pinctrl *info = bank->drvdata; 724d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 725751a99abSHeiko Stübner struct regmap *regmap; 726751a99abSHeiko Stübner int reg, ret; 727d3e51161SHeiko Stübner unsigned long flags; 728d3e51161SHeiko Stübner u8 bit; 72999e872d9SSonny Rao u32 data, rmask; 730d3e51161SHeiko Stübner 731d3e51161SHeiko Stübner dev_dbg(info->dev, "setting pull of GPIO%d-%d to %d\n", 732d3e51161SHeiko Stübner bank->bank_num, pin_num, pull); 733d3e51161SHeiko Stübner 734d3e51161SHeiko Stübner /* rk3066b does support any pulls */ 735a282926dSHeiko Stübner if (ctrl->type == RK3066B) 736d3e51161SHeiko Stübner return pull ? -EINVAL : 0; 737d3e51161SHeiko Stübner 738751a99abSHeiko Stübner ctrl->pull_calc_reg(bank, pin_num, ®map, ®, &bit); 739d3e51161SHeiko Stübner 7406ca5274dSHeiko Stübner switch (ctrl->type) { 7416ca5274dSHeiko Stübner case RK2928: 742d3e51161SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 743d3e51161SHeiko Stübner 744d3e51161SHeiko Stübner data = BIT(bit + 16); 745d3e51161SHeiko Stübner if (pull == PIN_CONFIG_BIAS_DISABLE) 746d3e51161SHeiko Stübner data |= BIT(bit); 747751a99abSHeiko Stübner ret = regmap_write(regmap, reg, data); 748d3e51161SHeiko Stübner 749d3e51161SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 750a282926dSHeiko Stübner break; 751a282926dSHeiko Stübner case RK3188: 75266d750e1SHeiko Stübner case RK3288: 7536ca5274dSHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 7546ca5274dSHeiko Stübner 7556ca5274dSHeiko Stübner /* enable the write to the equivalent lower bits */ 7566ca5274dSHeiko Stübner data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16); 75799e872d9SSonny Rao rmask = data | (data >> 16); 7586ca5274dSHeiko Stübner 7596ca5274dSHeiko Stübner switch (pull) { 7606ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_DISABLE: 7616ca5274dSHeiko Stübner break; 7626ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_PULL_UP: 7636ca5274dSHeiko Stübner data |= (1 << bit); 7646ca5274dSHeiko Stübner break; 7656ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_PULL_DOWN: 7666ca5274dSHeiko Stübner data |= (2 << bit); 7676ca5274dSHeiko Stübner break; 7686ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_BUS_HOLD: 7696ca5274dSHeiko Stübner data |= (3 << bit); 7706ca5274dSHeiko Stübner break; 7716ca5274dSHeiko Stübner default: 772d32c3e26SDan Carpenter spin_unlock_irqrestore(&bank->slock, flags); 7736ca5274dSHeiko Stübner dev_err(info->dev, "unsupported pull setting %d\n", 7746ca5274dSHeiko Stübner pull); 7756ca5274dSHeiko Stübner return -EINVAL; 7766ca5274dSHeiko Stübner } 7776ca5274dSHeiko Stübner 77899e872d9SSonny Rao ret = regmap_update_bits(regmap, reg, rmask, data); 7796ca5274dSHeiko Stübner 7806ca5274dSHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 7816ca5274dSHeiko Stübner break; 782a282926dSHeiko Stübner default: 783a282926dSHeiko Stübner dev_err(info->dev, "unsupported pinctrl type\n"); 784a282926dSHeiko Stübner return -EINVAL; 785d3e51161SHeiko Stübner } 786d3e51161SHeiko Stübner 787751a99abSHeiko Stübner return ret; 788d3e51161SHeiko Stübner } 789d3e51161SHeiko Stübner 790d3e51161SHeiko Stübner /* 791d3e51161SHeiko Stübner * Pinmux_ops handling 792d3e51161SHeiko Stübner */ 793d3e51161SHeiko Stübner 794d3e51161SHeiko Stübner static int rockchip_pmx_get_funcs_count(struct pinctrl_dev *pctldev) 795d3e51161SHeiko Stübner { 796d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 797d3e51161SHeiko Stübner 798d3e51161SHeiko Stübner return info->nfunctions; 799d3e51161SHeiko Stübner } 800d3e51161SHeiko Stübner 801d3e51161SHeiko Stübner static const char *rockchip_pmx_get_func_name(struct pinctrl_dev *pctldev, 802d3e51161SHeiko Stübner unsigned selector) 803d3e51161SHeiko Stübner { 804d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 805d3e51161SHeiko Stübner 806d3e51161SHeiko Stübner return info->functions[selector].name; 807d3e51161SHeiko Stübner } 808d3e51161SHeiko Stübner 809d3e51161SHeiko Stübner static int rockchip_pmx_get_groups(struct pinctrl_dev *pctldev, 810d3e51161SHeiko Stübner unsigned selector, const char * const **groups, 811d3e51161SHeiko Stübner unsigned * const num_groups) 812d3e51161SHeiko Stübner { 813d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 814d3e51161SHeiko Stübner 815d3e51161SHeiko Stübner *groups = info->functions[selector].groups; 816d3e51161SHeiko Stübner *num_groups = info->functions[selector].ngroups; 817d3e51161SHeiko Stübner 818d3e51161SHeiko Stübner return 0; 819d3e51161SHeiko Stübner } 820d3e51161SHeiko Stübner 82103e9f0caSLinus Walleij static int rockchip_pmx_set(struct pinctrl_dev *pctldev, unsigned selector, 822d3e51161SHeiko Stübner unsigned group) 823d3e51161SHeiko Stübner { 824d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 825d3e51161SHeiko Stübner const unsigned int *pins = info->groups[group].pins; 826d3e51161SHeiko Stübner const struct rockchip_pin_config *data = info->groups[group].data; 827d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 82814797189SHeiko Stübner int cnt, ret = 0; 829d3e51161SHeiko Stübner 830d3e51161SHeiko Stübner dev_dbg(info->dev, "enable function %s group %s\n", 831d3e51161SHeiko Stübner info->functions[selector].name, info->groups[group].name); 832d3e51161SHeiko Stübner 833d3e51161SHeiko Stübner /* 834d3e51161SHeiko Stübner * for each pin in the pin group selected, program the correspoding pin 835d3e51161SHeiko Stübner * pin function number in the config register. 836d3e51161SHeiko Stübner */ 837d3e51161SHeiko Stübner for (cnt = 0; cnt < info->groups[group].npins; cnt++) { 838d3e51161SHeiko Stübner bank = pin_to_bank(info, pins[cnt]); 83914797189SHeiko Stübner ret = rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 840d3e51161SHeiko Stübner data[cnt].func); 84114797189SHeiko Stübner if (ret) 84214797189SHeiko Stübner break; 84314797189SHeiko Stübner } 84414797189SHeiko Stübner 84514797189SHeiko Stübner if (ret) { 84614797189SHeiko Stübner /* revert the already done pin settings */ 84714797189SHeiko Stübner for (cnt--; cnt >= 0; cnt--) 84814797189SHeiko Stübner rockchip_set_mux(bank, pins[cnt] - bank->pin_base, 0); 84914797189SHeiko Stübner 85014797189SHeiko Stübner return ret; 851d3e51161SHeiko Stübner } 852d3e51161SHeiko Stübner 853d3e51161SHeiko Stübner return 0; 854d3e51161SHeiko Stübner } 855d3e51161SHeiko Stübner 856d3e51161SHeiko Stübner /* 857d3e51161SHeiko Stübner * The calls to gpio_direction_output() and gpio_direction_input() 858d3e51161SHeiko Stübner * leads to this function call (via the pinctrl_gpio_direction_{input|output}() 859d3e51161SHeiko Stübner * function called from the gpiolib interface). 860d3e51161SHeiko Stübner */ 861e5c2c9dbSDoug Anderson static int _rockchip_pmx_gpio_set_direction(struct gpio_chip *chip, 862e5c2c9dbSDoug Anderson int pin, bool input) 863d3e51161SHeiko Stübner { 864d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 865e5c2c9dbSDoug Anderson int ret; 866fab262f5SDoug Anderson unsigned long flags; 867d3e51161SHeiko Stübner u32 data; 868d3e51161SHeiko Stübner 869d3e51161SHeiko Stübner bank = gc_to_pin_bank(chip); 870d3e51161SHeiko Stübner 87114797189SHeiko Stübner ret = rockchip_set_mux(bank, pin, RK_FUNC_GPIO); 87214797189SHeiko Stübner if (ret < 0) 87314797189SHeiko Stübner return ret; 874d3e51161SHeiko Stübner 875fab262f5SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 876fab262f5SDoug Anderson 877d3e51161SHeiko Stübner data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); 878d3e51161SHeiko Stübner /* set bit to 1 for output, 0 for input */ 879d3e51161SHeiko Stübner if (!input) 880d3e51161SHeiko Stübner data |= BIT(pin); 881d3e51161SHeiko Stübner else 882d3e51161SHeiko Stübner data &= ~BIT(pin); 883d3e51161SHeiko Stübner writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); 884d3e51161SHeiko Stübner 885fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 886fab262f5SDoug Anderson 887d3e51161SHeiko Stübner return 0; 888d3e51161SHeiko Stübner } 889d3e51161SHeiko Stübner 890e5c2c9dbSDoug Anderson static int rockchip_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, 891e5c2c9dbSDoug Anderson struct pinctrl_gpio_range *range, 892e5c2c9dbSDoug Anderson unsigned offset, bool input) 893e5c2c9dbSDoug Anderson { 894e5c2c9dbSDoug Anderson struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 895e5c2c9dbSDoug Anderson struct gpio_chip *chip; 896e5c2c9dbSDoug Anderson int pin; 897e5c2c9dbSDoug Anderson 898e5c2c9dbSDoug Anderson chip = range->gc; 899e5c2c9dbSDoug Anderson pin = offset - chip->base; 900e5c2c9dbSDoug Anderson dev_dbg(info->dev, "gpio_direction for pin %u as %s-%d to %s\n", 901e5c2c9dbSDoug Anderson offset, range->name, pin, input ? "input" : "output"); 902e5c2c9dbSDoug Anderson 903e5c2c9dbSDoug Anderson return _rockchip_pmx_gpio_set_direction(chip, offset - chip->base, 904e5c2c9dbSDoug Anderson input); 905e5c2c9dbSDoug Anderson } 906e5c2c9dbSDoug Anderson 907d3e51161SHeiko Stübner static const struct pinmux_ops rockchip_pmx_ops = { 908d3e51161SHeiko Stübner .get_functions_count = rockchip_pmx_get_funcs_count, 909d3e51161SHeiko Stübner .get_function_name = rockchip_pmx_get_func_name, 910d3e51161SHeiko Stübner .get_function_groups = rockchip_pmx_get_groups, 91103e9f0caSLinus Walleij .set_mux = rockchip_pmx_set, 912d3e51161SHeiko Stübner .gpio_set_direction = rockchip_pmx_gpio_set_direction, 913d3e51161SHeiko Stübner }; 914d3e51161SHeiko Stübner 915d3e51161SHeiko Stübner /* 916d3e51161SHeiko Stübner * Pinconf_ops handling 917d3e51161SHeiko Stübner */ 918d3e51161SHeiko Stübner 91944b6d930SHeiko Stübner static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, 92044b6d930SHeiko Stübner enum pin_config_param pull) 92144b6d930SHeiko Stübner { 922a282926dSHeiko Stübner switch (ctrl->type) { 923a282926dSHeiko Stübner case RK2928: 924a282926dSHeiko Stübner return (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT || 925a282926dSHeiko Stübner pull == PIN_CONFIG_BIAS_DISABLE); 926a282926dSHeiko Stübner case RK3066B: 92744b6d930SHeiko Stübner return pull ? false : true; 928a282926dSHeiko Stübner case RK3188: 92966d750e1SHeiko Stübner case RK3288: 930a282926dSHeiko Stübner return (pull != PIN_CONFIG_BIAS_PULL_PIN_DEFAULT); 93144b6d930SHeiko Stübner } 93244b6d930SHeiko Stübner 933a282926dSHeiko Stübner return false; 93444b6d930SHeiko Stübner } 93544b6d930SHeiko Stübner 936e5c2c9dbSDoug Anderson static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value); 937a076e2edSHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset); 938a076e2edSHeiko Stübner 939d3e51161SHeiko Stübner /* set the pin config settings for a specified pin */ 940d3e51161SHeiko Stübner static int rockchip_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, 94103b054e9SSherman Yin unsigned long *configs, unsigned num_configs) 942d3e51161SHeiko Stübner { 943d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 944d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = pin_to_bank(info, pin); 94503b054e9SSherman Yin enum pin_config_param param; 94603b054e9SSherman Yin u16 arg; 94703b054e9SSherman Yin int i; 94803b054e9SSherman Yin int rc; 94903b054e9SSherman Yin 95003b054e9SSherman Yin for (i = 0; i < num_configs; i++) { 95103b054e9SSherman Yin param = pinconf_to_config_param(configs[i]); 95203b054e9SSherman Yin arg = pinconf_to_config_argument(configs[i]); 953d3e51161SHeiko Stübner 954d3e51161SHeiko Stübner switch (param) { 955d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_DISABLE: 95603b054e9SSherman Yin rc = rockchip_set_pull(bank, pin - bank->pin_base, 95703b054e9SSherman Yin param); 95803b054e9SSherman Yin if (rc) 95903b054e9SSherman Yin return rc; 96044b6d930SHeiko Stübner break; 961d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_PULL_UP: 962d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_PULL_DOWN: 963d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 9646ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_BUS_HOLD: 96544b6d930SHeiko Stübner if (!rockchip_pinconf_pull_valid(info->ctrl, param)) 96644b6d930SHeiko Stübner return -ENOTSUPP; 96744b6d930SHeiko Stübner 96844b6d930SHeiko Stübner if (!arg) 96944b6d930SHeiko Stübner return -EINVAL; 97044b6d930SHeiko Stübner 97103b054e9SSherman Yin rc = rockchip_set_pull(bank, pin - bank->pin_base, 97203b054e9SSherman Yin param); 97303b054e9SSherman Yin if (rc) 97403b054e9SSherman Yin return rc; 975d3e51161SHeiko Stübner break; 976a076e2edSHeiko Stübner case PIN_CONFIG_OUTPUT: 977e5c2c9dbSDoug Anderson rockchip_gpio_set(&bank->gpio_chip, 978e5c2c9dbSDoug Anderson pin - bank->pin_base, arg); 979e5c2c9dbSDoug Anderson rc = _rockchip_pmx_gpio_set_direction(&bank->gpio_chip, 980e5c2c9dbSDoug Anderson pin - bank->pin_base, false); 981a076e2edSHeiko Stübner if (rc) 982a076e2edSHeiko Stübner return rc; 983a076e2edSHeiko Stübner break; 984b547c800SHeiko Stübner case PIN_CONFIG_DRIVE_STRENGTH: 985b547c800SHeiko Stübner /* rk3288 is the first with per-pin drive-strength */ 986b547c800SHeiko Stübner if (info->ctrl->type != RK3288) 987b547c800SHeiko Stübner return -ENOTSUPP; 988b547c800SHeiko Stübner 989b547c800SHeiko Stübner rc = rk3288_set_drive(bank, pin - bank->pin_base, arg); 990b547c800SHeiko Stübner if (rc < 0) 991b547c800SHeiko Stübner return rc; 992b547c800SHeiko Stübner break; 993d3e51161SHeiko Stübner default: 994d3e51161SHeiko Stübner return -ENOTSUPP; 995d3e51161SHeiko Stübner break; 996d3e51161SHeiko Stübner } 99703b054e9SSherman Yin } /* for each config */ 998d3e51161SHeiko Stübner 999d3e51161SHeiko Stübner return 0; 1000d3e51161SHeiko Stübner } 1001d3e51161SHeiko Stübner 1002d3e51161SHeiko Stübner /* get the pin config settings for a specified pin */ 1003d3e51161SHeiko Stübner static int rockchip_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, 1004d3e51161SHeiko Stübner unsigned long *config) 1005d3e51161SHeiko Stübner { 1006d3e51161SHeiko Stübner struct rockchip_pinctrl *info = pinctrl_dev_get_drvdata(pctldev); 1007d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = pin_to_bank(info, pin); 1008d3e51161SHeiko Stübner enum pin_config_param param = pinconf_to_config_param(*config); 1009dab3eba7SHeiko Stübner u16 arg; 1010a076e2edSHeiko Stübner int rc; 1011d3e51161SHeiko Stübner 1012d3e51161SHeiko Stübner switch (param) { 1013d3e51161SHeiko Stübner case PIN_CONFIG_BIAS_DISABLE: 101444b6d930SHeiko Stübner if (rockchip_get_pull(bank, pin - bank->pin_base) != param) 1015d3e51161SHeiko Stübner return -EINVAL; 1016d3e51161SHeiko Stübner 1017dab3eba7SHeiko Stübner arg = 0; 1018d3e51161SHeiko Stübner break; 101944b6d930SHeiko Stübner case PIN_CONFIG_BIAS_PULL_UP: 102044b6d930SHeiko Stübner case PIN_CONFIG_BIAS_PULL_DOWN: 102144b6d930SHeiko Stübner case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: 10226ca5274dSHeiko Stübner case PIN_CONFIG_BIAS_BUS_HOLD: 102344b6d930SHeiko Stübner if (!rockchip_pinconf_pull_valid(info->ctrl, param)) 102444b6d930SHeiko Stübner return -ENOTSUPP; 102544b6d930SHeiko Stübner 102644b6d930SHeiko Stübner if (rockchip_get_pull(bank, pin - bank->pin_base) != param) 102744b6d930SHeiko Stübner return -EINVAL; 102844b6d930SHeiko Stübner 1029dab3eba7SHeiko Stübner arg = 1; 103044b6d930SHeiko Stübner break; 1031a076e2edSHeiko Stübner case PIN_CONFIG_OUTPUT: 1032a076e2edSHeiko Stübner rc = rockchip_get_mux(bank, pin - bank->pin_base); 1033a076e2edSHeiko Stübner if (rc != RK_FUNC_GPIO) 1034a076e2edSHeiko Stübner return -EINVAL; 1035a076e2edSHeiko Stübner 1036a076e2edSHeiko Stübner rc = rockchip_gpio_get(&bank->gpio_chip, pin - bank->pin_base); 1037a076e2edSHeiko Stübner if (rc < 0) 1038a076e2edSHeiko Stübner return rc; 1039a076e2edSHeiko Stübner 1040a076e2edSHeiko Stübner arg = rc ? 1 : 0; 1041a076e2edSHeiko Stübner break; 1042b547c800SHeiko Stübner case PIN_CONFIG_DRIVE_STRENGTH: 1043b547c800SHeiko Stübner /* rk3288 is the first with per-pin drive-strength */ 1044b547c800SHeiko Stübner if (info->ctrl->type != RK3288) 1045b547c800SHeiko Stübner return -ENOTSUPP; 1046b547c800SHeiko Stübner 1047b547c800SHeiko Stübner rc = rk3288_get_drive(bank, pin - bank->pin_base); 1048b547c800SHeiko Stübner if (rc < 0) 1049b547c800SHeiko Stübner return rc; 1050b547c800SHeiko Stübner 1051b547c800SHeiko Stübner arg = rc; 1052b547c800SHeiko Stübner break; 1053d3e51161SHeiko Stübner default: 1054d3e51161SHeiko Stübner return -ENOTSUPP; 1055d3e51161SHeiko Stübner break; 1056d3e51161SHeiko Stübner } 1057d3e51161SHeiko Stübner 1058dab3eba7SHeiko Stübner *config = pinconf_to_config_packed(param, arg); 1059dab3eba7SHeiko Stübner 1060d3e51161SHeiko Stübner return 0; 1061d3e51161SHeiko Stübner } 1062d3e51161SHeiko Stübner 1063d3e51161SHeiko Stübner static const struct pinconf_ops rockchip_pinconf_ops = { 1064d3e51161SHeiko Stübner .pin_config_get = rockchip_pinconf_get, 1065d3e51161SHeiko Stübner .pin_config_set = rockchip_pinconf_set, 1066ed62f2f2SHeiko Stübner .is_generic = true, 1067d3e51161SHeiko Stübner }; 1068d3e51161SHeiko Stübner 106965fca613SHeiko Stübner static const struct of_device_id rockchip_bank_match[] = { 107065fca613SHeiko Stübner { .compatible = "rockchip,gpio-bank" }, 10716ca5274dSHeiko Stübner { .compatible = "rockchip,rk3188-gpio-bank0" }, 107265fca613SHeiko Stübner {}, 107365fca613SHeiko Stübner }; 1074d3e51161SHeiko Stübner 1075d3e51161SHeiko Stübner static void rockchip_pinctrl_child_count(struct rockchip_pinctrl *info, 1076d3e51161SHeiko Stübner struct device_node *np) 1077d3e51161SHeiko Stübner { 1078d3e51161SHeiko Stübner struct device_node *child; 1079d3e51161SHeiko Stübner 1080d3e51161SHeiko Stübner for_each_child_of_node(np, child) { 108165fca613SHeiko Stübner if (of_match_node(rockchip_bank_match, child)) 1082d3e51161SHeiko Stübner continue; 1083d3e51161SHeiko Stübner 1084d3e51161SHeiko Stübner info->nfunctions++; 1085d3e51161SHeiko Stübner info->ngroups += of_get_child_count(child); 1086d3e51161SHeiko Stübner } 1087d3e51161SHeiko Stübner } 1088d3e51161SHeiko Stübner 1089d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_groups(struct device_node *np, 1090d3e51161SHeiko Stübner struct rockchip_pin_group *grp, 1091d3e51161SHeiko Stübner struct rockchip_pinctrl *info, 1092d3e51161SHeiko Stübner u32 index) 1093d3e51161SHeiko Stübner { 1094d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 1095d3e51161SHeiko Stübner int size; 1096d3e51161SHeiko Stübner const __be32 *list; 1097d3e51161SHeiko Stübner int num; 1098d3e51161SHeiko Stübner int i, j; 1099d3e51161SHeiko Stübner int ret; 1100d3e51161SHeiko Stübner 1101d3e51161SHeiko Stübner dev_dbg(info->dev, "group(%d): %s\n", index, np->name); 1102d3e51161SHeiko Stübner 1103d3e51161SHeiko Stübner /* Initialise group */ 1104d3e51161SHeiko Stübner grp->name = np->name; 1105d3e51161SHeiko Stübner 1106d3e51161SHeiko Stübner /* 1107d3e51161SHeiko Stübner * the binding format is rockchip,pins = <bank pin mux CONFIG>, 1108d3e51161SHeiko Stübner * do sanity check and calculate pins number 1109d3e51161SHeiko Stübner */ 1110d3e51161SHeiko Stübner list = of_get_property(np, "rockchip,pins", &size); 1111d3e51161SHeiko Stübner /* we do not check return since it's safe node passed down */ 1112d3e51161SHeiko Stübner size /= sizeof(*list); 1113d3e51161SHeiko Stübner if (!size || size % 4) { 1114d3e51161SHeiko Stübner dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n"); 1115d3e51161SHeiko Stübner return -EINVAL; 1116d3e51161SHeiko Stübner } 1117d3e51161SHeiko Stübner 1118d3e51161SHeiko Stübner grp->npins = size / 4; 1119d3e51161SHeiko Stübner 1120d3e51161SHeiko Stübner grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int), 1121d3e51161SHeiko Stübner GFP_KERNEL); 1122d3e51161SHeiko Stübner grp->data = devm_kzalloc(info->dev, grp->npins * 1123d3e51161SHeiko Stübner sizeof(struct rockchip_pin_config), 1124d3e51161SHeiko Stübner GFP_KERNEL); 1125d3e51161SHeiko Stübner if (!grp->pins || !grp->data) 1126d3e51161SHeiko Stübner return -ENOMEM; 1127d3e51161SHeiko Stübner 1128d3e51161SHeiko Stübner for (i = 0, j = 0; i < size; i += 4, j++) { 1129d3e51161SHeiko Stübner const __be32 *phandle; 1130d3e51161SHeiko Stübner struct device_node *np_config; 1131d3e51161SHeiko Stübner 1132d3e51161SHeiko Stübner num = be32_to_cpu(*list++); 1133d3e51161SHeiko Stübner bank = bank_num_to_bank(info, num); 1134d3e51161SHeiko Stübner if (IS_ERR(bank)) 1135d3e51161SHeiko Stübner return PTR_ERR(bank); 1136d3e51161SHeiko Stübner 1137d3e51161SHeiko Stübner grp->pins[j] = bank->pin_base + be32_to_cpu(*list++); 1138d3e51161SHeiko Stübner grp->data[j].func = be32_to_cpu(*list++); 1139d3e51161SHeiko Stübner 1140d3e51161SHeiko Stübner phandle = list++; 1141d3e51161SHeiko Stübner if (!phandle) 1142d3e51161SHeiko Stübner return -EINVAL; 1143d3e51161SHeiko Stübner 1144d3e51161SHeiko Stübner np_config = of_find_node_by_phandle(be32_to_cpup(phandle)); 1145d3e51161SHeiko Stübner ret = pinconf_generic_parse_dt_config(np_config, 1146d3e51161SHeiko Stübner &grp->data[j].configs, &grp->data[j].nconfigs); 1147d3e51161SHeiko Stübner if (ret) 1148d3e51161SHeiko Stübner return ret; 1149d3e51161SHeiko Stübner } 1150d3e51161SHeiko Stübner 1151d3e51161SHeiko Stübner return 0; 1152d3e51161SHeiko Stübner } 1153d3e51161SHeiko Stübner 1154d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_functions(struct device_node *np, 1155d3e51161SHeiko Stübner struct rockchip_pinctrl *info, 1156d3e51161SHeiko Stübner u32 index) 1157d3e51161SHeiko Stübner { 1158d3e51161SHeiko Stübner struct device_node *child; 1159d3e51161SHeiko Stübner struct rockchip_pmx_func *func; 1160d3e51161SHeiko Stübner struct rockchip_pin_group *grp; 1161d3e51161SHeiko Stübner int ret; 1162d3e51161SHeiko Stübner static u32 grp_index; 1163d3e51161SHeiko Stübner u32 i = 0; 1164d3e51161SHeiko Stübner 1165d3e51161SHeiko Stübner dev_dbg(info->dev, "parse function(%d): %s\n", index, np->name); 1166d3e51161SHeiko Stübner 1167d3e51161SHeiko Stübner func = &info->functions[index]; 1168d3e51161SHeiko Stübner 1169d3e51161SHeiko Stübner /* Initialise function */ 1170d3e51161SHeiko Stübner func->name = np->name; 1171d3e51161SHeiko Stübner func->ngroups = of_get_child_count(np); 1172d3e51161SHeiko Stübner if (func->ngroups <= 0) 1173d3e51161SHeiko Stübner return 0; 1174d3e51161SHeiko Stübner 1175d3e51161SHeiko Stübner func->groups = devm_kzalloc(info->dev, 1176d3e51161SHeiko Stübner func->ngroups * sizeof(char *), GFP_KERNEL); 1177d3e51161SHeiko Stübner if (!func->groups) 1178d3e51161SHeiko Stübner return -ENOMEM; 1179d3e51161SHeiko Stübner 1180d3e51161SHeiko Stübner for_each_child_of_node(np, child) { 1181d3e51161SHeiko Stübner func->groups[i] = child->name; 1182d3e51161SHeiko Stübner grp = &info->groups[grp_index++]; 1183d3e51161SHeiko Stübner ret = rockchip_pinctrl_parse_groups(child, grp, info, i++); 1184d3e51161SHeiko Stübner if (ret) 1185d3e51161SHeiko Stübner return ret; 1186d3e51161SHeiko Stübner } 1187d3e51161SHeiko Stübner 1188d3e51161SHeiko Stübner return 0; 1189d3e51161SHeiko Stübner } 1190d3e51161SHeiko Stübner 1191d3e51161SHeiko Stübner static int rockchip_pinctrl_parse_dt(struct platform_device *pdev, 1192d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1193d3e51161SHeiko Stübner { 1194d3e51161SHeiko Stübner struct device *dev = &pdev->dev; 1195d3e51161SHeiko Stübner struct device_node *np = dev->of_node; 1196d3e51161SHeiko Stübner struct device_node *child; 1197d3e51161SHeiko Stübner int ret; 1198d3e51161SHeiko Stübner int i; 1199d3e51161SHeiko Stübner 1200d3e51161SHeiko Stübner rockchip_pinctrl_child_count(info, np); 1201d3e51161SHeiko Stübner 1202d3e51161SHeiko Stübner dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions); 1203d3e51161SHeiko Stübner dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups); 1204d3e51161SHeiko Stübner 1205d3e51161SHeiko Stübner info->functions = devm_kzalloc(dev, info->nfunctions * 1206d3e51161SHeiko Stübner sizeof(struct rockchip_pmx_func), 1207d3e51161SHeiko Stübner GFP_KERNEL); 1208d3e51161SHeiko Stübner if (!info->functions) { 1209d3e51161SHeiko Stübner dev_err(dev, "failed to allocate memory for function list\n"); 1210d3e51161SHeiko Stübner return -EINVAL; 1211d3e51161SHeiko Stübner } 1212d3e51161SHeiko Stübner 1213d3e51161SHeiko Stübner info->groups = devm_kzalloc(dev, info->ngroups * 1214d3e51161SHeiko Stübner sizeof(struct rockchip_pin_group), 1215d3e51161SHeiko Stübner GFP_KERNEL); 1216d3e51161SHeiko Stübner if (!info->groups) { 1217d3e51161SHeiko Stübner dev_err(dev, "failed allocate memory for ping group list\n"); 1218d3e51161SHeiko Stübner return -EINVAL; 1219d3e51161SHeiko Stübner } 1220d3e51161SHeiko Stübner 1221d3e51161SHeiko Stübner i = 0; 1222d3e51161SHeiko Stübner 1223d3e51161SHeiko Stübner for_each_child_of_node(np, child) { 122465fca613SHeiko Stübner if (of_match_node(rockchip_bank_match, child)) 1225d3e51161SHeiko Stübner continue; 122665fca613SHeiko Stübner 1227d3e51161SHeiko Stübner ret = rockchip_pinctrl_parse_functions(child, info, i++); 1228d3e51161SHeiko Stübner if (ret) { 1229d3e51161SHeiko Stübner dev_err(&pdev->dev, "failed to parse function\n"); 1230d3e51161SHeiko Stübner return ret; 1231d3e51161SHeiko Stübner } 1232d3e51161SHeiko Stübner } 1233d3e51161SHeiko Stübner 1234d3e51161SHeiko Stübner return 0; 1235d3e51161SHeiko Stübner } 1236d3e51161SHeiko Stübner 1237d3e51161SHeiko Stübner static int rockchip_pinctrl_register(struct platform_device *pdev, 1238d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1239d3e51161SHeiko Stübner { 1240d3e51161SHeiko Stübner struct pinctrl_desc *ctrldesc = &info->pctl; 1241d3e51161SHeiko Stübner struct pinctrl_pin_desc *pindesc, *pdesc; 1242d3e51161SHeiko Stübner struct rockchip_pin_bank *pin_bank; 1243d3e51161SHeiko Stübner int pin, bank, ret; 1244d3e51161SHeiko Stübner int k; 1245d3e51161SHeiko Stübner 1246d3e51161SHeiko Stübner ctrldesc->name = "rockchip-pinctrl"; 1247d3e51161SHeiko Stübner ctrldesc->owner = THIS_MODULE; 1248d3e51161SHeiko Stübner ctrldesc->pctlops = &rockchip_pctrl_ops; 1249d3e51161SHeiko Stübner ctrldesc->pmxops = &rockchip_pmx_ops; 1250d3e51161SHeiko Stübner ctrldesc->confops = &rockchip_pinconf_ops; 1251d3e51161SHeiko Stübner 1252d3e51161SHeiko Stübner pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * 1253d3e51161SHeiko Stübner info->ctrl->nr_pins, GFP_KERNEL); 1254d3e51161SHeiko Stübner if (!pindesc) { 1255d3e51161SHeiko Stübner dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n"); 1256d3e51161SHeiko Stübner return -ENOMEM; 1257d3e51161SHeiko Stübner } 1258d3e51161SHeiko Stübner ctrldesc->pins = pindesc; 1259d3e51161SHeiko Stübner ctrldesc->npins = info->ctrl->nr_pins; 1260d3e51161SHeiko Stübner 1261d3e51161SHeiko Stübner pdesc = pindesc; 1262d3e51161SHeiko Stübner for (bank = 0 , k = 0; bank < info->ctrl->nr_banks; bank++) { 1263d3e51161SHeiko Stübner pin_bank = &info->ctrl->pin_banks[bank]; 1264d3e51161SHeiko Stübner for (pin = 0; pin < pin_bank->nr_pins; pin++, k++) { 1265d3e51161SHeiko Stübner pdesc->number = k; 1266d3e51161SHeiko Stübner pdesc->name = kasprintf(GFP_KERNEL, "%s-%d", 1267d3e51161SHeiko Stübner pin_bank->name, pin); 1268d3e51161SHeiko Stübner pdesc++; 1269d3e51161SHeiko Stübner } 1270d3e51161SHeiko Stübner } 1271d3e51161SHeiko Stübner 12720fb7dcb1SDoug Anderson ret = rockchip_pinctrl_parse_dt(pdev, info); 12730fb7dcb1SDoug Anderson if (ret) 12740fb7dcb1SDoug Anderson return ret; 12750fb7dcb1SDoug Anderson 1276d3e51161SHeiko Stübner info->pctl_dev = pinctrl_register(ctrldesc, &pdev->dev, info); 1277d3e51161SHeiko Stübner if (!info->pctl_dev) { 1278d3e51161SHeiko Stübner dev_err(&pdev->dev, "could not register pinctrl driver\n"); 1279d3e51161SHeiko Stübner return -EINVAL; 1280d3e51161SHeiko Stübner } 1281d3e51161SHeiko Stübner 1282d3e51161SHeiko Stübner for (bank = 0; bank < info->ctrl->nr_banks; ++bank) { 1283d3e51161SHeiko Stübner pin_bank = &info->ctrl->pin_banks[bank]; 1284d3e51161SHeiko Stübner pin_bank->grange.name = pin_bank->name; 1285d3e51161SHeiko Stübner pin_bank->grange.id = bank; 1286d3e51161SHeiko Stübner pin_bank->grange.pin_base = pin_bank->pin_base; 1287d3e51161SHeiko Stübner pin_bank->grange.base = pin_bank->gpio_chip.base; 1288d3e51161SHeiko Stübner pin_bank->grange.npins = pin_bank->gpio_chip.ngpio; 1289d3e51161SHeiko Stübner pin_bank->grange.gc = &pin_bank->gpio_chip; 1290d3e51161SHeiko Stübner pinctrl_add_gpio_range(info->pctl_dev, &pin_bank->grange); 1291d3e51161SHeiko Stübner } 1292d3e51161SHeiko Stübner 1293d3e51161SHeiko Stübner return 0; 1294d3e51161SHeiko Stübner } 1295d3e51161SHeiko Stübner 1296d3e51161SHeiko Stübner /* 1297d3e51161SHeiko Stübner * GPIO handling 1298d3e51161SHeiko Stübner */ 1299d3e51161SHeiko Stübner 13000351c287SAxel Lin static int rockchip_gpio_request(struct gpio_chip *chip, unsigned offset) 13010351c287SAxel Lin { 13020351c287SAxel Lin return pinctrl_request_gpio(chip->base + offset); 13030351c287SAxel Lin } 13040351c287SAxel Lin 13050351c287SAxel Lin static void rockchip_gpio_free(struct gpio_chip *chip, unsigned offset) 13060351c287SAxel Lin { 13070351c287SAxel Lin pinctrl_free_gpio(chip->base + offset); 13080351c287SAxel Lin } 13090351c287SAxel Lin 1310d3e51161SHeiko Stübner static void rockchip_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 1311d3e51161SHeiko Stübner { 1312d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); 1313d3e51161SHeiko Stübner void __iomem *reg = bank->reg_base + GPIO_SWPORT_DR; 1314d3e51161SHeiko Stübner unsigned long flags; 1315d3e51161SHeiko Stübner u32 data; 1316d3e51161SHeiko Stübner 1317d3e51161SHeiko Stübner spin_lock_irqsave(&bank->slock, flags); 1318d3e51161SHeiko Stübner 1319d3e51161SHeiko Stübner data = readl(reg); 1320d3e51161SHeiko Stübner data &= ~BIT(offset); 1321d3e51161SHeiko Stübner if (value) 1322d3e51161SHeiko Stübner data |= BIT(offset); 1323d3e51161SHeiko Stübner writel(data, reg); 1324d3e51161SHeiko Stübner 1325d3e51161SHeiko Stübner spin_unlock_irqrestore(&bank->slock, flags); 1326d3e51161SHeiko Stübner } 1327d3e51161SHeiko Stübner 1328d3e51161SHeiko Stübner /* 1329d3e51161SHeiko Stübner * Returns the level of the pin for input direction and setting of the DR 1330d3e51161SHeiko Stübner * register for output gpios. 1331d3e51161SHeiko Stübner */ 1332d3e51161SHeiko Stübner static int rockchip_gpio_get(struct gpio_chip *gc, unsigned offset) 1333d3e51161SHeiko Stübner { 1334d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); 1335d3e51161SHeiko Stübner u32 data; 1336d3e51161SHeiko Stübner 1337d3e51161SHeiko Stübner data = readl(bank->reg_base + GPIO_EXT_PORT); 1338d3e51161SHeiko Stübner data >>= offset; 1339d3e51161SHeiko Stübner data &= 1; 1340d3e51161SHeiko Stübner return data; 1341d3e51161SHeiko Stübner } 1342d3e51161SHeiko Stübner 1343d3e51161SHeiko Stübner /* 1344d3e51161SHeiko Stübner * gpiolib gpio_direction_input callback function. The setting of the pin 1345d3e51161SHeiko Stübner * mux function as 'gpio input' will be handled by the pinctrl susbsystem 1346d3e51161SHeiko Stübner * interface. 1347d3e51161SHeiko Stübner */ 1348d3e51161SHeiko Stübner static int rockchip_gpio_direction_input(struct gpio_chip *gc, unsigned offset) 1349d3e51161SHeiko Stübner { 1350d3e51161SHeiko Stübner return pinctrl_gpio_direction_input(gc->base + offset); 1351d3e51161SHeiko Stübner } 1352d3e51161SHeiko Stübner 1353d3e51161SHeiko Stübner /* 1354d3e51161SHeiko Stübner * gpiolib gpio_direction_output callback function. The setting of the pin 1355d3e51161SHeiko Stübner * mux function as 'gpio output' will be handled by the pinctrl susbsystem 1356d3e51161SHeiko Stübner * interface. 1357d3e51161SHeiko Stübner */ 1358d3e51161SHeiko Stübner static int rockchip_gpio_direction_output(struct gpio_chip *gc, 1359d3e51161SHeiko Stübner unsigned offset, int value) 1360d3e51161SHeiko Stübner { 1361d3e51161SHeiko Stübner rockchip_gpio_set(gc, offset, value); 1362d3e51161SHeiko Stübner return pinctrl_gpio_direction_output(gc->base + offset); 1363d3e51161SHeiko Stübner } 1364d3e51161SHeiko Stübner 1365d3e51161SHeiko Stübner /* 1366d3e51161SHeiko Stübner * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin 1367d3e51161SHeiko Stübner * and a virtual IRQ, if not already present. 1368d3e51161SHeiko Stübner */ 1369d3e51161SHeiko Stübner static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset) 1370d3e51161SHeiko Stübner { 1371d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc_to_pin_bank(gc); 1372d3e51161SHeiko Stübner unsigned int virq; 1373d3e51161SHeiko Stübner 1374d3e51161SHeiko Stübner if (!bank->domain) 1375d3e51161SHeiko Stübner return -ENXIO; 1376d3e51161SHeiko Stübner 1377d3e51161SHeiko Stübner virq = irq_create_mapping(bank->domain, offset); 1378d3e51161SHeiko Stübner 1379d3e51161SHeiko Stübner return (virq) ? : -ENXIO; 1380d3e51161SHeiko Stübner } 1381d3e51161SHeiko Stübner 1382d3e51161SHeiko Stübner static const struct gpio_chip rockchip_gpiolib_chip = { 13830351c287SAxel Lin .request = rockchip_gpio_request, 13840351c287SAxel Lin .free = rockchip_gpio_free, 1385d3e51161SHeiko Stübner .set = rockchip_gpio_set, 1386d3e51161SHeiko Stübner .get = rockchip_gpio_get, 1387d3e51161SHeiko Stübner .direction_input = rockchip_gpio_direction_input, 1388d3e51161SHeiko Stübner .direction_output = rockchip_gpio_direction_output, 1389d3e51161SHeiko Stübner .to_irq = rockchip_gpio_to_irq, 1390d3e51161SHeiko Stübner .owner = THIS_MODULE, 1391d3e51161SHeiko Stübner }; 1392d3e51161SHeiko Stübner 1393d3e51161SHeiko Stübner /* 1394d3e51161SHeiko Stübner * Interrupt handling 1395d3e51161SHeiko Stübner */ 1396d3e51161SHeiko Stübner 1397d3e51161SHeiko Stübner static void rockchip_irq_demux(unsigned int irq, struct irq_desc *desc) 1398d3e51161SHeiko Stübner { 1399d3e51161SHeiko Stübner struct irq_chip *chip = irq_get_chip(irq); 1400d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = irq_get_handler_data(irq); 1401d3e51161SHeiko Stübner u32 pend; 1402d3e51161SHeiko Stübner 1403d3e51161SHeiko Stübner dev_dbg(bank->drvdata->dev, "got irq for bank %s\n", bank->name); 1404d3e51161SHeiko Stübner 1405d3e51161SHeiko Stübner chained_irq_enter(chip, desc); 1406d3e51161SHeiko Stübner 1407d3e51161SHeiko Stübner pend = readl_relaxed(bank->reg_base + GPIO_INT_STATUS); 1408d3e51161SHeiko Stübner 1409d3e51161SHeiko Stübner while (pend) { 1410d3e51161SHeiko Stübner unsigned int virq; 1411d3e51161SHeiko Stübner 1412d3e51161SHeiko Stübner irq = __ffs(pend); 1413d3e51161SHeiko Stübner pend &= ~BIT(irq); 1414d3e51161SHeiko Stübner virq = irq_linear_revmap(bank->domain, irq); 1415d3e51161SHeiko Stübner 1416d3e51161SHeiko Stübner if (!virq) { 1417d3e51161SHeiko Stübner dev_err(bank->drvdata->dev, "unmapped irq %d\n", irq); 1418d3e51161SHeiko Stübner continue; 1419d3e51161SHeiko Stübner } 1420d3e51161SHeiko Stübner 1421d3e51161SHeiko Stübner dev_dbg(bank->drvdata->dev, "handling irq %d\n", irq); 1422d3e51161SHeiko Stübner 14235a927501SHeiko Stübner /* 14245a927501SHeiko Stübner * Triggering IRQ on both rising and falling edge 14255a927501SHeiko Stübner * needs manual intervention. 14265a927501SHeiko Stübner */ 14275a927501SHeiko Stübner if (bank->toggle_edge_mode & BIT(irq)) { 1428*53b1bfc7SDoug Anderson u32 data, data_old, polarity; 1429*53b1bfc7SDoug Anderson unsigned long flags; 1430*53b1bfc7SDoug Anderson 1431*53b1bfc7SDoug Anderson data = readl_relaxed(bank->reg_base + GPIO_EXT_PORT); 1432*53b1bfc7SDoug Anderson do { 1433*53b1bfc7SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 1434*53b1bfc7SDoug Anderson 1435*53b1bfc7SDoug Anderson polarity = readl_relaxed(bank->reg_base + 1436*53b1bfc7SDoug Anderson GPIO_INT_POLARITY); 14375a927501SHeiko Stübner if (data & BIT(irq)) 14385a927501SHeiko Stübner polarity &= ~BIT(irq); 14395a927501SHeiko Stübner else 14405a927501SHeiko Stübner polarity |= BIT(irq); 1441*53b1bfc7SDoug Anderson writel(polarity, 1442*53b1bfc7SDoug Anderson bank->reg_base + GPIO_INT_POLARITY); 14435a927501SHeiko Stübner 1444*53b1bfc7SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 1445*53b1bfc7SDoug Anderson 1446*53b1bfc7SDoug Anderson data_old = data; 1447*53b1bfc7SDoug Anderson data = readl_relaxed(bank->reg_base + 1448*53b1bfc7SDoug Anderson GPIO_EXT_PORT); 1449*53b1bfc7SDoug Anderson } while ((data & BIT(irq)) != (data_old & BIT(irq))); 14505a927501SHeiko Stübner } 14515a927501SHeiko Stübner 1452d3e51161SHeiko Stübner generic_handle_irq(virq); 1453d3e51161SHeiko Stübner } 1454d3e51161SHeiko Stübner 1455d3e51161SHeiko Stübner chained_irq_exit(chip, desc); 1456d3e51161SHeiko Stübner } 1457d3e51161SHeiko Stübner 1458d3e51161SHeiko Stübner static int rockchip_irq_set_type(struct irq_data *d, unsigned int type) 1459d3e51161SHeiko Stübner { 1460d3e51161SHeiko Stübner struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 1461d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = gc->private; 1462d3e51161SHeiko Stübner u32 mask = BIT(d->hwirq); 1463d3e51161SHeiko Stübner u32 polarity; 1464d3e51161SHeiko Stübner u32 level; 1465d3e51161SHeiko Stübner u32 data; 1466fab262f5SDoug Anderson unsigned long flags; 146714797189SHeiko Stübner int ret; 1468d3e51161SHeiko Stübner 14695a927501SHeiko Stübner /* make sure the pin is configured as gpio input */ 147014797189SHeiko Stübner ret = rockchip_set_mux(bank, d->hwirq, RK_FUNC_GPIO); 147114797189SHeiko Stübner if (ret < 0) 147214797189SHeiko Stübner return ret; 147314797189SHeiko Stübner 1474fab262f5SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 1475fab262f5SDoug Anderson 14765a927501SHeiko Stübner data = readl_relaxed(bank->reg_base + GPIO_SWPORT_DDR); 14775a927501SHeiko Stübner data &= ~mask; 14785a927501SHeiko Stübner writel_relaxed(data, bank->reg_base + GPIO_SWPORT_DDR); 14795a927501SHeiko Stübner 1480fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 1481fab262f5SDoug Anderson 1482d3e51161SHeiko Stübner if (type & IRQ_TYPE_EDGE_BOTH) 1483d3e51161SHeiko Stübner __irq_set_handler_locked(d->irq, handle_edge_irq); 1484d3e51161SHeiko Stübner else 1485d3e51161SHeiko Stübner __irq_set_handler_locked(d->irq, handle_level_irq); 1486d3e51161SHeiko Stübner 1487fab262f5SDoug Anderson spin_lock_irqsave(&bank->slock, flags); 1488d3e51161SHeiko Stübner irq_gc_lock(gc); 1489d3e51161SHeiko Stübner 1490d3e51161SHeiko Stübner level = readl_relaxed(gc->reg_base + GPIO_INTTYPE_LEVEL); 1491d3e51161SHeiko Stübner polarity = readl_relaxed(gc->reg_base + GPIO_INT_POLARITY); 1492d3e51161SHeiko Stübner 1493d3e51161SHeiko Stübner switch (type) { 14945a927501SHeiko Stübner case IRQ_TYPE_EDGE_BOTH: 14955a927501SHeiko Stübner bank->toggle_edge_mode |= mask; 14965a927501SHeiko Stübner level |= mask; 14975a927501SHeiko Stübner 14985a927501SHeiko Stübner /* 14995a927501SHeiko Stübner * Determine gpio state. If 1 next interrupt should be falling 15005a927501SHeiko Stübner * otherwise rising. 15015a927501SHeiko Stübner */ 15025a927501SHeiko Stübner data = readl(bank->reg_base + GPIO_EXT_PORT); 15035a927501SHeiko Stübner if (data & mask) 15045a927501SHeiko Stübner polarity &= ~mask; 15055a927501SHeiko Stübner else 15065a927501SHeiko Stübner polarity |= mask; 15075a927501SHeiko Stübner break; 1508d3e51161SHeiko Stübner case IRQ_TYPE_EDGE_RISING: 15095a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1510d3e51161SHeiko Stübner level |= mask; 1511d3e51161SHeiko Stübner polarity |= mask; 1512d3e51161SHeiko Stübner break; 1513d3e51161SHeiko Stübner case IRQ_TYPE_EDGE_FALLING: 15145a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1515d3e51161SHeiko Stübner level |= mask; 1516d3e51161SHeiko Stübner polarity &= ~mask; 1517d3e51161SHeiko Stübner break; 1518d3e51161SHeiko Stübner case IRQ_TYPE_LEVEL_HIGH: 15195a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1520d3e51161SHeiko Stübner level &= ~mask; 1521d3e51161SHeiko Stübner polarity |= mask; 1522d3e51161SHeiko Stübner break; 1523d3e51161SHeiko Stübner case IRQ_TYPE_LEVEL_LOW: 15245a927501SHeiko Stübner bank->toggle_edge_mode &= ~mask; 1525d3e51161SHeiko Stübner level &= ~mask; 1526d3e51161SHeiko Stübner polarity &= ~mask; 1527d3e51161SHeiko Stübner break; 1528d3e51161SHeiko Stübner default: 15297cc5f970SAxel Lin irq_gc_unlock(gc); 1530fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 1531d3e51161SHeiko Stübner return -EINVAL; 1532d3e51161SHeiko Stübner } 1533d3e51161SHeiko Stübner 1534d3e51161SHeiko Stübner writel_relaxed(level, gc->reg_base + GPIO_INTTYPE_LEVEL); 1535d3e51161SHeiko Stübner writel_relaxed(polarity, gc->reg_base + GPIO_INT_POLARITY); 1536d3e51161SHeiko Stübner 1537d3e51161SHeiko Stübner irq_gc_unlock(gc); 1538fab262f5SDoug Anderson spin_unlock_irqrestore(&bank->slock, flags); 1539d3e51161SHeiko Stübner 1540d3e51161SHeiko Stübner return 0; 1541d3e51161SHeiko Stübner } 1542d3e51161SHeiko Stübner 154368bda47cSDoug Anderson static void rockchip_irq_suspend(struct irq_data *d) 154468bda47cSDoug Anderson { 154568bda47cSDoug Anderson struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 154668bda47cSDoug Anderson struct rockchip_pin_bank *bank = gc->private; 154768bda47cSDoug Anderson 154868bda47cSDoug Anderson bank->saved_enables = irq_reg_readl(gc, GPIO_INTEN); 154968bda47cSDoug Anderson irq_reg_writel(gc, gc->wake_active, GPIO_INTEN); 155068bda47cSDoug Anderson } 155168bda47cSDoug Anderson 155268bda47cSDoug Anderson static void rockchip_irq_resume(struct irq_data *d) 155368bda47cSDoug Anderson { 155468bda47cSDoug Anderson struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 155568bda47cSDoug Anderson struct rockchip_pin_bank *bank = gc->private; 155668bda47cSDoug Anderson 155768bda47cSDoug Anderson irq_reg_writel(gc, bank->saved_enables, GPIO_INTEN); 155868bda47cSDoug Anderson } 155968bda47cSDoug Anderson 1560f2dd028cSDoug Anderson static void rockchip_irq_disable(struct irq_data *d) 1561f2dd028cSDoug Anderson { 1562f2dd028cSDoug Anderson struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 1563f2dd028cSDoug Anderson u32 val; 1564f2dd028cSDoug Anderson 1565f2dd028cSDoug Anderson irq_gc_lock(gc); 1566f2dd028cSDoug Anderson 1567f2dd028cSDoug Anderson val = irq_reg_readl(gc, GPIO_INTEN); 1568f2dd028cSDoug Anderson val &= ~d->mask; 1569f2dd028cSDoug Anderson irq_reg_writel(gc, val, GPIO_INTEN); 1570f2dd028cSDoug Anderson 1571f2dd028cSDoug Anderson irq_gc_unlock(gc); 1572f2dd028cSDoug Anderson } 1573f2dd028cSDoug Anderson 1574f2dd028cSDoug Anderson static void rockchip_irq_enable(struct irq_data *d) 1575f2dd028cSDoug Anderson { 1576f2dd028cSDoug Anderson struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 1577f2dd028cSDoug Anderson u32 val; 1578f2dd028cSDoug Anderson 1579f2dd028cSDoug Anderson irq_gc_lock(gc); 1580f2dd028cSDoug Anderson 1581f2dd028cSDoug Anderson val = irq_reg_readl(gc, GPIO_INTEN); 1582f2dd028cSDoug Anderson val |= d->mask; 1583f2dd028cSDoug Anderson irq_reg_writel(gc, val, GPIO_INTEN); 1584f2dd028cSDoug Anderson 1585f2dd028cSDoug Anderson irq_gc_unlock(gc); 1586f2dd028cSDoug Anderson } 1587f2dd028cSDoug Anderson 1588d3e51161SHeiko Stübner static int rockchip_interrupts_register(struct platform_device *pdev, 1589d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1590d3e51161SHeiko Stübner { 1591d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 1592d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = ctrl->pin_banks; 1593d3e51161SHeiko Stübner unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; 1594d3e51161SHeiko Stübner struct irq_chip_generic *gc; 1595d3e51161SHeiko Stübner int ret; 1596d3e51161SHeiko Stübner int i; 1597d3e51161SHeiko Stübner 1598d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1599d3e51161SHeiko Stübner if (!bank->valid) { 1600d3e51161SHeiko Stübner dev_warn(&pdev->dev, "bank %s is not valid\n", 1601d3e51161SHeiko Stübner bank->name); 1602d3e51161SHeiko Stübner continue; 1603d3e51161SHeiko Stübner } 1604d3e51161SHeiko Stübner 1605d3e51161SHeiko Stübner bank->domain = irq_domain_add_linear(bank->of_node, 32, 1606d3e51161SHeiko Stübner &irq_generic_chip_ops, NULL); 1607d3e51161SHeiko Stübner if (!bank->domain) { 1608d3e51161SHeiko Stübner dev_warn(&pdev->dev, "could not initialize irq domain for bank %s\n", 1609d3e51161SHeiko Stübner bank->name); 1610d3e51161SHeiko Stübner continue; 1611d3e51161SHeiko Stübner } 1612d3e51161SHeiko Stübner 1613d3e51161SHeiko Stübner ret = irq_alloc_domain_generic_chips(bank->domain, 32, 1, 1614d3e51161SHeiko Stübner "rockchip_gpio_irq", handle_level_irq, 1615d3e51161SHeiko Stübner clr, 0, IRQ_GC_INIT_MASK_CACHE); 1616d3e51161SHeiko Stübner if (ret) { 1617d3e51161SHeiko Stübner dev_err(&pdev->dev, "could not alloc generic chips for bank %s\n", 1618d3e51161SHeiko Stübner bank->name); 1619d3e51161SHeiko Stübner irq_domain_remove(bank->domain); 1620d3e51161SHeiko Stübner continue; 1621d3e51161SHeiko Stübner } 1622d3e51161SHeiko Stübner 1623d3e51161SHeiko Stübner gc = irq_get_domain_generic_chip(bank->domain, 0); 1624d3e51161SHeiko Stübner gc->reg_base = bank->reg_base; 1625d3e51161SHeiko Stübner gc->private = bank; 1626f2dd028cSDoug Anderson gc->chip_types[0].regs.mask = GPIO_INTMASK; 1627d3e51161SHeiko Stübner gc->chip_types[0].regs.ack = GPIO_PORTS_EOI; 1628d3e51161SHeiko Stübner gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; 1629f2dd028cSDoug Anderson gc->chip_types[0].chip.irq_mask = irq_gc_mask_set_bit; 1630f2dd028cSDoug Anderson gc->chip_types[0].chip.irq_unmask = irq_gc_mask_clr_bit; 1631f2dd028cSDoug Anderson gc->chip_types[0].chip.irq_enable = rockchip_irq_enable; 1632f2dd028cSDoug Anderson gc->chip_types[0].chip.irq_disable = rockchip_irq_disable; 1633d3e51161SHeiko Stübner gc->chip_types[0].chip.irq_set_wake = irq_gc_set_wake; 163468bda47cSDoug Anderson gc->chip_types[0].chip.irq_suspend = rockchip_irq_suspend; 163568bda47cSDoug Anderson gc->chip_types[0].chip.irq_resume = rockchip_irq_resume; 1636d3e51161SHeiko Stübner gc->chip_types[0].chip.irq_set_type = rockchip_irq_set_type; 1637876d716bSDoug Anderson gc->wake_enabled = IRQ_MSK(bank->nr_pins); 1638d3e51161SHeiko Stübner 1639d3e51161SHeiko Stübner irq_set_handler_data(bank->irq, bank); 1640d3e51161SHeiko Stübner irq_set_chained_handler(bank->irq, rockchip_irq_demux); 1641d3e51161SHeiko Stübner } 1642d3e51161SHeiko Stübner 1643d3e51161SHeiko Stübner return 0; 1644d3e51161SHeiko Stübner } 1645d3e51161SHeiko Stübner 1646d3e51161SHeiko Stübner static int rockchip_gpiolib_register(struct platform_device *pdev, 1647d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1648d3e51161SHeiko Stübner { 1649d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 1650d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = ctrl->pin_banks; 1651d3e51161SHeiko Stübner struct gpio_chip *gc; 1652d3e51161SHeiko Stübner int ret; 1653d3e51161SHeiko Stübner int i; 1654d3e51161SHeiko Stübner 1655d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1656d3e51161SHeiko Stübner if (!bank->valid) { 1657d3e51161SHeiko Stübner dev_warn(&pdev->dev, "bank %s is not valid\n", 1658d3e51161SHeiko Stübner bank->name); 1659d3e51161SHeiko Stübner continue; 1660d3e51161SHeiko Stübner } 1661d3e51161SHeiko Stübner 1662d3e51161SHeiko Stübner bank->gpio_chip = rockchip_gpiolib_chip; 1663d3e51161SHeiko Stübner 1664d3e51161SHeiko Stübner gc = &bank->gpio_chip; 1665d3e51161SHeiko Stübner gc->base = bank->pin_base; 1666d3e51161SHeiko Stübner gc->ngpio = bank->nr_pins; 1667d3e51161SHeiko Stübner gc->dev = &pdev->dev; 1668d3e51161SHeiko Stübner gc->of_node = bank->of_node; 1669d3e51161SHeiko Stübner gc->label = bank->name; 1670d3e51161SHeiko Stübner 1671d3e51161SHeiko Stübner ret = gpiochip_add(gc); 1672d3e51161SHeiko Stübner if (ret) { 1673d3e51161SHeiko Stübner dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n", 1674d3e51161SHeiko Stübner gc->label, ret); 1675d3e51161SHeiko Stübner goto fail; 1676d3e51161SHeiko Stübner } 1677d3e51161SHeiko Stübner } 1678d3e51161SHeiko Stübner 1679d3e51161SHeiko Stübner rockchip_interrupts_register(pdev, info); 1680d3e51161SHeiko Stübner 1681d3e51161SHeiko Stübner return 0; 1682d3e51161SHeiko Stübner 1683d3e51161SHeiko Stübner fail: 1684d3e51161SHeiko Stübner for (--i, --bank; i >= 0; --i, --bank) { 1685d3e51161SHeiko Stübner if (!bank->valid) 1686d3e51161SHeiko Stübner continue; 1687b4e7c55dSabdoulaye berthe gpiochip_remove(&bank->gpio_chip); 1688d3e51161SHeiko Stübner } 1689d3e51161SHeiko Stübner return ret; 1690d3e51161SHeiko Stübner } 1691d3e51161SHeiko Stübner 1692d3e51161SHeiko Stübner static int rockchip_gpiolib_unregister(struct platform_device *pdev, 1693d3e51161SHeiko Stübner struct rockchip_pinctrl *info) 1694d3e51161SHeiko Stübner { 1695d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl = info->ctrl; 1696d3e51161SHeiko Stübner struct rockchip_pin_bank *bank = ctrl->pin_banks; 1697d3e51161SHeiko Stübner int i; 1698d3e51161SHeiko Stübner 1699b4e7c55dSabdoulaye berthe for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1700d3e51161SHeiko Stübner if (!bank->valid) 1701d3e51161SHeiko Stübner continue; 1702b4e7c55dSabdoulaye berthe gpiochip_remove(&bank->gpio_chip); 1703d3e51161SHeiko Stübner } 1704d3e51161SHeiko Stübner 1705b4e7c55dSabdoulaye berthe return 0; 1706d3e51161SHeiko Stübner } 1707d3e51161SHeiko Stübner 1708d3e51161SHeiko Stübner static int rockchip_get_bank_data(struct rockchip_pin_bank *bank, 1709622f3237SHeiko Stübner struct rockchip_pinctrl *info) 1710d3e51161SHeiko Stübner { 1711d3e51161SHeiko Stübner struct resource res; 1712751a99abSHeiko Stübner void __iomem *base; 1713d3e51161SHeiko Stübner 1714d3e51161SHeiko Stübner if (of_address_to_resource(bank->of_node, 0, &res)) { 1715622f3237SHeiko Stübner dev_err(info->dev, "cannot find IO resource for bank\n"); 1716d3e51161SHeiko Stübner return -ENOENT; 1717d3e51161SHeiko Stübner } 1718d3e51161SHeiko Stübner 1719622f3237SHeiko Stübner bank->reg_base = devm_ioremap_resource(info->dev, &res); 1720d3e51161SHeiko Stübner if (IS_ERR(bank->reg_base)) 1721d3e51161SHeiko Stübner return PTR_ERR(bank->reg_base); 1722d3e51161SHeiko Stübner 17236ca5274dSHeiko Stübner /* 17246ca5274dSHeiko Stübner * special case, where parts of the pull setting-registers are 17256ca5274dSHeiko Stübner * part of the PMU register space 17266ca5274dSHeiko Stübner */ 17276ca5274dSHeiko Stübner if (of_device_is_compatible(bank->of_node, 17286ca5274dSHeiko Stübner "rockchip,rk3188-gpio-bank0")) { 1729a658efaaSHeiko Stübner struct device_node *node; 1730bfc7a42aSHeiko Stübner 1731a658efaaSHeiko Stübner node = of_parse_phandle(bank->of_node->parent, 1732a658efaaSHeiko Stübner "rockchip,pmu", 0); 1733a658efaaSHeiko Stübner if (!node) { 17346ca5274dSHeiko Stübner if (of_address_to_resource(bank->of_node, 1, &res)) { 1735622f3237SHeiko Stübner dev_err(info->dev, "cannot find IO resource for bank\n"); 17366ca5274dSHeiko Stübner return -ENOENT; 17376ca5274dSHeiko Stübner } 17386ca5274dSHeiko Stübner 1739622f3237SHeiko Stübner base = devm_ioremap_resource(info->dev, &res); 1740751a99abSHeiko Stübner if (IS_ERR(base)) 1741751a99abSHeiko Stübner return PTR_ERR(base); 1742a658efaaSHeiko Stübner rockchip_regmap_config.max_register = 1743a658efaaSHeiko Stübner resource_size(&res) - 4; 1744a658efaaSHeiko Stübner rockchip_regmap_config.name = 1745a658efaaSHeiko Stübner "rockchip,rk3188-gpio-bank0-pull"; 1746a658efaaSHeiko Stübner bank->regmap_pull = devm_regmap_init_mmio(info->dev, 1747a658efaaSHeiko Stübner base, 1748751a99abSHeiko Stübner &rockchip_regmap_config); 1749a658efaaSHeiko Stübner } 17506ca5274dSHeiko Stübner } 175165fca613SHeiko Stübner 1752d3e51161SHeiko Stübner bank->irq = irq_of_parse_and_map(bank->of_node, 0); 1753d3e51161SHeiko Stübner 1754d3e51161SHeiko Stübner bank->clk = of_clk_get(bank->of_node, 0); 1755d3e51161SHeiko Stübner if (IS_ERR(bank->clk)) 1756d3e51161SHeiko Stübner return PTR_ERR(bank->clk); 1757d3e51161SHeiko Stübner 1758d3e51161SHeiko Stübner return clk_prepare_enable(bank->clk); 1759d3e51161SHeiko Stübner } 1760d3e51161SHeiko Stübner 1761d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[]; 1762d3e51161SHeiko Stübner 1763d3e51161SHeiko Stübner /* retrieve the soc specific data */ 1764d3e51161SHeiko Stübner static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data( 1765d3e51161SHeiko Stübner struct rockchip_pinctrl *d, 1766d3e51161SHeiko Stübner struct platform_device *pdev) 1767d3e51161SHeiko Stübner { 1768d3e51161SHeiko Stübner const struct of_device_id *match; 1769d3e51161SHeiko Stübner struct device_node *node = pdev->dev.of_node; 1770d3e51161SHeiko Stübner struct device_node *np; 1771d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl; 1772d3e51161SHeiko Stübner struct rockchip_pin_bank *bank; 177395ec8ae4SHeiko Stübner int grf_offs, pmu_offs, i, j; 1774d3e51161SHeiko Stübner 1775d3e51161SHeiko Stübner match = of_match_node(rockchip_pinctrl_dt_match, node); 1776d3e51161SHeiko Stübner ctrl = (struct rockchip_pin_ctrl *)match->data; 1777d3e51161SHeiko Stübner 1778d3e51161SHeiko Stübner for_each_child_of_node(node, np) { 1779d3e51161SHeiko Stübner if (!of_find_property(np, "gpio-controller", NULL)) 1780d3e51161SHeiko Stübner continue; 1781d3e51161SHeiko Stübner 1782d3e51161SHeiko Stübner bank = ctrl->pin_banks; 1783d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 1784d3e51161SHeiko Stübner if (!strcmp(bank->name, np->name)) { 1785d3e51161SHeiko Stübner bank->of_node = np; 1786d3e51161SHeiko Stübner 1787622f3237SHeiko Stübner if (!rockchip_get_bank_data(bank, d)) 1788d3e51161SHeiko Stübner bank->valid = true; 1789d3e51161SHeiko Stübner 1790d3e51161SHeiko Stübner break; 1791d3e51161SHeiko Stübner } 1792d3e51161SHeiko Stübner } 1793d3e51161SHeiko Stübner } 1794d3e51161SHeiko Stübner 179595ec8ae4SHeiko Stübner grf_offs = ctrl->grf_mux_offset; 179695ec8ae4SHeiko Stübner pmu_offs = ctrl->pmu_mux_offset; 1797d3e51161SHeiko Stübner bank = ctrl->pin_banks; 1798d3e51161SHeiko Stübner for (i = 0; i < ctrl->nr_banks; ++i, ++bank) { 17996bc0d121SHeiko Stübner int bank_pins = 0; 18006bc0d121SHeiko Stübner 1801d3e51161SHeiko Stübner spin_lock_init(&bank->slock); 1802d3e51161SHeiko Stübner bank->drvdata = d; 1803d3e51161SHeiko Stübner bank->pin_base = ctrl->nr_pins; 1804d3e51161SHeiko Stübner ctrl->nr_pins += bank->nr_pins; 18056bc0d121SHeiko Stübner 18066bc0d121SHeiko Stübner /* calculate iomux offsets */ 18076bc0d121SHeiko Stübner for (j = 0; j < 4; j++) { 18086bc0d121SHeiko Stübner struct rockchip_iomux *iom = &bank->iomux[j]; 180903716e1dSHeiko Stübner int inc; 18106bc0d121SHeiko Stübner 18116bc0d121SHeiko Stübner if (bank_pins >= bank->nr_pins) 18126bc0d121SHeiko Stübner break; 18136bc0d121SHeiko Stübner 18146bc0d121SHeiko Stübner /* preset offset value, set new start value */ 18156bc0d121SHeiko Stübner if (iom->offset >= 0) { 181695ec8ae4SHeiko Stübner if (iom->type & IOMUX_SOURCE_PMU) 181795ec8ae4SHeiko Stübner pmu_offs = iom->offset; 181895ec8ae4SHeiko Stübner else 18196bc0d121SHeiko Stübner grf_offs = iom->offset; 18206bc0d121SHeiko Stübner } else { /* set current offset */ 182195ec8ae4SHeiko Stübner iom->offset = (iom->type & IOMUX_SOURCE_PMU) ? 182295ec8ae4SHeiko Stübner pmu_offs : grf_offs; 18236bc0d121SHeiko Stübner } 18246bc0d121SHeiko Stübner 18256bc0d121SHeiko Stübner dev_dbg(d->dev, "bank %d, iomux %d has offset 0x%x\n", 18266bc0d121SHeiko Stübner i, j, iom->offset); 18276bc0d121SHeiko Stübner 18286bc0d121SHeiko Stübner /* 18296bc0d121SHeiko Stübner * Increase offset according to iomux width. 183003716e1dSHeiko Stübner * 4bit iomux'es are spread over two registers. 18316bc0d121SHeiko Stübner */ 183203716e1dSHeiko Stübner inc = (iom->type & IOMUX_WIDTH_4BIT) ? 8 : 4; 183395ec8ae4SHeiko Stübner if (iom->type & IOMUX_SOURCE_PMU) 183495ec8ae4SHeiko Stübner pmu_offs += inc; 183595ec8ae4SHeiko Stübner else 183603716e1dSHeiko Stübner grf_offs += inc; 18376bc0d121SHeiko Stübner 18386bc0d121SHeiko Stübner bank_pins += 8; 18396bc0d121SHeiko Stübner } 1840d3e51161SHeiko Stübner } 1841d3e51161SHeiko Stübner 1842d3e51161SHeiko Stübner return ctrl; 1843d3e51161SHeiko Stübner } 1844d3e51161SHeiko Stübner 18458dca9331SChris Zhong #define RK3288_GRF_GPIO6C_IOMUX 0x64 18468dca9331SChris Zhong #define GPIO6C6_SEL_WRITE_ENABLE BIT(28) 18478dca9331SChris Zhong 18488dca9331SChris Zhong static u32 rk3288_grf_gpio6c_iomux; 18498dca9331SChris Zhong 18509198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev) 18519198f509SChris Zhong { 18529198f509SChris Zhong struct rockchip_pinctrl *info = dev_get_drvdata(dev); 18538dca9331SChris Zhong int ret = pinctrl_force_sleep(info->pctl_dev); 18549198f509SChris Zhong 18558dca9331SChris Zhong if (ret) 18568dca9331SChris Zhong return ret; 18578dca9331SChris Zhong 18588dca9331SChris Zhong /* 18598dca9331SChris Zhong * RK3288 GPIO6_C6 mux would be modified by Maskrom when resume, so save 18608dca9331SChris Zhong * the setting here, and restore it at resume. 18618dca9331SChris Zhong */ 18628dca9331SChris Zhong if (info->ctrl->type == RK3288) { 18638dca9331SChris Zhong ret = regmap_read(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, 18648dca9331SChris Zhong &rk3288_grf_gpio6c_iomux); 18658dca9331SChris Zhong if (ret) { 18668dca9331SChris Zhong pinctrl_force_default(info->pctl_dev); 18678dca9331SChris Zhong return ret; 18688dca9331SChris Zhong } 18698dca9331SChris Zhong } 18708dca9331SChris Zhong 18718dca9331SChris Zhong return 0; 18729198f509SChris Zhong } 18739198f509SChris Zhong 18749198f509SChris Zhong static int __maybe_unused rockchip_pinctrl_resume(struct device *dev) 18759198f509SChris Zhong { 18769198f509SChris Zhong struct rockchip_pinctrl *info = dev_get_drvdata(dev); 18778dca9331SChris Zhong int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, 18788dca9331SChris Zhong rk3288_grf_gpio6c_iomux | 18798dca9331SChris Zhong GPIO6C6_SEL_WRITE_ENABLE); 18808dca9331SChris Zhong 18818dca9331SChris Zhong if (ret) 18828dca9331SChris Zhong return ret; 18839198f509SChris Zhong 18849198f509SChris Zhong return pinctrl_force_default(info->pctl_dev); 18859198f509SChris Zhong } 18869198f509SChris Zhong 18879198f509SChris Zhong static SIMPLE_DEV_PM_OPS(rockchip_pinctrl_dev_pm_ops, rockchip_pinctrl_suspend, 18889198f509SChris Zhong rockchip_pinctrl_resume); 18899198f509SChris Zhong 1890d3e51161SHeiko Stübner static int rockchip_pinctrl_probe(struct platform_device *pdev) 1891d3e51161SHeiko Stübner { 1892d3e51161SHeiko Stübner struct rockchip_pinctrl *info; 1893d3e51161SHeiko Stübner struct device *dev = &pdev->dev; 1894d3e51161SHeiko Stübner struct rockchip_pin_ctrl *ctrl; 189514dee867SHeiko Stübner struct device_node *np = pdev->dev.of_node, *node; 1896d3e51161SHeiko Stübner struct resource *res; 1897751a99abSHeiko Stübner void __iomem *base; 1898d3e51161SHeiko Stübner int ret; 1899d3e51161SHeiko Stübner 1900d3e51161SHeiko Stübner if (!dev->of_node) { 1901d3e51161SHeiko Stübner dev_err(dev, "device tree node not found\n"); 1902d3e51161SHeiko Stübner return -ENODEV; 1903d3e51161SHeiko Stübner } 1904d3e51161SHeiko Stübner 1905d3e51161SHeiko Stübner info = devm_kzalloc(dev, sizeof(struct rockchip_pinctrl), GFP_KERNEL); 1906d3e51161SHeiko Stübner if (!info) 1907d3e51161SHeiko Stübner return -ENOMEM; 1908d3e51161SHeiko Stübner 1909622f3237SHeiko Stübner info->dev = dev; 1910622f3237SHeiko Stübner 1911d3e51161SHeiko Stübner ctrl = rockchip_pinctrl_get_soc_data(info, pdev); 1912d3e51161SHeiko Stübner if (!ctrl) { 1913d3e51161SHeiko Stübner dev_err(dev, "driver data not available\n"); 1914d3e51161SHeiko Stübner return -EINVAL; 1915d3e51161SHeiko Stübner } 1916d3e51161SHeiko Stübner info->ctrl = ctrl; 1917d3e51161SHeiko Stübner 19181e747e59SHeiko Stübner node = of_parse_phandle(np, "rockchip,grf", 0); 19191e747e59SHeiko Stübner if (node) { 19201e747e59SHeiko Stübner info->regmap_base = syscon_node_to_regmap(node); 19211e747e59SHeiko Stübner if (IS_ERR(info->regmap_base)) 19221e747e59SHeiko Stübner return PTR_ERR(info->regmap_base); 19231e747e59SHeiko Stübner } else { 1924d3e51161SHeiko Stübner res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1925751a99abSHeiko Stübner base = devm_ioremap_resource(&pdev->dev, res); 1926751a99abSHeiko Stübner if (IS_ERR(base)) 1927751a99abSHeiko Stübner return PTR_ERR(base); 1928751a99abSHeiko Stübner 1929751a99abSHeiko Stübner rockchip_regmap_config.max_register = resource_size(res) - 4; 1930751a99abSHeiko Stübner rockchip_regmap_config.name = "rockchip,pinctrl"; 1931751a99abSHeiko Stübner info->regmap_base = devm_regmap_init_mmio(&pdev->dev, base, 1932751a99abSHeiko Stübner &rockchip_regmap_config); 1933d3e51161SHeiko Stübner 1934bfc7a42aSHeiko Stübner /* to check for the old dt-bindings */ 1935bfc7a42aSHeiko Stübner info->reg_size = resource_size(res); 1936bfc7a42aSHeiko Stübner 1937bfc7a42aSHeiko Stübner /* Honor the old binding, with pull registers as 2nd resource */ 1938bfc7a42aSHeiko Stübner if (ctrl->type == RK3188 && info->reg_size < 0x200) { 19396ca5274dSHeiko Stübner res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 1940751a99abSHeiko Stübner base = devm_ioremap_resource(&pdev->dev, res); 1941751a99abSHeiko Stübner if (IS_ERR(base)) 1942751a99abSHeiko Stübner return PTR_ERR(base); 1943751a99abSHeiko Stübner 19441e747e59SHeiko Stübner rockchip_regmap_config.max_register = 19451e747e59SHeiko Stübner resource_size(res) - 4; 1946751a99abSHeiko Stübner rockchip_regmap_config.name = "rockchip,pinctrl-pull"; 19471e747e59SHeiko Stübner info->regmap_pull = devm_regmap_init_mmio(&pdev->dev, 19481e747e59SHeiko Stübner base, 1949751a99abSHeiko Stübner &rockchip_regmap_config); 19506ca5274dSHeiko Stübner } 19511e747e59SHeiko Stübner } 19526ca5274dSHeiko Stübner 195314dee867SHeiko Stübner /* try to find the optional reference to the pmu syscon */ 195414dee867SHeiko Stübner node = of_parse_phandle(np, "rockchip,pmu", 0); 195514dee867SHeiko Stübner if (node) { 195614dee867SHeiko Stübner info->regmap_pmu = syscon_node_to_regmap(node); 195714dee867SHeiko Stübner if (IS_ERR(info->regmap_pmu)) 195814dee867SHeiko Stübner return PTR_ERR(info->regmap_pmu); 195914dee867SHeiko Stübner } 196014dee867SHeiko Stübner 1961d3e51161SHeiko Stübner ret = rockchip_gpiolib_register(pdev, info); 1962d3e51161SHeiko Stübner if (ret) 1963d3e51161SHeiko Stübner return ret; 1964d3e51161SHeiko Stübner 1965d3e51161SHeiko Stübner ret = rockchip_pinctrl_register(pdev, info); 1966d3e51161SHeiko Stübner if (ret) { 1967d3e51161SHeiko Stübner rockchip_gpiolib_unregister(pdev, info); 1968d3e51161SHeiko Stübner return ret; 1969d3e51161SHeiko Stübner } 1970d3e51161SHeiko Stübner 1971d3e51161SHeiko Stübner platform_set_drvdata(pdev, info); 1972d3e51161SHeiko Stübner 1973d3e51161SHeiko Stübner return 0; 1974d3e51161SHeiko Stübner } 1975d3e51161SHeiko Stübner 1976d3e51161SHeiko Stübner static struct rockchip_pin_bank rk2928_pin_banks[] = { 1977d3e51161SHeiko Stübner PIN_BANK(0, 32, "gpio0"), 1978d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 1979d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 1980d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 1981d3e51161SHeiko Stübner }; 1982d3e51161SHeiko Stübner 1983d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk2928_pin_ctrl = { 1984d3e51161SHeiko Stübner .pin_banks = rk2928_pin_banks, 1985d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk2928_pin_banks), 1986d3e51161SHeiko Stübner .label = "RK2928-GPIO", 1987a282926dSHeiko Stübner .type = RK2928, 198895ec8ae4SHeiko Stübner .grf_mux_offset = 0xa8, 1989a282926dSHeiko Stübner .pull_calc_reg = rk2928_calc_pull_reg_and_bit, 1990d3e51161SHeiko Stübner }; 1991d3e51161SHeiko Stübner 1992d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066a_pin_banks[] = { 1993d3e51161SHeiko Stübner PIN_BANK(0, 32, "gpio0"), 1994d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 1995d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 1996d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 1997d3e51161SHeiko Stübner PIN_BANK(4, 32, "gpio4"), 1998d3e51161SHeiko Stübner PIN_BANK(6, 16, "gpio6"), 1999d3e51161SHeiko Stübner }; 2000d3e51161SHeiko Stübner 2001d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066a_pin_ctrl = { 2002d3e51161SHeiko Stübner .pin_banks = rk3066a_pin_banks, 2003d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk3066a_pin_banks), 2004d3e51161SHeiko Stübner .label = "RK3066a-GPIO", 2005a282926dSHeiko Stübner .type = RK2928, 200695ec8ae4SHeiko Stübner .grf_mux_offset = 0xa8, 2007a282926dSHeiko Stübner .pull_calc_reg = rk2928_calc_pull_reg_and_bit, 2008d3e51161SHeiko Stübner }; 2009d3e51161SHeiko Stübner 2010d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3066b_pin_banks[] = { 2011d3e51161SHeiko Stübner PIN_BANK(0, 32, "gpio0"), 2012d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 2013d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 2014d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 2015d3e51161SHeiko Stübner }; 2016d3e51161SHeiko Stübner 2017d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3066b_pin_ctrl = { 2018d3e51161SHeiko Stübner .pin_banks = rk3066b_pin_banks, 2019d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk3066b_pin_banks), 2020d3e51161SHeiko Stübner .label = "RK3066b-GPIO", 2021a282926dSHeiko Stübner .type = RK3066B, 202295ec8ae4SHeiko Stübner .grf_mux_offset = 0x60, 2023d3e51161SHeiko Stübner }; 2024d3e51161SHeiko Stübner 2025d3e51161SHeiko Stübner static struct rockchip_pin_bank rk3188_pin_banks[] = { 2026fc72c923SHeiko Stübner PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_GPIO_ONLY, 0, 0, 0), 2027d3e51161SHeiko Stübner PIN_BANK(1, 32, "gpio1"), 2028d3e51161SHeiko Stübner PIN_BANK(2, 32, "gpio2"), 2029d3e51161SHeiko Stübner PIN_BANK(3, 32, "gpio3"), 2030d3e51161SHeiko Stübner }; 2031d3e51161SHeiko Stübner 2032d3e51161SHeiko Stübner static struct rockchip_pin_ctrl rk3188_pin_ctrl = { 2033d3e51161SHeiko Stübner .pin_banks = rk3188_pin_banks, 2034d3e51161SHeiko Stübner .nr_banks = ARRAY_SIZE(rk3188_pin_banks), 2035d3e51161SHeiko Stübner .label = "RK3188-GPIO", 2036a282926dSHeiko Stübner .type = RK3188, 203795ec8ae4SHeiko Stübner .grf_mux_offset = 0x60, 20386ca5274dSHeiko Stübner .pull_calc_reg = rk3188_calc_pull_reg_and_bit, 2039d3e51161SHeiko Stübner }; 2040d3e51161SHeiko Stübner 2041304f077dSHeiko Stübner static struct rockchip_pin_bank rk3288_pin_banks[] = { 2042304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU, 2043304f077dSHeiko Stübner IOMUX_SOURCE_PMU, 2044304f077dSHeiko Stübner IOMUX_SOURCE_PMU, 2045304f077dSHeiko Stübner IOMUX_UNROUTED 2046304f077dSHeiko Stübner ), 2047304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_UNROUTED, 2048304f077dSHeiko Stübner IOMUX_UNROUTED, 2049304f077dSHeiko Stübner IOMUX_UNROUTED, 2050304f077dSHeiko Stübner 0 2051304f077dSHeiko Stübner ), 2052304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, IOMUX_UNROUTED), 2053304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, IOMUX_WIDTH_4BIT), 2054304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_WIDTH_4BIT, 2055304f077dSHeiko Stübner IOMUX_WIDTH_4BIT, 2056304f077dSHeiko Stübner 0, 2057304f077dSHeiko Stübner 0 2058304f077dSHeiko Stübner ), 2059304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(5, 32, "gpio5", IOMUX_UNROUTED, 2060304f077dSHeiko Stübner 0, 2061304f077dSHeiko Stübner 0, 2062304f077dSHeiko Stübner IOMUX_UNROUTED 2063304f077dSHeiko Stübner ), 2064304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(6, 32, "gpio6", 0, 0, 0, IOMUX_UNROUTED), 2065304f077dSHeiko Stübner PIN_BANK_IOMUX_FLAGS(7, 32, "gpio7", 0, 2066304f077dSHeiko Stübner 0, 2067304f077dSHeiko Stübner IOMUX_WIDTH_4BIT, 2068304f077dSHeiko Stübner IOMUX_UNROUTED 2069304f077dSHeiko Stübner ), 2070304f077dSHeiko Stübner PIN_BANK(8, 16, "gpio8"), 2071304f077dSHeiko Stübner }; 2072304f077dSHeiko Stübner 2073304f077dSHeiko Stübner static struct rockchip_pin_ctrl rk3288_pin_ctrl = { 2074304f077dSHeiko Stübner .pin_banks = rk3288_pin_banks, 2075304f077dSHeiko Stübner .nr_banks = ARRAY_SIZE(rk3288_pin_banks), 2076304f077dSHeiko Stübner .label = "RK3288-GPIO", 207766d750e1SHeiko Stübner .type = RK3288, 2078304f077dSHeiko Stübner .grf_mux_offset = 0x0, 2079304f077dSHeiko Stübner .pmu_mux_offset = 0x84, 2080304f077dSHeiko Stübner .pull_calc_reg = rk3288_calc_pull_reg_and_bit, 2081304f077dSHeiko Stübner }; 2082304f077dSHeiko Stübner 2083d3e51161SHeiko Stübner static const struct of_device_id rockchip_pinctrl_dt_match[] = { 2084d3e51161SHeiko Stübner { .compatible = "rockchip,rk2928-pinctrl", 2085d3e51161SHeiko Stübner .data = (void *)&rk2928_pin_ctrl }, 2086d3e51161SHeiko Stübner { .compatible = "rockchip,rk3066a-pinctrl", 2087d3e51161SHeiko Stübner .data = (void *)&rk3066a_pin_ctrl }, 2088d3e51161SHeiko Stübner { .compatible = "rockchip,rk3066b-pinctrl", 2089d3e51161SHeiko Stübner .data = (void *)&rk3066b_pin_ctrl }, 2090d3e51161SHeiko Stübner { .compatible = "rockchip,rk3188-pinctrl", 2091d3e51161SHeiko Stübner .data = (void *)&rk3188_pin_ctrl }, 2092304f077dSHeiko Stübner { .compatible = "rockchip,rk3288-pinctrl", 2093304f077dSHeiko Stübner .data = (void *)&rk3288_pin_ctrl }, 2094d3e51161SHeiko Stübner {}, 2095d3e51161SHeiko Stübner }; 2096d3e51161SHeiko Stübner MODULE_DEVICE_TABLE(of, rockchip_pinctrl_dt_match); 2097d3e51161SHeiko Stübner 2098d3e51161SHeiko Stübner static struct platform_driver rockchip_pinctrl_driver = { 2099d3e51161SHeiko Stübner .probe = rockchip_pinctrl_probe, 2100d3e51161SHeiko Stübner .driver = { 2101d3e51161SHeiko Stübner .name = "rockchip-pinctrl", 21029198f509SChris Zhong .pm = &rockchip_pinctrl_dev_pm_ops, 21030be9e70dSAxel Lin .of_match_table = rockchip_pinctrl_dt_match, 2104d3e51161SHeiko Stübner }, 2105d3e51161SHeiko Stübner }; 2106d3e51161SHeiko Stübner 2107d3e51161SHeiko Stübner static int __init rockchip_pinctrl_drv_register(void) 2108d3e51161SHeiko Stübner { 2109d3e51161SHeiko Stübner return platform_driver_register(&rockchip_pinctrl_driver); 2110d3e51161SHeiko Stübner } 2111d3e51161SHeiko Stübner postcore_initcall(rockchip_pinctrl_drv_register); 2112d3e51161SHeiko Stübner 2113d3e51161SHeiko Stübner MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>"); 2114d3e51161SHeiko Stübner MODULE_DESCRIPTION("Rockchip pinctrl driver"); 2115d3e51161SHeiko Stübner MODULE_LICENSE("GPL v2"); 2116