Commit deecd433 authored by Richard Purdie's avatar Richard Purdie Committed by Russell King

[ARM PATCH] 2522/1: Sharp SCOOP - Add mutliple device support

Patch from Richard Purdie

Sharp SCOOP: Devices with multiple scoop interfaces are now
available so:
* add support for mutliple device support to the driver
* Update corgi, collie and poodle to share the scoop
  device structure so a device can be selected in drivers
* Update drivers to use the device structures

Signed-off-by: Richard Purdie
Signed-off-by: Russell King
parent d364e189
......@@ -15,47 +15,52 @@
#include <asm/io.h>
#include <asm/hardware/scoop.h>
static void __iomem *scoop_io_base;
#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
#define SCOOP_REG(adr) (*(volatile unsigned short*)(scoop_io_base+(adr)))
struct scoop_dev {
void *base;
spinlock_t scoop_lock;
u32 scoop_gpwr;
};
void reset_scoop(void)
void reset_scoop(struct device *dev)
{
SCOOP_REG(SCOOP_MCR) = 0x0100; // 00
SCOOP_REG(SCOOP_CDR) = 0x0000; // 04
SCOOP_REG(SCOOP_CPR) = 0x0000; // 0C
SCOOP_REG(SCOOP_CCR) = 0x0000; // 10
SCOOP_REG(SCOOP_IMR) = 0x0000; // 18
SCOOP_REG(SCOOP_IRM) = 0x00FF; // 14
SCOOP_REG(SCOOP_ISR) = 0x0000; // 1C
SCOOP_REG(SCOOP_IRM) = 0x0000;
struct scoop_dev *sdev = dev_get_drvdata(dev);
SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100; // 00
SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000; // 04
SCOOP_REG(sdev->base,SCOOP_CPR) = 0x0000; // 0C
SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000; // 10
SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000; // 18
SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF; // 14
SCOOP_REG(sdev->base,SCOOP_ISR) = 0x0000; // 1C
SCOOP_REG(sdev->base,SCOOP_IRM) = 0x0000;
}
static DEFINE_SPINLOCK(scoop_lock);
static u32 scoop_gpwr;
unsigned short set_scoop_gpio(unsigned short bit)
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit;
unsigned long flag;
struct scoop_dev *sdev = dev_get_drvdata(dev);
spin_lock_irqsave(&scoop_lock, flag);
gpio_bit = SCOOP_REG(SCOOP_GPWR) | bit;
SCOOP_REG(SCOOP_GPWR) = gpio_bit;
spin_unlock_irqrestore(&scoop_lock, flag);
spin_lock_irqsave(&sdev->scoop_lock, flag);
gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) | bit;
SCOOP_REG(sdev->base, SCOOP_GPWR) = gpio_bit;
spin_unlock_irqrestore(&sdev->scoop_lock, flag);
return gpio_bit;
}
unsigned short reset_scoop_gpio(unsigned short bit)
unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
{
unsigned short gpio_bit;
unsigned long flag;
struct scoop_dev *sdev = dev_get_drvdata(dev);
spin_lock_irqsave(&scoop_lock, flag);
gpio_bit = SCOOP_REG(SCOOP_GPWR) & ~bit;
SCOOP_REG(SCOOP_GPWR) = gpio_bit;
spin_unlock_irqrestore(&scoop_lock, flag);
spin_lock_irqsave(&sdev->scoop_lock, flag);
gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) & ~bit;
SCOOP_REG(sdev->base,SCOOP_GPWR) = gpio_bit;
spin_unlock_irqrestore(&sdev->scoop_lock, flag);
return gpio_bit;
}
......@@ -63,25 +68,30 @@ unsigned short reset_scoop_gpio(unsigned short bit)
EXPORT_SYMBOL(set_scoop_gpio);
EXPORT_SYMBOL(reset_scoop_gpio);
unsigned short read_scoop_reg(unsigned short reg)
unsigned short read_scoop_reg(struct device *dev, unsigned short reg)
{
return SCOOP_REG(reg);
struct scoop_dev *sdev = dev_get_drvdata(dev);
return SCOOP_REG(sdev->base,reg);
}
void write_scoop_reg(unsigned short reg, unsigned short data)
void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data)
{
SCOOP_REG(reg)=data;
struct scoop_dev *sdev = dev_get_drvdata(dev);
SCOOP_REG(sdev->base,reg)=data;
}
EXPORT_SYMBOL(reset_scoop);
EXPORT_SYMBOL(read_scoop_reg);
EXPORT_SYMBOL(write_scoop_reg);
#ifdef CONFIG_PM
static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
{
if (level == SUSPEND_POWER_DOWN) {
scoop_gpwr = SCOOP_REG(SCOOP_GPWR);
SCOOP_REG(SCOOP_GPWR) = 0;
struct scoop_dev *sdev = dev_get_drvdata(dev);
sdev->scoop_gpwr = SCOOP_REG(sdev->base,SCOOP_GPWR);
SCOOP_REG(sdev->base,SCOOP_GPWR) = 0;
}
return 0;
}
......@@ -89,13 +99,20 @@ static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
static int scoop_resume(struct device *dev, uint32_t level)
{
if (level == RESUME_POWER_ON) {
SCOOP_REG(SCOOP_GPWR) = scoop_gpwr;
struct scoop_dev *sdev = dev_get_drvdata(dev);
SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
}
return 0;
}
#else
#define scoop_suspend NULL
#define scoop_resume NULL
#endif
int __init scoop_probe(struct device *dev)
{
struct scoop_dev *devptr;
struct scoop_config *inf;
struct platform_device *pdev = to_platform_device(dev);
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -103,25 +120,50 @@ int __init scoop_probe(struct device *dev)
if (!mem)
return -EINVAL;
devptr = kmalloc(sizeof(struct scoop_dev), GFP_KERNEL);
if (!devptr)
return -ENOMEM;
memset(devptr, 0, sizeof(struct scoop_dev));
spin_lock_init(&devptr->scoop_lock);
inf = dev->platform_data;
scoop_io_base = ioremap(mem->start, 0x1000);
if (!scoop_io_base)
devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
if (!devptr->base) {
kfree(devptr);
return -ENOMEM;
}
SCOOP_REG(SCOOP_MCR) = 0x0140;
dev_set_drvdata(dev, devptr);
reset_scoop();
printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base);
SCOOP_REG(SCOOP_GPCR) = inf->io_dir & 0xffff;
SCOOP_REG(SCOOP_GPWR) = inf->io_out & 0xffff;
SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140;
reset_scoop(dev);
SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
return 0;
}
static int scoop_remove(struct device *dev)
{
struct scoop_dev *sdev = dev_get_drvdata(dev);
if (sdev) {
iounmap(sdev->base);
kfree(sdev);
dev_set_drvdata(dev, NULL);
}
return 0;
}
static struct device_driver scoop_driver = {
.name = "sharp-scoop",
.bus = &platform_bus_type,
.probe = scoop_probe,
.remove = scoop_remove,
.suspend = scoop_suspend,
.resume = scoop_resume,
};
......
......@@ -59,7 +59,7 @@ static struct scoop_config corgi_scoop_setup = {
.io_out = CORGI_SCOOP_IO_OUT,
};
static struct platform_device corgiscoop_device = {
struct platform_device corgiscoop_device = {
.name = "sharp-scoop",
.id = -1,
.dev = {
......
......@@ -51,7 +51,7 @@ static struct scoop_config poodle_scoop_setup = {
.io_out = POODLE_SCOOP_IO_OUT,
};
static struct platform_device poodle_scoop_device = {
struct platform_device poodle_scoop_device = {
.name = "sharp-scoop",
.id = -1,
.dev = {
......
......@@ -55,7 +55,7 @@ static struct scoop_config collie_scoop_setup = {
.io_out = COLLIE_SCOOP_IO_OUT,
};
static struct platform_device colliescoop_device = {
struct platform_device colliescoop_device = {
.name = "sharp-scoop",
.id = -1,
.dev = {
......
......@@ -38,7 +38,7 @@ static struct pcmcia_irqs irqs[] = {
static void sharpsl_pcmcia_init_reset(void)
{
reset_scoop();
reset_scoop(&corgiscoop_device.dev);
keep_vs = NO_KEEP_VS;
keep_rd = 0;
}
......@@ -79,8 +79,8 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
}
/* Enable interrupt */
write_scoop_reg(SCOOP_IMR, 0x00C0);
write_scoop_reg(SCOOP_MCR, 0x0101);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, 0x00C0);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, 0x0101);
keep_vs = NO_KEEP_VS;
skt->irq = CORGI_IRQ_GPIO_CF_IRQ;
......@@ -102,30 +102,30 @@ static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
{
unsigned short cpr, csr;
cpr = read_scoop_reg(SCOOP_CPR);
cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR);
write_scoop_reg(SCOOP_IRM, 0x00FF);
write_scoop_reg(SCOOP_ISR, 0x0000);
write_scoop_reg(SCOOP_IRM, 0x0000);
csr = read_scoop_reg(SCOOP_CSR);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x00FF);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_ISR, 0x0000);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x0000);
csr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CSR);
if (csr & 0x0004) {
/* card eject */
write_scoop_reg(SCOOP_CDR, 0x0000);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
keep_vs = NO_KEEP_VS;
}
else if (!(keep_vs & NO_KEEP_VS)) {
/* keep vs1,vs2 */
write_scoop_reg(SCOOP_CDR, 0x0000);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
csr |= keep_vs;
}
else if (cpr & 0x0003) {
/* power on */
write_scoop_reg(SCOOP_CDR, 0x0000);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
keep_vs = (csr & 0x00C0);
}
else {
/* card detect */
write_scoop_reg(SCOOP_CDR, 0x0002);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0002);
}
state->detect = (csr & 0x0004) ? 0 : 1;
......@@ -166,10 +166,10 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
local_irq_save(flags);
nmcr = (mcr = read_scoop_reg(SCOOP_MCR)) & ~0x0010;
ncpr = (cpr = read_scoop_reg(SCOOP_CPR)) & ~0x0083;
nccr = (ccr = read_scoop_reg(SCOOP_CCR)) & ~0x0080;
nimr = (imr = read_scoop_reg(SCOOP_IMR)) & ~0x003E;
nmcr = (mcr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR)) & ~0x0010;
ncpr = (cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR)) & ~0x0083;
nccr = (ccr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR)) & ~0x0080;
nimr = (imr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR)) & ~0x003E;
ncpr |= (state->Vcc == 33) ? 0x0001 :
(state->Vcc == 50) ? 0x0002 : 0;
......@@ -193,13 +193,13 @@ static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
}
if (mcr != nmcr)
write_scoop_reg(SCOOP_MCR, nmcr);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, nmcr);
if (cpr != ncpr)
write_scoop_reg(SCOOP_CPR, ncpr);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR, ncpr);
if (ccr != nccr)
write_scoop_reg(SCOOP_CCR, nccr);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR, nccr);
if (imr != nimr)
write_scoop_reg(SCOOP_IMR, nimr);
write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, nimr);
local_irq_restore(flags);
......
......@@ -52,9 +52,9 @@ static void corgibl_send_intensity(int intensity)
corgi_ssp_blduty_set(intensity & 0x1f);
/* Bit 5 is via SCOOP */
if (intensity & 0x0020)
set_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);
set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
else
reset_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);
reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
spin_unlock_irqrestore(&bl_lock, flags);
}
......
......@@ -133,6 +133,10 @@ struct sharpsl_flash_param_info {
unsigned int phadadj;
};
/*
* Shared data structures
*/
extern struct platform_device corgiscoop_device;
/*
* External Functions
......
......@@ -40,8 +40,8 @@ struct scoop_config {
unsigned short io_dir;
};
void reset_scoop(void);
unsigned short set_scoop_gpio(unsigned short bit);
unsigned short reset_scoop_gpio(unsigned short bit);
unsigned short read_scoop_reg(unsigned short reg);
void write_scoop_reg(unsigned short reg, unsigned short data);
void reset_scoop(struct device *dev);
unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment