ARM: bcm281xx: GPIO driver
Subsystems (7)
v3 cover ARM: bcm281xx: GPIO driver
This patch series adds the GPIO driver, and its device tree bindings, for the Broadcom bcm281xx family of chips.
Markus Mayer (3):
ARM: bcm281xx: Add GPIO driver
ARM: bcm281xx: Device Tree bindings for GPIO driver
ARM: bcm281xx: Enable GPIO driver
.../devicetree/bindings/gpio/gpio-bcm-kona.txt | 41 ++ arch/arm/boot/dts/bcm11351.dtsi | 16 + arch/arm/mach-bcm/Kconfig | 2 +- drivers/gpio/Kconfig | 6 + drivers/gpio/Makefile | 1 + drivers/gpio/gpio-bcm-kona.c | 697 ++++++++++++++++++++ 6 files changed, 762 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt create mode 100644 drivers/gpio/gpio-bcm-kona.c
Signature · 1 line
1.7.9.5
PATCH v3 1/3 ARM: bcm281xx: Add GPIO driver
From: Markus Mayer <[email protected]>
This patch adds the GPIO driver for the bcm281xx family of chips.
--- drivers/gpio/gpio-bcm-kona.c | 697 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 697 insertions(+) create mode 100644 drivers/gpio/gpio-bcm-kona.c
drivers/gpio/gpio-bcm-kona.c new file +697 -0
@@ -0,0 +1,697 @@ +/* +* Copyright (C) 2012-2013 Broadcom Corporation +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/of_device.h> +#include <linux/module.h> +#include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> + +#define BCM_GPIO_PASSWD 0x00a5a501 +#define GPIO_PER_BANK 32 + +#define GPIO_BANK (gpio) ((gpio) >> 5) +#define GPIO_BIT (gpio) ((gpio) & (GPIO_PER_BANK - 1)) + +#define GPIO_GPOR0_OFFSET 0x00000000 +#define GPIO_GPIR0_OFFSET 0x00000020 +#define GPIO_GPORS0_OFFSET 0x00000040 +#define GPIO_GPORC0_OFFSET 0x00000060 +#define GPIO_ISR0_OFFSET 0x00000080 +#define GPIO_IMR0_OFFSET 0x000000A0 +#define GPIO_IMRC0_OFFSET 0x000000C0 +#define GPIO_GPCTR0_OFFSET 0x00000100 +#define GPIO_GPPLSR0_OFFSET 0x00000500 +#define GPIO_GPPWR_OFFSET 0x00000520 + +#define GPIO_GPCTR0_DBR_SHIFT 5 +#define GPIO_GPCTR0_DBR_MASK 0x000001E0 + +#define GPIO_GPCTR0_ITR_SHIFT 3 +#define GPIO_GPCTR0_ITR_MASK 0x00000018 +#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE 0x00000001 +#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE 0x00000002 +#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE 0x00000003 + +#define GPIO_GPCTR0_IOTR_MASK 0x00000001 +#define GPIO_GPCTR0_IOTR_CMD_0UTPUT 0x00000000 +#define GPIO_GPCTR0_IOTR_CMD_INPUT 0x00000001 + +#define GPIO_GPCTR0_DB_ENABLE_MASK 0x00000100 + +#define LOCK_CODE 0xFFFFFFFF +#define UNLOCK_CODE 0x0 + +struct bcm_kona_gpio_bank { +int id; +int irq; +}; + +struct bcm_kona_gpio { +struct irq_domain *irq_domain; +void __iomem *reg_base; +int num_bank; +int irq_base; +spinlock_t lock; +struct bcm_kona_gpio_bank *banks; +}; + +static struct gpio_chip bcm_gpio_chip; + +static void bcm_kona_gpio_irq_mask (struct irq_data *d); +static void bcm_kona_gpio_irq_unmask (struct irq_data *d); + +static struct bcm_kona_gpio bcm_kona_gpio; + +static inline u32 bcm_kona_gpio_out_status (int bank) +{ +return GPIO_GPOR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_in_status (int bank) +{ +return GPIO_GPIR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_out_set (int bank) +{ +return GPIO_GPORS0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_out_clear (int bank) +{ +return GPIO_GPORC0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_status (int bank) +{ +return GPIO_ISR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_mask (int bank) +{ +return GPIO_IMR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_mskclr (int bank) +{ +return GPIO_IMRC0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_pwd_status (int bank) +{ +return GPIO_GPPLSR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_control (int gpio) +{ +return GPIO_GPCTR0_OFFSET + (gpio <<2 ); +} + +static int bcm_kona_count_irq_resources (struct platform_device *pdev) +{ +struct resource *res; +int count =0 ; + +for (;;) { + res =platform_get_resource (pdev,IORESOURCE_IRQ , count); +if (!res) +break ; + count++; + } +return count; +} + +static void bcm_kona_gpio_set_lockcode_bank (int bank_id,int lockcode) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base; +/* This register is password protected */ +writel (BCM_GPIO_PASSWD , reg_base +GPIO_GPPWR_OFFSET ); +/* Lock the bank */ +writel (lockcode, reg_base +bcm_kona_gpio_pwd_status (bank_id)); +} + +static inline void bcm_kona_gpio_lock_bank (int bank_id) +{ +bcm_kona_gpio_set_lockcode_bank (bank_id,LOCK_CODE ); +} + +static inline void bcm_kona_gpio_unlock_bank (int bank_id) +{ +bcm_kona_gpio_set_lockcode_bank (bank_id,UNLOCK_CODE ); +} + +static void bcm_kona_gpio_set (struct gpio_chip *chip,unsigned gpio, +int value) +{ +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val, reg_offset; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + +/* determine the GPIO pin direction */ + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &=GPIO_GPCTR0_IOTR_MASK ; + +/* this function only applies to output pin */ +if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) +return ; + + reg_offset = value ?bcm_kona_gpio_out_set (bank_id) : +bcm_kona_gpio_out_clear (bank_id); + + val =readl (reg_base + reg_offset); + val |=1 << bit; +writel (val, reg_base + reg_offset); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static int bcm_kona_gpio_get (struct gpio_chip *chip,unsigned gpio) +{ +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val, reg_offset; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + +/* determine the GPIO pin direction */ + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &=GPIO_GPCTR0_IOTR_MASK ; + +/* read the GPIO bank status */ + reg_offset = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ? +bcm_kona_gpio_in_status (bank_id) : +bcm_kona_gpio_out_status (bank_id); + val =readl (reg_base + reg_offset); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +/* return the specified bit status */ +return (val >> bit) &1 ; +} + +static int bcm_kona_gpio_direction_input (struct gpio_chip *chip, +unsigned gpio) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; +int bank_id =GPIO_BANK (gpio); + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_IOTR_MASK ; + val |=GPIO_GPCTR0_IOTR_CMD_INPUT ; +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static int bcm_kona_gpio_direction_output (struct gpio_chip *chip, +unsigned gpio,int value) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +u32 val, reg_offset; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_IOTR_MASK ; + val |=GPIO_GPCTR0_IOTR_CMD_0UTPUT ; +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + reg_offset = value ?bcm_kona_gpio_out_set (bank_id) : +bcm_kona_gpio_out_clear (bank_id); + + val =readl (reg_base + reg_offset); + val |=1 << bit; +writel (val, reg_base + reg_offset); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static int bcm_kona_gpio_to_irq (struct gpio_chip *chip,unsigned gpio) +{ +if (gpio >= bcm_gpio_chip.ngpio) +return -ENXIO ; +return irq_create_mapping (bcm_kona_gpio.irq_domain, gpio); +} + +static int bcm_kona_gpio_set_debounce (struct gpio_chip *chip,unsigned gpio, +unsigned debounce) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val, res; +unsigned long flags; +int bank_id =GPIO_BANK (gpio); + +/* debounce must be 1-128ms (or 0) */ +if ((debounce >0 && debounce <1000 ) || debounce >128000 ) { +dev_err (chip->dev,"Debounce value %u not in range\n" , + debounce); +return -EINVAL ; + } + +/* calculate debounce bit value */ +if (debounce !=0 ) { +/* Convert to ms */ + debounce /=1000 ; + +/* find the MSB */ + res =fls (debounce) -1 ; + +/* Check if MSB-1 is set (round up or down) */ +if (res >0 && (debounce &1 << (res -1 ))) + res++; + } + +/* spin lock for read-modify-write of the GPIO register */ +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_DBR_MASK ; + +if (debounce ==0 ) { +/* disable debounce */ + val &= ~GPIO_GPCTR0_DB_ENABLE_MASK ; + }else { + val |=GPIO_GPCTR0_DB_ENABLE_MASK | + (res <<GPIO_GPCTR0_DBR_SHIFT ); + } + +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static int bcm_kona_gpio_request (struct gpio_chip *chip,unsigned gpio) +{ +struct irq_data d; + + d.hwirq = gpio; +bcm_kona_gpio_irq_unmask (&d); + +return 0 ; +} + +static void bcm_kona_gpio_free (struct gpio_chip *chip,unsigned gpio) +{ +struct irq_data d; + + d.hwirq = gpio; +bcm_kona_gpio_irq_mask (&d); +} + +static struct gpio_chip bcm_gpio_chip = { + .label ="bcm-kona-gpio" , + .request = bcm_kona_gpio_request, + .free = bcm_kona_gpio_free, + .direction_input = bcm_kona_gpio_direction_input, + .get = bcm_kona_gpio_get, + .direction_output = bcm_kona_gpio_direction_output, + .set = bcm_kona_gpio_set, + .set_debounce = bcm_kona_gpio_set_debounce, + .to_irq = bcm_kona_gpio_to_irq, + .base =0 , +}; + +static void bcm_kona_gpio_irq_ack (struct irq_data *d) +{ +int gpio = d->hwirq; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_int_status (bank_id)); + val |=1 << bit; +writel (val, reg_base +bcm_kona_gpio_int_status (bank_id)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static void bcm_kona_gpio_irq_mask (struct irq_data *d) +{ +int gpio = d->hwirq; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_int_mask (bank_id)); + val |=1 << bit; +writel (val, reg_base +bcm_kona_gpio_int_mask (bank_id)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static void bcm_kona_gpio_irq_unmask (struct irq_data *d) +{ +int gpio = d->hwirq; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_int_mskclr (bank_id)); + val |=1 << bit; +writel (val, reg_base +bcm_kona_gpio_int_mskclr (bank_id)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static int bcm_kona_gpio_irq_set_type (struct irq_data *d,unsigned int type) +{ +int gpio = d->hwirq; +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 lvl_type; +u32 val; +unsigned long flags; +int bank_id =GPIO_BANK (gpio); + +switch (type &IRQ_TYPE_SENSE_MASK ) { +case IRQ_TYPE_EDGE_RISING : + lvl_type =GPIO_GPCTR0_ITR_CMD_RISING_EDGE ; +break ; + +case IRQ_TYPE_EDGE_FALLING : + lvl_type =GPIO_GPCTR0_ITR_CMD_FALLING_EDGE ; +break ; + +case IRQ_TYPE_EDGE_BOTH : + lvl_type =GPIO_GPCTR0_ITR_CMD_BOTH_EDGE ; +break ; + +case IRQ_TYPE_LEVEL_HIGH : +case IRQ_TYPE_LEVEL_LOW : +/* BCM GPIO doesn't support level triggering */ +default : +dev_err (bcm_gpio_chip.dev,"Invalid BCM GPIO irq type 0x%x\n" , + type); +return -EINVAL ; + } + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_ITR_MASK ; + val |= lvl_type <<GPIO_GPCTR0_ITR_SHIFT ; +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static void bcm_kona_gpio_irq_handler (unsigned int irq,struct irq_desc *desc) +{ +int bit, bank_id; +void __iomem *reg_base = bcm_kona_gpio.reg_base; +unsigned long sta; +struct bcm_kona_gpio_bank *bank =irq_get_handler_data (irq); +struct irq_chip *chip =irq_desc_get_chip (desc); + +chained_irq_enter (chip, desc); + + bank_id = bank->id; +bcm_kona_gpio_unlock_bank (bank_id); + + sta =readl (reg_base +bcm_kona_gpio_int_status (bank_id)) & + (~(readl (reg_base +bcm_kona_gpio_int_mask (bank_id)))); + +for_each_set_bit (bit, &sta,32 ) { +/* +* Clear interrupt before handler is called so we don't +* miss any interrupt occurred during executing them. +*/ +writel (readl (reg_base +bcm_kona_gpio_int_status (bank_id)) | + (1 << bit), + reg_base +bcm_kona_gpio_int_status (bank_id)); + +/* Invoke interrupt handler */ +generic_handle_irq (gpio_to_irq (GPIO_PER_BANK * bank_id + bit)); + } + +bcm_kona_gpio_lock_bank (bank_id); + +chained_irq_exit (chip, desc); +} + +static struct irq_chip bcm_gpio_irq_chip = { + .name ="bcm-kona-gpio" , + .irq_ack = bcm_kona_gpio_irq_ack, + .irq_mask = bcm_kona_gpio_irq_mask, + .irq_unmask = bcm_kona_gpio_irq_unmask, + .irq_set_type = bcm_kona_gpio_irq_set_type, +}; + +static struct __initconst of_device_id bcm_kona_gpio_of_match[] = { + { .compatible ="brcm,kona-gpio" }, + {} +}; +MODULE_DEVICE_TABLE (of, kona_gpio_match); + +/* +* This lock class tells lockdep that GPIO irqs are in a different +* category than their parents, so it won't report false recursion. +*/ +static struct lock_class_key gpio_lock_class; + +static int bcm_kona_gpio_irq_map (struct irq_domain *d,unsigned int virq, +irq_hw_number_t hwirq) +{ +irq_set_chip_data (virq, &d->host_data); +irq_set_lockdep_class (virq, &gpio_lock_class); +irq_set_chip_and_handler (virq, &bcm_gpio_irq_chip, handle_simple_irq); +irq_set_nested_thread (virq,1 ); +set_irq_flags (virq,IRQF_VALID ); + +return 0 ; +} + +static void bcm_kona_gpio_irq_unmap (struct irq_domain *d,unsigned int virq) +{ +irq_set_chip_and_handler (virq,NULL ,NULL ); +irq_set_chip_data (virq,NULL ); +} + +static struct irq_domain_ops bcm_kona_irq_ops = { + .map = bcm_kona_gpio_irq_map, + .unmap = bcm_kona_gpio_irq_unmap, + .xlate = irq_domain_xlate_twocell, +}; + +static void bcm_kona_gpio_reset (int num_bank) +{ +int i; +void __iomem *reg_base = bcm_kona_gpio.reg_base; + +/* disable interrupts and clear status */ +for (i =0 ; i < num_bank; i++) { +bcm_kona_gpio_unlock_bank (i); +writel (0xFFFFFFFF , reg_base +bcm_kona_gpio_int_mask (i)); +writel (0xFFFFFFFF , reg_base +bcm_kona_gpio_int_status (i)); +bcm_kona_gpio_lock_bank (i); + } +} + +static int bcm_kona_gpio_probe (struct platform_device *pdev) +{ +const struct of_device_id *match; +struct resource *res; +struct bcm_kona_gpio_bank *bank; +int ret; +int i; + + match =of_match_device (bcm_kona_gpio_of_match, &pdev->dev); +if (!match) { +dev_err (&pdev->dev,"Failed to find gpio controller\n" ); +return -ENODEV ; + } + + bcm_kona_gpio.num_bank =bcm_kona_count_irq_resources (pdev); +if (bcm_kona_gpio.num_bank ==0 ) { +dev_err (&pdev->dev,"Couldn't determine # GPIO banks\n" ); +return -ENOENT ; + } + bcm_gpio_chip.of_node = pdev->dev.of_node; + bcm_gpio_chip.dev = &pdev->dev; + bcm_gpio_chip.ngpio = bcm_kona_gpio.num_bank *GPIO_PER_BANK ; + bcm_kona_gpio.banks =devm_kzalloc (&pdev->dev, + bcm_kona_gpio.num_bank * +sizeof (*bcm_kona_gpio.banks), +GFP_KERNEL ); +if (!bcm_kona_gpio.banks) { +dev_err (&pdev->dev,"Couldn't allocate bank structure\n" ); +return -ENOMEM ; + } + + bcm_kona_gpio.irq_base =irq_alloc_descs (-1 ,0 , bcm_gpio_chip.ngpio, +0 ); +if (bcm_kona_gpio.irq_base <0 ) { +dev_err (&pdev->dev,"Couldn't allocate IRQ numbers\n" ); +return -ENXIO ; + } + bcm_kona_gpio.irq_domain =irq_domain_add_linear (pdev->dev.of_node, + bcm_gpio_chip.ngpio, + &bcm_kona_irq_ops, + &bcm_kona_gpio); +if (!bcm_kona_gpio.irq_domain) { +dev_err (&pdev->dev,"Couldn't allocate IRQ domain\n" ); + ret = -ENXIO ; + goto err_irq_descs; + } +for (i =0 ; i < bcm_kona_gpio.num_bank; i++) { + bank = &bcm_kona_gpio.banks[i]; + bank->id = i; + bank->irq =platform_get_irq (pdev, i); +if (bank->irq <0 ) { +dev_err (&pdev->dev,"Couldn't get IRQ for bank %d" , i); + ret = -ENOENT ; + goto err_irq_domain; + } + } + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) { +dev_err (&pdev->dev,"Missing MEM resource\n" ); + ret = -ENXIO ; + goto err_irq_domain; + } + + bcm_kona_gpio.reg_base =devm_request_and_ioremap (&pdev->dev, res); +if (!bcm_kona_gpio.reg_base) { +dev_err (&pdev->dev,"Couldn't ioremap regs\n" ); + ret = -ENXIO ; + goto err_irq_domain; + } +dev_info (&pdev->dev,"Setting up Kona GPIO at 0x%p (phys %#x)\n" , + bcm_kona_gpio.reg_base, res->start); + +bcm_kona_gpio_reset (bcm_kona_gpio.num_bank); + + ret =gpiochip_add (&bcm_gpio_chip); +if (ret <0 ) { +dev_err (&pdev->dev,"Couldn't add GPIO chip -- %d\n" , ret); + goto err_irq_domain; + } +for (i =0 ; i < bcm_gpio_chip.ngpio; i++) { +int irq =bcm_kona_gpio_to_irq (&bcm_gpio_chip, i); + bank = &bcm_kona_gpio.banks[GPIO_BANK (i)]; +irq_set_lockdep_class (irq, &gpio_lock_class); +irq_set_chip_data (irq, bank); +irq_set_chip_and_handler (irq, &bcm_gpio_irq_chip, + handle_simple_irq); +set_irq_flags (irq,IRQF_VALID ); + } +for (i =0 ; i < bcm_kona_gpio.num_bank; i++) { + bank = &bcm_kona_gpio.banks[i]; + +irq_set_chained_handler (bank->irq, bcm_kona_gpio_irq_handler); +irq_set_handler_data (bank->irq, bank); + } + +spin_lock_init (&bcm_kona_gpio.lock); + +return 0 ; + +err_irq_domain: +irq_domain_remove (bcm_kona_gpio.irq_domain); + +err_irq_descs: +irq_free_descs (bcm_kona_gpio.irq_base, bcm_gpio_chip.ngpio); + +return ret; +} + +static int bcm_kona_gpio_remove (struct platform_device *pdev) +{ +int i, ret; +struct bcm_kona_gpio_bank *bank; + +for (i =0 ; i < bcm_gpio_chip.ngpio; i++) +gpio_free (i); + ret =gpiochip_remove (&bcm_gpio_chip); +if (ret <0 ) { +dev_err (&pdev->dev,"Couldn't remove GPIO chip -- %d\n" , ret); +return ret; + } +for (i =0 ; i < bcm_kona_gpio.num_bank; i++) { + bank = &bcm_kona_gpio.banks[i]; +irq_set_chained_handler (bank->irq,NULL ); +irq_set_handler_data (bank->irq,NULL ); + } +irq_domain_remove (bcm_kona_gpio.irq_domain); +irq_free_descs (bcm_kona_gpio.irq_base, bcm_gpio_chip.ngpio); + +return 0 ; +} + +static struct platform_driver bcm_kona_gpio_driver = { + .driver = { + .name ="bcm-kona-gpio" , + .owner =THIS_MODULE , + .of_match_table = bcm_kona_gpio_of_match, + }, + .probe = bcm_kona_gpio_probe, + .remove = bcm_kona_gpio_remove, +}; + +module_platform_driver (bcm_kona_gpio_driver); + +MODULE_AUTHOR ("Broadcom" ); +MODULE_DESCRIPTION ("Broadcom Kona GPIO Driver" ); +MODULE_LICENSE ("GPL v2" );
Signature · 1 line
1.7.9.5
PATCH v3 1/3 ARM: bcm281xx: Add GPIO driver
Quoted 4 lines · Markus Mayer
From: Markus Mayer <[email protected]>
This patch adds the GPIO driver for the bcm281xx family of chips.
May be I am missing my mails, but I could not find even in archives. The patch says its v3, I could not trace v1/v2 and not change log.
Quoted 44 lines
Signed-off-by Markus Mayer <[email protected]>Reviewed-by Ray Jui <[email protected]>Reviewed-by Christian Daudt <[email protected]>Reviewed-by Tim Kryger <[email protected]>Reviewed-by Matt Porter <[email protected]>Reviewed-by Alex Elder <[email protected]>--- drivers/gpio/gpio-bcm-kona.c | 697 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 697 insertions(+) create mode 100644 drivers/gpio/gpio-bcm-kona.cdrivers/gpio/gpio-bcm-kona.c new file +27
-0@@ -0,0 +1,697 @@ +/* +* Copyright (C) 2012-2013 Broadcom Corporation +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation version 2. +* +* This program is distributed "as is" WITHOUT ANY WARRANTY of any +* kind, whether express or implied; without even the implied warranty +* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +*/ + +#include <linux/io.h> +#include <linux/gpio.h> +#include <linux/of_device.h> +#include <linux/module.h> +#include <linux/irqdomain.h> +#include <linux/irqchip/chained_irq.h> + +#define BCM_GPIO_PASSWD 0x00a5a501 +#define GPIO_PER_BANK 32 + +#define GPIO_BANK (gpio) ((gpio) >> 5) +#define GPIO_BIT (gpio) ((gpio) & (GPIO_PER_BANK - 1)) + +#define GPIO_GPOR0_OFFSET 0x00000000
drivers/gpio/gpio-bcm-kona.c line 37
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+#define GPIO_GPIR0_OFFSET 0x00000020 +#define GPIO_GPORS0_OFFSET 0x00000040 +#define GPIO_GPORC0_OFFSET 0x00000060 +#define GPIO_ISR0_OFFSET 0x00000080 +#define GPIO_IMR0_OFFSET 0x000000A0 +#define GPIO_IMRC0_OFFSET 0x000000C0 +#define GPIO_GPCTR0_OFFSET 0x00000100 +#define GPIO_GPPLSR0_OFFSET 0x00000500 +#define GPIO_GPPWR_OFFSET 0x00000520 +
Why these macros can't be something like this ?
#define GPIO_GPOR_OFFSET(bank) (0x00000000 + (bank) << 2)
Quoted 24 lines
drivers/gpio/gpio-bcm-kona.c new file +24
-0+#define GPIO_GPCTR0_DBR_SHIFT 5 +#define GPIO_GPCTR0_DBR_MASK 0x000001E0 + +#define GPIO_GPCTR0_ITR_SHIFT 3 +#define GPIO_GPCTR0_ITR_MASK 0x00000018 +#define GPIO_GPCTR0_ITR_CMD_RISING_EDGE 0x00000001 +#define GPIO_GPCTR0_ITR_CMD_FALLING_EDGE 0x00000002 +#define GPIO_GPCTR0_ITR_CMD_BOTH_EDGE 0x00000003 + +#define GPIO_GPCTR0_IOTR_MASK 0x00000001 +#define GPIO_GPCTR0_IOTR_CMD_0UTPUT 0x00000000 +#define GPIO_GPCTR0_IOTR_CMD_INPUT 0x00000001 + +#define GPIO_GPCTR0_DB_ENABLE_MASK 0x00000100 + +#define LOCK_CODE 0xFFFFFFFF +#define UNLOCK_CODE 0x0 + +struct bcm_kona_gpio_bank { +int id; +int irq; +}; + +struct bcm_kona_gpio {
drivers/gpio/gpio-bcm-kona.c line 71
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+struct irq_domain *irq_domain; +void __iomem *reg_base; +int num_bank; +int irq_base; +spinlock_t lock; +struct bcm_kona_gpio_bank *banks; +}; + +static struct gpio_chip bcm_gpio_chip; +
Can this be embed in bcm_kona_gpio?
You can then get rid of all the accesses to global variable bcm_kona_gpio.
drivers/gpio/gpio-bcm-kona.c line 76
Quoted 5 lines
drivers/gpio/gpio-bcm-kona.c new file +5
-0+static void bcm_kona_gpio_irq_mask (struct irq_data *d); +static void bcm_kona_gpio_irq_unmask (struct irq_data *d); + +static struct bcm_kona_gpio bcm_kona_gpio; +
Can this be allocated dynamically ?
And the changed global pointer can be accessed only in probe. You can remove all direct access once you embed as mentioned above.
Quoted 34 lines
drivers/gpio/gpio-bcm-kona.c new file +34
-0+static inline u32 bcm_kona_gpio_out_status (int bank) +{ +return GPIO_GPOR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_in_status (int bank) +{ +return GPIO_GPIR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_out_set (int bank) +{ +return GPIO_GPORS0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_out_clear (int bank) +{ +return GPIO_GPORC0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_status (int bank) +{ +return GPIO_ISR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_mask (int bank) +{ +return GPIO_IMR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_mskclr (int bank) +{ +return GPIO_IMRC0_OFFSET + (bank <<2 ); +}
drivers/gpio/gpio-bcm-kona.c line 120
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+ +static inline u32 bcm_kona_gpio_pwd_status (int bank) +{ +return GPIO_GPPLSR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_control (int gpio) +{ +return GPIO_GPCTR0_OFFSET + (gpio <<2 ); +}
All these functions can go away if you can have the macros as shown above ?
drivers/gpio/gpio-bcm-kona.c line 128
Quoted 8 lines
drivers/gpio/gpio-bcm-kona.c new file +8
-0+ +static int bcm_kona_count_irq_resources (struct platform_device *pdev) +{ +struct resource *res; +int count =0 ; + +for (;;) { + res =platform_get_resource (pdev,IORESOURCE_IRQ , count);
platform_get_irq instead
drivers/gpio/gpio-bcm-kona.c line 138
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+if (!res) +break ; + count++; + } +return count; +} + +static void bcm_kona_gpio_set_lockcode_bank (int bank_id,int lockcode) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base;
pass gpio_chip to avoid using global
drivers/gpio/gpio-bcm-kona.c line 145
Quoted 7 lines
drivers/gpio/gpio-bcm-kona.c new file +7
-0+/* This register is password protected */ +writel (BCM_GPIO_PASSWD , reg_base +GPIO_GPPWR_OFFSET ); +/* Lock the bank */ +writel (lockcode, reg_base +bcm_kona_gpio_pwd_status (bank_id)); +} + +static inline void bcm_kona_gpio_lock_bank (int bank_id)
ditto
drivers/gpio/gpio-bcm-kona.c line 150
Quoted 5 lines
drivers/gpio/gpio-bcm-kona.c new file +5
-0+{ +bcm_kona_gpio_set_lockcode_bank (bank_id,LOCK_CODE ); +} + +static inline void bcm_kona_gpio_unlock_bank (int bank_id)
ditto
drivers/gpio/gpio-bcm-kona.c line 160
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+{ +bcm_kona_gpio_set_lockcode_bank (bank_id,UNLOCK_CODE ); +} + +static void bcm_kona_gpio_set (struct gpio_chip *chip,unsigned gpio, +int value) +{ +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base;
fetch bcm_kona_gpio from gpio_chip
Quoted 97 lines
drivers/gpio/gpio-bcm-kona.c new file +97
-0+u32 val, reg_offset; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + +/* determine the GPIO pin direction */ + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &=GPIO_GPCTR0_IOTR_MASK ; + +/* this function only applies to output pin */ +if (GPIO_GPCTR0_IOTR_CMD_INPUT == val) +return ; + + reg_offset = value ?bcm_kona_gpio_out_set (bank_id) : +bcm_kona_gpio_out_clear (bank_id); + + val =readl (reg_base + reg_offset); + val |=1 << bit; +writel (val, reg_base + reg_offset); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static int bcm_kona_gpio_get (struct gpio_chip *chip,unsigned gpio) +{ +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val, reg_offset; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + +/* determine the GPIO pin direction */ + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &=GPIO_GPCTR0_IOTR_MASK ; + +/* read the GPIO bank status */ + reg_offset = (GPIO_GPCTR0_IOTR_CMD_INPUT == val) ? +bcm_kona_gpio_in_status (bank_id) : +bcm_kona_gpio_out_status (bank_id); + val =readl (reg_base + reg_offset); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +/* return the specified bit status */ +return (val >> bit) &1 ; +} + +static int bcm_kona_gpio_direction_input (struct gpio_chip *chip, +unsigned gpio) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; +int bank_id =GPIO_BANK (gpio); + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_IOTR_MASK ; + val |=GPIO_GPCTR0_IOTR_CMD_INPUT ; +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static int bcm_kona_gpio_direction_output (struct gpio_chip *chip, +unsigned gpio,int value) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +u32 val, reg_offset; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_IOTR_MASK ; + val |=GPIO_GPCTR0_IOTR_CMD_0UTPUT ; +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + reg_offset = value ?bcm_kona_gpio_out_set (bank_id) : +bcm_kona_gpio_out_clear (bank_id); + + val =readl (reg_base + reg_offset); + val |=1 << bit; +writel (val, reg_base + reg_offset);
drivers/gpio/gpio-bcm-kona.c line 267
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+ +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static int bcm_kona_gpio_to_irq (struct gpio_chip *chip,unsigned gpio) +{ +if (gpio >= bcm_gpio_chip.ngpio)
is bcm_gpio_chip != chip ?
Globals are even if you have that value passed as argument ?
Quoted 140 lines
drivers/gpio/gpio-bcm-kona.c new file +140
-0+return -ENXIO ; +return irq_create_mapping (bcm_kona_gpio.irq_domain, gpio); +} + +static int bcm_kona_gpio_set_debounce (struct gpio_chip *chip,unsigned gpio, +unsigned debounce) +{ +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val, res; +unsigned long flags; +int bank_id =GPIO_BANK (gpio); + +/* debounce must be 1-128ms (or 0) */ +if ((debounce >0 && debounce <1000 ) || debounce >128000 ) { +dev_err (chip->dev,"Debounce value %u not in range\n" , + debounce); +return -EINVAL ; + } + +/* calculate debounce bit value */ +if (debounce !=0 ) { +/* Convert to ms */ + debounce /=1000 ; + +/* find the MSB */ + res =fls (debounce) -1 ; + +/* Check if MSB-1 is set (round up or down) */ +if (res >0 && (debounce &1 << (res -1 ))) + res++; + } + +/* spin lock for read-modify-write of the GPIO register */ +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_DBR_MASK ; + +if (debounce ==0 ) { +/* disable debounce */ + val &= ~GPIO_GPCTR0_DB_ENABLE_MASK ; + }else { + val |=GPIO_GPCTR0_DB_ENABLE_MASK | + (res <<GPIO_GPCTR0_DBR_SHIFT ); + } + +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static int bcm_kona_gpio_request (struct gpio_chip *chip,unsigned gpio) +{ +struct irq_data d; + + d.hwirq = gpio; +bcm_kona_gpio_irq_unmask (&d); + +return 0 ; +} + +static void bcm_kona_gpio_free (struct gpio_chip *chip,unsigned gpio) +{ +struct irq_data d; + + d.hwirq = gpio; +bcm_kona_gpio_irq_mask (&d); +} + +static struct gpio_chip bcm_gpio_chip = { + .label ="bcm-kona-gpio" , + .request = bcm_kona_gpio_request, + .free = bcm_kona_gpio_free, + .direction_input = bcm_kona_gpio_direction_input, + .get = bcm_kona_gpio_get, + .direction_output = bcm_kona_gpio_direction_output, + .set = bcm_kona_gpio_set, + .set_debounce = bcm_kona_gpio_set_debounce, + .to_irq = bcm_kona_gpio_to_irq, + .base =0 , +}; + +static void bcm_kona_gpio_irq_ack (struct irq_data *d) +{ +int gpio = d->hwirq; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_int_status (bank_id)); + val |=1 << bit; +writel (val, reg_base +bcm_kona_gpio_int_status (bank_id)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static void bcm_kona_gpio_irq_mask (struct irq_data *d) +{ +int gpio = d->hwirq; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_int_mask (bank_id)); + val |=1 << bit; +writel (val, reg_base +bcm_kona_gpio_int_mask (bank_id)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static void bcm_kona_gpio_irq_unmask (struct irq_data *d) +{ +int gpio = d->hwirq; +int bank_id =GPIO_BANK (gpio); +int bit =GPIO_BIT (gpio); +void __iomem *reg_base = bcm_kona_gpio.reg_base; +u32 val; +unsigned long flags; + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_int_mskclr (bank_id)); + val |=1 << bit;
drivers/gpio/gpio-bcm-kona.c line 417
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+writel (val, reg_base +bcm_kona_gpio_int_mskclr (bank_id)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); +} + +static int bcm_kona_gpio_irq_set_type (struct irq_data *d,unsigned int type) +{ +int gpio = d->hwirq; +void __iomem *reg_base = bcm_kona_gpio.reg_base;
irq_*_get_irq_chip_* series of helpers will be useful in these case You have chip, chip_data, handler_data in irq_data to avoid all these global data.
Quoted 221 lines
drivers/gpio/gpio-bcm-kona.c new file +221
-0+u32 lvl_type; +u32 val; +unsigned long flags; +int bank_id =GPIO_BANK (gpio); + +switch (type &IRQ_TYPE_SENSE_MASK ) { +case IRQ_TYPE_EDGE_RISING : + lvl_type =GPIO_GPCTR0_ITR_CMD_RISING_EDGE ; +break ; + +case IRQ_TYPE_EDGE_FALLING : + lvl_type =GPIO_GPCTR0_ITR_CMD_FALLING_EDGE ; +break ; + +case IRQ_TYPE_EDGE_BOTH : + lvl_type =GPIO_GPCTR0_ITR_CMD_BOTH_EDGE ; +break ; + +case IRQ_TYPE_LEVEL_HIGH : +case IRQ_TYPE_LEVEL_LOW : +/* BCM GPIO doesn't support level triggering */ +default : +dev_err (bcm_gpio_chip.dev,"Invalid BCM GPIO irq type 0x%x\n" , + type); +return -EINVAL ; + } + +spin_lock_irqsave (&bcm_kona_gpio.lock, flags); +bcm_kona_gpio_unlock_bank (bank_id); + + val =readl (reg_base +bcm_kona_gpio_control (gpio)); + val &= ~GPIO_GPCTR0_ITR_MASK ; + val |= lvl_type <<GPIO_GPCTR0_ITR_SHIFT ; +writel (val, reg_base +bcm_kona_gpio_control (gpio)); + +bcm_kona_gpio_lock_bank (bank_id); +spin_unlock_irqrestore (&bcm_kona_gpio.lock, flags); + +return 0 ; +} + +static void bcm_kona_gpio_irq_handler (unsigned int irq,struct irq_desc *desc) +{ +int bit, bank_id; +void __iomem *reg_base = bcm_kona_gpio.reg_base; +unsigned long sta; +struct bcm_kona_gpio_bank *bank =irq_get_handler_data (irq); +struct irq_chip *chip =irq_desc_get_chip (desc); + +chained_irq_enter (chip, desc); + + bank_id = bank->id; +bcm_kona_gpio_unlock_bank (bank_id); + + sta =readl (reg_base +bcm_kona_gpio_int_status (bank_id)) & + (~(readl (reg_base +bcm_kona_gpio_int_mask (bank_id)))); + +for_each_set_bit (bit, &sta,32 ) { +/* +* Clear interrupt before handler is called so we don't +* miss any interrupt occurred during executing them. +*/ +writel (readl (reg_base +bcm_kona_gpio_int_status (bank_id)) | + (1 << bit), + reg_base +bcm_kona_gpio_int_status (bank_id)); + +/* Invoke interrupt handler */ +generic_handle_irq (gpio_to_irq (GPIO_PER_BANK * bank_id + bit)); + } + +bcm_kona_gpio_lock_bank (bank_id); + +chained_irq_exit (chip, desc); +} + +static struct irq_chip bcm_gpio_irq_chip = { + .name ="bcm-kona-gpio" , + .irq_ack = bcm_kona_gpio_irq_ack, + .irq_mask = bcm_kona_gpio_irq_mask, + .irq_unmask = bcm_kona_gpio_irq_unmask, + .irq_set_type = bcm_kona_gpio_irq_set_type, +}; + +static struct __initconst of_device_id bcm_kona_gpio_of_match[] = { + { .compatible ="brcm,kona-gpio" }, + {} +}; +MODULE_DEVICE_TABLE (of, kona_gpio_match); + +/* +* This lock class tells lockdep that GPIO irqs are in a different +* category than their parents, so it won't report false recursion. +*/ +static struct lock_class_key gpio_lock_class; + +static int bcm_kona_gpio_irq_map (struct irq_domain *d,unsigned int virq, +irq_hw_number_t hwirq) +{ +irq_set_chip_data (virq, &d->host_data); +irq_set_lockdep_class (virq, &gpio_lock_class); +irq_set_chip_and_handler (virq, &bcm_gpio_irq_chip, handle_simple_irq); +irq_set_nested_thread (virq,1 ); +set_irq_flags (virq,IRQF_VALID ); + +return 0 ; +} + +static void bcm_kona_gpio_irq_unmap (struct irq_domain *d,unsigned int virq) +{ +irq_set_chip_and_handler (virq,NULL ,NULL ); +irq_set_chip_data (virq,NULL ); +} + +static struct irq_domain_ops bcm_kona_irq_ops = { + .map = bcm_kona_gpio_irq_map, + .unmap = bcm_kona_gpio_irq_unmap, + .xlate = irq_domain_xlate_twocell, +}; + +static void bcm_kona_gpio_reset (int num_bank) +{ +int i; +void __iomem *reg_base = bcm_kona_gpio.reg_base; + +/* disable interrupts and clear status */ +for (i =0 ; i < num_bank; i++) { +bcm_kona_gpio_unlock_bank (i); +writel (0xFFFFFFFF , reg_base +bcm_kona_gpio_int_mask (i)); +writel (0xFFFFFFFF , reg_base +bcm_kona_gpio_int_status (i)); +bcm_kona_gpio_lock_bank (i); + } +} + +static int bcm_kona_gpio_probe (struct platform_device *pdev) +{ +const struct of_device_id *match; +struct resource *res; +struct bcm_kona_gpio_bank *bank; +int ret; +int i; + + match =of_match_device (bcm_kona_gpio_of_match, &pdev->dev); +if (!match) { +dev_err (&pdev->dev,"Failed to find gpio controller\n" ); +return -ENODEV ; + } + + bcm_kona_gpio.num_bank =bcm_kona_count_irq_resources (pdev); +if (bcm_kona_gpio.num_bank ==0 ) { +dev_err (&pdev->dev,"Couldn't determine # GPIO banks\n" ); +return -ENOENT ; + } + bcm_gpio_chip.of_node = pdev->dev.of_node; + bcm_gpio_chip.dev = &pdev->dev; + bcm_gpio_chip.ngpio = bcm_kona_gpio.num_bank *GPIO_PER_BANK ; + bcm_kona_gpio.banks =devm_kzalloc (&pdev->dev, + bcm_kona_gpio.num_bank * +sizeof (*bcm_kona_gpio.banks), +GFP_KERNEL ); +if (!bcm_kona_gpio.banks) { +dev_err (&pdev->dev,"Couldn't allocate bank structure\n" ); +return -ENOMEM ; + } + + bcm_kona_gpio.irq_base =irq_alloc_descs (-1 ,0 , bcm_gpio_chip.ngpio, +0 ); +if (bcm_kona_gpio.irq_base <0 ) { +dev_err (&pdev->dev,"Couldn't allocate IRQ numbers\n" ); +return -ENXIO ; + } + bcm_kona_gpio.irq_domain =irq_domain_add_linear (pdev->dev.of_node, + bcm_gpio_chip.ngpio, + &bcm_kona_irq_ops, + &bcm_kona_gpio); +if (!bcm_kona_gpio.irq_domain) { +dev_err (&pdev->dev,"Couldn't allocate IRQ domain\n" ); + ret = -ENXIO ; + goto err_irq_descs; + } +for (i =0 ; i < bcm_kona_gpio.num_bank; i++) { + bank = &bcm_kona_gpio.banks[i]; + bank->id = i; + bank->irq =platform_get_irq (pdev, i); +if (bank->irq <0 ) { +dev_err (&pdev->dev,"Couldn't get IRQ for bank %d" , i); + ret = -ENOENT ; + goto err_irq_domain; + } + } + + res =platform_get_resource (pdev,IORESOURCE_MEM ,0 ); +if (!res) { +dev_err (&pdev->dev,"Missing MEM resource\n" ); + ret = -ENXIO ; + goto err_irq_domain; + } + + bcm_kona_gpio.reg_base =devm_request_and_ioremap (&pdev->dev, res); +if (!bcm_kona_gpio.reg_base) { +dev_err (&pdev->dev,"Couldn't ioremap regs\n" ); + ret = -ENXIO ; + goto err_irq_domain; + } +dev_info (&pdev->dev,"Setting up Kona GPIO at 0x%p (phys %#x)\n" , + bcm_kona_gpio.reg_base, res->start); + +bcm_kona_gpio_reset (bcm_kona_gpio.num_bank); + + ret =gpiochip_add (&bcm_gpio_chip); +if (ret <0 ) { +dev_err (&pdev->dev,"Couldn't add GPIO chip -- %d\n" , ret); + goto err_irq_domain; + } +for (i =0 ; i < bcm_gpio_chip.ngpio; i++) { +int irq =bcm_kona_gpio_to_irq (&bcm_gpio_chip, i); + bank = &bcm_kona_gpio.banks[GPIO_BANK (i)]; +irq_set_lockdep_class (irq, &gpio_lock_class); +irq_set_chip_data (irq, bank); +irq_set_chip_and_handler (irq, &bcm_gpio_irq_chip, + handle_simple_irq); +set_irq_flags (irq,IRQF_VALID );
drivers/gpio/gpio-bcm-kona.c line 648
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+ } +for (i =0 ; i < bcm_kona_gpio.num_bank; i++) { + bank = &bcm_kona_gpio.banks[i]; + +irq_set_chained_handler (bank->irq, bcm_kona_gpio_irq_handler); +irq_set_handler_data (bank->irq, bank); + } + +spin_lock_init (&bcm_kona_gpio.lock); +
platform_set_drvdata to set it as bcm_kona_gpio so that you need not access the global pointer anywhere else. In fact it can removed I think.
Quoted 7 lines
drivers/gpio/gpio-bcm-kona.c new file +7
-0+return 0 ; + +err_irq_domain: +irq_domain_remove (bcm_kona_gpio.irq_domain); + +err_irq_descs: +irq_free_descs (bcm_kona_gpio.irq_base, bcm_gpio_chip.ngpio);
drivers/gpio/gpio-bcm-kona.c line 665
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+ +return ret; +} + +static int bcm_kona_gpio_remove (struct platform_device *pdev) +{ +int i, ret; +struct bcm_kona_gpio_bank *bank; + +for (i =0 ; i < bcm_gpio_chip.ngpio; i++)
may be bcm_kona_gpio as driver data will help here ?
Quoted 22 lines
drivers/gpio/gpio-bcm-kona.c new file +22
-0+gpio_free (i); + ret =gpiochip_remove (&bcm_gpio_chip); +if (ret <0 ) { +dev_err (&pdev->dev,"Couldn't remove GPIO chip -- %d\n" , ret); +return ret; + } +for (i =0 ; i < bcm_kona_gpio.num_bank; i++) { + bank = &bcm_kona_gpio.banks[i]; +irq_set_chained_handler (bank->irq,NULL ); +irq_set_handler_data (bank->irq,NULL ); + } +irq_domain_remove (bcm_kona_gpio.irq_domain); +irq_free_descs (bcm_kona_gpio.irq_base, bcm_gpio_chip.ngpio); + +return 0 ; +} + +static struct platform_driver bcm_kona_gpio_driver = { + .driver = { + .name ="bcm-kona-gpio" , + .owner =THIS_MODULE , + .of_match_table = bcm_kona_gpio_of_match,
drivers/gpio/gpio-bcm-kona.c line 697
Quoted 10 lines
drivers/gpio/gpio-bcm-kona.c new file +10
-0+ }, + .probe = bcm_kona_gpio_probe, + .remove = bcm_kona_gpio_remove, +}; + +module_platform_driver (bcm_kona_gpio_driver); + +MODULE_AUTHOR ("Broadcom" ); +MODULE_DESCRIPTION ("Broadcom Kona GPIO Driver" ); +MODULE_LICENSE ("GPL v2" );
IMO, you don't require any global data or pointers if probe populates all the pdev, irq/gpio_chip data member appropriately
Regards,
Sudeep
PATCH v3 1/3 ARM: bcm281xx: Add GPIO driver
Quoted 7 lines · Sudeep KarkadaNagesha
Quoted 4 lines · Markus Mayer
From: Markus Mayer <[email protected]>
This patch adds the GPIO driver for the bcm281xx family of chips.
May be I am missing my mails, but I could not find even in archives. The patch says its v3, I could not trace v1/v2 and not change log.
No, you didn't miss any e-mails. We had some internal reviews and the plan was for me to renumber the patches and start from v1 again for the public review, but I clearly forgot. Hence v3 is really the first public version of this patch.
Quoted 2 lines
Why these macros can't be something like this ? #define
GPIO_GPOR_OFFSET(bank)(0x00000000+ (bank) << 2)
Done.
Quoted 3 lines
Can this be embed in
bcm_kona_gpio?
You can then get rid of all the accesses to global variablebcm_kona_gpio.
Still working on this one, but the global variable will go away. The same is true of the other globals.
Quoted 37 lines
Quoted 37 lines
drivers/gpio/gpio-bcm-kona.c new file +37
-0+static inline u32 bcm_kona_gpio_out_status (int bank) +{ +return GPIO_GPOR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_in_status (int bank) +{ +return GPIO_GPIR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_out_set (int bank) +{ +return GPIO_GPORS0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_out_clear (int bank) +{ +return GPIO_GPORC0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_status (int bank) +{ +return GPIO_ISR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_mask (int bank) +{ +return GPIO_IMR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_int_mskclr (int bank) +{ +return GPIO_IMRC0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_pwd_status (int bank) +{
Quoted 8 lines
drivers/gpio/gpio-bcm-kona.c line 120
Quoted 7 lines
drivers/gpio/gpio-bcm-kona.c new file +7
-0+return GPIO_GPPLSR0_OFFSET + (bank <<2 ); +} + +static inline u32 bcm_kona_gpio_control (int gpio) +{ +return GPIO_GPCTR0_OFFSET + (gpio <<2 ); +}All these functions can go away if you can have the macros as shown above ?
I took those functions out.
Quoted 8 lines
drivers/gpio/gpio-bcm-kona.c line 128
Quoted 7 lines
drivers/gpio/gpio-bcm-kona.c new file +7
-0+static int bcm_kona_count_irq_resources (struct platform_device *pdev) +{ +struct resource *res; +int count =0 ; + +for (;;) { + res =platform_get_resource (pdev,IORESOURCE_IRQ , count);
platform_get_irqinstead
Done.
Quoted 9 lines
drivers/gpio/gpio-bcm-kona.c line 134
Quoted 6 lines
drivers/gpio/gpio-bcm-kona.c new file +6
-0+if (!res) +break ; + count++; + } +return count; +}IMO, you don't require any global data or pointers if probe populates all the pdev, irq/gpio_chip data member appropriately
Yes, they'll go away in the next revision of this driver which I am hoping to post shortly.
Thanks,
-Markus
Signature · 2 lines
Markus Mayer Broadcom Landing Team
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
In reply to Markus Mayer--- .../devicetree/bindings/gpio/gpio-bcm-kona.txt | 41 ++++++++++++++++++++ arch/arm/boot/dts/bcm11351.dtsi | 16 ++++++++ 2 files changed, 57 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt new file +41 -0
@@ -0,0 +1,41 @@ +Broadcom Kona Family GPIO +------------------------- + +This GPIO driver is used in the following Broadcom SoCs: + BCM11130, BCM11140, BCM11351, BCM28145, BCM28155 + +The GPIO controller only supports edge, not level triggering. + +Required properties: + - compatible: "brcm,kona-gpio" + - reg: Physical base address and length of the controller's registers. + - interrupts: The interrupt outputs from the controller. + - #gpio-cells: Should be <2>. The first cell is the pin number, the second + cell is used to specify optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) + - #interrupt-cells: Should be <2>. The first cell is the GPIO number. + The second cell is used to specify flags: + - trigger type (bits[1:0]): + 1 = low-to-high edge triggered. + 2 = high-to-low edge triggered. + 3 = low-to-high or high-to-low edge triggered + Valid values are 1, 2, 3 + - gpio-controller: Marks the device node as a GPIO controller. + - interrupt-controller: Marks the device node as an interrupt controller. + +Example: + gpio: gpio at 35003000 { + compatible = "brcm,kona-gpio"; + reg = <0x35003000 0x800>; + interrupts = + <0x0 106 0x4 + 0x0 115 0x4 + 0x0 114 0x4 + 0x0 113 0x4 + 0x0 112 0x4 + 0x0 111 0x4>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + };
arch/arm/boot/dts/bcm11351.dtsi +16 -0
@@ -63,6 +63,22 @@ clock-frequency = <32768>; }; + gpio: gpio at 35003000 { + compatible = "brcm,kona-gpio"; + reg = <0x35003000 0x800>; + interrupts = + <0x0 106 0x4 + 0x0 115 0x4 + 0x0 114 0x4 + 0x0 113 0x4 + 0x0 112 0x4 + 0x0 111 0x4>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + }; + sdio0: sdio at 0x3f180000 { compatible = "bcm,kona-sdhci"; reg = <0x3f180000 0x10000>;
Signature · 1 line
1.7.9.5
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
(CC'ing the DT bindings maintainers hence quoting the binding in full)
On 07/26/2013 02:25 PM, Markus Mayer wrote:
Some kind of patch description is always useful.
Quoted 2 lines
.../devicetree/bindings/gpio/gpio-bcm-kona.txt | 41 ++++++++++++++++++++ arch/arm/boot/dts/bcm11351.dtsi | 16 ++++++++
It's more usual to put the DT binding doc change and driver change in one patch, then "make use of that" in a later separate patch which edits *.dts and *.dtsi.
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt line 7
Quoted 9 lines
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +7
-0+Broadcom Kona Family GPIO +------------------------- + +This GPIO driver is used in the following Broadcom SoCs: + BCM11130, BCM11140, BCM11351, BCM28145, BCM28155 + +The GPIO controller only supports edge, not level triggering.
add "... of interrupts"? This might not be worth mentioning; it's clearly spelled out in the description of the interrupt cells below.
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt line 12
Quoted 4 lines
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +4
-0+Required properties: + - compatible: "brcm,kona-gpio" + - reg: Physical base address and length of the controller's registers. + - interrupts: The interrupt outputs from the controller.
How many entries are required? I notice there's more than 1 in the example below.
Quoted 31 lines
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +29
-0+ - #gpio-cells: Should be <2>. The first cell is the pin number, the second + cell is used to specify optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) + - #interrupt-cells: Should be <2>. The first cell is the GPIO number. + The second cell is used to specify flags: + - trigger type (bits[1:0]): + 1 = low-to-high edge triggered. + 2 = high-to-low edge triggered. + 3 = low-to-high or high-to-low edge triggered + Valid values are 1, 2, 3 + - gpio-controller: Marks the device node as a GPIO controller. + - interrupt-controller: Marks the device node as an interrupt controller. + +Example: + gpio: gpio at 35003000 { + compatible = "brcm,kona-gpio"; + reg = <0x35003000 0x800>; + interrupts = + <0x0 106 0x4 + 0x0 115 0x4 + 0x0 114 0x4 + 0x0 113 0x4 + 0x0 112 0x4 + 0x0 111 0x4>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + };
arch/arm/boot/dts/bcm11351.dtsi line 67
Quoted 3 lines
arch/arm/boot/dts/bcm11351.dtsi +2
-0+ gpio: gpio at 35003000 { + compatible = "brcm,kona-gpio";
In order to enable any later chip-specific quirking requirements, that compatible property should both specify the IP block and the specific chip it's included in, so I'd expect to see something like:
compatible = "brcm,brcm11351-gpio", "brcm,kona-gpio";
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
Quoted 5 lines · Stephen Warren
(CC'ing the DT bindings maintainers hence quoting the binding in full)
On 07/26/2013 02:25 PM, Markus Mayer wrote:
Some kind of patch description is always useful.
I will add something along the lines of "GPIO device tree bindings for the Broadcom bcm281xx family of chips."
Quoted 6 lines
Quoted 2 lines
.../devicetree/bindings/gpio/gpio-bcm-kona.txt | 41 ++++++++++++++++++++ arch/arm/boot/dts/bcm11351.dtsi | 16 ++++++++It's more usual to put the DT binding doc change and driver change in one patch, then "make use of that" in a later separate patch which edits *.dts and *.dtsi.
Sure. I have no issue moving the gpio-bcm-kona.txt into the other patch, together with the code.
Quoted 12 lines
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt line 7
Quoted 9 lines
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +7
-0+Broadcom Kona Family GPIO +------------------------- + +This GPIO driver is used in the following Broadcom SoCs: + BCM11130, BCM11140, BCM11351, BCM28145, BCM28155 + +The GPIO controller only supports edge, not level triggering.add "... of interrupts"? This might not be worth mentioning; it's clearly spelled out in the description of the interrupt cells below.
Added.
Quoted 7 lines
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt line 12
Quoted 4 lines
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +4
-0+Required properties: + - compatible: "brcm,kona-gpio" + - reg: Physical base address and length of the controller's registers. + - interrupts: The interrupt outputs from the controller.How many entries are required? I notice there's more than 1 in the example below.
You only "need" the ones you want to use, i.e. at least one. The board supports up to 6. I can mention as much in the description.
[...]
Quoted 10 lines
arch/arm/boot/dts/bcm11351.dtsi line 67
Quoted 4 lines
arch/arm/boot/dts/bcm11351.dtsi +2
-0+ gpio: gpio at 35003000 { + compatible = "brcm,kona-gpio";In order to enable any later chip-specific quirking requirements, that compatible property should both specify the IP block and the specific chip it's included in, so I'd expect to see something like:
compatible = "brcm,brcm11351-gpio", "brcm,kona-gpio";
Added.
Thanks,
-Markus
Signature · 2 lines
Markus Mayer Broadcom Landing Team
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
Quoted 12 lines · Markus Mayer
Quoted 11 lines · Stephen Warren
(CC'ing the DT bindings maintainers hence quoting the binding in full)
Quoted 6 lines · Markus Mayer
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +4
-0+Required properties: + - compatible: "brcm,kona-gpio" + - reg: Physical base address and length of the controller's registers. + - interrupts: The interrupt outputs from the controller.
Quoted 5 lines
Quoted 2 lines
How many entries are required? I notice there's more than 1 in the example below.
You only "need" the ones you want to use, i.e. at least one. The board supports up to 6. I can mention as much in the description.
Isn't this a property of the SoC's IP block, not of the board?
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
Quoted 13 lines · Stephen Warren
Quoted 12 lines · Markus Mayer
Quoted 11 lines · Stephen Warren
(CC'ing the DT bindings maintainers hence quoting the binding in full)
Quoted 6 lines · Markus Mayer
Documentation/devicetree/bindings/gpio/gpio-bcm-kona.txt +4
-0+Required properties: + - compatible: "brcm,kona-gpio" + - reg: Physical base address and length of the controller's registers. + - interrupts: The interrupt outputs from the controller.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
How many entries are required? I notice there's more than 1 in the example below.
You only "need" the ones you want to use, i.e. at least one. The board supports up to 6. I can mention as much in the description.
Isn't this a property of the SoC's IP block, not of the board?
Yes. I wasn't very precise with my statement.
What I added to the description is "Specify at least 1 GPIO interrupt. The maximum number is 6."
Signature · 2 lines
Markus Mayer Broadcom Landing Team
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
Quoted 7 lines · Markus Mayer
Quoted 1 line · Stephen Warren
Isn't this a property of the SoC's IP block, not of the board?
Yes. I wasn't very precise with my statement.
What I added to the description is "Specify at least 1 GPIO interrupt. The maximum number is 6."
The IP has a configurable number of banks, each of which has its own interrupt. If a particular SoC was configured to have six banks then you need to list six interrupts in the DTS. Perhaps it would help to spell that out that relationship explicitly in the documentation rather than talking about a minimum or maximum number of interrupts? Also, you may want to mention that interrupts should to be ordered by bank number.
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
In reply to Markus MayerQuoted 11 lines · Markus Mayer
arch/arm/boot/dts/bcm11351.dtsi +5
-0@@ -63,6 +63,22 @@ clock-frequency = <32768>; }; + gpio: gpio at 35003000 { + compatible = "brcm,kona-gpio"; + reg = <0x35003000 0x800>; + interrupts = + <0x0 106 0x4
arch/arm/boot/dts/bcm11351.dtsi line 80
Quoted 10 lines
arch/arm/boot/dts/bcm11351.dtsi +10
-0+ 0x0 115 0x4 + 0x0 114 0x4 + 0x0 113 0x4 + 0x0 112 0x4 + 0x0 111 0x4>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + };
Do this:
#include <dt-bindings//interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
Rewrite like this:
+ interrupts =
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
As you can see we can now understand the dts file.
Possibly this should also be done in the examples.
Yours,
Linus Walleij
PATCH v3 2/3 ARM: bcm281xx: Device Tree bindings for GPIO driver
Quoted 35 lines · Linus Walleij
Quoted 11 lines · Markus Mayer
arch/arm/boot/dts/bcm11351.dtsi +5
-0@@ -63,6 +63,22 @@ clock-frequency = <32768>; }; + gpio: gpio at 35003000 { + compatible = "brcm,kona-gpio"; + reg = <0x35003000 0x800>; + interrupts = + <0x0 106 0x4arch/arm/boot/dts/bcm11351.dtsi line 80
Quoted 10 lines
arch/arm/boot/dts/bcm11351.dtsi +10
-0+ 0x0 115 0x4 + 0x0 114 0x4 + 0x0 113 0x4 + 0x0 112 0x4 + 0x0 111 0x4>; + #gpio-cells = <2>; + #interrupt-cells = <2>; + gpio-controller; + interrupt-controller; + };Do this:
#include <
dt-bindings//interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/arm-gic.h>Rewrite like this:
(quoted diff) +3
-0+ interrupts = + <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH + GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH
Quoted 3 lines
As you can see we can now understand the dts file.
Possibly this should also be done in the examples.
Thanks for the feedback. This change will be part of the next revision that I am about to send out (in dtsi & examples).
Regards,
-Markus
Signature · 2 lines
Markus Mayer Broadcom Landing Team
PATCH v3 3/3 ARM: bcm281xx: Enable GPIO driver
In reply to Markus MayerThis patch adds the Kconfig and Makefile glue to compile the GPIO driver for bcm281xx when CONFIG_GPIO_BCM=y.
--- arch/arm/mach-bcm/Kconfig | 2 +- drivers/gpio/Kconfig | 6 ++++++ drivers/gpio/Makefile | 1 + 3 files changed, 8 insertions(+), 1 deletion(-)
arch/arm/mach-bcm/Kconfig +1 -1
@@ -9,7 +9,7 @@ config ARCH_BCM select CLKSRC_OF select GENERIC_CLOCKEVENTS select GENERIC_TIME - select GPIO_BCM + select GPIO_BCM_KONA select SPARSE_IRQ select TICK_ONESHOT help
drivers/gpio/Kconfig +6 -0
@@ -714,6 +714,12 @@ config GPIO_MSIC Enable support for GPIO on intel MSIC controllers found in intel MID devices +config GPIO_BCM_KONA + bool "Broadcom Kona GPIO" + depends on ARCH_BCM + help + Turn on GPIO support for Broadcom "Kona" chips. + comment "USB GPIO expanders:" config GPIO_VIPERBOARD
drivers/gpio/Makefile +1 -0
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o +obj-$(CONFIG_GPIO_BCM_KONA) += gpio-bcm-kona.o obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
Signature · 1 line
1.7.9.5