diff options
Diffstat (limited to 'drivers/gpio/gpio-mpc8xxx.c')
| -rw-r--r-- | drivers/gpio/gpio-mpc8xxx.c | 70 | 
1 files changed, 42 insertions, 28 deletions
| diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index d1ff879e6ff2..a6952ba343a8 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -15,6 +15,7 @@  #include <linux/of.h>  #include <linux/of_gpio.h>  #include <linux/of_irq.h> +#include <linux/of_platform.h>  #include <linux/gpio.h>  #include <linux/slab.h>  #include <linux/irq.h> @@ -39,6 +40,7 @@ struct mpc8xxx_gpio_chip {  	 */  	u32 data;  	struct irq_domain *irq; +	unsigned int irqn;  	const void *of_dev_id_data;  }; @@ -342,20 +344,20 @@ static struct of_device_id mpc8xxx_gpio_ids[] __initdata = {  	{}  }; -static void __init mpc8xxx_add_controller(struct device_node *np) +static int mpc8xxx_probe(struct platform_device *pdev)  { +	struct device_node *np = pdev->dev.of_node;  	struct mpc8xxx_gpio_chip *mpc8xxx_gc;  	struct of_mm_gpio_chip *mm_gc;  	struct gpio_chip *gc;  	const struct of_device_id *id; -	unsigned hwirq;  	int ret; -	mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); -	if (!mpc8xxx_gc) { -		ret = -ENOMEM; -		goto err; -	} +	mpc8xxx_gc = devm_kzalloc(&pdev->dev, sizeof(*mpc8xxx_gc), GFP_KERNEL); +	if (!mpc8xxx_gc) +		return -ENOMEM; + +	platform_set_drvdata(pdev, mpc8xxx_gc);  	spin_lock_init(&mpc8xxx_gc->lock); @@ -375,16 +377,16 @@ static void __init mpc8xxx_add_controller(struct device_node *np)  	ret = of_mm_gpiochip_add(np, mm_gc);  	if (ret) -		goto err; +		return ret; -	hwirq = irq_of_parse_and_map(np, 0); -	if (hwirq == NO_IRQ) -		goto skip_irq; +	mpc8xxx_gc->irqn = irq_of_parse_and_map(np, 0); +	if (mpc8xxx_gc->irqn == NO_IRQ) +		return 0;  	mpc8xxx_gc->irq = irq_domain_add_linear(np, MPC8XXX_GPIO_PINS,  					&mpc8xxx_gpio_irq_ops, mpc8xxx_gc);  	if (!mpc8xxx_gc->irq) -		goto skip_irq; +		return 0;  	id = of_match_node(mpc8xxx_gpio_ids, np);  	if (id) @@ -394,27 +396,39 @@ static void __init mpc8xxx_add_controller(struct device_node *np)  	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);  	out_be32(mm_gc->regs + GPIO_IMR, 0); -	irq_set_handler_data(hwirq, mpc8xxx_gc); -	irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade); - -skip_irq: -	return; - -err: -	pr_err("%s: registration failed with status %d\n", -	       np->full_name, ret); -	kfree(mpc8xxx_gc); +	irq_set_handler_data(mpc8xxx_gc->irqn, mpc8xxx_gc); +	irq_set_chained_handler(mpc8xxx_gc->irqn, mpc8xxx_gpio_irq_cascade); -	return; +	return 0;  } -static int __init mpc8xxx_add_gpiochips(void) +static int mpc8xxx_remove(struct platform_device *pdev)  { -	struct device_node *np; +	struct mpc8xxx_gpio_chip *mpc8xxx_gc = platform_get_drvdata(pdev); + +	if (mpc8xxx_gc->irq) { +		irq_set_handler_data(mpc8xxx_gc->irqn, NULL); +		irq_set_chained_handler(mpc8xxx_gc->irqn, NULL); +		irq_domain_remove(mpc8xxx_gc->irq); +	} -	for_each_matching_node(np, mpc8xxx_gpio_ids) -		mpc8xxx_add_controller(np); +	of_mm_gpiochip_remove(&mpc8xxx_gc->mm_gc);  	return 0;  } -arch_initcall(mpc8xxx_add_gpiochips); + +static struct platform_driver mpc8xxx_plat_driver = { +	.probe		= mpc8xxx_probe, +	.remove		= mpc8xxx_remove, +	.driver		= { +		.name = "gpio-mpc8xxx", +		.of_match_table	= mpc8xxx_gpio_ids, +	}, +}; + +static int __init mpc8xxx_init(void) +{ +	return platform_driver_register(&mpc8xxx_plat_driver); +} + +arch_initcall(mpc8xxx_init); |