forked from Minki/linux
Merge branches 'acorn', 'ebsa110' and 'sa11x0' into platforms
This commit is contained in:
commit
aae528d9a8
@ -759,6 +759,7 @@ config ARCH_SA1100
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select HAVE_IDE
|
||||
select NEED_MACH_MEMORY_H
|
||||
select SPARSE_IRQ
|
||||
help
|
||||
Support for StrongARM 11x0 based boards.
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/errno.h>
|
||||
@ -28,9 +29,8 @@
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#include <asm/hardware/sa1111.h>
|
||||
@ -86,8 +86,10 @@
|
||||
#define IRQ_S1_CD_VALID (52)
|
||||
#define IRQ_S0_BVD1_STSCHG (53)
|
||||
#define IRQ_S1_BVD1_STSCHG (54)
|
||||
#define SA1111_IRQ_NR (55)
|
||||
|
||||
extern void __init 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
|
||||
@ -104,6 +106,7 @@ struct sa1111 {
|
||||
int irq_base; /* base for cascaded on-chip IRQs */
|
||||
spinlock_t lock;
|
||||
void __iomem *base;
|
||||
struct sa1111_platform_data *pdata;
|
||||
#ifdef CONFIG_PM
|
||||
void *saved_state;
|
||||
#endif
|
||||
@ -118,6 +121,7 @@ static struct sa1111 *g_sa1111;
|
||||
struct sa1111_dev_info {
|
||||
unsigned long offset;
|
||||
unsigned long skpcr_mask;
|
||||
bool dma;
|
||||
unsigned int devid;
|
||||
unsigned int irq[6];
|
||||
};
|
||||
@ -126,6 +130,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
||||
{
|
||||
.offset = SA1111_USB,
|
||||
.skpcr_mask = SKPCR_UCLKEN,
|
||||
.dma = true,
|
||||
.devid = SA1111_DEVID_USB,
|
||||
.irq = {
|
||||
IRQ_USBPWR,
|
||||
@ -139,6 +144,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
||||
{
|
||||
.offset = 0x0600,
|
||||
.skpcr_mask = SKPCR_I2SCLKEN | SKPCR_L3CLKEN,
|
||||
.dma = true,
|
||||
.devid = SA1111_DEVID_SAC,
|
||||
.irq = {
|
||||
AUDXMTDMADONEA,
|
||||
@ -155,7 +161,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
||||
{
|
||||
.offset = SA1111_KBD,
|
||||
.skpcr_mask = SKPCR_PTCLKEN,
|
||||
.devid = SA1111_DEVID_PS2,
|
||||
.devid = SA1111_DEVID_PS2_KBD,
|
||||
.irq = {
|
||||
IRQ_TPRXINT,
|
||||
IRQ_TPTXINT
|
||||
@ -164,7 +170,7 @@ static struct sa1111_dev_info sa1111_devices[] = {
|
||||
{
|
||||
.offset = SA1111_MSE,
|
||||
.skpcr_mask = SKPCR_PMCLKEN,
|
||||
.devid = SA1111_DEVID_PS2,
|
||||
.devid = SA1111_DEVID_PS2_MSE,
|
||||
.irq = {
|
||||
IRQ_MSRXINT,
|
||||
IRQ_MSTXINT
|
||||
@ -434,16 +440,28 @@ static struct irq_chip sa1111_high_chip = {
|
||||
.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;
|
||||
unsigned int irq;
|
||||
unsigned i, irq;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* We're guaranteed that this region hasn't been taken.
|
||||
*/
|
||||
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 */
|
||||
sa1111_writel(0, irqbase + SA1111_INTEN0);
|
||||
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_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,
|
||||
handle_edge_irq);
|
||||
irq_set_chip_data(irq, sachip);
|
||||
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,
|
||||
handle_edge_irq);
|
||||
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_handler_data(sachip->irq, sachip);
|
||||
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
|
||||
|
||||
#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)
|
||||
{
|
||||
struct sa1111_dev *dev = SA1111_DEV(_dev);
|
||||
|
||||
release_resource(&dev->res);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
@ -624,67 +618,58 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
|
||||
struct sa1111_dev_info *info)
|
||||
{
|
||||
struct sa1111_dev *dev;
|
||||
unsigned i;
|
||||
int ret;
|
||||
|
||||
dev = kzalloc(sizeof(struct sa1111_dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
device_initialize(&dev->dev);
|
||||
dev_set_name(&dev->dev, "%4.4lx", info->offset);
|
||||
dev->devid = info->devid;
|
||||
dev->dev.parent = sachip->dev;
|
||||
dev->dev.bus = &sa1111_bus_type;
|
||||
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.end = dev->res.start + 511;
|
||||
dev->res.name = dev_name(&dev->dev);
|
||||
dev->res.flags = IORESOURCE_MEM;
|
||||
dev->mapbase = sachip->base + info->offset;
|
||||
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);
|
||||
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_set_name(&dev->dev, NULL);
|
||||
kfree(dev);
|
||||
goto out;
|
||||
goto err_resource;
|
||||
}
|
||||
|
||||
ret = device_add(&dev->dev);
|
||||
if (ret)
|
||||
goto err_add;
|
||||
return 0;
|
||||
|
||||
ret = device_register(&dev->dev);
|
||||
if (ret) {
|
||||
release_resource(&dev->res);
|
||||
kfree(dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
#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:
|
||||
err_add:
|
||||
release_resource(&dev->res);
|
||||
err_resource:
|
||||
put_device(&dev->dev);
|
||||
err_alloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -698,16 +683,21 @@ out:
|
||||
* Returns:
|
||||
* %-ENODEV device not found.
|
||||
* %-EBUSY physical address already marked in-use.
|
||||
* %-EINVAL no platform data passed
|
||||
* %0 successful.
|
||||
*/
|
||||
static int __devinit
|
||||
__sa1111_probe(struct device *me, struct resource *mem, int irq)
|
||||
{
|
||||
struct sa1111_platform_data *pd = me->platform_data;
|
||||
struct sa1111 *sachip;
|
||||
unsigned long id;
|
||||
unsigned int has_devs;
|
||||
int i, ret = -ENODEV;
|
||||
|
||||
if (!pd)
|
||||
return -EINVAL;
|
||||
|
||||
sachip = kzalloc(sizeof(struct sa1111), GFP_KERNEL);
|
||||
if (!sachip)
|
||||
return -ENOMEM;
|
||||
@ -727,6 +717,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
||||
sachip->dev = me;
|
||||
dev_set_drvdata(sachip->dev, sachip);
|
||||
|
||||
sachip->pdata = pd;
|
||||
sachip->phys = mem->start;
|
||||
sachip->irq = irq;
|
||||
|
||||
@ -759,6 +750,16 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
||||
*/
|
||||
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
|
||||
{
|
||||
unsigned int val;
|
||||
@ -789,24 +790,14 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
|
||||
}
|
||||
#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;
|
||||
|
||||
has_devs = ~0;
|
||||
if (machine_is_assabet() || machine_is_jornada720() ||
|
||||
machine_is_badge4())
|
||||
has_devs &= ~(1 << 4);
|
||||
else
|
||||
has_devs &= ~(1 << 1);
|
||||
if (pd)
|
||||
has_devs &= ~pd->disable_devs;
|
||||
|
||||
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]);
|
||||
|
||||
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)
|
||||
{
|
||||
device_unregister(dev);
|
||||
struct sa1111_dev *sadev = SA1111_DEV(dev);
|
||||
device_del(&sadev->dev);
|
||||
release_resource(&sadev->res);
|
||||
put_device(&sadev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -846,6 +840,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
|
||||
if (sachip->irq != NO_IRQ) {
|
||||
irq_set_chained_handler(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);
|
||||
}
|
||||
@ -904,6 +899,9 @@ static int sa1111_suspend(struct platform_device *dev, pm_message_t state)
|
||||
save->skpwm0 = sa1111_readl(base + SA1111_SKPWM0);
|
||||
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;
|
||||
save->intpol0 = sa1111_readl(base + SA1111_INTPOL0);
|
||||
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);
|
||||
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);
|
||||
|
||||
spin_unlock_irqrestore(&sachip->lock, flags);
|
||||
|
||||
#ifdef CONFIG_ARCH_SA1100
|
||||
sa1110_mb_disable();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -966,6 +966,11 @@ static int sa1111_resume(struct platform_device *dev)
|
||||
*/
|
||||
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
|
||||
* released spinlock!
|
||||
@ -1053,6 +1058,7 @@ static struct platform_driver sa1111_device_driver = {
|
||||
.resume = sa1111_resume,
|
||||
.driver = {
|
||||
.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
|
||||
* @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);
|
||||
unsigned long flags;
|
||||
unsigned int val;
|
||||
int 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);
|
||||
if (sachip->pdata && sachip->pdata->enable)
|
||||
ret = sachip->pdata->enable(sachip->pdata->data, sadev->devid);
|
||||
|
||||
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);
|
||||
|
||||
@ -1265,6 +1278,9 @@ void sa1111_disable_device(struct sa1111_dev *sadev)
|
||||
val = sa1111_readl(sachip->base + SA1111_SKPCR);
|
||||
sa1111_writel(val & ~sadev->skpcr_mask, sachip->base + SA1111_SKPCR);
|
||||
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);
|
||||
|
||||
@ -1279,7 +1295,7 @@ 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;
|
||||
return dev->devid & drv->devid;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct sa1111_dev *sadev = SA1111_DEV(dev);
|
||||
@ -1333,6 +1357,7 @@ struct bus_type sa1111_bus_type = {
|
||||
.remove = sa1111_bus_remove,
|
||||
.suspend = sa1111_bus_suspend,
|
||||
.resume = sa1111_bus_resume,
|
||||
.shutdown = sa1111_bus_shutdown,
|
||||
};
|
||||
EXPORT_SYMBOL(sa1111_bus_type);
|
||||
|
||||
@ -1349,9 +1374,70 @@ void sa1111_driver_unregister(struct sa1111_driver *driver)
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
platform_driver_register(&sa1111_device_driver);
|
||||
return ret;
|
||||
@ -1360,6 +1446,9 @@ static int __init sa1111_init(void)
|
||||
static void __exit sa1111_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&sa1111_device_driver);
|
||||
#ifdef CONFIG_DMABOUNCE
|
||||
bus_unregister_notifier(&sa1111_bus_type, &sa1111_bus_notifier);
|
||||
#endif
|
||||
bus_unregister(&sa1111_bus_type);
|
||||
}
|
||||
|
||||
|
@ -132,33 +132,9 @@
|
||||
#define SKPCR_DCLKEN (1<<7)
|
||||
#define SKPCR_PWMCLKEN (1<<8)
|
||||
|
||||
/*
|
||||
* USB Host controller
|
||||
*/
|
||||
/* USB Host controller */
|
||||
#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
|
||||
*
|
||||
@ -327,22 +303,6 @@
|
||||
* 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_PADDR (0x000)
|
||||
@ -425,106 +385,30 @@
|
||||
#define SA1111_WAKEPOL0 0x0034
|
||||
#define SA1111_WAKEPOL1 0x0038
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* PS/2 Trackpad and Mouse Interfaces */
|
||||
#define SA1111_KBD 0x0a00
|
||||
#define SA1111_MSE 0x0c00
|
||||
|
||||
/*
|
||||
* These are offsets from the above bases.
|
||||
*/
|
||||
#define SA1111_PS2CR 0x0000
|
||||
#define SA1111_PS2STAT 0x0004
|
||||
#define SA1111_PS2DATA 0x0008
|
||||
#define SA1111_PS2CLKDIV 0x000c
|
||||
#define SA1111_PS2PRECNT 0x0010
|
||||
/* PCMCIA Interface */
|
||||
#define SA1111_PCMCIA 0x1600
|
||||
|
||||
#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;
|
||||
|
||||
#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
|
||||
#define SA1111_DEVID_SBI (1 << 0)
|
||||
#define SA1111_DEVID_SK (1 << 1)
|
||||
#define SA1111_DEVID_USB (1 << 2)
|
||||
#define SA1111_DEVID_SAC (1 << 3)
|
||||
#define SA1111_DEVID_SSP (1 << 4)
|
||||
#define SA1111_DEVID_PS2 (3 << 5)
|
||||
#define SA1111_DEVID_PS2_KBD (1 << 5)
|
||||
#define SA1111_DEVID_PS2_MSE (1 << 6)
|
||||
#define SA1111_DEVID_GPIO (1 << 7)
|
||||
#define SA1111_DEVID_INT (1 << 8)
|
||||
#define SA1111_DEVID_PCMCIA (1 << 9)
|
||||
|
||||
struct sa1111_dev {
|
||||
struct device dev;
|
||||
@ -548,6 +432,7 @@ struct sa1111_driver {
|
||||
int (*remove)(struct sa1111_dev *);
|
||||
int (*suspend)(struct sa1111_dev *, pm_message_t);
|
||||
int (*resume)(struct sa1111_dev *);
|
||||
void (*shutdown)(struct sa1111_dev *);
|
||||
};
|
||||
|
||||
#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)
|
||||
|
||||
/*
|
||||
* 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 *);
|
||||
|
||||
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 {
|
||||
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 */
|
||||
|
@ -30,10 +30,7 @@
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#define IRQ_MASK 0xfe000000 /* read */
|
||||
#define IRQ_MSET 0xfe000000 /* write */
|
||||
#define IRQ_STAT 0xff000000 /* read */
|
||||
#define IRQ_MCLR 0xff000000 /* write */
|
||||
#include "core.h"
|
||||
|
||||
static void ebsa110_mask_irq(struct irq_data *d)
|
||||
{
|
||||
@ -79,22 +76,22 @@ static struct map_desc ebsa110_io_desc[] __initdata = {
|
||||
{ /* IRQ_STAT/IRQ_MCLR */
|
||||
.virtual = IRQ_STAT,
|
||||
.pfn = __phys_to_pfn(TRICK4_PHYS),
|
||||
.length = PGDIR_SIZE,
|
||||
.length = TRICK4_SIZE,
|
||||
.type = MT_DEVICE
|
||||
}, { /* IRQ_MASK/IRQ_MSET */
|
||||
.virtual = IRQ_MASK,
|
||||
.pfn = __phys_to_pfn(TRICK3_PHYS),
|
||||
.length = PGDIR_SIZE,
|
||||
.length = TRICK3_SIZE,
|
||||
.type = MT_DEVICE
|
||||
}, { /* SOFT_BASE */
|
||||
.virtual = SOFT_BASE,
|
||||
.pfn = __phys_to_pfn(TRICK1_PHYS),
|
||||
.length = PGDIR_SIZE,
|
||||
.length = TRICK1_SIZE,
|
||||
.type = MT_DEVICE
|
||||
}, { /* PIT_BASE */
|
||||
.virtual = PIT_BASE,
|
||||
.pfn = __phys_to_pfn(TRICK0_PHYS),
|
||||
.length = PGDIR_SIZE,
|
||||
.length = TRICK0_SIZE,
|
||||
.type = MT_DEVICE
|
||||
},
|
||||
|
||||
|
41
arch/arm/mach-ebsa110/core.h
Normal file
41
arch/arm/mach-ebsa110/core.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 1996-2000 Russell King.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This file contains the core hardware definitions of the EBSA-110.
|
||||
*/
|
||||
#ifndef CORE_H
|
||||
#define CORE_H
|
||||
|
||||
/* Physical addresses/sizes */
|
||||
#define ISAMEM_PHYS 0xe0000000
|
||||
#define ISAMEM_SIZE 0x10000000
|
||||
|
||||
#define ISAIO_PHYS 0xf0000000
|
||||
#define ISAIO_SIZE PGDIR_SIZE
|
||||
|
||||
#define TRICK0_PHYS 0xf2000000
|
||||
#define TRICK0_SIZE PGDIR_SIZE
|
||||
#define TRICK1_PHYS 0xf2400000
|
||||
#define TRICK1_SIZE PGDIR_SIZE
|
||||
#define TRICK2_PHYS 0xf2800000
|
||||
#define TRICK3_PHYS 0xf2c00000
|
||||
#define TRICK3_SIZE PGDIR_SIZE
|
||||
#define TRICK4_PHYS 0xf3000000
|
||||
#define TRICK4_SIZE PGDIR_SIZE
|
||||
#define TRICK5_PHYS 0xf3400000
|
||||
#define TRICK6_PHYS 0xf3800000
|
||||
#define TRICK7_PHYS 0xf3c00000
|
||||
|
||||
/* Virtual addresses */
|
||||
#define PIT_BASE 0xfc000000 /* trick 0 */
|
||||
#define SOFT_BASE 0xfd000000 /* trick 1 */
|
||||
#define IRQ_MASK 0xfe000000 /* trick 3 - read */
|
||||
#define IRQ_MSET 0xfe000000 /* trick 3 - write */
|
||||
#define IRQ_STAT 0xff000000 /* trick 4 - read */
|
||||
#define IRQ_MCLR 0xff000000 /* trick 4 - write */
|
||||
|
||||
#endif
|
@ -12,48 +12,9 @@
|
||||
#ifndef __ASM_ARCH_HARDWARE_H
|
||||
#define __ASM_ARCH_HARDWARE_H
|
||||
|
||||
/*
|
||||
* The EBSA110 has a weird "ISA IO" region:
|
||||
*
|
||||
* Region 0 (addr = 0xf0000000 + io << 2)
|
||||
* --------------------------------------------------------
|
||||
* Physical region IO region
|
||||
* f0000fe0 - f0000ffc 3f8 - 3ff ttyS0
|
||||
* f0000e60 - f0000e64 398 - 399
|
||||
* f0000de0 - f0000dfc 378 - 37f lp0
|
||||
* f0000be0 - f0000bfc 2f8 - 2ff ttyS1
|
||||
*
|
||||
* Region 1 (addr = 0xf0000000 + (io & ~1) << 1 + (io & 1))
|
||||
* --------------------------------------------------------
|
||||
* Physical region IO region
|
||||
* f00014f1 a79 pnp write data
|
||||
* f00007c0 - f00007c1 3e0 - 3e1 pcmcia
|
||||
* f00004f1 279 pnp address
|
||||
* f0000440 - f000046c 220 - 236 eth0
|
||||
* f0000405 203 pnp read data
|
||||
*/
|
||||
|
||||
#define ISAMEM_PHYS 0xe0000000
|
||||
#define ISAMEM_SIZE 0x10000000
|
||||
|
||||
#define ISAIO_PHYS 0xf0000000
|
||||
#define ISAIO_SIZE PGDIR_SIZE
|
||||
|
||||
#define TRICK0_PHYS 0xf2000000
|
||||
#define TRICK1_PHYS 0xf2400000
|
||||
#define TRICK2_PHYS 0xf2800000
|
||||
#define TRICK3_PHYS 0xf2c00000
|
||||
#define TRICK4_PHYS 0xf3000000
|
||||
#define TRICK5_PHYS 0xf3400000
|
||||
#define TRICK6_PHYS 0xf3800000
|
||||
#define TRICK7_PHYS 0xf3c00000
|
||||
|
||||
#define ISAMEM_BASE 0xe0000000
|
||||
#define ISAIO_BASE 0xf0000000
|
||||
|
||||
#define PIT_BASE 0xfc000000
|
||||
#define SOFT_BASE 0xfd000000
|
||||
|
||||
/*
|
||||
* RAM definitions
|
||||
*/
|
||||
|
@ -177,6 +177,26 @@ void writesl(void __iomem *addr, const void *data, int len)
|
||||
}
|
||||
EXPORT_SYMBOL(writesl);
|
||||
|
||||
/*
|
||||
* The EBSA110 has a weird "ISA IO" region:
|
||||
*
|
||||
* Region 0 (addr = 0xf0000000 + io << 2)
|
||||
* --------------------------------------------------------
|
||||
* Physical region IO region
|
||||
* f0000fe0 - f0000ffc 3f8 - 3ff ttyS0
|
||||
* f0000e60 - f0000e64 398 - 399
|
||||
* f0000de0 - f0000dfc 378 - 37f lp0
|
||||
* f0000be0 - f0000bfc 2f8 - 2ff ttyS1
|
||||
*
|
||||
* Region 1 (addr = 0xf0000000 + (io & ~1) << 1 + (io & 1))
|
||||
* --------------------------------------------------------
|
||||
* Physical region IO region
|
||||
* f00014f1 a79 pnp write data
|
||||
* f00007c0 - f00007c1 3e0 - 3e1 pcmcia
|
||||
* f00004f1 279 pnp address
|
||||
* f0000440 - f000046c 220 - 236 eth0
|
||||
* f0000405 203 pnp read data
|
||||
*/
|
||||
#define SUPERIO_PORT(p) \
|
||||
(((p) >> 3) == (0x3f8 >> 3) || \
|
||||
((p) >> 3) == (0x2f8 >> 3) || \
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include <asm/system.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include "core.h"
|
||||
|
||||
static spinlock_t leds_lock;
|
||||
|
||||
static void ebsa110_leds_event(led_event_t ledevt)
|
||||
|
@ -223,6 +223,7 @@ static struct resource sa1111_resources[] = {
|
||||
|
||||
static struct sa1111_platform_data sa1111_info = {
|
||||
.irq_base = LUBBOCK_SA1111_IRQ_BASE,
|
||||
.disable_devs = SA1111_DEVID_SAC,
|
||||
};
|
||||
|
||||
static struct platform_device sa1111_device = {
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
# Common support
|
||||
obj-y := clock.o generic.o irq.o dma.o time.o #nmi-oopser.o
|
||||
obj-y := clock.o generic.o irq.o time.o #nmi-oopser.o
|
||||
obj-m :=
|
||||
obj-n :=
|
||||
obj- :=
|
||||
|
@ -15,14 +15,16 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/mfd/ucb1x00.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/mm.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable-hwdef.h>
|
||||
@ -36,17 +38,18 @@
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <mach/assabet.h>
|
||||
#include <mach/mcp.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
#define ASSABET_BCR_DB1110 \
|
||||
(ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \
|
||||
(ASSABET_BCR_SPK_OFF | \
|
||||
ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \
|
||||
ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \
|
||||
ASSABET_BCR_IRDA_MD0)
|
||||
|
||||
#define ASSABET_BCR_DB1111 \
|
||||
(ASSABET_BCR_SPK_OFF | ASSABET_BCR_QMUTE | \
|
||||
(ASSABET_BCR_SPK_OFF | \
|
||||
ASSABET_BCR_LED_GREEN | ASSABET_BCR_LED_RED | \
|
||||
ASSABET_BCR_RS232EN | ASSABET_BCR_LCD_12RGB | \
|
||||
ASSABET_BCR_CF_BUS_OFF | ASSABET_BCR_STEREO_LB | \
|
||||
@ -69,31 +72,10 @@ void ASSABET_BCR_frob(unsigned int mask, unsigned int val)
|
||||
|
||||
EXPORT_SYMBOL(ASSABET_BCR_frob);
|
||||
|
||||
static void assabet_backlight_power(int on)
|
||||
static void assabet_ucb1x00_reset(enum ucb1x00_reset state)
|
||||
{
|
||||
#ifndef ASSABET_PAL_VIDEO
|
||||
if (on)
|
||||
ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
|
||||
else
|
||||
#endif
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn on/off the backlight. When turning the backlight on,
|
||||
* we wait 500us after turning it on so we don't cause the
|
||||
* supplies to droop when we enable the LCD controller (and
|
||||
* cause a hard reset.)
|
||||
*/
|
||||
static void assabet_lcd_power(int on)
|
||||
{
|
||||
#ifndef ASSABET_PAL_VIDEO
|
||||
if (on) {
|
||||
ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
|
||||
udelay(500);
|
||||
} else
|
||||
#endif
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
|
||||
if (state == UCB_RST_PROBE)
|
||||
ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
|
||||
}
|
||||
|
||||
|
||||
@ -152,15 +134,8 @@ static struct flash_platform_data assabet_flash_data = {
|
||||
};
|
||||
|
||||
static struct resource assabet_flash_resources[] = {
|
||||
{
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = SA1100_CS1_PHYS,
|
||||
.end = SA1100_CS1_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
|
||||
DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M),
|
||||
};
|
||||
|
||||
|
||||
@ -199,18 +174,126 @@ static struct irda_platform_data assabet_irda_data = {
|
||||
.set_speed = assabet_irda_set_speed,
|
||||
};
|
||||
|
||||
static struct ucb1x00_plat_data assabet_ucb1x00_data = {
|
||||
.reset = assabet_ucb1x00_reset,
|
||||
.gpio_base = -1,
|
||||
};
|
||||
|
||||
static struct mcp_plat_data assabet_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
.codec_pdata = &assabet_ucb1x00_data,
|
||||
};
|
||||
|
||||
static void assabet_lcd_set_visual(u32 visual)
|
||||
{
|
||||
u_int is_true_color = visual == FB_VISUAL_TRUECOLOR;
|
||||
|
||||
if (machine_is_assabet()) {
|
||||
#if 1 // phase 4 or newer Assabet's
|
||||
if (is_true_color)
|
||||
ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
|
||||
else
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
|
||||
#else
|
||||
// older Assabet's
|
||||
if (is_true_color)
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
|
||||
else
|
||||
ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ASSABET_PAL_VIDEO
|
||||
static void assabet_lcd_backlight_power(int on)
|
||||
{
|
||||
if (on)
|
||||
ASSABET_BCR_set(ASSABET_BCR_LIGHT_ON);
|
||||
else
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn on/off the backlight. When turning the backlight on, we wait
|
||||
* 500us after turning it on so we don't cause the supplies to droop
|
||||
* when we enable the LCD controller (and cause a hard reset.)
|
||||
*/
|
||||
static void assabet_lcd_power(int on)
|
||||
{
|
||||
if (on) {
|
||||
ASSABET_BCR_set(ASSABET_BCR_LCD_ON);
|
||||
udelay(500);
|
||||
} else
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
* The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually
|
||||
* takes an RGB666 signal, but we provide it with an RGB565 signal
|
||||
* instead (def_rgb_16).
|
||||
*/
|
||||
static struct sa1100fb_mach_info lq039q2ds54_info = {
|
||||
.pixclock = 171521, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 5, .vsync_len = 1,
|
||||
.left_margin = 61, .upper_margin = 3,
|
||||
.right_margin = 9, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
|
||||
.backlight_power = assabet_lcd_backlight_power,
|
||||
.lcd_power = assabet_lcd_power,
|
||||
.set_visual = assabet_lcd_set_visual,
|
||||
};
|
||||
#else
|
||||
static void assabet_pal_backlight_power(int on)
|
||||
{
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LIGHT_ON);
|
||||
}
|
||||
|
||||
static void assabet_pal_power(int on)
|
||||
{
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
|
||||
}
|
||||
|
||||
static struct sa1100fb_mach_info pal_info = {
|
||||
.pixclock = 67797, .bpp = 16,
|
||||
.xres = 640, .yres = 512,
|
||||
|
||||
.hsync_len = 64, .vsync_len = 6,
|
||||
.left_margin = 125, .upper_margin = 70,
|
||||
.right_margin = 115, .lower_margin = 36,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
|
||||
|
||||
.backlight_power = assabet_pal_backlight_power,
|
||||
.lcd_power = assabet_pal_power,
|
||||
.set_visual = assabet_lcd_set_visual,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ASSABET_NEPONSET
|
||||
static struct resource neponset_resources[] = {
|
||||
DEFINE_RES_MEM(0x10000000, 0x08000000),
|
||||
DEFINE_RES_MEM(0x18000000, 0x04000000),
|
||||
DEFINE_RES_MEM(0x40000000, SZ_8K),
|
||||
DEFINE_RES_IRQ(IRQ_GPIO25),
|
||||
};
|
||||
#endif
|
||||
|
||||
static void __init assabet_init(void)
|
||||
{
|
||||
/*
|
||||
* Ensure that the power supply is in "high power" mode.
|
||||
*/
|
||||
GPDR |= GPIO_GPIO16;
|
||||
GPSR = GPIO_GPIO16;
|
||||
GPDR |= GPIO_GPIO16;
|
||||
|
||||
/*
|
||||
* Ensure that these pins are set as outputs and are driving
|
||||
@ -218,8 +301,16 @@ static void __init assabet_init(void)
|
||||
* the WS latch in the CPLD, and we don't float causing
|
||||
* excessive power drain. --rmk
|
||||
*/
|
||||
GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
|
||||
GPCR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
|
||||
GPDR |= GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM;
|
||||
|
||||
/*
|
||||
* Also set GPIO27 as an output; this is used to clock UART3
|
||||
* via the FPGA and as otherwise has no pullups or pulldowns,
|
||||
* so stop it floating.
|
||||
*/
|
||||
GPCR = GPIO_GPIO27;
|
||||
GPDR |= GPIO_GPIO27;
|
||||
|
||||
/*
|
||||
* Set up registers for sleep mode.
|
||||
@ -231,8 +322,7 @@ static void __init assabet_init(void)
|
||||
PPDR |= PPC_TXD3 | PPC_TXD1;
|
||||
PPSR |= PPC_TXD3 | PPC_TXD1;
|
||||
|
||||
sa1100fb_lcd_power = assabet_lcd_power;
|
||||
sa1100fb_backlight_power = assabet_backlight_power;
|
||||
sa11x0_ppc_configure_mcp();
|
||||
|
||||
if (machine_has_neponset()) {
|
||||
/*
|
||||
@ -246,9 +336,17 @@ static void __init assabet_init(void)
|
||||
#ifndef CONFIG_ASSABET_NEPONSET
|
||||
printk( "Warning: Neponset detected but full support "
|
||||
"hasn't been configured in the kernel\n" );
|
||||
#else
|
||||
platform_device_register_simple("neponset", 0,
|
||||
neponset_resources, ARRAY_SIZE(neponset_resources));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef ASSABET_PAL_VIDEO
|
||||
sa11x0_register_lcd(&lq039q2ds54_info);
|
||||
#else
|
||||
sa11x0_register_lcd(&pal_video);
|
||||
#endif
|
||||
sa11x0_register_mtd(&assabet_flash_data, assabet_flash_resources,
|
||||
ARRAY_SIZE(assabet_flash_resources));
|
||||
sa11x0_register_irda(&assabet_irda_data);
|
||||
@ -412,21 +510,8 @@ static void __init assabet_map_io(void)
|
||||
*/
|
||||
Ser1SDCR0 |= SDCR0_SUS;
|
||||
|
||||
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 {
|
||||
if (!machine_has_neponset())
|
||||
sa1100_register_uart_fns(&assabet_port_fns);
|
||||
}
|
||||
|
||||
/*
|
||||
* When Neponset is attached, the first UART should be
|
||||
@ -449,6 +534,7 @@ MACHINE_START(ASSABET, "Intel-Assabet")
|
||||
.atag_offset = 0x100,
|
||||
.fixup = fixup_assabet,
|
||||
.map_io = assabet_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = assabet_init,
|
||||
|
@ -39,20 +39,27 @@
|
||||
#include "generic.h"
|
||||
|
||||
static struct resource sa1111_resources[] = {
|
||||
[0] = {
|
||||
.start = BADGE4_SA1111_BASE,
|
||||
.end = BADGE4_SA1111_BASE + 0x00001fff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = BADGE4_IRQ_GPIO_SA1111,
|
||||
.end = BADGE4_IRQ_GPIO_SA1111,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(BADGE4_SA1111_BASE, 0x2000),
|
||||
[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 = {
|
||||
.irq_base = IRQ_BOARD_END,
|
||||
.disable_devs = SA1111_DEVID_PS2_MSE,
|
||||
.enable = badge4_sa1111_enable,
|
||||
.disable = badge4_sa1111_disable,
|
||||
};
|
||||
|
||||
static u64 sa1111_dmamask = 0xffffffffUL;
|
||||
@ -121,11 +128,8 @@ static struct flash_platform_data badge4_flash_data = {
|
||||
.nr_parts = ARRAY_SIZE(badge4_partitions),
|
||||
};
|
||||
|
||||
static struct resource badge4_flash_resource = {
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_64M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
static struct resource badge4_flash_resource =
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_64M);
|
||||
|
||||
static int five_v_on __initdata = 0;
|
||||
|
||||
@ -269,11 +273,6 @@ static struct map_desc badge4_io_desc[] __initdata = {
|
||||
.pfn = __phys_to_pfn(0x10000000),
|
||||
.length = 0x00100000,
|
||||
.type = MT_DEVICE
|
||||
}, { /* SA-1111 */
|
||||
.virtual = 0xf4000000,
|
||||
.pfn = __phys_to_pfn(0x48000000),
|
||||
.length = 0x00100000,
|
||||
.type = MT_DEVICE
|
||||
}
|
||||
};
|
||||
|
||||
@ -304,6 +303,7 @@ static void __init badge4_map_io(void)
|
||||
MACHINE_START(BADGE4, "Hewlett-Packard Laboratories BadgePAD 4")
|
||||
.atag_offset = 0x100,
|
||||
.map_io = badge4_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
#ifdef CONFIG_SA1111
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
@ -30,14 +29,11 @@
|
||||
|
||||
#include <mach/cerf.h>
|
||||
#include <mach/mcp.h>
|
||||
#include <mach/irqs.h>
|
||||
#include "generic.h"
|
||||
|
||||
static struct resource cerfuart2_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x80030000,
|
||||
.end = 0x8003ffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(0x80030000, SZ_64K),
|
||||
};
|
||||
|
||||
static struct platform_device cerfuart2_device = {
|
||||
@ -87,11 +83,8 @@ static struct flash_platform_data cerf_flash_data = {
|
||||
.nr_parts = ARRAY_SIZE(cerf_partitions),
|
||||
};
|
||||
|
||||
static struct resource cerf_flash_resource = {
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
static struct resource cerf_flash_resource =
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
|
||||
|
||||
static void __init cerf_init_irq(void)
|
||||
{
|
||||
@ -128,6 +121,7 @@ static struct mcp_plat_data cerf_mcp_data = {
|
||||
|
||||
static void __init cerf_init(void)
|
||||
{
|
||||
sa11x0_ppc_configure_mcp();
|
||||
platform_add_devices(cerf_devices, ARRAY_SIZE(cerf_devices));
|
||||
sa11x0_register_mtd(&cerf_flash_data, &cerf_flash_resource, 1);
|
||||
sa11x0_register_mcp(&cerf_mcp_data);
|
||||
@ -136,6 +130,7 @@ static void __init cerf_init(void)
|
||||
MACHINE_START(CERF, "Intrinsyc CerfBoard/CerfCube")
|
||||
/* Maintainer: support@intrinsyc.com */
|
||||
.map_io = cerf_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = cerf_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = cerf_init,
|
||||
|
@ -22,15 +22,17 @@
|
||||
#include <linux/tty.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/ucb1x00.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/pda_power.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/setup.h>
|
||||
#include <mach/collie.h>
|
||||
@ -44,15 +46,12 @@
|
||||
#include <asm/mach/sharpsl_param.h>
|
||||
#include <asm/hardware/locomo.h>
|
||||
#include <mach/mcp.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
static struct resource collie_scoop_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x40800000,
|
||||
.end = 0x40800fff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(0x40800000, SZ_4K),
|
||||
};
|
||||
|
||||
static struct scoop_config collie_scoop_setup = {
|
||||
@ -85,10 +84,14 @@ static struct scoop_pcmcia_config collie_pcmcia_config = {
|
||||
.num_devs = 1,
|
||||
};
|
||||
|
||||
static struct ucb1x00_plat_data collie_ucb1x00_data = {
|
||||
.gpio_base = COLLIE_TC35143_GPIO_BASE,
|
||||
};
|
||||
|
||||
static struct mcp_plat_data collie_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM | MCCR0_ExtClk,
|
||||
.sclk_rate = 9216000,
|
||||
.gpio_base = COLLIE_TC35143_GPIO_BASE,
|
||||
.codec_pdata = &collie_ucb1x00_data,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -221,16 +224,8 @@ device_initcall(collie_uart_init);
|
||||
|
||||
|
||||
static struct resource locomo_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x40000000,
|
||||
.end = 0x40001fff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_GPIO25,
|
||||
.end = IRQ_GPIO25,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(0x40000000, SZ_8K),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_GPIO25),
|
||||
};
|
||||
|
||||
static struct locomo_platform_data locomo_info = {
|
||||
@ -303,11 +298,21 @@ static struct flash_platform_data collie_flash_data = {
|
||||
};
|
||||
|
||||
static struct resource collie_flash_resources[] = {
|
||||
{
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
|
||||
};
|
||||
|
||||
static struct sa1100fb_mach_info collie_lcd_info = {
|
||||
.pixclock = 171521, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 5, .vsync_len = 1,
|
||||
.left_margin = 11, .upper_margin = 2,
|
||||
.right_margin = 30, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
};
|
||||
|
||||
static void __init collie_init(void)
|
||||
@ -341,6 +346,10 @@ static void __init collie_init(void)
|
||||
|
||||
collie_power_resource[0].start = gpio_to_irq(COLLIE_GPIO_AC_IN);
|
||||
collie_power_resource[0].end = gpio_to_irq(COLLIE_GPIO_AC_IN);
|
||||
|
||||
sa11x0_ppc_configure_mcp();
|
||||
|
||||
|
||||
platform_scoop_config = &collie_pcmcia_config;
|
||||
|
||||
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
@ -348,6 +357,7 @@ static void __init collie_init(void)
|
||||
printk(KERN_WARNING "collie: Unable to register LoCoMo device\n");
|
||||
}
|
||||
|
||||
sa11x0_register_lcd(&collie_lcd_info);
|
||||
sa11x0_register_mtd(&collie_flash_data, collie_flash_resources,
|
||||
ARRAY_SIZE(collie_flash_resources));
|
||||
sa11x0_register_mcp(&collie_mcp_data);
|
||||
@ -383,6 +393,7 @@ static void __init collie_map_io(void)
|
||||
|
||||
MACHINE_START(COLLIE, "Sharp-Collie")
|
||||
.map_io = collie_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = collie_init,
|
||||
|
@ -1,348 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-sa1100/dma.c
|
||||
*
|
||||
* Support functions for the SA11x0 internal DMA channels.
|
||||
*
|
||||
* Copyright (C) 2000, 2001 by Nicolas Pitre
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/dma.h>
|
||||
|
||||
|
||||
#undef DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DPRINTK( s, arg... ) printk( "dma<%p>: " s, regs , ##arg )
|
||||
#else
|
||||
#define DPRINTK( x... )
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *device_id; /* device name */
|
||||
u_long device; /* this channel device, 0 if unused*/
|
||||
dma_callback_t callback; /* to call when DMA completes */
|
||||
void *data; /* ... with private data ptr */
|
||||
} sa1100_dma_t;
|
||||
|
||||
static sa1100_dma_t dma_chan[SA1100_DMA_CHANNELS];
|
||||
|
||||
static DEFINE_SPINLOCK(dma_list_lock);
|
||||
|
||||
|
||||
static irqreturn_t dma_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
dma_regs_t *dma_regs = dev_id;
|
||||
sa1100_dma_t *dma = dma_chan + (((u_int)dma_regs >> 5) & 7);
|
||||
int status = dma_regs->RdDCSR;
|
||||
|
||||
if (status & (DCSR_ERROR)) {
|
||||
printk(KERN_CRIT "DMA on \"%s\" caused an error\n", dma->device_id);
|
||||
dma_regs->ClrDCSR = DCSR_ERROR;
|
||||
}
|
||||
|
||||
dma_regs->ClrDCSR = status & (DCSR_DONEA | DCSR_DONEB);
|
||||
if (dma->callback) {
|
||||
if (status & DCSR_DONEA)
|
||||
dma->callback(dma->data);
|
||||
if (status & DCSR_DONEB)
|
||||
dma->callback(dma->data);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sa1100_request_dma - allocate one of the SA11x0's DMA channels
|
||||
* @device: The SA11x0 peripheral targeted by this request
|
||||
* @device_id: An ascii name for the claiming device
|
||||
* @callback: Function to be called when the DMA completes
|
||||
* @data: A cookie passed back to the callback function
|
||||
* @dma_regs: Pointer to the location of the allocated channel's identifier
|
||||
*
|
||||
* This function will search for a free DMA channel and returns the
|
||||
* address of the hardware registers for that channel as the channel
|
||||
* identifier. This identifier is written to the location pointed by
|
||||
* @dma_regs. The list of possible values for @device are listed into
|
||||
* arch/arm/mach-sa1100/include/mach/dma.h as a dma_device_t enum.
|
||||
*
|
||||
* Note that reading from a port and writing to the same port are
|
||||
* actually considered as two different streams requiring separate
|
||||
* DMA registrations.
|
||||
*
|
||||
* The @callback function is called from interrupt context when one
|
||||
* of the two possible DMA buffers in flight has terminated. That
|
||||
* function has to be small and efficient while posponing more complex
|
||||
* processing to a lower priority execution context.
|
||||
*
|
||||
* If no channels are available, or if the desired @device is already in
|
||||
* use by another DMA channel, then an error code is returned. This
|
||||
* function must be called before any other DMA calls.
|
||||
**/
|
||||
|
||||
int sa1100_request_dma (dma_device_t device, const char *device_id,
|
||||
dma_callback_t callback, void *data,
|
||||
dma_regs_t **dma_regs)
|
||||
{
|
||||
sa1100_dma_t *dma = NULL;
|
||||
dma_regs_t *regs;
|
||||
int i, err;
|
||||
|
||||
*dma_regs = NULL;
|
||||
|
||||
err = 0;
|
||||
spin_lock(&dma_list_lock);
|
||||
for (i = 0; i < SA1100_DMA_CHANNELS; i++) {
|
||||
if (dma_chan[i].device == device) {
|
||||
err = -EBUSY;
|
||||
break;
|
||||
} else if (!dma_chan[i].device && !dma) {
|
||||
dma = &dma_chan[i];
|
||||
}
|
||||
}
|
||||
if (!err) {
|
||||
if (dma)
|
||||
dma->device = device;
|
||||
else
|
||||
err = -ENOSR;
|
||||
}
|
||||
spin_unlock(&dma_list_lock);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
i = dma - dma_chan;
|
||||
regs = (dma_regs_t *)&DDAR(i);
|
||||
err = request_irq(IRQ_DMA0 + i, dma_irq_handler, IRQF_DISABLED,
|
||||
device_id, regs);
|
||||
if (err) {
|
||||
printk(KERN_ERR
|
||||
"%s: unable to request IRQ %d for %s\n",
|
||||
__func__, IRQ_DMA0 + i, device_id);
|
||||
dma->device = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
*dma_regs = regs;
|
||||
dma->device_id = device_id;
|
||||
dma->callback = callback;
|
||||
dma->data = data;
|
||||
|
||||
regs->ClrDCSR =
|
||||
(DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
|
||||
DCSR_IE | DCSR_ERROR | DCSR_RUN);
|
||||
regs->DDAR = device;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sa1100_free_dma - free a SA11x0 DMA channel
|
||||
* @regs: identifier for the channel to free
|
||||
*
|
||||
* This clears all activities on a given DMA channel and releases it
|
||||
* for future requests. The @regs identifier is provided by a
|
||||
* successful call to sa1100_request_dma().
|
||||
**/
|
||||
|
||||
void sa1100_free_dma(dma_regs_t *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SA1100_DMA_CHANNELS; i++)
|
||||
if (regs == (dma_regs_t *)&DDAR(i))
|
||||
break;
|
||||
if (i >= SA1100_DMA_CHANNELS) {
|
||||
printk(KERN_ERR "%s: bad DMA identifier\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dma_chan[i].device) {
|
||||
printk(KERN_ERR "%s: Trying to free free DMA\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
regs->ClrDCSR =
|
||||
(DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
|
||||
DCSR_IE | DCSR_ERROR | DCSR_RUN);
|
||||
free_irq(IRQ_DMA0 + i, regs);
|
||||
dma_chan[i].device = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sa1100_start_dma - submit a data buffer for DMA
|
||||
* @regs: identifier for the channel to use
|
||||
* @dma_ptr: buffer physical (or bus) start address
|
||||
* @size: buffer size
|
||||
*
|
||||
* This function hands the given data buffer to the hardware for DMA
|
||||
* access. If another buffer is already in flight then this buffer
|
||||
* will be queued so the DMA engine will switch to it automatically
|
||||
* when the previous one is done. The DMA engine is actually toggling
|
||||
* between two buffers so at most 2 successful calls can be made before
|
||||
* one of them terminates and the callback function is called.
|
||||
*
|
||||
* The @regs identifier is provided by a successful call to
|
||||
* sa1100_request_dma().
|
||||
*
|
||||
* The @size must not be larger than %MAX_DMA_SIZE. If a given buffer
|
||||
* is larger than that then it's the caller's responsibility to split
|
||||
* it into smaller chunks and submit them separately. If this is the
|
||||
* case then a @size of %CUT_DMA_SIZE is recommended to avoid ending
|
||||
* up with too small chunks. The callback function can be used to chain
|
||||
* submissions of buffer chunks.
|
||||
*
|
||||
* Error return values:
|
||||
* %-EOVERFLOW: Given buffer size is too big.
|
||||
* %-EBUSY: Both DMA buffers are already in use.
|
||||
* %-EAGAIN: Both buffers were busy but one of them just completed
|
||||
* but the interrupt handler has to execute first.
|
||||
*
|
||||
* This function returs 0 on success.
|
||||
**/
|
||||
|
||||
int sa1100_start_dma(dma_regs_t *regs, dma_addr_t dma_ptr, u_int size)
|
||||
{
|
||||
unsigned long flags;
|
||||
u_long status;
|
||||
int ret;
|
||||
|
||||
if (dma_ptr & 3)
|
||||
printk(KERN_WARNING "DMA: unaligned start address (0x%08lx)\n",
|
||||
(unsigned long)dma_ptr);
|
||||
|
||||
if (size > MAX_DMA_SIZE)
|
||||
return -EOVERFLOW;
|
||||
|
||||
local_irq_save(flags);
|
||||
status = regs->RdDCSR;
|
||||
|
||||
/* If both DMA buffers are started, there's nothing else we can do. */
|
||||
if ((status & (DCSR_STRTA | DCSR_STRTB)) == (DCSR_STRTA | DCSR_STRTB)) {
|
||||
DPRINTK("start: st %#x busy\n", status);
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (((status & DCSR_BIU) && (status & DCSR_STRTB)) ||
|
||||
(!(status & DCSR_BIU) && !(status & DCSR_STRTA))) {
|
||||
if (status & DCSR_DONEA) {
|
||||
/* give a chance for the interrupt to be processed */
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
regs->DBSA = dma_ptr;
|
||||
regs->DBTA = size;
|
||||
regs->SetDCSR = DCSR_STRTA | DCSR_IE | DCSR_RUN;
|
||||
DPRINTK("start a=%#x s=%d on A\n", dma_ptr, size);
|
||||
} else {
|
||||
if (status & DCSR_DONEB) {
|
||||
/* give a chance for the interrupt to be processed */
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
regs->DBSB = dma_ptr;
|
||||
regs->DBTB = size;
|
||||
regs->SetDCSR = DCSR_STRTB | DCSR_IE | DCSR_RUN;
|
||||
DPRINTK("start a=%#x s=%d on B\n", dma_ptr, size);
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
local_irq_restore(flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sa1100_get_dma_pos - return current DMA position
|
||||
* @regs: identifier for the channel to use
|
||||
*
|
||||
* This function returns the current physical (or bus) address for the
|
||||
* given DMA channel. If the channel is running i.e. not in a stopped
|
||||
* state then the caller must disable interrupts prior calling this
|
||||
* function and process the returned value before re-enabling them to
|
||||
* prevent races with the completion interrupt handler and the callback
|
||||
* function. The validation of the returned value is the caller's
|
||||
* responsibility as well -- the hardware seems to return out of range
|
||||
* values when the DMA engine completes a buffer.
|
||||
*
|
||||
* The @regs identifier is provided by a successful call to
|
||||
* sa1100_request_dma().
|
||||
**/
|
||||
|
||||
dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs)
|
||||
{
|
||||
int status;
|
||||
|
||||
/*
|
||||
* We must determine whether buffer A or B is active.
|
||||
* Two possibilities: either we are in the middle of
|
||||
* a buffer, or the DMA controller just switched to the
|
||||
* next toggle but the interrupt hasn't been serviced yet.
|
||||
* The former case is straight forward. In the later case,
|
||||
* we'll do like if DMA is just at the end of the previous
|
||||
* toggle since all registers haven't been reset yet.
|
||||
* This goes around the edge case and since we're always
|
||||
* a little behind anyways it shouldn't make a big difference.
|
||||
* If DMA has been stopped prior calling this then the
|
||||
* position is exact.
|
||||
*/
|
||||
status = regs->RdDCSR;
|
||||
if ((!(status & DCSR_BIU) && (status & DCSR_STRTA)) ||
|
||||
( (status & DCSR_BIU) && !(status & DCSR_STRTB)))
|
||||
return regs->DBSA;
|
||||
else
|
||||
return regs->DBSB;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sa1100_reset_dma - reset a DMA channel
|
||||
* @regs: identifier for the channel to use
|
||||
*
|
||||
* This function resets and reconfigure the given DMA channel. This is
|
||||
* particularly useful after a sleep/wakeup event.
|
||||
*
|
||||
* The @regs identifier is provided by a successful call to
|
||||
* sa1100_request_dma().
|
||||
**/
|
||||
|
||||
void sa1100_reset_dma(dma_regs_t *regs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SA1100_DMA_CHANNELS; i++)
|
||||
if (regs == (dma_regs_t *)&DDAR(i))
|
||||
break;
|
||||
if (i >= SA1100_DMA_CHANNELS) {
|
||||
printk(KERN_ERR "%s: bad DMA identifier\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
regs->ClrDCSR =
|
||||
(DCSR_DONEA | DCSR_DONEB | DCSR_STRTA | DCSR_STRTB |
|
||||
DCSR_IE | DCSR_ERROR | DCSR_RUN);
|
||||
regs->DDAR = dma_chan[i].device;
|
||||
}
|
||||
|
||||
|
||||
EXPORT_SYMBOL(sa1100_request_dma);
|
||||
EXPORT_SYMBOL(sa1100_free_dma);
|
||||
EXPORT_SYMBOL(sa1100_start_dma);
|
||||
EXPORT_SYMBOL(sa1100_get_dma_pos);
|
||||
EXPORT_SYMBOL(sa1100_reset_dma);
|
||||
|
@ -14,18 +14,23 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/flash.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
unsigned int reset_status;
|
||||
@ -149,16 +154,8 @@ static void sa11x0_register_device(struct platform_device *dev, void *data)
|
||||
|
||||
|
||||
static struct resource sa11x0udc_resources[] = {
|
||||
[0] = {
|
||||
.start = __PREG(Ser0UDCCR),
|
||||
.end = __PREG(Ser0UDCCR) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser0UDC,
|
||||
.end = IRQ_Ser0UDC,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(__PREG(Ser0UDCCR), SZ_64K),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_Ser0UDC),
|
||||
};
|
||||
|
||||
static u64 sa11x0udc_dma_mask = 0xffffffffUL;
|
||||
@ -175,16 +172,8 @@ static struct platform_device sa11x0udc_device = {
|
||||
};
|
||||
|
||||
static struct resource sa11x0uart1_resources[] = {
|
||||
[0] = {
|
||||
.start = __PREG(Ser1UTCR0),
|
||||
.end = __PREG(Ser1UTCR0) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser1UART,
|
||||
.end = IRQ_Ser1UART,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(__PREG(Ser1UTCR0), SZ_64K),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_Ser1UART),
|
||||
};
|
||||
|
||||
static struct platform_device sa11x0uart1_device = {
|
||||
@ -195,16 +184,8 @@ static struct platform_device sa11x0uart1_device = {
|
||||
};
|
||||
|
||||
static struct resource sa11x0uart3_resources[] = {
|
||||
[0] = {
|
||||
.start = __PREG(Ser3UTCR0),
|
||||
.end = __PREG(Ser3UTCR0) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser3UART,
|
||||
.end = IRQ_Ser3UART,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(__PREG(Ser3UTCR0), SZ_64K),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_Ser3UART),
|
||||
};
|
||||
|
||||
static struct platform_device sa11x0uart3_device = {
|
||||
@ -215,16 +196,9 @@ static struct platform_device sa11x0uart3_device = {
|
||||
};
|
||||
|
||||
static struct resource sa11x0mcp_resources[] = {
|
||||
[0] = {
|
||||
.start = __PREG(Ser4MCCR0),
|
||||
.end = __PREG(Ser4MCCR0) + 0xffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser4MCP,
|
||||
.end = IRQ_Ser4MCP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(__PREG(Ser4MCCR0), SZ_64K),
|
||||
[1] = DEFINE_RES_MEM(__PREG(Ser4MCCR1), 4),
|
||||
[2] = DEFINE_RES_IRQ(IRQ_Ser4MCP),
|
||||
};
|
||||
|
||||
static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
|
||||
@ -240,22 +214,24 @@ static struct platform_device sa11x0mcp_device = {
|
||||
.resource = sa11x0mcp_resources,
|
||||
};
|
||||
|
||||
void __init sa11x0_ppc_configure_mcp(void)
|
||||
{
|
||||
/* Setup the PPC unit for the MCP */
|
||||
PPDR &= ~PPC_RXD4;
|
||||
PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
|
||||
PSDR |= PPC_RXD4;
|
||||
PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
|
||||
PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
|
||||
}
|
||||
|
||||
void sa11x0_register_mcp(struct mcp_plat_data *data)
|
||||
{
|
||||
sa11x0_register_device(&sa11x0mcp_device, data);
|
||||
}
|
||||
|
||||
static struct resource sa11x0ssp_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x80070000,
|
||||
.end = 0x8007ffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_Ser4SSP,
|
||||
.end = IRQ_Ser4SSP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(0x80070000, SZ_64K),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_Ser4SSP),
|
||||
};
|
||||
|
||||
static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
|
||||
@ -272,16 +248,8 @@ static struct platform_device sa11x0ssp_device = {
|
||||
};
|
||||
|
||||
static struct resource sa11x0fb_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xb0100000,
|
||||
.end = 0xb010ffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_LCD,
|
||||
.end = IRQ_LCD,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(0xb0100000, SZ_64K),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_LCD),
|
||||
};
|
||||
|
||||
static struct platform_device sa11x0fb_device = {
|
||||
@ -294,6 +262,11 @@ static struct platform_device sa11x0fb_device = {
|
||||
.resource = sa11x0fb_resources,
|
||||
};
|
||||
|
||||
void sa11x0_register_lcd(struct sa1100fb_mach_info *inf)
|
||||
{
|
||||
sa11x0_register_device(&sa11x0fb_device, inf);
|
||||
}
|
||||
|
||||
static struct platform_device sa11x0pcmcia_device = {
|
||||
.name = "sa11x0-pcmcia",
|
||||
.id = -1,
|
||||
@ -314,23 +287,10 @@ void sa11x0_register_mtd(struct flash_platform_data *flash,
|
||||
}
|
||||
|
||||
static struct resource sa11x0ir_resources[] = {
|
||||
{
|
||||
.start = __PREG(Ser2UTCR0),
|
||||
.end = __PREG(Ser2UTCR0) + 0x24 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = __PREG(Ser2HSCR0),
|
||||
.end = __PREG(Ser2HSCR0) + 0x1c - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = __PREG(Ser2HSCR2),
|
||||
.end = __PREG(Ser2HSCR2) + 0x04 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = IRQ_Ser2ICP,
|
||||
.end = IRQ_Ser2ICP,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
}
|
||||
DEFINE_RES_MEM(__PREG(Ser2UTCR0), 0x24),
|
||||
DEFINE_RES_MEM(__PREG(Ser2HSCR0), 0x1c),
|
||||
DEFINE_RES_MEM(__PREG(Ser2HSCR2), 0x04),
|
||||
DEFINE_RES_IRQ(IRQ_Ser2ICP),
|
||||
};
|
||||
|
||||
static struct platform_device sa11x0ir_device = {
|
||||
@ -350,14 +310,37 @@ static struct platform_device sa11x0rtc_device = {
|
||||
.id = -1,
|
||||
};
|
||||
|
||||
static struct resource sa11x0dma_resources[] = {
|
||||
DEFINE_RES_MEM(DMA_PHYS, DMA_SIZE),
|
||||
DEFINE_RES_IRQ(IRQ_DMA0),
|
||||
DEFINE_RES_IRQ(IRQ_DMA1),
|
||||
DEFINE_RES_IRQ(IRQ_DMA2),
|
||||
DEFINE_RES_IRQ(IRQ_DMA3),
|
||||
DEFINE_RES_IRQ(IRQ_DMA4),
|
||||
DEFINE_RES_IRQ(IRQ_DMA5),
|
||||
};
|
||||
|
||||
static u64 sa11x0dma_dma_mask = DMA_BIT_MASK(32);
|
||||
|
||||
static struct platform_device sa11x0dma_device = {
|
||||
.name = "sa11x0-dma",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &sa11x0dma_dma_mask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(sa11x0dma_resources),
|
||||
.resource = sa11x0dma_resources,
|
||||
};
|
||||
|
||||
static struct platform_device *sa11x0_devices[] __initdata = {
|
||||
&sa11x0udc_device,
|
||||
&sa11x0uart1_device,
|
||||
&sa11x0uart3_device,
|
||||
&sa11x0ssp_device,
|
||||
&sa11x0pcmcia_device,
|
||||
&sa11x0fb_device,
|
||||
&sa11x0rtc_device,
|
||||
&sa11x0dma_device,
|
||||
};
|
||||
|
||||
static int __init sa1100_init(void)
|
||||
@ -368,12 +351,6 @@ static int __init sa1100_init(void)
|
||||
|
||||
arch_initcall(sa1100_init);
|
||||
|
||||
void (*sa1100fb_backlight_power)(int on);
|
||||
void (*sa1100fb_lcd_power)(int on);
|
||||
|
||||
EXPORT_SYMBOL(sa1100fb_backlight_power);
|
||||
EXPORT_SYMBOL(sa1100fb_lcd_power);
|
||||
|
||||
|
||||
/*
|
||||
* Common I/O mapping:
|
||||
@ -428,7 +405,7 @@ void __init sa1100_map_io(void)
|
||||
* the MBGNT signal false to ensure the SA1111 doesn't own the
|
||||
* SDRAM bus.
|
||||
*/
|
||||
void __init sa1110_mb_disable(void)
|
||||
void sa1110_mb_disable(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@ -447,7 +424,7 @@ void __init sa1110_mb_disable(void)
|
||||
* If the system is going to use the SA-1111 DMA engines, set up
|
||||
* the memory bus request/grant pins.
|
||||
*/
|
||||
void __devinit sa1110_mb_enable(void)
|
||||
void sa1110_mb_enable(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -16,9 +16,6 @@ extern void sa11x0_restart(char, const char *);
|
||||
mi->bank[__nr].start = (__start), \
|
||||
mi->bank[__nr].size = (__size)
|
||||
|
||||
extern void (*sa1100fb_backlight_power)(int on);
|
||||
extern void (*sa1100fb_lcd_power)(int on);
|
||||
|
||||
extern void sa1110_mb_enable(void);
|
||||
extern void sa1110_mb_disable(void);
|
||||
|
||||
@ -39,4 +36,8 @@ struct irda_platform_data;
|
||||
void sa11x0_register_irda(struct irda_platform_data *irda);
|
||||
|
||||
struct mcp_plat_data;
|
||||
void sa11x0_ppc_configure_mcp(void);
|
||||
void sa11x0_register_mcp(struct mcp_plat_data *data);
|
||||
|
||||
struct sa1100fb_mach_info;
|
||||
void sa11x0_register_lcd(struct sa1100fb_mach_info *inf);
|
||||
|
@ -14,11 +14,14 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/irda.h>
|
||||
|
||||
#include <mach/h3xxx.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -36,13 +39,28 @@ static void h3100_lcd_power(int enable)
|
||||
}
|
||||
}
|
||||
|
||||
static struct sa1100fb_mach_info h3100_lcd_info = {
|
||||
.pixclock = 406977, .bpp = 4,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 26, .vsync_len = 41,
|
||||
.left_margin = 4, .upper_margin = 0,
|
||||
.right_margin = 4, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
.cmap_greyscale = 1,
|
||||
.cmap_inverse = 1,
|
||||
|
||||
.lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
|
||||
.lcd_power = h3100_lcd_power,
|
||||
};
|
||||
|
||||
static void __init h3100_map_io(void)
|
||||
{
|
||||
h3xxx_map_io();
|
||||
|
||||
sa1100fb_lcd_power = h3100_lcd_power;
|
||||
|
||||
/* Older bootldrs put GPIO2-9 in alternate mode on the
|
||||
assumption that they are used for video */
|
||||
GAFR &= ~0x000001fb;
|
||||
@ -80,12 +98,15 @@ static void __init h3100_mach_init(void)
|
||||
{
|
||||
h3xxx_init_gpio(h3100_default_gpio, ARRAY_SIZE(h3100_default_gpio));
|
||||
h3xxx_mach_init();
|
||||
|
||||
sa11x0_register_lcd(&h3100_lcd_info);
|
||||
sa11x0_register_irda(&h3100_irda_data);
|
||||
}
|
||||
|
||||
MACHINE_START(H3100, "Compaq iPAQ H3100")
|
||||
.atag_offset = 0x100,
|
||||
.map_io = h3100_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = h3100_mach_init,
|
||||
|
@ -14,11 +14,14 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/irda.h>
|
||||
|
||||
#include <mach/h3xxx.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -56,11 +59,35 @@ err2: gpio_free(H3XXX_EGPIO_LCD_ON);
|
||||
err1: return;
|
||||
}
|
||||
|
||||
static const struct sa1100fb_rgb h3600_rgb_16 = {
|
||||
.red = { .offset = 12, .length = 4, },
|
||||
.green = { .offset = 7, .length = 4, },
|
||||
.blue = { .offset = 1, .length = 4, },
|
||||
.transp = { .offset = 0, .length = 0, },
|
||||
};
|
||||
|
||||
static struct sa1100fb_mach_info h3600_lcd_info = {
|
||||
.pixclock = 174757, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 3, .vsync_len = 3,
|
||||
.left_margin = 12, .upper_margin = 10,
|
||||
.right_margin = 17, .lower_margin = 1,
|
||||
|
||||
.cmap_static = 1,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
|
||||
.rgb[RGB_16] = &h3600_rgb_16,
|
||||
|
||||
.lcd_power = h3600_lcd_power,
|
||||
};
|
||||
|
||||
|
||||
static void __init h3600_map_io(void)
|
||||
{
|
||||
h3xxx_map_io();
|
||||
|
||||
sa1100fb_lcd_power = h3600_lcd_power;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -121,12 +148,15 @@ static void __init h3600_mach_init(void)
|
||||
{
|
||||
h3xxx_init_gpio(h3600_default_gpio, ARRAY_SIZE(h3600_default_gpio));
|
||||
h3xxx_mach_init();
|
||||
|
||||
sa11x0_register_lcd(&h3600_lcd_info);
|
||||
sa11x0_register_irda(&h3600_irda_data);
|
||||
}
|
||||
|
||||
MACHINE_START(H3600, "Compaq iPAQ H3600")
|
||||
.atag_offset = 0x100,
|
||||
.map_io = h3600_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = h3600_mach_init,
|
||||
|
@ -109,11 +109,8 @@ static struct flash_platform_data h3xxx_flash_data = {
|
||||
.nr_parts = ARRAY_SIZE(h3xxx_partitions),
|
||||
};
|
||||
|
||||
static struct resource h3xxx_flash_resource = {
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
static struct resource h3xxx_flash_resource =
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
|
||||
|
||||
|
||||
/*
|
||||
@ -186,11 +183,7 @@ static struct sa1100_port_fns h3xxx_port_fns __initdata = {
|
||||
*/
|
||||
|
||||
static struct resource egpio_resources[] = {
|
||||
[0] = {
|
||||
.start = H3600_EGPIO_PHYS,
|
||||
.end = H3600_EGPIO_PHYS + 0x4 - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(H3600_EGPIO_PHYS, 0x4),
|
||||
};
|
||||
|
||||
static struct htc_egpio_chip egpio_chips[] = {
|
||||
|
@ -22,12 +22,10 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/flash.h>
|
||||
@ -35,6 +33,9 @@
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
/**********************************************************************
|
||||
@ -179,11 +180,8 @@ static struct flash_platform_data hackkit_flash_data = {
|
||||
.nr_parts = ARRAY_SIZE(hackkit_partitions),
|
||||
};
|
||||
|
||||
static struct resource hackkit_flash_resource = {
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
static struct resource hackkit_flash_resource =
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
|
||||
|
||||
static void __init hackkit_init(void)
|
||||
{
|
||||
@ -197,6 +195,7 @@ static void __init hackkit_init(void)
|
||||
MACHINE_START(HACKKIT, "HackKit Cpu Board")
|
||||
.atag_offset = 0x100,
|
||||
.map_io = hackkit_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = hackkit_init,
|
||||
|
@ -1590,224 +1590,9 @@
|
||||
|
||||
/*
|
||||
* Direct Memory Access (DMA) control registers
|
||||
*
|
||||
* Registers
|
||||
* DDAR0 Direct Memory Access (DMA) Device Address Register
|
||||
* channel 0 (read/write).
|
||||
* DCSR0 Direct Memory Access (DMA) Control and Status
|
||||
* Register channel 0 (read/write).
|
||||
* DBSA0 Direct Memory Access (DMA) Buffer Start address
|
||||
* register A channel 0 (read/write).
|
||||
* DBTA0 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register A channel 0 (read/write).
|
||||
* DBSB0 Direct Memory Access (DMA) Buffer Start address
|
||||
* register B channel 0 (read/write).
|
||||
* DBTB0 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register B channel 0 (read/write).
|
||||
*
|
||||
* DDAR1 Direct Memory Access (DMA) Device Address Register
|
||||
* channel 1 (read/write).
|
||||
* DCSR1 Direct Memory Access (DMA) Control and Status
|
||||
* Register channel 1 (read/write).
|
||||
* DBSA1 Direct Memory Access (DMA) Buffer Start address
|
||||
* register A channel 1 (read/write).
|
||||
* DBTA1 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register A channel 1 (read/write).
|
||||
* DBSB1 Direct Memory Access (DMA) Buffer Start address
|
||||
* register B channel 1 (read/write).
|
||||
* DBTB1 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register B channel 1 (read/write).
|
||||
*
|
||||
* DDAR2 Direct Memory Access (DMA) Device Address Register
|
||||
* channel 2 (read/write).
|
||||
* DCSR2 Direct Memory Access (DMA) Control and Status
|
||||
* Register channel 2 (read/write).
|
||||
* DBSA2 Direct Memory Access (DMA) Buffer Start address
|
||||
* register A channel 2 (read/write).
|
||||
* DBTA2 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register A channel 2 (read/write).
|
||||
* DBSB2 Direct Memory Access (DMA) Buffer Start address
|
||||
* register B channel 2 (read/write).
|
||||
* DBTB2 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register B channel 2 (read/write).
|
||||
*
|
||||
* DDAR3 Direct Memory Access (DMA) Device Address Register
|
||||
* channel 3 (read/write).
|
||||
* DCSR3 Direct Memory Access (DMA) Control and Status
|
||||
* Register channel 3 (read/write).
|
||||
* DBSA3 Direct Memory Access (DMA) Buffer Start address
|
||||
* register A channel 3 (read/write).
|
||||
* DBTA3 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register A channel 3 (read/write).
|
||||
* DBSB3 Direct Memory Access (DMA) Buffer Start address
|
||||
* register B channel 3 (read/write).
|
||||
* DBTB3 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register B channel 3 (read/write).
|
||||
*
|
||||
* DDAR4 Direct Memory Access (DMA) Device Address Register
|
||||
* channel 4 (read/write).
|
||||
* DCSR4 Direct Memory Access (DMA) Control and Status
|
||||
* Register channel 4 (read/write).
|
||||
* DBSA4 Direct Memory Access (DMA) Buffer Start address
|
||||
* register A channel 4 (read/write).
|
||||
* DBTA4 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register A channel 4 (read/write).
|
||||
* DBSB4 Direct Memory Access (DMA) Buffer Start address
|
||||
* register B channel 4 (read/write).
|
||||
* DBTB4 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register B channel 4 (read/write).
|
||||
*
|
||||
* DDAR5 Direct Memory Access (DMA) Device Address Register
|
||||
* channel 5 (read/write).
|
||||
* DCSR5 Direct Memory Access (DMA) Control and Status
|
||||
* Register channel 5 (read/write).
|
||||
* DBSA5 Direct Memory Access (DMA) Buffer Start address
|
||||
* register A channel 5 (read/write).
|
||||
* DBTA5 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register A channel 5 (read/write).
|
||||
* DBSB5 Direct Memory Access (DMA) Buffer Start address
|
||||
* register B channel 5 (read/write).
|
||||
* DBTB5 Direct Memory Access (DMA) Buffer Transfer count
|
||||
* register B channel 5 (read/write).
|
||||
*/
|
||||
|
||||
#define DMASp 0x00000020 /* DMA control reg. Space [byte] */
|
||||
|
||||
#define DDAR(Nb) __REG(0xB0000000 + (Nb)*DMASp) /* DMA Device Address Reg. channel [0..5] */
|
||||
#define SetDCSR(Nb) __REG(0xB0000004 + (Nb)*DMASp) /* Set DMA Control & Status Reg. channel [0..5] (write) */
|
||||
#define ClrDCSR(Nb) __REG(0xB0000008 + (Nb)*DMASp) /* Clear DMA Control & Status Reg. channel [0..5] (write) */
|
||||
#define RdDCSR(Nb) __REG(0xB000000C + (Nb)*DMASp) /* Read DMA Control & Status Reg. channel [0..5] (read) */
|
||||
#define DBSA(Nb) __REG(0xB0000010 + (Nb)*DMASp) /* DMA Buffer Start address reg. A channel [0..5] */
|
||||
#define DBTA(Nb) __REG(0xB0000014 + (Nb)*DMASp) /* DMA Buffer Transfer count reg. A channel [0..5] */
|
||||
#define DBSB(Nb) __REG(0xB0000018 + (Nb)*DMASp) /* DMA Buffer Start address reg. B channel [0..5] */
|
||||
#define DBTB(Nb) __REG(0xB000001C + (Nb)*DMASp) /* DMA Buffer Transfer count reg. B channel [0..5] */
|
||||
|
||||
#define DDAR_RW 0x00000001 /* device data Read/Write */
|
||||
#define DDAR_DevWr (DDAR_RW*0) /* Device data Write */
|
||||
/* (memory -> device) */
|
||||
#define DDAR_DevRd (DDAR_RW*1) /* Device data Read */
|
||||
/* (device -> memory) */
|
||||
#define DDAR_E 0x00000002 /* big/little Endian device */
|
||||
#define DDAR_LtlEnd (DDAR_E*0) /* Little Endian device */
|
||||
#define DDAR_BigEnd (DDAR_E*1) /* Big Endian device */
|
||||
#define DDAR_BS 0x00000004 /* device Burst Size */
|
||||
#define DDAR_Brst4 (DDAR_BS*0) /* Burst-of-4 device */
|
||||
#define DDAR_Brst8 (DDAR_BS*1) /* Burst-of-8 device */
|
||||
#define DDAR_DW 0x00000008 /* device Data Width */
|
||||
#define DDAR_8BitDev (DDAR_DW*0) /* 8-Bit Device */
|
||||
#define DDAR_16BitDev (DDAR_DW*1) /* 16-Bit Device */
|
||||
#define DDAR_DS Fld (4, 4) /* Device Select */
|
||||
#define DDAR_Ser0UDCTr /* Ser. port 0 UDC Transmit */ \
|
||||
(0x0 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser0UDCRc /* Ser. port 0 UDC Receive */ \
|
||||
(0x1 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser1SDLCTr /* Ser. port 1 SDLC Transmit */ \
|
||||
(0x2 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser1SDLCRc /* Ser. port 1 SDLC Receive */ \
|
||||
(0x3 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser1UARTTr /* Ser. port 1 UART Transmit */ \
|
||||
(0x4 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser1UARTRc /* Ser. port 1 UART Receive */ \
|
||||
(0x5 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser2ICPTr /* Ser. port 2 ICP Transmit */ \
|
||||
(0x6 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser2ICPRc /* Ser. port 2 ICP Receive */ \
|
||||
(0x7 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser3UARTTr /* Ser. port 3 UART Transmit */ \
|
||||
(0x8 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser3UARTRc /* Ser. port 3 UART Receive */ \
|
||||
(0x9 << FShft (DDAR_DS))
|
||||
#define DDAR_Ser4MCP0Tr /* Ser. port 4 MCP 0 Transmit */ \
|
||||
/* (audio) */ \
|
||||
(0xA << FShft (DDAR_DS))
|
||||
#define DDAR_Ser4MCP0Rc /* Ser. port 4 MCP 0 Receive */ \
|
||||
/* (audio) */ \
|
||||
(0xB << FShft (DDAR_DS))
|
||||
#define DDAR_Ser4MCP1Tr /* Ser. port 4 MCP 1 Transmit */ \
|
||||
/* (telecom) */ \
|
||||
(0xC << FShft (DDAR_DS))
|
||||
#define DDAR_Ser4MCP1Rc /* Ser. port 4 MCP 1 Receive */ \
|
||||
/* (telecom) */ \
|
||||
(0xD << FShft (DDAR_DS))
|
||||
#define DDAR_Ser4SSPTr /* Ser. port 4 SSP Transmit */ \
|
||||
(0xE << FShft (DDAR_DS))
|
||||
#define DDAR_Ser4SSPRc /* Ser. port 4 SSP Receive */ \
|
||||
(0xF << FShft (DDAR_DS))
|
||||
#define DDAR_DA Fld (24, 8) /* Device Address */
|
||||
#define DDAR_DevAdd(Add) /* Device Address */ \
|
||||
(((Add) & 0xF0000000) | \
|
||||
(((Add) & 0X003FFFFC) << (FShft (DDAR_DA) - 2)))
|
||||
#define DDAR_Ser0UDCWr /* Ser. port 0 UDC Write */ \
|
||||
(DDAR_DevWr + DDAR_Brst8 + DDAR_8BitDev + \
|
||||
DDAR_Ser0UDCTr + DDAR_DevAdd (__PREG(Ser0UDCDR)))
|
||||
#define DDAR_Ser0UDCRd /* Ser. port 0 UDC Read */ \
|
||||
(DDAR_DevRd + DDAR_Brst8 + DDAR_8BitDev + \
|
||||
DDAR_Ser0UDCRc + DDAR_DevAdd (__PREG(Ser0UDCDR)))
|
||||
#define DDAR_Ser1UARTWr /* Ser. port 1 UART Write */ \
|
||||
(DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser1UARTTr + DDAR_DevAdd (__PREG(Ser1UTDR)))
|
||||
#define DDAR_Ser1UARTRd /* Ser. port 1 UART Read */ \
|
||||
(DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser1UARTRc + DDAR_DevAdd (__PREG(Ser1UTDR)))
|
||||
#define DDAR_Ser1SDLCWr /* Ser. port 1 SDLC Write */ \
|
||||
(DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser1SDLCTr + DDAR_DevAdd (__PREG(Ser1SDDR)))
|
||||
#define DDAR_Ser1SDLCRd /* Ser. port 1 SDLC Read */ \
|
||||
(DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser1SDLCRc + DDAR_DevAdd (__PREG(Ser1SDDR)))
|
||||
#define DDAR_Ser2UARTWr /* Ser. port 2 UART Write */ \
|
||||
(DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser2ICPTr + DDAR_DevAdd (__PREG(Ser2UTDR)))
|
||||
#define DDAR_Ser2UARTRd /* Ser. port 2 UART Read */ \
|
||||
(DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser2ICPRc + DDAR_DevAdd (__PREG(Ser2UTDR)))
|
||||
#define DDAR_Ser2HSSPWr /* Ser. port 2 HSSP Write */ \
|
||||
(DDAR_DevWr + DDAR_Brst8 + DDAR_8BitDev + \
|
||||
DDAR_Ser2ICPTr + DDAR_DevAdd (__PREG(Ser2HSDR)))
|
||||
#define DDAR_Ser2HSSPRd /* Ser. port 2 HSSP Read */ \
|
||||
(DDAR_DevRd + DDAR_Brst8 + DDAR_8BitDev + \
|
||||
DDAR_Ser2ICPRc + DDAR_DevAdd (__PREG(Ser2HSDR)))
|
||||
#define DDAR_Ser3UARTWr /* Ser. port 3 UART Write */ \
|
||||
(DDAR_DevWr + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser3UARTTr + DDAR_DevAdd (__PREG(Ser3UTDR)))
|
||||
#define DDAR_Ser3UARTRd /* Ser. port 3 UART Read */ \
|
||||
(DDAR_DevRd + DDAR_Brst4 + DDAR_8BitDev + \
|
||||
DDAR_Ser3UARTRc + DDAR_DevAdd (__PREG(Ser3UTDR)))
|
||||
#define DDAR_Ser4MCP0Wr /* Ser. port 4 MCP 0 Write (audio) */ \
|
||||
(DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \
|
||||
DDAR_Ser4MCP0Tr + DDAR_DevAdd (__PREG(Ser4MCDR0)))
|
||||
#define DDAR_Ser4MCP0Rd /* Ser. port 4 MCP 0 Read (audio) */ \
|
||||
(DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \
|
||||
DDAR_Ser4MCP0Rc + DDAR_DevAdd (__PREG(Ser4MCDR0)))
|
||||
#define DDAR_Ser4MCP1Wr /* Ser. port 4 MCP 1 Write */ \
|
||||
/* (telecom) */ \
|
||||
(DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \
|
||||
DDAR_Ser4MCP1Tr + DDAR_DevAdd (__PREG(Ser4MCDR1)))
|
||||
#define DDAR_Ser4MCP1Rd /* Ser. port 4 MCP 1 Read */ \
|
||||
/* (telecom) */ \
|
||||
(DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \
|
||||
DDAR_Ser4MCP1Rc + DDAR_DevAdd (__PREG(Ser4MCDR1)))
|
||||
#define DDAR_Ser4SSPWr /* Ser. port 4 SSP Write (16 bits) */ \
|
||||
(DDAR_DevWr + DDAR_Brst4 + DDAR_16BitDev + \
|
||||
DDAR_Ser4SSPTr + DDAR_DevAdd (__PREG(Ser4SSDR)))
|
||||
#define DDAR_Ser4SSPRd /* Ser. port 4 SSP Read (16 bits) */ \
|
||||
(DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \
|
||||
DDAR_Ser4SSPRc + DDAR_DevAdd (__PREG(Ser4SSDR)))
|
||||
|
||||
#define DCSR_RUN 0x00000001 /* DMA running */
|
||||
#define DCSR_IE 0x00000002 /* DMA Interrupt Enable */
|
||||
#define DCSR_ERROR 0x00000004 /* DMA ERROR */
|
||||
#define DCSR_DONEA 0x00000008 /* DONE DMA transfer buffer A */
|
||||
#define DCSR_STRTA 0x00000010 /* STaRTed DMA transfer buffer A */
|
||||
#define DCSR_DONEB 0x00000020 /* DONE DMA transfer buffer B */
|
||||
#define DCSR_STRTB 0x00000040 /* STaRTed DMA transfer buffer B */
|
||||
#define DCSR_BIU 0x00000080 /* DMA Buffer In Use */
|
||||
#define DCSR_BufA (DCSR_BIU*0) /* DMA Buffer A in use */
|
||||
#define DCSR_BufB (DCSR_BIU*1) /* DMA Buffer B in use */
|
||||
|
||||
#define DBT_TC Fld (13, 0) /* Transfer Count */
|
||||
#define DBTA_TCA DBT_TC /* Transfer Count buffer A */
|
||||
#define DBTB_TCB DBT_TC /* Transfer Count buffer B */
|
||||
#define DMA_SIZE (6 * 0x20)
|
||||
#define DMA_PHYS 0xb0000000
|
||||
|
||||
|
||||
/*
|
||||
@ -1903,16 +1688,6 @@
|
||||
#define LCD_Int100_0A 0xF /* LCD Intensity = 100.0% = 1 */
|
||||
/* (Alternative) */
|
||||
|
||||
#define LCCR0 __REG(0xB0100000) /* LCD Control Reg. 0 */
|
||||
#define LCSR __REG(0xB0100004) /* LCD Status Reg. */
|
||||
#define DBAR1 __REG(0xB0100010) /* LCD DMA Base Address Reg. channel 1 */
|
||||
#define DCAR1 __REG(0xB0100014) /* LCD DMA Current Address Reg. channel 1 */
|
||||
#define DBAR2 __REG(0xB0100018) /* LCD DMA Base Address Reg. channel 2 */
|
||||
#define DCAR2 __REG(0xB010001C) /* LCD DMA Current Address Reg. channel 2 */
|
||||
#define LCCR1 __REG(0xB0100020) /* LCD Control Reg. 1 */
|
||||
#define LCCR2 __REG(0xB0100024) /* LCD Control Reg. 2 */
|
||||
#define LCCR3 __REG(0xB0100028) /* LCD Control Reg. 3 */
|
||||
|
||||
#define LCCR0_LEN 0x00000001 /* LCD ENable */
|
||||
#define LCCR0_CMS 0x00000002 /* Color/Monochrome display Select */
|
||||
#define LCCR0_Color (LCCR0_CMS*0) /* Color display */
|
||||
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* arch/arm/mach-sa1100/include/mach/dma.h
|
||||
*
|
||||
* Generic SA1100 DMA support
|
||||
*
|
||||
* Copyright (C) 2000 Nicolas Pitre
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_DMA_H
|
||||
#define __ASM_ARCH_DMA_H
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
|
||||
/*
|
||||
* The SA1100 has six internal DMA channels.
|
||||
*/
|
||||
#define SA1100_DMA_CHANNELS 6
|
||||
|
||||
/*
|
||||
* Maximum physical DMA buffer size
|
||||
*/
|
||||
#define MAX_DMA_SIZE 0x1fff
|
||||
#define CUT_DMA_SIZE 0x1000
|
||||
|
||||
/*
|
||||
* All possible SA1100 devices a DMA channel can be attached to.
|
||||
*/
|
||||
typedef enum {
|
||||
DMA_Ser0UDCWr = DDAR_Ser0UDCWr, /* Ser. port 0 UDC Write */
|
||||
DMA_Ser0UDCRd = DDAR_Ser0UDCRd, /* Ser. port 0 UDC Read */
|
||||
DMA_Ser1UARTWr = DDAR_Ser1UARTWr, /* Ser. port 1 UART Write */
|
||||
DMA_Ser1UARTRd = DDAR_Ser1UARTRd, /* Ser. port 1 UART Read */
|
||||
DMA_Ser1SDLCWr = DDAR_Ser1SDLCWr, /* Ser. port 1 SDLC Write */
|
||||
DMA_Ser1SDLCRd = DDAR_Ser1SDLCRd, /* Ser. port 1 SDLC Read */
|
||||
DMA_Ser2UARTWr = DDAR_Ser2UARTWr, /* Ser. port 2 UART Write */
|
||||
DMA_Ser2UARTRd = DDAR_Ser2UARTRd, /* Ser. port 2 UART Read */
|
||||
DMA_Ser2HSSPWr = DDAR_Ser2HSSPWr, /* Ser. port 2 HSSP Write */
|
||||
DMA_Ser2HSSPRd = DDAR_Ser2HSSPRd, /* Ser. port 2 HSSP Read */
|
||||
DMA_Ser3UARTWr = DDAR_Ser3UARTWr, /* Ser. port 3 UART Write */
|
||||
DMA_Ser3UARTRd = DDAR_Ser3UARTRd, /* Ser. port 3 UART Read */
|
||||
DMA_Ser4MCP0Wr = DDAR_Ser4MCP0Wr, /* Ser. port 4 MCP 0 Write (audio) */
|
||||
DMA_Ser4MCP0Rd = DDAR_Ser4MCP0Rd, /* Ser. port 4 MCP 0 Read (audio) */
|
||||
DMA_Ser4MCP1Wr = DDAR_Ser4MCP1Wr, /* Ser. port 4 MCP 1 Write */
|
||||
DMA_Ser4MCP1Rd = DDAR_Ser4MCP1Rd, /* Ser. port 4 MCP 1 Read */
|
||||
DMA_Ser4SSPWr = DDAR_Ser4SSPWr, /* Ser. port 4 SSP Write (16 bits) */
|
||||
DMA_Ser4SSPRd = DDAR_Ser4SSPRd /* Ser. port 4 SSP Read (16 bits) */
|
||||
} dma_device_t;
|
||||
|
||||
typedef struct {
|
||||
volatile u_long DDAR;
|
||||
volatile u_long SetDCSR;
|
||||
volatile u_long ClrDCSR;
|
||||
volatile u_long RdDCSR;
|
||||
volatile dma_addr_t DBSA;
|
||||
volatile u_long DBTA;
|
||||
volatile dma_addr_t DBSB;
|
||||
volatile u_long DBTB;
|
||||
} dma_regs_t;
|
||||
|
||||
typedef void (*dma_callback_t)(void *data);
|
||||
|
||||
/*
|
||||
* DMA function prototypes
|
||||
*/
|
||||
|
||||
extern int sa1100_request_dma( dma_device_t device, const char *device_id,
|
||||
dma_callback_t callback, void *data,
|
||||
dma_regs_t **regs );
|
||||
extern void sa1100_free_dma( dma_regs_t *regs );
|
||||
extern int sa1100_start_dma( dma_regs_t *regs, dma_addr_t dma_ptr, u_int size );
|
||||
extern dma_addr_t sa1100_get_dma_pos(dma_regs_t *regs);
|
||||
extern void sa1100_reset_dma(dma_regs_t *regs);
|
||||
|
||||
/**
|
||||
* sa1100_stop_dma - stop DMA in progress
|
||||
* @regs: identifier for the channel to use
|
||||
*
|
||||
* This stops DMA without clearing buffer pointers. Unlike
|
||||
* sa1100_clear_dma() this allows subsequent use of sa1100_resume_dma()
|
||||
* or sa1100_get_dma_pos().
|
||||
*
|
||||
* The @regs identifier is provided by a successful call to
|
||||
* sa1100_request_dma().
|
||||
**/
|
||||
|
||||
#define sa1100_stop_dma(regs) ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN)
|
||||
|
||||
/**
|
||||
* sa1100_resume_dma - resume DMA on a stopped channel
|
||||
* @regs: identifier for the channel to use
|
||||
*
|
||||
* This resumes DMA on a channel previously stopped with
|
||||
* sa1100_stop_dma().
|
||||
*
|
||||
* The @regs identifier is provided by a successful call to
|
||||
* sa1100_request_dma().
|
||||
**/
|
||||
|
||||
#define sa1100_resume_dma(regs) ((regs)->SetDCSR = DCSR_IE|DCSR_RUN)
|
||||
|
||||
/**
|
||||
* sa1100_clear_dma - clear DMA pointers
|
||||
* @regs: identifier for the channel to use
|
||||
*
|
||||
* This clear any DMA state so the DMA engine is ready to restart
|
||||
* with new buffers through sa1100_start_dma(). Any buffers in flight
|
||||
* are discarded.
|
||||
*
|
||||
* The @regs identifier is provided by a successful call to
|
||||
* sa1100_request_dma().
|
||||
**/
|
||||
|
||||
#define sa1100_clear_dma(regs) ((regs)->ClrDCSR = DCSR_IE|DCSR_RUN|DCSR_STRTA|DCSR_STRTB)
|
||||
|
||||
#endif /* _ASM_ARCH_DMA_H */
|
@ -71,22 +71,19 @@
|
||||
/*
|
||||
* Figure out the MAX IRQ number.
|
||||
*
|
||||
* If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
|
||||
* If we have an LoCoMo, the max IRQ is IRQ_BOARD_START + 4
|
||||
* Otherwise, we have the standard IRQs only.
|
||||
* Neponset, SA1111 and UCB1x00 are sparse IRQ aware, so can dynamically
|
||||
* allocate their IRQs above NR_IRQS.
|
||||
*
|
||||
* LoCoMo has 4 additional IRQs, but is not sparse IRQ aware, and so has
|
||||
* to be included in the NR_IRQS calculation.
|
||||
*/
|
||||
#ifdef CONFIG_SA1111
|
||||
#define NR_IRQS (IRQ_BOARD_END + 55)
|
||||
#elif defined(CONFIG_SHARP_LOCOMO)
|
||||
#define NR_IRQS (IRQ_BOARD_START + 4)
|
||||
#ifdef CONFIG_SHARP_LOCOMO
|
||||
#define NR_IRQS_LOCOMO 4
|
||||
#else
|
||||
#define NR_IRQS (IRQ_BOARD_START)
|
||||
#define NR_IRQS_LOCOMO 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Board specific IRQs. Define them here.
|
||||
* Do not surround them with ifdefs.
|
||||
*/
|
||||
#define IRQ_NEPONSET_SMC9196 (IRQ_BOARD_START + 0)
|
||||
#define IRQ_NEPONSET_USAR (IRQ_BOARD_START + 1)
|
||||
#define IRQ_NEPONSET_SA1111 (IRQ_BOARD_START + 2)
|
||||
#ifndef NR_IRQS
|
||||
#define NR_IRQS (IRQ_BOARD_START + NR_IRQS_LOCOMO)
|
||||
#endif
|
||||
#define SA1100_NR_IRQS (IRQ_BOARD_START + NR_IRQS_LOCOMO)
|
||||
|
@ -16,7 +16,7 @@ struct mcp_plat_data {
|
||||
u32 mccr0;
|
||||
u32 mccr1;
|
||||
unsigned int sclk_rate;
|
||||
int gpio_base;
|
||||
void *codec_pdata;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -15,54 +15,6 @@
|
||||
/*
|
||||
* Neponset definitions:
|
||||
*/
|
||||
|
||||
#define NEPONSET_CPLD_BASE (0x10000000)
|
||||
#define Nep_p2v( x ) ((x) - NEPONSET_CPLD_BASE + 0xf3000000)
|
||||
#define Nep_v2p( x ) ((x) - 0xf3000000 + NEPONSET_CPLD_BASE)
|
||||
|
||||
#define _IRR 0x10000024 /* Interrupt Reason Register */
|
||||
#define _AUD_CTL 0x100000c0 /* Audio controls (RW) */
|
||||
#define _MDM_CTL_0 0x100000b0 /* Modem control 0 (RW) */
|
||||
#define _MDM_CTL_1 0x100000b4 /* Modem control 1 (RW) */
|
||||
#define _NCR_0 0x100000a0 /* Control Register (RW) */
|
||||
#define _KP_X_OUT 0x10000090 /* Keypad row write (RW) */
|
||||
#define _KP_Y_IN 0x10000080 /* Keypad column read (RO) */
|
||||
#define _SWPK 0x10000020 /* Switch pack (RO) */
|
||||
#define _WHOAMI 0x10000000 /* System ID Register (RO) */
|
||||
|
||||
#define _LEDS 0x10000010 /* LEDs [31:0] (WO) */
|
||||
|
||||
#define IRR (*((volatile u_char *) Nep_p2v(_IRR)))
|
||||
#define AUD_CTL (*((volatile u_char *) Nep_p2v(_AUD_CTL)))
|
||||
#define MDM_CTL_0 (*((volatile u_char *) Nep_p2v(_MDM_CTL_0)))
|
||||
#define MDM_CTL_1 (*((volatile u_char *) Nep_p2v(_MDM_CTL_1)))
|
||||
#define NCR_0 (*((volatile u_char *) Nep_p2v(_NCR_0)))
|
||||
#define KP_X_OUT (*((volatile u_char *) Nep_p2v(_KP_X_OUT)))
|
||||
#define KP_Y_IN (*((volatile u_char *) Nep_p2v(_KP_Y_IN)))
|
||||
#define SWPK (*((volatile u_char *) Nep_p2v(_SWPK)))
|
||||
#define WHOAMI (*((volatile u_char *) Nep_p2v(_WHOAMI)))
|
||||
|
||||
#define LEDS (*((volatile Word *) Nep_p2v(_LEDS)))
|
||||
|
||||
#define IRR_ETHERNET (1<<0)
|
||||
#define IRR_USAR (1<<1)
|
||||
#define IRR_SA1111 (1<<2)
|
||||
|
||||
#define AUD_SEL_1341 (1<<0)
|
||||
#define AUD_MUTE_1341 (1<<1)
|
||||
|
||||
#define MDM_CTL0_RTS1 (1 << 0)
|
||||
#define MDM_CTL0_DTR1 (1 << 1)
|
||||
#define MDM_CTL0_RTS2 (1 << 2)
|
||||
#define MDM_CTL0_DTR2 (1 << 3)
|
||||
|
||||
#define MDM_CTL1_CTS1 (1 << 0)
|
||||
#define MDM_CTL1_DSR1 (1 << 1)
|
||||
#define MDM_CTL1_DCD1 (1 << 2)
|
||||
#define MDM_CTL1_CTS2 (1 << 3)
|
||||
#define MDM_CTL1_DSR2 (1 << 4)
|
||||
#define MDM_CTL1_DCD2 (1 << 5)
|
||||
|
||||
#define NCR_GP01_OFF (1<<0)
|
||||
#define NCR_TP_PWR_EN (1<<1)
|
||||
#define NCR_MS_PWR_EN (1<<2)
|
||||
@ -71,4 +23,8 @@
|
||||
#define NCR_A0VPP (1<<5)
|
||||
#define NCR_A1VPP (1<<6)
|
||||
|
||||
void neponset_ncr_frob(unsigned int, unsigned int);
|
||||
#define neponset_ncr_set(v) neponset_ncr_frob(0, v)
|
||||
#define neponset_ncr_clear(v) neponset_ncr_frob(v, 0)
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@
|
||||
#define SHANNON_GPIO_U3_RTS GPIO_GPIO (19) /* ?? */
|
||||
#define SHANNON_GPIO_U3_CTS GPIO_GPIO (20) /* ?? */
|
||||
#define SHANNON_GPIO_SENSE_12V GPIO_GPIO (21) /* Input, 12v flash unprotect detected */
|
||||
#define SHANNON_GPIO_DISP_EN GPIO_GPIO (22) /* out */
|
||||
#define SHANNON_GPIO_DISP_EN 22 /* out */
|
||||
/* XXX GPIO 23 unaccounted for */
|
||||
#define SHANNON_GPIO_EJECT_0 GPIO_GPIO (24) /* in */
|
||||
#define SHANNON_IRQ_GPIO_EJECT_0 IRQ_GPIO24
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
#include "generic.h"
|
||||
@ -221,11 +222,8 @@ static struct irq_chip sa1100_normal_chip = {
|
||||
.irq_set_wake = sa1100_set_wake,
|
||||
};
|
||||
|
||||
static struct resource irq_resource = {
|
||||
.name = "irqs",
|
||||
.start = 0x90050000,
|
||||
.end = 0x9005ffff,
|
||||
};
|
||||
static struct resource irq_resource =
|
||||
DEFINE_RES_MEM_NAMED(0x90050000, SZ_64K, "irqs");
|
||||
|
||||
static struct sa1100irq_state {
|
||||
unsigned int saved;
|
||||
|
@ -23,9 +23,7 @@
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <video/s1d13xxxfb.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/hardware/sa1111.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/setup.h>
|
||||
@ -34,6 +32,9 @@
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
/*
|
||||
@ -46,7 +47,7 @@
|
||||
|
||||
/* memory space (line 52 of HP's doc) */
|
||||
#define SA1111REGSTART 0x40000000
|
||||
#define SA1111REGLEN 0x00001fff
|
||||
#define SA1111REGLEN 0x00002000
|
||||
#define EPSONREGSTART 0x48000000
|
||||
#define EPSONREGLEN 0x00100000
|
||||
#define EPSONFBSTART 0x48200000
|
||||
@ -174,16 +175,8 @@ static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
|
||||
};
|
||||
|
||||
static struct resource s1d13xxxfb_resources[] = {
|
||||
[0] = {
|
||||
.start = EPSONFBSTART,
|
||||
.end = EPSONFBSTART + EPSONFBLEN,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = EPSONREGSTART,
|
||||
.end = EPSONREGSTART + EPSONREGLEN,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
[0] = DEFINE_RES_MEM(EPSONFBSTART, EPSONFBLEN),
|
||||
[1] = DEFINE_RES_MEM(EPSONREGSTART, EPSONREGLEN),
|
||||
};
|
||||
|
||||
static struct platform_device s1d13xxxfb_device = {
|
||||
@ -197,20 +190,12 @@ static struct platform_device s1d13xxxfb_device = {
|
||||
};
|
||||
|
||||
static struct resource sa1111_resources[] = {
|
||||
[0] = {
|
||||
.start = SA1111REGSTART,
|
||||
.end = SA1111REGSTART + SA1111REGLEN,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_GPIO1,
|
||||
.end = IRQ_GPIO1,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(SA1111REGSTART, SA1111REGLEN),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_GPIO1),
|
||||
};
|
||||
|
||||
static struct sa1111_platform_data sa1111_info = {
|
||||
.irq_base = IRQ_BOARD_END,
|
||||
.disable_devs = SA1111_DEVID_PS2_MSE,
|
||||
};
|
||||
|
||||
static u64 sa1111_dmamask = 0xffffffffUL;
|
||||
@ -284,11 +269,6 @@ static struct map_desc jornada720_io_desc[] __initdata = {
|
||||
.pfn = __phys_to_pfn(EPSONFBSTART),
|
||||
.length = EPSONFBLEN,
|
||||
.type = MT_DEVICE
|
||||
}, { /* SA-1111 */
|
||||
.virtual = 0xf4000000,
|
||||
.pfn = __phys_to_pfn(SA1111REGSTART),
|
||||
.length = SA1111REGLEN,
|
||||
.type = MT_DEVICE
|
||||
}
|
||||
};
|
||||
|
||||
@ -352,11 +332,8 @@ static struct flash_platform_data jornada720_flash_data = {
|
||||
.nr_parts = ARRAY_SIZE(jornada720_partitions),
|
||||
};
|
||||
|
||||
static struct resource jornada720_flash_resource = {
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
static struct resource jornada720_flash_resource =
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M);
|
||||
|
||||
static void __init jornada720_mach_init(void)
|
||||
{
|
||||
@ -367,6 +344,7 @@ MACHINE_START(JORNADA720, "HP Jornada 720")
|
||||
/* Maintainer: Kristoffer Ericson <Kristoffer.Ericson@gmail.com> */
|
||||
.atag_offset = 0x100,
|
||||
.map_io = jornada720_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = jornada720_mach_init,
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/tty.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mach-types.h>
|
||||
@ -15,6 +17,7 @@
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <mach/mcp.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -26,8 +29,86 @@ static struct mcp_plat_data lart_mcp_data = {
|
||||
.sclk_rate = 11981000,
|
||||
};
|
||||
|
||||
#ifdef LART_GREY_LCD
|
||||
static struct sa1100fb_mach_info lart_grey_info = {
|
||||
.pixclock = 150000, .bpp = 4,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 1, .vsync_len = 1,
|
||||
.left_margin = 4, .upper_margin = 0,
|
||||
.right_margin = 2, .lower_margin = 0,
|
||||
|
||||
.cmap_greyscale = 1,
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
#ifdef LART_COLOR_LCD
|
||||
static struct sa1100fb_mach_info lart_color_info = {
|
||||
.pixclock = 150000, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 2, .vsync_len = 3,
|
||||
.left_margin = 69, .upper_margin = 14,
|
||||
.right_margin = 8, .lower_margin = 4,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
#ifdef LART_VIDEO_OUT
|
||||
static struct sa1100fb_mach_info lart_video_info = {
|
||||
.pixclock = 39721, .bpp = 16,
|
||||
.xres = 640, .yres = 480,
|
||||
|
||||
.hsync_len = 95, .vsync_len = 2,
|
||||
.left_margin = 40, .upper_margin = 32,
|
||||
.right_margin = 24, .lower_margin = 11,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LART_KIT01_LCD
|
||||
static struct sa1100fb_mach_info lart_kit01_info = {
|
||||
.pixclock = 63291, .bpp = 16,
|
||||
.xres = 640, .yres = 480,
|
||||
|
||||
.hsync_len = 64, .vsync_len = 3,
|
||||
.left_margin = 122, .upper_margin = 45,
|
||||
.right_margin = 10, .lower_margin = 10,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg
|
||||
};
|
||||
#endif
|
||||
|
||||
static void __init lart_init(void)
|
||||
{
|
||||
struct sa1100fb_mach_info *inf = NULL;
|
||||
|
||||
#ifdef LART_GREY_LCD
|
||||
inf = &lart_grey_info;
|
||||
#endif
|
||||
#ifdef LART_COLOR_LCD
|
||||
inf = &lart_color_info;
|
||||
#endif
|
||||
#ifdef LART_VIDEO_OUT
|
||||
inf = &lart_video_info;
|
||||
#endif
|
||||
#ifdef LART_KIT01_LCD
|
||||
inf = &lart_kit01_info;
|
||||
#endif
|
||||
|
||||
if (inf)
|
||||
sa11x0_register_lcd(inf);
|
||||
|
||||
sa11x0_ppc_configure_mcp();
|
||||
sa11x0_register_mcp(&lart_mcp_data);
|
||||
}
|
||||
|
||||
@ -63,6 +144,7 @@ static void __init lart_map_io(void)
|
||||
MACHINE_START(LART, "LART")
|
||||
.atag_offset = 0x100,
|
||||
.map_io = lart_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.init_machine = lart_init,
|
||||
.timer = &sa1100_timer,
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/nanoengine.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -58,15 +59,8 @@ static struct flash_platform_data nanoengine_flash_data = {
|
||||
};
|
||||
|
||||
static struct resource nanoengine_flash_resources[] = {
|
||||
{
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = SA1100_CS1_PHYS,
|
||||
.end = SA1100_CS1_PHYS + SZ_32M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_32M),
|
||||
DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_32M),
|
||||
};
|
||||
|
||||
static struct map_desc nanoengine_io_desc[] __initdata = {
|
||||
@ -114,6 +108,7 @@ static void __init nanoengine_init(void)
|
||||
MACHINE_START(NANOENGINE, "BSE nanoEngine")
|
||||
.atag_offset = 0x100,
|
||||
.map_io = nanoengine_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = nanoengine_init,
|
||||
|
@ -1,89 +1,104 @@
|
||||
/*
|
||||
* linux/arch/arm/mach-sa1100/neponset.c
|
||||
*
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <mach/assabet.h>
|
||||
#include <mach/neponset.h>
|
||||
#include <asm/hardware/sa1111.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
/*
|
||||
* Install handler for Neponset IRQ. Note that we have to loop here
|
||||
* since the ETHERNET and USAR IRQs are level based, and we need to
|
||||
* ensure that the IRQ signal is deasserted before returning. This
|
||||
* is rather unfortunate.
|
||||
*/
|
||||
static void
|
||||
neponset_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/assabet.h>
|
||||
#include <mach/neponset.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#define NEP_IRQ_SMC91X 0
|
||||
#define NEP_IRQ_USAR 1
|
||||
#define NEP_IRQ_SA1111 2
|
||||
#define NEP_IRQ_NR 3
|
||||
|
||||
#define WHOAMI 0x00
|
||||
#define LEDS 0x10
|
||||
#define SWPK 0x20
|
||||
#define IRR 0x24
|
||||
#define KP_Y_IN 0x80
|
||||
#define KP_X_OUT 0x90
|
||||
#define NCR_0 0xa0
|
||||
#define MDM_CTL_0 0xb0
|
||||
#define MDM_CTL_1 0xb4
|
||||
#define AUD_CTL 0xc0
|
||||
|
||||
#define IRR_ETHERNET (1 << 0)
|
||||
#define IRR_USAR (1 << 1)
|
||||
#define IRR_SA1111 (1 << 2)
|
||||
|
||||
#define MDM_CTL0_RTS1 (1 << 0)
|
||||
#define MDM_CTL0_DTR1 (1 << 1)
|
||||
#define MDM_CTL0_RTS2 (1 << 2)
|
||||
#define MDM_CTL0_DTR2 (1 << 3)
|
||||
|
||||
#define MDM_CTL1_CTS1 (1 << 0)
|
||||
#define MDM_CTL1_DSR1 (1 << 1)
|
||||
#define MDM_CTL1_DCD1 (1 << 2)
|
||||
#define MDM_CTL1_CTS2 (1 << 3)
|
||||
#define MDM_CTL1_DSR2 (1 << 4)
|
||||
#define MDM_CTL1_DCD2 (1 << 5)
|
||||
|
||||
#define AUD_SEL_1341 (1 << 0)
|
||||
#define AUD_MUTE_1341 (1 << 1)
|
||||
|
||||
extern void sa1110_mb_disable(void);
|
||||
|
||||
struct neponset_drvdata {
|
||||
void __iomem *base;
|
||||
struct platform_device *sa1111;
|
||||
struct platform_device *smc91x;
|
||||
unsigned irq_base;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
u32 ncr0;
|
||||
u32 mdm_ctl_0;
|
||||
#endif
|
||||
};
|
||||
|
||||
static void __iomem *nep_base;
|
||||
|
||||
void neponset_ncr_frob(unsigned int mask, unsigned int val)
|
||||
{
|
||||
unsigned int irr;
|
||||
void __iomem *base = nep_base;
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* Acknowledge the parent IRQ.
|
||||
*/
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
if (base) {
|
||||
unsigned long flags;
|
||||
unsigned v;
|
||||
|
||||
/*
|
||||
* Read the interrupt reason register. Let's have all
|
||||
* active IRQ bits high. Note: there is a typo in the
|
||||
* Neponset user's guide for the SA1111 IRR level.
|
||||
*/
|
||||
irr = IRR ^ (IRR_ETHERNET | IRR_USAR);
|
||||
|
||||
if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Since there is no individual mask, we have to
|
||||
* mask the parent IRQ. This is safe, since we'll
|
||||
* recheck the register for any pending IRQs.
|
||||
*/
|
||||
if (irr & (IRR_ETHERNET | IRR_USAR)) {
|
||||
desc->irq_data.chip->irq_mask(&desc->irq_data);
|
||||
|
||||
/*
|
||||
* Ack the interrupt now to prevent re-entering
|
||||
* this neponset handler. Again, this is safe
|
||||
* since we'll check the IRR register prior to
|
||||
* leaving.
|
||||
*/
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
|
||||
if (irr & IRR_ETHERNET) {
|
||||
generic_handle_irq(IRQ_NEPONSET_SMC9196);
|
||||
}
|
||||
|
||||
if (irr & IRR_USAR) {
|
||||
generic_handle_irq(IRQ_NEPONSET_USAR);
|
||||
}
|
||||
|
||||
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
||||
}
|
||||
|
||||
if (irr & IRR_SA1111) {
|
||||
generic_handle_irq(IRQ_NEPONSET_SA1111);
|
||||
}
|
||||
local_irq_save(flags);
|
||||
v = readb_relaxed(base + NCR_0);
|
||||
writeb_relaxed((v & ~mask) | val, base + NCR_0);
|
||||
local_irq_restore(flags);
|
||||
} else {
|
||||
WARN(1, "nep_base unset\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
|
||||
{
|
||||
u_int mdm_ctl0 = MDM_CTL_0;
|
||||
void __iomem *base = nep_base;
|
||||
u_int mdm_ctl0;
|
||||
|
||||
if (!base)
|
||||
return;
|
||||
|
||||
mdm_ctl0 = readb_relaxed(base + MDM_CTL_0);
|
||||
if (port->mapbase == _Ser1UTCR0) {
|
||||
if (mctrl & TIOCM_RTS)
|
||||
mdm_ctl0 &= ~MDM_CTL0_RTS2;
|
||||
@ -106,14 +121,19 @@ static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
|
||||
mdm_ctl0 |= MDM_CTL0_DTR1;
|
||||
}
|
||||
|
||||
MDM_CTL_0 = mdm_ctl0;
|
||||
writeb_relaxed(mdm_ctl0, base + MDM_CTL_0);
|
||||
}
|
||||
|
||||
static u_int neponset_get_mctrl(struct uart_port *port)
|
||||
{
|
||||
void __iomem *base = nep_base;
|
||||
u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
|
||||
u_int mdm_ctl1 = MDM_CTL_1;
|
||||
u_int mdm_ctl1;
|
||||
|
||||
if (!base)
|
||||
return ret;
|
||||
|
||||
mdm_ctl1 = readb_relaxed(base + MDM_CTL_1);
|
||||
if (port->mapbase == _Ser1UTCR0) {
|
||||
if (mdm_ctl1 & MDM_CTL1_DCD2)
|
||||
ret &= ~TIOCM_CD;
|
||||
@ -138,209 +158,278 @@ static struct sa1100_port_fns neponset_port_fns __devinitdata = {
|
||||
.get_mctrl = neponset_get_mctrl,
|
||||
};
|
||||
|
||||
/*
|
||||
* Install handler for Neponset IRQ. Note that we have to loop here
|
||||
* since the ETHERNET and USAR IRQs are level based, and we need to
|
||||
* ensure that the IRQ signal is deasserted before returning. This
|
||||
* is rather unfortunate.
|
||||
*/
|
||||
static void neponset_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct neponset_drvdata *d = irq_desc_get_handler_data(desc);
|
||||
unsigned int irr;
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* Acknowledge the parent IRQ.
|
||||
*/
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
|
||||
/*
|
||||
* Read the interrupt reason register. Let's have all
|
||||
* active IRQ bits high. Note: there is a typo in the
|
||||
* Neponset user's guide for the SA1111 IRR level.
|
||||
*/
|
||||
irr = readb_relaxed(d->base + IRR);
|
||||
irr ^= IRR_ETHERNET | IRR_USAR;
|
||||
|
||||
if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Since there is no individual mask, we have to
|
||||
* mask the parent IRQ. This is safe, since we'll
|
||||
* recheck the register for any pending IRQs.
|
||||
*/
|
||||
if (irr & (IRR_ETHERNET | IRR_USAR)) {
|
||||
desc->irq_data.chip->irq_mask(&desc->irq_data);
|
||||
|
||||
/*
|
||||
* Ack the interrupt now to prevent re-entering
|
||||
* this neponset handler. Again, this is safe
|
||||
* since we'll check the IRR register prior to
|
||||
* leaving.
|
||||
*/
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
|
||||
if (irr & IRR_ETHERNET)
|
||||
generic_handle_irq(d->irq_base + NEP_IRQ_SMC91X);
|
||||
|
||||
if (irr & IRR_USAR)
|
||||
generic_handle_irq(d->irq_base + NEP_IRQ_USAR);
|
||||
|
||||
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
||||
}
|
||||
|
||||
if (irr & IRR_SA1111)
|
||||
generic_handle_irq(d->irq_base + NEP_IRQ_SA1111);
|
||||
}
|
||||
}
|
||||
|
||||
/* Yes, we really do not have any kind of masking or unmasking */
|
||||
static void nochip_noop(struct irq_data *irq)
|
||||
{
|
||||
}
|
||||
|
||||
static struct irq_chip nochip = {
|
||||
.name = "neponset",
|
||||
.irq_ack = nochip_noop,
|
||||
.irq_mask = nochip_noop,
|
||||
.irq_unmask = nochip_noop,
|
||||
};
|
||||
|
||||
static struct sa1111_platform_data sa1111_info = {
|
||||
.disable_devs = SA1111_DEVID_PS2_MSE,
|
||||
};
|
||||
|
||||
static int __devinit neponset_probe(struct platform_device *dev)
|
||||
{
|
||||
sa1100_register_uart_fns(&neponset_port_fns);
|
||||
struct neponset_drvdata *d;
|
||||
struct resource *nep_res, *sa1111_res, *smc91x_res;
|
||||
struct resource sa1111_resources[] = {
|
||||
DEFINE_RES_MEM(0x40000000, SZ_8K),
|
||||
{ .flags = IORESOURCE_IRQ },
|
||||
};
|
||||
struct platform_device_info sa1111_devinfo = {
|
||||
.parent = &dev->dev,
|
||||
.name = "sa1111",
|
||||
.id = 0,
|
||||
.res = sa1111_resources,
|
||||
.num_res = ARRAY_SIZE(sa1111_resources),
|
||||
.data = &sa1111_info,
|
||||
.size_data = sizeof(sa1111_info),
|
||||
.dma_mask = 0xffffffffUL,
|
||||
};
|
||||
struct resource smc91x_resources[] = {
|
||||
DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS,
|
||||
0x02000000, "smc91x-regs"),
|
||||
DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS + 0x02000000,
|
||||
0x02000000, "smc91x-attrib"),
|
||||
{ .flags = IORESOURCE_IRQ },
|
||||
};
|
||||
struct platform_device_info smc91x_devinfo = {
|
||||
.parent = &dev->dev,
|
||||
.name = "smc91x",
|
||||
.id = 0,
|
||||
.res = smc91x_resources,
|
||||
.num_res = ARRAY_SIZE(smc91x_resources),
|
||||
};
|
||||
int ret, irq;
|
||||
|
||||
if (nep_base)
|
||||
return -EBUSY;
|
||||
|
||||
irq = ret = platform_get_irq(dev, 0);
|
||||
if (ret < 0)
|
||||
goto err_alloc;
|
||||
|
||||
nep_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
smc91x_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
|
||||
sa1111_res = platform_get_resource(dev, IORESOURCE_MEM, 2);
|
||||
if (!nep_res || !smc91x_res || !sa1111_res) {
|
||||
ret = -ENXIO;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
d = kzalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d) {
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
d->base = ioremap(nep_res->start, SZ_4K);
|
||||
if (!d->base) {
|
||||
ret = -ENOMEM;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
if (readb_relaxed(d->base + WHOAMI) != 0x11) {
|
||||
dev_warn(&dev->dev, "Neponset board detected, but wrong ID: %02x\n",
|
||||
readb_relaxed(d->base + WHOAMI));
|
||||
ret = -ENODEV;
|
||||
goto err_id;
|
||||
}
|
||||
|
||||
ret = irq_alloc_descs(-1, IRQ_BOARD_START, NEP_IRQ_NR, -1);
|
||||
if (ret <= 0) {
|
||||
dev_err(&dev->dev, "unable to allocate %u irqs: %d\n",
|
||||
NEP_IRQ_NR, ret);
|
||||
if (ret == 0)
|
||||
ret = -ENOMEM;
|
||||
goto err_irq_alloc;
|
||||
}
|
||||
|
||||
d->irq_base = ret;
|
||||
|
||||
irq_set_chip_and_handler(d->irq_base + NEP_IRQ_SMC91X, &nochip,
|
||||
handle_simple_irq);
|
||||
set_irq_flags(d->irq_base + NEP_IRQ_SMC91X, IRQF_VALID | IRQF_PROBE);
|
||||
irq_set_chip_and_handler(d->irq_base + NEP_IRQ_USAR, &nochip,
|
||||
handle_simple_irq);
|
||||
set_irq_flags(d->irq_base + NEP_IRQ_USAR, IRQF_VALID | IRQF_PROBE);
|
||||
irq_set_chip(d->irq_base + NEP_IRQ_SA1111, &nochip);
|
||||
|
||||
irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
|
||||
irq_set_handler_data(irq, d);
|
||||
irq_set_chained_handler(irq, neponset_irq_handler);
|
||||
|
||||
/*
|
||||
* Install handler for GPIO25.
|
||||
*/
|
||||
irq_set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
|
||||
irq_set_chained_handler(IRQ_GPIO25, neponset_irq_handler);
|
||||
|
||||
/*
|
||||
* We would set IRQ_GPIO25 to be a wake-up IRQ, but
|
||||
* unfortunately something on the Neponset activates
|
||||
* this IRQ on sleep (ethernet?)
|
||||
* We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
|
||||
* something on the Neponset activates this IRQ on sleep (eth?)
|
||||
*/
|
||||
#if 0
|
||||
enable_irq_wake(IRQ_GPIO25);
|
||||
enable_irq_wake(irq);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup other Neponset IRQs. SA1111 will be done by the
|
||||
* generic SA1111 code.
|
||||
*/
|
||||
irq_set_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq);
|
||||
set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE);
|
||||
irq_set_handler(IRQ_NEPONSET_USAR, handle_simple_irq);
|
||||
set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE);
|
||||
dev_info(&dev->dev, "Neponset daughter board, providing IRQ%u-%u\n",
|
||||
d->irq_base, d->irq_base + NEP_IRQ_NR - 1);
|
||||
nep_base = d->base;
|
||||
|
||||
/*
|
||||
* Disable GPIO 0/1 drivers so the buttons work on the module.
|
||||
*/
|
||||
NCR_0 = NCR_GP01_OFF;
|
||||
sa1100_register_uart_fns(&neponset_port_fns);
|
||||
|
||||
/* Ensure that the memory bus request/grant signals are setup */
|
||||
sa1110_mb_disable();
|
||||
|
||||
/* Disable GPIO 0/1 drivers so the buttons work on the Assabet */
|
||||
writeb_relaxed(NCR_GP01_OFF, d->base + NCR_0);
|
||||
|
||||
sa1111_resources[0].parent = sa1111_res;
|
||||
sa1111_resources[1].start = d->irq_base + NEP_IRQ_SA1111;
|
||||
sa1111_resources[1].end = d->irq_base + NEP_IRQ_SA1111;
|
||||
d->sa1111 = platform_device_register_full(&sa1111_devinfo);
|
||||
|
||||
smc91x_resources[0].parent = smc91x_res;
|
||||
smc91x_resources[1].parent = smc91x_res;
|
||||
smc91x_resources[2].start = d->irq_base + NEP_IRQ_SMC91X;
|
||||
smc91x_resources[2].end = d->irq_base + NEP_IRQ_SMC91X;
|
||||
d->smc91x = platform_device_register_full(&smc91x_devinfo);
|
||||
|
||||
platform_set_drvdata(dev, d);
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq_alloc:
|
||||
err_id:
|
||||
iounmap(d->base);
|
||||
err_ioremap:
|
||||
kfree(d);
|
||||
err_alloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/*
|
||||
* LDM power management.
|
||||
*/
|
||||
static unsigned int neponset_saved_state;
|
||||
|
||||
static int neponset_suspend(struct platform_device *dev, pm_message_t state)
|
||||
static int __devexit neponset_remove(struct platform_device *dev)
|
||||
{
|
||||
/*
|
||||
* Save state.
|
||||
*/
|
||||
neponset_saved_state = NCR_0;
|
||||
struct neponset_drvdata *d = platform_get_drvdata(dev);
|
||||
int irq = platform_get_irq(dev, 0);
|
||||
|
||||
if (!IS_ERR(d->sa1111))
|
||||
platform_device_unregister(d->sa1111);
|
||||
if (!IS_ERR(d->smc91x))
|
||||
platform_device_unregister(d->smc91x);
|
||||
irq_set_chained_handler(irq, NULL);
|
||||
irq_free_descs(d->irq_base, NEP_IRQ_NR);
|
||||
nep_base = NULL;
|
||||
iounmap(d->base);
|
||||
kfree(d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neponset_resume(struct platform_device *dev)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int neponset_suspend(struct device *dev)
|
||||
{
|
||||
NCR_0 = neponset_saved_state;
|
||||
struct neponset_drvdata *d = dev_get_drvdata(dev);
|
||||
|
||||
d->ncr0 = readb_relaxed(d->base + NCR_0);
|
||||
d->mdm_ctl_0 = readb_relaxed(d->base + MDM_CTL_0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int neponset_resume(struct device *dev)
|
||||
{
|
||||
struct neponset_drvdata *d = dev_get_drvdata(dev);
|
||||
|
||||
writeb_relaxed(d->ncr0, d->base + NCR_0);
|
||||
writeb_relaxed(d->mdm_ctl_0, d->base + MDM_CTL_0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops neponset_pm_ops = {
|
||||
.suspend_noirq = neponset_suspend,
|
||||
.resume_noirq = neponset_resume,
|
||||
.freeze_noirq = neponset_suspend,
|
||||
.restore_noirq = neponset_resume,
|
||||
};
|
||||
#define PM_OPS &neponset_pm_ops
|
||||
#else
|
||||
#define neponset_suspend NULL
|
||||
#define neponset_resume NULL
|
||||
#define PM_OPS NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver neponset_device_driver = {
|
||||
.probe = neponset_probe,
|
||||
.suspend = neponset_suspend,
|
||||
.resume = neponset_resume,
|
||||
.remove = __devexit_p(neponset_remove),
|
||||
.driver = {
|
||||
.name = "neponset",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = PM_OPS,
|
||||
},
|
||||
};
|
||||
|
||||
static struct resource neponset_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x10000000,
|
||||
.end = 0x17ffffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device neponset_device = {
|
||||
.name = "neponset",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(neponset_resources),
|
||||
.resource = neponset_resources,
|
||||
};
|
||||
|
||||
static struct resource sa1111_resources[] = {
|
||||
[0] = {
|
||||
.start = 0x40000000,
|
||||
.end = 0x40001fff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_NEPONSET_SA1111,
|
||||
.end = IRQ_NEPONSET_SA1111,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct sa1111_platform_data sa1111_info = {
|
||||
.irq_base = IRQ_BOARD_END,
|
||||
};
|
||||
|
||||
static u64 sa1111_dmamask = 0xffffffffUL;
|
||||
|
||||
static struct platform_device sa1111_device = {
|
||||
.name = "sa1111",
|
||||
.id = 0,
|
||||
.dev = {
|
||||
.dma_mask = &sa1111_dmamask,
|
||||
.coherent_dma_mask = 0xffffffff,
|
||||
.platform_data = &sa1111_info,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(sa1111_resources),
|
||||
.resource = sa1111_resources,
|
||||
};
|
||||
|
||||
static struct resource smc91x_resources[] = {
|
||||
[0] = {
|
||||
.name = "smc91x-regs",
|
||||
.start = SA1100_CS3_PHYS,
|
||||
.end = SA1100_CS3_PHYS + 0x01ffffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = IRQ_NEPONSET_SMC9196,
|
||||
.end = IRQ_NEPONSET_SMC9196,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[2] = {
|
||||
.name = "smc91x-attrib",
|
||||
.start = SA1100_CS3_PHYS + 0x02000000,
|
||||
.end = SA1100_CS3_PHYS + 0x03ffffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device smc91x_device = {
|
||||
.name = "smc91x",
|
||||
.id = 0,
|
||||
.num_resources = ARRAY_SIZE(smc91x_resources),
|
||||
.resource = smc91x_resources,
|
||||
};
|
||||
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&neponset_device,
|
||||
&sa1111_device,
|
||||
&smc91x_device,
|
||||
};
|
||||
|
||||
extern void sa1110_mb_disable(void);
|
||||
|
||||
static int __init neponset_init(void)
|
||||
{
|
||||
platform_driver_register(&neponset_device_driver);
|
||||
|
||||
/*
|
||||
* The Neponset is only present on the Assabet machine type.
|
||||
*/
|
||||
if (!machine_is_assabet())
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Ensure that the memory bus request/grant signals are setup,
|
||||
* and the grant is held in its inactive state, whether or not
|
||||
* we actually have a Neponset attached.
|
||||
*/
|
||||
sa1110_mb_disable();
|
||||
|
||||
if (!machine_has_neponset()) {
|
||||
printk(KERN_DEBUG "Neponset expansion board not present\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (WHOAMI != 0x11) {
|
||||
printk(KERN_WARNING "Neponset board detected, but "
|
||||
"wrong ID: %02x\n", WHOAMI);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
return platform_driver_register(&neponset_device_driver);
|
||||
}
|
||||
|
||||
subsys_initcall(neponset_init);
|
||||
|
||||
static struct map_desc neponset_io_desc[] __initdata = {
|
||||
{ /* System Registers */
|
||||
.virtual = 0xf3000000,
|
||||
.pfn = __phys_to_pfn(0x10000000),
|
||||
.length = SZ_1M,
|
||||
.type = MT_DEVICE
|
||||
}, { /* 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));
|
||||
}
|
||||
|
@ -135,12 +135,8 @@ struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys
|
||||
&sys->resources);
|
||||
}
|
||||
|
||||
static struct resource pci_io_ports = {
|
||||
.name = "PCI IO",
|
||||
.start = 0x400,
|
||||
.end = 0x7FF,
|
||||
.flags = IORESOURCE_IO,
|
||||
};
|
||||
static struct resource pci_io_ports =
|
||||
DEFINE_RES_IO_NAMED(0x400, 0x400, "PCI IO");
|
||||
|
||||
static struct resource pci_non_prefetchable_memory = {
|
||||
.name = "PCI non-prefetchable",
|
||||
|
@ -37,17 +37,9 @@
|
||||
#define IRQ_GPIO_ETH0_IRQ IRQ_GPIO21
|
||||
|
||||
static struct resource smc91x_resources[] = {
|
||||
[0] = {
|
||||
.start = PLEB_ETH0_P,
|
||||
.end = PLEB_ETH0_P | 0x03ffffff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[0] = DEFINE_RES_MEM(PLEB_ETH0_P, 0x04000000),
|
||||
#if 0 /* Autoprobe instead, to get rising/falling edge characteristic right */
|
||||
[1] = {
|
||||
.start = IRQ_GPIO_ETH0_IRQ,
|
||||
.end = IRQ_GPIO_ETH0_IRQ,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
[1] = DEFINE_RES_IRQ(IRQ_GPIO_ETH0_IRQ),
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -70,16 +62,8 @@ static struct platform_device *devices[] __initdata = {
|
||||
* the two SA1100 lowest chip select outputs.
|
||||
*/
|
||||
static struct resource pleb_flash_resources[] = {
|
||||
[0] = {
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_8M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = SA1100_CS1_PHYS,
|
||||
.end = SA1100_CS1_PHYS + SZ_8M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
[0] = DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_8M),
|
||||
[1] = DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_8M),
|
||||
};
|
||||
|
||||
|
||||
@ -147,6 +131,7 @@ static void __init pleb_map_io(void)
|
||||
|
||||
MACHINE_START(PLEB, "PLEB")
|
||||
.map_io = pleb_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = pleb_init,
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/setup.h>
|
||||
@ -19,6 +21,7 @@
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <mach/mcp.h>
|
||||
#include <mach/shannon.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include "generic.h"
|
||||
|
||||
@ -46,19 +49,32 @@ static struct flash_platform_data shannon_flash_data = {
|
||||
.nr_parts = ARRAY_SIZE(shannon_partitions),
|
||||
};
|
||||
|
||||
static struct resource shannon_flash_resource = {
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_4M - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
static struct resource shannon_flash_resource =
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_4M);
|
||||
|
||||
static struct mcp_plat_data shannon_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
};
|
||||
|
||||
static struct sa1100fb_mach_info shannon_lcd_info = {
|
||||
.pixclock = 152500, .bpp = 8,
|
||||
.xres = 640, .yres = 480,
|
||||
|
||||
.hsync_len = 4, .vsync_len = 3,
|
||||
.left_margin = 2, .upper_margin = 0,
|
||||
.right_margin = 1, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
|
||||
.lccr3 = LCCR3_ACBsDiv(512),
|
||||
};
|
||||
|
||||
static void __init shannon_init(void)
|
||||
{
|
||||
sa11x0_ppc_configure_mcp();
|
||||
sa11x0_register_lcd(&shannon_lcd_info);
|
||||
sa11x0_register_mtd(&shannon_flash_data, &shannon_flash_resource, 1);
|
||||
sa11x0_register_mcp(&shannon_mcp_data);
|
||||
}
|
||||
@ -84,6 +100,7 @@ static void __init shannon_map_io(void)
|
||||
MACHINE_START(SHANNON, "Shannon (AKA: Tuxscreen)")
|
||||
.atag_offset = 0x100,
|
||||
.map_io = shannon_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.init_machine = shannon_init,
|
||||
|
@ -7,15 +7,15 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/tty.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mfd/ucb1x00.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/setup.h>
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
#include <mach/mcp.h>
|
||||
#include <mach/simpad.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/ioport.h>
|
||||
@ -176,21 +177,18 @@ static struct flash_platform_data simpad_flash_data = {
|
||||
|
||||
|
||||
static struct resource simpad_flash_resources [] = {
|
||||
{
|
||||
.start = SA1100_CS0_PHYS,
|
||||
.end = SA1100_CS0_PHYS + SZ_16M -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = SA1100_CS1_PHYS,
|
||||
.end = SA1100_CS1_PHYS + SZ_16M -1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}
|
||||
DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_16M),
|
||||
DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_16M),
|
||||
};
|
||||
|
||||
static struct ucb1x00_plat_data simpad_ucb1x00_data = {
|
||||
.gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
|
||||
};
|
||||
|
||||
static struct mcp_plat_data simpad_mcp_data = {
|
||||
.mccr0 = MCCR0_ADM,
|
||||
.sclk_rate = 11981000,
|
||||
.gpio_base = SIMPAD_UCB1X00_GPIO_BASE,
|
||||
.codec_pdata = &simpad_ucb1x00_data,
|
||||
};
|
||||
|
||||
|
||||
@ -376,6 +374,7 @@ static int __init simpad_init(void)
|
||||
|
||||
pm_power_off = simpad_power_off;
|
||||
|
||||
sa11x0_ppc_configure_mcp();
|
||||
sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
|
||||
ARRAY_SIZE(simpad_flash_resources));
|
||||
sa11x0_register_mcp(&simpad_mcp_data);
|
||||
@ -394,6 +393,7 @@ MACHINE_START(SIMPAD, "Simpad")
|
||||
/* Maintainer: Holger Freyther */
|
||||
.atag_offset = 0x100,
|
||||
.map_io = simpad_map_io,
|
||||
.nr_irqs = SA1100_NR_IRQS,
|
||||
.init_irq = sa1100_init_irq,
|
||||
.timer = &sa1100_timer,
|
||||
.restart = sa11x0_restart,
|
||||
|
@ -26,27 +26,36 @@
|
||||
*
|
||||
* Causes sa11x0 to enter sleep state
|
||||
*
|
||||
* Must be aligned to a cacheline.
|
||||
*/
|
||||
|
||||
.balign 32
|
||||
ENTRY(sa1100_finish_suspend)
|
||||
@ disable clock switching
|
||||
mcr p15, 0, r1, c15, c2, 2
|
||||
|
||||
@ Adjust memory timing before lowering CPU clock
|
||||
@ Clock speed adjustment without changing memory timing makes
|
||||
@ CPU hang in some cases
|
||||
ldr r0, =MDREFR
|
||||
ldr r1, [r0]
|
||||
orr r1, r1, #MDREFR_K1DB2
|
||||
str r1, [r0]
|
||||
ldr r6, =MDREFR
|
||||
ldr r4, [r6]
|
||||
orr r4, r4, #MDREFR_K1DB2
|
||||
ldr r5, =PPCR
|
||||
|
||||
@ Pre-load __udelay into the I-cache
|
||||
mov r0, #1
|
||||
bl __udelay
|
||||
mov r0, r0
|
||||
|
||||
@ The following must all exist in a single cache line to
|
||||
@ avoid accessing memory until this sequence is complete,
|
||||
@ otherwise we occasionally hang.
|
||||
|
||||
@ Adjust memory timing before lowering CPU clock
|
||||
str r4, [r6]
|
||||
|
||||
@ delay 90us and set CPU PLL to lowest speed
|
||||
@ fixes resume problem on high speed SA1110
|
||||
mov r0, #90
|
||||
bl __udelay
|
||||
ldr r0, =PPCR
|
||||
mov r1, #0
|
||||
str r1, [r0]
|
||||
str r1, [r5]
|
||||
mov r0, #90
|
||||
bl __udelay
|
||||
|
||||
@ -85,12 +94,10 @@ ENTRY(sa1100_finish_suspend)
|
||||
bic r5, r5, #FMsk(MSC_RT)
|
||||
bic r5, r5, #FMsk(MSC_RT)<<16
|
||||
|
||||
ldr r6, =MDREFR
|
||||
|
||||
ldr r7, [r6]
|
||||
bic r7, r7, #0x0000FF00
|
||||
bic r7, r7, #0x000000F0
|
||||
orr r8, r7, #MDREFR_SLFRSH
|
||||
bic r7, r7, #0x0000FF00
|
||||
bic r7, r7, #0x000000F0
|
||||
orr r8, r7, #MDREFR_SLFRSH
|
||||
|
||||
ldr r9, =MDCNFG
|
||||
ldr r10, [r9]
|
||||
|
@ -19,8 +19,8 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <asm/hardware/ssp.h>
|
||||
|
||||
#define TIMEOUT 100000
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/sched_clock.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
static u32 notrace sa1100_read_sched_clock(void)
|
||||
{
|
||||
|
@ -252,6 +252,15 @@ config EP93XX_DMA
|
||||
help
|
||||
Enable support for the Cirrus Logic EP93xx M2P/M2M DMA controller.
|
||||
|
||||
config DMA_SA11X0
|
||||
tristate "SA-11x0 DMA support"
|
||||
depends on ARCH_SA1100
|
||||
select DMA_ENGINE
|
||||
help
|
||||
Support the DMA engine found on Intel StrongARM SA-1100 and
|
||||
SA-1110 SoCs. This DMA engine can only be used with on-chip
|
||||
devices.
|
||||
|
||||
config DMA_ENGINE
|
||||
bool
|
||||
|
||||
|
@ -27,3 +27,4 @@ obj-$(CONFIG_PL330_DMA) += pl330.o
|
||||
obj-$(CONFIG_PCH_DMA) += pch_dma.o
|
||||
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
|
||||
obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
|
||||
obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
|
||||
|
1109
drivers/dma/sa11x0-dma.c
Normal file
1109
drivers/dma/sa11x0-dma.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,7 @@
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
static int sa1100_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include <mach/jornada720.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
MODULE_AUTHOR("Kristoffer Ericson <Kristoffer.Ericson@gmail.com>");
|
||||
MODULE_DESCRIPTION("HP Jornada 710/720/728 keyboard driver");
|
||||
|
@ -24,6 +24,26 @@
|
||||
|
||||
#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 serio *io;
|
||||
struct sa1111_dev *dev;
|
||||
@ -45,22 +65,22 @@ static irqreturn_t ps2_rxint(int irq, void *dev_id)
|
||||
struct ps2if *ps2if = dev_id;
|
||||
unsigned int scancode, flag, status;
|
||||
|
||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
status = sa1111_readl(ps2if->base + PS2STAT);
|
||||
while (status & PS2STAT_RXF) {
|
||||
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) |
|
||||
(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)
|
||||
flag ^= SERIO_PARITY;
|
||||
|
||||
serio_interrupt(ps2if->io, scancode, flag);
|
||||
|
||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
status = sa1111_readl(ps2if->base + PS2STAT);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -75,12 +95,12 @@ static irqreturn_t ps2_txint(int irq, void *dev_id)
|
||||
unsigned int status;
|
||||
|
||||
spin_lock(&ps2if->lock);
|
||||
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
status = sa1111_readl(ps2if->base + PS2STAT);
|
||||
if (ps2if->head == ps2if->tail) {
|
||||
disable_irq_nosync(irq);
|
||||
/* done */
|
||||
} 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);
|
||||
}
|
||||
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 (sa1111_readl(ps2if->base + SA1111_PS2STAT) & PS2STAT_TXE) {
|
||||
sa1111_writel(val, ps2if->base + SA1111_PS2DATA);
|
||||
if (sa1111_readl(ps2if->base + PS2STAT) & PS2STAT_TXE) {
|
||||
sa1111_writel(val, ps2if->base + PS2DATA);
|
||||
} else {
|
||||
if (ps2if->head == ps2if->tail)
|
||||
enable_irq(ps2if->dev->irq[1]);
|
||||
@ -124,13 +144,16 @@ static int ps2_open(struct serio *io)
|
||||
struct ps2if *ps2if = io->port_data;
|
||||
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,
|
||||
SA1111_DRIVER_NAME(ps2if->dev), ps2if);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
|
||||
ps2if->dev->irq[0], ret);
|
||||
sa1111_disable_device(ps2if->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -140,6 +163,7 @@ static int ps2_open(struct serio *io)
|
||||
printk(KERN_ERR "sa1111ps2: could not allocate IRQ%d: %d\n",
|
||||
ps2if->dev->irq[1], ret);
|
||||
free_irq(ps2if->dev->irq[0], ps2if);
|
||||
sa1111_disable_device(ps2if->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -147,7 +171,7 @@ static int ps2_open(struct serio *io)
|
||||
|
||||
enable_irq_wake(ps2if->dev->irq[0]);
|
||||
|
||||
sa1111_writel(PS2CR_ENA, ps2if->base + SA1111_PS2CR);
|
||||
sa1111_writel(PS2CR_ENA, ps2if->base + PS2CR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -155,7 +179,7 @@ static void ps2_close(struct serio *io)
|
||||
{
|
||||
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]);
|
||||
|
||||
@ -175,7 +199,7 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if)
|
||||
int maxread = 100;
|
||||
|
||||
while (maxread--) {
|
||||
if ((sa1111_readl(ps2if->base + SA1111_PS2DATA) & 0xff) == 0xff)
|
||||
if ((sa1111_readl(ps2if->base + PS2DATA) & 0xff) == 0xff)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -185,11 +209,11 @@ static unsigned int __devinit ps2_test_one(struct ps2if *ps2if,
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
sa1111_writel(PS2CR_ENA | mask, ps2if->base + SA1111_PS2CR);
|
||||
sa1111_writel(PS2CR_ENA | mask, ps2if->base + PS2CR);
|
||||
|
||||
udelay(2);
|
||||
|
||||
val = sa1111_readl(ps2if->base + SA1111_PS2STAT);
|
||||
val = sa1111_readl(ps2if->base + PS2STAT);
|
||||
return val & (PS2STAT_KBC | PS2STAT_KBD);
|
||||
}
|
||||
|
||||
@ -220,7 +244,7 @@ static int __devinit ps2_test(struct ps2if *ps2if)
|
||||
ret = -ENODEV;
|
||||
}
|
||||
|
||||
sa1111_writel(0, ps2if->base + SA1111_PS2CR);
|
||||
sa1111_writel(0, ps2if->base + PS2CR);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -274,8 +298,8 @@ static int __devinit ps2_probe(struct sa1111_dev *dev)
|
||||
sa1111_enable_device(ps2if->dev);
|
||||
|
||||
/* Incoming clock is 8MHz */
|
||||
sa1111_writel(0, ps2if->base + SA1111_PS2CLKDIV);
|
||||
sa1111_writel(127, ps2if->base + SA1111_PS2PRECNT);
|
||||
sa1111_writel(0, ps2if->base + PS2CLKDIV);
|
||||
sa1111_writel(127, ps2if->base + PS2PRECNT);
|
||||
|
||||
/*
|
||||
* Flush any pending input.
|
||||
@ -330,6 +354,7 @@ static int __devexit ps2_remove(struct sa1111_dev *dev)
|
||||
static struct sa1111_driver ps2_driver = {
|
||||
.drv = {
|
||||
.name = "sa1111-ps2",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.devid = SA1111_DEVID_PS2,
|
||||
.probe = ps2_probe,
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/jornada720.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
MODULE_AUTHOR("Kristoffer Ericson <kristoffer.ericson@gmail.com>");
|
||||
MODULE_DESCRIPTION("HP Jornada 710/720/728 touchscreen driver");
|
||||
|
@ -847,8 +847,9 @@ config MCP_SA11X0
|
||||
|
||||
# Chip drivers
|
||||
config MCP_UCB1200
|
||||
tristate "Support for UCB1200 / UCB1300"
|
||||
depends on MCP
|
||||
bool "Support for UCB1200 / UCB1300"
|
||||
depends on MCP_SA11X0
|
||||
select MCP
|
||||
|
||||
config MCP_UCB1200_TS
|
||||
tristate "Touchscreen interface support"
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/mfd/mcp.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
|
||||
@ -48,39 +47,11 @@ static int mcp_bus_remove(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcp_bus_suspend(struct device *dev, pm_message_t state)
|
||||
{
|
||||
struct mcp *mcp = to_mcp(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (dev->driver) {
|
||||
struct mcp_driver *drv = to_mcp_driver(dev->driver);
|
||||
|
||||
ret = drv->suspend(mcp, state);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcp_bus_resume(struct device *dev)
|
||||
{
|
||||
struct mcp *mcp = to_mcp(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (dev->driver) {
|
||||
struct mcp_driver *drv = to_mcp_driver(dev->driver);
|
||||
|
||||
ret = drv->resume(mcp);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct bus_type mcp_bus_type = {
|
||||
.name = "mcp",
|
||||
.match = mcp_bus_match,
|
||||
.probe = mcp_bus_probe,
|
||||
.remove = mcp_bus_remove,
|
||||
.suspend = mcp_bus_suspend,
|
||||
.resume = mcp_bus_resume,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -208,6 +179,7 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
|
||||
mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL);
|
||||
if (mcp) {
|
||||
spin_lock_init(&mcp->lock);
|
||||
device_initialize(&mcp->attached_device);
|
||||
mcp->attached_device.parent = parent;
|
||||
mcp->attached_device.bus = &mcp_bus_type;
|
||||
mcp->attached_device.dma_mask = parent->dma_mask;
|
||||
@ -217,18 +189,25 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
|
||||
}
|
||||
EXPORT_SYMBOL(mcp_host_alloc);
|
||||
|
||||
int mcp_host_register(struct mcp *mcp)
|
||||
int mcp_host_add(struct mcp *mcp, void *pdata)
|
||||
{
|
||||
mcp->attached_device.platform_data = pdata;
|
||||
dev_set_name(&mcp->attached_device, "mcp0");
|
||||
return device_register(&mcp->attached_device);
|
||||
return device_add(&mcp->attached_device);
|
||||
}
|
||||
EXPORT_SYMBOL(mcp_host_register);
|
||||
EXPORT_SYMBOL(mcp_host_add);
|
||||
|
||||
void mcp_host_unregister(struct mcp *mcp)
|
||||
void mcp_host_del(struct mcp *mcp)
|
||||
{
|
||||
device_unregister(&mcp->attached_device);
|
||||
device_del(&mcp->attached_device);
|
||||
}
|
||||
EXPORT_SYMBOL(mcp_host_unregister);
|
||||
EXPORT_SYMBOL(mcp_host_del);
|
||||
|
||||
void mcp_host_free(struct mcp *mcp)
|
||||
{
|
||||
put_device(&mcp->attached_device);
|
||||
}
|
||||
EXPORT_SYMBOL(mcp_host_free);
|
||||
|
||||
int mcp_driver_register(struct mcp_driver *mcpdrv)
|
||||
{
|
||||
|
@ -13,51 +13,61 @@
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/mfd/mcp.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/system.h>
|
||||
#include <mach/mcp.h>
|
||||
|
||||
#include <mach/assabet.h>
|
||||
|
||||
#define DRIVER_NAME "sa11x0-mcp"
|
||||
|
||||
struct mcp_sa11x0 {
|
||||
u32 mccr0;
|
||||
u32 mccr1;
|
||||
void __iomem *base0;
|
||||
void __iomem *base1;
|
||||
u32 mccr0;
|
||||
u32 mccr1;
|
||||
};
|
||||
|
||||
/* Register offsets */
|
||||
#define MCCR0(m) ((m)->base0 + 0x00)
|
||||
#define MCDR0(m) ((m)->base0 + 0x08)
|
||||
#define MCDR1(m) ((m)->base0 + 0x0c)
|
||||
#define MCDR2(m) ((m)->base0 + 0x10)
|
||||
#define MCSR(m) ((m)->base0 + 0x18)
|
||||
#define MCCR1(m) ((m)->base1 + 0x00)
|
||||
|
||||
#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
|
||||
|
||||
static void
|
||||
mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
|
||||
{
|
||||
unsigned int mccr0;
|
||||
struct mcp_sa11x0 *m = priv(mcp);
|
||||
|
||||
divisor /= 32;
|
||||
|
||||
mccr0 = Ser4MCCR0 & ~0x00007f00;
|
||||
mccr0 |= divisor << 8;
|
||||
Ser4MCCR0 = mccr0;
|
||||
m->mccr0 &= ~0x00007f00;
|
||||
m->mccr0 |= divisor << 8;
|
||||
writel_relaxed(m->mccr0, MCCR0(m));
|
||||
}
|
||||
|
||||
static void
|
||||
mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
|
||||
{
|
||||
unsigned int mccr0;
|
||||
struct mcp_sa11x0 *m = priv(mcp);
|
||||
|
||||
divisor /= 32;
|
||||
|
||||
mccr0 = Ser4MCCR0 & ~0x0000007f;
|
||||
mccr0 |= divisor;
|
||||
Ser4MCCR0 = mccr0;
|
||||
m->mccr0 &= ~0x0000007f;
|
||||
m->mccr0 |= divisor;
|
||||
writel_relaxed(m->mccr0, MCCR0(m));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -69,14 +79,15 @@ mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
|
||||
static void
|
||||
mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
|
||||
{
|
||||
struct mcp_sa11x0 *m = priv(mcp);
|
||||
int ret = -ETIME;
|
||||
int i;
|
||||
|
||||
Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff);
|
||||
writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m));
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
udelay(mcp->rw_timeout);
|
||||
if (Ser4MCSR & MCSR_CWC) {
|
||||
if (readl_relaxed(MCSR(m)) & MCSR_CWC) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
@ -95,15 +106,16 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
|
||||
static unsigned int
|
||||
mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
|
||||
{
|
||||
struct mcp_sa11x0 *m = priv(mcp);
|
||||
int ret = -ETIME;
|
||||
int i;
|
||||
|
||||
Ser4MCDR2 = reg << 17 | MCDR2_Rd;
|
||||
writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m));
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
udelay(mcp->rw_timeout);
|
||||
if (Ser4MCSR & MCSR_CRC) {
|
||||
ret = Ser4MCDR2 & 0xffff;
|
||||
if (readl_relaxed(MCSR(m)) & MCSR_CRC) {
|
||||
ret = readl_relaxed(MCDR2(m)) & 0xffff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -116,13 +128,19 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
|
||||
|
||||
static void mcp_sa11x0_enable(struct mcp *mcp)
|
||||
{
|
||||
Ser4MCSR = -1;
|
||||
Ser4MCCR0 |= MCCR0_MCE;
|
||||
struct mcp_sa11x0 *m = priv(mcp);
|
||||
|
||||
writel(-1, MCSR(m));
|
||||
m->mccr0 |= MCCR0_MCE;
|
||||
writel_relaxed(m->mccr0, MCCR0(m));
|
||||
}
|
||||
|
||||
static void mcp_sa11x0_disable(struct mcp *mcp)
|
||||
{
|
||||
Ser4MCCR0 &= ~MCCR0_MCE;
|
||||
struct mcp_sa11x0 *m = priv(mcp);
|
||||
|
||||
m->mccr0 &= ~MCCR0_MCE;
|
||||
writel_relaxed(m->mccr0, MCCR0(m));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -137,55 +155,64 @@ static struct mcp_ops mcp_sa11x0 = {
|
||||
.disable = mcp_sa11x0_disable,
|
||||
};
|
||||
|
||||
static int mcp_sa11x0_probe(struct platform_device *pdev)
|
||||
static int mcp_sa11x0_probe(struct platform_device *dev)
|
||||
{
|
||||
struct mcp_plat_data *data = pdev->dev.platform_data;
|
||||
struct mcp_plat_data *data = dev->dev.platform_data;
|
||||
struct resource *mem0, *mem1;
|
||||
struct mcp_sa11x0 *m;
|
||||
struct mcp *mcp;
|
||||
int ret;
|
||||
|
||||
if (!data)
|
||||
return -ENODEV;
|
||||
|
||||
if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
|
||||
return -EBUSY;
|
||||
mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
|
||||
if (!mem0 || !mem1)
|
||||
return -ENXIO;
|
||||
|
||||
mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0));
|
||||
if (!request_mem_region(mem0->start, resource_size(mem0),
|
||||
DRIVER_NAME)) {
|
||||
ret = -EBUSY;
|
||||
goto err_mem0;
|
||||
}
|
||||
|
||||
if (!request_mem_region(mem1->start, resource_size(mem1),
|
||||
DRIVER_NAME)) {
|
||||
ret = -EBUSY;
|
||||
goto err_mem1;
|
||||
}
|
||||
|
||||
mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0));
|
||||
if (!mcp) {
|
||||
ret = -ENOMEM;
|
||||
goto release;
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
mcp->owner = THIS_MODULE;
|
||||
mcp->ops = &mcp_sa11x0;
|
||||
mcp->sclk_rate = data->sclk_rate;
|
||||
mcp->dma_audio_rd = DMA_Ser4MCP0Rd;
|
||||
mcp->dma_audio_wr = DMA_Ser4MCP0Wr;
|
||||
mcp->dma_telco_rd = DMA_Ser4MCP1Rd;
|
||||
mcp->dma_telco_wr = DMA_Ser4MCP1Wr;
|
||||
mcp->gpio_base = data->gpio_base;
|
||||
|
||||
platform_set_drvdata(pdev, mcp);
|
||||
m = priv(mcp);
|
||||
m->mccr0 = data->mccr0 | 0x7f7f;
|
||||
m->mccr1 = data->mccr1;
|
||||
|
||||
if (machine_is_assabet()) {
|
||||
ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
|
||||
m->base0 = ioremap(mem0->start, resource_size(mem0));
|
||||
m->base1 = ioremap(mem1->start, resource_size(mem1));
|
||||
if (!m->base0 || !m->base1) {
|
||||
ret = -ENOMEM;
|
||||
goto err_ioremap;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the PPC unit correctly.
|
||||
*/
|
||||
PPDR &= ~PPC_RXD4;
|
||||
PPDR |= PPC_TXD4 | PPC_SCLK | PPC_SFRM;
|
||||
PSDR |= PPC_RXD4;
|
||||
PSDR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
|
||||
PPSR &= ~(PPC_TXD4 | PPC_SCLK | PPC_SFRM);
|
||||
platform_set_drvdata(dev, mcp);
|
||||
|
||||
/*
|
||||
* Initialise device. Note that we initially
|
||||
* set the sampling rate to minimum.
|
||||
*/
|
||||
Ser4MCSR = -1;
|
||||
Ser4MCCR1 = data->mccr1;
|
||||
Ser4MCCR0 = data->mccr0 | 0x7f7f;
|
||||
writel_relaxed(-1, MCSR(m));
|
||||
writel_relaxed(m->mccr1, MCCR1(m));
|
||||
writel_relaxed(m->mccr0, MCCR0(m));
|
||||
|
||||
/*
|
||||
* Calculate the read/write timeout (us) from the bit clock
|
||||
@ -195,62 +222,90 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
|
||||
mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
|
||||
mcp->sclk_rate;
|
||||
|
||||
ret = mcp_host_register(mcp);
|
||||
ret = mcp_host_add(mcp, data->codec_pdata);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
return 0;
|
||||
|
||||
release:
|
||||
release_mem_region(0x80060000, 0x60);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
platform_set_drvdata(dev, NULL);
|
||||
|
||||
out:
|
||||
err_ioremap:
|
||||
iounmap(m->base1);
|
||||
iounmap(m->base0);
|
||||
mcp_host_free(mcp);
|
||||
err_alloc:
|
||||
release_mem_region(mem1->start, resource_size(mem1));
|
||||
err_mem1:
|
||||
release_mem_region(mem0->start, resource_size(mem0));
|
||||
err_mem0:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcp_sa11x0_remove(struct platform_device *dev)
|
||||
{
|
||||
struct mcp *mcp = platform_get_drvdata(dev);
|
||||
struct mcp_sa11x0 *m = priv(mcp);
|
||||
struct resource *mem0, *mem1;
|
||||
|
||||
if (m->mccr0 & MCCR0_MCE)
|
||||
dev_warn(&dev->dev,
|
||||
"device left active (missing disable call?)\n");
|
||||
|
||||
mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||
mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
|
||||
|
||||
platform_set_drvdata(dev, NULL);
|
||||
mcp_host_unregister(mcp);
|
||||
release_mem_region(0x80060000, 0x60);
|
||||
mcp_host_del(mcp);
|
||||
iounmap(m->base1);
|
||||
iounmap(m->base0);
|
||||
mcp_host_free(mcp);
|
||||
release_mem_region(mem1->start, resource_size(mem1));
|
||||
release_mem_region(mem0->start, resource_size(mem0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mcp_sa11x0_suspend(struct device *dev)
|
||||
{
|
||||
struct mcp *mcp = platform_get_drvdata(dev);
|
||||
struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
|
||||
|
||||
priv(mcp)->mccr0 = Ser4MCCR0;
|
||||
priv(mcp)->mccr1 = Ser4MCCR1;
|
||||
Ser4MCCR0 &= ~MCCR0_MCE;
|
||||
if (m->mccr0 & MCCR0_MCE)
|
||||
dev_warn(dev, "device left active (missing disable call?)\n");
|
||||
|
||||
writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcp_sa11x0_resume(struct platform_device *dev)
|
||||
static int mcp_sa11x0_resume(struct device *dev)
|
||||
{
|
||||
struct mcp *mcp = platform_get_drvdata(dev);
|
||||
struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
|
||||
|
||||
Ser4MCCR1 = priv(mcp)->mccr1;
|
||||
Ser4MCCR0 = priv(mcp)->mccr0;
|
||||
writel_relaxed(m->mccr1, MCCR1(m));
|
||||
writel_relaxed(m->mccr0, MCCR0(m));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The driver for the SA11x0 MCP port.
|
||||
*/
|
||||
MODULE_ALIAS("platform:sa11x0-mcp");
|
||||
static const struct dev_pm_ops mcp_sa11x0_pm_ops = {
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend = mcp_sa11x0_suspend,
|
||||
.freeze = mcp_sa11x0_suspend,
|
||||
.poweroff = mcp_sa11x0_suspend,
|
||||
.resume_noirq = mcp_sa11x0_resume,
|
||||
.thaw_noirq = mcp_sa11x0_resume,
|
||||
.restore_noirq = mcp_sa11x0_resume,
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct platform_driver mcp_sa11x0_driver = {
|
||||
.probe = mcp_sa11x0_probe,
|
||||
.remove = mcp_sa11x0_remove,
|
||||
.suspend = mcp_sa11x0_suspend,
|
||||
.resume = mcp_sa11x0_resume,
|
||||
.driver = {
|
||||
.name = "sa11x0-mcp",
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &mcp_sa11x0_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
@ -259,6 +314,7 @@ static struct platform_driver mcp_sa11x0_driver = {
|
||||
*/
|
||||
module_platform_driver(mcp_sa11x0_driver);
|
||||
|
||||
MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
|
||||
MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -11,14 +11,15 @@
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/mfd/ucb1x00.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
|
||||
|
||||
#define UCB1X00_ATTR(name,input)\
|
||||
static ssize_t name##_show(struct device *dev, struct device_attribute *attr, \
|
||||
char *buf) \
|
||||
@ -38,14 +39,45 @@ UCB1X00_ATTR(batt_temp, UCB_ADC_INP_AD2);
|
||||
|
||||
static int ucb1x00_assabet_add(struct ucb1x00_dev *dev)
|
||||
{
|
||||
device_create_file(&dev->ucb->dev, &dev_attr_vbatt);
|
||||
device_create_file(&dev->ucb->dev, &dev_attr_vcharger);
|
||||
device_create_file(&dev->ucb->dev, &dev_attr_batt_temp);
|
||||
struct ucb1x00 *ucb = dev->ucb;
|
||||
struct platform_device *pdev;
|
||||
struct gpio_keys_platform_data keys;
|
||||
static struct gpio_keys_button buttons[6];
|
||||
unsigned i;
|
||||
|
||||
memset(buttons, 0, sizeof(buttons));
|
||||
memset(&keys, 0, sizeof(keys));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(buttons); i++) {
|
||||
buttons[i].code = BTN_0 + i;
|
||||
buttons[i].gpio = ucb->gpio.base + i;
|
||||
buttons[i].type = EV_KEY;
|
||||
buttons[i].can_disable = true;
|
||||
}
|
||||
|
||||
keys.buttons = buttons;
|
||||
keys.nbuttons = ARRAY_SIZE(buttons);
|
||||
keys.poll_interval = 50;
|
||||
keys.name = "ucb1x00";
|
||||
|
||||
pdev = platform_device_register_data(&ucb->dev, "gpio-keys", -1,
|
||||
&keys, sizeof(keys));
|
||||
|
||||
device_create_file(&ucb->dev, &dev_attr_vbatt);
|
||||
device_create_file(&ucb->dev, &dev_attr_vcharger);
|
||||
device_create_file(&ucb->dev, &dev_attr_batt_temp);
|
||||
|
||||
dev->priv = pdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ucb1x00_assabet_remove(struct ucb1x00_dev *dev)
|
||||
{
|
||||
struct platform_device *pdev = dev->priv;
|
||||
|
||||
if (!IS_ERR(pdev))
|
||||
platform_device_unregister(pdev);
|
||||
|
||||
device_remove_file(&dev->ucb->dev, &dev_attr_batt_temp);
|
||||
device_remove_file(&dev->ucb->dev, &dev_attr_vcharger);
|
||||
device_remove_file(&dev->ucb->dev, &dev_attr_vbatt);
|
||||
|
@ -23,14 +23,12 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/mfd/ucb1x00.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/semaphore.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
static DEFINE_MUTEX(ucb1x00_mutex);
|
||||
static LIST_HEAD(ucb1x00_drivers);
|
||||
@ -102,7 +100,7 @@ void ucb1x00_io_write(struct ucb1x00 *ucb, unsigned int set, unsigned int clear)
|
||||
* ucb1x00_enable must have been called to enable the comms
|
||||
* before using this function.
|
||||
*
|
||||
* This function does not take any semaphores or spinlocks.
|
||||
* This function does not take any mutexes or spinlocks.
|
||||
*/
|
||||
unsigned int ucb1x00_io_read(struct ucb1x00 *ucb)
|
||||
{
|
||||
@ -120,14 +118,22 @@ static void ucb1x00_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
else
|
||||
ucb->io_out &= ~(1 << offset);
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
|
||||
ucb1x00_disable(ucb);
|
||||
spin_unlock_irqrestore(&ucb->io_lock, flags);
|
||||
}
|
||||
|
||||
static int ucb1x00_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
|
||||
return ucb1x00_reg_read(ucb, UCB_IO_DATA) & (1 << offset);
|
||||
unsigned val;
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
val = ucb1x00_reg_read(ucb, UCB_IO_DATA);
|
||||
ucb1x00_disable(ucb);
|
||||
|
||||
return val & (1 << offset);
|
||||
}
|
||||
|
||||
static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
@ -137,7 +143,9 @@ static int ucb1x00_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
|
||||
spin_lock_irqsave(&ucb->io_lock, flags);
|
||||
ucb->io_dir &= ~(1 << offset);
|
||||
ucb1x00_enable(ucb);
|
||||
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
|
||||
ucb1x00_disable(ucb);
|
||||
spin_unlock_irqrestore(&ucb->io_lock, flags);
|
||||
|
||||
return 0;
|
||||
@ -157,6 +165,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
|
||||
else
|
||||
ucb->io_out &= ~mask;
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
if (old != ucb->io_out)
|
||||
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
|
||||
|
||||
@ -164,11 +173,19 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
|
||||
ucb->io_dir |= mask;
|
||||
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
|
||||
}
|
||||
ucb1x00_disable(ucb);
|
||||
spin_unlock_irqrestore(&ucb->io_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ucb1x00_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct ucb1x00 *ucb = container_of(chip, struct ucb1x00, gpio);
|
||||
|
||||
return ucb->irq_base > 0 ? ucb->irq_base + offset : -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* UCB1300 data sheet says we must:
|
||||
* 1. enable ADC => 5us (including reference startup time)
|
||||
@ -186,7 +203,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
|
||||
* Any code wishing to use the ADC converter must call this
|
||||
* function prior to using it.
|
||||
*
|
||||
* This function takes the ADC semaphore to prevent two or more
|
||||
* This function takes the ADC mutex to prevent two or more
|
||||
* concurrent uses, and therefore may sleep. As a result, it
|
||||
* can only be called from process context, not interrupt
|
||||
* context.
|
||||
@ -196,7 +213,7 @@ static int ucb1x00_gpio_direction_output(struct gpio_chip *chip, unsigned offset
|
||||
*/
|
||||
void ucb1x00_adc_enable(struct ucb1x00 *ucb)
|
||||
{
|
||||
down(&ucb->adc_sem);
|
||||
mutex_lock(&ucb->adc_mutex);
|
||||
|
||||
ucb->adc_cr |= UCB_ADC_ENA;
|
||||
|
||||
@ -218,7 +235,7 @@ void ucb1x00_adc_enable(struct ucb1x00 *ucb)
|
||||
* complete (2 frames max without sync).
|
||||
*
|
||||
* If called for a synchronised ADC conversion, it may sleep
|
||||
* with the ADC semaphore held.
|
||||
* with the ADC mutex held.
|
||||
*/
|
||||
unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
|
||||
{
|
||||
@ -246,7 +263,7 @@ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync)
|
||||
* ucb1x00_adc_disable - disable the ADC converter
|
||||
* @ucb: UCB1x00 structure describing chip
|
||||
*
|
||||
* Disable the ADC converter and release the ADC semaphore.
|
||||
* Disable the ADC converter and release the ADC mutex.
|
||||
*/
|
||||
void ucb1x00_adc_disable(struct ucb1x00 *ucb)
|
||||
{
|
||||
@ -254,7 +271,7 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb)
|
||||
ucb1x00_reg_write(ucb, UCB_ADC_CR, ucb->adc_cr);
|
||||
ucb1x00_disable(ucb);
|
||||
|
||||
up(&ucb->adc_sem);
|
||||
mutex_unlock(&ucb->adc_mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -265,10 +282,9 @@ void ucb1x00_adc_disable(struct ucb1x00 *ucb)
|
||||
* SIBCLK to talk to the chip. We leave the clock running until
|
||||
* we have finished processing all interrupts from the chip.
|
||||
*/
|
||||
static irqreturn_t ucb1x00_irq(int irqnr, void *devid)
|
||||
static void ucb1x00_irq(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct ucb1x00 *ucb = devid;
|
||||
struct ucb1x00_irq *irq;
|
||||
struct ucb1x00 *ucb = irq_desc_get_handler_data(desc);
|
||||
unsigned int isr, i;
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
@ -276,157 +292,104 @@ static irqreturn_t ucb1x00_irq(int irqnr, void *devid)
|
||||
ucb1x00_reg_write(ucb, UCB_IE_CLEAR, isr);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_CLEAR, 0);
|
||||
|
||||
for (i = 0, irq = ucb->irq_handler; i < 16 && isr; i++, isr >>= 1, irq++)
|
||||
if (isr & 1 && irq->fn)
|
||||
irq->fn(i, irq->devid);
|
||||
for (i = 0; i < 16 && isr; i++, isr >>= 1, irq++)
|
||||
if (isr & 1)
|
||||
generic_handle_irq(ucb->irq_base + i);
|
||||
ucb1x00_disable(ucb);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* ucb1x00_hook_irq - hook a UCB1x00 interrupt
|
||||
* @ucb: UCB1x00 structure describing chip
|
||||
* @idx: interrupt index
|
||||
* @fn: function to call when interrupt is triggered
|
||||
* @devid: device id to pass to interrupt handler
|
||||
*
|
||||
* Hook the specified interrupt. You can only register one handler
|
||||
* for each interrupt source. The interrupt source is not enabled
|
||||
* by this function; use ucb1x00_enable_irq instead.
|
||||
*
|
||||
* Interrupt handlers will be called with other interrupts enabled.
|
||||
*
|
||||
* Returns zero on success, or one of the following errors:
|
||||
* -EINVAL if the interrupt index is invalid
|
||||
* -EBUSY if the interrupt has already been hooked
|
||||
*/
|
||||
int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid)
|
||||
static void ucb1x00_irq_update(struct ucb1x00 *ucb, unsigned mask)
|
||||
{
|
||||
struct ucb1x00_irq *irq;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (idx < 16) {
|
||||
irq = ucb->irq_handler + idx;
|
||||
ret = -EBUSY;
|
||||
|
||||
spin_lock_irq(&ucb->lock);
|
||||
if (irq->fn == NULL) {
|
||||
irq->devid = devid;
|
||||
irq->fn = fn;
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock_irq(&ucb->lock);
|
||||
}
|
||||
return ret;
|
||||
ucb1x00_enable(ucb);
|
||||
if (ucb->irq_ris_enbl & mask)
|
||||
ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
|
||||
ucb->irq_mask);
|
||||
if (ucb->irq_fal_enbl & mask)
|
||||
ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
|
||||
ucb->irq_mask);
|
||||
ucb1x00_disable(ucb);
|
||||
}
|
||||
|
||||
/**
|
||||
* ucb1x00_enable_irq - enable an UCB1x00 interrupt source
|
||||
* @ucb: UCB1x00 structure describing chip
|
||||
* @idx: interrupt index
|
||||
* @edges: interrupt edges to enable
|
||||
*
|
||||
* Enable the specified interrupt to trigger on %UCB_RISING,
|
||||
* %UCB_FALLING or both edges. The interrupt should have been
|
||||
* hooked by ucb1x00_hook_irq.
|
||||
*/
|
||||
void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
|
||||
static void ucb1x00_irq_noop(struct irq_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (idx < 16) {
|
||||
spin_lock_irqsave(&ucb->lock, flags);
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
if (edges & UCB_RISING) {
|
||||
ucb->irq_ris_enbl |= 1 << idx;
|
||||
ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
|
||||
}
|
||||
if (edges & UCB_FALLING) {
|
||||
ucb->irq_fal_enbl |= 1 << idx;
|
||||
ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
|
||||
}
|
||||
ucb1x00_disable(ucb);
|
||||
spin_unlock_irqrestore(&ucb->lock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ucb1x00_disable_irq - disable an UCB1x00 interrupt source
|
||||
* @ucb: UCB1x00 structure describing chip
|
||||
* @edges: interrupt edges to disable
|
||||
*
|
||||
* Disable the specified interrupt triggering on the specified
|
||||
* (%UCB_RISING, %UCB_FALLING or both) edges.
|
||||
*/
|
||||
void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges)
|
||||
static void ucb1x00_irq_mask(struct irq_data *data)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
|
||||
unsigned mask = 1 << (data->irq - ucb->irq_base);
|
||||
|
||||
if (idx < 16) {
|
||||
spin_lock_irqsave(&ucb->lock, flags);
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
if (edges & UCB_RISING) {
|
||||
ucb->irq_ris_enbl &= ~(1 << idx);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
|
||||
}
|
||||
if (edges & UCB_FALLING) {
|
||||
ucb->irq_fal_enbl &= ~(1 << idx);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
|
||||
}
|
||||
ucb1x00_disable(ucb);
|
||||
spin_unlock_irqrestore(&ucb->lock, flags);
|
||||
}
|
||||
raw_spin_lock(&ucb->irq_lock);
|
||||
ucb->irq_mask &= ~mask;
|
||||
ucb1x00_irq_update(ucb, mask);
|
||||
raw_spin_unlock(&ucb->irq_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* ucb1x00_free_irq - disable and free the specified UCB1x00 interrupt
|
||||
* @ucb: UCB1x00 structure describing chip
|
||||
* @idx: interrupt index
|
||||
* @devid: device id.
|
||||
*
|
||||
* Disable the interrupt source and remove the handler. devid must
|
||||
* match the devid passed when hooking the interrupt.
|
||||
*
|
||||
* Returns zero on success, or one of the following errors:
|
||||
* -EINVAL if the interrupt index is invalid
|
||||
* -ENOENT if devid does not match
|
||||
*/
|
||||
int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid)
|
||||
static void ucb1x00_irq_unmask(struct irq_data *data)
|
||||
{
|
||||
struct ucb1x00_irq *irq;
|
||||
int ret;
|
||||
struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
|
||||
unsigned mask = 1 << (data->irq - ucb->irq_base);
|
||||
|
||||
if (idx >= 16)
|
||||
goto bad;
|
||||
|
||||
irq = ucb->irq_handler + idx;
|
||||
ret = -ENOENT;
|
||||
|
||||
spin_lock_irq(&ucb->lock);
|
||||
if (irq->devid == devid) {
|
||||
ucb->irq_ris_enbl &= ~(1 << idx);
|
||||
ucb->irq_fal_enbl &= ~(1 << idx);
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl);
|
||||
ucb1x00_disable(ucb);
|
||||
|
||||
irq->fn = NULL;
|
||||
irq->devid = NULL;
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock_irq(&ucb->lock);
|
||||
return ret;
|
||||
|
||||
bad:
|
||||
printk(KERN_ERR "Freeing bad UCB1x00 irq %d\n", idx);
|
||||
return -EINVAL;
|
||||
raw_spin_lock(&ucb->irq_lock);
|
||||
ucb->irq_mask |= mask;
|
||||
ucb1x00_irq_update(ucb, mask);
|
||||
raw_spin_unlock(&ucb->irq_lock);
|
||||
}
|
||||
|
||||
static int ucb1x00_irq_set_type(struct irq_data *data, unsigned int type)
|
||||
{
|
||||
struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
|
||||
unsigned mask = 1 << (data->irq - ucb->irq_base);
|
||||
|
||||
raw_spin_lock(&ucb->irq_lock);
|
||||
if (type & IRQ_TYPE_EDGE_RISING)
|
||||
ucb->irq_ris_enbl |= mask;
|
||||
else
|
||||
ucb->irq_ris_enbl &= ~mask;
|
||||
|
||||
if (type & IRQ_TYPE_EDGE_FALLING)
|
||||
ucb->irq_fal_enbl |= mask;
|
||||
else
|
||||
ucb->irq_fal_enbl &= ~mask;
|
||||
if (ucb->irq_mask & mask) {
|
||||
ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
|
||||
ucb->irq_mask);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
|
||||
ucb->irq_mask);
|
||||
}
|
||||
raw_spin_unlock(&ucb->irq_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ucb1x00_irq_set_wake(struct irq_data *data, unsigned int on)
|
||||
{
|
||||
struct ucb1x00 *ucb = irq_data_get_irq_chip_data(data);
|
||||
struct ucb1x00_plat_data *pdata = ucb->mcp->attached_device.platform_data;
|
||||
unsigned mask = 1 << (data->irq - ucb->irq_base);
|
||||
|
||||
if (!pdata || !pdata->can_wakeup)
|
||||
return -EINVAL;
|
||||
|
||||
raw_spin_lock(&ucb->irq_lock);
|
||||
if (on)
|
||||
ucb->irq_wake |= mask;
|
||||
else
|
||||
ucb->irq_wake &= ~mask;
|
||||
raw_spin_unlock(&ucb->irq_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip ucb1x00_irqchip = {
|
||||
.name = "ucb1x00",
|
||||
.irq_ack = ucb1x00_irq_noop,
|
||||
.irq_mask = ucb1x00_irq_mask,
|
||||
.irq_unmask = ucb1x00_irq_unmask,
|
||||
.irq_set_type = ucb1x00_irq_set_type,
|
||||
.irq_set_wake = ucb1x00_irq_set_wake,
|
||||
};
|
||||
|
||||
static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
|
||||
{
|
||||
struct ucb1x00_dev *dev;
|
||||
@ -440,8 +403,8 @@ static int ucb1x00_add_dev(struct ucb1x00 *ucb, struct ucb1x00_driver *drv)
|
||||
ret = drv->add(dev);
|
||||
|
||||
if (ret == 0) {
|
||||
list_add(&dev->dev_node, &ucb->devs);
|
||||
list_add(&dev->drv_node, &drv->devs);
|
||||
list_add_tail(&dev->dev_node, &ucb->devs);
|
||||
list_add_tail(&dev->drv_node, &drv->devs);
|
||||
} else {
|
||||
kfree(dev);
|
||||
}
|
||||
@ -533,98 +496,126 @@ static struct class ucb1x00_class = {
|
||||
|
||||
static int ucb1x00_probe(struct mcp *mcp)
|
||||
{
|
||||
struct ucb1x00 *ucb;
|
||||
struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
|
||||
struct ucb1x00_driver *drv;
|
||||
unsigned int id;
|
||||
struct ucb1x00 *ucb;
|
||||
unsigned id, i, irq_base;
|
||||
int ret = -ENODEV;
|
||||
int temp;
|
||||
|
||||
/* Tell the platform to deassert the UCB1x00 reset */
|
||||
if (pdata && pdata->reset)
|
||||
pdata->reset(UCB_RST_PROBE);
|
||||
|
||||
mcp_enable(mcp);
|
||||
id = mcp_reg_read(mcp, UCB_ID);
|
||||
mcp_disable(mcp);
|
||||
|
||||
if (id != UCB_ID_1200 && id != UCB_ID_1300 && id != UCB_ID_TC35143) {
|
||||
printk(KERN_WARNING "UCB1x00 ID not found: %04x\n", id);
|
||||
goto err_disable;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ucb = kzalloc(sizeof(struct ucb1x00), GFP_KERNEL);
|
||||
ret = -ENOMEM;
|
||||
if (!ucb)
|
||||
goto err_disable;
|
||||
|
||||
goto out;
|
||||
|
||||
device_initialize(&ucb->dev);
|
||||
ucb->dev.class = &ucb1x00_class;
|
||||
ucb->dev.parent = &mcp->attached_device;
|
||||
dev_set_name(&ucb->dev, "ucb1x00");
|
||||
|
||||
spin_lock_init(&ucb->lock);
|
||||
raw_spin_lock_init(&ucb->irq_lock);
|
||||
spin_lock_init(&ucb->io_lock);
|
||||
sema_init(&ucb->adc_sem, 1);
|
||||
mutex_init(&ucb->adc_mutex);
|
||||
|
||||
ucb->id = id;
|
||||
ucb->mcp = mcp;
|
||||
|
||||
ret = device_add(&ucb->dev);
|
||||
if (ret)
|
||||
goto err_dev_add;
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
ucb->irq = ucb1x00_detect_irq(ucb);
|
||||
ucb1x00_disable(ucb);
|
||||
if (ucb->irq == NO_IRQ) {
|
||||
printk(KERN_ERR "UCB1x00: IRQ probe failed\n");
|
||||
dev_err(&ucb->dev, "IRQ probe failed\n");
|
||||
ret = -ENODEV;
|
||||
goto err_free;
|
||||
goto err_no_irq;
|
||||
}
|
||||
|
||||
ucb->gpio.base = -1;
|
||||
if (mcp->gpio_base != 0) {
|
||||
irq_base = pdata ? pdata->irq_base : 0;
|
||||
ucb->irq_base = irq_alloc_descs(-1, irq_base, 16, -1);
|
||||
if (ucb->irq_base < 0) {
|
||||
dev_err(&ucb->dev, "unable to allocate 16 irqs: %d\n",
|
||||
ucb->irq_base);
|
||||
goto err_irq_alloc;
|
||||
}
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
unsigned irq = ucb->irq_base + i;
|
||||
|
||||
irq_set_chip_and_handler(irq, &ucb1x00_irqchip, handle_edge_irq);
|
||||
irq_set_chip_data(irq, ucb);
|
||||
set_irq_flags(irq, IRQF_VALID | IRQ_NOREQUEST);
|
||||
}
|
||||
|
||||
irq_set_irq_type(ucb->irq, IRQ_TYPE_EDGE_RISING);
|
||||
irq_set_handler_data(ucb->irq, ucb);
|
||||
irq_set_chained_handler(ucb->irq, ucb1x00_irq);
|
||||
|
||||
if (pdata && pdata->gpio_base) {
|
||||
ucb->gpio.label = dev_name(&ucb->dev);
|
||||
ucb->gpio.base = mcp->gpio_base;
|
||||
ucb->gpio.dev = &ucb->dev;
|
||||
ucb->gpio.owner = THIS_MODULE;
|
||||
ucb->gpio.base = pdata->gpio_base;
|
||||
ucb->gpio.ngpio = 10;
|
||||
ucb->gpio.set = ucb1x00_gpio_set;
|
||||
ucb->gpio.get = ucb1x00_gpio_get;
|
||||
ucb->gpio.direction_input = ucb1x00_gpio_direction_input;
|
||||
ucb->gpio.direction_output = ucb1x00_gpio_direction_output;
|
||||
ucb->gpio.to_irq = ucb1x00_to_irq;
|
||||
ret = gpiochip_add(&ucb->gpio);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
goto err_gpio_add;
|
||||
} else
|
||||
dev_info(&ucb->dev, "gpio_base not set so no gpiolib support");
|
||||
|
||||
ret = request_irq(ucb->irq, ucb1x00_irq, IRQF_TRIGGER_RISING,
|
||||
"UCB1x00", ucb);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "ucb1x00: unable to grab irq%d: %d\n",
|
||||
ucb->irq, ret);
|
||||
goto err_gpio;
|
||||
}
|
||||
|
||||
mcp_set_drvdata(mcp, ucb);
|
||||
|
||||
ret = device_register(&ucb->dev);
|
||||
if (ret)
|
||||
goto err_irq;
|
||||
|
||||
if (pdata)
|
||||
device_set_wakeup_capable(&ucb->dev, pdata->can_wakeup);
|
||||
|
||||
INIT_LIST_HEAD(&ucb->devs);
|
||||
mutex_lock(&ucb1x00_mutex);
|
||||
list_add(&ucb->node, &ucb1x00_devices);
|
||||
list_add_tail(&ucb->node, &ucb1x00_devices);
|
||||
list_for_each_entry(drv, &ucb1x00_drivers, node) {
|
||||
ucb1x00_add_dev(ucb, drv);
|
||||
}
|
||||
mutex_unlock(&ucb1x00_mutex);
|
||||
|
||||
goto out;
|
||||
return ret;
|
||||
|
||||
err_irq:
|
||||
free_irq(ucb->irq, ucb);
|
||||
err_gpio:
|
||||
if (ucb->gpio.base != -1)
|
||||
temp = gpiochip_remove(&ucb->gpio);
|
||||
err_free:
|
||||
kfree(ucb);
|
||||
err_disable:
|
||||
mcp_disable(mcp);
|
||||
err_gpio_add:
|
||||
irq_set_chained_handler(ucb->irq, NULL);
|
||||
err_irq_alloc:
|
||||
if (ucb->irq_base > 0)
|
||||
irq_free_descs(ucb->irq_base, 16);
|
||||
err_no_irq:
|
||||
device_del(&ucb->dev);
|
||||
err_dev_add:
|
||||
put_device(&ucb->dev);
|
||||
out:
|
||||
if (pdata && pdata->reset)
|
||||
pdata->reset(UCB_RST_PROBE_FAIL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ucb1x00_remove(struct mcp *mcp)
|
||||
{
|
||||
struct ucb1x00_plat_data *pdata = mcp->attached_device.platform_data;
|
||||
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
|
||||
struct list_head *l, *n;
|
||||
int ret;
|
||||
@ -643,8 +634,12 @@ static void ucb1x00_remove(struct mcp *mcp)
|
||||
dev_err(&ucb->dev, "Can't remove gpio chip: %d\n", ret);
|
||||
}
|
||||
|
||||
free_irq(ucb->irq, ucb);
|
||||
irq_set_chained_handler(ucb->irq, NULL);
|
||||
irq_free_descs(ucb->irq_base, 16);
|
||||
device_unregister(&ucb->dev);
|
||||
|
||||
if (pdata && pdata->reset)
|
||||
pdata->reset(UCB_RST_REMOVE);
|
||||
}
|
||||
|
||||
int ucb1x00_register_driver(struct ucb1x00_driver *drv)
|
||||
@ -653,7 +648,7 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv)
|
||||
|
||||
INIT_LIST_HEAD(&drv->devs);
|
||||
mutex_lock(&ucb1x00_mutex);
|
||||
list_add(&drv->node, &ucb1x00_drivers);
|
||||
list_add_tail(&drv->node, &ucb1x00_drivers);
|
||||
list_for_each_entry(ucb, &ucb1x00_devices, node) {
|
||||
ucb1x00_add_dev(ucb, drv);
|
||||
}
|
||||
@ -674,44 +669,86 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv)
|
||||
mutex_unlock(&ucb1x00_mutex);
|
||||
}
|
||||
|
||||
static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state)
|
||||
static int ucb1x00_suspend(struct device *dev)
|
||||
{
|
||||
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
|
||||
struct ucb1x00_dev *dev;
|
||||
struct ucb1x00_plat_data *pdata = dev->platform_data;
|
||||
struct ucb1x00 *ucb = dev_get_drvdata(dev);
|
||||
struct ucb1x00_dev *udev;
|
||||
|
||||
mutex_lock(&ucb1x00_mutex);
|
||||
list_for_each_entry(dev, &ucb->devs, dev_node) {
|
||||
if (dev->drv->suspend)
|
||||
dev->drv->suspend(dev, state);
|
||||
list_for_each_entry(udev, &ucb->devs, dev_node) {
|
||||
if (udev->drv->suspend)
|
||||
udev->drv->suspend(udev);
|
||||
}
|
||||
mutex_unlock(&ucb1x00_mutex);
|
||||
|
||||
if (ucb->irq_wake) {
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&ucb->irq_lock, flags);
|
||||
ucb1x00_enable(ucb);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
|
||||
ucb->irq_wake);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
|
||||
ucb->irq_wake);
|
||||
ucb1x00_disable(ucb);
|
||||
raw_spin_unlock_irqrestore(&ucb->irq_lock, flags);
|
||||
|
||||
enable_irq_wake(ucb->irq);
|
||||
} else if (pdata && pdata->reset)
|
||||
pdata->reset(UCB_RST_SUSPEND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ucb1x00_resume(struct mcp *mcp)
|
||||
static int ucb1x00_resume(struct device *dev)
|
||||
{
|
||||
struct ucb1x00 *ucb = mcp_get_drvdata(mcp);
|
||||
struct ucb1x00_dev *dev;
|
||||
struct ucb1x00_plat_data *pdata = dev->platform_data;
|
||||
struct ucb1x00 *ucb = dev_get_drvdata(dev);
|
||||
struct ucb1x00_dev *udev;
|
||||
|
||||
if (!ucb->irq_wake && pdata && pdata->reset)
|
||||
pdata->reset(UCB_RST_RESUME);
|
||||
|
||||
ucb1x00_enable(ucb);
|
||||
ucb1x00_reg_write(ucb, UCB_IO_DATA, ucb->io_out);
|
||||
ucb1x00_reg_write(ucb, UCB_IO_DIR, ucb->io_dir);
|
||||
|
||||
if (ucb->irq_wake) {
|
||||
unsigned long flags;
|
||||
|
||||
raw_spin_lock_irqsave(&ucb->irq_lock, flags);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_RIS, ucb->irq_ris_enbl &
|
||||
ucb->irq_mask);
|
||||
ucb1x00_reg_write(ucb, UCB_IE_FAL, ucb->irq_fal_enbl &
|
||||
ucb->irq_mask);
|
||||
raw_spin_unlock_irqrestore(&ucb->irq_lock, flags);
|
||||
|
||||
disable_irq_wake(ucb->irq);
|
||||
}
|
||||
ucb1x00_disable(ucb);
|
||||
|
||||
mutex_lock(&ucb1x00_mutex);
|
||||
list_for_each_entry(dev, &ucb->devs, dev_node) {
|
||||
if (dev->drv->resume)
|
||||
dev->drv->resume(dev);
|
||||
list_for_each_entry(udev, &ucb->devs, dev_node) {
|
||||
if (udev->drv->resume)
|
||||
udev->drv->resume(udev);
|
||||
}
|
||||
mutex_unlock(&ucb1x00_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops ucb1x00_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(ucb1x00_suspend, ucb1x00_resume)
|
||||
};
|
||||
|
||||
static struct mcp_driver ucb1x00_driver = {
|
||||
.drv = {
|
||||
.name = "ucb1x00",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &ucb1x00_pm_ops,
|
||||
},
|
||||
.probe = ucb1x00_probe,
|
||||
.remove = ucb1x00_remove,
|
||||
.suspend = ucb1x00_suspend,
|
||||
.resume = ucb1x00_resume,
|
||||
};
|
||||
|
||||
static int __init ucb1x00_init(void)
|
||||
@ -742,14 +779,10 @@ EXPORT_SYMBOL(ucb1x00_adc_enable);
|
||||
EXPORT_SYMBOL(ucb1x00_adc_read);
|
||||
EXPORT_SYMBOL(ucb1x00_adc_disable);
|
||||
|
||||
EXPORT_SYMBOL(ucb1x00_hook_irq);
|
||||
EXPORT_SYMBOL(ucb1x00_free_irq);
|
||||
EXPORT_SYMBOL(ucb1x00_enable_irq);
|
||||
EXPORT_SYMBOL(ucb1x00_disable_irq);
|
||||
|
||||
EXPORT_SYMBOL(ucb1x00_register_driver);
|
||||
EXPORT_SYMBOL(ucb1x00_unregister_driver);
|
||||
|
||||
MODULE_ALIAS("mcp:ucb1x00");
|
||||
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
|
||||
MODULE_DESCRIPTION("UCB1x00 core driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -20,8 +20,9 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
@ -32,7 +33,6 @@
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mfd/ucb1x00.h>
|
||||
|
||||
#include <mach/dma.h>
|
||||
#include <mach/collie.h>
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
@ -42,6 +42,8 @@ struct ucb1x00_ts {
|
||||
struct input_dev *idev;
|
||||
struct ucb1x00 *ucb;
|
||||
|
||||
spinlock_t irq_lock;
|
||||
unsigned irq_disabled;
|
||||
wait_queue_head_t irq_wait;
|
||||
struct task_struct *rtask;
|
||||
u16 x_res;
|
||||
@ -238,7 +240,12 @@ static int ucb1x00_thread(void *_ts)
|
||||
if (ucb1x00_ts_pen_down(ts)) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
ucb1x00_enable_irq(ts->ucb, UCB_IRQ_TSPX, machine_is_collie() ? UCB_RISING : UCB_FALLING);
|
||||
spin_lock_irq(&ts->irq_lock);
|
||||
if (ts->irq_disabled) {
|
||||
ts->irq_disabled = 0;
|
||||
enable_irq(ts->ucb->irq_base + UCB_IRQ_TSPX);
|
||||
}
|
||||
spin_unlock_irq(&ts->irq_lock);
|
||||
ucb1x00_disable(ts->ucb);
|
||||
|
||||
/*
|
||||
@ -281,23 +288,37 @@ static int ucb1x00_thread(void *_ts)
|
||||
* We only detect touch screen _touches_ with this interrupt
|
||||
* handler, and even then we just schedule our task.
|
||||
*/
|
||||
static void ucb1x00_ts_irq(int idx, void *id)
|
||||
static irqreturn_t ucb1x00_ts_irq(int irq, void *id)
|
||||
{
|
||||
struct ucb1x00_ts *ts = id;
|
||||
|
||||
ucb1x00_disable_irq(ts->ucb, UCB_IRQ_TSPX, UCB_FALLING);
|
||||
spin_lock(&ts->irq_lock);
|
||||
ts->irq_disabled = 1;
|
||||
disable_irq_nosync(ts->ucb->irq_base + UCB_IRQ_TSPX);
|
||||
spin_unlock(&ts->irq_lock);
|
||||
wake_up(&ts->irq_wait);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ucb1x00_ts_open(struct input_dev *idev)
|
||||
{
|
||||
struct ucb1x00_ts *ts = input_get_drvdata(idev);
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(ts->rtask);
|
||||
|
||||
if (machine_is_collie())
|
||||
flags = IRQF_TRIGGER_RISING;
|
||||
else
|
||||
flags = IRQF_TRIGGER_FALLING;
|
||||
|
||||
ts->irq_disabled = 0;
|
||||
|
||||
init_waitqueue_head(&ts->irq_wait);
|
||||
ret = ucb1x00_hook_irq(ts->ucb, UCB_IRQ_TSPX, ucb1x00_ts_irq, ts);
|
||||
ret = request_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ucb1x00_ts_irq,
|
||||
flags, "ucb1x00-ts", ts);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@ -314,7 +335,7 @@ static int ucb1x00_ts_open(struct input_dev *idev)
|
||||
if (!IS_ERR(ts->rtask)) {
|
||||
ret = 0;
|
||||
} else {
|
||||
ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
|
||||
free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts);
|
||||
ts->rtask = NULL;
|
||||
ret = -EFAULT;
|
||||
}
|
||||
@ -334,7 +355,7 @@ static void ucb1x00_ts_close(struct input_dev *idev)
|
||||
kthread_stop(ts->rtask);
|
||||
|
||||
ucb1x00_enable(ts->ucb);
|
||||
ucb1x00_free_irq(ts->ucb, UCB_IRQ_TSPX, ts);
|
||||
free_irq(ts->ucb->irq_base + UCB_IRQ_TSPX, ts);
|
||||
ucb1x00_reg_write(ts->ucb, UCB_TS_CR, 0);
|
||||
ucb1x00_disable(ts->ucb);
|
||||
}
|
||||
@ -359,11 +380,13 @@ static int ucb1x00_ts_add(struct ucb1x00_dev *dev)
|
||||
ts->ucb = dev->ucb;
|
||||
ts->idev = idev;
|
||||
ts->adcsync = adcsync ? UCB_SYNC : UCB_NOSYNC;
|
||||
spin_lock_init(&ts->irq_lock);
|
||||
|
||||
idev->name = "Touchscreen panel";
|
||||
idev->id.product = ts->ucb->id;
|
||||
idev->open = ucb1x00_ts_open;
|
||||
idev->close = ucb1x00_ts_close;
|
||||
idev->dev.parent = &ts->ucb->dev;
|
||||
|
||||
idev->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
|
||||
idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
|
||||
|
@ -23,106 +23,6 @@
|
||||
#include <asm/sizes.h>
|
||||
#include <asm/mach/flash.h>
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This is here for documentation purposes only - until these people
|
||||
* submit their machine types. It will be gone January 2005.
|
||||
*/
|
||||
static struct mtd_partition consus_partitions[] = {
|
||||
{
|
||||
.name = "Consus boot firmware",
|
||||
.offset = 0,
|
||||
.size = 0x00040000,
|
||||
.mask_flags = MTD_WRITABLE, /* force read-only */
|
||||
}, {
|
||||
.name = "Consus kernel",
|
||||
.offset = 0x00040000,
|
||||
.size = 0x00100000,
|
||||
.mask_flags = 0,
|
||||
}, {
|
||||
.name = "Consus disk",
|
||||
.offset = 0x00140000,
|
||||
/* The rest (up to 16M) for jffs. We could put 0 and
|
||||
make it find the size automatically, but right now
|
||||
i have 32 megs. jffs will use all 32 megs if given
|
||||
the chance, and this leads to horrible problems
|
||||
when you try to re-flash the image because blob
|
||||
won't erase the whole partition. */
|
||||
.size = 0x01000000 - 0x00140000,
|
||||
.mask_flags = 0,
|
||||
}, {
|
||||
/* this disk is a secondary disk, which can be used as
|
||||
needed, for simplicity, make it the size of the other
|
||||
consus partition, although realistically it could be
|
||||
the remainder of the disk (depending on the file
|
||||
system used) */
|
||||
.name = "Consus disk2",
|
||||
.offset = 0x01000000,
|
||||
.size = 0x01000000 - 0x00140000,
|
||||
.mask_flags = 0,
|
||||
}
|
||||
};
|
||||
|
||||
/* Frodo has 2 x 16M 28F128J3A flash chips in bank 0: */
|
||||
static struct mtd_partition frodo_partitions[] =
|
||||
{
|
||||
{
|
||||
.name = "bootloader",
|
||||
.size = 0x00040000,
|
||||
.offset = 0x00000000,
|
||||
.mask_flags = MTD_WRITEABLE
|
||||
}, {
|
||||
.name = "bootloader params",
|
||||
.size = 0x00040000,
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.mask_flags = MTD_WRITEABLE
|
||||
}, {
|
||||
.name = "kernel",
|
||||
.size = 0x00100000,
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.mask_flags = MTD_WRITEABLE
|
||||
}, {
|
||||
.name = "ramdisk",
|
||||
.size = 0x00400000,
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.mask_flags = MTD_WRITEABLE
|
||||
}, {
|
||||
.name = "file system",
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
.offset = MTDPART_OFS_APPEND
|
||||
}
|
||||
};
|
||||
|
||||
static struct mtd_partition jornada56x_partitions[] = {
|
||||
{
|
||||
.name = "bootldr",
|
||||
.size = 0x00040000,
|
||||
.offset = 0,
|
||||
.mask_flags = MTD_WRITEABLE,
|
||||
}, {
|
||||
.name = "rootfs",
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
}
|
||||
};
|
||||
|
||||
static void jornada56x_set_vpp(int vpp)
|
||||
{
|
||||
if (vpp)
|
||||
GPSR = GPIO_GPIO26;
|
||||
else
|
||||
GPCR = GPIO_GPIO26;
|
||||
GPDR |= GPIO_GPIO26;
|
||||
}
|
||||
|
||||
/*
|
||||
* Machine Phys Size set_vpp
|
||||
* Consus : SA1100_CS0_PHYS SZ_32M
|
||||
* Frodo : SA1100_CS0_PHYS SZ_32M
|
||||
* Jornada56x: SA1100_CS0_PHYS SZ_32M jornada56x_set_vpp
|
||||
*/
|
||||
#endif
|
||||
|
||||
struct sa_subdev_info {
|
||||
char name[16];
|
||||
struct map_info map;
|
||||
@ -373,21 +273,9 @@ static int __exit sa1100_mtd_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static void sa1100_mtd_shutdown(struct platform_device *dev)
|
||||
{
|
||||
struct sa_info *info = platform_get_drvdata(dev);
|
||||
if (info && mtd_suspend(info->mtd) == 0)
|
||||
mtd_resume(info->mtd);
|
||||
}
|
||||
#else
|
||||
#define sa1100_mtd_shutdown NULL
|
||||
#endif
|
||||
|
||||
static struct platform_driver sa1100_mtd_driver = {
|
||||
.probe = sa1100_mtd_probe,
|
||||
.remove = __exit_p(sa1100_mtd_remove),
|
||||
.shutdown = sa1100_mtd_shutdown,
|
||||
.driver = {
|
||||
.name = "sa1100-mtd",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -2281,7 +2281,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
|
||||
if (ret)
|
||||
goto out_release_io;
|
||||
#if defined(CONFIG_SA1100_ASSABET)
|
||||
NCR_0 |= NCR_ENET_OSC_EN;
|
||||
neponset_ncr_set(NCR_ENET_OSC_EN);
|
||||
#endif
|
||||
platform_set_drvdata(pdev, ndev);
|
||||
ret = smc_enable_device(pdev);
|
||||
|
@ -356,7 +356,7 @@ config VLSI_FIR
|
||||
|
||||
config SA1100_FIR
|
||||
tristate "SA1100 Internal IR"
|
||||
depends on ARCH_SA1100 && IRDA
|
||||
depends on ARCH_SA1100 && IRDA && DMA_SA11X0
|
||||
|
||||
config VIA_FIR
|
||||
tristate "VIA VT8231/VT1211 SIR/MIR/FIR"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -94,12 +94,7 @@ neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_sta
|
||||
|
||||
ret = sa1111_pcmcia_configure_socket(skt, state);
|
||||
if (ret == 0) {
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set;
|
||||
|
||||
local_irq_restore(flags);
|
||||
neponset_ncr_frob(ncr_mask, ncr_set);
|
||||
sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,40 @@
|
||||
|
||||
#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_CD_VALID (1)
|
||||
#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)
|
||||
{
|
||||
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) {
|
||||
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;
|
||||
|
||||
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_set_mask & pccr_skt_mask;
|
||||
sa1111_writel(val, s->dev->mapbase + SA1111_PCCR);
|
||||
sa1111_writel(val, s->dev->mapbase + PCCR);
|
||||
local_irq_restore(flags);
|
||||
|
||||
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)
|
||||
{
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
ret = sa1111_enable_device(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_set_drvdata(&dev->dev, NULL);
|
||||
|
||||
if (!request_mem_region(dev->res.start, 512,
|
||||
SA1111_DRIVER_NAME(dev)))
|
||||
if (!request_mem_region(dev->res.start, 512, SA1111_DRIVER_NAME(dev))) {
|
||||
sa1111_disable_device(dev);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
base = dev->mapbase;
|
||||
|
||||
@ -181,8 +221,8 @@ static int pcmcia_probe(struct sa1111_dev *dev)
|
||||
/*
|
||||
* 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);
|
||||
sa1111_writel(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + PCSSR);
|
||||
sa1111_writel(PCCR_S0_FLT | PCCR_S1_FLT, base + PCCR);
|
||||
|
||||
#ifdef CONFIG_SA1100_BADGE4
|
||||
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);
|
||||
sa1111_disable_device(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/irq.h>
|
||||
#include <mach/irqs.h>
|
||||
|
||||
#ifdef CONFIG_ARCH_PXA
|
||||
#include <mach/regs-rtc.h>
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <asm/mach/serial_sa1100.h>
|
||||
|
||||
/* We've been assigned a range on the "Low-density serial ports" major */
|
||||
|
@ -16,87 +16,37 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/assabet.h>
|
||||
#include <mach/badge4.h>
|
||||
#include <asm/hardware/sa1111.h>
|
||||
|
||||
#ifndef CONFIG_SA1111
|
||||
#error "This file is SA-1111 bus glue. CONFIG_SA1111 must be defined."
|
||||
#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)
|
||||
{
|
||||
unsigned int usb_rst = 0;
|
||||
|
||||
printk(KERN_DEBUG "%s: starting SA-1111 OHCI USB Controller\n",
|
||||
__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
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
#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)
|
||||
|
||||
#if 0
|
||||
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_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
|
||||
((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
|
||||
@ -105,98 +55,27 @@ static void dump_hci_status(struct usb_hcd *hcd, const char *label)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* 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)
|
||||
static int ohci_sa1111_reset(struct usb_hcd *hcd)
|
||||
{
|
||||
struct usb_hcd *hcd;
|
||||
int retval;
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
|
||||
hcd = usb_create_hcd (driver, &dev->dev, "sa1111");
|
||||
if (!hcd)
|
||||
return -ENOMEM;
|
||||
hcd->rsrc_start = dev->res.start;
|
||||
hcd->rsrc_len = resource_size(&dev->res);
|
||||
ohci_hcd_init(ohci);
|
||||
return ohci_init(ohci);
|
||||
}
|
||||
|
||||
if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
dbg("request_mem_region failed");
|
||||
retval = -EBUSY;
|
||||
goto err1;
|
||||
static int __devinit ohci_sa1111_start(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
int ret;
|
||||
|
||||
ret = ohci_run(ohci);
|
||||
if (ret < 0) {
|
||||
ohci_err(ohci, "can't start\n");
|
||||
ohci_stop(hcd);
|
||||
}
|
||||
hcd->regs = dev->mapbase;
|
||||
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* 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 = {
|
||||
.description = hcd_name,
|
||||
.product_desc = "SA-1111 OHCI",
|
||||
@ -211,8 +90,10 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
|
||||
/*
|
||||
* basic lifecycle operations
|
||||
*/
|
||||
.reset = ohci_sa1111_reset,
|
||||
.start = ohci_sa1111_start,
|
||||
.stop = ohci_stop,
|
||||
.shutdown = ohci_shutdown,
|
||||
|
||||
/*
|
||||
* 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,
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
static int ohci_hcd_sa1111_drv_probe(struct sa1111_dev *dev)
|
||||
static int sa1111_start_hc(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;
|
||||
|
||||
if (usb_disabled())
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.drv = {
|
||||
.name = "sa1111-ohci",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.devid = SA1111_DEVID_USB,
|
||||
.probe = ohci_hcd_sa1111_drv_probe,
|
||||
.remove = ohci_hcd_sa1111_drv_remove,
|
||||
.probe = ohci_hcd_sa1111_probe,
|
||||
.remove = ohci_hcd_sa1111_remove,
|
||||
.shutdown = ohci_hcd_sa1111_shutdown,
|
||||
};
|
||||
|
||||
|
@ -173,281 +173,47 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <video/sa1100fb.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <mach/assabet.h>
|
||||
#include <mach/shannon.h>
|
||||
|
||||
/*
|
||||
* debugging?
|
||||
*/
|
||||
#define DEBUG 0
|
||||
/*
|
||||
* Complain if VAR is out of range.
|
||||
*/
|
||||
#define DEBUG_VAR 1
|
||||
|
||||
#undef ASSABET_PAL_VIDEO
|
||||
|
||||
#include "sa1100fb.h"
|
||||
|
||||
extern void (*sa1100fb_backlight_power)(int on);
|
||||
extern void (*sa1100fb_lcd_power)(int on);
|
||||
|
||||
static struct sa1100fb_rgb rgb_4 = {
|
||||
static const struct sa1100fb_rgb rgb_4 = {
|
||||
.red = { .offset = 0, .length = 4, },
|
||||
.green = { .offset = 0, .length = 4, },
|
||||
.blue = { .offset = 0, .length = 4, },
|
||||
.transp = { .offset = 0, .length = 0, },
|
||||
};
|
||||
|
||||
static struct sa1100fb_rgb rgb_8 = {
|
||||
static const struct sa1100fb_rgb rgb_8 = {
|
||||
.red = { .offset = 0, .length = 8, },
|
||||
.green = { .offset = 0, .length = 8, },
|
||||
.blue = { .offset = 0, .length = 8, },
|
||||
.transp = { .offset = 0, .length = 0, },
|
||||
};
|
||||
|
||||
static struct sa1100fb_rgb def_rgb_16 = {
|
||||
static const struct sa1100fb_rgb def_rgb_16 = {
|
||||
.red = { .offset = 11, .length = 5, },
|
||||
.green = { .offset = 5, .length = 6, },
|
||||
.blue = { .offset = 0, .length = 5, },
|
||||
.transp = { .offset = 0, .length = 0, },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_SA1100_ASSABET
|
||||
#ifndef ASSABET_PAL_VIDEO
|
||||
/*
|
||||
* The assabet uses a sharp LQ039Q2DS54 LCD module. It is actually
|
||||
* takes an RGB666 signal, but we provide it with an RGB565 signal
|
||||
* instead (def_rgb_16).
|
||||
*/
|
||||
static struct sa1100fb_mach_info lq039q2ds54_info __initdata = {
|
||||
.pixclock = 171521, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 5, .vsync_len = 1,
|
||||
.left_margin = 61, .upper_margin = 3,
|
||||
.right_margin = 9, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
};
|
||||
#else
|
||||
static struct sa1100fb_mach_info pal_info __initdata = {
|
||||
.pixclock = 67797, .bpp = 16,
|
||||
.xres = 640, .yres = 512,
|
||||
|
||||
.hsync_len = 64, .vsync_len = 6,
|
||||
.left_margin = 125, .upper_margin = 70,
|
||||
.right_margin = 115, .lower_margin = 36,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SA1100_H3600
|
||||
static struct sa1100fb_mach_info h3600_info __initdata = {
|
||||
.pixclock = 174757, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 3, .vsync_len = 3,
|
||||
.left_margin = 12, .upper_margin = 10,
|
||||
.right_margin = 17, .lower_margin = 1,
|
||||
|
||||
.cmap_static = 1,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
};
|
||||
|
||||
static struct sa1100fb_rgb h3600_rgb_16 = {
|
||||
.red = { .offset = 12, .length = 4, },
|
||||
.green = { .offset = 7, .length = 4, },
|
||||
.blue = { .offset = 1, .length = 4, },
|
||||
.transp = { .offset = 0, .length = 0, },
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SA1100_H3100
|
||||
static struct sa1100fb_mach_info h3100_info __initdata = {
|
||||
.pixclock = 406977, .bpp = 4,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 26, .vsync_len = 41,
|
||||
.left_margin = 4, .upper_margin = 0,
|
||||
.right_margin = 4, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
.cmap_greyscale = 1,
|
||||
.cmap_inverse = 1,
|
||||
|
||||
.lccr0 = LCCR0_Mono | LCCR0_4PixMono | LCCR0_Sngl | LCCR0_Pas,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SA1100_COLLIE
|
||||
static struct sa1100fb_mach_info collie_info __initdata = {
|
||||
.pixclock = 171521, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 5, .vsync_len = 1,
|
||||
.left_margin = 11, .upper_margin = 2,
|
||||
.right_margin = 30, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(2),
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LART_GREY_LCD
|
||||
static struct sa1100fb_mach_info lart_grey_info __initdata = {
|
||||
.pixclock = 150000, .bpp = 4,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 1, .vsync_len = 1,
|
||||
.left_margin = 4, .upper_margin = 0,
|
||||
.right_margin = 2, .lower_margin = 0,
|
||||
|
||||
.cmap_greyscale = 1,
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Mono | LCCR0_Sngl | LCCR0_Pas | LCCR0_4PixMono,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
#ifdef LART_COLOR_LCD
|
||||
static struct sa1100fb_mach_info lart_color_info __initdata = {
|
||||
.pixclock = 150000, .bpp = 16,
|
||||
.xres = 320, .yres = 240,
|
||||
|
||||
.hsync_len = 2, .vsync_len = 3,
|
||||
.left_margin = 69, .upper_margin = 14,
|
||||
.right_margin = 8, .lower_margin = 4,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
#ifdef LART_VIDEO_OUT
|
||||
static struct sa1100fb_mach_info lart_video_info __initdata = {
|
||||
.pixclock = 39721, .bpp = 16,
|
||||
.xres = 640, .yres = 480,
|
||||
|
||||
.hsync_len = 95, .vsync_len = 2,
|
||||
.left_margin = 40, .upper_margin = 32,
|
||||
.right_margin = 24, .lower_margin = 11,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnL | LCCR3_PixFlEdg | LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef LART_KIT01_LCD
|
||||
static struct sa1100fb_mach_info lart_kit01_info __initdata = {
|
||||
.pixclock = 63291, .bpp = 16,
|
||||
.xres = 640, .yres = 480,
|
||||
|
||||
.hsync_len = 64, .vsync_len = 3,
|
||||
.left_margin = 122, .upper_margin = 45,
|
||||
.right_margin = 10, .lower_margin = 10,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Sngl | LCCR0_Act,
|
||||
.lccr3 = LCCR3_OutEnH | LCCR3_PixFlEdg
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SA1100_SHANNON
|
||||
static struct sa1100fb_mach_info shannon_info __initdata = {
|
||||
.pixclock = 152500, .bpp = 8,
|
||||
.xres = 640, .yres = 480,
|
||||
|
||||
.hsync_len = 4, .vsync_len = 3,
|
||||
.left_margin = 2, .upper_margin = 0,
|
||||
.right_margin = 1, .lower_margin = 0,
|
||||
|
||||
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
|
||||
|
||||
.lccr0 = LCCR0_Color | LCCR0_Dual | LCCR0_Pas,
|
||||
.lccr3 = LCCR3_ACBsDiv(512),
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static struct sa1100fb_mach_info * __init
|
||||
sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
|
||||
{
|
||||
struct sa1100fb_mach_info *inf = NULL;
|
||||
|
||||
/*
|
||||
* R G B T
|
||||
* default {11,5}, { 5,6}, { 0,5}, { 0,0}
|
||||
* h3600 {12,4}, { 7,4}, { 1,4}, { 0,0}
|
||||
* freebird { 8,4}, { 4,4}, { 0,4}, {12,4}
|
||||
*/
|
||||
#ifdef CONFIG_SA1100_ASSABET
|
||||
if (machine_is_assabet()) {
|
||||
#ifndef ASSABET_PAL_VIDEO
|
||||
inf = &lq039q2ds54_info;
|
||||
#else
|
||||
inf = &pal_info;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_H3100
|
||||
if (machine_is_h3100()) {
|
||||
inf = &h3100_info;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_H3600
|
||||
if (machine_is_h3600()) {
|
||||
inf = &h3600_info;
|
||||
fbi->rgb[RGB_16] = &h3600_rgb_16;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_COLLIE
|
||||
if (machine_is_collie()) {
|
||||
inf = &collie_info;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_LART
|
||||
if (machine_is_lart()) {
|
||||
#ifdef LART_GREY_LCD
|
||||
inf = &lart_grey_info;
|
||||
#endif
|
||||
#ifdef LART_COLOR_LCD
|
||||
inf = &lart_color_info;
|
||||
#endif
|
||||
#ifdef LART_VIDEO_OUT
|
||||
inf = &lart_video_info;
|
||||
#endif
|
||||
#ifdef LART_KIT01_LCD
|
||||
inf = &lart_kit01_info;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_SA1100_SHANNON
|
||||
if (machine_is_shannon()) {
|
||||
inf = &shannon_info;
|
||||
}
|
||||
#endif
|
||||
return inf;
|
||||
}
|
||||
|
||||
static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
|
||||
static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
|
||||
@ -533,7 +299,7 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
|
||||
* is what you poke into the framebuffer to produce the
|
||||
* colour you requested.
|
||||
*/
|
||||
if (fbi->cmap_inverse) {
|
||||
if (fbi->inf->cmap_inverse) {
|
||||
red = 0xffff - red;
|
||||
green = 0xffff - green;
|
||||
blue = 0xffff - blue;
|
||||
@ -607,14 +373,14 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
var->xres = MIN_XRES;
|
||||
if (var->yres < MIN_YRES)
|
||||
var->yres = MIN_YRES;
|
||||
if (var->xres > fbi->max_xres)
|
||||
var->xres = fbi->max_xres;
|
||||
if (var->yres > fbi->max_yres)
|
||||
var->yres = fbi->max_yres;
|
||||
if (var->xres > fbi->inf->xres)
|
||||
var->xres = fbi->inf->xres;
|
||||
if (var->yres > fbi->inf->yres)
|
||||
var->yres = fbi->inf->yres;
|
||||
var->xres_virtual = max(var->xres_virtual, var->xres);
|
||||
var->yres_virtual = max(var->yres_virtual, var->yres);
|
||||
|
||||
DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
|
||||
dev_dbg(fbi->dev, "var->bits_per_pixel=%d\n", var->bits_per_pixel);
|
||||
switch (var->bits_per_pixel) {
|
||||
case 4:
|
||||
rgbidx = RGB_4;
|
||||
@ -638,16 +404,16 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
var->blue = fbi->rgb[rgbidx]->blue;
|
||||
var->transp = fbi->rgb[rgbidx]->transp;
|
||||
|
||||
DPRINTK("RGBT length = %d:%d:%d:%d\n",
|
||||
dev_dbg(fbi->dev, "RGBT length = %d:%d:%d:%d\n",
|
||||
var->red.length, var->green.length, var->blue.length,
|
||||
var->transp.length);
|
||||
|
||||
DPRINTK("RGBT offset = %d:%d:%d:%d\n",
|
||||
dev_dbg(fbi->dev, "RGBT offset = %d:%d:%d:%d\n",
|
||||
var->red.offset, var->green.offset, var->blue.offset,
|
||||
var->transp.offset);
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n",
|
||||
dev_dbg(fbi->dev, "dma period = %d ps, clock = %d kHz\n",
|
||||
sa1100fb_display_dma_period(var),
|
||||
cpufreq_get(smp_processor_id()));
|
||||
#endif
|
||||
@ -655,22 +421,10 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void sa1100fb_set_truecolor(u_int is_true_color)
|
||||
static void sa1100fb_set_visual(struct sa1100fb_info *fbi, u32 visual)
|
||||
{
|
||||
if (machine_is_assabet()) {
|
||||
#if 1 // phase 4 or newer Assabet's
|
||||
if (is_true_color)
|
||||
ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
|
||||
else
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
|
||||
#else
|
||||
// older Assabet's
|
||||
if (is_true_color)
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);
|
||||
else
|
||||
ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);
|
||||
#endif
|
||||
}
|
||||
if (fbi->inf->set_visual)
|
||||
fbi->inf->set_visual(visual);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -683,11 +437,11 @@ static int sa1100fb_set_par(struct fb_info *info)
|
||||
struct fb_var_screeninfo *var = &info->var;
|
||||
unsigned long palette_mem_size;
|
||||
|
||||
DPRINTK("set_par\n");
|
||||
dev_dbg(fbi->dev, "set_par\n");
|
||||
|
||||
if (var->bits_per_pixel == 16)
|
||||
fbi->fb.fix.visual = FB_VISUAL_TRUECOLOR;
|
||||
else if (!fbi->cmap_static)
|
||||
else if (!fbi->inf->cmap_static)
|
||||
fbi->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR;
|
||||
else {
|
||||
/*
|
||||
@ -704,7 +458,7 @@ static int sa1100fb_set_par(struct fb_info *info)
|
||||
|
||||
palette_mem_size = fbi->palette_size * sizeof(u16);
|
||||
|
||||
DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
|
||||
dev_dbg(fbi->dev, "palette_mem_size = 0x%08lx\n", palette_mem_size);
|
||||
|
||||
fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
|
||||
fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
|
||||
@ -712,7 +466,7 @@ static int sa1100fb_set_par(struct fb_info *info)
|
||||
/*
|
||||
* Set (any) board control register to handle new color depth
|
||||
*/
|
||||
sa1100fb_set_truecolor(fbi->fb.fix.visual == FB_VISUAL_TRUECOLOR);
|
||||
sa1100fb_set_visual(fbi, fbi->fb.fix.visual);
|
||||
sa1100fb_activate_var(var, fbi);
|
||||
|
||||
return 0;
|
||||
@ -728,7 +482,7 @@ sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
|
||||
/*
|
||||
* Make sure the user isn't doing something stupid.
|
||||
*/
|
||||
if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->cmap_static))
|
||||
if (!kspc && (fbi->fb.var.bits_per_pixel == 16 || fbi->inf->cmap_static))
|
||||
return -EINVAL;
|
||||
|
||||
return gen_set_cmap(cmap, kspc, con, info);
|
||||
@ -775,7 +529,7 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
|
||||
struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
|
||||
int i;
|
||||
|
||||
DPRINTK("sa1100fb_blank: blank=%d\n", blank);
|
||||
dev_dbg(fbi->dev, "sa1100fb_blank: blank=%d\n", blank);
|
||||
|
||||
switch (blank) {
|
||||
case FB_BLANK_POWERDOWN:
|
||||
@ -863,43 +617,43 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
|
||||
u_int half_screen_size, yres, pcd;
|
||||
u_long flags;
|
||||
|
||||
DPRINTK("Configuring SA1100 LCD\n");
|
||||
dev_dbg(fbi->dev, "Configuring SA1100 LCD\n");
|
||||
|
||||
DPRINTK("var: xres=%d hslen=%d lm=%d rm=%d\n",
|
||||
dev_dbg(fbi->dev, "var: xres=%d hslen=%d lm=%d rm=%d\n",
|
||||
var->xres, var->hsync_len,
|
||||
var->left_margin, var->right_margin);
|
||||
DPRINTK("var: yres=%d vslen=%d um=%d bm=%d\n",
|
||||
dev_dbg(fbi->dev, "var: yres=%d vslen=%d um=%d bm=%d\n",
|
||||
var->yres, var->vsync_len,
|
||||
var->upper_margin, var->lower_margin);
|
||||
|
||||
#if DEBUG_VAR
|
||||
if (var->xres < 16 || var->xres > 1024)
|
||||
printk(KERN_ERR "%s: invalid xres %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid xres %d\n",
|
||||
fbi->fb.fix.id, var->xres);
|
||||
if (var->hsync_len < 1 || var->hsync_len > 64)
|
||||
printk(KERN_ERR "%s: invalid hsync_len %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid hsync_len %d\n",
|
||||
fbi->fb.fix.id, var->hsync_len);
|
||||
if (var->left_margin < 1 || var->left_margin > 255)
|
||||
printk(KERN_ERR "%s: invalid left_margin %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid left_margin %d\n",
|
||||
fbi->fb.fix.id, var->left_margin);
|
||||
if (var->right_margin < 1 || var->right_margin > 255)
|
||||
printk(KERN_ERR "%s: invalid right_margin %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid right_margin %d\n",
|
||||
fbi->fb.fix.id, var->right_margin);
|
||||
if (var->yres < 1 || var->yres > 1024)
|
||||
printk(KERN_ERR "%s: invalid yres %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid yres %d\n",
|
||||
fbi->fb.fix.id, var->yres);
|
||||
if (var->vsync_len < 1 || var->vsync_len > 64)
|
||||
printk(KERN_ERR "%s: invalid vsync_len %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid vsync_len %d\n",
|
||||
fbi->fb.fix.id, var->vsync_len);
|
||||
if (var->upper_margin < 0 || var->upper_margin > 255)
|
||||
printk(KERN_ERR "%s: invalid upper_margin %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid upper_margin %d\n",
|
||||
fbi->fb.fix.id, var->upper_margin);
|
||||
if (var->lower_margin < 0 || var->lower_margin > 255)
|
||||
printk(KERN_ERR "%s: invalid lower_margin %d\n",
|
||||
dev_err(fbi->dev, "%s: invalid lower_margin %d\n",
|
||||
fbi->fb.fix.id, var->lower_margin);
|
||||
#endif
|
||||
|
||||
new_regs.lccr0 = fbi->lccr0 |
|
||||
new_regs.lccr0 = fbi->inf->lccr0 |
|
||||
LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
|
||||
LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
|
||||
|
||||
@ -914,7 +668,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
|
||||
* the YRES parameter.
|
||||
*/
|
||||
yres = var->yres;
|
||||
if (fbi->lccr0 & LCCR0_Dual)
|
||||
if (fbi->inf->lccr0 & LCCR0_Dual)
|
||||
yres /= 2;
|
||||
|
||||
new_regs.lccr2 =
|
||||
@ -924,14 +678,14 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
|
||||
LCCR2_EndFrmDel(var->lower_margin);
|
||||
|
||||
pcd = get_pcd(var->pixclock, cpufreq_get(0));
|
||||
new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->lccr3 |
|
||||
new_regs.lccr3 = LCCR3_PixClkDiv(pcd) | fbi->inf->lccr3 |
|
||||
(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
|
||||
(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL);
|
||||
|
||||
DPRINTK("nlccr0 = 0x%08lx\n", new_regs.lccr0);
|
||||
DPRINTK("nlccr1 = 0x%08lx\n", new_regs.lccr1);
|
||||
DPRINTK("nlccr2 = 0x%08lx\n", new_regs.lccr2);
|
||||
DPRINTK("nlccr3 = 0x%08lx\n", new_regs.lccr3);
|
||||
dev_dbg(fbi->dev, "nlccr0 = 0x%08lx\n", new_regs.lccr0);
|
||||
dev_dbg(fbi->dev, "nlccr1 = 0x%08lx\n", new_regs.lccr1);
|
||||
dev_dbg(fbi->dev, "nlccr2 = 0x%08lx\n", new_regs.lccr2);
|
||||
dev_dbg(fbi->dev, "nlccr3 = 0x%08lx\n", new_regs.lccr3);
|
||||
|
||||
half_screen_size = var->bits_per_pixel;
|
||||
half_screen_size = half_screen_size * var->xres * var->yres / 16;
|
||||
@ -951,9 +705,12 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
|
||||
* Only update the registers if the controller is enabled
|
||||
* and something has changed.
|
||||
*/
|
||||
if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) ||
|
||||
(LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) ||
|
||||
(DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2))
|
||||
if (readl_relaxed(fbi->base + LCCR0) != fbi->reg_lccr0 ||
|
||||
readl_relaxed(fbi->base + LCCR1) != fbi->reg_lccr1 ||
|
||||
readl_relaxed(fbi->base + LCCR2) != fbi->reg_lccr2 ||
|
||||
readl_relaxed(fbi->base + LCCR3) != fbi->reg_lccr3 ||
|
||||
readl_relaxed(fbi->base + DBAR1) != fbi->dbar1 ||
|
||||
readl_relaxed(fbi->base + DBAR2) != fbi->dbar2)
|
||||
sa1100fb_schedule_work(fbi, C_REENABLE);
|
||||
|
||||
return 0;
|
||||
@ -967,18 +724,18 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_
|
||||
*/
|
||||
static inline void __sa1100fb_backlight_power(struct sa1100fb_info *fbi, int on)
|
||||
{
|
||||
DPRINTK("backlight o%s\n", on ? "n" : "ff");
|
||||
dev_dbg(fbi->dev, "backlight o%s\n", on ? "n" : "ff");
|
||||
|
||||
if (sa1100fb_backlight_power)
|
||||
sa1100fb_backlight_power(on);
|
||||
if (fbi->inf->backlight_power)
|
||||
fbi->inf->backlight_power(on);
|
||||
}
|
||||
|
||||
static inline void __sa1100fb_lcd_power(struct sa1100fb_info *fbi, int on)
|
||||
{
|
||||
DPRINTK("LCD power o%s\n", on ? "n" : "ff");
|
||||
dev_dbg(fbi->dev, "LCD power o%s\n", on ? "n" : "ff");
|
||||
|
||||
if (sa1100fb_lcd_power)
|
||||
sa1100fb_lcd_power(on);
|
||||
if (fbi->inf->lcd_power)
|
||||
fbi->inf->lcd_power(on);
|
||||
}
|
||||
|
||||
static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
|
||||
@ -1008,14 +765,25 @@ static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
|
||||
}
|
||||
|
||||
if (mask) {
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* SA-1100 requires the GPIO direction register set
|
||||
* appropriately for the alternate function. Hence
|
||||
* we set it here via bitmask rather than excessive
|
||||
* fiddling via the GPIO subsystem - and even then
|
||||
* we'll still have to deal with GAFR.
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
GPDR |= mask;
|
||||
GAFR |= mask;
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
|
||||
{
|
||||
DPRINTK("Enabling LCD controller\n");
|
||||
dev_dbg(fbi->dev, "Enabling LCD controller\n");
|
||||
|
||||
/*
|
||||
* Make sure the mode bits are present in the first palette entry
|
||||
@ -1024,43 +792,46 @@ static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
|
||||
fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
|
||||
|
||||
/* Sequence from 11.7.10 */
|
||||
LCCR3 = fbi->reg_lccr3;
|
||||
LCCR2 = fbi->reg_lccr2;
|
||||
LCCR1 = fbi->reg_lccr1;
|
||||
LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN;
|
||||
DBAR1 = fbi->dbar1;
|
||||
DBAR2 = fbi->dbar2;
|
||||
LCCR0 |= LCCR0_LEN;
|
||||
writel_relaxed(fbi->reg_lccr3, fbi->base + LCCR3);
|
||||
writel_relaxed(fbi->reg_lccr2, fbi->base + LCCR2);
|
||||
writel_relaxed(fbi->reg_lccr1, fbi->base + LCCR1);
|
||||
writel_relaxed(fbi->reg_lccr0 & ~LCCR0_LEN, fbi->base + LCCR0);
|
||||
writel_relaxed(fbi->dbar1, fbi->base + DBAR1);
|
||||
writel_relaxed(fbi->dbar2, fbi->base + DBAR2);
|
||||
writel_relaxed(fbi->reg_lccr0 | LCCR0_LEN, fbi->base + LCCR0);
|
||||
|
||||
if (machine_is_shannon()) {
|
||||
GPDR |= SHANNON_GPIO_DISP_EN;
|
||||
GPSR |= SHANNON_GPIO_DISP_EN;
|
||||
}
|
||||
if (machine_is_shannon())
|
||||
gpio_set_value(SHANNON_GPIO_DISP_EN, 1);
|
||||
|
||||
DPRINTK("DBAR1 = 0x%08x\n", DBAR1);
|
||||
DPRINTK("DBAR2 = 0x%08x\n", DBAR2);
|
||||
DPRINTK("LCCR0 = 0x%08x\n", LCCR0);
|
||||
DPRINTK("LCCR1 = 0x%08x\n", LCCR1);
|
||||
DPRINTK("LCCR2 = 0x%08x\n", LCCR2);
|
||||
DPRINTK("LCCR3 = 0x%08x\n", LCCR3);
|
||||
dev_dbg(fbi->dev, "DBAR1: 0x%08x\n", readl_relaxed(fbi->base + DBAR1));
|
||||
dev_dbg(fbi->dev, "DBAR2: 0x%08x\n", readl_relaxed(fbi->base + DBAR2));
|
||||
dev_dbg(fbi->dev, "LCCR0: 0x%08x\n", readl_relaxed(fbi->base + LCCR0));
|
||||
dev_dbg(fbi->dev, "LCCR1: 0x%08x\n", readl_relaxed(fbi->base + LCCR1));
|
||||
dev_dbg(fbi->dev, "LCCR2: 0x%08x\n", readl_relaxed(fbi->base + LCCR2));
|
||||
dev_dbg(fbi->dev, "LCCR3: 0x%08x\n", readl_relaxed(fbi->base + LCCR3));
|
||||
}
|
||||
|
||||
static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
|
||||
{
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
u32 lccr0;
|
||||
|
||||
DPRINTK("Disabling LCD controller\n");
|
||||
dev_dbg(fbi->dev, "Disabling LCD controller\n");
|
||||
|
||||
if (machine_is_shannon()) {
|
||||
GPCR |= SHANNON_GPIO_DISP_EN;
|
||||
}
|
||||
if (machine_is_shannon())
|
||||
gpio_set_value(SHANNON_GPIO_DISP_EN, 0);
|
||||
|
||||
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
add_wait_queue(&fbi->ctrlr_wait, &wait);
|
||||
|
||||
LCSR = 0xffffffff; /* Clear LCD Status Register */
|
||||
LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
|
||||
LCCR0 &= ~LCCR0_LEN; /* Disable LCD Controller */
|
||||
/* Clear LCD Status Register */
|
||||
writel_relaxed(~0, fbi->base + LCSR);
|
||||
|
||||
lccr0 = readl_relaxed(fbi->base + LCCR0);
|
||||
lccr0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
|
||||
writel_relaxed(lccr0, fbi->base + LCCR0);
|
||||
lccr0 &= ~LCCR0_LEN; /* Disable LCD Controller */
|
||||
writel_relaxed(lccr0, fbi->base + LCCR0);
|
||||
|
||||
schedule_timeout(20 * HZ / 1000);
|
||||
remove_wait_queue(&fbi->ctrlr_wait, &wait);
|
||||
@ -1072,14 +843,15 @@ static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
|
||||
static irqreturn_t sa1100fb_handle_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct sa1100fb_info *fbi = dev_id;
|
||||
unsigned int lcsr = LCSR;
|
||||
unsigned int lcsr = readl_relaxed(fbi->base + LCSR);
|
||||
|
||||
if (lcsr & LCSR_LDD) {
|
||||
LCCR0 |= LCCR0_LDM;
|
||||
u32 lccr0 = readl_relaxed(fbi->base + LCCR0) | LCCR0_LDM;
|
||||
writel_relaxed(lccr0, fbi->base + LCCR0);
|
||||
wake_up(&fbi->ctrlr_wait);
|
||||
}
|
||||
|
||||
LCSR = lcsr;
|
||||
writel_relaxed(lcsr, fbi->base + LCSR);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -1268,7 +1040,7 @@ sa1100fb_freq_policy(struct notifier_block *nb, unsigned long val,
|
||||
switch (val) {
|
||||
case CPUFREQ_ADJUST:
|
||||
case CPUFREQ_INCOMPATIBLE:
|
||||
printk(KERN_DEBUG "min dma period: %d ps, "
|
||||
dev_dbg(fbi->dev, "min dma period: %d ps, "
|
||||
"new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
|
||||
policy->max);
|
||||
/* todo: fill in min/max values */
|
||||
@ -1318,7 +1090,7 @@ static int sa1100fb_resume(struct platform_device *dev)
|
||||
* cache. Once this area is remapped, all virtual memory
|
||||
* access to the video memory should occur at the new region.
|
||||
*/
|
||||
static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
|
||||
static int __devinit sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
|
||||
{
|
||||
/*
|
||||
* We reserve one page for the palette, plus the size
|
||||
@ -1344,7 +1116,7 @@ static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
|
||||
}
|
||||
|
||||
/* Fake monspecs to fill in fbinfo structure */
|
||||
static struct fb_monspecs monspecs __initdata = {
|
||||
static struct fb_monspecs monspecs __devinitdata = {
|
||||
.hfmin = 30000,
|
||||
.hfmax = 70000,
|
||||
.vfmin = 50,
|
||||
@ -1352,10 +1124,11 @@ static struct fb_monspecs monspecs __initdata = {
|
||||
};
|
||||
|
||||
|
||||
static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
|
||||
static struct sa1100fb_info * __devinit sa1100fb_init_fbinfo(struct device *dev)
|
||||
{
|
||||
struct sa1100fb_mach_info *inf;
|
||||
struct sa1100fb_mach_info *inf = dev->platform_data;
|
||||
struct sa1100fb_info *fbi;
|
||||
unsigned i;
|
||||
|
||||
fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
|
||||
GFP_KERNEL);
|
||||
@ -1390,8 +1163,6 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
|
||||
fbi->rgb[RGB_8] = &rgb_8;
|
||||
fbi->rgb[RGB_16] = &def_rgb_16;
|
||||
|
||||
inf = sa1100fb_get_machine_info(fbi);
|
||||
|
||||
/*
|
||||
* People just don't seem to get this. We don't support
|
||||
* anything but correct entries now, so panic if someone
|
||||
@ -1402,13 +1173,10 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
|
||||
panic("sa1100fb error: invalid LCCR3 fields set or zero "
|
||||
"pixclock.");
|
||||
|
||||
fbi->max_xres = inf->xres;
|
||||
fbi->fb.var.xres = inf->xres;
|
||||
fbi->fb.var.xres_virtual = inf->xres;
|
||||
fbi->max_yres = inf->yres;
|
||||
fbi->fb.var.yres = inf->yres;
|
||||
fbi->fb.var.yres_virtual = inf->yres;
|
||||
fbi->max_bpp = inf->bpp;
|
||||
fbi->fb.var.bits_per_pixel = inf->bpp;
|
||||
fbi->fb.var.pixclock = inf->pixclock;
|
||||
fbi->fb.var.hsync_len = inf->hsync_len;
|
||||
@ -1419,14 +1187,16 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
|
||||
fbi->fb.var.lower_margin = inf->lower_margin;
|
||||
fbi->fb.var.sync = inf->sync;
|
||||
fbi->fb.var.grayscale = inf->cmap_greyscale;
|
||||
fbi->cmap_inverse = inf->cmap_inverse;
|
||||
fbi->cmap_static = inf->cmap_static;
|
||||
fbi->lccr0 = inf->lccr0;
|
||||
fbi->lccr3 = inf->lccr3;
|
||||
fbi->state = C_STARTUP;
|
||||
fbi->task_state = (u_char)-1;
|
||||
fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
|
||||
fbi->max_bpp / 8;
|
||||
fbi->fb.fix.smem_len = inf->xres * inf->yres *
|
||||
inf->bpp / 8;
|
||||
fbi->inf = inf;
|
||||
|
||||
/* Copy the RGB bitfield overrides */
|
||||
for (i = 0; i < NR_RGB; i++)
|
||||
if (inf->rgb[i])
|
||||
fbi->rgb[i] = inf->rgb[i];
|
||||
|
||||
init_waitqueue_head(&fbi->ctrlr_wait);
|
||||
INIT_WORK(&fbi->task, sa1100fb_task);
|
||||
@ -1438,13 +1208,20 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
|
||||
static int __devinit sa1100fb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sa1100fb_info *fbi;
|
||||
struct resource *res;
|
||||
int ret, irq;
|
||||
|
||||
if (!pdev->dev.platform_data) {
|
||||
dev_err(&pdev->dev, "no platform LCD data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0)
|
||||
if (irq < 0 || !res)
|
||||
return -EINVAL;
|
||||
|
||||
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
|
||||
if (!request_mem_region(res->start, resource_size(res), "LCD"))
|
||||
return -EBUSY;
|
||||
|
||||
fbi = sa1100fb_init_fbinfo(&pdev->dev);
|
||||
@ -1452,6 +1229,10 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
|
||||
if (!fbi)
|
||||
goto failed;
|
||||
|
||||
fbi->base = ioremap(res->start, resource_size(res));
|
||||
if (!fbi->base)
|
||||
goto failed;
|
||||
|
||||
/* Initialize video memory */
|
||||
ret = sa1100fb_map_video_memory(fbi);
|
||||
if (ret)
|
||||
@ -1459,14 +1240,16 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
|
||||
|
||||
ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
|
||||
dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
#ifdef ASSABET_PAL_VIDEO
|
||||
if (machine_is_assabet())
|
||||
ASSABET_BCR_clear(ASSABET_BCR_LCD_ON);
|
||||
#endif
|
||||
if (machine_is_shannon()) {
|
||||
ret = gpio_request_one(SHANNON_GPIO_DISP_EN,
|
||||
GPIOF_OUT_INIT_LOW, "display enable");
|
||||
if (ret)
|
||||
goto err_free_irq;
|
||||
}
|
||||
|
||||
/*
|
||||
* This makes sure that our colour bitfield
|
||||
@ -1478,7 +1261,7 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
|
||||
|
||||
ret = register_framebuffer(&fbi->fb);
|
||||
if (ret < 0)
|
||||
goto err_free_irq;
|
||||
goto err_reg_fb;
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
|
||||
@ -1490,12 +1273,17 @@ static int __devinit sa1100fb_probe(struct platform_device *pdev)
|
||||
/* This driver cannot be unloaded at the moment */
|
||||
return 0;
|
||||
|
||||
err_reg_fb:
|
||||
if (machine_is_shannon())
|
||||
gpio_free(SHANNON_GPIO_DISP_EN);
|
||||
err_free_irq:
|
||||
free_irq(irq, fbi);
|
||||
failed:
|
||||
if (fbi)
|
||||
iounmap(fbi->base);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
kfree(fbi);
|
||||
release_mem_region(0xb0100000, 0x10000);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1505,6 +1293,7 @@ static struct platform_driver sa1100fb_driver = {
|
||||
.resume = sa1100fb_resume,
|
||||
.driver = {
|
||||
.name = "sa11x0-fb",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -10,44 +10,15 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These are the bitfields for each
|
||||
* display depth that we support.
|
||||
*/
|
||||
struct sa1100fb_rgb {
|
||||
struct fb_bitfield red;
|
||||
struct fb_bitfield green;
|
||||
struct fb_bitfield blue;
|
||||
struct fb_bitfield transp;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure describes the machine which we are running on.
|
||||
*/
|
||||
struct sa1100fb_mach_info {
|
||||
u_long pixclock;
|
||||
|
||||
u_short xres;
|
||||
u_short yres;
|
||||
|
||||
u_char bpp;
|
||||
u_char hsync_len;
|
||||
u_char left_margin;
|
||||
u_char right_margin;
|
||||
|
||||
u_char vsync_len;
|
||||
u_char upper_margin;
|
||||
u_char lower_margin;
|
||||
u_char sync;
|
||||
|
||||
u_int cmap_greyscale:1,
|
||||
cmap_inverse:1,
|
||||
cmap_static:1,
|
||||
unused:29;
|
||||
|
||||
u_int lccr0;
|
||||
u_int lccr3;
|
||||
};
|
||||
#define LCCR0 0x0000 /* LCD Control Reg. 0 */
|
||||
#define LCSR 0x0004 /* LCD Status Reg. */
|
||||
#define DBAR1 0x0010 /* LCD DMA Base Address Reg. channel 1 */
|
||||
#define DCAR1 0x0014 /* LCD DMA Current Address Reg. channel 1 */
|
||||
#define DBAR2 0x0018 /* LCD DMA Base Address Reg. channel 2 */
|
||||
#define DCAR2 0x001C /* LCD DMA Current Address Reg. channel 2 */
|
||||
#define LCCR1 0x0020 /* LCD Control Reg. 1 */
|
||||
#define LCCR2 0x0024 /* LCD Control Reg. 2 */
|
||||
#define LCCR3 0x0028 /* LCD Control Reg. 3 */
|
||||
|
||||
/* Shadows for LCD controller registers */
|
||||
struct sa1100fb_lcd_reg {
|
||||
@ -57,19 +28,11 @@ struct sa1100fb_lcd_reg {
|
||||
unsigned long lccr3;
|
||||
};
|
||||
|
||||
#define RGB_4 (0)
|
||||
#define RGB_8 (1)
|
||||
#define RGB_16 (2)
|
||||
#define NR_RGB 3
|
||||
|
||||
struct sa1100fb_info {
|
||||
struct fb_info fb;
|
||||
struct device *dev;
|
||||
struct sa1100fb_rgb *rgb[NR_RGB];
|
||||
|
||||
u_int max_bpp;
|
||||
u_int max_xres;
|
||||
u_int max_yres;
|
||||
const struct sa1100fb_rgb *rgb[NR_RGB];
|
||||
void __iomem *base;
|
||||
|
||||
/*
|
||||
* These are the addresses we mapped
|
||||
@ -88,12 +51,6 @@ struct sa1100fb_info {
|
||||
dma_addr_t dbar1;
|
||||
dma_addr_t dbar2;
|
||||
|
||||
u_int lccr0;
|
||||
u_int lccr3;
|
||||
u_int cmap_inverse:1,
|
||||
cmap_static:1,
|
||||
unused:30;
|
||||
|
||||
u_int reg_lccr0;
|
||||
u_int reg_lccr1;
|
||||
u_int reg_lccr2;
|
||||
@ -109,6 +66,8 @@ struct sa1100fb_info {
|
||||
struct notifier_block freq_transition;
|
||||
struct notifier_block freq_policy;
|
||||
#endif
|
||||
|
||||
const struct sa1100fb_mach_info *inf;
|
||||
};
|
||||
|
||||
#define TO_INF(ptr,member) container_of(ptr,struct sa1100fb_info,member)
|
||||
@ -129,15 +88,6 @@ struct sa1100fb_info {
|
||||
|
||||
#define SA1100_NAME "SA1100"
|
||||
|
||||
/*
|
||||
* Debug macros
|
||||
*/
|
||||
#if DEBUG
|
||||
# define DPRINTK(fmt, args...) printk("%s: " fmt, __func__ , ## args)
|
||||
#else
|
||||
# define DPRINTK(fmt, args...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Minimum X and Y resolutions
|
||||
*/
|
||||
|
@ -10,8 +10,6 @@
|
||||
#ifndef MCP_H
|
||||
#define MCP_H
|
||||
|
||||
#include <mach/dma.h>
|
||||
|
||||
struct mcp_ops;
|
||||
|
||||
struct mcp {
|
||||
@ -21,12 +19,7 @@ struct mcp {
|
||||
int use_count;
|
||||
unsigned int sclk_rate;
|
||||
unsigned int rw_timeout;
|
||||
dma_device_t dma_audio_rd;
|
||||
dma_device_t dma_audio_wr;
|
||||
dma_device_t dma_telco_rd;
|
||||
dma_device_t dma_telco_wr;
|
||||
struct device attached_device;
|
||||
int gpio_base;
|
||||
};
|
||||
|
||||
struct mcp_ops {
|
||||
@ -47,15 +40,14 @@ void mcp_disable(struct mcp *);
|
||||
#define mcp_get_sclk_rate(mcp) ((mcp)->sclk_rate)
|
||||
|
||||
struct mcp *mcp_host_alloc(struct device *, size_t);
|
||||
int mcp_host_register(struct mcp *);
|
||||
void mcp_host_unregister(struct mcp *);
|
||||
int mcp_host_add(struct mcp *, void *);
|
||||
void mcp_host_del(struct mcp *);
|
||||
void mcp_host_free(struct mcp *);
|
||||
|
||||
struct mcp_driver {
|
||||
struct device_driver drv;
|
||||
int (*probe)(struct mcp *);
|
||||
void (*remove)(struct mcp *);
|
||||
int (*suspend)(struct mcp *, pm_message_t);
|
||||
int (*resume)(struct mcp *);
|
||||
};
|
||||
|
||||
int mcp_driver_register(struct mcp_driver *);
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
#include <linux/mfd/mcp.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#define UCB_IO_DATA 0x00
|
||||
#define UCB_IO_DIR 0x01
|
||||
@ -104,17 +104,27 @@
|
||||
#define UCB_MODE_DYN_VFLAG_ENA (1 << 12)
|
||||
#define UCB_MODE_AUD_OFF_CAN (1 << 13)
|
||||
|
||||
enum ucb1x00_reset {
|
||||
UCB_RST_PROBE,
|
||||
UCB_RST_RESUME,
|
||||
UCB_RST_SUSPEND,
|
||||
UCB_RST_REMOVE,
|
||||
UCB_RST_PROBE_FAIL,
|
||||
};
|
||||
|
||||
struct ucb1x00_irq {
|
||||
void *devid;
|
||||
void (*fn)(int, void *);
|
||||
struct ucb1x00_plat_data {
|
||||
void (*reset)(enum ucb1x00_reset);
|
||||
unsigned irq_base;
|
||||
int gpio_base;
|
||||
unsigned can_wakeup;
|
||||
};
|
||||
|
||||
struct ucb1x00 {
|
||||
spinlock_t lock;
|
||||
raw_spinlock_t irq_lock;
|
||||
struct mcp *mcp;
|
||||
unsigned int irq;
|
||||
struct semaphore adc_sem;
|
||||
int irq_base;
|
||||
struct mutex adc_mutex;
|
||||
spinlock_t io_lock;
|
||||
u16 id;
|
||||
u16 io_dir;
|
||||
@ -122,7 +132,8 @@ struct ucb1x00 {
|
||||
u16 adc_cr;
|
||||
u16 irq_fal_enbl;
|
||||
u16 irq_ris_enbl;
|
||||
struct ucb1x00_irq irq_handler[16];
|
||||
u16 irq_mask;
|
||||
u16 irq_wake;
|
||||
struct device dev;
|
||||
struct list_head node;
|
||||
struct list_head devs;
|
||||
@ -144,7 +155,7 @@ struct ucb1x00_driver {
|
||||
struct list_head devs;
|
||||
int (*add)(struct ucb1x00_dev *dev);
|
||||
void (*remove)(struct ucb1x00_dev *dev);
|
||||
int (*suspend)(struct ucb1x00_dev *dev, pm_message_t state);
|
||||
int (*suspend)(struct ucb1x00_dev *dev);
|
||||
int (*resume)(struct ucb1x00_dev *dev);
|
||||
};
|
||||
|
||||
@ -245,15 +256,4 @@ unsigned int ucb1x00_adc_read(struct ucb1x00 *ucb, int adc_channel, int sync);
|
||||
void ucb1x00_adc_enable(struct ucb1x00 *ucb);
|
||||
void ucb1x00_adc_disable(struct ucb1x00 *ucb);
|
||||
|
||||
/*
|
||||
* Which edges of the IRQ do you want to control today?
|
||||
*/
|
||||
#define UCB_RISING (1 << 0)
|
||||
#define UCB_FALLING (1 << 1)
|
||||
|
||||
int ucb1x00_hook_irq(struct ucb1x00 *ucb, unsigned int idx, void (*fn)(int, void *), void *devid);
|
||||
void ucb1x00_enable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
|
||||
void ucb1x00_disable_irq(struct ucb1x00 *ucb, unsigned int idx, int edges);
|
||||
int ucb1x00_free_irq(struct ucb1x00 *ucb, unsigned int idx, void *devid);
|
||||
|
||||
#endif
|
||||
|
24
include/linux/sa11x0-dma.h
Normal file
24
include/linux/sa11x0-dma.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SA11x0 DMA Engine support
|
||||
*
|
||||
* Copyright (C) 2012 Russell King
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef __LINUX_SA11X0_DMA_H
|
||||
#define __LINUX_SA11X0_DMA_H
|
||||
|
||||
struct dma_chan;
|
||||
|
||||
#if defined(CONFIG_DMA_SA11X0) || defined(CONFIG_DMA_SA11X0_MODULE)
|
||||
bool sa11x0_dma_filter_fn(struct dma_chan *, void *);
|
||||
#else
|
||||
static inline bool sa11x0_dma_filter_fn(struct dma_chan *c, void *d)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
63
include/video/sa1100fb.h
Normal file
63
include/video/sa1100fb.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* StrongARM 1100 LCD Controller Frame Buffer Device
|
||||
*
|
||||
* Copyright (C) 1999 Eric A. Thomas
|
||||
* Based on acornfb.c Copyright (C) Russell King.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU General Public
|
||||
* License. See the file COPYING in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#ifndef _VIDEO_SA1100FB_H
|
||||
#define _VIDEO_SA1100FB_H
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define RGB_4 0
|
||||
#define RGB_8 1
|
||||
#define RGB_16 2
|
||||
#define NR_RGB 3
|
||||
|
||||
/* These are the bitfields for each display depth that we support. */
|
||||
struct sa1100fb_rgb {
|
||||
struct fb_bitfield red;
|
||||
struct fb_bitfield green;
|
||||
struct fb_bitfield blue;
|
||||
struct fb_bitfield transp;
|
||||
};
|
||||
|
||||
/* This structure describes the machine which we are running on. */
|
||||
struct sa1100fb_mach_info {
|
||||
u_long pixclock;
|
||||
|
||||
u_short xres;
|
||||
u_short yres;
|
||||
|
||||
u_char bpp;
|
||||
u_char hsync_len;
|
||||
u_char left_margin;
|
||||
u_char right_margin;
|
||||
|
||||
u_char vsync_len;
|
||||
u_char upper_margin;
|
||||
u_char lower_margin;
|
||||
u_char sync;
|
||||
|
||||
u_int cmap_greyscale:1,
|
||||
cmap_inverse:1,
|
||||
cmap_static:1,
|
||||
unused:29;
|
||||
|
||||
u_int lccr0;
|
||||
u_int lccr3;
|
||||
|
||||
/* Overrides for the default RGB maps */
|
||||
const struct sa1100fb_rgb *rgb[NR_RGB];
|
||||
|
||||
void (*backlight_power)(int);
|
||||
void (*lcd_power)(int);
|
||||
void (*set_visual)(u32);
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user