1*6ac73095SBeniamino Galvani /* 2*6ac73095SBeniamino Galvani * Pin controller and GPIO driver for Amlogic Meson SoCs 3*6ac73095SBeniamino Galvani * 4*6ac73095SBeniamino Galvani * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> 5*6ac73095SBeniamino Galvani * 6*6ac73095SBeniamino Galvani * This program is free software; you can redistribute it and/or 7*6ac73095SBeniamino Galvani * modify it under the terms of the GNU General Public License 8*6ac73095SBeniamino Galvani * version 2 as published by the Free Software Foundation. 9*6ac73095SBeniamino Galvani * 10*6ac73095SBeniamino Galvani * You should have received a copy of the GNU General Public License 11*6ac73095SBeniamino Galvani * along with this program. If not, see <http://www.gnu.org/licenses/>. 12*6ac73095SBeniamino Galvani */ 13*6ac73095SBeniamino Galvani 14*6ac73095SBeniamino Galvani /* 15*6ac73095SBeniamino Galvani * The available pins are organized in banks (A,B,C,D,E,X,Y,Z,AO, 16*6ac73095SBeniamino Galvani * BOOT,CARD for meson6 and X,Y,DV,H,Z,AO,BOOT,CARD for meson8) and 17*6ac73095SBeniamino Galvani * each bank has a variable number of pins. 18*6ac73095SBeniamino Galvani * 19*6ac73095SBeniamino Galvani * The AO bank is special because it belongs to the Always-On power 20*6ac73095SBeniamino Galvani * domain which can't be powered off; the bank also uses a set of 21*6ac73095SBeniamino Galvani * registers different from the other banks. 22*6ac73095SBeniamino Galvani * 23*6ac73095SBeniamino Galvani * For each of the two power domains (regular and always-on) there are 24*6ac73095SBeniamino Galvani * 4 different register ranges that control the following properties 25*6ac73095SBeniamino Galvani * of the pins: 26*6ac73095SBeniamino Galvani * 1) pin muxing 27*6ac73095SBeniamino Galvani * 2) pull enable/disable 28*6ac73095SBeniamino Galvani * 3) pull up/down 29*6ac73095SBeniamino Galvani * 4) GPIO direction, output value, input value 30*6ac73095SBeniamino Galvani * 31*6ac73095SBeniamino Galvani * In some cases the register ranges for pull enable and pull 32*6ac73095SBeniamino Galvani * direction are the same and thus there are only 3 register ranges. 33*6ac73095SBeniamino Galvani * 34*6ac73095SBeniamino Galvani * Every pinmux group can be enabled by a specific bit in the first 35*6ac73095SBeniamino Galvani * register range of the domain; when all groups for a given pin are 36*6ac73095SBeniamino Galvani * disabled the pin acts as a GPIO. 37*6ac73095SBeniamino Galvani * 38*6ac73095SBeniamino Galvani * For the pull and GPIO configuration every bank uses a contiguous 39*6ac73095SBeniamino Galvani * set of bits in the register sets described above; the same register 40*6ac73095SBeniamino Galvani * can be shared by more banks with different offsets. 41*6ac73095SBeniamino Galvani * 42*6ac73095SBeniamino Galvani * In addition to this there are some registers shared between all 43*6ac73095SBeniamino Galvani * banks that control the IRQ functionality. This feature is not 44*6ac73095SBeniamino Galvani * supported at the moment by the driver. 45*6ac73095SBeniamino Galvani */ 46*6ac73095SBeniamino Galvani 47*6ac73095SBeniamino Galvani #include <linux/device.h> 48*6ac73095SBeniamino Galvani #include <linux/gpio.h> 49*6ac73095SBeniamino Galvani #include <linux/init.h> 50*6ac73095SBeniamino Galvani #include <linux/io.h> 51*6ac73095SBeniamino Galvani #include <linux/module.h> 52*6ac73095SBeniamino Galvani #include <linux/of.h> 53*6ac73095SBeniamino Galvani #include <linux/of_address.h> 54*6ac73095SBeniamino Galvani #include <linux/pinctrl/pinconf-generic.h> 55*6ac73095SBeniamino Galvani #include <linux/pinctrl/pinconf.h> 56*6ac73095SBeniamino Galvani #include <linux/pinctrl/pinctrl.h> 57*6ac73095SBeniamino Galvani #include <linux/pinctrl/pinmux.h> 58*6ac73095SBeniamino Galvani #include <linux/platform_device.h> 59*6ac73095SBeniamino Galvani #include <linux/regmap.h> 60*6ac73095SBeniamino Galvani #include <linux/seq_file.h> 61*6ac73095SBeniamino Galvani 62*6ac73095SBeniamino Galvani #include "../core.h" 63*6ac73095SBeniamino Galvani #include "../pinctrl-utils.h" 64*6ac73095SBeniamino Galvani #include "pinctrl-meson.h" 65*6ac73095SBeniamino Galvani 66*6ac73095SBeniamino Galvani /** 67*6ac73095SBeniamino Galvani * meson_get_bank() - find the bank containing a given pin 68*6ac73095SBeniamino Galvani * 69*6ac73095SBeniamino Galvani * @domain: the domain containing the pin 70*6ac73095SBeniamino Galvani * @pin: the pin number 71*6ac73095SBeniamino Galvani * @bank: the found bank 72*6ac73095SBeniamino Galvani * 73*6ac73095SBeniamino Galvani * Return: 0 on success, a negative value on error 74*6ac73095SBeniamino Galvani */ 75*6ac73095SBeniamino Galvani static int meson_get_bank(struct meson_domain *domain, unsigned int pin, 76*6ac73095SBeniamino Galvani struct meson_bank **bank) 77*6ac73095SBeniamino Galvani { 78*6ac73095SBeniamino Galvani int i; 79*6ac73095SBeniamino Galvani 80*6ac73095SBeniamino Galvani for (i = 0; i < domain->data->num_banks; i++) { 81*6ac73095SBeniamino Galvani if (pin >= domain->data->banks[i].first && 82*6ac73095SBeniamino Galvani pin <= domain->data->banks[i].last) { 83*6ac73095SBeniamino Galvani *bank = &domain->data->banks[i]; 84*6ac73095SBeniamino Galvani return 0; 85*6ac73095SBeniamino Galvani } 86*6ac73095SBeniamino Galvani } 87*6ac73095SBeniamino Galvani 88*6ac73095SBeniamino Galvani return -EINVAL; 89*6ac73095SBeniamino Galvani } 90*6ac73095SBeniamino Galvani 91*6ac73095SBeniamino Galvani /** 92*6ac73095SBeniamino Galvani * meson_get_domain_and_bank() - find domain and bank containing a given pin 93*6ac73095SBeniamino Galvani * 94*6ac73095SBeniamino Galvani * @pc: Meson pin controller device 95*6ac73095SBeniamino Galvani * @pin: the pin number 96*6ac73095SBeniamino Galvani * @domain: the found domain 97*6ac73095SBeniamino Galvani * @bank: the found bank 98*6ac73095SBeniamino Galvani * 99*6ac73095SBeniamino Galvani * Return: 0 on success, a negative value on error 100*6ac73095SBeniamino Galvani */ 101*6ac73095SBeniamino Galvani static int meson_get_domain_and_bank(struct meson_pinctrl *pc, unsigned int pin, 102*6ac73095SBeniamino Galvani struct meson_domain **domain, 103*6ac73095SBeniamino Galvani struct meson_bank **bank) 104*6ac73095SBeniamino Galvani { 105*6ac73095SBeniamino Galvani struct meson_domain *d; 106*6ac73095SBeniamino Galvani int i; 107*6ac73095SBeniamino Galvani 108*6ac73095SBeniamino Galvani for (i = 0; i < pc->data->num_domains; i++) { 109*6ac73095SBeniamino Galvani d = &pc->domains[i]; 110*6ac73095SBeniamino Galvani if (pin >= d->data->pin_base && 111*6ac73095SBeniamino Galvani pin < d->data->pin_base + d->data->num_pins) { 112*6ac73095SBeniamino Galvani *domain = d; 113*6ac73095SBeniamino Galvani return meson_get_bank(d, pin, bank); 114*6ac73095SBeniamino Galvani } 115*6ac73095SBeniamino Galvani } 116*6ac73095SBeniamino Galvani 117*6ac73095SBeniamino Galvani return -EINVAL; 118*6ac73095SBeniamino Galvani } 119*6ac73095SBeniamino Galvani 120*6ac73095SBeniamino Galvani /** 121*6ac73095SBeniamino Galvani * meson_calc_reg_and_bit() - calculate register and bit for a pin 122*6ac73095SBeniamino Galvani * 123*6ac73095SBeniamino Galvani * @bank: the bank containing the pin 124*6ac73095SBeniamino Galvani * @pin: the pin number 125*6ac73095SBeniamino Galvani * @reg_type: the type of register needed (pull-enable, pull, etc...) 126*6ac73095SBeniamino Galvani * @reg: the computed register offset 127*6ac73095SBeniamino Galvani * @bit: the computed bit 128*6ac73095SBeniamino Galvani */ 129*6ac73095SBeniamino Galvani static void meson_calc_reg_and_bit(struct meson_bank *bank, unsigned int pin, 130*6ac73095SBeniamino Galvani enum meson_reg_type reg_type, 131*6ac73095SBeniamino Galvani unsigned int *reg, unsigned int *bit) 132*6ac73095SBeniamino Galvani { 133*6ac73095SBeniamino Galvani struct meson_reg_desc *desc = &bank->regs[reg_type]; 134*6ac73095SBeniamino Galvani 135*6ac73095SBeniamino Galvani *reg = desc->reg * 4; 136*6ac73095SBeniamino Galvani *bit = desc->bit + pin - bank->first; 137*6ac73095SBeniamino Galvani } 138*6ac73095SBeniamino Galvani 139*6ac73095SBeniamino Galvani static int meson_get_groups_count(struct pinctrl_dev *pcdev) 140*6ac73095SBeniamino Galvani { 141*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 142*6ac73095SBeniamino Galvani 143*6ac73095SBeniamino Galvani return pc->data->num_groups; 144*6ac73095SBeniamino Galvani } 145*6ac73095SBeniamino Galvani 146*6ac73095SBeniamino Galvani static const char *meson_get_group_name(struct pinctrl_dev *pcdev, 147*6ac73095SBeniamino Galvani unsigned selector) 148*6ac73095SBeniamino Galvani { 149*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 150*6ac73095SBeniamino Galvani 151*6ac73095SBeniamino Galvani return pc->data->groups[selector].name; 152*6ac73095SBeniamino Galvani } 153*6ac73095SBeniamino Galvani 154*6ac73095SBeniamino Galvani static int meson_get_group_pins(struct pinctrl_dev *pcdev, unsigned selector, 155*6ac73095SBeniamino Galvani const unsigned **pins, unsigned *num_pins) 156*6ac73095SBeniamino Galvani { 157*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 158*6ac73095SBeniamino Galvani 159*6ac73095SBeniamino Galvani *pins = pc->data->groups[selector].pins; 160*6ac73095SBeniamino Galvani *num_pins = pc->data->groups[selector].num_pins; 161*6ac73095SBeniamino Galvani 162*6ac73095SBeniamino Galvani return 0; 163*6ac73095SBeniamino Galvani } 164*6ac73095SBeniamino Galvani 165*6ac73095SBeniamino Galvani static void meson_pin_dbg_show(struct pinctrl_dev *pcdev, struct seq_file *s, 166*6ac73095SBeniamino Galvani unsigned offset) 167*6ac73095SBeniamino Galvani { 168*6ac73095SBeniamino Galvani seq_printf(s, " %s", dev_name(pcdev->dev)); 169*6ac73095SBeniamino Galvani } 170*6ac73095SBeniamino Galvani 171*6ac73095SBeniamino Galvani static const struct pinctrl_ops meson_pctrl_ops = { 172*6ac73095SBeniamino Galvani .get_groups_count = meson_get_groups_count, 173*6ac73095SBeniamino Galvani .get_group_name = meson_get_group_name, 174*6ac73095SBeniamino Galvani .get_group_pins = meson_get_group_pins, 175*6ac73095SBeniamino Galvani .dt_node_to_map = pinconf_generic_dt_node_to_map_all, 176*6ac73095SBeniamino Galvani .dt_free_map = pinctrl_utils_dt_free_map, 177*6ac73095SBeniamino Galvani .pin_dbg_show = meson_pin_dbg_show, 178*6ac73095SBeniamino Galvani }; 179*6ac73095SBeniamino Galvani 180*6ac73095SBeniamino Galvani /** 181*6ac73095SBeniamino Galvani * meson_pmx_disable_other_groups() - disable other groups using a given pin 182*6ac73095SBeniamino Galvani * 183*6ac73095SBeniamino Galvani * @pc: meson pin controller device 184*6ac73095SBeniamino Galvani * @pin: number of the pin 185*6ac73095SBeniamino Galvani * @sel_group: index of the selected group, or -1 if none 186*6ac73095SBeniamino Galvani * 187*6ac73095SBeniamino Galvani * The function disables all pinmux groups using a pin except the 188*6ac73095SBeniamino Galvani * selected one. If @sel_group is -1 all groups are disabled, leaving 189*6ac73095SBeniamino Galvani * the pin in GPIO mode. 190*6ac73095SBeniamino Galvani */ 191*6ac73095SBeniamino Galvani static void meson_pmx_disable_other_groups(struct meson_pinctrl *pc, 192*6ac73095SBeniamino Galvani unsigned int pin, int sel_group) 193*6ac73095SBeniamino Galvani { 194*6ac73095SBeniamino Galvani struct meson_pmx_group *group; 195*6ac73095SBeniamino Galvani struct meson_domain *domain; 196*6ac73095SBeniamino Galvani int i, j; 197*6ac73095SBeniamino Galvani 198*6ac73095SBeniamino Galvani for (i = 0; i < pc->data->num_groups; i++) { 199*6ac73095SBeniamino Galvani group = &pc->data->groups[i]; 200*6ac73095SBeniamino Galvani if (group->is_gpio || i == sel_group) 201*6ac73095SBeniamino Galvani continue; 202*6ac73095SBeniamino Galvani 203*6ac73095SBeniamino Galvani for (j = 0; j < group->num_pins; j++) { 204*6ac73095SBeniamino Galvani if (group->pins[j] == pin) { 205*6ac73095SBeniamino Galvani /* We have found a group using the pin */ 206*6ac73095SBeniamino Galvani domain = &pc->domains[group->domain]; 207*6ac73095SBeniamino Galvani regmap_update_bits(domain->reg_mux, 208*6ac73095SBeniamino Galvani group->reg * 4, 209*6ac73095SBeniamino Galvani BIT(group->bit), 0); 210*6ac73095SBeniamino Galvani } 211*6ac73095SBeniamino Galvani } 212*6ac73095SBeniamino Galvani } 213*6ac73095SBeniamino Galvani } 214*6ac73095SBeniamino Galvani 215*6ac73095SBeniamino Galvani static int meson_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num, 216*6ac73095SBeniamino Galvani unsigned group_num) 217*6ac73095SBeniamino Galvani { 218*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 219*6ac73095SBeniamino Galvani struct meson_pmx_func *func = &pc->data->funcs[func_num]; 220*6ac73095SBeniamino Galvani struct meson_pmx_group *group = &pc->data->groups[group_num]; 221*6ac73095SBeniamino Galvani struct meson_domain *domain = &pc->domains[group->domain]; 222*6ac73095SBeniamino Galvani int i, ret = 0; 223*6ac73095SBeniamino Galvani 224*6ac73095SBeniamino Galvani dev_dbg(pc->dev, "enable function %s, group %s\n", func->name, 225*6ac73095SBeniamino Galvani group->name); 226*6ac73095SBeniamino Galvani 227*6ac73095SBeniamino Galvani /* 228*6ac73095SBeniamino Galvani * Disable groups using the same pin. 229*6ac73095SBeniamino Galvani * The selected group is not disabled to avoid glitches. 230*6ac73095SBeniamino Galvani */ 231*6ac73095SBeniamino Galvani for (i = 0; i < group->num_pins; i++) 232*6ac73095SBeniamino Galvani meson_pmx_disable_other_groups(pc, group->pins[i], group_num); 233*6ac73095SBeniamino Galvani 234*6ac73095SBeniamino Galvani /* Function 0 (GPIO) doesn't need any additional setting */ 235*6ac73095SBeniamino Galvani if (func_num) 236*6ac73095SBeniamino Galvani ret = regmap_update_bits(domain->reg_mux, group->reg * 4, 237*6ac73095SBeniamino Galvani BIT(group->bit), BIT(group->bit)); 238*6ac73095SBeniamino Galvani 239*6ac73095SBeniamino Galvani return ret; 240*6ac73095SBeniamino Galvani } 241*6ac73095SBeniamino Galvani 242*6ac73095SBeniamino Galvani static int meson_pmx_request_gpio(struct pinctrl_dev *pcdev, 243*6ac73095SBeniamino Galvani struct pinctrl_gpio_range *range, 244*6ac73095SBeniamino Galvani unsigned offset) 245*6ac73095SBeniamino Galvani { 246*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 247*6ac73095SBeniamino Galvani 248*6ac73095SBeniamino Galvani meson_pmx_disable_other_groups(pc, range->pin_base + offset, -1); 249*6ac73095SBeniamino Galvani 250*6ac73095SBeniamino Galvani return 0; 251*6ac73095SBeniamino Galvani } 252*6ac73095SBeniamino Galvani 253*6ac73095SBeniamino Galvani static int meson_pmx_get_funcs_count(struct pinctrl_dev *pcdev) 254*6ac73095SBeniamino Galvani { 255*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 256*6ac73095SBeniamino Galvani 257*6ac73095SBeniamino Galvani return pc->data->num_funcs; 258*6ac73095SBeniamino Galvani } 259*6ac73095SBeniamino Galvani 260*6ac73095SBeniamino Galvani static const char *meson_pmx_get_func_name(struct pinctrl_dev *pcdev, 261*6ac73095SBeniamino Galvani unsigned selector) 262*6ac73095SBeniamino Galvani { 263*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 264*6ac73095SBeniamino Galvani 265*6ac73095SBeniamino Galvani return pc->data->funcs[selector].name; 266*6ac73095SBeniamino Galvani } 267*6ac73095SBeniamino Galvani 268*6ac73095SBeniamino Galvani static int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector, 269*6ac73095SBeniamino Galvani const char * const **groups, 270*6ac73095SBeniamino Galvani unsigned * const num_groups) 271*6ac73095SBeniamino Galvani { 272*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 273*6ac73095SBeniamino Galvani 274*6ac73095SBeniamino Galvani *groups = pc->data->funcs[selector].groups; 275*6ac73095SBeniamino Galvani *num_groups = pc->data->funcs[selector].num_groups; 276*6ac73095SBeniamino Galvani 277*6ac73095SBeniamino Galvani return 0; 278*6ac73095SBeniamino Galvani } 279*6ac73095SBeniamino Galvani 280*6ac73095SBeniamino Galvani static const struct pinmux_ops meson_pmx_ops = { 281*6ac73095SBeniamino Galvani .set_mux = meson_pmx_set_mux, 282*6ac73095SBeniamino Galvani .get_functions_count = meson_pmx_get_funcs_count, 283*6ac73095SBeniamino Galvani .get_function_name = meson_pmx_get_func_name, 284*6ac73095SBeniamino Galvani .get_function_groups = meson_pmx_get_groups, 285*6ac73095SBeniamino Galvani .gpio_request_enable = meson_pmx_request_gpio, 286*6ac73095SBeniamino Galvani }; 287*6ac73095SBeniamino Galvani 288*6ac73095SBeniamino Galvani static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, 289*6ac73095SBeniamino Galvani unsigned long *configs, unsigned num_configs) 290*6ac73095SBeniamino Galvani { 291*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 292*6ac73095SBeniamino Galvani struct meson_domain *domain; 293*6ac73095SBeniamino Galvani struct meson_bank *bank; 294*6ac73095SBeniamino Galvani enum pin_config_param param; 295*6ac73095SBeniamino Galvani unsigned int reg, bit; 296*6ac73095SBeniamino Galvani int i, ret; 297*6ac73095SBeniamino Galvani u16 arg; 298*6ac73095SBeniamino Galvani 299*6ac73095SBeniamino Galvani ret = meson_get_domain_and_bank(pc, pin, &domain, &bank); 300*6ac73095SBeniamino Galvani if (ret) 301*6ac73095SBeniamino Galvani return ret; 302*6ac73095SBeniamino Galvani 303*6ac73095SBeniamino Galvani for (i = 0; i < num_configs; i++) { 304*6ac73095SBeniamino Galvani param = pinconf_to_config_param(configs[i]); 305*6ac73095SBeniamino Galvani arg = pinconf_to_config_argument(configs[i]); 306*6ac73095SBeniamino Galvani 307*6ac73095SBeniamino Galvani switch (param) { 308*6ac73095SBeniamino Galvani case PIN_CONFIG_BIAS_DISABLE: 309*6ac73095SBeniamino Galvani dev_dbg(pc->dev, "pin %u: disable bias\n", pin); 310*6ac73095SBeniamino Galvani 311*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); 312*6ac73095SBeniamino Galvani ret = regmap_update_bits(domain->reg_pull, reg, 313*6ac73095SBeniamino Galvani BIT(bit), 0); 314*6ac73095SBeniamino Galvani if (ret) 315*6ac73095SBeniamino Galvani return ret; 316*6ac73095SBeniamino Galvani break; 317*6ac73095SBeniamino Galvani case PIN_CONFIG_BIAS_PULL_UP: 318*6ac73095SBeniamino Galvani dev_dbg(pc->dev, "pin %u: enable pull-up\n", pin); 319*6ac73095SBeniamino Galvani 320*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_PULLEN, 321*6ac73095SBeniamino Galvani ®, &bit); 322*6ac73095SBeniamino Galvani ret = regmap_update_bits(domain->reg_pullen, reg, 323*6ac73095SBeniamino Galvani BIT(bit), BIT(bit)); 324*6ac73095SBeniamino Galvani if (ret) 325*6ac73095SBeniamino Galvani return ret; 326*6ac73095SBeniamino Galvani 327*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); 328*6ac73095SBeniamino Galvani ret = regmap_update_bits(domain->reg_pull, reg, 329*6ac73095SBeniamino Galvani BIT(bit), BIT(bit)); 330*6ac73095SBeniamino Galvani if (ret) 331*6ac73095SBeniamino Galvani return ret; 332*6ac73095SBeniamino Galvani break; 333*6ac73095SBeniamino Galvani case PIN_CONFIG_BIAS_PULL_DOWN: 334*6ac73095SBeniamino Galvani dev_dbg(pc->dev, "pin %u: enable pull-down\n", pin); 335*6ac73095SBeniamino Galvani 336*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_PULLEN, 337*6ac73095SBeniamino Galvani ®, &bit); 338*6ac73095SBeniamino Galvani ret = regmap_update_bits(domain->reg_pullen, reg, 339*6ac73095SBeniamino Galvani BIT(bit), BIT(bit)); 340*6ac73095SBeniamino Galvani if (ret) 341*6ac73095SBeniamino Galvani return ret; 342*6ac73095SBeniamino Galvani 343*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); 344*6ac73095SBeniamino Galvani ret = regmap_update_bits(domain->reg_pull, reg, 345*6ac73095SBeniamino Galvani BIT(bit), 0); 346*6ac73095SBeniamino Galvani if (ret) 347*6ac73095SBeniamino Galvani return ret; 348*6ac73095SBeniamino Galvani break; 349*6ac73095SBeniamino Galvani default: 350*6ac73095SBeniamino Galvani return -ENOTSUPP; 351*6ac73095SBeniamino Galvani } 352*6ac73095SBeniamino Galvani } 353*6ac73095SBeniamino Galvani 354*6ac73095SBeniamino Galvani return 0; 355*6ac73095SBeniamino Galvani } 356*6ac73095SBeniamino Galvani 357*6ac73095SBeniamino Galvani static int meson_pinconf_get_pull(struct meson_pinctrl *pc, unsigned int pin) 358*6ac73095SBeniamino Galvani { 359*6ac73095SBeniamino Galvani struct meson_domain *domain; 360*6ac73095SBeniamino Galvani struct meson_bank *bank; 361*6ac73095SBeniamino Galvani unsigned int reg, bit, val; 362*6ac73095SBeniamino Galvani int ret, conf; 363*6ac73095SBeniamino Galvani 364*6ac73095SBeniamino Galvani ret = meson_get_domain_and_bank(pc, pin, &domain, &bank); 365*6ac73095SBeniamino Galvani if (ret) 366*6ac73095SBeniamino Galvani return ret; 367*6ac73095SBeniamino Galvani 368*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_PULLEN, ®, &bit); 369*6ac73095SBeniamino Galvani 370*6ac73095SBeniamino Galvani ret = regmap_read(domain->reg_pullen, reg, &val); 371*6ac73095SBeniamino Galvani if (ret) 372*6ac73095SBeniamino Galvani return ret; 373*6ac73095SBeniamino Galvani 374*6ac73095SBeniamino Galvani if (!(val & BIT(bit))) { 375*6ac73095SBeniamino Galvani conf = PIN_CONFIG_BIAS_DISABLE; 376*6ac73095SBeniamino Galvani } else { 377*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); 378*6ac73095SBeniamino Galvani 379*6ac73095SBeniamino Galvani ret = regmap_read(domain->reg_pull, reg, &val); 380*6ac73095SBeniamino Galvani if (ret) 381*6ac73095SBeniamino Galvani return ret; 382*6ac73095SBeniamino Galvani 383*6ac73095SBeniamino Galvani if (val & BIT(bit)) 384*6ac73095SBeniamino Galvani conf = PIN_CONFIG_BIAS_PULL_UP; 385*6ac73095SBeniamino Galvani else 386*6ac73095SBeniamino Galvani conf = PIN_CONFIG_BIAS_PULL_DOWN; 387*6ac73095SBeniamino Galvani } 388*6ac73095SBeniamino Galvani 389*6ac73095SBeniamino Galvani return conf; 390*6ac73095SBeniamino Galvani } 391*6ac73095SBeniamino Galvani 392*6ac73095SBeniamino Galvani static int meson_pinconf_get(struct pinctrl_dev *pcdev, unsigned int pin, 393*6ac73095SBeniamino Galvani unsigned long *config) 394*6ac73095SBeniamino Galvani { 395*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 396*6ac73095SBeniamino Galvani enum pin_config_param param = pinconf_to_config_param(*config); 397*6ac73095SBeniamino Galvani u16 arg; 398*6ac73095SBeniamino Galvani 399*6ac73095SBeniamino Galvani switch (param) { 400*6ac73095SBeniamino Galvani case PIN_CONFIG_BIAS_DISABLE: 401*6ac73095SBeniamino Galvani case PIN_CONFIG_BIAS_PULL_DOWN: 402*6ac73095SBeniamino Galvani case PIN_CONFIG_BIAS_PULL_UP: 403*6ac73095SBeniamino Galvani if (meson_pinconf_get_pull(pc, pin) == param) 404*6ac73095SBeniamino Galvani arg = 1; 405*6ac73095SBeniamino Galvani else 406*6ac73095SBeniamino Galvani return -EINVAL; 407*6ac73095SBeniamino Galvani break; 408*6ac73095SBeniamino Galvani default: 409*6ac73095SBeniamino Galvani return -ENOTSUPP; 410*6ac73095SBeniamino Galvani } 411*6ac73095SBeniamino Galvani 412*6ac73095SBeniamino Galvani *config = pinconf_to_config_packed(param, arg); 413*6ac73095SBeniamino Galvani dev_dbg(pc->dev, "pinconf for pin %u is %lu\n", pin, *config); 414*6ac73095SBeniamino Galvani 415*6ac73095SBeniamino Galvani return 0; 416*6ac73095SBeniamino Galvani } 417*6ac73095SBeniamino Galvani 418*6ac73095SBeniamino Galvani static int meson_pinconf_group_set(struct pinctrl_dev *pcdev, 419*6ac73095SBeniamino Galvani unsigned int num_group, 420*6ac73095SBeniamino Galvani unsigned long *configs, unsigned num_configs) 421*6ac73095SBeniamino Galvani { 422*6ac73095SBeniamino Galvani struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); 423*6ac73095SBeniamino Galvani struct meson_pmx_group *group = &pc->data->groups[num_group]; 424*6ac73095SBeniamino Galvani int i; 425*6ac73095SBeniamino Galvani 426*6ac73095SBeniamino Galvani dev_dbg(pc->dev, "set pinconf for group %s\n", group->name); 427*6ac73095SBeniamino Galvani 428*6ac73095SBeniamino Galvani for (i = 0; i < group->num_pins; i++) { 429*6ac73095SBeniamino Galvani meson_pinconf_set(pcdev, group->pins[i], configs, 430*6ac73095SBeniamino Galvani num_configs); 431*6ac73095SBeniamino Galvani } 432*6ac73095SBeniamino Galvani 433*6ac73095SBeniamino Galvani return 0; 434*6ac73095SBeniamino Galvani } 435*6ac73095SBeniamino Galvani 436*6ac73095SBeniamino Galvani static int meson_pinconf_group_get(struct pinctrl_dev *pcdev, 437*6ac73095SBeniamino Galvani unsigned int group, unsigned long *config) 438*6ac73095SBeniamino Galvani { 439*6ac73095SBeniamino Galvani return -ENOSYS; 440*6ac73095SBeniamino Galvani } 441*6ac73095SBeniamino Galvani 442*6ac73095SBeniamino Galvani static const struct pinconf_ops meson_pinconf_ops = { 443*6ac73095SBeniamino Galvani .pin_config_get = meson_pinconf_get, 444*6ac73095SBeniamino Galvani .pin_config_set = meson_pinconf_set, 445*6ac73095SBeniamino Galvani .pin_config_group_get = meson_pinconf_group_get, 446*6ac73095SBeniamino Galvani .pin_config_group_set = meson_pinconf_group_set, 447*6ac73095SBeniamino Galvani .is_generic = true, 448*6ac73095SBeniamino Galvani }; 449*6ac73095SBeniamino Galvani 450*6ac73095SBeniamino Galvani static inline struct meson_domain *to_meson_domain(struct gpio_chip *chip) 451*6ac73095SBeniamino Galvani { 452*6ac73095SBeniamino Galvani return container_of(chip, struct meson_domain, chip); 453*6ac73095SBeniamino Galvani } 454*6ac73095SBeniamino Galvani 455*6ac73095SBeniamino Galvani static int meson_gpio_request(struct gpio_chip *chip, unsigned gpio) 456*6ac73095SBeniamino Galvani { 457*6ac73095SBeniamino Galvani return pinctrl_request_gpio(chip->base + gpio); 458*6ac73095SBeniamino Galvani } 459*6ac73095SBeniamino Galvani 460*6ac73095SBeniamino Galvani static void meson_gpio_free(struct gpio_chip *chip, unsigned gpio) 461*6ac73095SBeniamino Galvani { 462*6ac73095SBeniamino Galvani struct meson_domain *domain = to_meson_domain(chip); 463*6ac73095SBeniamino Galvani 464*6ac73095SBeniamino Galvani pinctrl_free_gpio(domain->data->pin_base + gpio); 465*6ac73095SBeniamino Galvani } 466*6ac73095SBeniamino Galvani 467*6ac73095SBeniamino Galvani static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) 468*6ac73095SBeniamino Galvani { 469*6ac73095SBeniamino Galvani struct meson_domain *domain = to_meson_domain(chip); 470*6ac73095SBeniamino Galvani unsigned int reg, bit, pin; 471*6ac73095SBeniamino Galvani struct meson_bank *bank; 472*6ac73095SBeniamino Galvani int ret; 473*6ac73095SBeniamino Galvani 474*6ac73095SBeniamino Galvani pin = domain->data->pin_base + gpio; 475*6ac73095SBeniamino Galvani ret = meson_get_bank(domain, pin, &bank); 476*6ac73095SBeniamino Galvani if (ret) 477*6ac73095SBeniamino Galvani return ret; 478*6ac73095SBeniamino Galvani 479*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); 480*6ac73095SBeniamino Galvani 481*6ac73095SBeniamino Galvani return regmap_update_bits(domain->reg_gpio, reg, BIT(bit), BIT(bit)); 482*6ac73095SBeniamino Galvani } 483*6ac73095SBeniamino Galvani 484*6ac73095SBeniamino Galvani static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, 485*6ac73095SBeniamino Galvani int value) 486*6ac73095SBeniamino Galvani { 487*6ac73095SBeniamino Galvani struct meson_domain *domain = to_meson_domain(chip); 488*6ac73095SBeniamino Galvani unsigned int reg, bit, pin; 489*6ac73095SBeniamino Galvani struct meson_bank *bank; 490*6ac73095SBeniamino Galvani int ret; 491*6ac73095SBeniamino Galvani 492*6ac73095SBeniamino Galvani pin = domain->data->pin_base + gpio; 493*6ac73095SBeniamino Galvani ret = meson_get_bank(domain, pin, &bank); 494*6ac73095SBeniamino Galvani if (ret) 495*6ac73095SBeniamino Galvani return ret; 496*6ac73095SBeniamino Galvani 497*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); 498*6ac73095SBeniamino Galvani ret = regmap_update_bits(domain->reg_gpio, reg, BIT(bit), 0); 499*6ac73095SBeniamino Galvani if (ret) 500*6ac73095SBeniamino Galvani return ret; 501*6ac73095SBeniamino Galvani 502*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_OUT, ®, &bit); 503*6ac73095SBeniamino Galvani return regmap_update_bits(domain->reg_gpio, reg, BIT(bit), 504*6ac73095SBeniamino Galvani value ? BIT(bit) : 0); 505*6ac73095SBeniamino Galvani } 506*6ac73095SBeniamino Galvani 507*6ac73095SBeniamino Galvani static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) 508*6ac73095SBeniamino Galvani { 509*6ac73095SBeniamino Galvani struct meson_domain *domain = to_meson_domain(chip); 510*6ac73095SBeniamino Galvani unsigned int reg, bit, pin; 511*6ac73095SBeniamino Galvani struct meson_bank *bank; 512*6ac73095SBeniamino Galvani int ret; 513*6ac73095SBeniamino Galvani 514*6ac73095SBeniamino Galvani pin = domain->data->pin_base + gpio; 515*6ac73095SBeniamino Galvani ret = meson_get_bank(domain, pin, &bank); 516*6ac73095SBeniamino Galvani if (ret) 517*6ac73095SBeniamino Galvani return; 518*6ac73095SBeniamino Galvani 519*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_OUT, ®, &bit); 520*6ac73095SBeniamino Galvani regmap_update_bits(domain->reg_gpio, reg, BIT(bit), 521*6ac73095SBeniamino Galvani value ? BIT(bit) : 0); 522*6ac73095SBeniamino Galvani } 523*6ac73095SBeniamino Galvani 524*6ac73095SBeniamino Galvani static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio) 525*6ac73095SBeniamino Galvani { 526*6ac73095SBeniamino Galvani struct meson_domain *domain = to_meson_domain(chip); 527*6ac73095SBeniamino Galvani unsigned int reg, bit, val, pin; 528*6ac73095SBeniamino Galvani struct meson_bank *bank; 529*6ac73095SBeniamino Galvani int ret; 530*6ac73095SBeniamino Galvani 531*6ac73095SBeniamino Galvani pin = domain->data->pin_base + gpio; 532*6ac73095SBeniamino Galvani ret = meson_get_bank(domain, pin, &bank); 533*6ac73095SBeniamino Galvani if (ret) 534*6ac73095SBeniamino Galvani return ret; 535*6ac73095SBeniamino Galvani 536*6ac73095SBeniamino Galvani meson_calc_reg_and_bit(bank, pin, REG_IN, ®, &bit); 537*6ac73095SBeniamino Galvani regmap_read(domain->reg_gpio, reg, &val); 538*6ac73095SBeniamino Galvani 539*6ac73095SBeniamino Galvani return !!(val & BIT(bit)); 540*6ac73095SBeniamino Galvani } 541*6ac73095SBeniamino Galvani 542*6ac73095SBeniamino Galvani static const struct of_device_id meson_pinctrl_dt_match[] = { 543*6ac73095SBeniamino Galvani { 544*6ac73095SBeniamino Galvani .compatible = "amlogic,meson8-pinctrl", 545*6ac73095SBeniamino Galvani .data = &meson8_pinctrl_data, 546*6ac73095SBeniamino Galvani }, 547*6ac73095SBeniamino Galvani { }, 548*6ac73095SBeniamino Galvani }; 549*6ac73095SBeniamino Galvani MODULE_DEVICE_TABLE(of, meson_pinctrl_dt_match); 550*6ac73095SBeniamino Galvani 551*6ac73095SBeniamino Galvani static int meson_gpiolib_register(struct meson_pinctrl *pc) 552*6ac73095SBeniamino Galvani { 553*6ac73095SBeniamino Galvani struct meson_domain *domain; 554*6ac73095SBeniamino Galvani int i, ret; 555*6ac73095SBeniamino Galvani 556*6ac73095SBeniamino Galvani for (i = 0; i < pc->data->num_domains; i++) { 557*6ac73095SBeniamino Galvani domain = &pc->domains[i]; 558*6ac73095SBeniamino Galvani 559*6ac73095SBeniamino Galvani domain->chip.label = domain->data->name; 560*6ac73095SBeniamino Galvani domain->chip.dev = pc->dev; 561*6ac73095SBeniamino Galvani domain->chip.request = meson_gpio_request; 562*6ac73095SBeniamino Galvani domain->chip.free = meson_gpio_free; 563*6ac73095SBeniamino Galvani domain->chip.direction_input = meson_gpio_direction_input; 564*6ac73095SBeniamino Galvani domain->chip.direction_output = meson_gpio_direction_output; 565*6ac73095SBeniamino Galvani domain->chip.get = meson_gpio_get; 566*6ac73095SBeniamino Galvani domain->chip.set = meson_gpio_set; 567*6ac73095SBeniamino Galvani domain->chip.base = -1; 568*6ac73095SBeniamino Galvani domain->chip.ngpio = domain->data->num_pins; 569*6ac73095SBeniamino Galvani domain->chip.can_sleep = false; 570*6ac73095SBeniamino Galvani domain->chip.of_node = domain->of_node; 571*6ac73095SBeniamino Galvani domain->chip.of_gpio_n_cells = 2; 572*6ac73095SBeniamino Galvani 573*6ac73095SBeniamino Galvani ret = gpiochip_add(&domain->chip); 574*6ac73095SBeniamino Galvani if (ret) { 575*6ac73095SBeniamino Galvani dev_err(pc->dev, "can't add gpio chip %s\n", 576*6ac73095SBeniamino Galvani domain->data->name); 577*6ac73095SBeniamino Galvani goto fail; 578*6ac73095SBeniamino Galvani } 579*6ac73095SBeniamino Galvani 580*6ac73095SBeniamino Galvani ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev), 581*6ac73095SBeniamino Galvani 0, domain->data->pin_base, 582*6ac73095SBeniamino Galvani domain->chip.ngpio); 583*6ac73095SBeniamino Galvani if (ret) { 584*6ac73095SBeniamino Galvani dev_err(pc->dev, "can't add pin range\n"); 585*6ac73095SBeniamino Galvani goto fail; 586*6ac73095SBeniamino Galvani } 587*6ac73095SBeniamino Galvani } 588*6ac73095SBeniamino Galvani 589*6ac73095SBeniamino Galvani return 0; 590*6ac73095SBeniamino Galvani fail: 591*6ac73095SBeniamino Galvani for (i--; i >= 0; i--) 592*6ac73095SBeniamino Galvani gpiochip_remove(&pc->domains[i].chip); 593*6ac73095SBeniamino Galvani 594*6ac73095SBeniamino Galvani return ret; 595*6ac73095SBeniamino Galvani } 596*6ac73095SBeniamino Galvani 597*6ac73095SBeniamino Galvani static struct meson_domain_data *meson_get_domain_data(struct meson_pinctrl *pc, 598*6ac73095SBeniamino Galvani struct device_node *np) 599*6ac73095SBeniamino Galvani { 600*6ac73095SBeniamino Galvani int i; 601*6ac73095SBeniamino Galvani 602*6ac73095SBeniamino Galvani for (i = 0; i < pc->data->num_domains; i++) { 603*6ac73095SBeniamino Galvani if (!strcmp(np->name, pc->data->domain_data[i].name)) 604*6ac73095SBeniamino Galvani return &pc->data->domain_data[i]; 605*6ac73095SBeniamino Galvani } 606*6ac73095SBeniamino Galvani 607*6ac73095SBeniamino Galvani return NULL; 608*6ac73095SBeniamino Galvani } 609*6ac73095SBeniamino Galvani 610*6ac73095SBeniamino Galvani static struct regmap_config meson_regmap_config = { 611*6ac73095SBeniamino Galvani .reg_bits = 32, 612*6ac73095SBeniamino Galvani .val_bits = 32, 613*6ac73095SBeniamino Galvani .reg_stride = 4, 614*6ac73095SBeniamino Galvani }; 615*6ac73095SBeniamino Galvani 616*6ac73095SBeniamino Galvani static struct regmap *meson_map_resource(struct meson_pinctrl *pc, 617*6ac73095SBeniamino Galvani struct device_node *node, char *name) 618*6ac73095SBeniamino Galvani { 619*6ac73095SBeniamino Galvani struct resource res; 620*6ac73095SBeniamino Galvani void __iomem *base; 621*6ac73095SBeniamino Galvani int i; 622*6ac73095SBeniamino Galvani 623*6ac73095SBeniamino Galvani i = of_property_match_string(node, "reg-names", name); 624*6ac73095SBeniamino Galvani if (of_address_to_resource(node, i, &res)) 625*6ac73095SBeniamino Galvani return ERR_PTR(-ENOENT); 626*6ac73095SBeniamino Galvani 627*6ac73095SBeniamino Galvani base = devm_ioremap_resource(pc->dev, &res); 628*6ac73095SBeniamino Galvani if (IS_ERR(base)) 629*6ac73095SBeniamino Galvani return ERR_CAST(base); 630*6ac73095SBeniamino Galvani 631*6ac73095SBeniamino Galvani meson_regmap_config.max_register = resource_size(&res) - 4; 632*6ac73095SBeniamino Galvani meson_regmap_config.name = devm_kasprintf(pc->dev, GFP_KERNEL, 633*6ac73095SBeniamino Galvani "%s-%s", node->name, 634*6ac73095SBeniamino Galvani name); 635*6ac73095SBeniamino Galvani if (!meson_regmap_config.name) 636*6ac73095SBeniamino Galvani return ERR_PTR(-ENOMEM); 637*6ac73095SBeniamino Galvani 638*6ac73095SBeniamino Galvani return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config); 639*6ac73095SBeniamino Galvani } 640*6ac73095SBeniamino Galvani 641*6ac73095SBeniamino Galvani static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, 642*6ac73095SBeniamino Galvani struct device_node *node) 643*6ac73095SBeniamino Galvani { 644*6ac73095SBeniamino Galvani struct device_node *np; 645*6ac73095SBeniamino Galvani struct meson_domain *domain; 646*6ac73095SBeniamino Galvani int i = 0, num_domains = 0; 647*6ac73095SBeniamino Galvani 648*6ac73095SBeniamino Galvani for_each_child_of_node(node, np) { 649*6ac73095SBeniamino Galvani if (!of_find_property(np, "gpio-controller", NULL)) 650*6ac73095SBeniamino Galvani continue; 651*6ac73095SBeniamino Galvani num_domains++; 652*6ac73095SBeniamino Galvani } 653*6ac73095SBeniamino Galvani 654*6ac73095SBeniamino Galvani if (num_domains != pc->data->num_domains) { 655*6ac73095SBeniamino Galvani dev_err(pc->dev, "wrong number of subnodes\n"); 656*6ac73095SBeniamino Galvani return -EINVAL; 657*6ac73095SBeniamino Galvani } 658*6ac73095SBeniamino Galvani 659*6ac73095SBeniamino Galvani pc->domains = devm_kzalloc(pc->dev, num_domains * 660*6ac73095SBeniamino Galvani sizeof(struct meson_domain), GFP_KERNEL); 661*6ac73095SBeniamino Galvani if (!pc->domains) 662*6ac73095SBeniamino Galvani return -ENOMEM; 663*6ac73095SBeniamino Galvani 664*6ac73095SBeniamino Galvani for_each_child_of_node(node, np) { 665*6ac73095SBeniamino Galvani if (!of_find_property(np, "gpio-controller", NULL)) 666*6ac73095SBeniamino Galvani continue; 667*6ac73095SBeniamino Galvani 668*6ac73095SBeniamino Galvani domain = &pc->domains[i]; 669*6ac73095SBeniamino Galvani 670*6ac73095SBeniamino Galvani domain->data = meson_get_domain_data(pc, np); 671*6ac73095SBeniamino Galvani if (!domain->data) { 672*6ac73095SBeniamino Galvani dev_err(pc->dev, "domain data not found for node %s\n", 673*6ac73095SBeniamino Galvani np->name); 674*6ac73095SBeniamino Galvani return -ENODEV; 675*6ac73095SBeniamino Galvani } 676*6ac73095SBeniamino Galvani 677*6ac73095SBeniamino Galvani domain->of_node = np; 678*6ac73095SBeniamino Galvani 679*6ac73095SBeniamino Galvani domain->reg_mux = meson_map_resource(pc, np, "mux"); 680*6ac73095SBeniamino Galvani if (IS_ERR(domain->reg_mux)) { 681*6ac73095SBeniamino Galvani dev_err(pc->dev, "mux registers not found\n"); 682*6ac73095SBeniamino Galvani return PTR_ERR(domain->reg_mux); 683*6ac73095SBeniamino Galvani } 684*6ac73095SBeniamino Galvani 685*6ac73095SBeniamino Galvani domain->reg_pull = meson_map_resource(pc, np, "pull"); 686*6ac73095SBeniamino Galvani if (IS_ERR(domain->reg_pull)) { 687*6ac73095SBeniamino Galvani dev_err(pc->dev, "pull registers not found\n"); 688*6ac73095SBeniamino Galvani return PTR_ERR(domain->reg_pull); 689*6ac73095SBeniamino Galvani } 690*6ac73095SBeniamino Galvani 691*6ac73095SBeniamino Galvani domain->reg_pullen = meson_map_resource(pc, np, "pull-enable"); 692*6ac73095SBeniamino Galvani /* Use pull region if pull-enable one is not present */ 693*6ac73095SBeniamino Galvani if (IS_ERR(domain->reg_pullen)) 694*6ac73095SBeniamino Galvani domain->reg_pullen = domain->reg_pull; 695*6ac73095SBeniamino Galvani 696*6ac73095SBeniamino Galvani domain->reg_gpio = meson_map_resource(pc, np, "gpio"); 697*6ac73095SBeniamino Galvani if (IS_ERR(domain->reg_gpio)) { 698*6ac73095SBeniamino Galvani dev_err(pc->dev, "gpio registers not found\n"); 699*6ac73095SBeniamino Galvani return PTR_ERR(domain->reg_gpio); 700*6ac73095SBeniamino Galvani } 701*6ac73095SBeniamino Galvani 702*6ac73095SBeniamino Galvani i++; 703*6ac73095SBeniamino Galvani } 704*6ac73095SBeniamino Galvani 705*6ac73095SBeniamino Galvani return 0; 706*6ac73095SBeniamino Galvani } 707*6ac73095SBeniamino Galvani 708*6ac73095SBeniamino Galvani static int meson_pinctrl_probe(struct platform_device *pdev) 709*6ac73095SBeniamino Galvani { 710*6ac73095SBeniamino Galvani const struct of_device_id *match; 711*6ac73095SBeniamino Galvani struct device *dev = &pdev->dev; 712*6ac73095SBeniamino Galvani struct meson_pinctrl *pc; 713*6ac73095SBeniamino Galvani int ret; 714*6ac73095SBeniamino Galvani 715*6ac73095SBeniamino Galvani pc = devm_kzalloc(dev, sizeof(struct meson_pinctrl), GFP_KERNEL); 716*6ac73095SBeniamino Galvani if (!pc) 717*6ac73095SBeniamino Galvani return -ENOMEM; 718*6ac73095SBeniamino Galvani 719*6ac73095SBeniamino Galvani pc->dev = dev; 720*6ac73095SBeniamino Galvani match = of_match_node(meson_pinctrl_dt_match, pdev->dev.of_node); 721*6ac73095SBeniamino Galvani pc->data = (struct meson_pinctrl_data *)match->data; 722*6ac73095SBeniamino Galvani 723*6ac73095SBeniamino Galvani ret = meson_pinctrl_parse_dt(pc, pdev->dev.of_node); 724*6ac73095SBeniamino Galvani if (ret) 725*6ac73095SBeniamino Galvani return ret; 726*6ac73095SBeniamino Galvani 727*6ac73095SBeniamino Galvani pc->desc.name = "pinctrl-meson"; 728*6ac73095SBeniamino Galvani pc->desc.owner = THIS_MODULE; 729*6ac73095SBeniamino Galvani pc->desc.pctlops = &meson_pctrl_ops; 730*6ac73095SBeniamino Galvani pc->desc.pmxops = &meson_pmx_ops; 731*6ac73095SBeniamino Galvani pc->desc.confops = &meson_pinconf_ops; 732*6ac73095SBeniamino Galvani pc->desc.pins = pc->data->pins; 733*6ac73095SBeniamino Galvani pc->desc.npins = pc->data->num_pins; 734*6ac73095SBeniamino Galvani 735*6ac73095SBeniamino Galvani pc->pcdev = pinctrl_register(&pc->desc, pc->dev, pc); 736*6ac73095SBeniamino Galvani if (!pc->pcdev) { 737*6ac73095SBeniamino Galvani dev_err(pc->dev, "can't register pinctrl device"); 738*6ac73095SBeniamino Galvani return -EINVAL; 739*6ac73095SBeniamino Galvani } 740*6ac73095SBeniamino Galvani 741*6ac73095SBeniamino Galvani ret = meson_gpiolib_register(pc); 742*6ac73095SBeniamino Galvani if (ret) { 743*6ac73095SBeniamino Galvani pinctrl_unregister(pc->pcdev); 744*6ac73095SBeniamino Galvani return ret; 745*6ac73095SBeniamino Galvani } 746*6ac73095SBeniamino Galvani 747*6ac73095SBeniamino Galvani return 0; 748*6ac73095SBeniamino Galvani } 749*6ac73095SBeniamino Galvani 750*6ac73095SBeniamino Galvani static struct platform_driver meson_pinctrl_driver = { 751*6ac73095SBeniamino Galvani .probe = meson_pinctrl_probe, 752*6ac73095SBeniamino Galvani .driver = { 753*6ac73095SBeniamino Galvani .name = "meson-pinctrl", 754*6ac73095SBeniamino Galvani .of_match_table = meson_pinctrl_dt_match, 755*6ac73095SBeniamino Galvani }, 756*6ac73095SBeniamino Galvani }; 757*6ac73095SBeniamino Galvani module_platform_driver(meson_pinctrl_driver); 758*6ac73095SBeniamino Galvani 759*6ac73095SBeniamino Galvani MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); 760*6ac73095SBeniamino Galvani MODULE_DESCRIPTION("Amlogic Meson pinctrl driver"); 761*6ac73095SBeniamino Galvani MODULE_LICENSE("GPL v2"); 762