diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-01-29 11:19:06 (GMT) |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2012-02-09 15:34:17 (GMT) |
commit | f942b0fd6c81416bb8d52bc26a76a58c02d87bc2 (patch) | |
tree | f967454e0cc399bd24392a2da8472d63d3302f38 /arch/arm/mach-sa1100/neponset.c | |
parent | bab50a35ee703955bd708a4a44cd56ed30e601c8 (diff) | |
download | linux-f942b0fd6c81416bb8d52bc26a76a58c02d87bc2.tar.xz |
ARM: sa11x0: neponset: move register definitions to neponset.c
Move the board specific neponset register definitions to the board
file, rather than mach/neponset.h. However, as the NCR_0 register
definitions are used by some drivers, leave these behind.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-sa1100/neponset.c')
-rw-r--r-- | arch/arm/mach-sa1100/neponset.c | 114 |
1 files changed, 91 insertions, 23 deletions
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c index 2a9e1e2..3c0d4b8 100644 --- a/arch/arm/mach-sa1100/neponset.c +++ b/arch/arm/mach-sa1100/neponset.c @@ -27,9 +27,40 @@ #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; @@ -39,19 +70,34 @@ struct neponset_drvdata { #endif }; +static void __iomem *nep_base; + void neponset_ncr_frob(unsigned int mask, unsigned int val) { - unsigned long flags; - - local_irq_save(flags); - NCR_0 = (NCR_0 & ~mask) | val; - local_irq_restore(flags); + void __iomem *base = nep_base; + + if (base) { + unsigned long flags; + unsigned v; + + 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; @@ -74,14 +120,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; @@ -128,7 +179,8 @@ static void neponset_irq_handler(unsigned int irq, struct irq_desc *desc) * 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); + irr = readb_relaxed(d->base + IRR); + irr ^= IRR_ETHERNET | IRR_USAR; if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0) break; @@ -182,7 +234,7 @@ static struct sa1111_platform_data sa1111_info = { static int __devinit neponset_probe(struct platform_device *dev) { struct neponset_drvdata *d; - struct resource *sa1111_res, *smc91x_res; + struct resource *nep_res, *sa1111_res, *smc91x_res; struct resource sa1111_resources[] = { DEFINE_RES_MEM(0x40000000, SZ_8K), { .flags = IORESOURCE_IRQ }, @@ -213,30 +265,40 @@ static int __devinit neponset_probe(struct platform_device *dev) }; 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 (!smc91x_res || !sa1111_res) { + if (!nep_res || !smc91x_res || !sa1111_res) { ret = -ENXIO; goto err_alloc; } - if (WHOAMI != 0x11) { - dev_warn(&dev->dev, "Neponset board detected, but wrong ID: %02x\n", - WHOAMI); - ret = -ENODEV; - 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", @@ -270,6 +332,7 @@ static int __devinit neponset_probe(struct platform_device *dev) 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; sa1100_register_uart_fns(&neponset_port_fns); @@ -277,7 +340,7 @@ static int __devinit neponset_probe(struct platform_device *dev) sa1110_mb_disable(); /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */ - NCR_0 = NCR_GP01_OFF; + 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; @@ -295,6 +358,9 @@ static int __devinit neponset_probe(struct platform_device *dev) return 0; err_irq_alloc: + err_id: + iounmap(d->base); + err_ioremap: kfree(d); err_alloc: return ret; @@ -311,6 +377,8 @@ static int __devexit neponset_remove(struct platform_device *dev) 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; @@ -321,8 +389,8 @@ static int neponset_suspend(struct device *dev) { struct neponset_drvdata *d = dev_get_drvdata(dev); - d->ncr0 = NCR_0; - d->mdm_ctl_0 = MDM_CTL_0; + d->ncr0 = readb_relaxed(d->base + NCR_0); + d->mdm_ctl_0 = readb_relaxed(d->base + MDM_CTL_0); return 0; } @@ -331,8 +399,8 @@ static int neponset_resume(struct device *dev) { struct neponset_drvdata *d = dev_get_drvdata(dev); - NCR_0 = d->ncr0; - MDM_CTL_0 = d->mdm_ctl_0; + writeb_relaxed(d->ncr0, d->base + NCR_0); + writeb_relaxed(d->mdm_ctl_0, d->base + MDM_CTL_0); return 0; } |