diff options
author | Carlo Caione <carlo@endlessm.com> | 2016-03-01 23:04:34 +0100 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2016-03-09 13:00:28 +0700 |
commit | 9dab1868ec0db4bce44db2759beadf1b2156085a (patch) | |
tree | 99f1a7baf782f0c59fb8d7aa5647b489e99d78e8 /drivers/pinctrl/meson/pinctrl-meson.c | |
parent | ac1afc46573a7d5447f23be5f88bc43580a92530 (diff) | |
download | linux-9dab1868ec0db4bce44db2759beadf1b2156085a.tar.gz linux-9dab1868ec0db4bce44db2759beadf1b2156085a.tar.bz2 linux-9dab1868ec0db4bce44db2759beadf1b2156085a.zip |
pinctrl: amlogic: Make driver independent from two-domain configuration
In the Amlogic Meson8 / Meson8b platforms we have two different buses:
cbus and aobus, corresponding to 2 different power domains (regular and
always-on). On each bus a different set of registers is mapped to manage
muxes, GPIOs and in general to control a clear subset of the pins.
Considering this architecture, having two different pinctrl devices, one
for each bus / power domain, makes much more sense than just having one
single device.
Right now we have one single pin controller driver that uses two
different domains (represented by 'gpio' and 'gpio-ao' sub-nodes in the
DTS) to manage the set of registers on the two buses. This dual-domain
configuration is hardcoded into the driver that strictly requires one
domain for each bus in the same pin controller device.
With this patch we refactor the driver to allow splitting the driver in
two parts. This change is needed to have a proper description of the HW
in the device-tree where we want to introduce aobus and cbus.
Signed-off-by: Carlo Caione <carlo@endlessm.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/meson/pinctrl-meson.c')
-rw-r--r-- | drivers/pinctrl/meson/pinctrl-meson.c | 135 |
1 files changed, 59 insertions, 76 deletions
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index 3dd1a446f6f4..0bdb8fd3afd1 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -103,15 +103,13 @@ static int meson_get_domain_and_bank(struct meson_pinctrl *pc, unsigned int pin, struct meson_bank **bank) { struct meson_domain *d; - int i; - for (i = 0; i < pc->data->num_domains; i++) { - d = &pc->domains[i]; - if (pin >= d->data->pin_base && - pin < d->data->pin_base + d->data->num_pins) { - *domain = d; - return meson_get_bank(d, pin, bank); - } + d = pc->domain; + + if (pin >= d->data->pin_base && + pin < d->data->pin_base + d->data->num_pins) { + *domain = d; + return meson_get_bank(d, pin, bank); } return -EINVAL; @@ -203,7 +201,7 @@ static void meson_pmx_disable_other_groups(struct meson_pinctrl *pc, for (j = 0; j < group->num_pins; j++) { if (group->pins[j] == pin) { /* We have found a group using the pin */ - domain = &pc->domains[group->domain]; + domain = pc->domain; regmap_update_bits(domain->reg_mux, group->reg * 4, BIT(group->bit), 0); @@ -218,7 +216,7 @@ static int meson_pmx_set_mux(struct pinctrl_dev *pcdev, unsigned func_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]; - struct meson_domain *domain = &pc->domains[group->domain]; + struct meson_domain *domain = pc->domain; int i, ret = 0; dev_dbg(pc->dev, "enable function %s, group %s\n", func->name, @@ -536,12 +534,20 @@ static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio) static const struct of_device_id meson_pinctrl_dt_match[] = { { - .compatible = "amlogic,meson8-pinctrl", - .data = &meson8_pinctrl_data, + .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-pinctrl", - .data = &meson8b_pinctrl_data, + .compatible = "amlogic,meson8b-aobus-pinctrl", + .data = &meson8b_aobus_pinctrl_data, }, { }, }; @@ -549,62 +555,46 @@ static const struct of_device_id meson_pinctrl_dt_match[] = { static int meson_gpiolib_register(struct meson_pinctrl *pc) { struct meson_domain *domain; - int i, ret; + int ret; - for (i = 0; i < pc->data->num_domains; i++) { - domain = &pc->domains[i]; - - domain->chip.label = domain->data->name; - domain->chip.parent = pc->dev; - domain->chip.request = meson_gpio_request; - domain->chip.free = meson_gpio_free; - domain->chip.direction_input = meson_gpio_direction_input; - domain->chip.direction_output = meson_gpio_direction_output; - domain->chip.get = meson_gpio_get; - domain->chip.set = meson_gpio_set; - domain->chip.base = domain->data->pin_base; - domain->chip.ngpio = domain->data->num_pins; - domain->chip.can_sleep = false; - domain->chip.of_node = domain->of_node; - domain->chip.of_gpio_n_cells = 2; - - ret = gpiochip_add_data(&domain->chip, domain); - if (ret) { - dev_err(pc->dev, "can't add gpio chip %s\n", - domain->data->name); - goto fail; - } + domain = pc->domain; + + domain->chip.label = domain->data->name; + domain->chip.parent = pc->dev; + domain->chip.request = meson_gpio_request; + domain->chip.free = meson_gpio_free; + domain->chip.direction_input = meson_gpio_direction_input; + domain->chip.direction_output = meson_gpio_direction_output; + domain->chip.get = meson_gpio_get; + domain->chip.set = meson_gpio_set; + domain->chip.base = domain->data->pin_base; + domain->chip.ngpio = domain->data->num_pins; + domain->chip.can_sleep = false; + domain->chip.of_node = domain->of_node; + domain->chip.of_gpio_n_cells = 2; + + ret = gpiochip_add_data(&domain->chip, domain); + if (ret) { + dev_err(pc->dev, "can't add gpio chip %s\n", + domain->data->name); + goto fail; + } - ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev), - 0, domain->data->pin_base, - domain->chip.ngpio); - if (ret) { - dev_err(pc->dev, "can't add pin range\n"); - goto fail; - } + ret = gpiochip_add_pin_range(&domain->chip, dev_name(pc->dev), + 0, domain->data->pin_base, + domain->chip.ngpio); + if (ret) { + dev_err(pc->dev, "can't add pin range\n"); + goto fail; } return 0; fail: - for (i--; i >= 0; i--) - gpiochip_remove(&pc->domains[i].chip); + gpiochip_remove(&pc->domain->chip); return ret; } -static struct meson_domain_data *meson_get_domain_data(struct meson_pinctrl *pc, - struct device_node *np) -{ - int i; - - for (i = 0; i < pc->data->num_domains; i++) { - if (!strcmp(np->name, pc->data->domain_data[i].name)) - return &pc->data->domain_data[i]; - } - - return NULL; -} - static struct regmap_config meson_regmap_config = { .reg_bits = 32, .val_bits = 32, @@ -641,7 +631,7 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, { struct device_node *np; struct meson_domain *domain; - int i = 0, num_domains = 0; + int num_domains = 0; for_each_child_of_node(node, np) { if (!of_find_property(np, "gpio-controller", NULL)) @@ -649,29 +639,22 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, num_domains++; } - if (num_domains != pc->data->num_domains) { + if (num_domains != 1) { dev_err(pc->dev, "wrong number of subnodes\n"); return -EINVAL; } - pc->domains = devm_kzalloc(pc->dev, num_domains * - sizeof(struct meson_domain), GFP_KERNEL); - if (!pc->domains) + pc->domain = devm_kzalloc(pc->dev, sizeof(struct meson_domain), GFP_KERNEL); + if (!pc->domain) return -ENOMEM; + domain = pc->domain; + domain->data = pc->data->domain_data; + for_each_child_of_node(node, np) { if (!of_find_property(np, "gpio-controller", NULL)) continue; - domain = &pc->domains[i]; - - domain->data = meson_get_domain_data(pc, np); - if (!domain->data) { - dev_err(pc->dev, "domain data not found for node %s\n", - np->name); - return -ENODEV; - } - domain->of_node = np; domain->reg_mux = meson_map_resource(pc, np, "mux"); @@ -697,7 +680,7 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc, return PTR_ERR(domain->reg_gpio); } - i++; + break; } return 0; @@ -716,7 +699,7 @@ static int meson_pinctrl_probe(struct platform_device *pdev) 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 *) match->data; ret = meson_pinctrl_parse_dt(pc, pdev->dev.of_node); if (ret) |