Skip to content

Commit

Permalink
pinctrl: amlogic: Make driver independent from two-domain configuration
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Carlo Caione authored and Linus Walleij committed Mar 9, 2016
1 parent ac1afc4 commit 9dab186
Show file tree
Hide file tree
Showing 4 changed files with 228 additions and 224 deletions.
135 changes: 59 additions & 76 deletions drivers/pinctrl/meson/pinctrl-meson.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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,
Expand Down Expand Up @@ -536,75 +534,67 @@ 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,
},
{ },
};

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,
Expand Down Expand Up @@ -641,37 +631,30 @@ 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))
continue;
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");
Expand All @@ -697,7 +680,7 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
return PTR_ERR(domain->reg_gpio);
}

i++;
break;
}

return 0;
Expand All @@ -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)
Expand Down
21 changes: 5 additions & 16 deletions drivers/pinctrl/meson/pinctrl-meson.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ struct meson_pmx_group {
bool is_gpio;
unsigned int reg;
unsigned int bit;
unsigned int domain;
};

/**
Expand Down Expand Up @@ -144,15 +143,14 @@ struct meson_pinctrl_data {
unsigned int num_pins;
unsigned int num_groups;
unsigned int num_funcs;
unsigned int num_domains;
};

struct meson_pinctrl {
struct device *dev;
struct pinctrl_dev *pcdev;
struct pinctrl_desc desc;
struct meson_pinctrl_data *data;
struct meson_domain *domains;
struct meson_domain *domain;
};

#define PIN(x, b) (b + x)
Expand All @@ -164,7 +162,6 @@ struct meson_pinctrl {
.num_pins = ARRAY_SIZE(grp ## _pins), \
.reg = r, \
.bit = b, \
.domain = 0, \
}

#define GPIO_GROUP(gpio, b) \
Expand All @@ -175,16 +172,6 @@ struct meson_pinctrl {
.is_gpio = true, \
}

#define GROUP_AO(grp, r, b) \
{ \
.name = #grp, \
.pins = grp ## _pins, \
.num_pins = ARRAY_SIZE(grp ## _pins), \
.reg = r, \
.bit = b, \
.domain = 1, \
}

#define FUNCTION(fn) \
{ \
.name = #fn, \
Expand All @@ -208,5 +195,7 @@ struct meson_pinctrl {

#define MESON_PIN(x, b) PINCTRL_PIN(PIN(x, b), #x)

extern struct meson_pinctrl_data meson8_pinctrl_data;
extern struct meson_pinctrl_data meson8b_pinctrl_data;
extern struct meson_pinctrl_data meson8_cbus_pinctrl_data;
extern struct meson_pinctrl_data meson8_aobus_pinctrl_data;
extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data;
extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data;
Loading

0 comments on commit 9dab186

Please sign in to comment.