mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	gpio: davinci: Redesign driver to accommodate ngpios in one gpio chip
The Davinci GPIO driver is implemented to work with one monolithic Davinci GPIO platform device which may have up to Y(144) gpios. The Davinci GPIO driver instantiates number of GPIO chips with max 32 gpio pins per each during initialization and one IRQ domain. So, the current GPIO's opjects structure is: <platform device> Davinci GPIO controller |- <gpio0_chip0> ------| ... |--- irq_domain (hwirq [0..143]) |- <gpio0_chipN> ------| Current driver creates one chip for every 32 GPIOs in a controller. This was a limitation earlier now there is no need for that. Hence redesigning the driver to create one gpio chip for all the ngpio in the controller. |- <gpio0_chip0> ------|--- irq_domain (hwirq [0..143]). The previous discussion on this can be found here: https://www.spinics.net/lists/linux-omap/msg132869.html Signed-off-by: Keerthy <j-keerthy@ti.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
		
							parent
							
								
									53d333ac93
								
							
						
					
					
						commit
						b5cf3fd827
					
				
					 2 changed files with 83 additions and 56 deletions
				
			
		| 
						 | 
					@ -63,11 +63,13 @@ static inline int __davinci_direction(struct gpio_chip *chip,
 | 
				
			||||||
			unsigned offset, bool out, int value)
 | 
								unsigned offset, bool out, int value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
						struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
				
			||||||
	struct davinci_gpio_regs __iomem *g = d->regs;
 | 
						struct davinci_gpio_regs __iomem *g;
 | 
				
			||||||
	unsigned long flags;
 | 
						unsigned long flags;
 | 
				
			||||||
	u32 temp;
 | 
						u32 temp;
 | 
				
			||||||
	u32 mask = 1 << offset;
 | 
						int bank = offset / 32;
 | 
				
			||||||
 | 
						u32 mask = __gpio_mask(offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						g = d->regs[bank];
 | 
				
			||||||
	spin_lock_irqsave(&d->lock, flags);
 | 
						spin_lock_irqsave(&d->lock, flags);
 | 
				
			||||||
	temp = readl_relaxed(&g->dir);
 | 
						temp = readl_relaxed(&g->dir);
 | 
				
			||||||
	if (out) {
 | 
						if (out) {
 | 
				
			||||||
| 
						 | 
					@ -103,9 +105,12 @@ davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
 | 
				
			||||||
static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
 | 
					static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
						struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
				
			||||||
	struct davinci_gpio_regs __iomem *g = d->regs;
 | 
						struct davinci_gpio_regs __iomem *g;
 | 
				
			||||||
 | 
						int bank = offset / 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return !!((1 << offset) & readl_relaxed(&g->in_data));
 | 
						g = d->regs[bank];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return !!(__gpio_mask(offset) & readl_relaxed(&g->in_data));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -115,9 +120,13 @@ static void
 | 
				
			||||||
davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 | 
					davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
						struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
				
			||||||
	struct davinci_gpio_regs __iomem *g = d->regs;
 | 
						struct davinci_gpio_regs __iomem *g;
 | 
				
			||||||
 | 
						int bank = offset / 32;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	writel_relaxed((1 << offset), value ? &g->set_data : &g->clr_data);
 | 
						g = d->regs[bank];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						writel_relaxed(__gpio_mask(offset),
 | 
				
			||||||
 | 
							       value ? &g->set_data : &g->clr_data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct davinci_gpio_platform_data *
 | 
					static struct davinci_gpio_platform_data *
 | 
				
			||||||
| 
						 | 
					@ -165,7 +174,7 @@ static int davinci_gpio_of_xlate(struct gpio_chip *gc,
 | 
				
			||||||
	if (gpiospec->args[0] > pdata->ngpio)
 | 
						if (gpiospec->args[0] > pdata->ngpio)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gc != &chips[gpiospec->args[0] / 32].chip)
 | 
						if (gc != &chips->chip)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (flags)
 | 
						if (flags)
 | 
				
			||||||
| 
						 | 
					@ -177,11 +186,11 @@ static int davinci_gpio_of_xlate(struct gpio_chip *gc,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int davinci_gpio_probe(struct platform_device *pdev)
 | 
					static int davinci_gpio_probe(struct platform_device *pdev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int i, base;
 | 
						static int ctrl_num;
 | 
				
			||||||
 | 
						int gpio, bank;
 | 
				
			||||||
	unsigned ngpio, nbank;
 | 
						unsigned ngpio, nbank;
 | 
				
			||||||
	struct davinci_gpio_controller *chips;
 | 
						struct davinci_gpio_controller *chips;
 | 
				
			||||||
	struct davinci_gpio_platform_data *pdata;
 | 
						struct davinci_gpio_platform_data *pdata;
 | 
				
			||||||
	struct davinci_gpio_regs __iomem *regs;
 | 
					 | 
				
			||||||
	struct device *dev = &pdev->dev;
 | 
						struct device *dev = &pdev->dev;
 | 
				
			||||||
	struct resource *res;
 | 
						struct resource *res;
 | 
				
			||||||
	char label[MAX_LABEL_SIZE];
 | 
						char label[MAX_LABEL_SIZE];
 | 
				
			||||||
| 
						 | 
					@ -220,38 +229,30 @@ static int davinci_gpio_probe(struct platform_device *pdev)
 | 
				
			||||||
	if (IS_ERR(gpio_base))
 | 
						if (IS_ERR(gpio_base))
 | 
				
			||||||
		return PTR_ERR(gpio_base);
 | 
							return PTR_ERR(gpio_base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0, base = 0; base < ngpio; i++, base += 32) {
 | 
						snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", ctrl_num++);
 | 
				
			||||||
		snprintf(label, MAX_LABEL_SIZE, "davinci_gpio.%d", i);
 | 
						chips->chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
 | 
				
			||||||
		chips[i].chip.label = devm_kstrdup(dev, label, GFP_KERNEL);
 | 
							if (!chips->chip.label)
 | 
				
			||||||
		if (!chips[i].chip.label)
 | 
					 | 
				
			||||||
			return -ENOMEM;
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		chips[i].chip.direction_input = davinci_direction_in;
 | 
						chips->chip.direction_input = davinci_direction_in;
 | 
				
			||||||
		chips[i].chip.get = davinci_gpio_get;
 | 
						chips->chip.get = davinci_gpio_get;
 | 
				
			||||||
		chips[i].chip.direction_output = davinci_direction_out;
 | 
						chips->chip.direction_output = davinci_direction_out;
 | 
				
			||||||
		chips[i].chip.set = davinci_gpio_set;
 | 
						chips->chip.set = davinci_gpio_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		chips[i].chip.base = base;
 | 
						chips->chip.ngpio = ngpio;
 | 
				
			||||||
		chips[i].chip.ngpio = ngpio - base;
 | 
					 | 
				
			||||||
		if (chips[i].chip.ngpio > 32)
 | 
					 | 
				
			||||||
			chips[i].chip.ngpio = 32;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_OF_GPIO
 | 
					#ifdef CONFIG_OF_GPIO
 | 
				
			||||||
		chips[i].chip.of_gpio_n_cells = 2;
 | 
						chips->chip.of_gpio_n_cells = 2;
 | 
				
			||||||
		chips[i].chip.of_xlate = davinci_gpio_of_xlate;
 | 
						chips->chip.of_xlate = davinci_gpio_of_xlate;
 | 
				
			||||||
		chips[i].chip.parent = dev;
 | 
						chips->chip.parent = dev;
 | 
				
			||||||
		chips[i].chip.of_node = dev->of_node;
 | 
						chips->chip.of_node = dev->of_node;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		spin_lock_init(&chips[i].lock);
 | 
						spin_lock_init(&chips->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		regs = gpio_base + offset_array[i];
 | 
						for (gpio = 0, bank = 0; gpio < ngpio; gpio += 32, bank++)
 | 
				
			||||||
		if (!regs)
 | 
							chips->regs[bank] = gpio_base + offset_array[bank];
 | 
				
			||||||
			return -ENXIO;
 | 
					 | 
				
			||||||
		chips[i].regs = regs;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		gpiochip_add_data(&chips[i].chip, &chips[i]);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gpiochip_add_data(&chips->chip, chips);
 | 
				
			||||||
	platform_set_drvdata(pdev, chips);
 | 
						platform_set_drvdata(pdev, chips);
 | 
				
			||||||
	davinci_gpio_irq_setup(pdev);
 | 
						davinci_gpio_irq_setup(pdev);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -312,16 +313,19 @@ static struct irq_chip gpio_irqchip = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gpio_irq_handler(struct irq_desc *desc)
 | 
					static void gpio_irq_handler(struct irq_desc *desc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int irq = irq_desc_get_irq(desc);
 | 
					 | 
				
			||||||
	struct davinci_gpio_regs __iomem *g;
 | 
						struct davinci_gpio_regs __iomem *g;
 | 
				
			||||||
	u32 mask = 0xffff;
 | 
						u32 mask = 0xffff;
 | 
				
			||||||
 | 
						int bank_num;
 | 
				
			||||||
	struct davinci_gpio_controller *d;
 | 
						struct davinci_gpio_controller *d;
 | 
				
			||||||
 | 
						struct davinci_gpio_irq_data *irqdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d = (struct davinci_gpio_controller *)irq_desc_get_handler_data(desc);
 | 
						irqdata = (struct davinci_gpio_irq_data *)irq_desc_get_handler_data(desc);
 | 
				
			||||||
	g = (struct davinci_gpio_regs __iomem *)d->regs;
 | 
						bank_num = irqdata->bank_num;
 | 
				
			||||||
 | 
						g = irqdata->regs;
 | 
				
			||||||
 | 
						d = irqdata->chip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* we only care about one bank */
 | 
						/* we only care about one bank */
 | 
				
			||||||
	if (irq & 1)
 | 
						if ((bank_num % 2) == 1)
 | 
				
			||||||
		mask <<= 16;
 | 
							mask <<= 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* temporarily mask (level sensitive) parent IRQ */
 | 
						/* temporarily mask (level sensitive) parent IRQ */
 | 
				
			||||||
| 
						 | 
					@ -329,6 +333,7 @@ static void gpio_irq_handler(struct irq_desc *desc)
 | 
				
			||||||
	while (1) {
 | 
						while (1) {
 | 
				
			||||||
		u32		status;
 | 
							u32		status;
 | 
				
			||||||
		int		bit;
 | 
							int		bit;
 | 
				
			||||||
 | 
							irq_hw_number_t hw_irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* ack any irqs */
 | 
							/* ack any irqs */
 | 
				
			||||||
		status = readl_relaxed(&g->intstat) & mask;
 | 
							status = readl_relaxed(&g->intstat) & mask;
 | 
				
			||||||
| 
						 | 
					@ -341,9 +346,13 @@ static void gpio_irq_handler(struct irq_desc *desc)
 | 
				
			||||||
		while (status) {
 | 
							while (status) {
 | 
				
			||||||
			bit = __ffs(status);
 | 
								bit = __ffs(status);
 | 
				
			||||||
			status &= ~BIT(bit);
 | 
								status &= ~BIT(bit);
 | 
				
			||||||
 | 
								/* Max number of gpios per controller is 144 so
 | 
				
			||||||
 | 
								 * hw_irq will be in [0..143]
 | 
				
			||||||
 | 
								 */
 | 
				
			||||||
 | 
								hw_irq = (bank_num / 2) * 32 + bit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			generic_handle_irq(
 | 
								generic_handle_irq(
 | 
				
			||||||
				irq_find_mapping(d->irq_domain,
 | 
									irq_find_mapping(d->irq_domain, hw_irq));
 | 
				
			||||||
						 d->chip.base + bit));
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	chained_irq_exit(irq_desc_get_chip(desc), desc);
 | 
						chained_irq_exit(irq_desc_get_chip(desc), desc);
 | 
				
			||||||
| 
						 | 
					@ -355,7 +364,7 @@ static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset)
 | 
				
			||||||
	struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
						struct davinci_gpio_controller *d = gpiochip_get_data(chip);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (d->irq_domain)
 | 
						if (d->irq_domain)
 | 
				
			||||||
		return irq_create_mapping(d->irq_domain, d->chip.base + offset);
 | 
							return irq_create_mapping(d->irq_domain, offset);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return -ENXIO;
 | 
							return -ENXIO;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -369,7 +378,7 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset)
 | 
				
			||||||
	 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
 | 
						 * can provide direct-mapped IRQs to AINTC (up to 32 GPIOs).
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (offset < d->gpio_unbanked)
 | 
						if (offset < d->gpio_unbanked)
 | 
				
			||||||
		return d->gpio_irq + offset;
 | 
							return d->base_irq + offset;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -382,7 +391,7 @@ static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data);
 | 
						d = (struct davinci_gpio_controller *)irq_data_get_irq_handler_data(data);
 | 
				
			||||||
	g = (struct davinci_gpio_regs __iomem *)d->regs;
 | 
						g = (struct davinci_gpio_regs __iomem *)d->regs;
 | 
				
			||||||
	mask = __gpio_mask(data->irq - d->gpio_irq);
 | 
						mask = __gpio_mask(data->irq - d->base_irq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 | 
						if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -401,7 +410,7 @@ davinci_gpio_irq_map(struct irq_domain *d, unsigned int irq,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct davinci_gpio_controller *chips =
 | 
						struct davinci_gpio_controller *chips =
 | 
				
			||||||
				(struct davinci_gpio_controller *)d->host_data;
 | 
									(struct davinci_gpio_controller *)d->host_data;
 | 
				
			||||||
	struct davinci_gpio_regs __iomem *g = chips[hw / 32].regs;
 | 
						struct davinci_gpio_regs __iomem *g = chips->regs[hw / 32];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	irq_set_chip_and_handler_name(irq, &gpio_irqchip, handle_simple_irq,
 | 
						irq_set_chip_and_handler_name(irq, &gpio_irqchip, handle_simple_irq,
 | 
				
			||||||
				"davinci_gpio");
 | 
									"davinci_gpio");
 | 
				
			||||||
| 
						 | 
					@ -459,6 +468,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 | 
				
			||||||
	struct irq_domain	*irq_domain = NULL;
 | 
						struct irq_domain	*irq_domain = NULL;
 | 
				
			||||||
	const struct of_device_id *match;
 | 
						const struct of_device_id *match;
 | 
				
			||||||
	struct irq_chip *irq_chip;
 | 
						struct irq_chip *irq_chip;
 | 
				
			||||||
 | 
						struct davinci_gpio_irq_data *irqdata;
 | 
				
			||||||
	gpio_get_irq_chip_cb_t gpio_get_irq_chip;
 | 
						gpio_get_irq_chip_cb_t gpio_get_irq_chip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -514,10 +524,8 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 | 
				
			||||||
	 * IRQs, while the others use banked IRQs, would need some setup
 | 
						 * IRQs, while the others use banked IRQs, would need some setup
 | 
				
			||||||
	 * tweaks to recognize hardware which can do that.
 | 
						 * tweaks to recognize hardware which can do that.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) {
 | 
						chips->chip.to_irq = gpio_to_irq_banked;
 | 
				
			||||||
		chips[bank].chip.to_irq = gpio_to_irq_banked;
 | 
						chips->irq_domain = irq_domain;
 | 
				
			||||||
		chips[bank].irq_domain = irq_domain;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO
 | 
						 * AINTC can handle direct/unbanked IRQs for GPIOs, with the GPIO
 | 
				
			||||||
| 
						 | 
					@ -526,9 +534,9 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if (pdata->gpio_unbanked) {
 | 
						if (pdata->gpio_unbanked) {
 | 
				
			||||||
		/* pass "bank 0" GPIO IRQs to AINTC */
 | 
							/* pass "bank 0" GPIO IRQs to AINTC */
 | 
				
			||||||
		chips[0].chip.to_irq = gpio_to_irq_unbanked;
 | 
							chips->chip.to_irq = gpio_to_irq_unbanked;
 | 
				
			||||||
		chips[0].gpio_irq = bank_irq;
 | 
							chips->base_irq = bank_irq;
 | 
				
			||||||
		chips[0].gpio_unbanked = pdata->gpio_unbanked;
 | 
							chips->gpio_unbanked = pdata->gpio_unbanked;
 | 
				
			||||||
		binten = GENMASK(pdata->gpio_unbanked / 16, 0);
 | 
							binten = GENMASK(pdata->gpio_unbanked / 16, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* AINTC handles mask/unmask; GPIO handles triggering */
 | 
							/* AINTC handles mask/unmask; GPIO handles triggering */
 | 
				
			||||||
| 
						 | 
					@ -538,14 +546,14 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 | 
				
			||||||
		irq_chip->irq_set_type = gpio_irq_type_unbanked;
 | 
							irq_chip->irq_set_type = gpio_irq_type_unbanked;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* default trigger: both edges */
 | 
							/* default trigger: both edges */
 | 
				
			||||||
		g = chips[0].regs;
 | 
							g = chips->regs[0];
 | 
				
			||||||
		writel_relaxed(~0, &g->set_falling);
 | 
							writel_relaxed(~0, &g->set_falling);
 | 
				
			||||||
		writel_relaxed(~0, &g->set_rising);
 | 
							writel_relaxed(~0, &g->set_rising);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* set the direct IRQs up to use that irqchip */
 | 
							/* set the direct IRQs up to use that irqchip */
 | 
				
			||||||
		for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) {
 | 
							for (gpio = 0; gpio < pdata->gpio_unbanked; gpio++, irq++) {
 | 
				
			||||||
			irq_set_chip(irq, irq_chip);
 | 
								irq_set_chip(irq, irq_chip);
 | 
				
			||||||
			irq_set_handler_data(irq, &chips[gpio / 32]);
 | 
								irq_set_handler_data(irq, chips);
 | 
				
			||||||
			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
 | 
								irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -561,7 +569,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 | 
				
			||||||
		 * There are register sets for 32 GPIOs. 2 banks of 16
 | 
							 * There are register sets for 32 GPIOs. 2 banks of 16
 | 
				
			||||||
		 * GPIOs are covered by each set of registers hence divide by 2
 | 
							 * GPIOs are covered by each set of registers hence divide by 2
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		g = chips[bank / 2].regs;
 | 
							g = chips->regs[bank / 2];
 | 
				
			||||||
		writel_relaxed(~0, &g->clr_falling);
 | 
							writel_relaxed(~0, &g->clr_falling);
 | 
				
			||||||
		writel_relaxed(~0, &g->clr_rising);
 | 
							writel_relaxed(~0, &g->clr_rising);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -570,8 +578,19 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev)
 | 
				
			||||||
		 * gpio irqs. Pass the irq bank's corresponding controller to
 | 
							 * gpio irqs. Pass the irq bank's corresponding controller to
 | 
				
			||||||
		 * the chained irq handler.
 | 
							 * the chained irq handler.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
 | 
							irqdata = devm_kzalloc(&pdev->dev,
 | 
				
			||||||
 | 
									       sizeof(struct
 | 
				
			||||||
 | 
										      davinci_gpio_irq_data),
 | 
				
			||||||
 | 
										      GFP_KERNEL);
 | 
				
			||||||
 | 
							if (!irqdata)
 | 
				
			||||||
 | 
								return -ENOMEM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							irqdata->regs = g;
 | 
				
			||||||
 | 
							irqdata->bank_num = bank;
 | 
				
			||||||
 | 
							irqdata->chip = chips;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler,
 | 
							irq_set_chained_handler_and_data(bank_irq, gpio_irq_handler,
 | 
				
			||||||
						 &chips[gpio / 32]);
 | 
											 irqdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		binten |= BIT(bank);
 | 
							binten |= BIT(bank);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,19 +21,27 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <asm-generic/gpio.h>
 | 
					#include <asm-generic/gpio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define MAX_REGS_BANKS		5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct davinci_gpio_platform_data {
 | 
					struct davinci_gpio_platform_data {
 | 
				
			||||||
	u32	ngpio;
 | 
						u32	ngpio;
 | 
				
			||||||
	u32	gpio_unbanked;
 | 
						u32	gpio_unbanked;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct davinci_gpio_irq_data {
 | 
				
			||||||
 | 
						void __iomem			*regs;
 | 
				
			||||||
 | 
						struct davinci_gpio_controller	*chip;
 | 
				
			||||||
 | 
						int				bank_num;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct davinci_gpio_controller {
 | 
					struct davinci_gpio_controller {
 | 
				
			||||||
	struct gpio_chip	chip;
 | 
						struct gpio_chip	chip;
 | 
				
			||||||
	struct irq_domain	*irq_domain;
 | 
						struct irq_domain	*irq_domain;
 | 
				
			||||||
	/* Serialize access to GPIO registers */
 | 
						/* Serialize access to GPIO registers */
 | 
				
			||||||
	spinlock_t		lock;
 | 
						spinlock_t		lock;
 | 
				
			||||||
	void __iomem		*regs;
 | 
						void __iomem		*regs[MAX_REGS_BANKS];
 | 
				
			||||||
	int			gpio_unbanked;
 | 
						int			gpio_unbanked;
 | 
				
			||||||
	unsigned		gpio_irq;
 | 
						unsigned int		base_irq;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue