diff options
| author | Quentin Schulz <quentin.schulz@free-electrons.com> | 2017-12-05 09:46:41 -0500 |
|---|---|---|
| committer | Linus Walleij <linus.walleij@linaro.org> | 2017-12-07 04:05:58 -0500 |
| commit | 23f75d7dfa92132e08e31640e0f641dcdea781b9 (patch) | |
| tree | 174e4f50e93914cc5500990eb1e5054f3f830908 /drivers/pinctrl | |
| parent | 449317a8b4c4ed47c2a51f864c4697ae57195b96 (diff) | |
pinctrl: axp209: add pinctrl features
The X-Powers AXP209 has 3 GPIOs. GPIO0/1 can each act either as a GPIO,
an ADC or a LDO regulator. GPIO2 can only act as a GPIO.
This adds the pinctrl features to the driver so GPIO0/1 can be used as
ADC or LDO regulator.
Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl')
| -rw-r--r-- | drivers/pinctrl/pinctrl-axp209.c | 304 |
1 files changed, 284 insertions, 20 deletions
diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c index 6ee7dc1418fa..48cb57dcc575 100644 --- a/drivers/pinctrl/pinctrl-axp209.c +++ b/drivers/pinctrl/pinctrl-axp209.c | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * AXP20x GPIO driver | 2 | * AXP20x pinctrl and GPIO driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com> | 4 | * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com> |
| 5 | * Copyright (C) 2017 Quentin Schulz <quentin.schulz@free-electrons.com> | ||
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
| @@ -18,6 +19,9 @@ | |||
| 18 | #include <linux/mfd/axp20x.h> | 19 | #include <linux/mfd/axp20x.h> |
| 19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 20 | #include <linux/of.h> | 21 | #include <linux/of.h> |
| 22 | #include <linux/pinctrl/pinconf-generic.h> | ||
| 23 | #include <linux/pinctrl/pinctrl.h> | ||
| 24 | #include <linux/pinctrl/pinmux.h> | ||
| 21 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 22 | #include <linux/regmap.h> | 26 | #include <linux/regmap.h> |
| 23 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| @@ -27,9 +31,52 @@ | |||
| 27 | #define AXP20X_GPIO_FUNCTION_OUT_HIGH 1 | 31 | #define AXP20X_GPIO_FUNCTION_OUT_HIGH 1 |
| 28 | #define AXP20X_GPIO_FUNCTION_INPUT 2 | 32 | #define AXP20X_GPIO_FUNCTION_INPUT 2 |
| 29 | 33 | ||
| 34 | #define AXP20X_FUNC_GPIO_OUT 0 | ||
| 35 | #define AXP20X_FUNC_GPIO_IN 1 | ||
| 36 | #define AXP20X_FUNC_LDO 2 | ||
| 37 | #define AXP20X_FUNC_ADC 3 | ||
| 38 | #define AXP20X_FUNCS_NB 4 | ||
| 39 | |||
| 40 | #define AXP20X_MUX_GPIO_OUT 0 | ||
| 41 | #define AXP20X_MUX_GPIO_IN BIT(1) | ||
| 42 | #define AXP20X_MUX_ADC BIT(2) | ||
| 43 | |||
| 44 | struct axp20x_pctrl_desc { | ||
| 45 | const struct pinctrl_pin_desc *pins; | ||
| 46 | unsigned int npins; | ||
| 47 | /* Stores the pins supporting LDO function. Bit offset is pin number. */ | ||
| 48 | u8 ldo_mask; | ||
| 49 | /* Stores the pins supporting ADC function. Bit offset is pin number. */ | ||
| 50 | u8 adc_mask; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct axp20x_pinctrl_function { | ||
| 54 | const char *name; | ||
| 55 | unsigned int muxval; | ||
| 56 | const char **groups; | ||
| 57 | unsigned int ngroups; | ||
| 58 | }; | ||
| 59 | |||
| 30 | struct axp20x_gpio { | 60 | struct axp20x_gpio { |
| 31 | struct gpio_chip chip; | 61 | struct gpio_chip chip; |
| 32 | struct regmap *regmap; | 62 | struct regmap *regmap; |
| 63 | struct pinctrl_dev *pctl_dev; | ||
| 64 | struct device *dev; | ||
| 65 | const struct axp20x_pctrl_desc *desc; | ||
| 66 | struct axp20x_pinctrl_function funcs[AXP20X_FUNCS_NB]; | ||
| 67 | }; | ||
| 68 | |||
| 69 | static const struct pinctrl_pin_desc axp209_pins[] = { | ||
| 70 | PINCTRL_PIN(0, "GPIO0"), | ||
| 71 | PINCTRL_PIN(1, "GPIO1"), | ||
| 72 | PINCTRL_PIN(2, "GPIO2"), | ||
| 73 | }; | ||
| 74 | |||
| 75 | static const struct axp20x_pctrl_desc axp20x_data = { | ||
| 76 | .pins = axp209_pins, | ||
| 77 | .npins = ARRAY_SIZE(axp209_pins), | ||
| 78 | .ldo_mask = BIT(0) | BIT(1), | ||
| 79 | .adc_mask = BIT(0) | BIT(1), | ||
| 33 | }; | 80 | }; |
| 34 | 81 | ||
| 35 | static int axp20x_gpio_get_reg(unsigned int offset) | 82 | static int axp20x_gpio_get_reg(unsigned int offset) |
| @@ -48,16 +95,7 @@ static int axp20x_gpio_get_reg(unsigned int offset) | |||
| 48 | 95 | ||
| 49 | static int axp20x_gpio_input(struct gpio_chip *chip, unsigned int offset) | 96 | static int axp20x_gpio_input(struct gpio_chip *chip, unsigned int offset) |
| 50 | { | 97 | { |
| 51 | struct axp20x_gpio *gpio = gpiochip_get_data(chip); | 98 | return pinctrl_gpio_direction_input(chip->base + offset); |
| 52 | int reg; | ||
| 53 | |||
| 54 | reg = axp20x_gpio_get_reg(offset); | ||
| 55 | if (reg < 0) | ||
| 56 | return reg; | ||
| 57 | |||
| 58 | return regmap_update_bits(gpio->regmap, reg, | ||
| 59 | AXP20X_GPIO_FUNCTIONS, | ||
| 60 | AXP20X_GPIO_FUNCTION_INPUT); | ||
| 61 | } | 99 | } |
| 62 | 100 | ||
| 63 | static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset) | 101 | static int axp20x_gpio_get(struct gpio_chip *chip, unsigned int offset) |
| @@ -106,29 +144,220 @@ static int axp20x_gpio_get_direction(struct gpio_chip *chip, | |||
| 106 | static int axp20x_gpio_output(struct gpio_chip *chip, unsigned int offset, | 144 | static int axp20x_gpio_output(struct gpio_chip *chip, unsigned int offset, |
| 107 | int value) | 145 | int value) |
| 108 | { | 146 | { |
| 147 | chip->set(chip, offset, value); | ||
| 148 | |||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
| 153 | int value) | ||
| 154 | { | ||
| 109 | struct axp20x_gpio *gpio = gpiochip_get_data(chip); | 155 | struct axp20x_gpio *gpio = gpiochip_get_data(chip); |
| 110 | int reg; | 156 | int reg; |
| 111 | 157 | ||
| 112 | reg = axp20x_gpio_get_reg(offset); | 158 | reg = axp20x_gpio_get_reg(offset); |
| 113 | if (reg < 0) | 159 | if (reg < 0) |
| 160 | return; | ||
| 161 | |||
| 162 | regmap_update_bits(gpio->regmap, reg, | ||
| 163 | AXP20X_GPIO_FUNCTIONS, | ||
| 164 | value ? AXP20X_GPIO_FUNCTION_OUT_HIGH : | ||
| 165 | AXP20X_GPIO_FUNCTION_OUT_LOW); | ||
| 166 | } | ||
| 167 | |||
| 168 | static int axp20x_pmx_set(struct pinctrl_dev *pctldev, unsigned int offset, | ||
| 169 | u8 config) | ||
| 170 | { | ||
| 171 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 172 | int reg; | ||
| 173 | |||
| 174 | reg = axp20x_gpio_get_reg(offset); | ||
| 175 | if (reg < 0) | ||
| 114 | return reg; | 176 | return reg; |
| 115 | 177 | ||
| 116 | return regmap_update_bits(gpio->regmap, reg, | 178 | return regmap_update_bits(gpio->regmap, reg, AXP20X_GPIO_FUNCTIONS, |
| 117 | AXP20X_GPIO_FUNCTIONS, | 179 | config); |
| 118 | value ? AXP20X_GPIO_FUNCTION_OUT_HIGH | ||
| 119 | : AXP20X_GPIO_FUNCTION_OUT_LOW); | ||
| 120 | } | 180 | } |
| 121 | 181 | ||
| 122 | static void axp20x_gpio_set(struct gpio_chip *chip, unsigned int offset, | 182 | static int axp20x_pmx_func_cnt(struct pinctrl_dev *pctldev) |
| 123 | int value) | 183 | { |
| 184 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 185 | |||
| 186 | return ARRAY_SIZE(gpio->funcs); | ||
| 187 | } | ||
| 188 | |||
| 189 | static const char *axp20x_pmx_func_name(struct pinctrl_dev *pctldev, | ||
| 190 | unsigned int selector) | ||
| 191 | { | ||
| 192 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 193 | |||
| 194 | return gpio->funcs[selector].name; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int axp20x_pmx_func_groups(struct pinctrl_dev *pctldev, | ||
| 198 | unsigned int selector, | ||
| 199 | const char * const **groups, | ||
| 200 | unsigned int *num_groups) | ||
| 201 | { | ||
| 202 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 203 | |||
| 204 | *groups = gpio->funcs[selector].groups; | ||
| 205 | *num_groups = gpio->funcs[selector].ngroups; | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static int axp20x_pmx_set_mux(struct pinctrl_dev *pctldev, | ||
| 211 | unsigned int function, unsigned int group) | ||
| 212 | { | ||
| 213 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 214 | unsigned int mask; | ||
| 215 | |||
| 216 | /* Every pin supports GPIO_OUT and GPIO_IN functions */ | ||
| 217 | if (function <= AXP20X_FUNC_GPIO_IN) | ||
| 218 | return axp20x_pmx_set(pctldev, group, | ||
| 219 | gpio->funcs[function].muxval); | ||
| 220 | |||
| 221 | if (function == AXP20X_FUNC_LDO) | ||
| 222 | mask = gpio->desc->ldo_mask; | ||
| 223 | else | ||
| 224 | mask = gpio->desc->adc_mask; | ||
| 225 | |||
| 226 | if (!(BIT(group) & mask)) | ||
| 227 | return -EINVAL; | ||
| 228 | |||
| 229 | /* | ||
| 230 | * We let the regulator framework handle the LDO muxing as muxing bits | ||
| 231 | * are basically also regulators on/off bits. It's better not to enforce | ||
| 232 | * any state of the regulator when selecting LDO mux so that we don't | ||
| 233 | * interfere with the regulator driver. | ||
| 234 | */ | ||
| 235 | if (function == AXP20X_FUNC_LDO) | ||
| 236 | return 0; | ||
| 237 | |||
| 238 | return axp20x_pmx_set(pctldev, group, gpio->funcs[function].muxval); | ||
| 239 | } | ||
| 240 | |||
| 241 | static int axp20x_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, | ||
| 242 | struct pinctrl_gpio_range *range, | ||
| 243 | unsigned int offset, bool input) | ||
| 244 | { | ||
| 245 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 246 | |||
| 247 | if (input) | ||
| 248 | return axp20x_pmx_set(pctldev, offset, | ||
| 249 | gpio->funcs[AXP20X_FUNC_GPIO_IN].muxval); | ||
| 250 | |||
| 251 | return axp20x_pmx_set(pctldev, offset, | ||
| 252 | gpio->funcs[AXP20X_FUNC_GPIO_OUT].muxval); | ||
| 253 | } | ||
| 254 | |||
| 255 | static const struct pinmux_ops axp20x_pmx_ops = { | ||
| 256 | .get_functions_count = axp20x_pmx_func_cnt, | ||
| 257 | .get_function_name = axp20x_pmx_func_name, | ||
| 258 | .get_function_groups = axp20x_pmx_func_groups, | ||
| 259 | .set_mux = axp20x_pmx_set_mux, | ||
| 260 | .gpio_set_direction = axp20x_pmx_gpio_set_direction, | ||
| 261 | .strict = true, | ||
| 262 | }; | ||
| 263 | |||
| 264 | static int axp20x_groups_cnt(struct pinctrl_dev *pctldev) | ||
| 265 | { | ||
| 266 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 267 | |||
| 268 | return gpio->desc->npins; | ||
| 269 | } | ||
| 270 | |||
| 271 | static int axp20x_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, | ||
| 272 | const unsigned int **pins, unsigned int *num_pins) | ||
| 273 | { | ||
| 274 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); | ||
| 275 | |||
| 276 | *pins = (unsigned int *)&gpio->desc->pins[selector]; | ||
| 277 | *num_pins = 1; | ||
| 278 | |||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static const char *axp20x_group_name(struct pinctrl_dev *pctldev, | ||
| 283 | unsigned int selector) | ||
| 124 | { | 284 | { |
| 125 | axp20x_gpio_output(chip, offset, value); | 285 | struct axp20x_gpio *gpio = pinctrl_dev_get_drvdata(pctldev); |
| 286 | |||
| 287 | return gpio->desc->pins[selector].name; | ||
| 288 | } | ||
| 289 | |||
| 290 | static const struct pinctrl_ops axp20x_pctrl_ops = { | ||
| 291 | .dt_node_to_map = pinconf_generic_dt_node_to_map_group, | ||
| 292 | .dt_free_map = pinconf_generic_dt_free_map, | ||
| 293 | .get_groups_count = axp20x_groups_cnt, | ||
| 294 | .get_group_name = axp20x_group_name, | ||
| 295 | .get_group_pins = axp20x_group_pins, | ||
| 296 | }; | ||
| 297 | |||
| 298 | static void axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask, | ||
| 299 | unsigned int mask_len, | ||
| 300 | struct axp20x_pinctrl_function *func, | ||
| 301 | const struct pinctrl_pin_desc *pins) | ||
| 302 | { | ||
| 303 | unsigned long int mask_cpy = mask; | ||
| 304 | const char **group; | ||
| 305 | unsigned int ngroups = hweight8(mask); | ||
| 306 | int bit; | ||
| 307 | |||
| 308 | func->ngroups = ngroups; | ||
| 309 | if (func->ngroups > 0) { | ||
| 310 | func->groups = devm_kzalloc(dev, ngroups * sizeof(const char *), | ||
| 311 | GFP_KERNEL); | ||
| 312 | group = func->groups; | ||
| 313 | for_each_set_bit(bit, &mask_cpy, mask_len) { | ||
| 314 | *group = pins[bit].name; | ||
| 315 | group++; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | static void axp20x_build_funcs_groups(struct platform_device *pdev) | ||
| 321 | { | ||
| 322 | struct axp20x_gpio *gpio = platform_get_drvdata(pdev); | ||
| 323 | int i, pin, npins = gpio->desc->npins; | ||
| 324 | |||
| 325 | gpio->funcs[AXP20X_FUNC_GPIO_OUT].name = "gpio_out"; | ||
| 326 | gpio->funcs[AXP20X_FUNC_GPIO_OUT].muxval = AXP20X_MUX_GPIO_OUT; | ||
| 327 | gpio->funcs[AXP20X_FUNC_GPIO_IN].name = "gpio_in"; | ||
| 328 | gpio->funcs[AXP20X_FUNC_GPIO_IN].muxval = AXP20X_MUX_GPIO_IN; | ||
| 329 | gpio->funcs[AXP20X_FUNC_LDO].name = "ldo"; | ||
| 330 | /* | ||
| 331 | * Muxval for LDO is useless as we won't use it. | ||
| 332 | * See comment in axp20x_pmx_set_mux. | ||
| 333 | */ | ||
| 334 | gpio->funcs[AXP20X_FUNC_ADC].name = "adc"; | ||
| 335 | gpio->funcs[AXP20X_FUNC_ADC].muxval = AXP20X_MUX_ADC; | ||
| 336 | |||
| 337 | /* Every pin supports GPIO_OUT and GPIO_IN functions */ | ||
| 338 | for (i = 0; i <= AXP20X_FUNC_GPIO_IN; i++) { | ||
| 339 | gpio->funcs[i].ngroups = npins; | ||
| 340 | gpio->funcs[i].groups = devm_kzalloc(&pdev->dev, | ||
| 341 | npins * sizeof(char *), | ||
| 342 | GFP_KERNEL); | ||
| 343 | for (pin = 0; pin < npins; pin++) | ||
| 344 | gpio->funcs[i].groups[pin] = gpio->desc->pins[pin].name; | ||
| 345 | } | ||
| 346 | |||
| 347 | axp20x_funcs_groups_from_mask(&pdev->dev, gpio->desc->ldo_mask, | ||
| 348 | npins, &gpio->funcs[AXP20X_FUNC_LDO], | ||
| 349 | gpio->desc->pins); | ||
| 350 | |||
| 351 | axp20x_funcs_groups_from_mask(&pdev->dev, gpio->desc->adc_mask, | ||
| 352 | npins, &gpio->funcs[AXP20X_FUNC_ADC], | ||
| 353 | gpio->desc->pins); | ||
| 126 | } | 354 | } |
| 127 | 355 | ||
| 128 | static int axp20x_gpio_probe(struct platform_device *pdev) | 356 | static int axp20x_gpio_probe(struct platform_device *pdev) |
| 129 | { | 357 | { |
| 130 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); | 358 | struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); |
| 131 | struct axp20x_gpio *gpio; | 359 | struct axp20x_gpio *gpio; |
| 360 | struct pinctrl_desc *pctrl_desc; | ||
| 132 | int ret; | 361 | int ret; |
| 133 | 362 | ||
| 134 | if (!of_device_is_available(pdev->dev.of_node)) | 363 | if (!of_device_is_available(pdev->dev.of_node)) |
| @@ -145,6 +374,8 @@ static int axp20x_gpio_probe(struct platform_device *pdev) | |||
| 145 | 374 | ||
| 146 | gpio->chip.base = -1; | 375 | gpio->chip.base = -1; |
| 147 | gpio->chip.can_sleep = true; | 376 | gpio->chip.can_sleep = true; |
| 377 | gpio->chip.request = gpiochip_generic_request; | ||
| 378 | gpio->chip.free = gpiochip_generic_free; | ||
| 148 | gpio->chip.parent = &pdev->dev; | 379 | gpio->chip.parent = &pdev->dev; |
| 149 | gpio->chip.label = dev_name(&pdev->dev); | 380 | gpio->chip.label = dev_name(&pdev->dev); |
| 150 | gpio->chip.owner = THIS_MODULE; | 381 | gpio->chip.owner = THIS_MODULE; |
| @@ -155,7 +386,30 @@ static int axp20x_gpio_probe(struct platform_device *pdev) | |||
| 155 | gpio->chip.direction_output = axp20x_gpio_output; | 386 | gpio->chip.direction_output = axp20x_gpio_output; |
| 156 | gpio->chip.ngpio = 3; | 387 | gpio->chip.ngpio = 3; |
| 157 | 388 | ||
| 389 | gpio->desc = &axp20x_data; | ||
| 158 | gpio->regmap = axp20x->regmap; | 390 | gpio->regmap = axp20x->regmap; |
| 391 | gpio->dev = &pdev->dev; | ||
| 392 | |||
| 393 | platform_set_drvdata(pdev, gpio); | ||
| 394 | |||
| 395 | axp20x_build_funcs_groups(pdev); | ||
| 396 | |||
| 397 | pctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctrl_desc), GFP_KERNEL); | ||
| 398 | if (!pctrl_desc) | ||
| 399 | return -ENOMEM; | ||
| 400 | |||
| 401 | pctrl_desc->name = dev_name(&pdev->dev); | ||
| 402 | pctrl_desc->owner = THIS_MODULE; | ||
| 403 | pctrl_desc->pins = gpio->desc->pins; | ||
| 404 | pctrl_desc->npins = gpio->desc->npins; | ||
| 405 | pctrl_desc->pctlops = &axp20x_pctrl_ops; | ||
| 406 | pctrl_desc->pmxops = &axp20x_pmx_ops; | ||
| 407 | |||
| 408 | gpio->pctl_dev = devm_pinctrl_register(&pdev->dev, pctrl_desc, gpio); | ||
| 409 | if (IS_ERR(gpio->pctl_dev)) { | ||
| 410 | dev_err(&pdev->dev, "couldn't register pinctrl driver\n"); | ||
| 411 | return PTR_ERR(gpio->pctl_dev); | ||
| 412 | } | ||
| 159 | 413 | ||
| 160 | ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); | 414 | ret = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio); |
| 161 | if (ret) { | 415 | if (ret) { |
| @@ -163,7 +417,16 @@ static int axp20x_gpio_probe(struct platform_device *pdev) | |||
| 163 | return ret; | 417 | return ret; |
| 164 | } | 418 | } |
| 165 | 419 | ||
| 166 | dev_info(&pdev->dev, "AXP209 GPIO driver loaded\n"); | 420 | ret = gpiochip_add_pin_range(&gpio->chip, dev_name(&pdev->dev), |
| 421 | gpio->desc->pins->number, | ||
| 422 | gpio->desc->pins->number, | ||
| 423 | gpio->desc->npins); | ||
| 424 | if (ret) { | ||
| 425 | dev_err(&pdev->dev, "failed to add pin range\n"); | ||
| 426 | return ret; | ||
| 427 | } | ||
| 428 | |||
| 429 | dev_info(&pdev->dev, "AXP209 pinctrl and GPIO driver loaded\n"); | ||
| 167 | 430 | ||
| 168 | return 0; | 431 | return 0; |
| 169 | } | 432 | } |
| @@ -185,5 +448,6 @@ static struct platform_driver axp20x_gpio_driver = { | |||
| 185 | module_platform_driver(axp20x_gpio_driver); | 448 | module_platform_driver(axp20x_gpio_driver); |
| 186 | 449 | ||
| 187 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); | 450 | MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>"); |
| 188 | MODULE_DESCRIPTION("AXP20x PMIC GPIO driver"); | 451 | MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>"); |
| 452 | MODULE_DESCRIPTION("AXP20x PMIC pinctrl and GPIO driver"); | ||
| 189 | MODULE_LICENSE("GPL"); | 453 | MODULE_LICENSE("GPL"); |
