Skip to content

Commit

Permalink
gpio: mpc8xxx: handle differences between incarnations at a single place
Browse files Browse the repository at this point in the history
The gpio controllers that are handled by the mpc8xxx driver differ
slightly. Up to now some differences were handled by use of
of_device_is_compatible, others by use of struct of_device_id's data.

To make this consistent and easily extendable handle the differences at
a single place.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Uwe Kleine-König authored and Linus Walleij committed Jul 27, 2015
1 parent 4183afe commit 82e39b0
Showing 1 changed file with 38 additions and 11 deletions.
49 changes: 38 additions & 11 deletions drivers/gpio/gpio-mpc8xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,17 +312,13 @@ static struct irq_chip mpc8xxx_irq_chip = {
.irq_unmask = mpc8xxx_irq_unmask,
.irq_mask = mpc8xxx_irq_mask,
.irq_ack = mpc8xxx_irq_ack,
/* this might get overwritten in mpc8xxx_probe() */
.irq_set_type = mpc8xxx_irq_set_type,
};

static int mpc8xxx_gpio_irq_map(struct irq_domain *h, unsigned int irq,
irq_hw_number_t hwirq)
{
struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;

if (mpc8xxx_gc->of_dev_id_data)
mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;

irq_set_chip_data(irq, h->host_data);
irq_set_chip_and_handler(irq, &mpc8xxx_irq_chip, handle_level_irq);

Expand All @@ -334,11 +330,32 @@ static const struct irq_domain_ops mpc8xxx_gpio_irq_ops = {
.xlate = irq_domain_xlate_twocell,
};

struct mpc8xxx_gpio_devtype {
int (*gpio_dir_out)(struct gpio_chip *, unsigned int, int);
int (*gpio_get)(struct gpio_chip *, unsigned int);
int (*irq_set_type)(struct irq_data *, unsigned int);
};

static const struct mpc8xxx_gpio_devtype mpc512x_gpio_devtype = {
.gpio_dir_out = mpc5121_gpio_dir_out,
.irq_set_type = mpc512x_irq_set_type,
};

static const struct mpc8xxx_gpio_devtype mpc8572_gpio_devtype = {
.gpio_get = mpc8572_gpio_get,
};

static const struct mpc8xxx_gpio_devtype mpc8xxx_gpio_devtype_default = {
.gpio_dir_out = mpc8xxx_gpio_dir_out,
.gpio_get = mpc8xxx_gpio_get,
.irq_set_type = mpc8xxx_irq_set_type,
};

static const struct of_device_id mpc8xxx_gpio_ids[] = {
{ .compatible = "fsl,mpc8349-gpio", },
{ .compatible = "fsl,mpc8572-gpio", },
{ .compatible = "fsl,mpc8572-gpio", .data = &mpc8572_gpio_devtype, },
{ .compatible = "fsl,mpc8610-gpio", },
{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
{ .compatible = "fsl,mpc5121-gpio", .data = &mpc512x_gpio_devtype, },
{ .compatible = "fsl,pq3-gpio", },
{ .compatible = "fsl,qoriq-gpio", },
{}
Expand All @@ -351,6 +368,8 @@ static int mpc8xxx_probe(struct platform_device *pdev)
struct of_mm_gpio_chip *mm_gc;
struct gpio_chip *gc;
const struct of_device_id *id;
const struct mpc8xxx_gpio_devtype *devtype =
of_device_get_match_data(&pdev->dev);
int ret;

mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL);
Expand All @@ -367,10 +386,18 @@ static int mpc8xxx_probe(struct platform_device *pdev)
mm_gc->save_regs = mpc8xxx_gpio_save_regs;
gc->ngpio = MPC8XXX_GPIO_PINS;
gc->direction_input = mpc8xxx_gpio_dir_in;
gc->direction_output = of_device_is_compatible(np, "fsl,mpc5121-gpio") ?
mpc5121_gpio_dir_out : mpc8xxx_gpio_dir_out;
gc->get = of_device_is_compatible(np, "fsl,mpc8572-gpio") ?
mpc8572_gpio_get : mpc8xxx_gpio_get;

if (!devtype)
devtype = &mpc8xxx_gpio_devtype_default;

/*
* It's assumed that only a single type of gpio controller is available
* on the current machine, so overwriting global data is fine.
*/
mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type;

gc->direction_output = devtype->gpio_dir_out ?: mpc8xxx_gpio_dir_out;
gc->get = devtype->gpio_get ?: mpc8xxx_gpio_get;
gc->set = mpc8xxx_gpio_set;
gc->set_multiple = mpc8xxx_gpio_set_multiple;
gc->to_irq = mpc8xxx_gpio_to_irq;
Expand Down

0 comments on commit 82e39b0

Please sign in to comment.