diff options
Diffstat (limited to 'drivers/pinctrl/meson/pinctrl-meson.c')
-rw-r--r-- | drivers/pinctrl/meson/pinctrl-meson.c | 200 |
1 files changed, 28 insertions, 172 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index 66ed70c12733..29a458da78db 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -31,10 +31,6 @@ * In some cases the register ranges for pull enable and pull * direction are the same and thus there are only 3 register ranges. * - * Every pinmux group can be enabled by a specific bit in the first - * register range; when all groups for a given pin are disabled the - * pin acts as a GPIO. - * * For the pull and GPIO configuration every bank uses a contiguous * set of bits in the register sets described above; the same register * can be shared by more banks with different offsets. @@ -50,6 +46,7 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/of_device.h> #include <linux/pinctrl/pinconf-generic.h> #include <linux/pinctrl/pinconf.h> #include <linux/pinctrl/pinctrl.h> @@ -147,94 +144,24 @@ static const struct pinctrl_ops meson_pctrl_ops = { .pin_dbg_show = meson_pin_dbg_show, }; -/** - * meson_pmx_disable_other_groups() - disable other groups using a given pin - * - * @pc: meson pin controller device - * @pin: number of the pin - * @sel_group: index of the selected group, or -1 if none - * - * The function disables all pinmux groups using a pin except the - * selected one. If @sel_group is -1 all groups are disabled, leaving - * the pin in GPIO mode. - */ -static void meson_pmx_disable_other_groups(struct meson_pinctrl *pc, - unsigned int pin, int sel_group) -{ - struct meson_pmx_group *group; - int i, j; - - for (i = 0; i < pc->data->num_groups; i++) { - group = &pc->data->groups[i]; - if (group->is_gpio || i == sel_group) - continue; - - for (j = 0; j < group->num_pins; j++) { - if (group->pins[j] == pin) { - /* We have found a group using the pin */ - regmap_update_bits(pc->reg_mux, - group->reg * 4, - BIT(group->bit), 0); - } - } - } -} - -static int meson_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_num, - unsigned group_num) -{ - struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); - struct meson_pmx_func *func = &pc->data->funcs[func_num]; - struct meson_pmx_group *group = &pc->data->groups[group_num]; - int i, ret = 0; - - dev_dbg(pc->dev, "enable function %s, group %s\n", func->name, - group->name); - - /* - * Disable groups using the same pin. - * The selected group is not disabled to avoid glitches. - */ - for (i = 0; i < group->num_pins; i++) - meson_pmx_disable_other_groups(pc, group->pins[i], group_num); - - /* Function 0 (GPIO) doesn't need any additional setting */ - if (func_num) - ret = regmap_update_bits(pc->reg_mux, group->reg * 4, - BIT(group->bit), BIT(group->bit)); - - return ret; -} - -static int meson_pmx_request_gpio(struct pinctrl_dev *pcdev, - struct pinctrl_gpio_range *range, - unsigned offset) -{ - struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); - - meson_pmx_disable_other_groups(pc, offset, -1); - - return 0; -} - -static int meson_pmx_get_funcs_count(struct pinctrl_dev *pcdev) +int meson_pmx_get_funcs_count(struct pinctrl_dev *pcdev) { struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); return pc->data->num_funcs; } -static const char *meson_pmx_get_func_name(struct pinctrl_dev *pcdev, - unsigned selector) +const char *meson_pmx_get_func_name(struct pinctrl_dev *pcdev, + unsigned selector) { struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); return pc->data->funcs[selector].name; } -static int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector, - const char * const **groups, - unsigned * const num_groups) +int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector, + const char * const **groups, + unsigned * const num_groups) { struct meson_pinctrl *pc = pinctrl_dev_get_drvdata(pcdev); @@ -244,14 +171,6 @@ static int meson_pmx_get_groups(struct pinctrl_dev *pcdev, unsigned selector, return 0; } -static const struct pinmux_ops meson_pmx_ops = { - .set_mux = meson_pmx_set_mux, - .get_functions_count = meson_pmx_get_funcs_count, - .get_function_name = meson_pmx_get_func_name, - .get_function_groups = meson_pmx_get_groups, - .gpio_request_enable = meson_pmx_request_gpio, -}; - static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin, unsigned long *configs, unsigned num_configs) { @@ -399,7 +318,7 @@ static int meson_pinconf_group_set(struct pinctrl_dev *pcdev, static int meson_pinconf_group_get(struct pinctrl_dev *pcdev, unsigned int group, unsigned long *config) { - return -ENOSYS; + return -ENOTSUPP; } static const struct pinconf_ops meson_pinconf_ops = { @@ -410,31 +329,18 @@ static const struct pinconf_ops meson_pinconf_ops = { .is_generic = true, }; -static int meson_gpio_request(struct gpio_chip *chip, unsigned gpio) -{ - return pinctrl_request_gpio(chip->base + gpio); -} - -static void meson_gpio_free(struct gpio_chip *chip, unsigned gpio) -{ - struct meson_pinctrl *pc = gpiochip_get_data(chip); - - pinctrl_free_gpio(pc->data->pin_base + gpio); -} - static int meson_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) { struct meson_pinctrl *pc = gpiochip_get_data(chip); - unsigned int reg, bit, pin; + unsigned int reg, bit; struct meson_bank *bank; int ret; - pin = pc->data->pin_base + gpio; - ret = meson_get_bank(pc, pin, &bank); + ret = meson_get_bank(pc, gpio, &bank); if (ret) return ret; - meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); + meson_calc_reg_and_bit(bank, gpio, REG_DIR, ®, &bit); return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), BIT(bit)); } @@ -443,21 +349,20 @@ static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value) { struct meson_pinctrl *pc = gpiochip_get_data(chip); - unsigned int reg, bit, pin; + unsigned int reg, bit; struct meson_bank *bank; int ret; - pin = pc->data->pin_base + gpio; - ret = meson_get_bank(pc, pin, &bank); + ret = meson_get_bank(pc, gpio, &bank); if (ret) return ret; - meson_calc_reg_and_bit(bank, pin, REG_DIR, ®, &bit); + meson_calc_reg_and_bit(bank, gpio, REG_DIR, ®, &bit); ret = regmap_update_bits(pc->reg_gpio, reg, BIT(bit), 0); if (ret) return ret; - meson_calc_reg_and_bit(bank, pin, REG_OUT, ®, &bit); + meson_calc_reg_and_bit(bank, gpio, REG_OUT, ®, &bit); return regmap_update_bits(pc->reg_gpio, reg, BIT(bit), value ? BIT(bit) : 0); } @@ -465,16 +370,15 @@ static int meson_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) { struct meson_pinctrl *pc = gpiochip_get_data(chip); - unsigned int reg, bit, pin; + unsigned int reg, bit; struct meson_bank *bank; int ret; - pin = pc->data->pin_base + gpio; - ret = meson_get_bank(pc, pin, &bank); + ret = meson_get_bank(pc, gpio, &bank); if (ret) return; - meson_calc_reg_and_bit(bank, pin, REG_OUT, ®, &bit); + meson_calc_reg_and_bit(bank, gpio, REG_OUT, ®, &bit); regmap_update_bits(pc->reg_gpio, reg, BIT(bit), value ? BIT(bit) : 0); } @@ -482,70 +386,33 @@ static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value) static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio) { struct meson_pinctrl *pc = gpiochip_get_data(chip); - unsigned int reg, bit, val, pin; + unsigned int reg, bit, val; struct meson_bank *bank; int ret; - pin = pc->data->pin_base + gpio; - ret = meson_get_bank(pc, pin, &bank); + ret = meson_get_bank(pc, gpio, &bank); if (ret) return ret; - meson_calc_reg_and_bit(bank, pin, REG_IN, ®, &bit); + meson_calc_reg_and_bit(bank, gpio, REG_IN, ®, &bit); regmap_read(pc->reg_gpio, reg, &val); return !!(val & BIT(bit)); } -static const struct of_device_id meson_pinctrl_dt_match[] = { - { - .compatible = "amlogic,meson8-cbus-pinctrl", - .data = &meson8_cbus_pinctrl_data, - }, - { - .compatible = "amlogic,meson8b-cbus-pinctrl", - .data = &meson8b_cbus_pinctrl_data, - }, - { - .compatible = "amlogic,meson8-aobus-pinctrl", - .data = &meson8_aobus_pinctrl_data, - }, - { - .compatible = "amlogic,meson8b-aobus-pinctrl", - .data = &meson8b_aobus_pinctrl_data, - }, - { - .compatible = "amlogic,meson-gxbb-periphs-pinctrl", - .data = &meson_gxbb_periphs_pinctrl_data, - }, - { - .compatible = "amlogic,meson-gxbb-aobus-pinctrl", - .data = &meson_gxbb_aobus_pinctrl_data, - }, - { - .compatible = "amlogic,meson-gxl-periphs-pinctrl", - .data = &meson_gxl_periphs_pinctrl_data, - }, - { - .compatible = "amlogic,meson-gxl-aobus-pinctrl", - .data = &meson_gxl_aobus_pinctrl_data, - }, - { }, -}; - static int meson_gpiolib_register(struct meson_pinctrl *pc) { int ret; pc->chip.label = pc->data->name; pc->chip.parent = pc->dev; - pc->chip.request = meson_gpio_request; - pc->chip.free = meson_gpio_free; + pc->chip.request = gpiochip_generic_request; + pc->chip.free = gpiochip_generic_free; pc->chip.direction_input = meson_gpio_direction_input; pc->chip.direction_output = meson_gpio_direction_output; pc->chip.get = meson_gpio_get; pc->chip.set = meson_gpio_set; - pc->chip.base = pc->data->pin_base; + pc->chip.base = -1; pc->chip.ngpio = pc->data->num_pins; pc->chip.can_sleep = false; pc->chip.of_node = pc->of_node; @@ -640,9 +507,8 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, return 0; } -static int meson_pinctrl_probe(struct platform_device *pdev) +int meson_pinctrl_probe(struct platform_device *pdev) { - const struct of_device_id *match; struct device *dev = &pdev->dev; struct meson_pinctrl *pc; int ret; @@ -652,17 +518,16 @@ static int meson_pinctrl_probe(struct platform_device *pdev) return -ENOMEM; pc->dev = dev; - match = of_match_node(meson_pinctrl_dt_match, pdev->dev.of_node); - pc->data = (struct meson_pinctrl_data *) match->data; + pc->data = (struct meson_pinctrl_data *) of_device_get_match_data(dev); - ret = meson_pinctrl_parse_dt(pc, pdev->dev.of_node); + ret = meson_pinctrl_parse_dt(pc, dev->of_node); if (ret) return ret; pc->desc.name = "pinctrl-meson"; pc->desc.owner = THIS_MODULE; pc->desc.pctlops = &meson_pctrl_ops; - pc->desc.pmxops = &meson_pmx_ops; + pc->desc.pmxops = pc->data->pmx_ops; pc->desc.confops = &meson_pinconf_ops; pc->desc.pins = pc->data->pins; pc->desc.npins = pc->data->num_pins; @@ -675,12 +540,3 @@ static int meson_pinctrl_probe(struct platform_device *pdev) return meson_gpiolib_register(pc); } - -static struct platform_driver meson_pinctrl_driver = { - .probe = meson_pinctrl_probe, - .driver = { - .name = "meson-pinctrl", - .of_match_table = meson_pinctrl_dt_match, - }, -}; -builtin_platform_driver(meson_pinctrl_driver); |