Commit 18db28ae authored by Russell King's avatar Russell King

[ARM] Update SA1111 core and related drivers for LDM.

This cset updates the SA1111 core, PCMCIA, OHCI and keyboard drivers,
allowing them to take advantage of the Linux device manager code;
this implements initial suspend/resume support for the SA1111 in the
core.  Many existing drivers currently rely on the old PM-based
interface for suspend/resume support.
parent c5ac1f1c
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
...@@ -34,11 +35,132 @@ ...@@ -34,11 +35,132 @@
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
#include "sa1111.h" /*
* We keep the following data for the overall SA1111. Note that the
* struct device and struct resource are "fake"; they should be supplied
* by the bus above us. However, in the interests of getting all SA1111
* drivers converted over to the device model, we provide this as an
* anchor point for all the other drivers.
*/
struct sa1111 {
struct device dev;
struct resource res;
int irq;
spinlock_t lock;
void *base;
};
/*
* We _really_ need to eliminate this. Its only users
* are the PWM and DMA checking code.
*/
static struct sa1111 *g_sa1111;
static struct sa1111_dev usb_dev = {
.dev = {
.name = "Intel Corporation SA1111 [USB Controller]",
},
.skpcr_mask = SKPCR_UCLKEN,
.devid = SA1111_DEVID_USB,
.irq = {
USBPWR
NIRQHCIM,
HCIBUFFACC,
HCIRMTWKP,
NHCIMFCIR,
USB_PORT_RESUME
},
};
static struct sa1111_dev sac_dev = {
.dev = {
.name = "Intel Corporation SA1111 [Audio Controller]",
},
.skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
.devid = SA1111_DEVID_SAC,
.irq = {
AUDXMTDMADONEA,
AUDXMTDMADONEB,
AUDRCVDMADONEA,
AUDRCVDMADONEB
},
};
static struct sa1111_dev ssp_dev = {
.dev = {
.name = "Intel Corporation SA1111 [SSP Controller]",
},
.skpcr_mask = SKPCR_SCLKEN,
.devid = SA1111_DEVID_SSP,
};
static struct sa1111_dev kbd_dev = {
.dev = {
.name = "Intel Corporation SA1111 [PS2]",
},
.skpcr_mask = SKPCR_PTCLKEN,
.devid = SA1111_DEVID_PS2,
.irq = {
IRQ_TPRXINT,
IRQ_TPTXINT
},
};
static struct sa1111_dev mse_dev = {
.dev = {
.name = "Intel Corporation SA1111 [PS2]",
},
.skpcr_mask = SKPCR_PMCLKEN,
.devid = SA1111_DEVID_PS2,
.irq = {
IRQ_MSRXINT,
IRQ_MSTXINT
},
};
static struct sa1111_dev int_dev = {
.dev = {
.name = "Intel Corporation SA1111 [Interrupt Controller]",
},
.skpcr_mask = 0,
.devid = SA1111_DEVID_INT,
};
struct sa1111_device *sa1111; static struct sa1111_dev pcmcia_dev = {
.dev = {
.name = "Intel Corporation SA1111 [PCMCIA Controller]",
},
.skpcr_mask = 0,
.devid = SA1111_DEVID_PCMCIA,
.irq = {
S0_READY_NINT,
S0_CD_VALID,
S0_BVD1_STSCHG,
S1_READY_NINT,
S1_CD_VALID,
S1_BVD1_STSCHG,
},
};
EXPORT_SYMBOL(sa1111); static struct sa1111_dev *devs[] = {
&usb_dev,
&sac_dev,
&ssp_dev,
&kbd_dev,
&mse_dev,
&int_dev,
&pcmcia_dev,
};
static unsigned int dev_offset[] = {
SA1111_USB,
0x0600,
0x0800,
SA1111_KBD,
SA1111_MSE,
SA1111_INTC,
0x1800,
};
/* /*
* SA1111 interrupt support. Since clearing an IRQ while there are * SA1111 interrupt support. Since clearing an IRQ while there are
...@@ -205,27 +327,33 @@ static struct irqchip sa1111_high_chip = { ...@@ -205,27 +327,33 @@ static struct irqchip sa1111_high_chip = {
.type = sa1111_type_highirq, .type = sa1111_type_highirq,
}; };
static void __init sa1111_init_irq(int irq_nr) static void __init sa1111_init_irq(struct sa1111_dev *sadev)
{ {
unsigned int irq; unsigned int irq;
request_mem_region(_INTTEST0, 512, "irqs"); /*
* We're guaranteed that this region hasn't been taken.
*/
request_mem_region(sadev->res.start, 512, "irqs");
/* disable all IRQs */ /* disable all IRQs */
INTEN0 = 0; sa1111_writel(0, sadev->mapbase + SA1111_INTEN0);
INTEN1 = 0; sa1111_writel(0, sadev->mapbase + SA1111_INTEN1);
sa1111_writel(0, sadev->mapbase + SA1111_WAKEEN0);
sa1111_writel(0, sadev->mapbase + SA1111_WAKEEN1);
/* /*
* detect on rising edge. Note: Feb 2001 Errata for SA1111 * detect on rising edge. Note: Feb 2001 Errata for SA1111
* specifies that S0ReadyInt and S1ReadyInt should be '1'. * specifies that S0ReadyInt and S1ReadyInt should be '1'.
*/ */
INTPOL0 = 0; sa1111_writel(0, sadev->mapbase + SA1111_INTPOL0);
INTPOL1 = SA1111_IRQMASK_HI(S0_READY_NINT) | sa1111_writel(SA1111_IRQMASK_HI(S0_READY_NINT) |
SA1111_IRQMASK_HI(S1_READY_NINT); SA1111_IRQMASK_HI(S1_READY_NINT),
sadev->mapbase + SA1111_INTPOL1);
/* clear all IRQs */ /* clear all IRQs */
INTSTATCLR0 = ~0; sa1111_writel(~0, sadev->mapbase + SA1111_INTSTATCLR0);
INTSTATCLR1 = ~0; sa1111_writel(~0, sadev->mapbase + SA1111_INTSTATCLR1);
for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) { for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
set_irq_chip(irq, &sa1111_low_chip); set_irq_chip(irq, &sa1111_low_chip);
...@@ -242,24 +370,11 @@ static void __init sa1111_init_irq(int irq_nr) ...@@ -242,24 +370,11 @@ static void __init sa1111_init_irq(int irq_nr)
/* /*
* Register SA1111 interrupt * Register SA1111 interrupt
*/ */
set_irq_type(irq_nr, IRQT_RISING); set_irq_type(sadev->irq[0], IRQT_RISING);
set_irq_chained_handler(irq_nr, sa1111_irq_handler); set_irq_chained_handler(sadev->irq[0], sa1111_irq_handler);
} }
static int sa1111_suspend(struct device *dev, u32 state, u32 level) static struct device_driver sa1111_device_driver;
{
return 0;
}
static int sa1111_resume(struct device *dev, u32 level)
{
return 0;
}
static struct device_driver sa1111_device_driver = {
.suspend = sa1111_suspend,
.resume = sa1111_resume,
};
/** /**
* sa1111_probe - probe for a single SA1111 chip. * sa1111_probe - probe for a single SA1111 chip.
...@@ -274,30 +389,38 @@ static struct device_driver sa1111_device_driver = { ...@@ -274,30 +389,38 @@ static struct device_driver sa1111_device_driver = {
* %0 successful. * %0 successful.
*/ */
static int __init static int __init
sa1111_probe(struct device *parent, unsigned long phys_addr) sa1111_probe(unsigned long phys_addr, int irq)
{ {
struct sa1111_device *sa; struct sa1111 *sachip;
unsigned long id; unsigned long id;
int ret = -ENODEV; unsigned int has_devs;
int i, ret = -ENODEV;
sa = kmalloc(sizeof(struct sa1111_device), GFP_KERNEL); sachip = kmalloc(sizeof(struct sa1111), GFP_KERNEL);
if (!sa) if (!sachip)
return -ENOMEM; return -ENOMEM;
memset(sa, 0, sizeof(struct sa1111_device)); memset(sachip, 0, sizeof(struct sa1111));
spin_lock_init(&sachip->lock);
strncpy(sachip->dev.name, "Intel Corporation SA1111", sizeof(sachip->dev.name));
snprintf(sachip->dev.bus_id, sizeof(sachip->dev.bus_id), "%8.8lx", phys_addr);
sachip->dev.driver = &sa1111_device_driver;
sachip->dev.driver_data = sachip;
sa->resource.name = "SA1111"; sachip->res.name = sachip->dev.name;
sa->resource.start = phys_addr; sachip->res.start = phys_addr;
sa->resource.end = phys_addr + 0x2000; sachip->res.end = phys_addr + 0x2000;
sachip->irq = irq;
if (request_resource(&iomem_resource, &sa->resource)) { if (request_resource(&iomem_resource, &sachip->res)) {
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
/* eventually ioremap... */ sachip->base = ioremap(phys_addr, PAGE_SIZE * 2);
sa->base = (void *)0xf4000000; if (!sachip->base) {
if (!sa->base) {
ret = -ENOMEM; ret = -ENOMEM;
goto release; goto release;
} }
...@@ -305,7 +428,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) ...@@ -305,7 +428,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
/* /*
* Probe for the chip. Only touch the SBI registers. * Probe for the chip. Only touch the SBI registers.
*/ */
id = sa1111_readl(sa->base + SA1111_SKID); id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id); printk(KERN_DEBUG "SA1111 not detected: ID = %08lx\n", id);
ret = -ENODEV; ret = -ENODEV;
...@@ -315,12 +438,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) ...@@ -315,12 +438,7 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
/* /*
* We found the chip. * We found the chip.
*/ */
strcpy(sa->dev.name, "SA1111"); ret = register_sys_device(&sachip->dev);
sprintf(sa->dev.bus_id, "%8.8lx", phys_addr);
sa->dev.parent = parent;
sa->dev.driver = &sa1111_device_driver;
ret = device_register(&sa->dev);
if (ret) if (ret)
printk("sa1111 device_register failed: %d\n", ret); printk("sa1111 device_register failed: %d\n", ret);
...@@ -328,19 +446,64 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) ...@@ -328,19 +446,64 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
"silicon revision %lx, metal revision %lx\n", "silicon revision %lx, metal revision %lx\n",
(id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK)); (id & SKID_SIREV_MASK)>>4, (id & SKID_MTREV_MASK));
sa1111 = sa; g_sa1111 = sachip;
has_devs = ~0;
if (machine_is_assabet() || machine_is_jornada720() ||
machine_is_badge4())
has_devs &= ~(1 << 4);
else
has_devs &= ~(1 << 1);
for (i = 0; i < ARRAY_SIZE(devs); i++) {
if (!(has_devs & (1 << i)))
continue;
snprintf(devs[i]->dev.bus_id, sizeof(devs[i]->dev.bus_id),
"%4.4x", dev_offset[i]);
devs[i]->dev.parent = &sachip->dev;
devs[i]->dev.bus = &sa1111_bus_type;
devs[i]->res.start = sachip->res.start + dev_offset[i];
devs[i]->res.end = devs[i]->res.start + 511;
devs[i]->res.name = devs[i]->dev.name;
devs[i]->res.flags = IORESOURCE_MEM;
devs[i]->mapbase = sachip->base + dev_offset[i];
if (request_resource(&sachip->res, &devs[i]->res)) {
printk("SA1111: failed to allocate resource for %s\n",
devs[i]->res.name);
continue;
}
device_register(&devs[i]->dev);
}
return 0; return 0;
unmap: unmap:
// iounmap(sa->base); iounmap(sachip->base);
release: release:
release_resource(&sa->resource); release_resource(&sachip->res);
out: out:
kfree(sa); kfree(sachip);
return ret; return ret;
} }
static void __sa1111_remove(struct sa1111 *sachip)
{
int i;
for (i = 0; i < ARRAY_SIZE(devs); i++) {
put_device(&devs[i]->dev);
release_resource(&devs[i]->res);
}
iounmap(sachip->base);
release_resource(&sachip->res);
kfree(sachip);
}
/* /*
* Bring the SA1111 out of reset. This requires a set procedure: * Bring the SA1111 out of reset. This requires a set procedure:
* 1. nRESET asserted (by hardware) * 1. nRESET asserted (by hardware)
...@@ -355,12 +518,11 @@ sa1111_probe(struct device *parent, unsigned long phys_addr) ...@@ -355,12 +518,11 @@ sa1111_probe(struct device *parent, unsigned long phys_addr)
* SBI_SMCR * SBI_SMCR
* SBI_SKID * SBI_SKID
*/ */
void sa1111_wake(void) static void sa1111_wake(struct sa1111 *sachip)
{ {
struct sa1111_device *sa = sa1111;
unsigned long flags, r; unsigned long flags, r;
local_irq_save(flags); spin_lock_irqsave(&sachip->lock, flags);
/* /*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
...@@ -373,11 +535,11 @@ void sa1111_wake(void) ...@@ -373,11 +535,11 @@ void sa1111_wake(void)
/* /*
* Turn VCO on, and disable PLL Bypass. * Turn VCO on, and disable PLL Bypass.
*/ */
r = sa1111_readl(sa->base + SA1111_SKCR); r = sa1111_readl(sachip->base + SA1111_SKCR);
r &= ~SKCR_VCO_OFF; r &= ~SKCR_VCO_OFF;
sa1111_writel(r, sa->base + SA1111_SKCR); sa1111_writel(r, sachip->base + SA1111_SKCR);
r |= SKCR_PLL_BYPASS | SKCR_OE_EN; r |= SKCR_PLL_BYPASS | SKCR_OE_EN;
sa1111_writel(r, sa->base + SA1111_SKCR); sa1111_writel(r, sachip->base + SA1111_SKCR);
/* /*
* Wait lock time. SA1111 manual _doesn't_ * Wait lock time. SA1111 manual _doesn't_
...@@ -389,7 +551,7 @@ void sa1111_wake(void) ...@@ -389,7 +551,7 @@ void sa1111_wake(void)
* Enable RCLK. We also ensure that RDYEN is set. * Enable RCLK. We also ensure that RDYEN is set.
*/ */
r |= SKCR_RCLKEN | SKCR_RDYEN; r |= SKCR_RCLKEN | SKCR_RDYEN;
sa1111_writel(r, sa->base + SA1111_SKCR); sa1111_writel(r, sachip->base + SA1111_SKCR);
/* /*
* Wait 14 RCLK cycles for the chip to finish coming out * Wait 14 RCLK cycles for the chip to finish coming out
...@@ -400,76 +562,31 @@ void sa1111_wake(void) ...@@ -400,76 +562,31 @@ void sa1111_wake(void)
/* /*
* Ensure all clocks are initially off. * Ensure all clocks are initially off.
*/ */
sa1111_writel(0, sa->base + SA1111_SKPCR); sa1111_writel(0, sachip->base + SA1111_SKPCR);
local_irq_restore(flags); spin_unlock_irqrestore(&sachip->lock, flags);
}
void sa1111_doze(void)
{
struct sa1111_device *sa = sa1111;
unsigned long flags;
unsigned int val;
local_irq_save(flags);
if (sa1111_readl(sa->base + SA1111_SKPCR) & SKPCR_UCLKEN) {
local_irq_restore(flags);
printk("SA1111 doze mode refused\n");
return;
}
val = sa1111_readl(sa->base + SA1111_SKCR);
sa1111_writel(val & ~SKCR_RCLKEN, sa->base + SA1111_SKCR);
local_irq_restore(flags);
} }
/* /*
* Configure the SA1111 shared memory controller. * Configure the SA1111 shared memory controller.
*/ */
void sa1111_configure_smc(int sdram, unsigned int drac, unsigned int cas_latency) void
sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
unsigned int cas_latency)
{ {
struct sa1111_device *sa = sa1111;
unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC); unsigned int smcr = SMCR_DTIM | SMCR_MBGE | FInsrt(drac, SMCR_DRAC);
if (cas_latency == 3) if (cas_latency == 3)
smcr |= SMCR_CLAT; smcr |= SMCR_CLAT;
sa1111_writel(smcr, sa->base + SA1111_SMCR); sa1111_writel(smcr, sachip->base + SA1111_SMCR);
}
EXPORT_SYMBOL(sa1111_wake);
EXPORT_SYMBOL(sa1111_doze);
void sa1111_enable_device(unsigned int mask)
{
struct sa1111_device *sa = sa1111;
unsigned int val;
preempt_disable();
val = sa1111_readl(sa->base + SA1111_SKPCR);
sa1111_writel(val | mask, sa->base + SA1111_SKPCR);
preempt_enable();
} }
void sa1111_disable_device(unsigned int mask) /*
{ * According to the "Intel StrongARM SA-1111 Microprocessor Companion
struct sa1111_device *sa = sa1111;
unsigned int val;
preempt_disable();
val = sa1111_readl(sa->base + SA1111_SKPCR);
sa1111_writel(val & ~mask, sa->base + SA1111_SKPCR);
preempt_enable();
}
EXPORT_SYMBOL(sa1111_enable_device);
EXPORT_SYMBOL(sa1111_disable_device);
/* According to the "Intel StrongARM SA-1111 Microprocessor Companion
* Chip Specification Update" (June 2000), erratum #7, there is a * Chip Specification Update" (June 2000), erratum #7, there is a
* significant bug in Serial Audio Controller DMA. If the SAC is * significant bug in the SA1111 SDRAM shared memory controller. If
* accessing a region of memory above 1MB relative to the bank base, * an access to a region of memory above 1MB relative to the bank base,
* it is important that address bit 10 _NOT_ be asserted. Depending * it is important that address bit 10 _NOT_ be asserted. Depending
* on the configuration of the RAM, bit 10 may correspond to one * on the configuration of the RAM, bit 10 may correspond to one
* of several different (processor-relative) address bits. * of several different (processor-relative) address bits.
...@@ -479,7 +596,9 @@ EXPORT_SYMBOL(sa1111_disable_device); ...@@ -479,7 +596,9 @@ EXPORT_SYMBOL(sa1111_disable_device);
*/ */
int sa1111_check_dma_bug(dma_addr_t addr) int sa1111_check_dma_bug(dma_addr_t addr)
{ {
unsigned int physaddr=SA1111_DMA_ADDR((unsigned int)addr); struct sa1111 *sachip = g_sa1111;
unsigned int physaddr = SA1111_DMA_ADDR((unsigned int)addr);
unsigned int smcr;
/* Section 4.6 of the "Intel StrongARM SA-1111 Development Module /* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
* User's Guide" mentions that jumpers R51 and R52 control the * User's Guide" mentions that jumpers R51 and R52 control the
...@@ -494,9 +613,10 @@ int sa1111_check_dma_bug(dma_addr_t addr) ...@@ -494,9 +613,10 @@ int sa1111_check_dma_bug(dma_addr_t addr)
* above the start of the target bank: * above the start of the target bank:
*/ */
if (physaddr<(1<<20)) if (physaddr<(1<<20))
return 0; return 0;
switch (FExtr(SBI_SMCR, SMCR_DRAC)) { smcr = sa1111_readl(sachip->base + SA1111_SMCR);
switch (FExtr(smcr, SMCR_DRAC)) {
case 01: /* 10 row + bank address bits, A<20> must not be set */ case 01: /* 10 row + bank address bits, A<20> must not be set */
if (physaddr & (1<<20)) if (physaddr & (1<<20))
return -1; return -1;
...@@ -523,27 +643,26 @@ int sa1111_check_dma_bug(dma_addr_t addr) ...@@ -523,27 +643,26 @@ int sa1111_check_dma_bug(dma_addr_t addr)
break; break;
default: default:
printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%lo\n", printk(KERN_ERR "%s(): invalid SMCR DRAC value 0%lo\n",
__FUNCTION__, FExtr(SBI_SMCR, SMCR_DRAC)); __FUNCTION__, FExtr(smcr, SMCR_DRAC));
return -1; return -1;
} }
return 0; return 0;
} }
EXPORT_SYMBOL(sa1111_check_dma_bug);
int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
{ {
unsigned int val;
int ret; int ret;
ret = sa1111_probe(parent, phys); ret = sa1111_probe(phys, irq);
if (ret < 0) if (ret < 0)
return ret; return ret;
/* /*
* We found it. Wake the chip up. * We found it. Wake the chip up.
*/ */
sa1111_wake(); sa1111_wake(g_sa1111);
/* /*
* The SDRAM configuration of the SA1110 and the SA1111 must * The SDRAM configuration of the SA1110 and the SA1111 must
...@@ -552,7 +671,7 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) ...@@ -552,7 +671,7 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
* MBGNT signal, so we must have called sa1110_mb_disable() * MBGNT signal, so we must have called sa1110_mb_disable()
* beforehand. * beforehand.
*/ */
sa1111_configure_smc(1, sa1111_configure_smc(g_sa1111, 1,
FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), FExtr(MDCNFG, MDCNFG_SA1110_DRAC0),
FExtr(MDCNFG, MDCNFG_SA1110_TDL0)); FExtr(MDCNFG, MDCNFG_SA1110_TDL0));
...@@ -560,7 +679,8 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) ...@@ -560,7 +679,8 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
* We only need to turn on DCLK whenever we want to use the * We only need to turn on DCLK whenever we want to use the
* DMA. It can otherwise be held firmly in the off position. * DMA. It can otherwise be held firmly in the off position.
*/ */
sa1111_enable_device(SKPCR_DCLKEN); val = sa1111_readl(g_sa1111->base + SA1111_SKPCR);
sa1111_writel(val | SKPCR_DCLKEN, g_sa1111->base + SA1111_SKPCR);
/* /*
* Enable the SA1110 memory bus request and grant signals. * Enable the SA1110 memory bus request and grant signals.
...@@ -570,7 +690,341 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq) ...@@ -570,7 +690,341 @@ int sa1111_init(struct device *parent, unsigned long phys, unsigned int irq)
/* /*
* Initialise SA1111 IRQs * Initialise SA1111 IRQs
*/ */
sa1111_init_irq(irq); int_dev.irq[0] = irq;
sa1111_init_irq(&int_dev);
return 0;
}
struct sa1111_save_data {
unsigned int skcr;
unsigned int skpcr;
unsigned int skcdr;
unsigned char skaud;
unsigned char skpwm0;
unsigned char skpwm1;
/*
* Interrupt controller
*/
unsigned int intpol0;
unsigned int intpol1;
unsigned int inten0;
unsigned int inten1;
unsigned int wakepol0;
unsigned int wakepol1;
unsigned int wakeen0;
unsigned int wakeen1;
};
static int sa1111_suspend(struct device *dev, u32 state, u32 level)
{
struct sa1111 *sachip = dev->driver_data;
unsigned long flags;
char *base;
/*
* Save state.
*/
if (level == SUSPEND_SAVE_STATE ||
level == SUSPEND_DISABLE ||
level == SUSPEND_POWER_DOWN) {
struct sa1111_save_data *save;
if (!dev->saved_state)
dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL);
if (!dev->saved_state)
return -ENOMEM;
save = (struct sa1111_save_data *)dev->saved_state;
spin_lock_irqsave(&sachip->lock, flags);
base = sachip->base;
save->skcr = sa1111_readl(base + SA1111_SKCR);
save->skpcr = sa1111_readl(base + SA1111_SKPCR);
save->skcdr = sa1111_readl(base + SA1111_SKCDR);
save->skaud = sa1111_readl(base + SA1111_SKAUD);
save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0);
save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
save->intpol0 = sa1111_readl(base + SA1111_INTPOL0);
save->intpol1 = sa1111_readl(base + SA1111_INTPOL1);
save->inten0 = sa1111_readl(base + SA1111_INTEN0);
save->inten1 = sa1111_readl(base + SA1111_INTEN1);
save->wakepol0 = sa1111_readl(base + SA1111_WAKEPOL0);
save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1);
save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0);
save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1);
spin_unlock_irqrestore(&sachip->lock, flags);
}
/*
* Disable.
*/
if (level == SUSPEND_DISABLE && state == 4) {
unsigned int val;
spin_lock_irqsave(&sachip->lock, flags);
base = sachip->base;
sa1111_writel(0, base + SA1111_SKPWM0);
sa1111_writel(0, base + SA1111_SKPWM1);
val = sa1111_readl(base + SA1111_SKCR);
sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR);
spin_unlock_irqrestore(&sachip->lock, flags);
}
return 0;
}
/*
* sa1111_resume - Restore the SA1111 device state.
* @dev: device to restore
* @level: resume level
*
* Restore the general state of the SA1111; clock control and
* interrupt controller. Other parts of the SA1111 must be
* restored by their respective drivers, and must be called
* via LDM after this function.
*/
static int sa1111_resume(struct device *dev, u32 level)
{
struct sa1111 *sachip = dev->driver_data;
struct sa1111_save_data *save;
unsigned long flags, id;
char *base;
if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE)
return 0;
save = (struct sa1111_save_data *)dev->saved_state;
if (!save)
return 0;
dev->saved_state = NULL;
/*
* Ensure that the SA1111 is still here.
*/
id = sa1111_readl(sachip->base + SA1111_SKID);
if ((id & SKID_ID_MASK) != SKID_SA1111_ID) {
__sa1111_remove(sachip);
kfree(save);
return 0;
}
spin_lock_irqsave(&sachip->lock, flags);
sa1111_wake(sachip);
base = sachip->base;
sa1111_writel(save->skcr, base + SA1111_SKCR);
sa1111_writel(save->skpcr, base + SA1111_SKPCR);
sa1111_writel(save->skcdr, base + SA1111_SKCDR);
sa1111_writel(save->skaud, base + SA1111_SKAUD);
sa1111_writel(save->skpwm0, base + SA1111_SKPWM0);
sa1111_writel(save->skpwm1, base + SA1111_SKPWM1);
base = sachip->base + SA1111_INTC;
sa1111_writel(save->intpol0, base + SA1111_INTPOL0);
sa1111_writel(save->intpol1, base + SA1111_INTPOL1);
sa1111_writel(save->inten0, base + SA1111_INTEN0);
sa1111_writel(save->inten1, base + SA1111_INTEN1);
sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0);
sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1);
sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0);
sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1);
spin_unlock_irqrestore(&sachip->lock, flags);
kfree(save);
return 0; return 0;
} }
static struct device_driver sa1111_device_driver = {
.suspend = sa1111_suspend,
.resume = sa1111_resume,
};
/*
* Get the parent device driver (us) structure
* from a child function device
*/
static inline struct sa1111 *sa1111_chip_driver(struct sa1111_dev *sadev)
{
return (struct sa1111 *)sadev->dev.parent->driver_data;
}
/*
* The bits in the opdiv field are non-linear.
*/
static unsigned char opdiv_table[] = { 1, 4, 2, 8 };
static unsigned int __sa1111_pll_clock(struct sa1111 *sachip)
{
unsigned int skcdr, fbdiv, ipdiv, opdiv;
skcdr = sa1111_readl(sachip->base + SA1111_SKCDR);
fbdiv = (skcdr & 0x007f) + 2;
ipdiv = ((skcdr & 0x0f80) >> 7) + 2;
opdiv = opdiv_table[(skcdr & 0x3000) >> 12];
return 3686400 * fbdiv / (ipdiv * opdiv);
}
/**
* sa1111_pll_clock - return the current PLL clock frequency.
* @sadev: SA1111 function block
*
* BUG: we should look at SKCR. We also blindly believe that
* the chip is being fed with the 3.6864MHz clock.
*
* Returns the PLL clock in Hz.
*/
unsigned int sa1111_pll_clock(struct sa1111_dev *sadev)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
return __sa1111_pll_clock(sachip);
}
/**
* sa1111_select_audio_mode - select I2S or AC link mode
* @sadev: SA1111 function block
* @mode: One of %SA1111_AUDIO_ACLINK or %SA1111_AUDIO_I2S
*
* Frob the SKCR to select AC Link mode or I2S mode for
* the audio block.
*/
void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned long flags;
unsigned int val;
spin_lock_irqsave(&sachip->lock, flags);
val = sa1111_readl(sachip->base + SA1111_SKCR);
if (mode == SA1111_AUDIO_I2S) {
val &= ~SKCR_SELAC;
} else {
val |= SKCR_SELAC;
}
sa1111_writel(val, sachip->base + SA1111_SKCR);
spin_unlock_irqrestore(&sachip->lock, flags);
}
/**
* sa1111_set_audio_rate - set the audio sample rate
* @sadev: SA1111 SAC function block
* @rate: sample rate to select
*/
int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned int div;
if (sadev->devid != SA1111_DEVID_SAC)
return -EINVAL;
div = (__sa1111_pll_clock(sachip) / 256 + rate / 2) / rate;
if (div == 0)
div = 1;
if (div > 128)
div = 128;
sa1111_writel(div - 1, sachip->base + SA1111_SKAUD);
return 0;
}
/**
* sa1111_get_audio_rate - get the audio sample rate
* @sadev: SA1111 SAC function block device
*/
int sa1111_get_audio_rate(struct sa1111_dev *sadev)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned long div;
if (sadev->devid != SA1111_DEVID_SAC)
return -EINVAL;
div = sa1111_readl(sachip->base + SA1111_SKAUD) + 1;
return __sa1111_pll_clock(sachip) / (256 * div);
}
/*
* Individual device operations.
*/
/**
* sa1111_enable_device - enable an on-chip SA1111 function block
* @sadev: SA1111 function block device to enable
*/
void sa1111_enable_device(struct sa1111_dev *sadev)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned long flags;
unsigned int val;
spin_lock_irqsave(&sachip->lock, flags);
val = sa1111_readl(sachip->base + SA1111_SKPCR);
sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
spin_unlock_irqrestore(&sachip->lock, flags);
}
/**
* sa1111_disable_device - disable an on-chip SA1111 function block
* @sadev: SA1111 function block device to disable
*/
void sa1111_disable_device(struct sa1111_dev *sadev)
{
struct sa1111 *sachip = sa1111_chip_driver(sadev);
unsigned long flags;
unsigned int val;
spin_lock_irqsave(&sachip->lock, flags);
val = sa1111_readl(sachip->base + SA1111_SKPCR);
sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
spin_unlock_irqrestore(&sachip->lock, flags);
}
/*
* SA1111 "Register Access Bus."
*
* We model this as a regular bus type, and hang devices directly
* off this.
*/
static int sa1111_match(struct device *_dev, struct device_driver *_drv)
{
struct sa1111_dev *dev = SA1111_DEV(_dev);
struct sa1111_driver *drv = SA1111_DRV(_drv);
return dev->devid == drv->devid;
}
struct bus_type sa1111_bus_type = {
.name = "RAB",
.match = sa1111_match,
};
static int sa1111_rab_bus_init(void)
{
return bus_register(&sa1111_bus_type);
}
postcore_initcall(sa1111_rab_bus_init);
EXPORT_SYMBOL(sa1111_check_dma_bug);
EXPORT_SYMBOL(sa1111_select_audio_mode);
EXPORT_SYMBOL(sa1111_set_audio_rate);
EXPORT_SYMBOL(sa1111_get_audio_rate);
EXPORT_SYMBOL(sa1111_enable_device);
EXPORT_SYMBOL(sa1111_disable_device);
EXPORT_SYMBOL(sa1111_pll_clock);
EXPORT_SYMBOL(sa1111_bus_type);
...@@ -15,20 +15,26 @@ ...@@ -15,20 +15,26 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <asm/hardware/sa1111.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/hardware/sa1111.h>
extern struct pt_regs *kbd_pt_regs; extern struct pt_regs *kbd_pt_regs;
struct ps2if { struct ps2if {
struct serio io; struct serio io;
struct resource *res; struct sa1111_dev *dev;
unsigned long base; unsigned long base;
unsigned int irq; unsigned int open;
unsigned int skpcr_mask; spinlock_t lock;
unsigned int head;
unsigned int tail;
unsigned char buf[4];
}; };
/* /*
...@@ -36,104 +42,150 @@ struct ps2if { ...@@ -36,104 +42,150 @@ struct ps2if {
* at the most one, but we loop for safety. If there was a * at the most one, but we loop for safety. If there was a
* framing error, we have to manually clear the status. * framing error, we have to manually clear the status.
*/ */
static void ps2_int(int irq, void *dev_id, struct pt_regs *regs) static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct ps2if *sa = dev_id; struct ps2if *ps2if = dev_id;
unsigned int scancode, flag, status; unsigned int scancode, flag, status;
kbd_pt_regs = regs; kbd_pt_regs = regs;
status = sa1111_readl(sa->base + SA1111_PS2STAT); status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
while (status & PS2STAT_RXF) { while (status & PS2STAT_RXF) {
if (status & PS2STAT_STP) if (status & PS2STAT_STP)
sa1111_writel(PS2STAT_STP, sa->base + SA1111_PS2STAT); sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);
flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) | flag = (status & PS2STAT_STP ? SERIO_FRAME : 0) |
(status & PS2STAT_RXP ? 0 : SERIO_PARITY); (status & PS2STAT_RXP ? 0 : SERIO_PARITY);
scancode = sa1111_readl(sa->base + SA1111_PS2DATA) & 0xff; scancode = sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff;
if (hweight8(scancode) & 1) if (hweight8(scancode) & 1)
flag ^= SERIO_PARITY; flag ^= SERIO_PARITY;
serio_interrupt(&sa->io, scancode, flag); serio_interrupt(&ps2if->io, scancode, flag);
status = sa1111_readl(sa->base + SA1111_PS2STAT); status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
} }
} }
/*
* Completion of ps2 write
*/
static void ps2_txint(int irq, void *dev_id, struct pt_regs *regs)
{
struct ps2if *ps2if = dev_id;
unsigned int status;
spin_lock(&ps2if->lock);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
if (ps2if->head == ps2if->tail) {
disable_irq(irq);
/* done */
} else if (status & PS2STAT_TXE) {
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
}
spin_unlock(&ps2if->lock);
}
/* /*
* Write a byte to the PS2 port. We have to wait for the * Write a byte to the PS2 port. We have to wait for the
* port to indicate that the transmitter is empty. * port to indicate that the transmitter is empty.
*/ */
static int ps2_write(struct serio *io, unsigned char val) static int ps2_write(struct serio *io, unsigned char val)
{ {
struct ps2if *sa = io->driver; struct ps2if *ps2if = io->driver;
unsigned int timeleft = 10000; /* timeout in 100ms */ unsigned long flags;
unsigned int head;
while ((sa1111_readl(sa->base + SA1111_PS2STAT) & PS2STAT_TXE) == 0 && spin_lock_irqsave(&ps2if->lock, flags);
timeleft--)
udelay(10);
if (timeleft) /*
sa1111_writel(val, sa->base + SA1111_PS2DATA); * If the TX register is empty, we can go straight out.
*/
if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
} else {
if (ps2if->head == ps2if->tail)
enable_irq(ps2if->dev->irq[1]);
head = (ps2if->head + 1) & (sizeof(ps2if->buf) - 1);
if (head != ps2if->tail) {
ps2if->buf[ps2if->head] = val;
ps2if->head = head;
}
}
return timeleft ? 0 : SERIO_TIMEOUT; spin_unlock_irqrestore(&ps2if->lock, flags);
return 0;
} }
static int ps2_open(struct serio *io) static int ps2_open(struct serio *io)
{ {
struct ps2if *sa = io->driver; struct ps2if *ps2if = io->driver;
int ret; int ret;
sa1111_enable_device(sa->skpcr_mask); sa1111_enable_device(ps2if->dev);
ret = request_irq(sa->irq, ps2_int, 0, "ps2", sa); ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
if (ret) { if (ret) {
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n", printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
sa->irq, ret); ps2if->dev->irq[0], ret);
return ret; return ret;
} }
sa1111_writel(PS2CR_ENA, sa->base + SA1111_PS2CR); ret = request_irq(ps2if->dev->irq[1], ps2_txint, 0,
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
if (ret) {
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
ps2if->dev->irq[1], ret);
free_irq(ps2if->dev->irq[0], ps2if);
return ret;
}
ps2if->open = 1;
sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
return 0; return 0;
} }
static void ps2_close(struct serio *io) static void ps2_close(struct serio *io)
{ {
struct ps2if *sa = io->driver; struct ps2if *ps2if = io->driver;
sa1111_writel(0, ps2if->base + SA1111_PS2CR);
sa1111_writel(0, sa->base + SA1111_PS2CR); ps2if->open = 0;
free_irq(sa->irq, sa); free_irq(ps2if->dev->irq[1], ps2if);
free_irq(ps2if->dev->irq[0], ps2if);
sa1111_disable_device(sa->skpcr_mask); sa1111_disable_device(ps2if->dev);
} }
/* /*
* Clear the input buffer. * Clear the input buffer.
*/ */
static void __init ps2_clear_input(struct ps2if *sa) static void __init ps2_clear_input(struct ps2if *ps2if)
{ {
int maxread = 100; int maxread = 100;
while (maxread--) { while (maxread--) {
if ((sa1111_readl(sa->base + SA1111_PS2DATA) & 0xff) == 0xff) if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
break; break;
} }
} }
static inline unsigned int static inline unsigned int
ps2_test_one(struct ps2if *sa, unsigned int mask) ps2_test_one(struct ps2if *ps2if, unsigned int mask)
{ {
unsigned int val; unsigned int val;
sa1111_writel(PS2CR_ENA | mask, sa->base + SA1111_PS2CR); sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
udelay(2); udelay(2);
val = sa1111_readl(sa->base + SA1111_PS2STAT); val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
return val & (PS2STAT_KBC | PS2STAT_KBD); return val & (PS2STAT_KBC | PS2STAT_KBD);
} }
...@@ -141,141 +193,168 @@ ps2_test_one(struct ps2if *sa, unsigned int mask) ...@@ -141,141 +193,168 @@ ps2_test_one(struct ps2if *sa, unsigned int mask)
* Test the keyboard interface. We basically check to make sure that * Test the keyboard interface. We basically check to make sure that
* we can drive each line to the keyboard independently of each other. * we can drive each line to the keyboard independently of each other.
*/ */
static int __init ps2_test(struct ps2if *sa) static int __init ps2_test(struct ps2if *ps2if)
{ {
unsigned int stat; unsigned int stat;
int ret = 0; int ret = 0;
stat = ps2_test_one(sa, PS2CR_FKC); stat = ps2_test_one(ps2if, PS2CR_FKC);
if (stat != PS2STAT_KBD) { if (stat != PS2STAT_KBD) {
printk("Keyboard interface test failed[1]: %02x\n", stat); printk("PS/2 interface test failed[1]: %02x\n", stat);
ret = -ENODEV; ret = -ENODEV;
} }
stat = ps2_test_one(sa, 0); stat = ps2_test_one(ps2if, 0);
if (stat != (PS2STAT_KBC | PS2STAT_KBD)) { if (stat != (PS2STAT_KBC | PS2STAT_KBD)) {
printk("Keyboard interface test failed[2]: %02x\n", stat); printk("PS/2 interface test failed[2]: %02x\n", stat);
ret = -ENODEV; ret = -ENODEV;
} }
stat = ps2_test_one(sa, PS2CR_FKD); stat = ps2_test_one(ps2if, PS2CR_FKD);
if (stat != PS2STAT_KBC) { if (stat != PS2STAT_KBC) {
printk("Keyboard interface test failed[3]: %02x\n", stat); printk("PS/2 interface test failed[3]: %02x\n", stat);
ret = -ENODEV; ret = -ENODEV;
} }
sa1111_writel(0, sa->base + SA1111_PS2CR); sa1111_writel(0, ps2if->base + SA1111_PS2CR);
return ret; return ret;
} }
/* /*
* Initialise one PS/2 port. * Add one device to this driver.
*/ */
static int __init ps2_init_one(struct sa1111_device *dev, struct ps2if *sa) static int ps2_probe(struct device *dev)
{ {
struct sa1111_dev *sadev = SA1111_DEV(dev);
struct ps2if *ps2if;
int ret; int ret;
ps2if = kmalloc(sizeof(struct ps2if), GFP_KERNEL);
if (!ps2if) {
return -ENOMEM;
}
memset(ps2if, 0, sizeof(struct ps2if));
ps2if->io.type = SERIO_8042;
ps2if->io.write = ps2_write;
ps2if->io.open = ps2_open;
ps2if->io.close = ps2_close;
ps2if->io.name = dev->name;
ps2if->io.phys = dev->bus_id;
ps2if->io.driver = ps2if;
ps2if->dev = sadev;
dev->driver_data = ps2if;
spin_lock_init(&ps2if->lock);
/* /*
* Request the physical region for this PS2 port. * Request the physical region for this PS2 port.
*/ */
sa->res = request_mem_region(_SA1111(sa->base), 512, "ps2"); if (!request_mem_region(sadev->res.start,
if (!sa->res) sadev->res.end - sadev->res.start + 1,
return -EBUSY; SA1111_DRIVER_NAME(sadev))) {
ret = -EBUSY;
goto free;
}
/* /*
* Convert the chip offset to virtual address. * Our parent device has already mapped the region.
*/ */
sa->base += (unsigned long)dev->base; ps2if->base = (unsigned long)sadev->mapbase;
sa1111_enable_device(sa->skpcr_mask); sa1111_enable_device(ps2if->dev);
/* Incoming clock is 8MHz */ /* Incoming clock is 8MHz */
sa1111_writel(0, sa->base + SA1111_PS2CLKDIV); sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
sa1111_writel(127, sa->base + SA1111_PS2PRECNT); sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
/* /*
* Flush any pending input. * Flush any pending input.
*/ */
ps2_clear_input(sa); ps2_clear_input(ps2if);
/* /*
* Test the keyboard interface. * Test the keyboard interface.
*/ */
ret = ps2_test(sa); ret = ps2_test(ps2if);
if (ret) if (ret)
goto out; goto out;
/* /*
* Flush any pending input. * Flush any pending input.
*/ */
ps2_clear_input(sa); ps2_clear_input(ps2if);
sa1111_disable_device(sa->skpcr_mask);
serio_register_port(&sa->io); sa1111_disable_device(ps2if->dev);
serio_register_port(&ps2if->io);
return 0; return 0;
out: out:
sa1111_disable_device(sa->skpcr_mask); sa1111_disable_device(ps2if->dev);
release_resource(sa->res); release_mem_region(sadev->res.start,
sadev->res.end - sadev->res.start + 1);
free:
dev->driver_data = NULL;
kfree(ps2if);
return ret; return ret;
} }
/* /*
* Remove one PS/2 port. * Remove one device from this driver.
*/ */
static void __exit ps2_remove_one(struct ps2if *sa) static int ps2_remove(struct device *dev)
{ {
serio_unregister_port(&sa->io); struct ps2if *ps2if = dev->driver_data;
release_resource(sa->res); struct sa1111_dev *sadev = SA1111_DEV(dev);
serio_unregister_port(&ps2if->io);
release_mem_region(sadev->res.start,
sadev->res.end - sadev->res.start + 1);
kfree(ps2if);
dev->driver_data = NULL;
return 0;
} }
static struct ps2if ps2_kbd_port = /*
* We should probably do something here, but what?
*/
static int ps2_suspend(struct device *dev, u32 state, u32 level)
{ {
io: { return 0;
type: SERIO_8042, }
write: ps2_write,
open: ps2_open,
close: ps2_close,
name: "SA1111 PS/2 kbd port",
phys: "sa1111/serio0",
driver: &ps2_kbd_port,
},
base: SA1111_KBD,
irq: IRQ_TPRXINT,
skpcr_mask: SKPCR_PTCLKEN,
};
static struct ps2if ps2_mse_port = static int ps2_resume(struct device *dev, u32 level)
{ {
io: { return 0;
type: SERIO_8042, }
write: ps2_write,
open: ps2_open, /*
close: ps2_close, * Our device driver structure
name: "SA1111 PS/2 mouse port", */
phys: "sa1111/serio1", static struct sa1111_driver ps2_driver = {
driver: &ps2_mse_port, .drv = {
.name = "SA1111 PS2",
.bus = &sa1111_bus_type,
.probe = ps2_probe,
.remove = ps2_remove,
.suspend = ps2_suspend,
.resume = ps2_resume,
}, },
base: SA1111_MSE, .devid = SA1111_DEVID_PS2,
irq: IRQ_MSRXINT,
skpcr_mask: SKPCR_PMCLKEN,
}; };
static int __init ps2_init(void) static int __init ps2_init(void)
{ {
int ret = -ENODEV; return driver_register(&ps2_driver.drv);
if (sa1111) {
ret = ps2_init_one(sa1111, &ps2_kbd_port);
}
return ret;
} }
static void __exit ps2_exit(void) static void __exit ps2_exit(void)
{ {
ps2_remove_one(&ps2_kbd_port); remove_driver(&ps2_driver.drv);
} }
module_init(ps2_init); module_init(ps2_init);
......
...@@ -20,6 +20,7 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then ...@@ -20,6 +20,7 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then
fi fi
if [ "$CONFIG_ARM" = "y" ]; then if [ "$CONFIG_ARM" = "y" ]; then
dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA dep_tristate ' SA1100 support' CONFIG_PCMCIA_SA1100 $CONFIG_ARCH_SA1100 $CONFIG_PCMCIA
dep_tristate ' SA1111 support' CONFIG_PCMCIA_SA1111 $CONFIG_PCMCIA_SA1100 $CONFIG_SA1111 $CONFIG_PCMCIA
fi fi
fi fi
......
...@@ -14,6 +14,7 @@ obj-$(CONFIG_I82092) += i82092.o ...@@ -14,6 +14,7 @@ obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o obj-$(CONFIG_TCIC) += tcic.o
obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o obj-$(CONFIG_PCMCIA_SA1100) += sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa1111_cs.o
yenta_socket-objs := pci_socket.o yenta.o yenta_socket-objs := pci_socket.o yenta.o
...@@ -21,26 +22,29 @@ pcmcia_core-objs-y := cistpl.o rsrc_mgr.o bulkmem.o cs.o ...@@ -21,26 +22,29 @@ pcmcia_core-objs-y := cistpl.o rsrc_mgr.o bulkmem.o cs.o
pcmcia_core-objs-$(CONFIG_CARDBUS) += cardbus.o pcmcia_core-objs-$(CONFIG_CARDBUS) += cardbus.o
pcmcia_core-objs := $(pcmcia_core-objs-y) pcmcia_core-objs := $(pcmcia_core-objs-y)
sa1111_cs-objs-y := sa1111_generic.o
sa1111_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o
sa1111_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
sa1111_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o
sa1111_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o
sa1111_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o
sa1111_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o
sa1111_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o
sa1111_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o
sa1111_cs-objs := $(sa1111_cs-objs-y)
sa1100_cs-objs-y := sa1100_generic.o sa1100_cs-objs-y := sa1100_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_ADSBITSY) += sa1100_adsbitsy.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o sa1100_cs-objs-$(CONFIG_SA1100_ASSABET) += sa1100_assabet.o
sa1100_cs-objs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_BADGE4) += sa1100_badge4.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o sa1100_cs-objs-$(CONFIG_SA1100_CERF) += sa1100_cerf.o
sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o sa1100_cs-objs-$(CONFIG_SA1100_FLEXANET) += sa1100_flexanet.o
sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o sa1100_cs-objs-$(CONFIG_SA1100_FREEBIRD) += sa1100_freebird.o
sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSMASTER) += sa1100_graphicsmaster.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o sa1100_cs-objs-$(CONFIG_SA1100_GRAPHICSCLIENT) += sa1100_graphicsclient.o
sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o sa1100_cs-objs-$(CONFIG_SA1100_H3600) += sa1100_h3600.o
sa1100_cs-objs-$(CONFIG_SA1100_JORNADA720) += sa1100_jornada720.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o sa1100_cs-objs-$(CONFIG_SA1100_PANGOLIN) += sa1100_pangolin.o
sa1100_cs-objs-$(CONFIG_SA1100_PFS168) += sa1100_pfs168.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_PT_SYSTEM3) += sa1100_system3.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o sa1100_cs-objs-$(CONFIG_SA1100_SHANNON) += sa1100_shannon.o
sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o sa1100_cs-objs-$(CONFIG_SA1100_SIMPAD) += sa1100_simpad.o
sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o sa1100_cs-objs-$(CONFIG_SA1100_STORK) += sa1100_stork.o
sa1100_cs-objs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o sa1100_cs-objs-$(CONFIG_SA1100_TRIZEPS) += sa1100_trizeps.o
sa1100_cs-objs-$(CONFIG_SA1100_XP860) += sa1100_xp860.o sa1111_generic.o
sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o sa1100_cs-objs-$(CONFIG_SA1100_YOPY) += sa1100_yopy.o
sa1100_cs-objs := $(sa1100_cs-objs-y) sa1100_cs-objs := $(sa1100_cs-objs-y)
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/arch/badge4.h> #include <asm/arch/badge4.h>
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
......
...@@ -1135,15 +1135,9 @@ static int __init sa1100_pcmcia_init(void) ...@@ -1135,15 +1135,9 @@ static int __init sa1100_pcmcia_init(void)
} }
#endif #endif
#ifdef CONFIG_SA1100_ADSBITSY
pcmcia_adsbitsy_init();
#endif
#ifdef CONFIG_SA1100_ASSABET #ifdef CONFIG_SA1100_ASSABET
pcmcia_assabet_init(); pcmcia_assabet_init();
#endif #endif
#ifdef CONFIG_SA1100_BADGE4
pcmcia_badge4_init();
#endif
#ifdef CONFIG_SA1100_CERF #ifdef CONFIG_SA1100_CERF
pcmcia_cerf_init(); pcmcia_cerf_init();
#endif #endif
...@@ -1156,24 +1150,9 @@ static int __init sa1100_pcmcia_init(void) ...@@ -1156,24 +1150,9 @@ static int __init sa1100_pcmcia_init(void)
#ifdef CONFIG_SA1100_GRAPHICSCLIENT #ifdef CONFIG_SA1100_GRAPHICSCLIENT
pcmcia_gcplus_init(); pcmcia_gcplus_init();
#endif #endif
#ifdef CONFIG_SA1100_GRAPHICSMASTER
pcmcia_graphicsmaster_init();
#endif
#ifdef CONFIG_SA1100_JORNADA720
pcmcia_jornada720_init();
#endif
#ifdef CONFIG_ASSABET_NEPONSET
pcmcia_neponset_init();
#endif
#ifdef CONFIG_SA1100_PANGOLIN #ifdef CONFIG_SA1100_PANGOLIN
pcmcia_pangolin_init(); pcmcia_pangolin_init();
#endif #endif
#ifdef CONFIG_SA1100_PFS168
pcmcia_pfs_init();
#endif
#ifdef CONFIG_SA1100_PT_SYSTEM3
pcmcia_system3_init();
#endif
#ifdef CONFIG_SA1100_SHANNON #ifdef CONFIG_SA1100_SHANNON
pcmcia_shannon_init(); pcmcia_shannon_init();
#endif #endif
...@@ -1186,9 +1165,6 @@ static int __init sa1100_pcmcia_init(void) ...@@ -1186,9 +1165,6 @@ static int __init sa1100_pcmcia_init(void)
#ifdef CONFIG_SA1100_TRIZEPS #ifdef CONFIG_SA1100_TRIZEPS
pcmcia_trizeps_init(); pcmcia_trizeps_init();
#endif #endif
#ifdef CONFIG_SA1100_XP860
pcmcia_xp860_init();
#endif
#ifdef CONFIG_SA1100_YOPY #ifdef CONFIG_SA1100_YOPY
pcmcia_yopy_init(); pcmcia_yopy_init();
#endif #endif
...@@ -1203,15 +1179,9 @@ static int __init sa1100_pcmcia_init(void) ...@@ -1203,15 +1179,9 @@ static int __init sa1100_pcmcia_init(void)
*/ */
static void __exit sa1100_pcmcia_exit(void) static void __exit sa1100_pcmcia_exit(void)
{ {
#ifdef CONFIG_SA1100_ADSBITSY
pcmcia_adsbitsy_exit();
#endif
#ifdef CONFIG_SA1100_ASSABET #ifdef CONFIG_SA1100_ASSABET
pcmcia_assabet_exit(); pcmcia_assabet_exit();
#endif #endif
#ifdef CONFIG_SA1100_BADGE4
pcmcia_badge4_exit();
#endif
#ifdef CONFIG_SA1100_CERF #ifdef CONFIG_SA1100_CERF
pcmcia_cerf_exit(); pcmcia_cerf_exit();
#endif #endif
...@@ -1224,21 +1194,9 @@ static void __exit sa1100_pcmcia_exit(void) ...@@ -1224,21 +1194,9 @@ static void __exit sa1100_pcmcia_exit(void)
#ifdef CONFIG_SA1100_GRAPHICSCLIENT #ifdef CONFIG_SA1100_GRAPHICSCLIENT
pcmcia_gcplus_exit(); pcmcia_gcplus_exit();
#endif #endif
#ifdef CONFIG_SA1100_GRAPHICSMASTER
pcmcia_graphicsmaster_exit();
#endif
#ifdef CONFIG_SA1100_JORNADA720
pcmcia_jornada720_exit();
#endif
#ifdef CONFIG_ASSABET_NEPONSET
pcmcia_neponset_exit();
#endif
#ifdef CONFIG_SA1100_PANGOLIN #ifdef CONFIG_SA1100_PANGOLIN
pcmcia_pangolin_exit(); pcmcia_pangolin_exit();
#endif #endif
#ifdef CONFIG_SA1100_PFS168
pcmcia_pfs_exit();
#endif
#ifdef CONFIG_SA1100_SHANNON #ifdef CONFIG_SA1100_SHANNON
pcmcia_shannon_exit(); pcmcia_shannon_exit();
#endif #endif
...@@ -1248,9 +1206,6 @@ static void __exit sa1100_pcmcia_exit(void) ...@@ -1248,9 +1206,6 @@ static void __exit sa1100_pcmcia_exit(void)
#ifdef CONFIG_SA1100_STORK #ifdef CONFIG_SA1100_STORK
pcmcia_stork_exit(); pcmcia_stork_exit();
#endif #endif
#ifdef CONFIG_SA1100_XP860
pcmcia_xp860_exit();
#endif
#ifdef CONFIG_SA1100_YOPY #ifdef CONFIG_SA1100_YOPY
pcmcia_yopy_exit(); pcmcia_yopy_exit();
#endif #endif
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
......
...@@ -10,21 +10,50 @@ ...@@ -10,21 +10,50 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/arch/assabet.h> #include <asm/mach-types.h>
#include <asm/arch/neponset.h>
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
#include "sa1111_generic.h" #include "sa1111_generic.h"
/*
* Neponset uses the Maxim MAX1600, with the following connections:
*
* MAX1600 Neponset
*
* A0VCC SA-1111 GPIO A<1>
* A1VCC SA-1111 GPIO A<0>
* A0VPP CPLD NCR A0VPP
* A1VPP CPLD NCR A1VPP
* B0VCC SA-1111 GPIO A<2>
* B1VCC SA-1111 GPIO A<3>
* B0VPP ground (slot B is CF)
* B1VPP ground (slot B is CF)
*
* VX VCC (5V)
* VY VCC3_3 (3.3V)
* 12INA 12V
* 12INB ground (slot B is CF)
*
* The MAX1600 CODE pin is tied to ground, placing the device in
* "Standard Intel code" mode. Refer to the Maxim data sheet for
* the corresponding truth table.
*/
static int neponset_pcmcia_init(struct pcmcia_init *init) static int neponset_pcmcia_init(struct pcmcia_init *init)
{ {
/* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
/* MAX1600 to standby mode: */
PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP); NCR_0 &= ~(NCR_A0VPP | NCR_A1VPP);
/*
* Set GPIO_A<3:0> to be outputs for the MAX1600,
* and switch to standby mode.
*/
PA_DDR = 0;
PA_SDR = 0;
PA_DWR = 0;
PA_SSR = 0;
return sa1111_pcmcia_init(init); return sa1111_pcmcia_init(init);
} }
...@@ -35,29 +64,6 @@ neponset_pcmcia_configure_socket(const struct pcmcia_configure *conf) ...@@ -35,29 +64,6 @@ neponset_pcmcia_configure_socket(const struct pcmcia_configure *conf)
unsigned int ncr_set, pa_dwr_set; unsigned int ncr_set, pa_dwr_set;
int ret; int ret;
/* Neponset uses the Maxim MAX1600, with the following connections:
* MAX1600 Neponset
*
* A0VCC SA-1111 GPIO A<1>
* A1VCC SA-1111 GPIO A<0>
* A0VPP CPLD NCR A0VPP
* A1VPP CPLD NCR A1VPP
* B0VCC SA-1111 GPIO A<2>
* B1VCC SA-1111 GPIO A<3>
* B0VPP ground (slot B is CF)
* B1VPP ground (slot B is CF)
*
* VX VCC (5V)
* VY VCC3_3 (3.3V)
* 12INA 12V
* 12INB ground (slot B is CF)
*
* The MAX1600 CODE pin is tied to ground, placing the device in
* "Standard Intel code" mode. Refer to the Maxim data sheet for
* the corresponding truth table.
*/
switch (conf->sock) { switch (conf->sock) {
case 0: case 0:
pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1; pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
...@@ -135,13 +141,13 @@ int __init pcmcia_neponset_init(void) ...@@ -135,13 +141,13 @@ int __init pcmcia_neponset_init(void)
{ {
int ret = -ENODEV; int ret = -ENODEV;
if (machine_is_assabet() && sa1111) if (machine_is_assabet())
ret = sa1100_register_pcmcia(&neponset_pcmcia_ops); ret = sa1100_register_pcmcia(&neponset_pcmcia_ops);
return ret; return ret;
} }
void __exit pcmcia_neponset_exit(void) void __devexit pcmcia_neponset_exit(void)
{ {
sa1100_unregister_pcmcia(&neponset_pcmcia_ops); sa1100_unregister_pcmcia(&neponset_pcmcia_ops);
} }
...@@ -7,10 +7,11 @@ ...@@ -7,10 +7,11 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/delay.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/irq.h> #include <asm/irq.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h>
#include <asm/irq.h> #include <asm/irq.h>
#include "sa1100_generic.h" #include "sa1100_generic.h"
......
...@@ -5,10 +5,12 @@ ...@@ -5,10 +5,12 @@
* basically means we handle everything except controlling the * basically means we handle everything except controlling the
* power. Power is machine specific... * power. Power is machine specific...
*/ */
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/hardware/sa1111.h> #include <asm/hardware/sa1111.h>
...@@ -21,19 +23,18 @@ static struct irqs { ...@@ -21,19 +23,18 @@ static struct irqs {
int irq; int irq;
const char *str; const char *str;
} irqs[] = { } irqs[] = {
{ S0_CD_VALID, "SA1111 PCMCIA card detect" }, { IRQ_S0_CD_VALID, "SA1111 PCMCIA card detect" },
{ S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" }, { IRQ_S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1" },
{ S1_CD_VALID, "SA1111 CF card detect" }, { IRQ_S1_CD_VALID, "SA1111 CF card detect" },
{ S1_BVD1_STSCHG, "SA1111 CF BVD1" }, { IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1" },
}; };
static struct sa1111_dev *pcmcia;
int sa1111_pcmcia_init(struct pcmcia_init *init) int sa1111_pcmcia_init(struct pcmcia_init *init)
{ {
int i, ret; int i, ret;
if (!request_mem_region(_PCCR, 512, "PCMCIA"))
return -1;
for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) { for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) {
set_irq_type(irqs[i].irq, IRQT_FALLING); set_irq_type(irqs[i].irq, IRQT_FALLING);
ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT, ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
...@@ -47,8 +48,6 @@ int sa1111_pcmcia_init(struct pcmcia_init *init) ...@@ -47,8 +48,6 @@ int sa1111_pcmcia_init(struct pcmcia_init *init)
irqs[i].irq, ret); irqs[i].irq, ret);
while (i--) while (i--)
free_irq(irqs[i].irq, NULL); free_irq(irqs[i].irq, NULL);
release_mem_region(_PCCR, 16);
} }
return ret ? -1 : 2; return ret ? -1 : 2;
...@@ -61,8 +60,6 @@ int sa1111_pcmcia_shutdown(void) ...@@ -61,8 +60,6 @@ int sa1111_pcmcia_shutdown(void)
for (i = 0; i < ARRAY_SIZE(irqs); i++) for (i = 0; i < ARRAY_SIZE(irqs); i++)
free_irq(irqs[i].irq, NULL); free_irq(irqs[i].irq, NULL);
release_mem_region(_PCCR, 512);
return 0; return 0;
} }
...@@ -73,7 +70,7 @@ int sa1111_pcmcia_socket_state(struct pcmcia_state_array *state) ...@@ -73,7 +70,7 @@ int sa1111_pcmcia_socket_state(struct pcmcia_state_array *state)
if (state->size < 2) if (state->size < 2)
return -1; return -1;
status = PCSR; status = sa1111_readl(pcmcia->mapbase + SA1111_PCSR);
state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1; state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
state->state[0].ready = status & PCSR_S0_READY ? 1 : 0; state->state[0].ready = status & PCSR_S0_READY ? 1 : 0;
...@@ -99,8 +96,8 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info) ...@@ -99,8 +96,8 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
int ret = 0; int ret = 0;
switch (info->sock) { switch (info->sock) {
case 0: info->irq = S0_READY_NINT; break; case 0: info->irq = IRQ_S0_READY_NINT; break;
case 1: info->irq = S1_READY_NINT; break; case 1: info->irq = IRQ_S1_READY_NINT; break;
default: ret = 1; default: ret = 1;
} }
...@@ -109,7 +106,7 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info) ...@@ -109,7 +106,7 @@ int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
{ {
unsigned int rst, flt, wait, pse, irq, pccr_mask; unsigned int rst, flt, wait, pse, irq, pccr_mask, val;
unsigned long flags; unsigned long flags;
switch (conf->sock) { switch (conf->sock) {
...@@ -118,7 +115,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) ...@@ -118,7 +115,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
flt = PCCR_S0_FLT; flt = PCCR_S0_FLT;
wait = PCCR_S0_PWAITEN; wait = PCCR_S0_PWAITEN;
pse = PCCR_S0_PSE; pse = PCCR_S0_PSE;
irq = S0_READY_NINT; irq = IRQ_S0_READY_NINT;
break; break;
case 1: case 1:
...@@ -126,7 +123,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) ...@@ -126,7 +123,7 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
flt = PCCR_S1_FLT; flt = PCCR_S1_FLT;
wait = PCCR_S1_PWAITEN; wait = PCCR_S1_PWAITEN;
pse = PCCR_S1_PSE; pse = PCCR_S1_PSE;
irq = S1_READY_NINT; irq = IRQ_S1_READY_NINT;
break; break;
default: default:
...@@ -159,7 +156,9 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf) ...@@ -159,7 +156,9 @@ int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
pccr_mask |= flt; pccr_mask |= flt;
local_irq_save(flags); local_irq_save(flags);
PCCR = (PCCR & ~(pse | flt | wait | rst)) | pccr_mask; val = sa1111_readl(pcmcia->mapbase + SA1111_PCCR);
val = (val & ~(pse | flt | wait | rst)) | pccr_mask;
sa1111_writel(val, pcmcia->mapbase + SA1111_PCCR);
local_irq_restore(flags); local_irq_restore(flags);
if (conf->irq) if (conf->irq)
...@@ -179,3 +178,130 @@ int sa1111_pcmcia_socket_suspend(int sock) ...@@ -179,3 +178,130 @@ int sa1111_pcmcia_socket_suspend(int sock)
{ {
return 0; return 0;
} }
static int pcmcia_probe(struct device *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
unsigned long flags;
char *base;
local_irq_save(flags);
if (pcmcia) {
local_irq_restore(flags);
return -EBUSY;
}
pcmcia = sadev;
local_irq_restore(flags);
if (!request_mem_region(sadev->res.start, 512,
SA1111_DRIVER_NAME(sadev)))
return -EBUSY;
base = sadev->mapbase;
/*
* Initialise the suspend state.
*/
sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + SA1111_PCSSR);
sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR);
#ifdef CONFIG_SA1100_ADSBITSY
pcmcia_adsbitsy_init();
#endif
#ifdef CONFIG_SA1100_BADGE4
pcmcia_badge4_init();
#endif
#ifdef CONFIG_SA1100_GRAPHICSMASTER
pcmcia_graphicsmaster_init();
#endif
#ifdef CONFIG_SA1100_JORNADA720
pcmcia_jornada720_init();
#endif
#ifdef CONFIG_ASSABET_NEPONSET
pcmcia_neponset_init();
#endif
#ifdef CONFIG_SA1100_PFS168
pcmcia_pfs_init();
#endif
#ifdef CONFIG_SA1100_PT_SYSTEM3
pcmcia_system3_init();
#endif
#ifdef CONFIG_SA1100_XP860
pcmcia_xp860_init();
#endif
return 0;
}
static int __devexit pcmcia_remove(struct device *dev)
{
struct sa1111_dev *sadev = SA1111_DEV(dev);
#ifdef CONFIG_SA1100_ADSBITSY
pcmcia_adsbitsy_exit();
#endif
#ifdef CONFIG_SA1100_BADGE4
pcmcia_badge4_exit();
#endif
#ifdef CONFIG_SA1100_GRAPHICSMASTER
pcmcia_graphicsmaster_exit();
#endif
#ifdef CONFIG_SA1100_JORNADA720
pcmcia_jornada720_exit();
#endif
#ifdef CONFIG_ASSABET_NEPONSET
pcmcia_neponset_exit();
#endif
#ifdef CONFIG_SA1100_PFS168
pcmcia_pfs_exit();
#endif
#ifdef CONFIG_SA1100_PT_SYSTEM3
pcmcia_system3_exit();
#endif
#ifdef CONFIG_SA1100_XP860
pcmcia_xp860_exit();
#endif
release_mem_region(sadev->res.start, 512);
pcmcia = NULL;
return 0;
}
static int pcmcia_suspend(struct device *dev, u32 state, u32 level)
{
return 0;
}
static int pcmcia_resume(struct device *dev, u32 level)
{
return 0;
}
static struct sa1111_driver pcmcia_driver = {
.drv = {
.name = "SA1111 PCMCIA",
.bus = &sa1111_bus_type,
.probe = pcmcia_probe,
.remove = __devexit_p(pcmcia_remove),
.suspend = pcmcia_suspend,
.resume = pcmcia_resume,
},
.devid = SA1111_DEVID_PCMCIA,
};
static int __init sa1111_drv_pcmcia_init(void)
{
return driver_register(&pcmcia_driver.drv);
}
static void __exit sa1111_drv_pcmcia_exit(void)
{
remove_driver(&pcmcia_driver.drv);
}
module_init(sa1111_drv_pcmcia_init);
module_exit(sa1111_drv_pcmcia_exit);
MODULE_DESCRIPTION("SA1111 PCMCIA card socket driver");
MODULE_LICENSE("GPL");
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static void sa1111_start_hc(void) static void sa1111_start_hc(struct sa1111_dev *dev)
{ {
unsigned int usb_rst = 0; unsigned int usb_rst = 0;
...@@ -48,31 +48,35 @@ static void sa1111_start_hc(void) ...@@ -48,31 +48,35 @@ static void sa1111_start_hc(void)
* Configure the power sense and control lines. Place the USB * Configure the power sense and control lines. Place the USB
* host controller in reset. * host controller in reset.
*/ */
USB_RESET = usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
dev->mapbase + SA1111_USB_RESET);
/* /*
* Now, carefully enable the USB clock, and take * Now, carefully enable the USB clock, and take
* the USB host controller out of reset. * the USB host controller out of reset.
*/ */
SKPCR |= SKPCR_UCLKEN; sa1111_enable_device(dev);
udelay(11); udelay(11);
USB_RESET = usb_rst; sa1111_writel(usb_rst, dev->mapbase + SA1111_USB_RESET);
} }
static void sa1111_stop_hc(void) static void sa1111_stop_hc(struct sa1111_dev *dev)
{ {
unsigned int usb_rst;
printk(KERN_DEBUG __FILE__ printk(KERN_DEBUG __FILE__
": stopping SA-1111 OHCI USB Controller\n"); ": stopping SA-1111 OHCI USB Controller\n");
/* /*
* Put the USB host controller into reset. * Put the USB host controller into reset.
*/ */
USB_RESET |= USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET; usb_rst = sa1111_readl(dev->mapbase + SA1111_USB_RESET);
sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
dev->mapbase + SA1111_USB_RESET);
/* /*
* Stop the USB clock. * Stop the USB clock.
*/ */
SKPCR &= ~SKPCR_UCLKEN; sa1111_disable_device(dev);
#ifdef CONFIG_SA1100_BADGE4 #ifdef CONFIG_SA1100_BADGE4
if (machine_is_badge4()) { if (machine_is_badge4()) {
...@@ -86,9 +90,9 @@ static void sa1111_stop_hc(void) ...@@ -86,9 +90,9 @@ static void sa1111_stop_hc(void)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#if 0 #if 0
static void dump_hci_status(const char *label) static void dump_hci_status(struct usb_hcd *hcd, const char *label)
{ {
unsigned long status = USB_STATUS; unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
dbg ("%s USB_STATUS = { %s%s%s%s%s}", label, dbg ("%s USB_STATUS = { %s%s%s%s%s}", label,
((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""), ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
...@@ -101,11 +105,14 @@ static void dump_hci_status(const char *label) ...@@ -101,11 +105,14 @@ static void dump_hci_status(const char *label)
static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
{ {
//dump_hci_status("irq"); struct usb_hcd *hcd = __hcd;
// unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
//dump_hci_status(hcd, "irq");
#if 0 #if 0
/* may work better this way -- need to investigate further */ /* may work better this way -- need to investigate further */
if (USB_STATUS & USB_STATUS_NIRQHCIM) { if (status & USB_STATUS_NIRQHCIM) {
//dbg ("not normal HC interrupt; ignoring"); //dbg ("not normal HC interrupt; ignoring");
return; return;
} }
...@@ -116,7 +123,7 @@ static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r) ...@@ -116,7 +123,7 @@ static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
void usb_hcd_sa1111_remove (struct usb_hcd *); void usb_hcd_sa1111_remove (struct usb_hcd *, struct sa1111_dev *);
/* configure so an HC device and id are always provided */ /* configure so an HC device and id are always provided */
/* always called with process context; sleeping is OK */ /* always called with process context; sleeping is OK */
...@@ -132,21 +139,20 @@ void usb_hcd_sa1111_remove (struct usb_hcd *); ...@@ -132,21 +139,20 @@ void usb_hcd_sa1111_remove (struct usb_hcd *);
* *
* Store this function in the HCD's struct pci_driver as probe(). * Store this function in the HCD's struct pci_driver as probe().
*/ */
int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_out) int usb_hcd_sa1111_probe (const struct hc_driver *driver,
struct usb_hcd **hcd_out,
struct sa1111_dev *dev)
{ {
int retval; int retval;
struct usb_hcd *hcd = 0; struct usb_hcd *hcd = 0;
if (!sa1111) if (!request_mem_region(dev->res.start,
return -ENODEV; dev->res.end - dev->res.start + 1, hcd_name)) {
if (!request_mem_region(_USB_OHCI_OP_BASE,
_USB_EXTENT, hcd_name)) {
dbg("request_mem_region failed"); dbg("request_mem_region failed");
return -EBUSY; return -EBUSY;
} }
sa1111_start_hc(); sa1111_start_hc(dev);
hcd = driver->hcd_alloc (); hcd = driver->hcd_alloc ();
if (hcd == NULL){ if (hcd == NULL){
...@@ -157,9 +163,10 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o ...@@ -157,9 +163,10 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
hcd->driver = (struct hc_driver *) driver; hcd->driver = (struct hc_driver *) driver;
hcd->description = driver->description; hcd->description = driver->description;
hcd->irq = NIRQHCIM; hcd->irq = dev->irq[1];
hcd->regs = (void *) &USB_OHCI_OP_BASE; hcd->regs = dev->mapbase;
hcd->pdev = SA1111_FAKE_PCIDEV; hcd->pdev = SA1111_FAKE_PCIDEV;
hcd->parent = &dev->dev;
retval = hcd_buffer_create (hcd); retval = hcd_buffer_create (hcd);
if (retval != 0) { if (retval != 0) {
...@@ -167,8 +174,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o ...@@ -167,8 +174,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
goto err1; goto err1;
} }
set_irq_type(NIRQHCIM, IRQT_RISING); set_irq_type(hcd->irq, IRQT_RISING);
retval = request_irq (NIRQHCIM, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT, retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
hcd->description, hcd); hcd->description, hcd);
if (retval != 0) { if (retval != 0) {
dbg("request_irq failed"); dbg("request_irq failed");
...@@ -191,7 +198,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o ...@@ -191,7 +198,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
if ((retval = driver->start (hcd)) < 0) if ((retval = driver->start (hcd)) < 0)
{ {
usb_hcd_sa1111_remove(hcd); usb_hcd_sa1111_remove(hcd, dev);
return retval; return retval;
} }
...@@ -202,8 +209,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o ...@@ -202,8 +209,8 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
hcd_buffer_destroy (hcd); hcd_buffer_destroy (hcd);
if (hcd) driver->hcd_free(hcd); if (hcd) driver->hcd_free(hcd);
err1: err1:
sa1111_stop_hc(); sa1111_stop_hc(dev);
release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
return retval; return retval;
} }
...@@ -221,7 +228,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o ...@@ -221,7 +228,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
* context, normally "rmmod", "apmd", or something similar. * context, normally "rmmod", "apmd", or something similar.
* *
*/ */
void usb_hcd_sa1111_remove (struct usb_hcd *hcd) void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
{ {
struct usb_device *hub; struct usb_device *hub;
void *base; void *base;
...@@ -244,13 +251,13 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd) ...@@ -244,13 +251,13 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd)
usb_deregister_bus (&hcd->self); usb_deregister_bus (&hcd->self);
if (atomic_read (&hcd->self.refcnt) != 1) if (atomic_read (&hcd->self.refcnt) != 1)
err (__FUNCTION__ ": %s, count != 1", hcd->self.bus_name); err ("%s: %s, count != 1", __FUNCTION__, hcd->self.bus_name);
base = hcd->regs; base = hcd->regs;
hcd->driver->hcd_free (hcd); hcd->driver->hcd_free (hcd);
sa1111_stop_hc(); sa1111_stop_hc(dev);
release_mem_region(_USB_OHCI_OP_BASE, _USB_EXTENT); release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -275,7 +282,7 @@ ohci_sa1111_start (struct usb_hcd *hcd) ...@@ -275,7 +282,7 @@ ohci_sa1111_start (struct usb_hcd *hcd)
} }
ohci->regs = hcd->regs; ohci->regs = hcd->regs;
ohci->parent_dev = &sa1111->dev; ohci->parent_dev = hcd->parent;
if (hc_reset (ohci) < 0) { if (hc_reset (ohci) < 0) {
ohci_stop (hcd); ohci_stop (hcd);
...@@ -342,26 +349,67 @@ static const struct hc_driver ohci_sa1111_hc_driver = { ...@@ -342,26 +349,67 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* Only one SA-1111 ever exists. */ static int ohci_hcd_sa1111_drv_probe(struct device *_dev)
static struct usb_hcd *the_sa1111_hcd; {
struct sa1111_dev *dev = SA1111_DEV(_dev);
struct usb_hcd *hcd = NULL;
int ret;
ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &hcd, dev);
if (ret == 0)
dev->dev.driver_data = hcd;
return ret;
}
static int ohci_hcd_sa1111_drv_remove(struct device *_dev)
{
struct sa1111_dev *dev = SA1111_DEV(_dev);
struct usb_hcd *hcd = dev->dev.driver_data;
usb_hcd_sa1111_remove(hcd, dev);
dev->dev.driver_data = NULL;
static int __init ohci_hcd_sa1111_init (void) return 0;
}
static int ohci_hcd_sa1111_drv_suspend(struct device *dev, u32 state, u32 level)
{
return 0;
}
static int ohci_hcd_sa1111_drv_resume(struct device *dev, u32 level)
{
return 0;
}
static struct sa1111_driver ohci_hcd_sa1111_driver = {
.drv = {
.name = "SA1111 OHCI",
.bus = &sa1111_bus_type,
.probe = ohci_hcd_sa1111_drv_probe,
.remove = ohci_hcd_sa1111_drv_remove,
.suspend = ohci_hcd_sa1111_drv_suspend,
.resume = ohci_hcd_sa1111_drv_resume,
},
.devid = SA1111_DEVID_USB,
};
static int __init ohci_hcd_sa1111_init (void)
{ {
dbg (DRIVER_INFO " (SA-1111)"); dbg (DRIVER_INFO " (SA-1111)");
dbg ("block sizes: ed %d td %d", dbg ("block sizes: ed %d td %d",
sizeof (struct ed), sizeof (struct td)); sizeof (struct ed), sizeof (struct td));
the_sa1111_hcd = 0; return driver_register(&ohci_hcd_sa1111_driver.drv);
return usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &the_sa1111_hcd);
} }
module_init (ohci_hcd_sa1111_init);
static void __exit ohci_hcd_sa1111_cleanup (void)
static void __exit ohci_hcd_sa1111_cleanup (void) {
{ remove_driver(&ohci_hcd_sa1111_driver.drv);
if (the_sa1111_hcd) {
usb_hcd_sa1111_remove(the_sa1111_hcd);
the_sa1111_hcd = 0;
}
} }
module_init (ohci_hcd_sa1111_init);
module_exit (ohci_hcd_sa1111_cleanup); module_exit (ohci_hcd_sa1111_cleanup);
...@@ -64,18 +64,10 @@ ...@@ -64,18 +64,10 @@
#define SA1111_SMCR 0x0004 #define SA1111_SMCR 0x0004
#define SA1111_SKID 0x0008 #define SA1111_SKID 0x0008
#define _SBI_SKCR _SA1111(SA1111_SKCR)
#define _SBI_SMCR _SA1111(SA1111_SMCR)
#define _SBI_SKID _SA1111(SA1111_SKID)
#if LANGUAGE == C
#define SBI_SKCR __CCREG(SA1111_SKCR) #define SBI_SKCR __CCREG(SA1111_SKCR)
#define SBI_SMCR __CCREG(SA1111_SMCR) #define SBI_SMCR __CCREG(SA1111_SMCR)
#define SBI_SKID __CCREG(SA1111_SKID) #define SBI_SKID __CCREG(SA1111_SKID)
#endif /* LANGUAGE == C */
#define SKCR_PLL_BYPASS (1<<0) #define SKCR_PLL_BYPASS (1<<0)
#define SKCR_RCLKEN (1<<1) #define SKCR_RCLKEN (1<<1)
#define SKCR_SLEEP (1<<2) #define SKCR_SLEEP (1<<2)
...@@ -135,22 +127,10 @@ ...@@ -135,22 +127,10 @@
#define SA1111_SKPMC 0x020c #define SA1111_SKPMC 0x020c
#define SA1111_SKPTC 0x0210 #define SA1111_SKPTC 0x0210
#define SA1111_SKPEN0 0x0214 #define SA1111_SKPEN0 0x0214
#define SA1111_SKPWN0 0x0218 #define SA1111_SKPWM0 0x0218
#define SA1111_SKPEN1 0x021c #define SA1111_SKPEN1 0x021c
#define SA1111_SKPWM1 0x0220 #define SA1111_SKPWM1 0x0220
#define _SKPCR _SA1111(SA1111_SKPCR)
#define _SKCDR _SA1111(SA1111_SKCDR)
#define _SKAUD _SA1111(SA1111_SKAUD)
#define _SKPMC _SA1111(SA1111_SKPMC)
#define _SKPTC _SA1111(SA1111_SKPTC)
#define _SKPEN0 _SA1111(SA1111_SKPEN0)
#define _SKPWM0 _SA1111(SA1111_SKPWM0)
#define _SKPEN1 _SA1111(SA1111_SKPEN1)
#define _SKPWM1 _SA1111(SA1111_SKPWM1)
#if LANGUAGE == C
#define SKPCR __CCREG(SA1111_SKPCR) #define SKPCR __CCREG(SA1111_SKPCR)
#define SKCDR __CCREG(SA1111_SKCDR) #define SKCDR __CCREG(SA1111_SKCDR)
#define SKAUD __CCREG(SA1111_SKAUD) #define SKAUD __CCREG(SA1111_SKAUD)
...@@ -161,8 +141,6 @@ ...@@ -161,8 +141,6 @@
#define SKPEN1 __CCREG(SA1111_SKPEN1) #define SKPEN1 __CCREG(SA1111_SKPEN1)
#define SKPWM1 __CCREG(SA1111_SKPWM1) #define SKPWM1 __CCREG(SA1111_SKPWM1)
#endif /* LANGUAGE == C */
#define SKPCR_UCLKEN (1<<0) #define SKPCR_UCLKEN (1<<0)
#define SKPCR_ACCLKEN (1<<1) #define SKPCR_ACCLKEN (1<<1)
#define SKPCR_I2SCLKEN (1<<2) #define SKPCR_I2SCLKEN (1<<2)
...@@ -176,21 +154,14 @@ ...@@ -176,21 +154,14 @@
/* /*
* USB Host controller * USB Host controller
*/ */
#define _USB_OHCI_OP_BASE _SA1111( 0x400 ) #define SA1111_USB 0x0400
#define _USB_STATUS _SA1111( 0x518 )
#define _USB_RESET _SA1111( 0x51c )
#define _USB_INTERRUPTEST _SA1111( 0x520 )
#define _USB_EXTENT (_USB_INTERRUPTEST - _USB_OHCI_OP_BASE + 4)
#if LANGUAGE == C /*
* Offsets from SA1111_USB_BASE
#define USB_OHCI_OP_BASE __CCREG(0x0400) */
#define USB_STATUS __CCREG(0x0518) #define SA1111_USB_STATUS 0x0118
#define USB_RESET __CCREG(0x051c) #define SA1111_USB_RESET 0x011c
#define USB_INTERRUPTEST __CCReG(0x0520) #define SA1111_USB_IRQTEST 0x0120
#endif /* LANGUAGE == C */
#define USB_RESET_FORCEIFRESET (1 << 0) #define USB_RESET_FORCEIFRESET (1 << 0)
#define USB_RESET_FORCEHCRESET (1 << 1) #define USB_RESET_FORCEHCRESET (1 << 1)
...@@ -451,82 +422,56 @@ ...@@ -451,82 +422,56 @@
* WAKE_POL0 Wake-up polarity selection 0 * WAKE_POL0 Wake-up polarity selection 0
* WAKE_POL1 Wake-up polarity selection 1 * WAKE_POL1 Wake-up polarity selection 1
*/ */
#define SA1111_INTC 0x1600
#define SA1111_INTTEST0 0x1600 /*
#define SA1111_INTTEST1 0x1604 * These are offsets from the above base.
#define SA1111_INTEN0 0x1608 */
#define SA1111_INTEN1 0x160c #define SA1111_INTTEST0 0x0000
#define SA1111_INTPOL0 0x1610 #define SA1111_INTTEST1 0x0004
#define SA1111_INTPOL1 0x1614 #define SA1111_INTEN0 0x0008
#define SA1111_INTTSTSEL 0x1618 #define SA1111_INTEN1 0x000c
#define SA1111_INTSTATCLR0 0x161c #define SA1111_INTPOL0 0x0010
#define SA1111_INTSTATCLR1 0x1620 #define SA1111_INTPOL1 0x0014
#define SA1111_INTSET0 0x1624 #define SA1111_INTTSTSEL 0x0018
#define SA1111_INTSET1 0x1628 #define SA1111_INTSTATCLR0 0x001c
#define SA1111_WAKE_EN0 0x162c #define SA1111_INTSTATCLR1 0x0020
#define SA1111_WAKE_EN1 0x1630 #define SA1111_INTSET0 0x0024
#define SA1111_WAKE_POL0 0x1634 #define SA1111_INTSET1 0x0028
#define SA1111_WAKE_POL1 0x1638 #define SA1111_WAKEEN0 0x002c
#define SA1111_WAKEEN1 0x0030
#define _INTTEST0 _SA1111(SA1111_INTTEST0) #define SA1111_WAKEPOL0 0x0034
#define _INTTEST1 _SA1111(SA1111_INTTEST1) #define SA1111_WAKEPOL1 0x0038
#define _INTEN0 _SA1111(SA1111_INTEN0)
#define _INTEN1 _SA1111(SA1111_INTEN1) #define INTTEST0 __CCREG(SA1111_INTC + SA1111_INTTEST0)
#define _INTPOL0 _SA1111(SA1111_INTPOL0) #define INTTEST1 __CCREG(SA1111_INTC + SA1111_INTTEST1)
#define _INTPOL1 _SA1111(SA1111_INTPOL1) #define INTEN0 __CCREG(SA1111_INTC + SA1111_INTEN0)
#define _INTTSTSEL _SA1111(SA1111_INTTSTSEL) #define INTEN1 __CCREG(SA1111_INTC + SA1111_INTEN1)
#define _INTSTATCLR0 _SA1111(SA1111_INTSTATCLR0) #define INTPOL0 __CCREG(SA1111_INTC + SA1111_INTPOL0)
#define _INTSTATCLR1 _SA1111(SA1111_INTSTATCLR1) #define INTPOL1 __CCREG(SA1111_INTC + SA1111_INTPOL1)
#define _INTSET0 _SA1111(SA1111_INTSET0) #define INTTSTSEL __CCREG(SA1111_INTC + SA1111_INTTSTSEL)
#define _INTSET1 _SA1111(SA1111_INTSET1) #define INTSTATCLR0 __CCREG(SA1111_INTC + SA1111_INTSTATCLR0)
#define _WAKE_EN0 _SA1111(SA1111_WAKE_EN0) #define INTSTATCLR1 __CCREG(SA1111_INTC + SA1111_INTSTATCLR1)
#define _WAKE_EN1 _SA1111(SA1111_WAKE_EN1) #define INTSET0 __CCREG(SA1111_INTC + SA1111_INTSET0)
#define _WAKE_POL0 _SA1111(SA1111_WAKE_POL0) #define INTSET1 __CCREG(SA1111_INTC + SA1111_INTSET1)
#define _WAKE_POL1 _SA1111(SA1111_WAKE_POL1) #define WAKE_EN0 __CCREG(SA1111_INTC + SA1111_WAKEEN0)
#define WAKE_EN1 __CCREG(SA1111_INTC + SA1111_WAKEEN1)
#if LANGUAGE == C #define WAKE_POL0 __CCREG(SA1111_INTC + SA1111_WAKEPOL0)
#define WAKE_POL1 __CCREG(SA1111_INTC + SA1111_WAKEPOL1)
#define INTTEST0 __CCREG(SA1111_INTTEST0)
#define INTTEST1 __CCREG(SA1111_INTTEST1)
#define INTEN0 __CCREG(SA1111_INTEN0)
#define INTEN1 __CCREG(SA1111_INTEN1)
#define INTPOL0 __CCREG(SA1111_INTPOL0)
#define INTPOL1 __CCREG(SA1111_INTPOL1)
#define INTTSTSEL __CCREG(SA1111_INTTSTSEL)
#define INTSTATCLR0 __CCREG(SA1111_INTSTATCLR0)
#define INTSTATCLR1 __CCREG(SA1111_INTSTATCLR1)
#define INTSET0 __CCREG(SA1111_INTSET0)
#define INTSET1 __CCREG(SA1111_INTSET1)
#define WAKE_EN0 __CCREG(SA1111_WAKE_EN0)
#define WAKE_EN1 __CCREG(SA1111_WAKE_EN1)
#define WAKE_POL0 __CCREG(SA1111_WAKE_POL0)
#define WAKE_POL1 __CCREG(SA1111_WAKE_POL1)
#endif /* LANGUAGE == C */
/* /*
* PS/2 Trackpad and Mouse Interfaces * PS/2 Trackpad and Mouse Interfaces
* *
* Registers (prefix kbd applies to trackpad interface, mse to mouse) * Registers
* KBDCR Control Register * PS2CR Control Register
* KBDSTAT Status Register * PS2STAT Status Register
* KBDDATA Transmit/Receive Data register * PS2DATA Transmit/Receive Data register
* KBDCLKDIV Clock Division Register * PS2CLKDIV Clock Division Register
* KBDPRECNT Clock Precount Register * PS2PRECNT Clock Precount Register
* KBDTEST1 Test register 1 * PS2TEST1 Test register 1
* KBDTEST2 Test register 2 * PS2TEST2 Test register 2
* KBDTEST3 Test register 3 * PS2TEST3 Test register 3
* KBDTEST4 Test register 4 * PS2TEST4 Test register 4
* MSECR
* MSESTAT
* MSEDATA
* MSECLKDIV
* MSEPRECNT
* MSETEST1
* MSETEST2
* MSETEST3
* MSETEST4
*
*/ */
#define SA1111_KBD 0x0a00 #define SA1111_KBD 0x0a00
...@@ -564,17 +509,14 @@ ...@@ -564,17 +509,14 @@
* PCSSR Sleep State Register * PCSSR Sleep State Register
*/ */
#define _PCCR _SA1111( 0x1800 ) #define SA1111_PCMCIA 0x1600
#define _PCSSR _SA1111( 0x1804 )
#define _PCSR _SA1111( 0x1808 )
#if LANGUAGE == C
#define PCCR __CCREG(0x1800)
#define PCSSR __CCREG(0x1804)
#define PCSR __CCREG(0x1808)
#endif /* LANGUAGE == C */ /*
* These are offsets from the above base.
*/
#define SA1111_PCCR 0x0000
#define SA1111_PCSSR 0x0004
#define SA1111_PCSR 0x0008
#define PCSR_S0_READY (1<<0) #define PCSR_S0_READY (1<<0)
#define PCSR_S1_READY (1<<1) #define PCSR_S1_READY (1<<1)
...@@ -603,21 +545,56 @@ ...@@ -603,21 +545,56 @@
#define PCSSR_S0_SLEEP (1<<0) #define PCSSR_S0_SLEEP (1<<0)
#define PCSSR_S1_SLEEP (1<<1) #define PCSSR_S1_SLEEP (1<<1)
struct sa1111_device {
extern struct bus_type sa1111_bus_type;
#define SA1111_DEVID_SBI 0
#define SA1111_DEVID_SK 1
#define SA1111_DEVID_USB 2
#define SA1111_DEVID_SAC 3
#define SA1111_DEVID_SSP 4
#define SA1111_DEVID_PS2 5
#define SA1111_DEVID_GPIO 6
#define SA1111_DEVID_INT 7
#define SA1111_DEVID_PCMCIA 8
struct sa1111_dev {
struct device dev; struct device dev;
struct resource resource; unsigned int devid;
void *base; struct resource res;
void *mapbase;
unsigned int skpcr_mask;
unsigned int irq[6];
}; };
extern struct sa1111_device *sa1111; #define SA1111_DEV(_d) container_of((_d), struct sa1111_dev, dev)
int sa1111_check_dma_bug(dma_addr_t addr); struct sa1111_driver {
struct device_driver drv;
unsigned int devid;
};
#define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv)
#define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name)
/* /*
* These frob the SKPCR register. * These frob the SKPCR register.
*/ */
void sa1111_enable_device(unsigned int mask); void sa1111_enable_device(struct sa1111_dev *);
void sa1111_disable_device(unsigned int mask); void sa1111_disable_device(struct sa1111_dev *);
unsigned int sa1111_pll_clock(struct sa1111_dev *);
#define SA1111_AUDIO_ACLINK 0
#define SA1111_AUDIO_I2S 1
void sa1111_select_audio_mode(struct sa1111_dev *sadev, int mode);
int sa1111_set_audio_rate(struct sa1111_dev *sadev, int rate);
int sa1111_get_audio_rate(struct sa1111_dev *sadev);
int sa1111_check_dma_bug(dma_addr_t addr);
#endif /* _ASM_ARCH_SA1111 */ #endif /* _ASM_ARCH_SA1111 */
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