[ARM] 4962/1: Introduce standard gpio interface for Scoop2.
This deprecates old set/reset_scoop_gpio interfacein favour of support for generic gpio interface. It requires gpiolib, so it depends on the previous patch (gpiolib for SA-1100). Signed-off-by: Dmitry Baryshkov <dbaryshkov@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
committed by
Russell King
parent
45528e3817
commit
b43a9e6087
@@ -16,6 +16,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
#include <asm/gpio.h>
|
||||||
#include <asm/hardware/scoop.h>
|
#include <asm/hardware/scoop.h>
|
||||||
|
|
||||||
/* PCMCIA to Scoop linkage
|
/* PCMCIA to Scoop linkage
|
||||||
@@ -32,6 +33,7 @@ EXPORT_SYMBOL(platform_scoop_config);
|
|||||||
|
|
||||||
struct scoop_dev {
|
struct scoop_dev {
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
struct gpio_chip gpio;
|
||||||
spinlock_t scoop_lock;
|
spinlock_t scoop_lock;
|
||||||
unsigned short suspend_clr;
|
unsigned short suspend_clr;
|
||||||
unsigned short suspend_set;
|
unsigned short suspend_set;
|
||||||
@@ -51,6 +53,77 @@ void reset_scoop(struct device *dev)
|
|||||||
iowrite16(0x0000, sdev->base + SCOOP_IRM);
|
iowrite16(0x0000, sdev->base + SCOOP_IRM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __scoop_gpio_set(struct scoop_dev *sdev,
|
||||||
|
unsigned offset, int value)
|
||||||
|
{
|
||||||
|
unsigned short gpwr;
|
||||||
|
|
||||||
|
gpwr = ioread16(sdev->base + SCOOP_GPWR);
|
||||||
|
if (value)
|
||||||
|
gpwr |= 1 << (offset + 1);
|
||||||
|
else
|
||||||
|
gpwr &= ~(1 << (offset + 1));
|
||||||
|
iowrite16(gpwr, sdev->base + SCOOP_GPWR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scoop_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||||
|
{
|
||||||
|
struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sdev->scoop_lock, flags);
|
||||||
|
|
||||||
|
__scoop_gpio_set(sdev, offset, value);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sdev->scoop_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scoop_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||||
|
{
|
||||||
|
struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
|
||||||
|
|
||||||
|
/* XXX: I'm usure, but it seems so */
|
||||||
|
return ioread16(sdev->base + SCOOP_GPRR) & (1 << (offset + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scoop_gpio_direction_input(struct gpio_chip *chip,
|
||||||
|
unsigned offset)
|
||||||
|
{
|
||||||
|
struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned short gpcr;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sdev->scoop_lock, flags);
|
||||||
|
|
||||||
|
gpcr = ioread16(sdev->base + SCOOP_GPCR);
|
||||||
|
gpcr &= ~(1 << (offset + 1));
|
||||||
|
iowrite16(gpcr, sdev->base + SCOOP_GPCR);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sdev->scoop_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scoop_gpio_direction_output(struct gpio_chip *chip,
|
||||||
|
unsigned offset, int value)
|
||||||
|
{
|
||||||
|
struct scoop_dev *sdev = container_of(chip, struct scoop_dev, gpio);
|
||||||
|
unsigned long flags;
|
||||||
|
unsigned short gpcr;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sdev->scoop_lock, flags);
|
||||||
|
|
||||||
|
__scoop_gpio_set(sdev, offset, value);
|
||||||
|
|
||||||
|
gpcr = ioread16(sdev->base + SCOOP_GPCR);
|
||||||
|
gpcr |= 1 << (offset + 1);
|
||||||
|
iowrite16(gpcr, sdev->base + SCOOP_GPCR);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&sdev->scoop_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
|
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
|
||||||
{
|
{
|
||||||
unsigned short gpio_bit;
|
unsigned short gpio_bit;
|
||||||
@@ -138,6 +211,8 @@ static int __devinit scoop_probe(struct platform_device *pdev)
|
|||||||
struct scoop_dev *devptr;
|
struct scoop_dev *devptr;
|
||||||
struct scoop_config *inf;
|
struct scoop_config *inf;
|
||||||
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
int ret;
|
||||||
|
int temp;
|
||||||
|
|
||||||
if (!mem)
|
if (!mem)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -152,8 +227,8 @@ static int __devinit scoop_probe(struct platform_device *pdev)
|
|||||||
devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
|
devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
|
||||||
|
|
||||||
if (!devptr->base) {
|
if (!devptr->base) {
|
||||||
kfree(devptr);
|
ret = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto err_ioremap;
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, devptr);
|
platform_set_drvdata(pdev, devptr);
|
||||||
@@ -169,17 +244,55 @@ static int __devinit scoop_probe(struct platform_device *pdev)
|
|||||||
devptr->suspend_clr = inf->suspend_clr;
|
devptr->suspend_clr = inf->suspend_clr;
|
||||||
devptr->suspend_set = inf->suspend_set;
|
devptr->suspend_set = inf->suspend_set;
|
||||||
|
|
||||||
|
devptr->gpio.base = -1;
|
||||||
|
|
||||||
|
if (inf->gpio_base != 0) {
|
||||||
|
devptr->gpio.label = pdev->dev.bus_id;
|
||||||
|
devptr->gpio.base = inf->gpio_base;
|
||||||
|
devptr->gpio.ngpio = 12; /* PA11 = 0, PA12 = 1, etc. up to PA22 = 11 */
|
||||||
|
devptr->gpio.set = scoop_gpio_set;
|
||||||
|
devptr->gpio.get = scoop_gpio_get;
|
||||||
|
devptr->gpio.direction_input = scoop_gpio_direction_input;
|
||||||
|
devptr->gpio.direction_output = scoop_gpio_direction_output;
|
||||||
|
|
||||||
|
ret = gpiochip_add(&devptr->gpio);
|
||||||
|
if (ret)
|
||||||
|
goto err_gpio;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (devptr->gpio.base != -1)
|
||||||
|
temp = gpiochip_remove(&devptr->gpio);
|
||||||
|
err_gpio:
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
err_ioremap:
|
||||||
|
iounmap(devptr->base);
|
||||||
|
kfree(devptr);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devexit scoop_remove(struct platform_device *pdev)
|
static int __devexit scoop_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct scoop_dev *sdev = platform_get_drvdata(pdev);
|
struct scoop_dev *sdev = platform_get_drvdata(pdev);
|
||||||
if (sdev) {
|
int ret;
|
||||||
iounmap(sdev->base);
|
|
||||||
kfree(sdev);
|
if (!sdev)
|
||||||
platform_set_drvdata(pdev, NULL);
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (sdev->gpio.base != -1) {
|
||||||
|
ret = gpiochip_remove(&sdev->gpio);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pdev->dev, "Can't remove gpio chip: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
iounmap(sdev->base);
|
||||||
|
kfree(sdev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,6 +40,7 @@ struct scoop_config {
|
|||||||
unsigned short io_dir;
|
unsigned short io_dir;
|
||||||
unsigned short suspend_clr;
|
unsigned short suspend_clr;
|
||||||
unsigned short suspend_set;
|
unsigned short suspend_set;
|
||||||
|
int gpio_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Structure for linking scoop devices to PCMCIA sockets */
|
/* Structure for linking scoop devices to PCMCIA sockets */
|
||||||
@@ -62,7 +63,7 @@ struct scoop_pcmcia_config {
|
|||||||
extern struct scoop_pcmcia_config *platform_scoop_config;
|
extern struct scoop_pcmcia_config *platform_scoop_config;
|
||||||
|
|
||||||
void reset_scoop(struct device *dev);
|
void reset_scoop(struct device *dev);
|
||||||
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
|
unsigned short __deprecated set_scoop_gpio(struct device *dev, unsigned short bit);
|
||||||
unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
|
unsigned short __deprecated reset_scoop_gpio(struct device *dev, unsigned short bit);
|
||||||
unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
|
unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
|
||||||
void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
|
void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
|
||||||
|
Reference in New Issue
Block a user