summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-12 18:11:33 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-12 18:11:33 -0700
commitf7d02ae76ebbf5b8a9531fe150c49e126a397704 (patch)
treebcfdcab6e70658d55a3c843694e04e938bf9168f /drivers
parent78db2ad6f4df9145bfd6aab1c0f1c56d615288ec (diff)
parent158304ef09a28c7f2dd37d78f536a4e09ba084a1 (diff)
Merge branch 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'for-linus' of master.kernel.org:/home/rmk/linux-2.6-arm: (30 commits) [ARM] Use new get_irqnr_preamble [ARM] Ensure machine class menu is sorted alphabetically [ARM] 4333/2: KS8695: Micrel Development board [ARM] 4332/2: KS8695: Serial driver [ARM] 4331/3: Support for Micrel/Kendin KS8695 processor [ARM] 4371/1: AT91: Support for Atmel AT91SAM9RL-EK development board [ARM] 4372/1: Define byte sizes in asm-arm/sizes.h [ARM] 4370/3: AT91: Support for Atmel AT91SAM9RL processors. [ARM] Update mach-types [ARM] export symbol csum_partial_copy_from_user [ARM] iop13xx: msi support [ARM] stacktrace fix [ARM] Spinlock initializer cleanup [ARM] remove useless config option GENERIC_BUST_SPINLOCK [ARM] 4303/3: base kernel support for TI DaVinci [ARM] 4369/1: AT91: Fix circular dependency in header files [ARM] 4368/1: S3C24xx: build fix [ARM] 4364/1: AT91: LEDS on AT91SAM9261-EK [ARM] Fix iop32x/iop33x build [ARM] EBSA110: fix build errors caused by missing "const" ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/pata_icside.c184
-rw-r--r--drivers/ide/arm/icside.c41
-rw-r--r--drivers/ide/arm/rapide.c5
-rw-r--r--drivers/net/arm/ether1.c6
-rw-r--r--drivers/net/arm/ether3.c6
-rw-r--r--drivers/net/arm/etherh.c17
-rw-r--r--drivers/scsi/arm/arxescsi.c12
-rw-r--r--drivers/scsi/arm/cumana_2.c16
-rw-r--r--drivers/scsi/arm/eesox.c16
-rw-r--r--drivers/scsi/arm/powertec.c16
-rw-r--r--drivers/serial/8250_acorn.c3
-rw-r--r--drivers/serial/Kconfig17
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_ks8695.c657
-rw-r--r--drivers/usb/gadget/Kconfig2
15 files changed, 804 insertions, 195 deletions
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
index dbc8ee2adcf0..c791a46df461 100644
--- a/drivers/ata/pata_icside.c
+++ b/drivers/ata/pata_icside.c
@@ -60,6 +60,18 @@ struct pata_icside_state {
struct scatterlist sg[PATA_ICSIDE_MAX_SG];
};
+struct pata_icside_info {
+ struct pata_icside_state *state;
+ struct expansion_card *ec;
+ void __iomem *base;
+ void __iomem *irqaddr;
+ unsigned int irqmask;
+ const expansioncard_ops_t *irqops;
+ unsigned int mwdma_mask;
+ unsigned int nr_ports;
+ const struct portinfo *port[2];
+};
+
#define ICS_TYPE_A3IN 0
#define ICS_TYPE_A3USER 1
#define ICS_TYPE_V6 3
@@ -269,9 +281,10 @@ static u8 pata_icside_bmdma_status(struct ata_port *ap)
return readb(irq_port) & 1 ? ATA_DMA_INTR : 0;
}
-static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec)
+static int icside_dma_init(struct pata_icside_info *info)
{
- struct pata_icside_state *state = ae->private_data;
+ struct pata_icside_state *state = info->state;
+ struct expansion_card *ec = info->ec;
int i;
for (i = 0; i < ATA_MAX_DEVICES; i++) {
@@ -281,7 +294,7 @@ static int icside_dma_init(struct ata_probe_ent *ae, struct expansion_card *ec)
if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
state->dma = ec->dma;
- ae->mwdma_mask = 0x07; /* MW0..2 */
+ info->mwdma_mask = 0x07; /* MW0..2 */
}
return 0;
@@ -371,6 +384,8 @@ static struct ata_port_operations pata_icside_port_ops = {
.check_status = ata_check_status,
.dev_select = ata_std_dev_select,
+ .cable_detect = ata_cable_40wire,
+
.bmdma_setup = pata_icside_bmdma_setup,
.bmdma_start = pata_icside_bmdma_start,
@@ -385,7 +400,6 @@ static struct ata_port_operations pata_icside_port_ops = {
.error_handler = ata_bmdma_error_handler,
.post_internal_cmd = pata_icside_bmdma_stop,
- .irq_handler = ata_interrupt,
.irq_clear = ata_dummy_noret,
.irq_on = ata_irq_on,
.irq_ack = pata_icside_irq_ack,
@@ -396,11 +410,10 @@ static struct ata_port_operations pata_icside_port_ops = {
.bmdma_status = pata_icside_bmdma_status,
};
-static void
-pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base,
- const struct portinfo *info)
+static void __devinit
+pata_icside_setup_ioaddr(struct ata_ioports *ioaddr, void __iomem *base,
+ const struct portinfo *info)
{
- struct ata_ioports *ioaddr = &ae->port[ae->n_ports++];
void __iomem *cmd = base + info->dataoffset;
ioaddr->cmd_addr = cmd;
@@ -419,58 +432,44 @@ pata_icside_add_port(struct ata_probe_ent *ae, void __iomem *base,
ioaddr->altstatus_addr = ioaddr->ctl_addr;
}
-static int __init
-pata_icside_register_v5(struct ata_probe_ent *ae, struct expansion_card *ec)
+static int __devinit pata_icside_register_v5(struct pata_icside_info *info)
{
- struct pata_icside_state *state = ae->private_data;
+ struct pata_icside_state *state = info->state;
void __iomem *base;
- base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
- ecard_resource_len(ec, ECARD_RES_MEMC));
+ base = ecardm_iomap(info->ec, ECARD_RES_MEMC, 0, 0);
if (!base)
return -ENOMEM;
state->irq_port = base;
- ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
- ec->irqmask = 1;
- ec->irq_data = state;
- ec->ops = &pata_icside_ops_arcin_v5;
-
- /*
- * Be on the safe side - disable interrupts
- */
- ec->ops->irqdisable(ec, ec->irq);
-
- pata_icside_add_port(ae, base, &pata_icside_portinfo_v5);
+ info->base = base;
+ info->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
+ info->irqmask = 1;
+ info->irqops = &pata_icside_ops_arcin_v5;
+ info->nr_ports = 1;
+ info->port[0] = &pata_icside_portinfo_v5;
return 0;
}
-static int __init
-pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec)
+static int __devinit pata_icside_register_v6(struct pata_icside_info *info)
{
- struct pata_icside_state *state = ae->private_data;
+ struct pata_icside_state *state = info->state;
+ struct expansion_card *ec = info->ec;
void __iomem *ioc_base, *easi_base;
unsigned int sel = 0;
- int ret;
- ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
- ecard_resource_len(ec, ECARD_RES_IOCFAST));
- if (!ioc_base) {
- ret = -ENOMEM;
- goto out;
- }
+ ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
+ if (!ioc_base)
+ return -ENOMEM;
easi_base = ioc_base;
if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
- easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),
- ecard_resource_len(ec, ECARD_RES_EASI));
- if (!easi_base) {
- ret = -ENOMEM;
- goto unmap_slot;
- }
+ easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
+ if (!easi_base)
+ return -ENOMEM;
/*
* Enable access to the EASI region.
@@ -480,45 +479,72 @@ pata_icside_register_v6(struct ata_probe_ent *ae, struct expansion_card *ec)
writeb(sel, ioc_base);
- ec->irq_data = state;
- ec->ops = &pata_icside_ops_arcin_v6;
-
state->irq_port = easi_base;
state->ioc_base = ioc_base;
state->port[0].port_sel = sel;
state->port[1].port_sel = sel | 1;
/*
- * Be on the safe side - disable interrupts
- */
- ec->ops->irqdisable(ec, ec->irq);
-
- /*
- * Find and register the interfaces.
- */
- pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_1);
- pata_icside_add_port(ae, easi_base, &pata_icside_portinfo_v6_2);
-
- /*
* FIXME: work around libata's aversion to calling port_disable.
* This permanently disables interrupts on port 0 - bad luck if
* you have a drive on that port.
*/
state->port[0].disabled = 1;
- return icside_dma_init(ae, ec);
+ info->base = easi_base;
+ info->irqops = &pata_icside_ops_arcin_v6;
+ info->nr_ports = 2;
+ info->port[0] = &pata_icside_portinfo_v6_1;
+ info->port[1] = &pata_icside_portinfo_v6_2;
- unmap_slot:
- iounmap(ioc_base);
- out:
- return ret;
+ return icside_dma_init(info);
+}
+
+static int __devinit pata_icside_add_ports(struct pata_icside_info *info)
+{
+ struct expansion_card *ec = info->ec;
+ struct ata_host *host;
+ int i;
+
+ if (info->irqaddr) {
+ ec->irqaddr = info->irqaddr;
+ ec->irqmask = info->irqmask;
+ }
+ if (info->irqops)
+ ecard_setirq(ec, info->irqops, info->state);
+
+ /*
+ * Be on the safe side - disable interrupts
+ */
+ ec->ops->irqdisable(ec, ec->irq);
+
+ host = ata_host_alloc(&ec->dev, info->nr_ports);
+ if (!host)
+ return -ENOMEM;
+
+ host->private_data = info->state;
+ host->flags = ATA_HOST_SIMPLEX;
+
+ for (i = 0; i < info->nr_ports; i++) {
+ struct ata_port *ap = host->ports[i];
+
+ ap->pio_mask = 0x1f;
+ ap->mwdma_mask = info->mwdma_mask;
+ ap->flags |= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
+ ap->ops = &pata_icside_port_ops;
+
+ pata_icside_setup_ioaddr(&ap->ioaddr, info->base, info->port[i]);
+ }
+
+ return ata_host_activate(host, ec->irq, ata_interrupt, 0,
+ &pata_icside_sht);
}
static int __devinit
pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct pata_icside_state *state;
- struct ata_probe_ent ae;
+ struct pata_icside_info info;
void __iomem *idmem;
int ret;
@@ -526,7 +552,7 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto out;
- state = kzalloc(sizeof(struct pata_icside_state), GFP_KERNEL);
+ state = devm_kzalloc(&ec->dev, sizeof(*state), GFP_KERNEL);
if (!state) {
ret = -ENOMEM;
goto release;
@@ -535,8 +561,7 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
state->type = ICS_TYPE_NOTYPE;
state->dma = NO_DMA;
- idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
- ecard_resource_len(ec, ECARD_RES_IOCFAST));
+ idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (idmem) {
unsigned int type;
@@ -544,21 +569,14 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
- iounmap(idmem);
+ ecardm_iounmap(ec, idmem);
state->type = type;
}
- memset(&ae, 0, sizeof(ae));
- INIT_LIST_HEAD(&ae.node);
- ae.dev = &ec->dev;
- ae.port_ops = &pata_icside_port_ops;
- ae.sht = &pata_icside_sht;
- ae.pio_mask = 0x1f;
- ae.irq = ec->irq;
- ae.port_flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST;
- ae._host_flags = ATA_HOST_SIMPLEX;
- ae.private_data = state;
+ memset(&info, 0, sizeof(info));
+ info.state = state;
+ info.ec = ec;
switch (state->type) {
case ICS_TYPE_A3IN:
@@ -572,11 +590,11 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
break;
case ICS_TYPE_V5:
- ret = pata_icside_register_v5(&ae, ec);
+ ret = pata_icside_register_v5(&info);
break;
case ICS_TYPE_V6:
- ret = pata_icside_register_v6(&ae, ec);
+ ret = pata_icside_register_v6(&info);
break;
default:
@@ -586,12 +604,11 @@ pata_icside_probe(struct expansion_card *ec, const struct ecard_id *id)
}
if (ret == 0)
- ret = ata_device_add(&ae) == 0 ? -ENODEV : 0;
+ ret = pata_icside_add_ports(&info);
if (ret == 0)
goto out;
- kfree(state);
release:
ecard_release_resources(ec);
out:
@@ -609,8 +626,7 @@ static void pata_icside_shutdown(struct expansion_card *ec)
* this register via that region.
*/
local_irq_save(flags);
- if (ec->ops)
- ec->ops->irqdisable(ec, ec->irq);
+ ec->ops->irqdisable(ec, ec->irq);
local_irq_restore(flags);
/*
@@ -638,17 +654,9 @@ static void __devexit pata_icside_remove(struct expansion_card *ec)
* don't NULL out the drvdata - devres/libata wants it
* to free the ata_host structure.
*/
- ec->ops = NULL;
- ec->irq_data = NULL;
-
if (state->dma != NO_DMA)
free_dma(state->dma);
- if (state->ioc_base)
- iounmap(state->ioc_base);
- if (state->ioc_base != state->irq_port)
- iounmap(state->irq_port);
- kfree(state);
ecard_release_resources(ec);
}
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 1fe0457243db..66f826252aee 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -565,8 +565,7 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
ide_hwif_t *hwif;
void __iomem *base;
- base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
- ecard_resource_len(ec, ECARD_RES_MEMC));
+ base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base)
return -ENOMEM;
@@ -574,8 +573,8 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
ec->irqaddr = base + ICS_ARCIN_V5_INTRSTAT;
ec->irqmask = 1;
- ec->irq_data = state;
- ec->ops = &icside_ops_arcin_v5;
+
+ ecard_setirq(ec, &icside_ops_arcin_v5, state);
/*
* Be on the safe side - disable interrupts
@@ -583,10 +582,8 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
icside_irqdisable_arcin_v5(ec, 0);
hwif = icside_setup(base, &icside_cardinfo_v5, ec);
- if (!hwif) {
- iounmap(base);
+ if (!hwif)
return -ENODEV;
- }
state->hwif[0] = hwif;
@@ -605,8 +602,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
unsigned int sel = 0;
int ret;
- ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
- ecard_resource_len(ec, ECARD_RES_IOCFAST));
+ ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!ioc_base) {
ret = -ENOMEM;
goto out;
@@ -615,11 +611,10 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
easi_base = ioc_base;
if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
- easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),
- ecard_resource_len(ec, ECARD_RES_EASI));
+ easi_base = ecardm_iomap(ec, ECARD_RES_EASI, 0, 0);
if (!easi_base) {
ret = -ENOMEM;
- goto unmap_slot;
+ goto out;
}
/*
@@ -630,8 +625,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
writeb(sel, ioc_base);
- ec->irq_data = state;
- ec->ops = &icside_ops_arcin_v6;
+ ecard_setirq(ec, &icside_ops_arcin_v6, state);
state->irq_port = easi_base;
state->ioc_base = ioc_base;
@@ -649,7 +643,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
if (!hwif || !mate) {
ret = -ENODEV;
- goto unmap_port;
+ goto out;
}
state->hwif[0] = hwif;
@@ -686,11 +680,6 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
return 0;
- unmap_port:
- if (easi_base != ioc_base)
- iounmap(easi_base);
- unmap_slot:
- iounmap(ioc_base);
out:
return ret;
}
@@ -716,8 +705,7 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
state->type = ICS_TYPE_NOTYPE;
state->dev = &ec->dev;
- idmem = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
- ecard_resource_len(ec, ECARD_RES_IOCFAST));
+ idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (idmem) {
unsigned int type;
@@ -725,7 +713,7 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
type |= (readb(idmem + ICS_IDENT_OFFSET + 4) & 1) << 1;
type |= (readb(idmem + ICS_IDENT_OFFSET + 8) & 1) << 2;
type |= (readb(idmem + ICS_IDENT_OFFSET + 12) & 1) << 3;
- iounmap(idmem);
+ ecardm_iounmap(ec, idmem);
state->type = type;
}
@@ -793,13 +781,6 @@ static void __devexit icside_remove(struct expansion_card *ec)
}
ecard_set_drvdata(ec, NULL);
- ec->ops = NULL;
- ec->irq_data = NULL;
-
- if (state->ioc_base)
- iounmap(state->ioc_base);
- if (state->ioc_base != state->irq_port)
- iounmap(state->irq_port);
kfree(state);
ecard_release_resources(ec);
diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
index 890ea3fac3c6..83811af11610 100644
--- a/drivers/ide/arm/rapide.c
+++ b/drivers/ide/arm/rapide.c
@@ -63,8 +63,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto out;
- base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
- ecard_resource_len(ec, ECARD_RES_MEMC));
+ base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base) {
ret = -ENOMEM;
goto release;
@@ -81,7 +80,6 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
goto out;
}
- iounmap(base);
release:
ecard_release_resources(ec);
out:
@@ -96,7 +94,6 @@ static void __devexit rapide_remove(struct expansion_card *ec)
/* there must be a better way */
ide_unregister(hwif - ide_hwifs);
- iounmap(hwif->hwif_data);
ecard_release_resources(ec);
}
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index f075cebe84ad..f21148e7b579 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -1014,8 +1014,7 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
SET_NETDEV_DEV(dev, &ec->dev);
dev->irq = ec->irq;
- priv(dev)->base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
- ecard_resource_len(ec, ECARD_RES_IOCFAST));
+ priv(dev)->base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!priv(dev)->base) {
ret = -ENOMEM;
goto free;
@@ -1056,8 +1055,6 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
return 0;
free:
- if (priv(dev)->base)
- iounmap(priv(dev)->base);
free_netdev(dev);
release:
ecard_release_resources(ec);
@@ -1072,7 +1069,6 @@ static void __devexit ether1_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL);
unregister_netdev(dev);
- iounmap(priv(dev)->base);
free_netdev(dev);
ecard_release_resources(ec);
}
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 32da2eb9bcee..da713500654d 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -793,8 +793,7 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &ec->dev);
- priv(dev)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
- ecard_resource_len(ec, ECARD_RES_MEMC));
+ priv(dev)->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!priv(dev)->base) {
ret = -ENOMEM;
goto free;
@@ -869,8 +868,6 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
return 0;
free:
- if (priv(dev)->base)
- iounmap(priv(dev)->base);
free_netdev(dev);
release:
ecard_release_resources(ec);
@@ -885,7 +882,6 @@ static void __devexit ether3_remove(struct expansion_card *ec)
ecard_set_drvdata(ec, NULL);
unregister_netdev(dev);
- iounmap(priv(dev)->base);
free_netdev(dev);
ecard_release_resources(ec);
}
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 61f574aa3a99..769ba69451f4 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -686,7 +686,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
eh->supported = data->supported;
eh->ctrl = 0;
eh->id = ec->cid.product;
- eh->memc = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC), PAGE_SIZE);
+ eh->memc = ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE);
if (!eh->memc) {
ret = -ENOMEM;
goto free;
@@ -694,7 +694,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
eh->ctrl_port = eh->memc;
if (data->ctrl_ioc) {
- eh->ioc_fast = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST), PAGE_SIZE);
+ eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE);
if (!eh->ioc_fast) {
ret = -ENOMEM;
goto free;
@@ -710,8 +710,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
* IRQ and control port handling - only for non-NIC slot cards.
*/
if (ec->slot_no != 8) {
- ec->ops = &etherh_ops;
- ec->irq_data = eh;
+ ecard_setirq(ec, &etherh_ops, eh);
} else {
/*
* If we're in the NIC slot, make sure the IRQ is enabled
@@ -759,10 +758,6 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
return 0;
free:
- if (eh->ioc_fast)
- iounmap(eh->ioc_fast);
- if (eh->memc)
- iounmap(eh->memc);
free_netdev(dev);
release:
ecard_release_resources(ec);
@@ -773,16 +768,10 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit etherh_remove(struct expansion_card *ec)
{
struct net_device *dev = ecard_get_drvdata(ec);
- struct etherh_priv *eh = etherh_priv(dev);
ecard_set_drvdata(ec, NULL);
unregister_netdev(dev);
- ec->ops = NULL;
-
- if (eh->ioc_fast)
- iounmap(eh->ioc_fast);
- iounmap(eh->memc);
free_netdev(dev);
diff --git a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
index 7e132c5bacf8..2836fe248df9 100644
--- a/drivers/scsi/arm/arxescsi.c
+++ b/drivers/scsi/arm/arxescsi.c
@@ -281,7 +281,6 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
struct arxescsi_info *info;
- unsigned long resbase, reslen;
void __iomem *base;
int ret;
@@ -289,9 +288,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto out;
- resbase = ecard_resource_start(ec, ECARD_RES_MEMC);
- reslen = ecard_resource_len(ec, ECARD_RES_MEMC);
- base = ioremap(resbase, reslen);
+ base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base) {
ret = -ENOMEM;
goto out_region;
@@ -300,7 +297,7 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
host = scsi_host_alloc(&arxescsi_template, sizeof(struct arxescsi_info));
if (!host) {
ret = -ENOMEM;
- goto out_unmap;
+ goto out_region;
}
info = (struct arxescsi_info *)host->hostdata;
@@ -337,8 +334,6 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
fas216_release(host);
out_unregister:
scsi_host_put(host);
- out_unmap:
- iounmap(base);
out_region:
ecard_release_resources(ec);
out:
@@ -348,13 +343,10 @@ arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id)
static void __devexit arxescsi_remove(struct expansion_card *ec)
{
struct Scsi_Host *host = ecard_get_drvdata(ec);
- struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
ecard_set_drvdata(ec, NULL);
fas216_remove(host);
- iounmap(info->base);
-
fas216_release(host);
scsi_host_put(host);
ecard_release_resources(ec);
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 82add77ad131..68a64123af8f 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -401,7 +401,6 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
struct cumanascsi2_info *info;
- unsigned long resbase, reslen;
void __iomem *base;
int ret;
@@ -409,9 +408,7 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto out;
- resbase = ecard_resource_start(ec, ECARD_RES_MEMC);
- reslen = ecard_resource_len(ec, ECARD_RES_MEMC);
- base = ioremap(resbase, reslen);
+ base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0);
if (!base) {
ret = -ENOMEM;
goto out_region;
@@ -421,7 +418,7 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
sizeof(struct cumanascsi2_info));
if (!host) {
ret = -ENOMEM;
- goto out_unmap;
+ goto out_region;
}
ecard_set_drvdata(ec, host);
@@ -450,8 +447,8 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
ec->irqaddr = info->base + CUMANASCSI2_STATUS;
ec->irqmask = STATUS_INT;
- ec->irq_data = info;
- ec->ops = &cumanascsi_2_ops;
+
+ ecard_setirq(ec, &cumanascsi_2_ops, info);
ret = fas216_init(host);
if (ret)
@@ -490,9 +487,6 @@ cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id)
out_free:
scsi_host_put(host);
- out_unmap:
- iounmap(base);
-
out_region:
ecard_release_resources(ec);
@@ -512,8 +506,6 @@ static void __devexit cumanascsi2_remove(struct expansion_card *ec)
free_dma(info->info.scsi.dma);
free_irq(ec->irq, info);
- iounmap(info->base);
-
fas216_release(host);
scsi_host_put(host);
ecard_release_resources(ec);
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index ed06a8c19ad6..bb2477b3fb0b 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -519,7 +519,6 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
struct eesoxscsi_info *info;
- unsigned long resbase, reslen;
void __iomem *base;
int ret;
@@ -527,9 +526,7 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto out;
- resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
- reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
- base = ioremap(resbase, reslen);
+ base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!base) {
ret = -ENOMEM;
goto out_region;
@@ -539,7 +536,7 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
sizeof(struct eesoxscsi_info));
if (!host) {
ret = -ENOMEM;
- goto out_unmap;
+ goto out_region;
}
ecard_set_drvdata(ec, host);
@@ -569,8 +566,8 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
ec->irqaddr = base + EESOX_DMASTAT;
ec->irqmask = EESOX_STAT_INTR;
- ec->irq_data = info;
- ec->ops = &eesoxscsi_ops;
+
+ ecard_setirq(ec, &eesoxscsi_ops, info);
device_create_file(&ec->dev, &dev_attr_bus_term);
@@ -612,9 +609,6 @@ eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
device_remove_file(&ec->dev, &dev_attr_bus_term);
scsi_host_put(host);
- out_unmap:
- iounmap(base);
-
out_region:
ecard_release_resources(ec);
@@ -636,8 +630,6 @@ static void __devexit eesoxscsi_remove(struct expansion_card *ec)
device_remove_file(&ec->dev, &dev_attr_bus_term);
- iounmap(info->base);
-
fas216_release(host);
scsi_host_put(host);
ecard_release_resources(ec);
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 159047a34997..d9a546d1917c 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -313,7 +313,6 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct Scsi_Host *host;
struct powertec_info *info;
- unsigned long resbase, reslen;
void __iomem *base;
int ret;
@@ -321,9 +320,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto out;
- resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST);
- reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST);
- base = ioremap(resbase, reslen);
+ base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
if (!base) {
ret = -ENOMEM;
goto out_region;
@@ -333,7 +330,7 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
sizeof (struct powertec_info));
if (!host) {
ret = -ENOMEM;
- goto out_unmap;
+ goto out_region;
}
ecard_set_drvdata(ec, host);
@@ -361,8 +358,8 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
ec->irqaddr = base + POWERTEC_INTR_STATUS;
ec->irqmask = POWERTEC_INTR_BIT;
- ec->irq_data = info;
- ec->ops = &powertecscsi_ops;
+
+ ecard_setirq(ec, &powertecscsi_ops, info);
device_create_file(&ec->dev, &dev_attr_bus_term);
@@ -404,9 +401,6 @@ powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id)
device_remove_file(&ec->dev, &dev_attr_bus_term);
scsi_host_put(host);
- out_unmap:
- iounmap(base);
-
out_region:
ecard_release_resources(ec);
@@ -428,8 +422,6 @@ static void __devexit powertecscsi_remove(struct expansion_card *ec)
free_dma(info->info.scsi.dma);
free_irq(ec->irq, info);
- iounmap(info->base);
-
fas216_release(host);
scsi_host_put(host);
ecard_release_resources(ec);
diff --git a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c
index 562ba745a044..b0ce8c56f1a4 100644
--- a/drivers/serial/8250_acorn.c
+++ b/drivers/serial/8250_acorn.c
@@ -54,7 +54,7 @@ serial_card_probe(struct expansion_card *ec, const struct ecard_id *id)
info->num_ports = type->num_ports;
bus_addr = ecard_resource_start(ec, type->type);
- info->vaddr = ioremap(bus_addr, ecard_resource_len(ec, type->type));
+ info->vaddr = ecardm_iomap(ec, type->type, 0, 0);
if (!info->vaddr) {
kfree(info);
return -ENOMEM;
@@ -91,7 +91,6 @@ static void __devexit serial_card_remove(struct expansion_card *ec)
if (info->ports[i] > 0)
serial8250_unregister_port(info->ports[i]);
- iounmap(info->vaddr);
kfree(info);
}
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index a6f5bfbb777b..315ea9916456 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -359,6 +359,23 @@ config SERIAL_ATMEL_TTYAT
Say Y if you have an external 8250/16C550 UART. If unsure, say N.
+config SERIAL_KS8695
+ bool "Micrel KS8695 (Centaur) serial port support"
+ depends on ARCH_KS8695
+ select SERIAL_CORE
+ help
+ This selects the Micrel Centaur KS8695 UART. Say Y here.
+
+config SERIAL_KS8695_CONSOLE
+ bool "Support for console on KS8695 (Centaur) serial port"
+ depends on SERIAL_KS8695=y
+ select SERIAL_CORE_CONSOLE
+ help
+ Say Y here if you wish to use a KS8695 (Centaur) UART as the
+ system console (the system console is the device which
+ receives all kernel messages and warnings and which allows
+ logins in single user mode).
+
config SERIAL_CLPS711X
tristate "CLPS711X serial port support"
depends on ARM && ARCH_CLPS711X
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 4959bcb8d1ef..08ad0d978183 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -61,3 +61,4 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o
obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
+obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
new file mode 100644
index 000000000000..c5346d677315
--- /dev/null
+++ b/drivers/serial/serial_ks8695.c
@@ -0,0 +1,657 @@
+/*
+ * drivers/serial/serial_ks8695.c
+ *
+ * Driver for KS8695 serial ports
+ *
+ * Based on drivers/serial/serial_amba.c, by Kam Lee.
+ *
+ * Copyright 2002-2005 Micrel Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/regs-uart.h>
+#include <asm/arch/regs-irq.h>
+
+#if defined(CONFIG_SERIAL_KS8695_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+
+
+#define SERIAL_KS8695_MAJOR 204
+#define SERIAL_KS8695_MINOR 16
+#define SERIAL_KS8695_DEVNAME "ttyAM"
+
+#define SERIAL_KS8695_NR 1
+
+/*
+ * Access macros for the KS8695 UART
+ */
+#define UART_GET_CHAR(p) (__raw_readl((p)->membase + KS8695_URRB) & 0xFF)
+#define UART_PUT_CHAR(p, c) __raw_writel((c), (p)->membase + KS8695_URTH)
+#define UART_GET_FCR(p) __raw_readl((p)->membase + KS8695_URFC)
+#define UART_PUT_FCR(p, c) __raw_writel((c), (p)->membase + KS8695_URFC)
+#define UART_GET_MSR(p) __raw_readl((p)->membase + KS8695_URMS)
+#define UART_GET_LSR(p) __raw_readl((p)->membase + KS8695_URLS)
+#define UART_GET_LCR(p) __raw_readl((p)->membase + KS8695_URLC)
+#define UART_PUT_LCR(p, c) __raw_writel((c), (p)->membase + KS8695_URLC)
+#define UART_GET_MCR(p) __raw_readl((p)->membase + KS8695_URMC)
+#define UART_PUT_MCR(p, c) __raw_writel((c), (p)->membase + KS8695_URMC)
+#define UART_GET_BRDR(p) __raw_readl((p)->membase + KS8695_URBD)
+#define UART_PUT_BRDR(p, c) __raw_writel((c), (p)->membase + KS8695_URBD)
+
+#define KS8695_CLR_TX_INT() __raw_writel(1 << KS8695_IRQ_UART_TX, KS8695_IRQ_VA + KS8695_INTST)
+
+#define UART_DUMMY_LSR_RX 0x100
+#define UART_PORT_SIZE (KS8695_USR - KS8695_URRB + 4)
+
+#define tx_enabled(port) ((port)->unused[0])
+#define rx_enabled(port) ((port)->unused[1])
+
+
+#ifdef SUPPORT_SYSRQ
+static struct console ks8695_console;
+#endif
+
+static void ks8695uart_stop_tx(struct uart_port *port)
+{
+ if (tx_enabled(port)) {
+ disable_irq(KS8695_IRQ_UART_TX);
+ tx_enabled(port) = 0;
+ }
+}
+
+static void ks8695uart_start_tx(struct uart_port *port)
+{
+ if (!tx_enabled(port)) {
+ enable_irq(KS8695_IRQ_UART_TX);
+ tx_enabled(port) = 1;
+ }
+}
+
+static void ks8695uart_stop_rx(struct uart_port *port)
+{
+ if (rx_enabled(port)) {
+ disable_irq(KS8695_IRQ_UART_RX);
+ rx_enabled(port) = 0;
+ }
+}
+
+static void ks8695uart_enable_ms(struct uart_port *port)
+{
+ enable_irq(KS8695_IRQ_UART_MODEM_STATUS);
+}
+
+static void ks8695uart_disable_ms(struct uart_port *port)
+{
+ disable_irq(KS8695_IRQ_UART_MODEM_STATUS);
+}
+
+static irqreturn_t ks8695uart_rx_chars(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ struct tty_struct *tty = port->info->tty;
+ unsigned int status, ch, lsr, flg, max_count = 256;
+
+ status = UART_GET_LSR(port); /* clears pending LSR interrupts */
+ while ((status & URLS_URDR) && max_count--) {
+ ch = UART_GET_CHAR(port);
+ flg = TTY_NORMAL;
+
+ port->icount.rx++;
+
+ /*
+ * Note that the error handling code is
+ * out of the main execution path
+ */
+ lsr = UART_GET_LSR(port) | UART_DUMMY_LSR_RX;
+ if (unlikely(lsr & (URLS_URBI | URLS_URPE | URLS_URFE | URLS_URROE))) {
+ if (lsr & URLS_URBI) {
+ lsr &= ~(URLS_URFE | URLS_URPE);
+ port->icount.brk++;
+ if (uart_handle_break(port))
+ goto ignore_char;
+ }
+ if (lsr & URLS_URPE)
+ port->icount.parity++;
+ if (lsr & URLS_URFE)
+ port->icount.frame++;
+ if (lsr & URLS_URROE)
+ port->icount.overrun++;
+
+ lsr &= port->read_status_mask;
+
+ if (lsr & URLS_URBI)
+ flg = TTY_BREAK;
+ else if (lsr & URLS_URPE)
+ flg = TTY_PARITY;
+ else if (lsr & URLS_URFE)
+ flg = TTY_FRAME;
+ }
+
+ if (uart_handle_sysrq_char(port, ch))
+ goto ignore_char;
+
+ uart_insert_char(port, lsr, URLS_URROE, ch, flg);
+
+ignore_char:
+ status = UART_GET_LSR(port);
+ }
+ tty_flip_buffer_push(tty);
+
+ return IRQ_HANDLED;
+}
+
+
+static irqreturn_t ks8695uart_tx_chars(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ struct circ_buf *xmit = &port->info->xmit;
+ unsigned int count;
+
+ if (port->x_char) {
+ KS8695_CLR_TX_INT();
+ UART_PUT_CHAR(port, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
+ return IRQ_HANDLED;
+ }
+
+ if (uart_tx_stopped(port) || uart_circ_empty(xmit)) {
+ ks8695uart_stop_tx(port);
+ return IRQ_HANDLED;
+ }
+
+ count = 16; /* fifo size */
+ while (!uart_circ_empty(xmit) && (count-- > 0)) {
+ KS8695_CLR_TX_INT();
+ UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ ks8695uart_stop_tx(port);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t ks8695uart_modem_status(int irq, void *dev_id)
+{
+ struct uart_port *port = dev_id;
+ unsigned int status;
+
+ /*
+ * clear modem interrupt by reading MSR
+ */
+ status = UART_GET_MSR(port);
+
+ if (status & URMS_URDDCD)
+ uart_handle_dcd_change(port, status & URMS_URDDCD);
+
+ if (status & URMS_URDDST)
+ port->icount.dsr++;
+
+ if (status & URMS_URDCTS)
+ uart_handle_cts_change(port, status & URMS_URDCTS);
+
+ if (status & URMS_URTERI)
+ port->icount.rng++;
+
+ wake_up_interruptible(&port->info->delta_msr_wait);
+
+ return IRQ_HANDLED;
+}
+
+static unsigned int ks8695uart_tx_empty(struct uart_port *port)
+{
+ return (UART_GET_LSR(port) & URLS_URTE) ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int ks8695uart_get_mctrl(struct uart_port *port)
+{
+ unsigned int result = 0;
+ unsigned int status;
+
+ status = UART_GET_MSR(port);
+ if (status & URMS_URDCD)
+ result |= TIOCM_CAR;
+ if (status & URMS_URDSR)
+ result |= TIOCM_DSR;
+ if (status & URMS_URCTS)
+ result |= TIOCM_CTS;
+ if (status & URMS_URRI)
+ result |= TIOCM_RI;
+
+ return result;
+}
+
+static void ks8695uart_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+ unsigned int mcr;
+
+ mcr = UART_GET_MCR(port);
+ if (mctrl & TIOCM_RTS)
+ mcr |= URMC_URRTS;
+ else
+ mcr &= ~URMC_URRTS;
+
+ if (mctrl & TIOCM_DTR)
+ mcr |= URMC_URDTR;
+ else
+ mcr &= ~URMC_URDTR;
+
+ UART_PUT_MCR(port, mcr);
+}
+
+static void ks8695uart_break_ctl(struct uart_port *port, int break_state)
+{
+ unsigned int lcr;
+
+ lcr = UART_GET_LCR(port);
+
+ if (break_state == -1)
+ lcr |= URLC_URSBC;
+ else
+ lcr &= ~URLC_URSBC;
+
+ UART_PUT_LCR(port, lcr);
+}
+
+static int ks8695uart_startup(struct uart_port *port)
+{
+ int retval;
+
+ set_irq_flags(KS8695_IRQ_UART_TX, IRQF_VALID | IRQF_NOAUTOEN);
+ tx_enabled(port) = 0;
+ rx_enabled(port) = 1;
+
+ /*
+ * Allocate the IRQ
+ */
+ retval = request_irq(KS8695_IRQ_UART_TX, ks8695uart_tx_chars, IRQF_DISABLED, "UART TX", port);
+ if (retval)
+ goto err_tx;
+
+ retval = request_irq(KS8695_IRQ_UART_RX, ks8695uart_rx_chars, IRQF_DISABLED, "UART RX", port);
+ if (retval)
+ goto err_rx;
+
+ retval = request_irq(KS8695_IRQ_UART_LINE_STATUS, ks8695uart_rx_chars, IRQF_DISABLED, "UART LineStatus", port);
+ if (retval)
+ return err_ls;
+
+ retval = request_irq(KS8695_IRQ_UART_MODEM_STATUS, ks8695uart_modem_status, IRQF_DISABLED, "UART ModemStatus", port);
+ if (retval)
+ return err_ms;
+
+ return 0;
+
+err_ms:
+ free_irq(KS8695_IRQ_UART_LINE_STATUS, port);
+err_ls:
+ free_irq(KS8695_IRQ_UART_RX, port);
+err_rx:
+ free_irq(KS8695_IRQ_UART_TX, port);
+err_tx:
+ return retval;
+}
+
+static void ks8695uart_shutdown(struct uart_port *port)
+{
+ /*
+ * Free the interrupt
+ */
+ free_irq(KS8695_IRQ_UART_RX, port);
+ free_irq(KS8695_IRQ_UART_TX, port);
+ free_irq(KS8695_IRQ_UART_MODEM_STATUS, port);
+ free_irq(KS8695_IRQ_UART_LINE_STATUS, port);
+
+ /* disable break condition and fifos */
+ UART_PUT_LCR(port, UART_GET_LCR(port) & ~URLC_URSBC);
+ UART_PUT_FCR(port, UART_GET_FCR(port) & ~URFC_URFE);
+}
+
+static void ks8695uart_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old)
+{
+ unsigned int lcr, fcr = 0;
+ unsigned long flags;
+ unsigned int baud, quot;
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
+ quot = uart_get_divisor(port, baud);
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ lcr = URCL_5;
+ break;
+ case CS6:
+ lcr = URCL_6;
+ break;
+ case CS7:
+ lcr = URCL_7;
+ break;
+ default:
+ lcr = URCL_8;
+ break;
+ }
+
+ /* stop bits */
+ if (termios->c_cflag & CSTOPB)
+ lcr |= URLC_URSB;
+
+ /* parity */
+ if (termios->c_cflag & PARENB) {
+ if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */
+ if (termios->c_cflag & PARODD)
+ lcr |= URPE_MARK;
+ else
+ lcr |= URPE_SPACE;
+ }
+ else if (termios->c_cflag & PARODD)
+ lcr |= URPE_ODD;
+ else
+ lcr |= URPE_EVEN;
+ }
+
+ if (port->fifosize > 1)
+ fcr = URFC_URFRT_8 | URFC_URTFR | URFC_URRFR | URFC_URFE;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ port->read_status_mask = URLS_URROE;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= (URLS_URFE | URLS_URPE);
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= URLS_URBI;
+
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= (URLS_URFE | URLS_URPE);
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= URLS_URBI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= URLS_URROE;
+ }
+
+ /*
+ * Ignore all characters if CREAD is not set.
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= UART_DUMMY_LSR_RX;
+
+ /* first, disable everything */
+ if (UART_ENABLE_MS(port, termios->c_cflag))
+ ks8695uart_enable_ms(port);
+ else
+ ks8695uart_disable_ms(port);
+
+ /* Set baud rate */
+ UART_PUT_BRDR(port, quot);
+
+ UART_PUT_LCR(port, lcr);
+ UART_PUT_FCR(port, fcr);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *ks8695uart_type(struct uart_port *port)
+{
+ return port->type == PORT_KS8695 ? "KS8695" : NULL;
+}
+
+/*
+ * Release the memory region(s) being used by 'port'
+ */
+static void ks8695uart_release_port(struct uart_port *port)
+{
+ release_mem_region(port->mapbase, UART_PORT_SIZE);
+}
+
+/*
+ * Request the memory region(s) being used by 'port'
+ */
+static int ks8695uart_request_port(struct uart_port *port)
+{
+ return request_mem_region(port->mapbase, UART_PORT_SIZE,
+ "serial_ks8695") != NULL ? 0 : -EBUSY;
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void ks8695uart_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = PORT_KS8695;
+ ks8695uart_request_port(port);
+ }
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int ks8695uart_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ int ret = 0;
+
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_KS8695)
+ ret = -EINVAL;
+ if (ser->irq != port->irq)
+ ret = -EINVAL;
+ if (ser->baud_base < 9600)
+ ret = -EINVAL;
+ return ret;
+}
+
+static struct uart_ops ks8695uart_pops = {
+ .tx_empty = ks8695uart_tx_empty,
+ .set_mctrl = ks8695uart_set_mctrl,
+ .get_mctrl = ks8695uart_get_mctrl,
+ .stop_tx = ks8695uart_stop_tx,
+ .start_tx = ks8695uart_start_tx,
+ .stop_rx = ks8695uart_stop_rx,
+ .enable_ms = ks8695uart_enable_ms,
+ .break_ctl = ks8695uart_break_ctl,
+ .startup = ks8695uart_startup,
+ .shutdown = ks8695uart_shutdown,
+ .set_termios = ks8695uart_set_termios,
+ .type = ks8695uart_type,
+ .release_port = ks8695uart_release_port,
+ .request_port = ks8695uart_request_port,
+ .config_port = ks8695uart_config_port,
+ .verify_port = ks8695uart_verify_port,
+};
+
+static struct uart_port ks8695uart_ports[SERIAL_KS8695_NR] = {
+ {
+ .membase = (void *) KS8695_UART_VA,
+ .mapbase = KS8695_UART_VA,
+ .iotype = SERIAL_IO_MEM,
+ .irq = KS8695_IRQ_UART_TX,
+ .uartclk = CLOCK_TICK_RATE * 16,
+ .fifosize = 16,
+ .ops = &ks8695uart_pops,
+ .flags = ASYNC_BOOT_AUTOCONF,
+ .line = 0,
+ }
+};
+
+#ifdef CONFIG_SERIAL_KS8695_CONSOLE
+static void ks8695_console_putchar(struct uart_port *port, int ch)
+{
+ while (!(UART_GET_LSR(port) & URLS_URTHRE))
+ barrier();
+
+ UART_PUT_CHAR(port, ch);
+}
+
+static void ks8695_console_write(struct console *co, const char *s, u_int count)
+{
+ struct uart_port *port = ks8695uart_ports + co->index;
+
+ uart_console_write(port, s, count, ks8695_console_putchar);
+}
+
+static void __init ks8695_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits)
+{
+ unsigned int lcr;
+
+ lcr = UART_GET_LCR(port);
+
+ switch (lcr & URLC_PARITY) {
+ case URPE_ODD:
+ *parity = 'o';
+ break;
+ case URPE_EVEN:
+ *parity = 'e';
+ break;
+ default:
+ *parity = 'n';
+ }
+
+ switch (lcr & URLC_URCL) {
+ case URCL_5:
+ *bits = 5;
+ break;
+ case URCL_6:
+ *bits = 6;
+ break;
+ case URCL_7:
+ *bits = 7;
+ break;
+ default:
+ *bits = 8;
+ }
+
+ *baud = port->uartclk / (UART_GET_BRDR(port) & 0x0FFF);
+ *baud /= 16;
+ *baud &= 0xFFFFFFF0;
+}
+
+static int __init ks8695_console_setup(struct console *co, char *options)
+{
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ /*
+ * Check whether an invalid uart number has been specified, and
+ * if so, search for the first available port that does have
+ * console support.
+ */
+ port = uart_get_console(ks8695uart_ports, SERIAL_KS8695_NR, co);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else
+ ks8695_console_get_options(port, &baud, &parity, &bits);
+
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+extern struct uart_driver ks8695_reg;
+
+static struct console ks8695_console = {
+ .name = SERIAL_KS8695_DEVNAME,
+ .write = ks8695_console_write,
+ .device = uart_console_device,
+ .setup = ks8695_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &ks8695_reg,
+};
+
+static int __init ks8695_console_init(void)
+{
+ register_console(&ks8695_console);
+ return 0;
+}
+
+console_initcall(ks8695_console_init);
+
+#define KS8695_CONSOLE &ks8695_console
+#else
+#define KS8695_CONSOLE NULL
+#endif
+
+static struct uart_driver ks8695_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial_ks8695",
+ .dev_name = SERIAL_KS8695_DEVNAME,
+ .major = SERIAL_KS8695_MAJOR,
+ .minor = SERIAL_KS8695_MINOR,
+ .nr = SERIAL_KS8695_NR,
+ .cons = KS8695_CONSOLE,
+};
+
+static int __init ks8695uart_init(void)
+{
+ int i, ret;
+
+ printk(KERN_INFO "Serial: Micrel KS8695 UART driver\n");
+
+ ret = uart_register_driver(&ks8695_reg);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < SERIAL_KS8695_NR; i++)
+ uart_add_one_port(&ks8695_reg, &ks8695uart_ports[0]);
+
+ return 0;
+}
+
+static void __exit ks8695uart_exit(void)
+{
+ int i;
+
+ for (i = 0; i < SERIAL_KS8695_NR; i++)
+ uart_remove_one_port(&ks8695_reg, &ks8695uart_ports[0]);
+ uart_unregister_driver(&ks8695_reg);
+}
+
+module_init(ks8695uart_init);
+module_exit(ks8695uart_exit);
+
+MODULE_DESCRIPTION("KS8695 serial port driver");
+MODULE_AUTHOR("Micrel Inc.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 8065f2b53701..f771a7cae9ec 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -210,7 +210,7 @@ config USB_OTG
config USB_GADGET_AT91
boolean "AT91 USB Device Port"
- depends on ARCH_AT91
+ depends on ARCH_AT91 && !ARCH_AT91SAM9RL
select USB_GADGET_SELECTED
help
Many Atmel AT91 processors (such as the AT91RM2000) have a