Commit 32fc453e authored by Russell King's avatar Russell King

[ARM] Acorn expansion card core update.

Add __iomem annotations and use iomem functions where appropriate.
Separate out expansion card allocation/initialisation and freeing.
Convert device attributes to be handled by driver core.
Clean up deprecated function warnings for internal ecard_address
usage.
Signed-off-by: default avatarRussell King <rmk@arm.linux.org.uk>
parent 4ee9f192
...@@ -85,27 +85,21 @@ static struct expcard_blacklist __initdata blacklist[] = { ...@@ -85,27 +85,21 @@ static struct expcard_blacklist __initdata blacklist[] = {
}; };
asmlinkage extern int asmlinkage extern int
ecard_loader_reset(volatile unsigned char *pa, loader_t loader); ecard_loader_reset(unsigned long base, loader_t loader);
asmlinkage extern int asmlinkage extern int
ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader); ecard_loader_read(int off, unsigned long base, loader_t loader);
static const struct ecard_id * static inline unsigned short ecard_getu16(unsigned char *v)
ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
static inline unsigned short
ecard_getu16(unsigned char *v)
{ {
return v[0] | v[1] << 8; return v[0] | v[1] << 8;
} }
static inline signed long static inline signed long ecard_gets24(unsigned char *v)
ecard_gets24(unsigned char *v)
{ {
return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0); return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
} }
static inline ecard_t * static inline ecard_t *slot_to_ecard(unsigned int slot)
slot_to_ecard(unsigned int slot)
{ {
return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL; return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
} }
...@@ -122,26 +116,31 @@ slot_to_ecard(unsigned int slot) ...@@ -122,26 +116,31 @@ slot_to_ecard(unsigned int slot)
* From a security standpoint, we trust the card vendors. This * From a security standpoint, we trust the card vendors. This
* may be a misplaced trust. * may be a misplaced trust.
*/ */
#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
#define POD_INT_ADDR(x) ((volatile unsigned char *)\
((BUS_ADDR((x)) - IO_BASE) + IO_START))
static void ecard_task_reset(struct ecard_request *req) static void ecard_task_reset(struct ecard_request *req)
{ {
struct expansion_card *ec = req->ec; struct expansion_card *ec = req->ec;
if (ec->loader) struct resource *res;
ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
res = ec->slot_no == 8
? &ec->resource[ECARD_RES_MEMC]
: ec->type == ECARD_EASI
? &ec->resource[ECARD_RES_EASI]
: &ec->resource[ECARD_RES_IOCSYNC];
ecard_loader_reset(res->start, ec->loader);
} }
static void ecard_task_readbytes(struct ecard_request *req) static void ecard_task_readbytes(struct ecard_request *req)
{ {
unsigned char *buf = (unsigned char *)req->buffer; struct expansion_card *ec = req->ec;
volatile unsigned char *base_addr = unsigned char *buf = req->buffer;
(volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
unsigned int len = req->length; unsigned int len = req->length;
unsigned int off = req->address; unsigned int off = req->address;
if (req->ec->slot_no == 8) { if (ec->slot_no == 8) {
void __iomem *base = (void __iomem *)
ec->resource[ECARD_RES_MEMC].start;
/* /*
* The card maintains an index which increments the address * The card maintains an index which increments the address
* into a 4096-byte page on each access. We need to keep * into a 4096-byte page on each access. We need to keep
...@@ -161,7 +160,7 @@ static void ecard_task_readbytes(struct ecard_request *req) ...@@ -161,7 +160,7 @@ static void ecard_task_readbytes(struct ecard_request *req)
* greater than the offset, reset the hardware index counter. * greater than the offset, reset the hardware index counter.
*/ */
if (off == 0 || index > off) { if (off == 0 || index > off) {
*base_addr = 0; writeb(0, base);
index = 0; index = 0;
} }
...@@ -170,21 +169,24 @@ static void ecard_task_readbytes(struct ecard_request *req) ...@@ -170,21 +169,24 @@ static void ecard_task_readbytes(struct ecard_request *req)
* required offset. The read bytes are discarded. * required offset. The read bytes are discarded.
*/ */
while (index < off) { while (index < off) {
unsigned char byte; readb(base + page);
byte = base_addr[page];
index += 1; index += 1;
} }
while (len--) { while (len--) {
*buf++ = base_addr[page]; *buf++ = readb(base + page);
index += 1; index += 1;
} }
} else { } else {
unsigned long base = (ec->type == ECARD_EASI
? &ec->resource[ECARD_RES_EASI]
: &ec->resource[ECARD_RES_IOCSYNC])->start;
void __iomem *pbase = (void __iomem *)base;
if (!req->use_loader || !req->ec->loader) { if (!req->use_loader || !ec->loader) {
off *= 4; off *= 4;
while (len--) { while (len--) {
*buf++ = base_addr[off]; *buf++ = readb(pbase + off);
off += 4; off += 4;
} }
} else { } else {
...@@ -194,8 +196,8 @@ static void ecard_task_readbytes(struct ecard_request *req) ...@@ -194,8 +196,8 @@ static void ecard_task_readbytes(struct ecard_request *req)
* expansion card loader programs. * expansion card loader programs.
*/ */
*(unsigned long *)0x108 = 0; *(unsigned long *)0x108 = 0;
*buf++ = ecard_loader_read(off++, base_addr, *buf++ = ecard_loader_read(off++, base,
req->ec->loader); ec->loader);
} }
} }
} }
...@@ -406,7 +408,7 @@ static void ecard_def_irq_disable(ecard_t *ec, int irqnr) ...@@ -406,7 +408,7 @@ static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
static int ecard_def_irq_pending(ecard_t *ec) static int ecard_def_irq_pending(ecard_t *ec)
{ {
return !ec->irqmask || ec->irqaddr[0] & ec->irqmask; return !ec->irqmask || readb(ec->irqaddr) & ec->irqmask;
} }
static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr) static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
...@@ -421,7 +423,7 @@ static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr) ...@@ -421,7 +423,7 @@ static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr)
static int ecard_def_fiq_pending(ecard_t *ec) static int ecard_def_fiq_pending(ecard_t *ec)
{ {
return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask; return !ec->fiqmask || readb(ec->fiqaddr) & ec->fiqmask;
} }
static expansioncard_ops_t ecard_default_ops = { static expansioncard_ops_t ecard_default_ops = {
...@@ -522,7 +524,7 @@ static void ecard_dump_irq_state(void) ...@@ -522,7 +524,7 @@ static void ecard_dump_irq_state(void)
ec->ops->irqpending(ec) ? "" : "not "); ec->ops->irqpending(ec) ? "" : "not ");
else else
printk("irqaddr %p, mask = %02X, status = %02X\n", printk("irqaddr %p, mask = %02X, status = %02X\n",
ec->irqaddr, ec->irqmask, *ec->irqaddr); ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
} }
} }
...@@ -675,7 +677,7 @@ static int __init ecard_probeirqhw(void) ...@@ -675,7 +677,7 @@ static int __init ecard_probeirqhw(void)
#define IO_EC_MEMC8_BASE 0 #define IO_EC_MEMC8_BASE 0
#endif #endif
unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
{ {
unsigned long address = 0; unsigned long address = 0;
int slot = ec->slot_no; int slot = ec->slot_no;
...@@ -779,55 +781,89 @@ static void ecard_proc_init(void) ...@@ -779,55 +781,89 @@ static void ecard_proc_init(void)
get_ecard_dev_info); get_ecard_dev_info);
} }
#define ec_set_resource(ec,nr,st,sz,flg) \ #define ec_set_resource(ec,nr,st,sz) \
do { \ do { \
(ec)->resource[nr].name = ec->dev.bus_id; \ (ec)->resource[nr].name = ec->dev.bus_id; \
(ec)->resource[nr].start = st; \ (ec)->resource[nr].start = st; \
(ec)->resource[nr].end = (st) + (sz) - 1; \ (ec)->resource[nr].end = (st) + (sz) - 1; \
(ec)->resource[nr].flags = flg; \ (ec)->resource[nr].flags = IORESOURCE_MEM; \
} while (0) } while (0)
static void __init ecard_init_resources(struct expansion_card *ec) static void __init ecard_free_card(struct expansion_card *ec)
{
int i;
for (i = 0; i < ECARD_NUM_RESOURCES; i++)
if (ec->resource[i].flags)
release_resource(&ec->resource[i]);
kfree(ec);
}
static struct expansion_card *__init ecard_alloc_card(int type, int slot)
{ {
unsigned long base = PODSLOT_IOC4_BASE; struct expansion_card *ec;
unsigned int slot = ec->slot_no; unsigned long base;
int i; int i;
ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
if (!ec) {
ec = ERR_PTR(-ENOMEM);
goto nomem;
}
memset(ec, 0, sizeof(ecard_t));
ec->slot_no = slot;
ec->type = type;
ec->irq = NO_IRQ;
ec->fiq = NO_IRQ;
ec->dma = NO_DMA;
ec->ops = &ecard_default_ops;
snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
ec->dev.parent = NULL;
ec->dev.bus = &ecard_bus_type;
ec->dev.dma_mask = &ec->dma_mask;
ec->dma_mask = (u64)0xffffffff;
if (slot < 4) { if (slot < 4) {
ec_set_resource(ec, ECARD_RES_MEMC, ec_set_resource(ec, ECARD_RES_MEMC,
PODSLOT_MEMC_BASE + (slot << 14), PODSLOT_MEMC_BASE + (slot << 14),
PODSLOT_MEMC_SIZE, IORESOURCE_MEM); PODSLOT_MEMC_SIZE);
base = PODSLOT_IOC0_BASE; base = PODSLOT_IOC0_BASE + (slot << 14);
} } else
base = PODSLOT_IOC4_BASE + ((slot - 4) << 14);
#ifdef CONFIG_ARCH_RPC #ifdef CONFIG_ARCH_RPC
if (slot < 8) { if (slot < 8) {
ec_set_resource(ec, ECARD_RES_EASI, ec_set_resource(ec, ECARD_RES_EASI,
PODSLOT_EASI_BASE + (slot << 24), PODSLOT_EASI_BASE + (slot << 24),
PODSLOT_EASI_SIZE, IORESOURCE_MEM); PODSLOT_EASI_SIZE);
} }
if (slot == 8) { if (slot == 8) {
ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE);
NETSLOT_SIZE, IORESOURCE_MEM);
} else } else
#endif #endif
for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) { for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++)
ec_set_resource(ec, i + ECARD_RES_IOCSLOW, ec_set_resource(ec, i + ECARD_RES_IOCSLOW,
base + (slot << 14) + (i << 19), base + (i << 19), PODSLOT_IOC_SIZE);
PODSLOT_IOC_SIZE, IORESOURCE_MEM);
}
for (i = 0; i < ECARD_NUM_RESOURCES; i++) { for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
if (ec->resource[i].start && if (ec->resource[i].flags &&
request_resource(&iomem_resource, &ec->resource[i])) { request_resource(&iomem_resource, &ec->resource[i])) {
printk(KERN_ERR "%s: resource(s) not available\n", printk(KERN_ERR "%s: resource(s) not available\n",
ec->dev.bus_id); ec->dev.bus_id);
ec->resource[i].end -= ec->resource[i].start; ec->resource[i].end -= ec->resource[i].start;
ec->resource[i].start = 0; ec->resource[i].start = 0;
ec->resource[i].flags = 0;
} }
} }
nomem:
return ec;
} }
static ssize_t ecard_show_irq(struct device *dev, char *buf) static ssize_t ecard_show_irq(struct device *dev, char *buf)
...@@ -836,16 +872,12 @@ static ssize_t ecard_show_irq(struct device *dev, char *buf) ...@@ -836,16 +872,12 @@ static ssize_t ecard_show_irq(struct device *dev, char *buf)
return sprintf(buf, "%u\n", ec->irq); return sprintf(buf, "%u\n", ec->irq);
} }
static DEVICE_ATTR(irq, S_IRUGO, ecard_show_irq, NULL);
static ssize_t ecard_show_dma(struct device *dev, char *buf) static ssize_t ecard_show_dma(struct device *dev, char *buf)
{ {
struct expansion_card *ec = ECARD_DEV(dev); struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->dma); return sprintf(buf, "%u\n", ec->dma);
} }
static DEVICE_ATTR(dma, S_IRUGO, ecard_show_dma, NULL);
static ssize_t ecard_show_resources(struct device *dev, char *buf) static ssize_t ecard_show_resources(struct device *dev, char *buf)
{ {
struct expansion_card *ec = ECARD_DEV(dev); struct expansion_card *ec = ECARD_DEV(dev);
...@@ -861,23 +893,33 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf) ...@@ -861,23 +893,33 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf)
return str - buf; return str - buf;
} }
static DEVICE_ATTR(resource, S_IRUGO, ecard_show_resources, NULL);
static ssize_t ecard_show_vendor(struct device *dev, char *buf) static ssize_t ecard_show_vendor(struct device *dev, char *buf)
{ {
struct expansion_card *ec = ECARD_DEV(dev); struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.manufacturer); return sprintf(buf, "%u\n", ec->cid.manufacturer);
} }
static DEVICE_ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL);
static ssize_t ecard_show_device(struct device *dev, char *buf) static ssize_t ecard_show_device(struct device *dev, char *buf)
{ {
struct expansion_card *ec = ECARD_DEV(dev); struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.product); return sprintf(buf, "%u\n", ec->cid.product);
} }
static DEVICE_ATTR(device, S_IRUGO, ecard_show_device, NULL); static ssize_t ecard_show_type(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
}
static struct device_attribute ecard_dev_attrs[] = {
__ATTR(device, S_IRUGO, ecard_show_device, NULL),
__ATTR(dma, S_IRUGO, ecard_show_dma, NULL),
__ATTR(irq, S_IRUGO, ecard_show_irq, NULL),
__ATTR(resource, S_IRUGO, ecard_show_resources, NULL),
__ATTR(type, S_IRUGO, ecard_show_type, NULL),
__ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL),
__ATTR_NULL,
};
int ecard_request_resources(struct expansion_card *ec) int ecard_request_resources(struct expansion_card *ec)
...@@ -927,21 +969,13 @@ ecard_probe(int slot, card_type_t type) ...@@ -927,21 +969,13 @@ ecard_probe(int slot, card_type_t type)
ecard_t **ecp; ecard_t **ecp;
ecard_t *ec; ecard_t *ec;
struct ex_ecid cid; struct ex_ecid cid;
int i, rc = -ENOMEM; int i, rc;
ec = kmalloc(sizeof(ecard_t), GFP_KERNEL); ec = ecard_alloc_card(type, slot);
if (!ec) if (IS_ERR(ec)) {
rc = PTR_ERR(ec);
goto nomem; goto nomem;
}
memset(ec, 0, sizeof(ecard_t));
ec->slot_no = slot;
ec->type = type;
ec->irq = NO_IRQ;
ec->fiq = NO_IRQ;
ec->dma = NO_DMA;
ec->card_desc = NULL;
ec->ops = &ecard_default_ops;
rc = -ENODEV; rc = -ENODEV;
if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0) if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
...@@ -964,7 +998,7 @@ ecard_probe(int slot, card_type_t type) ...@@ -964,7 +998,7 @@ ecard_probe(int slot, card_type_t type)
ec->cid.fiqmask = cid.r_fiqmask; ec->cid.fiqmask = cid.r_fiqmask;
ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff); ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
ec->fiqaddr = ec->fiqaddr =
ec->irqaddr = (unsigned char *)ioaddr(ec->podaddr); ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr);
if (ec->cid.is) { if (ec->cid.is) {
ec->irqmask = ec->cid.irqmask; ec->irqmask = ec->cid.irqmask;
...@@ -983,14 +1017,6 @@ ecard_probe(int slot, card_type_t type) ...@@ -983,14 +1017,6 @@ ecard_probe(int slot, card_type_t type)
break; break;
} }
snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
ec->dev.parent = NULL;
ec->dev.bus = &ecard_bus_type;
ec->dev.dma_mask = &ec->dma_mask;
ec->dma_mask = (u64)0xffffffff;
ecard_init_resources(ec);
/* /*
* hook the interrupt handlers * hook the interrupt handlers
*/ */
...@@ -1017,17 +1043,12 @@ ecard_probe(int slot, card_type_t type) ...@@ -1017,17 +1043,12 @@ ecard_probe(int slot, card_type_t type)
slot_to_expcard[slot] = ec; slot_to_expcard[slot] = ec;
device_register(&ec->dev); device_register(&ec->dev);
device_create_file(&ec->dev, &dev_attr_dma);
device_create_file(&ec->dev, &dev_attr_irq);
device_create_file(&ec->dev, &dev_attr_resource);
device_create_file(&ec->dev, &dev_attr_vendor);
device_create_file(&ec->dev, &dev_attr_device);
return 0; return 0;
nodev: nodev:
kfree(ec); ecard_free_card(ec);
nomem: nomem:
return rc; return rc;
} }
...@@ -1128,9 +1149,15 @@ static void ecard_drv_shutdown(struct device *dev) ...@@ -1128,9 +1149,15 @@ static void ecard_drv_shutdown(struct device *dev)
if (drv->shutdown) if (drv->shutdown)
drv->shutdown(ec); drv->shutdown(ec);
ecard_release(ec); ecard_release(ec);
/*
* If this card has a loader, call the reset handler.
*/
if (ec->loader) {
req.fn = ecard_task_reset; req.fn = ecard_task_reset;
req.ec = ec; req.ec = ec;
ecard_call(&req); ecard_call(&req);
}
} }
int ecard_register_driver(struct ecard_driver *drv) int ecard_register_driver(struct ecard_driver *drv)
...@@ -1165,6 +1192,7 @@ static int ecard_match(struct device *_dev, struct device_driver *_drv) ...@@ -1165,6 +1192,7 @@ static int ecard_match(struct device *_dev, struct device_driver *_drv)
struct bus_type ecard_bus_type = { struct bus_type ecard_bus_type = {
.name = "ecard", .name = "ecard",
.dev_attrs = ecard_dev_attrs,
.match = ecard_match, .match = ecard_match,
}; };
...@@ -1176,7 +1204,7 @@ static int ecard_bus_init(void) ...@@ -1176,7 +1204,7 @@ static int ecard_bus_init(void)
postcore_initcall(ecard_bus_init); postcore_initcall(ecard_bus_init);
EXPORT_SYMBOL(ecard_readchunk); EXPORT_SYMBOL(ecard_readchunk);
EXPORT_SYMBOL(ecard_address); EXPORT_SYMBOL(__ecard_address);
EXPORT_SYMBOL(ecard_register_driver); EXPORT_SYMBOL(ecard_register_driver);
EXPORT_SYMBOL(ecard_remove_driver); EXPORT_SYMBOL(ecard_remove_driver);
EXPORT_SYMBOL(ecard_bus_type); EXPORT_SYMBOL(ecard_bus_type);
...@@ -155,8 +155,8 @@ struct expansion_card { ...@@ -155,8 +155,8 @@ struct expansion_card {
struct resource resource[ECARD_NUM_RESOURCES]; struct resource resource[ECARD_NUM_RESOURCES];
/* Public data */ /* Public data */
volatile unsigned char *irqaddr; /* address of IRQ register */ void __iomem *irqaddr; /* address of IRQ register */
volatile unsigned char *fiqaddr; /* address of FIQ register */ void __iomem *fiqaddr; /* address of FIQ register */
unsigned char irqmask; /* IRQ mask */ unsigned char irqmask; /* IRQ mask */
unsigned char fiqmask; /* FIQ mask */ unsigned char fiqmask; /* FIQ mask */
unsigned char claimed; /* Card claimed? */ unsigned char claimed; /* Card claimed? */
...@@ -207,9 +207,16 @@ struct in_chunk_dir { ...@@ -207,9 +207,16 @@ struct in_chunk_dir {
extern int ecard_readchunk (struct in_chunk_dir *cd, struct expansion_card *ec, int id, int num); extern int ecard_readchunk (struct in_chunk_dir *cd, struct expansion_card *ec, int id, int num);
/* /*
* Obtain the address of a card * Obtain the address of a card. This returns the "old style" address
* and should no longer be used.
*/ */
extern __deprecated unsigned int ecard_address (struct expansion_card *ec, card_type_t card_type, card_speed_t speed); static inline unsigned int __deprecated
ecard_address(struct expansion_card *ec, card_type_t type, card_speed_t speed)
{
extern unsigned int __ecard_address(struct expansion_card *,
card_type_t, card_speed_t);
return __ecard_address(ec, type, speed);
}
/* /*
* Request and release ecard resources * Request and release ecard resources
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment