mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
Merge branch 'sa1111' into sa11x0
Conflicts: arch/arm/common/sa1111.c arch/arm/mach-sa1100/neponset.c Fixed: arch/arm/mach-sa1100/assabet.c for the neponset changes
This commit is contained in:
commit
374da9da22
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
@ -28,9 +29,8 @@
|
|||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
|
||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <asm/mach-types.h>
|
|
||||||
#include <asm/irq.h>
|
|
||||||
#include <asm/mach/irq.h>
|
#include <asm/mach/irq.h>
|
||||||
|
#include <asm/mach-types.h>
|
||||||
#include <asm/sizes.h>
|
#include <asm/sizes.h>
|
||||||
|
|
||||||
#include <asm/hardware/sa1111.h>
|
#include <asm/hardware/sa1111.h>
|
||||||
@ -86,8 +86,10 @@
|
|||||||
#define IRQ_S1_CD_VALID (52)
|
#define IRQ_S1_CD_VALID (52)
|
||||||
#define IRQ_S0_BVD1_STSCHG (53)
|
#define IRQ_S0_BVD1_STSCHG (53)
|
||||||
#define IRQ_S1_BVD1_STSCHG (54)
|
#define IRQ_S1_BVD1_STSCHG (54)
|
||||||
|
#define SA1111_IRQ_NR (55)
|
||||||
|
|
||||||
extern void sa1110_mb_enable(void);
|
extern void sa1110_mb_enable(void);
|
||||||
|
extern void sa1110_mb_disable(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We keep the following data for the overall SA1111. Note that the
|
* We keep the following data for the overall SA1111. Note that the
|
||||||
@ -104,6 +106,7 @@ struct sa1111 {
|
|||||||
int irq_base; /* base for cascaded on-chip IRQs */
|
int irq_base; /* base for cascaded on-chip IRQs */
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
struct sa1111_platform_data *pdata;
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
void *saved_state;
|
void *saved_state;
|
||||||
#endif
|
#endif
|
||||||
@ -118,6 +121,7 @@ static struct sa1111 *g_sa1111;
|
|||||||
struct sa1111_dev_info {
|
struct sa1111_dev_info {
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
unsigned long skpcr_mask;
|
unsigned long skpcr_mask;
|
||||||
|
bool dma;
|
||||||
unsigned int devid;
|
unsigned int devid;
|
||||||
unsigned int irq[6];
|
unsigned int irq[6];
|
||||||
};
|
};
|
||||||
@ -126,6 +130,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
|||||||
{
|
{
|
||||||
.offset = SA1111_USB,
|
.offset = SA1111_USB,
|
||||||
.skpcr_mask = SKPCR_UCLKEN,
|
.skpcr_mask = SKPCR_UCLKEN,
|
||||||
|
.dma = true,
|
||||||
.devid = SA1111_DEVID_USB,
|
.devid = SA1111_DEVID_USB,
|
||||||
.irq = {
|
.irq = {
|
||||||
IRQ_USBPWR,
|
IRQ_USBPWR,
|
||||||
@ -139,6 +144,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
|||||||
{
|
{
|
||||||
.offset = 0x0600,
|
.offset = 0x0600,
|
||||||
.skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
|
.skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
|
||||||
|
.dma = true,
|
||||||
.devid = SA1111_DEVID_SAC,
|
.devid = SA1111_DEVID_SAC,
|
||||||
.irq = {
|
.irq = {
|
||||||
AUDXMTDMADONEA,
|
AUDXMTDMADONEA,
|
||||||
@ -155,7 +161,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
|||||||
{
|
{
|
||||||
.offset = SA1111_KBD,
|
.offset = SA1111_KBD,
|
||||||
.skpcr_mask = SKPCR_PTCLKEN,
|
.skpcr_mask = SKPCR_PTCLKEN,
|
||||||
.devid = SA1111_DEVID_PS2,
|
.devid = SA1111_DEVID_PS2_KBD,
|
||||||
.irq = {
|
.irq = {
|
||||||
IRQ_TPRXINT,
|
IRQ_TPRXINT,
|
||||||
IRQ_TPTXINT
|
IRQ_TPTXINT
|
||||||
@ -164,7 +170,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
|||||||
{
|
{
|
||||||
.offset = SA1111_MSE,
|
.offset = SA1111_MSE,
|
||||||
.skpcr_mask = SKPCR_PMCLKEN,
|
.skpcr_mask = SKPCR_PMCLKEN,
|
||||||
.devid = SA1111_DEVID_PS2,
|
.devid = SA1111_DEVID_PS2_MSE,
|
||||||
.irq = {
|
.irq = {
|
||||||
IRQ_MSRXINT,
|
IRQ_MSRXINT,
|
||||||
IRQ_MSTXINT
|
IRQ_MSTXINT
|
||||||
@ -434,16 +440,28 @@ static struct irq_chip sa1111_high_chip = {
|
|||||||
.irq_set_wake = sa1111_wake_highirq,
|
.irq_set_wake = sa1111_wake_highirq,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void sa1111_setup_irq(struct sa1111 *sachip)
|
static int sa1111_setup_irq(struct sa1111 *sachip, unsigned irq_base)
|
||||||
{
|
{
|
||||||
void __iomem *irqbase = sachip->base + SA1111_INTC;
|
void __iomem *irqbase = sachip->base + SA1111_INTC;
|
||||||
unsigned int irq;
|
unsigned i, irq;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We're guaranteed that this region hasn't been taken.
|
* We're guaranteed that this region hasn't been taken.
|
||||||
*/
|
*/
|
||||||
request_mem_region(sachip->phys + SA1111_INTC, 512, "irq");
|
request_mem_region(sachip->phys + SA1111_INTC, 512, "irq");
|
||||||
|
|
||||||
|
ret = irq_alloc_descs(-1, irq_base, SA1111_IRQ_NR, -1);
|
||||||
|
if (ret <= 0) {
|
||||||
|
dev_err(sachip->dev, "unable to allocate %u irqs: %d\n",
|
||||||
|
SA1111_IRQ_NR, ret);
|
||||||
|
if (ret == 0)
|
||||||
|
ret = -EINVAL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sachip->irq_base = ret;
|
||||||
|
|
||||||
/* disable all IRQs */
|
/* disable all IRQs */
|
||||||
sa1111_writel(0, irqbase + SA1111_INTEN0);
|
sa1111_writel(0, irqbase + SA1111_INTEN0);
|
||||||
sa1111_writel(0, irqbase + SA1111_INTEN1);
|
sa1111_writel(0, irqbase + SA1111_INTEN1);
|
||||||
@ -463,14 +481,16 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
|
|||||||
sa1111_writel(~0, irqbase + SA1111_INTSTATCLR0);
|
sa1111_writel(~0, irqbase + SA1111_INTSTATCLR0);
|
||||||
sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1);
|
sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1);
|
||||||
|
|
||||||
for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
|
for (i = IRQ_GPAIN0; i <= SSPROR; i++) {
|
||||||
|
irq = sachip->irq_base + i;
|
||||||
irq_set_chip_and_handler(irq, &sa1111_low_chip,
|
irq_set_chip_and_handler(irq, &sa1111_low_chip,
|
||||||
handle_edge_irq);
|
handle_edge_irq);
|
||||||
irq_set_chip_data(irq, sachip);
|
irq_set_chip_data(irq, sachip);
|
||||||
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
|
for (i = AUDXMTDMADONEA; i <= IRQ_S1_BVD1_STSCHG; i++) {
|
||||||
|
irq = sachip->irq_base + i;
|
||||||
irq_set_chip_and_handler(irq, &sa1111_high_chip,
|
irq_set_chip_and_handler(irq, &sa1111_high_chip,
|
||||||
handle_edge_irq);
|
handle_edge_irq);
|
||||||
irq_set_chip_data(irq, sachip);
|
irq_set_chip_data(irq, sachip);
|
||||||
@ -483,6 +503,11 @@ static void sa1111_setup_irq(struct sa1111 *sachip)
|
|||||||
irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
|
irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
|
||||||
irq_set_handler_data(sachip->irq, sachip);
|
irq_set_handler_data(sachip->irq, sachip);
|
||||||
irq_set_chained_handler(sachip->irq, sa1111_irq_handler);
|
irq_set_chained_handler(sachip->irq, sa1111_irq_handler);
|
||||||
|
|
||||||
|
dev_info(sachip->dev, "Providing IRQ%u-%u\n",
|
||||||
|
sachip->irq_base, sachip->irq_base + SA1111_IRQ_NR - 1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -581,41 +606,10 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_DMABOUNCE
|
|
||||||
/*
|
|
||||||
* According to the "Intel StrongARM SA-1111 Microprocessor Companion
|
|
||||||
* Chip Specification Update" (June 2000), erratum #7, there is a
|
|
||||||
* significant bug in the SA1111 SDRAM shared memory controller. If
|
|
||||||
* 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
|
|
||||||
* on the configuration of the RAM, bit 10 may correspond to one
|
|
||||||
* of several different (processor-relative) address bits.
|
|
||||||
*
|
|
||||||
* This routine only identifies whether or not a given DMA address
|
|
||||||
* is susceptible to the bug.
|
|
||||||
*
|
|
||||||
* This should only get called for sa1111_device types due to the
|
|
||||||
* way we configure our device dma_masks.
|
|
||||||
*/
|
|
||||||
static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
|
|
||||||
* User's Guide" mentions that jumpers R51 and R52 control the
|
|
||||||
* target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
|
|
||||||
* SDRAM bank 1 on Neponset). The default configuration selects
|
|
||||||
* Assabet, so any address in bank 1 is necessarily invalid.
|
|
||||||
*/
|
|
||||||
return (machine_is_assabet() || machine_is_pfs168()) &&
|
|
||||||
(addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void sa1111_dev_release(struct device *_dev)
|
static void sa1111_dev_release(struct device *_dev)
|
||||||
{
|
{
|
||||||
struct sa1111_dev *dev = SA1111_DEV(_dev);
|
struct sa1111_dev *dev = SA1111_DEV(_dev);
|
||||||
|
|
||||||
release_resource(&dev->res);
|
|
||||||
kfree(dev);
|
kfree(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,67 +618,58 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
|
|||||||
struct sa1111_dev_info *info)
|
struct sa1111_dev_info *info)
|
||||||
{
|
{
|
||||||
struct sa1111_dev *dev;
|
struct sa1111_dev *dev;
|
||||||
|
unsigned i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
|
dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
|
||||||
if (!dev) {
|
if (!dev) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out;
|
goto err_alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device_initialize(&dev->dev);
|
||||||
dev_set_name(&dev->dev, "%4.4lx", info->offset);
|
dev_set_name(&dev->dev, "%4.4lx", info->offset);
|
||||||
dev->devid = info->devid;
|
dev->devid = info->devid;
|
||||||
dev->dev.parent = sachip->dev;
|
dev->dev.parent = sachip->dev;
|
||||||
dev->dev.bus = &sa1111_bus_type;
|
dev->dev.bus = &sa1111_bus_type;
|
||||||
dev->dev.release = sa1111_dev_release;
|
dev->dev.release = sa1111_dev_release;
|
||||||
dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
|
|
||||||
dev->res.start = sachip->phys + info->offset;
|
dev->res.start = sachip->phys + info->offset;
|
||||||
dev->res.end = dev->res.start + 511;
|
dev->res.end = dev->res.start + 511;
|
||||||
dev->res.name = dev_name(&dev->dev);
|
dev->res.name = dev_name(&dev->dev);
|
||||||
dev->res.flags = IORESOURCE_MEM;
|
dev->res.flags = IORESOURCE_MEM;
|
||||||
dev->mapbase = sachip->base + info->offset;
|
dev->mapbase = sachip->base + info->offset;
|
||||||
dev->skpcr_mask = info->skpcr_mask;
|
dev->skpcr_mask = info->skpcr_mask;
|
||||||
memmove(dev->irq, info->irq, sizeof(dev->irq));
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(info->irq); i++)
|
||||||
|
dev->irq[i] = sachip->irq_base + info->irq[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the parent device has a DMA mask associated with it, and
|
||||||
|
* this child supports DMA, propagate it down to the children.
|
||||||
|
*/
|
||||||
|
if (info->dma && sachip->dev->dma_mask) {
|
||||||
|
dev->dma_mask = *sachip->dev->dma_mask;
|
||||||
|
dev->dev.dma_mask = &dev->dma_mask;
|
||||||
|
dev->dev.coherent_dma_mask = sachip->dev->coherent_dma_mask;
|
||||||
|
}
|
||||||
|
|
||||||
ret = request_resource(parent, &dev->res);
|
ret = request_resource(parent, &dev->res);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk("SA1111: failed to allocate resource for %s\n",
|
dev_err(sachip->dev, "failed to allocate resource for %s\n",
|
||||||
dev->res.name);
|
dev->res.name);
|
||||||
dev_set_name(&dev->dev, NULL);
|
goto err_resource;
|
||||||
kfree(dev);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = device_add(&dev->dev);
|
||||||
|
if (ret)
|
||||||
|
goto err_add;
|
||||||
|
return 0;
|
||||||
|
|
||||||
ret = device_register(&dev->dev);
|
err_add:
|
||||||
if (ret) {
|
release_resource(&dev->res);
|
||||||
release_resource(&dev->res);
|
err_resource:
|
||||||
kfree(dev);
|
put_device(&dev->dev);
|
||||||
goto out;
|
err_alloc:
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_DMABOUNCE
|
|
||||||
/*
|
|
||||||
* If the parent device has a DMA mask associated with it,
|
|
||||||
* propagate it down to the children.
|
|
||||||
*/
|
|
||||||
if (sachip->dev->dma_mask) {
|
|
||||||
dev->dma_mask = *sachip->dev->dma_mask;
|
|
||||||
dev->dev.dma_mask = &dev->dma_mask;
|
|
||||||
|
|
||||||
if (dev->dma_mask != 0xffffffffUL) {
|
|
||||||
ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
|
|
||||||
sa1111_needs_bounce);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(&dev->dev, "SA1111: Failed to register"
|
|
||||||
" with dmabounce\n");
|
|
||||||
device_unregister(&dev->dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,16 +683,21 @@ out:
|
|||||||
* Returns:
|
* Returns:
|
||||||
* %-ENODEV device not found.
|
* %-ENODEV device not found.
|
||||||
* %-EBUSY physical address already marked in-use.
|
* %-EBUSY physical address already marked in-use.
|
||||||
|
* %-EINVAL no platform data passed
|
||||||
* %0 successful.
|
* %0 successful.
|
||||||
*/
|
*/
|
||||||
static int __devinit
|
static int __devinit
|
||||||
__sa1111_probe(struct device *me, struct resource *mem, int irq)
|
__sa1111_probe(struct device *me, struct resource *mem, int irq)
|
||||||
{
|
{
|
||||||
|
struct sa1111_platform_data *pd = me->platform_data;
|
||||||
struct sa1111 *sachip;
|
struct sa1111 *sachip;
|
||||||
unsigned long id;
|
unsigned long id;
|
||||||
unsigned int has_devs;
|
unsigned int has_devs;
|
||||||
int i, ret = -ENODEV;
|
int i, ret = -ENODEV;
|
||||||
|
|
||||||
|
if (!pd)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
|
sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
|
||||||
if (!sachip)
|
if (!sachip)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -727,6 +717,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
|||||||
sachip->dev = me;
|
sachip->dev = me;
|
||||||
dev_set_drvdata(sachip->dev, sachip);
|
dev_set_drvdata(sachip->dev, sachip);
|
||||||
|
|
||||||
|
sachip->pdata = pd;
|
||||||
sachip->phys = mem->start;
|
sachip->phys = mem->start;
|
||||||
sachip->irq = irq;
|
sachip->irq = irq;
|
||||||
|
|
||||||
@ -759,6 +750,16 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
|||||||
*/
|
*/
|
||||||
sa1111_wake(sachip);
|
sa1111_wake(sachip);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The interrupt controller must be initialised before any
|
||||||
|
* other device to ensure that the interrupts are available.
|
||||||
|
*/
|
||||||
|
if (sachip->irq != NO_IRQ) {
|
||||||
|
ret = sa1111_setup_irq(sachip, pd->irq_base);
|
||||||
|
if (ret)
|
||||||
|
goto err_unmap;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_SA1100
|
#ifdef CONFIG_ARCH_SA1100
|
||||||
{
|
{
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
@ -789,24 +790,14 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* The interrupt controller must be initialised before any
|
|
||||||
* other device to ensure that the interrupts are available.
|
|
||||||
*/
|
|
||||||
if (sachip->irq != NO_IRQ)
|
|
||||||
sa1111_setup_irq(sachip);
|
|
||||||
|
|
||||||
g_sa1111 = sachip;
|
g_sa1111 = sachip;
|
||||||
|
|
||||||
has_devs = ~0;
|
has_devs = ~0;
|
||||||
if (machine_is_assabet() || machine_is_jornada720() ||
|
if (pd)
|
||||||
machine_is_badge4())
|
has_devs &= ~pd->disable_devs;
|
||||||
has_devs &= ~(1 << 4);
|
|
||||||
else
|
|
||||||
has_devs &= ~(1 << 1);
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(sa1111_devices); i++)
|
for (i = 0; i < ARRAY_SIZE(sa1111_devices); i++)
|
||||||
if (has_devs & (1 << i))
|
if (sa1111_devices[i].devid & has_devs)
|
||||||
sa1111_init_one_child(sachip, mem, &sa1111_devices[i]);
|
sa1111_init_one_child(sachip, mem, &sa1111_devices[i]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -824,7 +815,10 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
|||||||
|
|
||||||
static int sa1111_remove_one(struct device *dev, void *data)
|
static int sa1111_remove_one(struct device *dev, void *data)
|
||||||
{
|
{
|
||||||
device_unregister(dev);
|
struct sa1111_dev *sadev = SA1111_DEV(dev);
|
||||||
|
device_del(&sadev->dev);
|
||||||
|
release_resource(&sadev->res);
|
||||||
|
put_device(&sadev->dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -846,6 +840,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
|
|||||||
if (sachip->irq != NO_IRQ) {
|
if (sachip->irq != NO_IRQ) {
|
||||||
irq_set_chained_handler(sachip->irq, NULL);
|
irq_set_chained_handler(sachip->irq, NULL);
|
||||||
irq_set_handler_data(sachip->irq, NULL);
|
irq_set_handler_data(sachip->irq, NULL);
|
||||||
|
irq_free_descs(sachip->irq_base, SA1111_IRQ_NR);
|
||||||
|
|
||||||
release_mem_region(sachip->phys + SA1111_INTC, 512);
|
release_mem_region(sachip->phys + SA1111_INTC, 512);
|
||||||
}
|
}
|
||||||
@ -904,6 +899,9 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
|
|||||||
save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0);
|
save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0);
|
||||||
save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1);
|
save->skpwm1 = sa1111_readl(base + SA1111_SKPWM1);
|
||||||
|
|
||||||
|
sa1111_writel(0, sachip->base + SA1111_SKPWM0);
|
||||||
|
sa1111_writel(0, sachip->base + SA1111_SKPWM1);
|
||||||
|
|
||||||
base = sachip->base + SA1111_INTC;
|
base = sachip->base + SA1111_INTC;
|
||||||
save->intpol0 = sa1111_readl(base + SA1111_INTPOL0);
|
save->intpol0 = sa1111_readl(base + SA1111_INTPOL0);
|
||||||
save->intpol1 = sa1111_readl(base + SA1111_INTPOL1);
|
save->intpol1 = sa1111_readl(base + SA1111_INTPOL1);
|
||||||
@ -919,13 +917,15 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
|
|||||||
*/
|
*/
|
||||||
val = sa1111_readl(sachip->base + SA1111_SKCR);
|
val = sa1111_readl(sachip->base + SA1111_SKCR);
|
||||||
sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
|
sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR);
|
||||||
sa1111_writel(0, sachip->base + SA1111_SKPWM0);
|
|
||||||
sa1111_writel(0, sachip->base + SA1111_SKPWM1);
|
|
||||||
|
|
||||||
clk_disable(sachip->clk);
|
clk_disable(sachip->clk);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&sachip->lock, flags);
|
spin_unlock_irqrestore(&sachip->lock, flags);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_SA1100
|
||||||
|
sa1110_mb_disable();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,6 +966,11 @@ static int sa1111_resume(struct platform_device *dev)
|
|||||||
*/
|
*/
|
||||||
sa1111_wake(sachip);
|
sa1111_wake(sachip);
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_SA1100
|
||||||
|
/* Enable the memory bus request/grant signals */
|
||||||
|
sa1110_mb_enable();
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only lock for write ops. Also, sa1111_wake must be called with
|
* Only lock for write ops. Also, sa1111_wake must be called with
|
||||||
* released spinlock!
|
* released spinlock!
|
||||||
@ -1053,6 +1058,7 @@ static struct platform_driver sa1111_device_driver = {
|
|||||||
.resume = sa1111_resume,
|
.resume = sa1111_resume,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "sa1111",
|
.name = "sa1111",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1238,16 +1244,23 @@ EXPORT_SYMBOL(sa1111_set_sleep_io);
|
|||||||
* sa1111_enable_device - enable an on-chip SA1111 function block
|
* sa1111_enable_device - enable an on-chip SA1111 function block
|
||||||
* @sadev: SA1111 function block device to enable
|
* @sadev: SA1111 function block device to enable
|
||||||
*/
|
*/
|
||||||
void sa1111_enable_device(struct sa1111_dev *sadev)
|
int sa1111_enable_device(struct sa1111_dev *sadev)
|
||||||
{
|
{
|
||||||
struct sa1111 *sachip = sa1111_chip_driver(sadev);
|
struct sa1111 *sachip = sa1111_chip_driver(sadev);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&sachip->lock, flags);
|
if (sachip->pdata && sachip->pdata->enable)
|
||||||
val = sa1111_readl(sachip->base + SA1111_SKPCR);
|
ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid);
|
||||||
sa1111_writel(val | sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
|
|
||||||
spin_unlock_irqrestore(&sachip->lock, flags);
|
if (ret == 0) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sa1111_enable_device);
|
EXPORT_SYMBOL(sa1111_enable_device);
|
||||||
|
|
||||||
@ -1265,6 +1278,9 @@ void sa1111_disable_device(struct sa1111_dev *sadev)
|
|||||||
val = sa1111_readl(sachip->base + SA1111_SKPCR);
|
val = sa1111_readl(sachip->base + SA1111_SKPCR);
|
||||||
sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
|
sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
|
||||||
spin_unlock_irqrestore(&sachip->lock, flags);
|
spin_unlock_irqrestore(&sachip->lock, flags);
|
||||||
|
|
||||||
|
if (sachip->pdata && sachip->pdata->disable)
|
||||||
|
sachip->pdata->disable(sachip->pdata->data, sadev->devid);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sa1111_disable_device);
|
EXPORT_SYMBOL(sa1111_disable_device);
|
||||||
|
|
||||||
@ -1279,7 +1295,7 @@ static int sa1111_match(struct device *_dev, struct device_driver *_drv)
|
|||||||
struct sa1111_dev *dev = SA1111_DEV(_dev);
|
struct sa1111_dev *dev = SA1111_DEV(_dev);
|
||||||
struct sa1111_driver *drv = SA1111_DRV(_drv);
|
struct sa1111_driver *drv = SA1111_DRV(_drv);
|
||||||
|
|
||||||
return dev->devid == drv->devid;
|
return dev->devid & drv->devid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sa1111_bus_suspend(struct device *dev, pm_message_t state)
|
static int sa1111_bus_suspend(struct device *dev, pm_message_t state)
|
||||||
@ -1304,6 +1320,14 @@ static int sa1111_bus_resume(struct device *dev)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sa1111_bus_shutdown(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sa1111_driver *drv = SA1111_DRV(dev->driver);
|
||||||
|
|
||||||
|
if (drv && drv->shutdown)
|
||||||
|
drv->shutdown(SA1111_DEV(dev));
|
||||||
|
}
|
||||||
|
|
||||||
static int sa1111_bus_probe(struct device *dev)
|
static int sa1111_bus_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
struct sa1111_dev *sadev = SA1111_DEV(dev);
|
struct sa1111_dev *sadev = SA1111_DEV(dev);
|
||||||
@ -1333,6 +1357,7 @@ struct bus_type sa1111_bus_type = {
|
|||||||
.remove = sa1111_bus_remove,
|
.remove = sa1111_bus_remove,
|
||||||
.suspend = sa1111_bus_suspend,
|
.suspend = sa1111_bus_suspend,
|
||||||
.resume = sa1111_bus_resume,
|
.resume = sa1111_bus_resume,
|
||||||
|
.shutdown = sa1111_bus_shutdown,
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL(sa1111_bus_type);
|
EXPORT_SYMBOL(sa1111_bus_type);
|
||||||
|
|
||||||
@ -1349,9 +1374,70 @@ void sa1111_driver_unregister(struct sa1111_driver *driver)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sa1111_driver_unregister);
|
EXPORT_SYMBOL(sa1111_driver_unregister);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DMABOUNCE
|
||||||
|
/*
|
||||||
|
* According to the "Intel StrongARM SA-1111 Microprocessor Companion
|
||||||
|
* Chip Specification Update" (June 2000), erratum #7, there is a
|
||||||
|
* significant bug in the SA1111 SDRAM shared memory controller. If
|
||||||
|
* 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
|
||||||
|
* on the configuration of the RAM, bit 10 may correspond to one
|
||||||
|
* of several different (processor-relative) address bits.
|
||||||
|
*
|
||||||
|
* This routine only identifies whether or not a given DMA address
|
||||||
|
* is susceptible to the bug.
|
||||||
|
*
|
||||||
|
* This should only get called for sa1111_device types due to the
|
||||||
|
* way we configure our device dma_masks.
|
||||||
|
*/
|
||||||
|
static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Section 4.6 of the "Intel StrongARM SA-1111 Development Module
|
||||||
|
* User's Guide" mentions that jumpers R51 and R52 control the
|
||||||
|
* target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
|
||||||
|
* SDRAM bank 1 on Neponset). The default configuration selects
|
||||||
|
* Assabet, so any address in bank 1 is necessarily invalid.
|
||||||
|
*/
|
||||||
|
return (machine_is_assabet() || machine_is_pfs168()) &&
|
||||||
|
(addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sa1111_notifier_call(struct notifier_block *n, unsigned long action,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct sa1111_dev *dev = SA1111_DEV(data);
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case BUS_NOTIFY_ADD_DEVICE:
|
||||||
|
if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL) {
|
||||||
|
int ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
|
||||||
|
sa1111_needs_bounce);
|
||||||
|
if (ret)
|
||||||
|
dev_err(&dev->dev, "failed to register with dmabounce: %d\n", ret);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUS_NOTIFY_DEL_DEVICE:
|
||||||
|
if (dev->dev.dma_mask && dev->dma_mask < 0xffffffffUL)
|
||||||
|
dmabounce_unregister_dev(&dev->dev);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct notifier_block sa1111_bus_notifier = {
|
||||||
|
.notifier_call = sa1111_notifier_call,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
static int __init sa1111_init(void)
|
static int __init sa1111_init(void)
|
||||||
{
|
{
|
||||||
int ret = bus_register(&sa1111_bus_type);
|
int ret = bus_register(&sa1111_bus_type);
|
||||||
|
#ifdef CONFIG_DMABOUNCE
|
||||||
|
if (ret == 0)
|
||||||
|
bus_register_notifier(&sa1111_bus_type, &sa1111_bus_notifier);
|
||||||
|
#endif
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
platform_driver_register(&sa1111_device_driver);
|
platform_driver_register(&sa1111_device_driver);
|
||||||
return ret;
|
return ret;
|
||||||
@ -1360,6 +1446,9 @@ static int __init sa1111_init(void)
|
|||||||
static void __exit sa1111_exit(void)
|
static void __exit sa1111_exit(void)
|
||||||
{
|
{
|
||||||
platform_driver_unregister(&sa1111_device_driver);
|
platform_driver_unregister(&sa1111_device_driver);
|
||||||
|
#ifdef CONFIG_DMABOUNCE
|
||||||
|
bus_unregister_notifier(&sa1111_bus_type, &sa1111_bus_notifier);
|
||||||
|
#endif
|
||||||
bus_unregister(&sa1111_bus_type);
|
bus_unregister(&sa1111_bus_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,33 +132,9 @@
|
|||||||
#define SKPCR_DCLKEN (1<<7)
|
#define SKPCR_DCLKEN (1<<7)
|
||||||
#define SKPCR_PWMCLKEN (1<<8)
|
#define SKPCR_PWMCLKEN (1<<8)
|
||||||
|
|
||||||
/*
|
/* USB Host controller */
|
||||||
* USB Host controller
|
|
||||||
*/
|
|
||||||
#define SA1111_USB 0x0400
|
#define SA1111_USB 0x0400
|
||||||
|
|
||||||
/*
|
|
||||||
* Offsets from SA1111_USB_BASE
|
|
||||||
*/
|
|
||||||
#define SA1111_USB_STATUS 0x0118
|
|
||||||
#define SA1111_USB_RESET 0x011c
|
|
||||||
#define SA1111_USB_IRQTEST 0x0120
|
|
||||||
|
|
||||||
#define USB_RESET_FORCEIFRESET (1 << 0)
|
|
||||||
#define USB_RESET_FORCEHCRESET (1 << 1)
|
|
||||||
#define USB_RESET_CLKGENRESET (1 << 2)
|
|
||||||
#define USB_RESET_SIMSCALEDOWN (1 << 3)
|
|
||||||
#define USB_RESET_USBINTTEST (1 << 4)
|
|
||||||
#define USB_RESET_SLEEPSTBYEN (1 << 5)
|
|
||||||
#define USB_RESET_PWRSENSELOW (1 << 6)
|
|
||||||
#define USB_RESET_PWRCTRLLOW (1 << 7)
|
|
||||||
|
|
||||||
#define USB_STATUS_IRQHCIRMTWKUP (1 << 7)
|
|
||||||
#define USB_STATUS_IRQHCIBUFFACC (1 << 8)
|
|
||||||
#define USB_STATUS_NIRQHCIM (1 << 9)
|
|
||||||
#define USB_STATUS_NHCIMFCLR (1 << 10)
|
|
||||||
#define USB_STATUS_USBPWRSENSE (1 << 11)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Serial Audio Controller
|
* Serial Audio Controller
|
||||||
*
|
*
|
||||||
@ -327,22 +303,6 @@
|
|||||||
* PC_SSR GPIO Block C Sleep State
|
* PC_SSR GPIO Block C Sleep State
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _PA_DDR _SA1111( 0x1000 )
|
|
||||||
#define _PA_DRR _SA1111( 0x1004 )
|
|
||||||
#define _PA_DWR _SA1111( 0x1004 )
|
|
||||||
#define _PA_SDR _SA1111( 0x1008 )
|
|
||||||
#define _PA_SSR _SA1111( 0x100c )
|
|
||||||
#define _PB_DDR _SA1111( 0x1010 )
|
|
||||||
#define _PB_DRR _SA1111( 0x1014 )
|
|
||||||
#define _PB_DWR _SA1111( 0x1014 )
|
|
||||||
#define _PB_SDR _SA1111( 0x1018 )
|
|
||||||
#define _PB_SSR _SA1111( 0x101c )
|
|
||||||
#define _PC_DDR _SA1111( 0x1020 )
|
|
||||||
#define _PC_DRR _SA1111( 0x1024 )
|
|
||||||
#define _PC_DWR _SA1111( 0x1024 )
|
|
||||||
#define _PC_SDR _SA1111( 0x1028 )
|
|
||||||
#define _PC_SSR _SA1111( 0x102c )
|
|
||||||
|
|
||||||
#define SA1111_GPIO 0x1000
|
#define SA1111_GPIO 0x1000
|
||||||
|
|
||||||
#define SA1111_GPIO_PADDR (0x000)
|
#define SA1111_GPIO_PADDR (0x000)
|
||||||
@ -425,106 +385,30 @@
|
|||||||
#define SA1111_WAKEPOL0 0x0034
|
#define SA1111_WAKEPOL0 0x0034
|
||||||
#define SA1111_WAKEPOL1 0x0038
|
#define SA1111_WAKEPOL1 0x0038
|
||||||
|
|
||||||
/*
|
/* PS/2 Trackpad and Mouse Interfaces */
|
||||||
* PS/2 Trackpad and Mouse Interfaces
|
|
||||||
*
|
|
||||||
* Registers
|
|
||||||
* PS2CR Control Register
|
|
||||||
* PS2STAT Status Register
|
|
||||||
* PS2DATA Transmit/Receive Data register
|
|
||||||
* PS2CLKDIV Clock Division Register
|
|
||||||
* PS2PRECNT Clock Precount Register
|
|
||||||
* PS2TEST1 Test register 1
|
|
||||||
* PS2TEST2 Test register 2
|
|
||||||
* PS2TEST3 Test register 3
|
|
||||||
* PS2TEST4 Test register 4
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SA1111_KBD 0x0a00
|
#define SA1111_KBD 0x0a00
|
||||||
#define SA1111_MSE 0x0c00
|
#define SA1111_MSE 0x0c00
|
||||||
|
|
||||||
/*
|
/* PCMCIA Interface */
|
||||||
* These are offsets from the above bases.
|
#define SA1111_PCMCIA 0x1600
|
||||||
*/
|
|
||||||
#define SA1111_PS2CR 0x0000
|
|
||||||
#define SA1111_PS2STAT 0x0004
|
|
||||||
#define SA1111_PS2DATA 0x0008
|
|
||||||
#define SA1111_PS2CLKDIV 0x000c
|
|
||||||
#define SA1111_PS2PRECNT 0x0010
|
|
||||||
|
|
||||||
#define PS2CR_ENA 0x08
|
|
||||||
#define PS2CR_FKD 0x02
|
|
||||||
#define PS2CR_FKC 0x01
|
|
||||||
|
|
||||||
#define PS2STAT_STP 0x0100
|
|
||||||
#define PS2STAT_TXE 0x0080
|
|
||||||
#define PS2STAT_TXB 0x0040
|
|
||||||
#define PS2STAT_RXF 0x0020
|
|
||||||
#define PS2STAT_RXB 0x0010
|
|
||||||
#define PS2STAT_ENA 0x0008
|
|
||||||
#define PS2STAT_RXP 0x0004
|
|
||||||
#define PS2STAT_KBD 0x0002
|
|
||||||
#define PS2STAT_KBC 0x0001
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PCMCIA Interface
|
|
||||||
*
|
|
||||||
* Registers
|
|
||||||
* PCSR Status Register
|
|
||||||
* PCCR Control Register
|
|
||||||
* PCSSR Sleep State Register
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define SA1111_PCMCIA 0x1600
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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_S1_READY (1<<1)
|
|
||||||
#define PCSR_S0_DETECT (1<<2)
|
|
||||||
#define PCSR_S1_DETECT (1<<3)
|
|
||||||
#define PCSR_S0_VS1 (1<<4)
|
|
||||||
#define PCSR_S0_VS2 (1<<5)
|
|
||||||
#define PCSR_S1_VS1 (1<<6)
|
|
||||||
#define PCSR_S1_VS2 (1<<7)
|
|
||||||
#define PCSR_S0_WP (1<<8)
|
|
||||||
#define PCSR_S1_WP (1<<9)
|
|
||||||
#define PCSR_S0_BVD1 (1<<10)
|
|
||||||
#define PCSR_S0_BVD2 (1<<11)
|
|
||||||
#define PCSR_S1_BVD1 (1<<12)
|
|
||||||
#define PCSR_S1_BVD2 (1<<13)
|
|
||||||
|
|
||||||
#define PCCR_S0_RST (1<<0)
|
|
||||||
#define PCCR_S1_RST (1<<1)
|
|
||||||
#define PCCR_S0_FLT (1<<2)
|
|
||||||
#define PCCR_S1_FLT (1<<3)
|
|
||||||
#define PCCR_S0_PWAITEN (1<<4)
|
|
||||||
#define PCCR_S1_PWAITEN (1<<5)
|
|
||||||
#define PCCR_S0_PSE (1<<6)
|
|
||||||
#define PCCR_S1_PSE (1<<7)
|
|
||||||
|
|
||||||
#define PCSSR_S0_SLEEP (1<<0)
|
|
||||||
#define PCSSR_S1_SLEEP (1<<1)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern struct bus_type sa1111_bus_type;
|
extern struct bus_type sa1111_bus_type;
|
||||||
|
|
||||||
#define SA1111_DEVID_SBI 0
|
#define SA1111_DEVID_SBI (1 << 0)
|
||||||
#define SA1111_DEVID_SK 1
|
#define SA1111_DEVID_SK (1 << 1)
|
||||||
#define SA1111_DEVID_USB 2
|
#define SA1111_DEVID_USB (1 << 2)
|
||||||
#define SA1111_DEVID_SAC 3
|
#define SA1111_DEVID_SAC (1 << 3)
|
||||||
#define SA1111_DEVID_SSP 4
|
#define SA1111_DEVID_SSP (1 << 4)
|
||||||
#define SA1111_DEVID_PS2 5
|
#define SA1111_DEVID_PS2 (3 << 5)
|
||||||
#define SA1111_DEVID_GPIO 6
|
#define SA1111_DEVID_PS2_KBD (1 << 5)
|
||||||
#define SA1111_DEVID_INT 7
|
#define SA1111_DEVID_PS2_MSE (1 << 6)
|
||||||
#define SA1111_DEVID_PCMCIA 8
|
#define SA1111_DEVID_GPIO (1 << 7)
|
||||||
|
#define SA1111_DEVID_INT (1 << 8)
|
||||||
|
#define SA1111_DEVID_PCMCIA (1 << 9)
|
||||||
|
|
||||||
struct sa1111_dev {
|
struct sa1111_dev {
|
||||||
struct device dev;
|
struct device dev;
|
||||||
@ -548,6 +432,7 @@ struct sa1111_driver {
|
|||||||
int (*remove)(struct sa1111_dev *);
|
int (*remove)(struct sa1111_dev *);
|
||||||
int (*suspend)(struct sa1111_dev *, pm_message_t);
|
int (*suspend)(struct sa1111_dev *, pm_message_t);
|
||||||
int (*resume)(struct sa1111_dev *);
|
int (*resume)(struct sa1111_dev *);
|
||||||
|
void (*shutdown)(struct sa1111_dev *);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv)
|
#define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv)
|
||||||
@ -555,9 +440,10 @@ struct sa1111_driver {
|
|||||||
#define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name)
|
#define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These frob the SKPCR register.
|
* These frob the SKPCR register, and call platform specific
|
||||||
|
* enable/disable functions.
|
||||||
*/
|
*/
|
||||||
void sa1111_enable_device(struct sa1111_dev *);
|
int sa1111_enable_device(struct sa1111_dev *);
|
||||||
void sa1111_disable_device(struct sa1111_dev *);
|
void sa1111_disable_device(struct sa1111_dev *);
|
||||||
|
|
||||||
unsigned int sa1111_pll_clock(struct sa1111_dev *);
|
unsigned int sa1111_pll_clock(struct sa1111_dev *);
|
||||||
@ -580,6 +466,10 @@ void sa1111_set_sleep_io(struct sa1111_dev *sadev, unsigned int bits, unsigned i
|
|||||||
|
|
||||||
struct sa1111_platform_data {
|
struct sa1111_platform_data {
|
||||||
int irq_base; /* base for cascaded on-chip IRQs */
|
int irq_base; /* base for cascaded on-chip IRQs */
|
||||||
|
unsigned disable_devs;
|
||||||
|
void *data;
|
||||||
|
int (*enable)(void *, unsigned);
|
||||||
|
void (*disable)(void *, unsigned);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _ASM_ARCH_SA1111 */
|
#endif /* _ASM_ARCH_SA1111 */
|
||||||
|
@ -223,6 +223,7 @@ static struct resource sa1111_resources[] = {
|
|||||||
|
|
||||||
static struct sa1111_platform_data sa1111_info = {
|
static struct sa1111_platform_data sa1111_info = {
|
||||||
.irq_base = LUBBOCK_SA1111_IRQ_BASE,
|
.irq_base = LUBBOCK_SA1111_IRQ_BASE,
|
||||||
|
.disable_devs = SA1111_DEVID_SAC,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_device sa1111_device = {
|
static struct platform_device sa1111_device = {
|
||||||
|
@ -425,21 +425,8 @@ static void __init assabet_map_io(void)
|
|||||||
*/
|
*/
|
||||||
Ser1SDCR0 |= SDCR0_SUS;
|
Ser1SDCR0 |= SDCR0_SUS;
|
||||||
|
|
||||||
if (machine_has_neponset()) {
|
if (!machine_has_neponset())
|
||||||
#ifdef CONFIG_ASSABET_NEPONSET
|
|
||||||
extern void neponset_map_io(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We map Neponset registers even if it isn't present since
|
|
||||||
* many drivers will try to probe their stuff (and fail).
|
|
||||||
* This is still more friendly than a kernel paging request
|
|
||||||
* crash.
|
|
||||||
*/
|
|
||||||
neponset_map_io();
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
sa1100_register_uart_fns(&assabet_port_fns);
|
sa1100_register_uart_fns(&assabet_port_fns);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When Neponset is attached, the first UART should be
|
* When Neponset is attached, the first UART should be
|
||||||
|
@ -43,8 +43,24 @@ static struct resource sa1111_resources[] = {
|
|||||||
[1] = DEFINE_RES_IRQ(BADGE4_IRQ_GPIO_SA1111),
|
[1] = DEFINE_RES_IRQ(BADGE4_IRQ_GPIO_SA1111),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int badge4_sa1111_enable(void *data, unsigned devid)
|
||||||
|
{
|
||||||
|
if (devid == SA1111_DEVID_USB)
|
||||||
|
badge4_set_5V(BADGE4_5V_USB, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void badge4_sa1111_disable(void *data, unsigned devid)
|
||||||
|
{
|
||||||
|
if (devid == SA1111_DEVID_USB)
|
||||||
|
badge4_set_5V(BADGE4_5V_USB, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static struct sa1111_platform_data sa1111_info = {
|
static struct sa1111_platform_data sa1111_info = {
|
||||||
.irq_base = IRQ_BOARD_END,
|
.irq_base = IRQ_BOARD_END,
|
||||||
|
.disable_devs = SA1111_DEVID_PS2_MSE,
|
||||||
|
.enable = badge4_sa1111_enable,
|
||||||
|
.disable = badge4_sa1111_disable,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u64 sa1111_dmamask = 0xffffffffUL;
|
static u64 sa1111_dmamask = 0xffffffffUL;
|
||||||
@ -258,11 +274,6 @@ static struct map_desc badge4_io_desc[] __initdata = {
|
|||||||
.pfn = __phys_to_pfn(0x10000000),
|
.pfn = __phys_to_pfn(0x10000000),
|
||||||
.length = 0x00100000,
|
.length = 0x00100000,
|
||||||
.type = MT_DEVICE
|
.type = MT_DEVICE
|
||||||
}, { /* SA-1111 */
|
|
||||||
.virtual = 0xf4000000,
|
|
||||||
.pfn = __phys_to_pfn(0x48000000),
|
|
||||||
.length = 0x00100000,
|
|
||||||
.type = MT_DEVICE
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ static struct resource sa1111_resources[] = {
|
|||||||
|
|
||||||
static struct sa1111_platform_data sa1111_info = {
|
static struct sa1111_platform_data sa1111_info = {
|
||||||
.irq_base = IRQ_BOARD_END,
|
.irq_base = IRQ_BOARD_END,
|
||||||
|
.disable_devs = SA1111_DEVID_PS2_MSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u64 sa1111_dmamask = 0xffffffffUL;
|
static u64 sa1111_dmamask = 0xffffffffUL;
|
||||||
@ -268,11 +269,6 @@ static struct map_desc jornada720_io_desc[] __initdata = {
|
|||||||
.pfn = __phys_to_pfn(EPSONFBSTART),
|
.pfn = __phys_to_pfn(EPSONFBSTART),
|
||||||
.length = EPSONFBLEN,
|
.length = EPSONFBLEN,
|
||||||
.type = MT_DEVICE
|
.type = MT_DEVICE
|
||||||
}, { /* SA-1111 */
|
|
||||||
.virtual = 0xf4000000,
|
|
||||||
.pfn = __phys_to_pfn(SA1111REGSTART),
|
|
||||||
.length = SA1111REGLEN,
|
|
||||||
.type = MT_DEVICE
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -229,6 +229,7 @@ static struct irq_chip nochip = {
|
|||||||
|
|
||||||
static struct sa1111_platform_data sa1111_info = {
|
static struct sa1111_platform_data sa1111_info = {
|
||||||
.irq_base = IRQ_BOARD_END,
|
.irq_base = IRQ_BOARD_END,
|
||||||
|
.disable_devs = SA1111_DEVID_PS2_MSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __devinit neponset_probe(struct platform_device *dev)
|
static int __devinit neponset_probe(struct platform_device *dev)
|
||||||
@ -432,17 +433,3 @@ static int __init neponset_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
subsys_initcall(neponset_init);
|
subsys_initcall(neponset_init);
|
||||||
|
|
||||||
static struct map_desc neponset_io_desc[] __initdata = {
|
|
||||||
{ /* SA-1111 */
|
|
||||||
.virtual = 0xf4000000,
|
|
||||||
.pfn = __phys_to_pfn(0x40000000),
|
|
||||||
.length = SZ_1M,
|
|
||||||
.type = MT_DEVICE
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void __init neponset_map_io(void)
|
|
||||||
{
|
|
||||||
iotable_init(neponset_io_desc, ARRAY_SIZE(neponset_io_desc));
|
|
||||||
}
|
|
||||||
|
@ -24,6 +24,26 @@
|
|||||||
|
|
||||||
#include <asm/hardware/sa1111.h>
|
#include <asm/hardware/sa1111.h>
|
||||||
|
|
||||||
|
#define PS2CR 0x0000
|
||||||
|
#define PS2STAT 0x0004
|
||||||
|
#define PS2DATA 0x0008
|
||||||
|
#define PS2CLKDIV 0x000c
|
||||||
|
#define PS2PRECNT 0x0010
|
||||||
|
|
||||||
|
#define PS2CR_ENA 0x08
|
||||||
|
#define PS2CR_FKD 0x02
|
||||||
|
#define PS2CR_FKC 0x01
|
||||||
|
|
||||||
|
#define PS2STAT_STP 0x0100
|
||||||
|
#define PS2STAT_TXE 0x0080
|
||||||
|
#define PS2STAT_TXB 0x0040
|
||||||
|
#define PS2STAT_RXF 0x0020
|
||||||
|
#define PS2STAT_RXB 0x0010
|
||||||
|
#define PS2STAT_ENA 0x0008
|
||||||
|
#define PS2STAT_RXP 0x0004
|
||||||
|
#define PS2STAT_KBD 0x0002
|
||||||
|
#define PS2STAT_KBC 0x0001
|
||||||
|
|
||||||
struct ps2if {
|
struct ps2if {
|
||||||
struct serio *io;
|
struct serio *io;
|
||||||
struct sa1111_dev *dev;
|
struct sa1111_dev *dev;
|
||||||
@ -45,22 +65,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id)
|
|||||||
struct ps2if *ps2if = dev_id;
|
struct ps2if *ps2if = dev_id;
|
||||||
unsigned int scancode, flag, status;
|
unsigned int scancode, flag, status;
|
||||||
|
|
||||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
status = sa1111_readl(ps2if->base + PS2STAT);
|
||||||
while (status & PS2STAT_RXF) {
|
while (status & PS2STAT_RXF) {
|
||||||
if (status & PS2STAT_STP)
|
if (status & PS2STAT_STP)
|
||||||
sa1111_writel(PS2STAT_STP, ps2if->base + SA1111_PS2STAT);
|
sa1111_writel(PS2STAT_STP, ps2if->base + 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(ps2if->base + SA1111_PS2DATA) & 0xff;
|
scancode = sa1111_readl(ps2if->base + PS2DATA) & 0xff;
|
||||||
|
|
||||||
if (hweight8(scancode) & 1)
|
if (hweight8(scancode) & 1)
|
||||||
flag ^= SERIO_PARITY;
|
flag ^= SERIO_PARITY;
|
||||||
|
|
||||||
serio_interrupt(ps2if->io, scancode, flag);
|
serio_interrupt(ps2if->io, scancode, flag);
|
||||||
|
|
||||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
status = sa1111_readl(ps2if->base + PS2STAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
@ -75,12 +95,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
|
|||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
spin_lock(&ps2if->lock);
|
spin_lock(&ps2if->lock);
|
||||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
status = sa1111_readl(ps2if->base + PS2STAT);
|
||||||
if (ps2if->head == ps2if->tail) {
|
if (ps2if->head == ps2if->tail) {
|
||||||
disable_irq_nosync(irq);
|
disable_irq_nosync(irq);
|
||||||
/* done */
|
/* done */
|
||||||
} else if (status & PS2STAT_TXE) {
|
} else if (status & PS2STAT_TXE) {
|
||||||
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
|
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + PS2DATA);
|
||||||
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
|
ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1);
|
||||||
}
|
}
|
||||||
spin_unlock(&ps2if->lock);
|
spin_unlock(&ps2if->lock);
|
||||||
@ -103,8 +123,8 @@ static int ps2_write(struct serio *io, unsigned char val)
|
|||||||
/*
|
/*
|
||||||
* If the TX register is empty, we can go straight out.
|
* If the TX register is empty, we can go straight out.
|
||||||
*/
|
*/
|
||||||
if (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
|
if (sa1111_readl(ps2if->base + PS2STAT) & PS2STAT_TXE) {
|
||||||
sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
|
sa1111_writel(val, ps2if->base + PS2DATA);
|
||||||
} else {
|
} else {
|
||||||
if (ps2if->head == ps2if->tail)
|
if (ps2if->head == ps2if->tail)
|
||||||
enable_irq(ps2if->dev->irq[1]);
|
enable_irq(ps2if->dev->irq[1]);
|
||||||
@ -124,13 +144,16 @@ static int ps2_open(struct serio *io)
|
|||||||
struct ps2if *ps2if = io->port_data;
|
struct ps2if *ps2if = io->port_data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
sa1111_enable_device(ps2if->dev);
|
ret = sa1111_enable_device(ps2if->dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
|
ret = request_irq(ps2if->dev->irq[0], ps2_rxint, 0,
|
||||||
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
|
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",
|
||||||
ps2if->dev->irq[0], ret);
|
ps2if->dev->irq[0], ret);
|
||||||
|
sa1111_disable_device(ps2if->dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +163,7 @@ static int ps2_open(struct serio *io)
|
|||||||
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
|
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
|
||||||
ps2if->dev->irq[1], ret);
|
ps2if->dev->irq[1], ret);
|
||||||
free_irq(ps2if->dev->irq[0], ps2if);
|
free_irq(ps2if->dev->irq[0], ps2if);
|
||||||
|
sa1111_disable_device(ps2if->dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +171,7 @@ static int ps2_open(struct serio *io)
|
|||||||
|
|
||||||
enable_irq_wake(ps2if->dev->irq[0]);
|
enable_irq_wake(ps2if->dev->irq[0]);
|
||||||
|
|
||||||
sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
|
sa1111_writel(PS2CR_ENA, ps2if->base + PS2CR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +179,7 @@ static void ps2_close(struct serio *io)
|
|||||||
{
|
{
|
||||||
struct ps2if *ps2if = io->port_data;
|
struct ps2if *ps2if = io->port_data;
|
||||||
|
|
||||||
sa1111_writel(0, ps2if->base + SA1111_PS2CR);
|
sa1111_writel(0, ps2if->base + PS2CR);
|
||||||
|
|
||||||
disable_irq_wake(ps2if->dev->irq[0]);
|
disable_irq_wake(ps2if->dev->irq[0]);
|
||||||
|
|
||||||
@ -175,7 +199,7 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if)
|
|||||||
int maxread = 100;
|
int maxread = 100;
|
||||||
|
|
||||||
while (maxread--) {
|
while (maxread--) {
|
||||||
if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
|
if ((sa1111_readl(ps2if->base + PS2DATA) & 0xff) == 0xff)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -185,11 +209,11 @@ static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
|
|||||||
{
|
{
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
|
|
||||||
sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
|
sa1111_writel(PS2CR_ENA | mask, ps2if->base + PS2CR);
|
||||||
|
|
||||||
udelay(2);
|
udelay(2);
|
||||||
|
|
||||||
val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
val = sa1111_readl(ps2if->base + PS2STAT);
|
||||||
return val & (PS2STAT_KBC | PS2STAT_KBD);
|
return val & (PS2STAT_KBC | PS2STAT_KBD);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +244,7 @@ static int __devinit ps2_test(struct ps2if *ps2if)
|
|||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
sa1111_writel(0, ps2if->base + SA1111_PS2CR);
|
sa1111_writel(0, ps2if->base + PS2CR);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -274,8 +298,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
|
|||||||
sa1111_enable_device(ps2if->dev);
|
sa1111_enable_device(ps2if->dev);
|
||||||
|
|
||||||
/* Incoming clock is 8MHz */
|
/* Incoming clock is 8MHz */
|
||||||
sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
|
sa1111_writel(0, ps2if->base + PS2CLKDIV);
|
||||||
sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
|
sa1111_writel(127, ps2if->base + PS2PRECNT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush any pending input.
|
* Flush any pending input.
|
||||||
@ -330,6 +354,7 @@ static int __devexit ps2_remove(struct sa1111_dev *dev)
|
|||||||
static struct sa1111_driver ps2_driver = {
|
static struct sa1111_driver ps2_driver = {
|
||||||
.drv = {
|
.drv = {
|
||||||
.name = "sa1111-ps2",
|
.name = "sa1111-ps2",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.devid = SA1111_DEVID_PS2,
|
.devid = SA1111_DEVID_PS2,
|
||||||
.probe = ps2_probe,
|
.probe = ps2_probe,
|
||||||
|
@ -22,6 +22,40 @@
|
|||||||
|
|
||||||
#include "sa1111_generic.h"
|
#include "sa1111_generic.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These are offsets from the above base.
|
||||||
|
*/
|
||||||
|
#define PCCR 0x0000
|
||||||
|
#define PCSSR 0x0004
|
||||||
|
#define PCSR 0x0008
|
||||||
|
|
||||||
|
#define PCSR_S0_READY (1<<0)
|
||||||
|
#define PCSR_S1_READY (1<<1)
|
||||||
|
#define PCSR_S0_DETECT (1<<2)
|
||||||
|
#define PCSR_S1_DETECT (1<<3)
|
||||||
|
#define PCSR_S0_VS1 (1<<4)
|
||||||
|
#define PCSR_S0_VS2 (1<<5)
|
||||||
|
#define PCSR_S1_VS1 (1<<6)
|
||||||
|
#define PCSR_S1_VS2 (1<<7)
|
||||||
|
#define PCSR_S0_WP (1<<8)
|
||||||
|
#define PCSR_S1_WP (1<<9)
|
||||||
|
#define PCSR_S0_BVD1 (1<<10)
|
||||||
|
#define PCSR_S0_BVD2 (1<<11)
|
||||||
|
#define PCSR_S1_BVD1 (1<<12)
|
||||||
|
#define PCSR_S1_BVD2 (1<<13)
|
||||||
|
|
||||||
|
#define PCCR_S0_RST (1<<0)
|
||||||
|
#define PCCR_S1_RST (1<<1)
|
||||||
|
#define PCCR_S0_FLT (1<<2)
|
||||||
|
#define PCCR_S1_FLT (1<<3)
|
||||||
|
#define PCCR_S0_PWAITEN (1<<4)
|
||||||
|
#define PCCR_S1_PWAITEN (1<<5)
|
||||||
|
#define PCCR_S0_PSE (1<<6)
|
||||||
|
#define PCCR_S1_PSE (1<<7)
|
||||||
|
|
||||||
|
#define PCSSR_S0_SLEEP (1<<0)
|
||||||
|
#define PCSSR_S1_SLEEP (1<<1)
|
||||||
|
|
||||||
#define IDX_IRQ_S0_READY_NINT (0)
|
#define IDX_IRQ_S0_READY_NINT (0)
|
||||||
#define IDX_IRQ_S0_CD_VALID (1)
|
#define IDX_IRQ_S0_CD_VALID (1)
|
||||||
#define IDX_IRQ_S0_BVD1_STSCHG (2)
|
#define IDX_IRQ_S0_BVD1_STSCHG (2)
|
||||||
@ -49,7 +83,7 @@ static void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
|
|||||||
void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
|
void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
|
||||||
{
|
{
|
||||||
struct sa1111_pcmcia_socket *s = to_skt(skt);
|
struct sa1111_pcmcia_socket *s = to_skt(skt);
|
||||||
unsigned long status = sa1111_readl(s->dev->mapbase + SA1111_PCSR);
|
unsigned long status = sa1111_readl(s->dev->mapbase + PCSR);
|
||||||
|
|
||||||
switch (skt->nr) {
|
switch (skt->nr) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -105,10 +139,10 @@ int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s
|
|||||||
pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;
|
pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
val = sa1111_readl(s->dev->mapbase + SA1111_PCCR);
|
val = sa1111_readl(s->dev->mapbase + PCCR);
|
||||||
val &= ~pccr_skt_mask;
|
val &= ~pccr_skt_mask;
|
||||||
val |= pccr_set_mask & pccr_skt_mask;
|
val |= pccr_set_mask & pccr_skt_mask;
|
||||||
sa1111_writel(val, s->dev->mapbase + SA1111_PCCR);
|
sa1111_writel(val, s->dev->mapbase + PCCR);
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -163,12 +197,18 @@ int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops,
|
|||||||
static int pcmcia_probe(struct sa1111_dev *dev)
|
static int pcmcia_probe(struct sa1111_dev *dev)
|
||||||
{
|
{
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = sa1111_enable_device(dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
dev_set_drvdata(&dev->dev, NULL);
|
dev_set_drvdata(&dev->dev, NULL);
|
||||||
|
|
||||||
if (!request_mem_region(dev->res.start, 512,
|
if (!request_mem_region(dev->res.start, 512, SA1111_DRIVER_NAME(dev))) {
|
||||||
SA1111_DRIVER_NAME(dev)))
|
sa1111_disable_device(dev);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
base = dev->mapbase;
|
base = dev->mapbase;
|
||||||
|
|
||||||
@ -181,8 +221,8 @@ static int pcmcia_probe(struct sa1111_dev *dev)
|
|||||||
/*
|
/*
|
||||||
* Initialise the suspend state.
|
* Initialise the suspend state.
|
||||||
*/
|
*/
|
||||||
sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + SA1111_PCSSR);
|
sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + PCSSR);
|
||||||
sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + SA1111_PCCR);
|
sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + PCCR);
|
||||||
|
|
||||||
#ifdef CONFIG_SA1100_BADGE4
|
#ifdef CONFIG_SA1100_BADGE4
|
||||||
pcmcia_badge4_init(&dev->dev);
|
pcmcia_badge4_init(&dev->dev);
|
||||||
@ -212,6 +252,7 @@ static int __devexit pcmcia_remove(struct sa1111_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
release_mem_region(dev->res.start, 512);
|
release_mem_region(dev->res.start, 512);
|
||||||
|
sa1111_disable_device(dev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,87 +16,37 @@
|
|||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include <asm/mach-types.h>
|
#include <asm/mach-types.h>
|
||||||
#include <mach/assabet.h>
|
#include <mach/assabet.h>
|
||||||
#include <mach/badge4.h>
|
|
||||||
#include <asm/hardware/sa1111.h>
|
#include <asm/hardware/sa1111.h>
|
||||||
|
|
||||||
#ifndef CONFIG_SA1111
|
#ifndef CONFIG_SA1111
|
||||||
#error "This file is SA-1111 bus glue. CONFIG_SA1111 must be defined."
|
#error "This file is SA-1111 bus glue. CONFIG_SA1111 must be defined."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int usb_disabled(void);
|
#define USB_STATUS 0x0118
|
||||||
|
#define USB_RESET 0x011c
|
||||||
|
#define USB_IRQTEST 0x0120
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
#define USB_RESET_FORCEIFRESET (1 << 0)
|
||||||
|
#define USB_RESET_FORCEHCRESET (1 << 1)
|
||||||
|
#define USB_RESET_CLKGENRESET (1 << 2)
|
||||||
|
#define USB_RESET_SIMSCALEDOWN (1 << 3)
|
||||||
|
#define USB_RESET_USBINTTEST (1 << 4)
|
||||||
|
#define USB_RESET_SLEEPSTBYEN (1 << 5)
|
||||||
|
#define USB_RESET_PWRSENSELOW (1 << 6)
|
||||||
|
#define USB_RESET_PWRCTRLLOW (1 << 7)
|
||||||
|
|
||||||
static void sa1111_start_hc(struct sa1111_dev *dev)
|
#define USB_STATUS_IRQHCIRMTWKUP (1 << 7)
|
||||||
{
|
#define USB_STATUS_IRQHCIBUFFACC (1 << 8)
|
||||||
unsigned int usb_rst = 0;
|
#define USB_STATUS_NIRQHCIM (1 << 9)
|
||||||
|
#define USB_STATUS_NHCIMFCLR (1 << 10)
|
||||||
printk(KERN_DEBUG "%s: starting SA-1111 OHCI USB Controller\n",
|
#define USB_STATUS_USBPWRSENSE (1 << 11)
|
||||||
__FILE__);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SA1100_BADGE4
|
|
||||||
if (machine_is_badge4()) {
|
|
||||||
badge4_set_5V(BADGE4_5V_USB, 1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (machine_is_xp860() ||
|
|
||||||
machine_has_neponset() ||
|
|
||||||
machine_is_pfs168() ||
|
|
||||||
machine_is_badge4())
|
|
||||||
usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Configure the power sense and control lines. Place the USB
|
|
||||||
* host controller in reset.
|
|
||||||
*/
|
|
||||||
sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
|
|
||||||
dev->mapbase + SA1111_USB_RESET);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now, carefully enable the USB clock, and take
|
|
||||||
* the USB host controller out of reset.
|
|
||||||
*/
|
|
||||||
sa1111_enable_device(dev);
|
|
||||||
udelay(11);
|
|
||||||
sa1111_writel(usb_rst, dev->mapbase + SA1111_USB_RESET);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sa1111_stop_hc(struct sa1111_dev *dev)
|
|
||||||
{
|
|
||||||
unsigned int usb_rst;
|
|
||||||
printk(KERN_DEBUG "%s: stopping SA-1111 OHCI USB Controller\n",
|
|
||||||
__FILE__);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Put the USB host controller into reset.
|
|
||||||
*/
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
sa1111_disable_device(dev);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SA1100_BADGE4
|
|
||||||
if (machine_is_badge4()) {
|
|
||||||
/* Disable power to the USB bus */
|
|
||||||
badge4_set_5V(BADGE4_5V_USB, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void dump_hci_status(struct usb_hcd *hcd, const char *label)
|
static void dump_hci_status(struct usb_hcd *hcd, const char *label)
|
||||||
{
|
{
|
||||||
unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
|
unsigned long status = sa1111_readl(hcd->regs + 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 " : ""),
|
||||||
((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
|
((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
|
||||||
((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
|
((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
|
||||||
@ -105,98 +55,27 @@ static void dump_hci_status(struct usb_hcd *hcd, const char *label)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
static int ohci_sa1111_reset(struct usb_hcd *hcd)
|
||||||
|
|
||||||
/* configure so an HC device and id are always provided */
|
|
||||||
/* always called with process context; sleeping is OK */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* usb_hcd_sa1111_probe - initialize SA-1111-based HCDs
|
|
||||||
* Context: !in_interrupt()
|
|
||||||
*
|
|
||||||
* Allocates basic resources for this USB host controller, and
|
|
||||||
* then invokes the start() method for the HCD associated with it
|
|
||||||
* through the hotplug entry's driver_data.
|
|
||||||
*
|
|
||||||
* Store this function in the HCD's struct pci_driver as probe().
|
|
||||||
*/
|
|
||||||
int usb_hcd_sa1111_probe (const struct hc_driver *driver,
|
|
||||||
struct sa1111_dev *dev)
|
|
||||||
{
|
{
|
||||||
struct usb_hcd *hcd;
|
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||||
int retval;
|
|
||||||
|
|
||||||
hcd = usb_create_hcd (driver, &dev->dev, "sa1111");
|
ohci_hcd_init(ohci);
|
||||||
if (!hcd)
|
return ohci_init(ohci);
|
||||||
return -ENOMEM;
|
}
|
||||||
hcd->rsrc_start = dev->res.start;
|
|
||||||
hcd->rsrc_len = resource_size(&dev->res);
|
|
||||||
|
|
||||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
static int __devinit ohci_sa1111_start(struct usb_hcd *hcd)
|
||||||
dbg("request_mem_region failed");
|
{
|
||||||
retval = -EBUSY;
|
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||||
goto err1;
|
int ret;
|
||||||
|
|
||||||
|
ret = ohci_run(ohci);
|
||||||
|
if (ret < 0) {
|
||||||
|
ohci_err(ohci, "can't start\n");
|
||||||
|
ohci_stop(hcd);
|
||||||
}
|
}
|
||||||
hcd->regs = dev->mapbase;
|
return ret;
|
||||||
|
|
||||||
sa1111_start_hc(dev);
|
|
||||||
ohci_hcd_init(hcd_to_ohci(hcd));
|
|
||||||
|
|
||||||
retval = usb_add_hcd(hcd, dev->irq[1], 0);
|
|
||||||
if (retval == 0)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
sa1111_stop_hc(dev);
|
|
||||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
|
||||||
err1:
|
|
||||||
usb_put_hcd(hcd);
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* may be called without controller electrically present */
|
|
||||||
/* may be called with controller, bus, and devices active */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* usb_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs
|
|
||||||
* @dev: USB Host Controller being removed
|
|
||||||
* Context: !in_interrupt()
|
|
||||||
*
|
|
||||||
* Reverses the effect of usb_hcd_sa1111_probe(), first invoking
|
|
||||||
* the HCD's stop() method. It is always called from a thread
|
|
||||||
* context, normally "rmmod", "apmd", or something similar.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
|
|
||||||
{
|
|
||||||
usb_remove_hcd(hcd);
|
|
||||||
sa1111_stop_hc(dev);
|
|
||||||
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
|
||||||
usb_put_hcd(hcd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static int __devinit
|
|
||||||
ohci_sa1111_start (struct usb_hcd *hcd)
|
|
||||||
{
|
|
||||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if ((ret = ohci_init(ohci)) < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
if ((ret = ohci_run (ohci)) < 0) {
|
|
||||||
err ("can't start %s", hcd->self.bus_name);
|
|
||||||
ohci_stop (hcd);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
static const struct hc_driver ohci_sa1111_hc_driver = {
|
static const struct hc_driver ohci_sa1111_hc_driver = {
|
||||||
.description = hcd_name,
|
.description = hcd_name,
|
||||||
.product_desc = "SA-1111 OHCI",
|
.product_desc = "SA-1111 OHCI",
|
||||||
@ -211,8 +90,10 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
|
|||||||
/*
|
/*
|
||||||
* basic lifecycle operations
|
* basic lifecycle operations
|
||||||
*/
|
*/
|
||||||
|
.reset = ohci_sa1111_reset,
|
||||||
.start = ohci_sa1111_start,
|
.start = ohci_sa1111_start,
|
||||||
.stop = ohci_stop,
|
.stop = ohci_stop,
|
||||||
|
.shutdown = ohci_shutdown,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* managing i/o requests and associated device resources
|
* managing i/o requests and associated device resources
|
||||||
@ -238,33 +119,139 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
|
|||||||
.start_port_reset = ohci_start_port_reset,
|
.start_port_reset = ohci_start_port_reset,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
static int sa1111_start_hc(struct sa1111_dev *dev)
|
||||||
|
|
||||||
static int ohci_hcd_sa1111_drv_probe(struct sa1111_dev *dev)
|
|
||||||
{
|
{
|
||||||
|
unsigned int usb_rst = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev_dbg(&dev->dev, "starting SA-1111 OHCI USB Controller\n");
|
||||||
|
|
||||||
|
if (machine_is_xp860() ||
|
||||||
|
machine_has_neponset() ||
|
||||||
|
machine_is_pfs168() ||
|
||||||
|
machine_is_badge4())
|
||||||
|
usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configure the power sense and control lines. Place the USB
|
||||||
|
* host controller in reset.
|
||||||
|
*/
|
||||||
|
sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
|
||||||
|
dev->mapbase + USB_RESET);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, carefully enable the USB clock, and take
|
||||||
|
* the USB host controller out of reset.
|
||||||
|
*/
|
||||||
|
ret = sa1111_enable_device(dev);
|
||||||
|
if (ret == 0) {
|
||||||
|
udelay(11);
|
||||||
|
sa1111_writel(usb_rst, dev->mapbase + USB_RESET);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sa1111_stop_hc(struct sa1111_dev *dev)
|
||||||
|
{
|
||||||
|
unsigned int usb_rst;
|
||||||
|
|
||||||
|
dev_dbg(&dev->dev, "stopping SA-1111 OHCI USB Controller\n");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put the USB host controller into reset.
|
||||||
|
*/
|
||||||
|
usb_rst = sa1111_readl(dev->mapbase + USB_RESET);
|
||||||
|
sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET,
|
||||||
|
dev->mapbase + USB_RESET);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop the USB clock.
|
||||||
|
*/
|
||||||
|
sa1111_disable_device(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ohci_hcd_sa1111_probe - initialize SA-1111-based HCDs
|
||||||
|
*
|
||||||
|
* Allocates basic resources for this USB host controller, and
|
||||||
|
* then invokes the start() method for the HCD associated with it.
|
||||||
|
*/
|
||||||
|
static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev)
|
||||||
|
{
|
||||||
|
struct usb_hcd *hcd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (usb_disabled())
|
if (usb_disabled())
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, dev);
|
hcd = usb_create_hcd(&ohci_sa1111_hc_driver, &dev->dev, "sa1111");
|
||||||
|
if (!hcd)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
hcd->rsrc_start = dev->res.start;
|
||||||
|
hcd->rsrc_len = resource_size(&dev->res);
|
||||||
|
|
||||||
|
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||||
|
dbg("request_mem_region failed");
|
||||||
|
ret = -EBUSY;
|
||||||
|
goto err1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hcd->regs = dev->mapbase;
|
||||||
|
|
||||||
|
ret = sa1111_start_hc(dev);
|
||||||
|
if (ret)
|
||||||
|
goto err2;
|
||||||
|
|
||||||
|
ret = usb_add_hcd(hcd, dev->irq[1], 0);
|
||||||
|
if (ret == 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
sa1111_stop_hc(dev);
|
||||||
|
err2:
|
||||||
|
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||||
|
err1:
|
||||||
|
usb_put_hcd(hcd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ohci_hcd_sa1111_drv_remove(struct sa1111_dev *dev)
|
/**
|
||||||
|
* ohci_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs
|
||||||
|
* @dev: USB Host Controller being removed
|
||||||
|
*
|
||||||
|
* Reverses the effect of ohci_hcd_sa1111_probe(), first invoking
|
||||||
|
* the HCD's stop() method.
|
||||||
|
*/
|
||||||
|
static int ohci_hcd_sa1111_remove(struct sa1111_dev *dev)
|
||||||
{
|
{
|
||||||
struct usb_hcd *hcd = sa1111_get_drvdata(dev);
|
struct usb_hcd *hcd = sa1111_get_drvdata(dev);
|
||||||
|
|
||||||
usb_hcd_sa1111_remove(hcd, dev);
|
usb_remove_hcd(hcd);
|
||||||
|
sa1111_stop_hc(dev);
|
||||||
|
release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||||
|
usb_put_hcd(hcd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ohci_hcd_sa1111_shutdown(struct sa1111_dev *dev)
|
||||||
|
{
|
||||||
|
struct usb_hcd *hcd = sa1111_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) {
|
||||||
|
hcd->driver->shutdown(hcd);
|
||||||
|
sa1111_stop_hc(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static struct sa1111_driver ohci_hcd_sa1111_driver = {
|
static struct sa1111_driver ohci_hcd_sa1111_driver = {
|
||||||
.drv = {
|
.drv = {
|
||||||
.name = "sa1111-ohci",
|
.name = "sa1111-ohci",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
},
|
},
|
||||||
.devid = SA1111_DEVID_USB,
|
.devid = SA1111_DEVID_USB,
|
||||||
.probe = ohci_hcd_sa1111_drv_probe,
|
.probe = ohci_hcd_sa1111_probe,
|
||||||
.remove = ohci_hcd_sa1111_drv_remove,
|
.remove = ohci_hcd_sa1111_remove,
|
||||||
|
.shutdown = ohci_hcd_sa1111_shutdown,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user