123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- From 4f339b429583965a8eb7c23474414d0730db1215 Mon Sep 17 00:00:00 2001
- From: popcornmix <popcornmix@gmail.com>
- Date: Wed, 8 Oct 2014 18:50:05 +0100
- Subject: [PATCH 002/114] Add bcm2708_gpio driver
- Signed-off-by: popcornmix <popcornmix@gmail.com>
- bcm2708: Add extension to configure internal pulls
- The bcm2708 gpio controller supports internal pulls to be used as pull-up,
- pull-down or being entirely disabled. As it can be useful for a driver to
- change the pull configuration from it's default pull-down state, add an
- extension which allows configuring the pull per gpio.
- Signed-off-by: Julian Scheel <julian@jusst.de>
- bcm2708-gpio: Revert the use of pinctrl_request_gpio
- In non-DT systems, pinctrl_request_gpio always fails causing
- "requests probe deferral" messages. In DT systems, it isn't useful
- because the reference counting is independent of the normal pinctrl
- pin reservations.
- gpio: Only clear the currently occurring interrupt. Avoids losing interrupts
- See: linux #760
- bcm2708_gpio: Avoid calling irq_unmask for all interrupts
- When setting up the interrupts, specify that the handle_simple_irq
- handler should be used. This leaves interrupt acknowledgement to
- the caller, and prevents irq_unmask from being called for all
- interrupts.
- Issue: linux #760
- ---
- arch/arm/mach-bcm2708/Kconfig | 8 +
- arch/arm/mach-bcm2708/Makefile | 1 +
- arch/arm/mach-bcm2708/bcm2708.c | 28 ++
- arch/arm/mach-bcm2708/bcm2708_gpio.c | 426 ++++++++++++++++++++++++++++++
- arch/arm/mach-bcm2708/include/mach/gpio.h | 17 ++
- include/linux/platform_data/bcm2708.h | 23 ++
- 6 files changed, 503 insertions(+)
- create mode 100644 arch/arm/mach-bcm2708/bcm2708_gpio.c
- create mode 100644 arch/arm/mach-bcm2708/include/mach/gpio.h
- create mode 100644 include/linux/platform_data/bcm2708.h
- --- a/arch/arm/mach-bcm2708/Kconfig
- +++ b/arch/arm/mach-bcm2708/Kconfig
- @@ -9,6 +9,14 @@ config MACH_BCM2708
- help
- Include support for the Broadcom(R) BCM2708 platform.
-
- +config BCM2708_GPIO
- + bool "BCM2708 gpio support"
- + depends on MACH_BCM2708
- + select ARCH_REQUIRE_GPIOLIB
- + default y
- + help
- + Include support for the Broadcom(R) BCM2708 gpio.
- +
- config BCM2708_VCMEM
- bool "Videocore Memory"
- depends on MACH_BCM2708
- --- a/arch/arm/mach-bcm2708/Makefile
- +++ b/arch/arm/mach-bcm2708/Makefile
- @@ -3,4 +3,5 @@
- #
-
- obj-$(CONFIG_MACH_BCM2708) += clock.o bcm2708.o armctrl.o vcio.o power.o dma.o
- +obj-$(CONFIG_BCM2708_GPIO) += bcm2708_gpio.o
- obj-$(CONFIG_BCM2708_VCMEM) += vc_mem.o
- --- a/arch/arm/mach-bcm2708/bcm2708.c
- +++ b/arch/arm/mach-bcm2708/bcm2708.c
- @@ -331,6 +331,31 @@ static struct platform_device bcm2708_vc
- },
- };
-
- +#ifdef CONFIG_BCM2708_GPIO
- +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
- +
- +static struct resource bcm2708_gpio_resources[] = {
- + [0] = { /* general purpose I/O */
- + .start = GPIO_BASE,
- + .end = GPIO_BASE + SZ_4K - 1,
- + .flags = IORESOURCE_MEM,
- + },
- +};
- +
- +static u64 gpio_dmamask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON);
- +
- +static struct platform_device bcm2708_gpio_device = {
- + .name = BCM_GPIO_DRIVER_NAME,
- + .id = -1, /* only one VideoCore I/O area */
- + .resource = bcm2708_gpio_resources,
- + .num_resources = ARRAY_SIZE(bcm2708_gpio_resources),
- + .dev = {
- + .dma_mask = &gpio_dmamask,
- + .coherent_dma_mask = DMA_BIT_MASK(DMA_MASK_BITS_COMMON),
- + },
- +};
- +#endif
- +
- static struct resource bcm2708_systemtimer_resources[] = {
- [0] = { /* system timer access */
- .start = ST_BASE,
- @@ -473,6 +498,9 @@ void __init bcm2708_init(void)
-
- bcm_register_device(&bcm2708_dmaman_device);
- bcm_register_device(&bcm2708_vcio_device);
- +#ifdef CONFIG_BCM2708_GPIO
- + bcm_register_device(&bcm2708_gpio_device);
- +#endif
- bcm_register_device(&bcm2708_systemtimer_device);
- bcm_register_device(&bcm2708_fb_device);
- bcm_register_device(&bcm2708_usb_device);
- --- /dev/null
- +++ b/arch/arm/mach-bcm2708/bcm2708_gpio.c
- @@ -0,0 +1,426 @@
- +/*
- + * linux/arch/arm/mach-bcm2708/bcm2708_gpio.c
- + *
- + * Copyright (C) 2010 Broadcom
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + */
- +
- +#include <linux/spinlock.h>
- +#include <linux/module.h>
- +#include <linux/delay.h>
- +#include <linux/list.h>
- +#include <linux/io.h>
- +#include <linux/irq.h>
- +#include <linux/interrupt.h>
- +#include <linux/slab.h>
- +#include <mach/gpio.h>
- +#include <linux/gpio.h>
- +#include <linux/platform_device.h>
- +#include <mach/platform.h>
- +#include <linux/pinctrl/consumer.h>
- +
- +#include <linux/platform_data/bcm2708.h>
- +
- +#define BCM_GPIO_DRIVER_NAME "bcm2708_gpio"
- +#define DRIVER_NAME BCM_GPIO_DRIVER_NAME
- +#define BCM_GPIO_USE_IRQ 1
- +
- +#define GPIOFSEL(x) (0x00+(x)*4)
- +#define GPIOSET(x) (0x1c+(x)*4)
- +#define GPIOCLR(x) (0x28+(x)*4)
- +#define GPIOLEV(x) (0x34+(x)*4)
- +#define GPIOEDS(x) (0x40+(x)*4)
- +#define GPIOREN(x) (0x4c+(x)*4)
- +#define GPIOFEN(x) (0x58+(x)*4)
- +#define GPIOHEN(x) (0x64+(x)*4)
- +#define GPIOLEN(x) (0x70+(x)*4)
- +#define GPIOAREN(x) (0x7c+(x)*4)
- +#define GPIOAFEN(x) (0x88+(x)*4)
- +#define GPIOUD(x) (0x94+(x)*4)
- +#define GPIOUDCLK(x) (0x98+(x)*4)
- +
- +#define GPIO_BANKS 2
- +
- +enum { GPIO_FSEL_INPUT, GPIO_FSEL_OUTPUT,
- + GPIO_FSEL_ALT5, GPIO_FSEL_ALT_4,
- + GPIO_FSEL_ALT0, GPIO_FSEL_ALT1,
- + GPIO_FSEL_ALT2, GPIO_FSEL_ALT3,
- +};
- +
- + /* Each of the two spinlocks protects a different set of hardware
- + * regiters and data structurs. This decouples the code of the IRQ from
- + * the GPIO code. This also makes the case of a GPIO routine call from
- + * the IRQ code simpler.
- + */
- +static DEFINE_SPINLOCK(lock); /* GPIO registers */
- +
- +struct bcm2708_gpio {
- + struct list_head list;
- + void __iomem *base;
- + struct gpio_chip gc;
- + unsigned long rising[(BCM2708_NR_GPIOS + 31) / 32];
- + unsigned long falling[(BCM2708_NR_GPIOS + 31) / 32];
- + unsigned long high[(BCM2708_NR_GPIOS + 31) / 32];
- + unsigned long low[(BCM2708_NR_GPIOS + 31) / 32];
- +};
- +
- +static int bcm2708_set_function(struct gpio_chip *gc, unsigned offset,
- + int function)
- +{
- + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
- + unsigned long flags;
- + unsigned gpiodir;
- + unsigned gpio_bank = offset / 10;
- + unsigned gpio_field_offset = (offset - 10 * gpio_bank) * 3;
- +
- +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set_function %p (%d,%d)\n", gc, offset, function);
- + if (offset >= BCM2708_NR_GPIOS)
- + return -EINVAL;
- +
- + spin_lock_irqsave(&lock, flags);
- +
- + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));
- + gpiodir &= ~(7 << gpio_field_offset);
- + gpiodir |= function << gpio_field_offset;
- + writel(gpiodir, gpio->base + GPIOFSEL(gpio_bank));
- + spin_unlock_irqrestore(&lock, flags);
- + gpiodir = readl(gpio->base + GPIOFSEL(gpio_bank));
- +
- + return 0;
- +}
- +
- +static int bcm2708_gpio_dir_in(struct gpio_chip *gc, unsigned offset)
- +{
- + return bcm2708_set_function(gc, offset, GPIO_FSEL_INPUT);
- +}
- +
- +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value);
- +static int bcm2708_gpio_dir_out(struct gpio_chip *gc, unsigned offset,
- + int value)
- +{
- + int ret;
- + ret = bcm2708_set_function(gc, offset, GPIO_FSEL_OUTPUT);
- + if (ret >= 0)
- + bcm2708_gpio_set(gc, offset, value);
- + return ret;
- +}
- +
- +static int bcm2708_gpio_get(struct gpio_chip *gc, unsigned offset)
- +{
- + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
- + unsigned gpio_bank = offset / 32;
- + unsigned gpio_field_offset = (offset - 32 * gpio_bank);
- + unsigned lev;
- +
- + if (offset >= BCM2708_NR_GPIOS)
- + return 0;
- + lev = readl(gpio->base + GPIOLEV(gpio_bank));
- +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_get %p (%d)=%d\n", gc, offset, 0x1 & (lev>>gpio_field_offset));
- + return 0x1 & (lev >> gpio_field_offset);
- +}
- +
- +static void bcm2708_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
- +{
- + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
- + unsigned gpio_bank = offset / 32;
- + unsigned gpio_field_offset = (offset - 32 * gpio_bank);
- +//printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_set %p (%d=%d)\n", gc, offset, value);
- + if (offset >= BCM2708_NR_GPIOS)
- + return;
- + if (value)
- + writel(1 << gpio_field_offset, gpio->base + GPIOSET(gpio_bank));
- + else
- + writel(1 << gpio_field_offset, gpio->base + GPIOCLR(gpio_bank));
- +}
- +
- +/**********************
- + * extension to configure pullups
- + */
- +int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset,
- + bcm2708_gpio_pull_t value)
- +{
- + struct bcm2708_gpio *gpio = container_of(gc, struct bcm2708_gpio, gc);
- + unsigned gpio_bank = offset / 32;
- + unsigned gpio_field_offset = (offset - 32 * gpio_bank);
- +
- + if (offset >= BCM2708_NR_GPIOS)
- + return -EINVAL;
- +
- + switch (value) {
- + case BCM2708_PULL_UP:
- + writel(2, gpio->base + GPIOUD(0));
- + break;
- + case BCM2708_PULL_DOWN:
- + writel(1, gpio->base + GPIOUD(0));
- + break;
- + case BCM2708_PULL_OFF:
- + writel(0, gpio->base + GPIOUD(0));
- + break;
- + }
- +
- + udelay(5);
- + writel(1 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank));
- + udelay(5);
- + writel(0, gpio->base + GPIOUD(0));
- + writel(0 << gpio_field_offset, gpio->base + GPIOUDCLK(gpio_bank));
- +
- + return 0;
- +}
- +EXPORT_SYMBOL(bcm2708_gpio_setpull);
- +
- +/*************************************************************************************************************************
- + * bcm2708 GPIO IRQ
- + */
- +
- +#if BCM_GPIO_USE_IRQ
- +
- +static int bcm2708_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
- +{
- + return gpio_to_irq(gpio);
- +}
- +
- +static int bcm2708_gpio_irq_set_type(struct irq_data *d, unsigned type)
- +{
- + unsigned irq = d->irq;
- + struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
- + unsigned gn = irq_to_gpio(irq);
- + unsigned gb = gn / 32;
- + unsigned go = gn % 32;
- +
- + gpio->rising[gb] &= ~(1 << go);
- + gpio->falling[gb] &= ~(1 << go);
- + gpio->high[gb] &= ~(1 << go);
- + gpio->low[gb] &= ~(1 << go);
- +
- + if (type & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
- + return -EINVAL;
- +
- + if (type & IRQ_TYPE_EDGE_RISING)
- + gpio->rising[gb] |= (1 << go);
- + if (type & IRQ_TYPE_EDGE_FALLING)
- + gpio->falling[gb] |= (1 << go);
- + if (type & IRQ_TYPE_LEVEL_HIGH)
- + gpio->high[gb] |= (1 << go);
- + if (type & IRQ_TYPE_LEVEL_LOW)
- + gpio->low[gb] |= (1 << go);
- + return 0;
- +}
- +
- +static void bcm2708_gpio_irq_mask(struct irq_data *d)
- +{
- + unsigned irq = d->irq;
- + struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
- + unsigned gn = irq_to_gpio(irq);
- + unsigned gb = gn / 32;
- + unsigned long rising = readl(gpio->base + GPIOREN(gb));
- + unsigned long falling = readl(gpio->base + GPIOFEN(gb));
- + unsigned long high = readl(gpio->base + GPIOHEN(gb));
- + unsigned long low = readl(gpio->base + GPIOLEN(gb));
- +
- + gn = gn % 32;
- +
- + writel(rising & ~(1 << gn), gpio->base + GPIOREN(gb));
- + writel(falling & ~(1 << gn), gpio->base + GPIOFEN(gb));
- + writel(high & ~(1 << gn), gpio->base + GPIOHEN(gb));
- + writel(low & ~(1 << gn), gpio->base + GPIOLEN(gb));
- +}
- +
- +static void bcm2708_gpio_irq_unmask(struct irq_data *d)
- +{
- + unsigned irq = d->irq;
- + struct bcm2708_gpio *gpio = irq_get_chip_data(irq);
- + unsigned gn = irq_to_gpio(irq);
- + unsigned gb = gn / 32;
- + unsigned go = gn % 32;
- + unsigned long rising = readl(gpio->base + GPIOREN(gb));
- + unsigned long falling = readl(gpio->base + GPIOFEN(gb));
- + unsigned long high = readl(gpio->base + GPIOHEN(gb));
- + unsigned long low = readl(gpio->base + GPIOLEN(gb));
- +
- + if (gpio->rising[gb] & (1 << go)) {
- + writel(rising | (1 << go), gpio->base + GPIOREN(gb));
- + } else {
- + writel(rising & ~(1 << go), gpio->base + GPIOREN(gb));
- + }
- +
- + if (gpio->falling[gb] & (1 << go)) {
- + writel(falling | (1 << go), gpio->base + GPIOFEN(gb));
- + } else {
- + writel(falling & ~(1 << go), gpio->base + GPIOFEN(gb));
- + }
- +
- + if (gpio->high[gb] & (1 << go)) {
- + writel(high | (1 << go), gpio->base + GPIOHEN(gb));
- + } else {
- + writel(high & ~(1 << go), gpio->base + GPIOHEN(gb));
- + }
- +
- + if (gpio->low[gb] & (1 << go)) {
- + writel(low | (1 << go), gpio->base + GPIOLEN(gb));
- + } else {
- + writel(low & ~(1 << go), gpio->base + GPIOLEN(gb));
- + }
- +}
- +
- +static struct irq_chip bcm2708_irqchip = {
- + .name = "GPIO",
- + .irq_enable = bcm2708_gpio_irq_unmask,
- + .irq_disable = bcm2708_gpio_irq_mask,
- + .irq_unmask = bcm2708_gpio_irq_unmask,
- + .irq_mask = bcm2708_gpio_irq_mask,
- + .irq_set_type = bcm2708_gpio_irq_set_type,
- +};
- +
- +static irqreturn_t bcm2708_gpio_interrupt(int irq, void *dev_id)
- +{
- + unsigned long edsr;
- + unsigned bank;
- + int i;
- + unsigned gpio;
- + unsigned level_bits;
- + struct bcm2708_gpio *gpio_data = dev_id;
- +
- + for (bank = 0; bank < GPIO_BANKS; bank++) {
- + edsr = readl(__io_address(GPIO_BASE) + GPIOEDS(bank));
- + level_bits = gpio_data->high[bank] | gpio_data->low[bank];
- +
- + for_each_set_bit(i, &edsr, 32) {
- + gpio = i + bank * 32;
- + /* ack edge triggered IRQs immediately */
- + if (!(level_bits & (1<<i)))
- + writel(1<<i,
- + __io_address(GPIO_BASE) + GPIOEDS(bank));
- + generic_handle_irq(gpio_to_irq(gpio));
- + /* ack level triggered IRQ after handling them */
- + if (level_bits & (1<<i))
- + writel(1<<i,
- + __io_address(GPIO_BASE) + GPIOEDS(bank));
- + }
- + }
- + return IRQ_HANDLED;
- +}
- +
- +static struct irqaction bcm2708_gpio_irq = {
- + .name = "BCM2708 GPIO catchall handler",
- + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
- + .handler = bcm2708_gpio_interrupt,
- +};
- +
- +static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)
- +{
- + unsigned irq;
- +
- + ucb->gc.to_irq = bcm2708_gpio_to_irq;
- +
- + for (irq = GPIO_IRQ_START; irq < (GPIO_IRQ_START + GPIO_IRQS); irq++) {
- + irq_set_chip_data(irq, ucb);
- + irq_set_chip_and_handler(irq, &bcm2708_irqchip,
- + handle_simple_irq);
- + set_irq_flags(irq, IRQF_VALID);
- + }
- +
- + bcm2708_gpio_irq.dev_id = ucb;
- + setup_irq(IRQ_GPIO3, &bcm2708_gpio_irq);
- +}
- +
- +#else
- +
- +static void bcm2708_gpio_irq_init(struct bcm2708_gpio *ucb)
- +{
- +}
- +
- +#endif /* #if BCM_GPIO_USE_IRQ ***************************************************************************************************************** */
- +
- +static int bcm2708_gpio_probe(struct platform_device *dev)
- +{
- + struct bcm2708_gpio *ucb;
- + struct resource *res;
- + int bank;
- + int err = 0;
- +
- + printk(KERN_INFO DRIVER_NAME ": bcm2708_gpio_probe %p\n", dev);
- +
- + ucb = kzalloc(sizeof(*ucb), GFP_KERNEL);
- + if (NULL == ucb) {
- + printk(KERN_ERR DRIVER_NAME ": failed to allocate "
- + "mailbox memory\n");
- + err = -ENOMEM;
- + goto err;
- + }
- +
- + res = platform_get_resource(dev, IORESOURCE_MEM, 0);
- +
- + platform_set_drvdata(dev, ucb);
- + ucb->base = __io_address(GPIO_BASE);
- +
- + ucb->gc.label = "bcm2708_gpio";
- + ucb->gc.base = 0;
- + ucb->gc.ngpio = BCM2708_NR_GPIOS;
- + ucb->gc.owner = THIS_MODULE;
- +
- + ucb->gc.direction_input = bcm2708_gpio_dir_in;
- + ucb->gc.direction_output = bcm2708_gpio_dir_out;
- + ucb->gc.get = bcm2708_gpio_get;
- + ucb->gc.set = bcm2708_gpio_set;
- + ucb->gc.can_sleep = 0;
- +
- + for (bank = 0; bank < GPIO_BANKS; bank++) {
- + writel(0, ucb->base + GPIOREN(bank));
- + writel(0, ucb->base + GPIOFEN(bank));
- + writel(0, ucb->base + GPIOHEN(bank));
- + writel(0, ucb->base + GPIOLEN(bank));
- + writel(0, ucb->base + GPIOAREN(bank));
- + writel(0, ucb->base + GPIOAFEN(bank));
- + writel(~0, ucb->base + GPIOEDS(bank));
- + }
- +
- + bcm2708_gpio_irq_init(ucb);
- +
- + err = gpiochip_add(&ucb->gc);
- +
- +err:
- + return err;
- +
- +}
- +
- +static int bcm2708_gpio_remove(struct platform_device *dev)
- +{
- + int err = 0;
- + struct bcm2708_gpio *ucb = platform_get_drvdata(dev);
- +
- + printk(KERN_ERR DRIVER_NAME ": bcm2708_gpio_remove %p\n", dev);
- +
- + gpiochip_remove(&ucb->gc);
- +
- + platform_set_drvdata(dev, NULL);
- + kfree(ucb);
- +
- + return err;
- +}
- +
- +static struct platform_driver bcm2708_gpio_driver = {
- + .probe = bcm2708_gpio_probe,
- + .remove = bcm2708_gpio_remove,
- + .driver = {
- + .name = "bcm2708_gpio"},
- +};
- +
- +static int __init bcm2708_gpio_init(void)
- +{
- + return platform_driver_register(&bcm2708_gpio_driver);
- +}
- +
- +static void __exit bcm2708_gpio_exit(void)
- +{
- + platform_driver_unregister(&bcm2708_gpio_driver);
- +}
- +
- +module_init(bcm2708_gpio_init);
- +module_exit(bcm2708_gpio_exit);
- +
- +MODULE_DESCRIPTION("Broadcom BCM2708 GPIO driver");
- +MODULE_LICENSE("GPL");
- --- /dev/null
- +++ b/arch/arm/mach-bcm2708/include/mach/gpio.h
- @@ -0,0 +1,17 @@
- +/*
- + * arch/arm/mach-bcm2708/include/mach/gpio.h
- + *
- + * This file is licensed under the terms of the GNU General Public
- + * License version 2. This program is licensed "as is" without any
- + * warranty of any kind, whether express or implied.
- + */
- +
- +#ifndef __ASM_ARCH_GPIO_H
- +#define __ASM_ARCH_GPIO_H
- +
- +#define BCM2708_NR_GPIOS 54 // number of gpio lines
- +
- +#define gpio_to_irq(x) ((x) + GPIO_IRQ_START)
- +#define irq_to_gpio(x) ((x) - GPIO_IRQ_START)
- +
- +#endif
- --- /dev/null
- +++ b/include/linux/platform_data/bcm2708.h
- @@ -0,0 +1,23 @@
- +/*
- + * include/linux/platform_data/bcm2708.h
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License version 2 as
- + * published by the Free Software Foundation.
- + *
- + * (C) 2014 Julian Scheel <julian@jusst.de>
- + *
- + */
- +#ifndef __BCM2708_H_
- +#define __BCM2708_H_
- +
- +typedef enum {
- + BCM2708_PULL_OFF,
- + BCM2708_PULL_UP,
- + BCM2708_PULL_DOWN
- +} bcm2708_gpio_pull_t;
- +
- +extern int bcm2708_gpio_setpull(struct gpio_chip *gc, unsigned offset,
- + bcm2708_gpio_pull_t value);
- +
- +#endif
|