diff options
Diffstat (limited to 'drivers/gpio/gpio-davinci.c')
| -rw-r--r-- | drivers/gpio/gpio-davinci.c | 60 | 
1 files changed, 36 insertions, 24 deletions
| diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index a5ece8ea79bc..5c1564fcc24e 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -9,6 +9,7 @@   * the Free Software Foundation; either version 2 of the License, or   * (at your option) any later version.   */ +  #include <linux/gpio/driver.h>  #include <linux/errno.h>  #include <linux/kernel.h> @@ -24,6 +25,12 @@  #include <linux/platform_device.h>  #include <linux/platform_data/gpio-davinci.h>  #include <linux/irqchip/chained_irq.h> +#include <linux/spinlock.h> + +#include <asm-generic/gpio.h> + +#define MAX_REGS_BANKS 5 +#define MAX_INT_PER_BANK 32  struct davinci_gpio_regs {  	u32	dir; @@ -41,11 +48,31 @@ struct davinci_gpio_regs {  typedef struct irq_chip *(*gpio_get_irq_chip_cb_t)(unsigned int irq);  #define BINTEN	0x8 /* GPIO Interrupt Per-Bank Enable Register */ -#define MAX_LABEL_SIZE 20  static void __iomem *gpio_base;  static unsigned int offset_array[5] = {0x10, 0x38, 0x60, 0x88, 0xb0}; +struct davinci_gpio_irq_data { +	void __iomem			*regs; +	struct davinci_gpio_controller	*chip; +	int				bank_num; +}; + +struct davinci_gpio_controller { +	struct gpio_chip	chip; +	struct irq_domain	*irq_domain; +	/* Serialize access to GPIO registers */ +	spinlock_t		lock; +	void __iomem		*regs[MAX_REGS_BANKS]; +	int			gpio_unbanked; +	int			irqs[MAX_INT_PER_BANK]; +}; + +static inline u32 __gpio_mask(unsigned gpio) +{ +	return 1 << (gpio % 32); +} +  static inline struct davinci_gpio_regs __iomem *irq2regs(struct irq_data *d)  {  	struct davinci_gpio_regs __iomem *g; @@ -166,14 +193,12 @@ of_err:  static int davinci_gpio_probe(struct platform_device *pdev)  { -	static int ctrl_num, bank_base; -	int gpio, bank, i, ret = 0; +	int bank, i, ret = 0;  	unsigned int ngpio, nbank, nirq;  	struct davinci_gpio_controller *chips;  	struct davinci_gpio_platform_data *pdata;  	struct device *dev = &pdev->dev;  	struct resource *res; -	char label[MAX_LABEL_SIZE];  	pdata = davinci_gpio_get_pdata(pdev);  	if (!pdata) { @@ -207,10 +232,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)  	else  		nirq = DIV_ROUND_UP(ngpio, 16); -	nbank = DIV_ROUND_UP(ngpio, 32); -	chips = devm_kcalloc(dev, -			     nbank, sizeof(struct davinci_gpio_controller), -			     GFP_KERNEL); +	chips = devm_kzalloc(dev, sizeof(*chips), GFP_KERNEL);  	if (!chips)  		return -ENOMEM; @@ -228,10 +250,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)  		}  	} -	snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++); -	chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL); -		if (!chips->chip.label) -			return -ENOMEM; +	chips->chip.label = dev_name(dev);  	chips->chip.direction_input = davinci_direction_in;  	chips->chip.get = davinci_gpio_get; @@ -239,7 +258,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)  	chips->chip.set = davinci_gpio_set;  	chips->chip.ngpio = ngpio; -	chips->chip.base = bank_base; +	chips->chip.base = -1;  #ifdef CONFIG_OF_GPIO  	chips->chip.of_gpio_n_cells = 2; @@ -252,28 +271,21 @@ static int davinci_gpio_probe(struct platform_device *pdev)  	}  #endif  	spin_lock_init(&chips->lock); -	bank_base += ngpio; -	for (gpio = 0, bank = 0; gpio < ngpio; gpio += 32, bank++) +	nbank = DIV_ROUND_UP(ngpio, 32); +	for (bank = 0; bank < nbank; bank++)  		chips->regs[bank] = gpio_base + offset_array[bank];  	ret = devm_gpiochip_add_data(dev, &chips->chip, chips);  	if (ret) -		goto err; +		return ret;  	platform_set_drvdata(pdev, chips);  	ret = davinci_gpio_irq_setup(pdev);  	if (ret) -		goto err; +		return ret;  	return 0; - -err: -	/* Revert the static variable increments */ -	ctrl_num--; -	bank_base -= ngpio; - -	return ret;  }  /*--------------------------------------------------------------------------*/ |