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[] = {
};
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
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 *
ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
static inline unsigned short
ecard_getu16(unsigned char *v)
static inline unsigned short ecard_getu16(unsigned char *v)
{
return v[0] | v[1] << 8;
}
static inline signed long
ecard_gets24(unsigned char *v)
static inline signed long ecard_gets24(unsigned char *v)
{
return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
}
static inline ecard_t *
slot_to_ecard(unsigned int slot)
static inline ecard_t *slot_to_ecard(unsigned int slot)
{
return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
}
......@@ -122,26 +116,31 @@ slot_to_ecard(unsigned int slot)
* From a security standpoint, we trust the card vendors. This
* 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)
{
struct expansion_card *ec = req->ec;
if (ec->loader)
ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
struct resource *res;
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)
{
unsigned char *buf = (unsigned char *)req->buffer;
volatile unsigned char *base_addr =
(volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
struct expansion_card *ec = req->ec;
unsigned char *buf = req->buffer;
unsigned int len = req->length;
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
* 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)
* greater than the offset, reset the hardware index counter.
*/
if (off == 0 || index > off) {
*base_addr = 0;
writeb(0, base);
index = 0;
}
......@@ -170,21 +169,24 @@ static void ecard_task_readbytes(struct ecard_request *req)
* required offset. The read bytes are discarded.
*/
while (index < off) {
unsigned char byte;
byte = base_addr[page];
readb(base + page);
index += 1;
}
while (len--) {
*buf++ = base_addr[page];
*buf++ = readb(base + page);
index += 1;
}
} 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;
while (len--) {
*buf++ = base_addr[off];
*buf++ = readb(pbase + off);
off += 4;
}
} else {
......@@ -194,8 +196,8 @@ static void ecard_task_readbytes(struct ecard_request *req)
* expansion card loader programs.
*/
*(unsigned long *)0x108 = 0;
*buf++ = ecard_loader_read(off++, base_addr,
req->ec->loader);
*buf++ = ecard_loader_read(off++, base,
ec->loader);
}
}
}
......@@ -406,7 +408,7 @@ static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
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)
......@@ -421,7 +423,7 @@ static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr)
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 = {
......@@ -522,7 +524,7 @@ static void ecard_dump_irq_state(void)
ec->ops->irqpending(ec) ? "" : "not ");
else
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)
#define IO_EC_MEMC8_BASE 0
#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;
int slot = ec->slot_no;
......@@ -779,55 +781,89 @@ static void ecard_proc_init(void)
get_ecard_dev_info);
}
#define ec_set_resource(ec,nr,st,sz,flg) \
#define ec_set_resource(ec,nr,st,sz) \
do { \
(ec)->resource[nr].name = ec->dev.bus_id; \
(ec)->resource[nr].start = st; \
(ec)->resource[nr].end = (st) + (sz) - 1; \
(ec)->resource[nr].flags = flg; \
(ec)->resource[nr].flags = IORESOURCE_MEM; \
} 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;
unsigned int slot = ec->slot_no;
struct expansion_card *ec;
unsigned long base;
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) {
ec_set_resource(ec, ECARD_RES_MEMC,
PODSLOT_MEMC_BASE + (slot << 14),
PODSLOT_MEMC_SIZE, IORESOURCE_MEM);
base = PODSLOT_IOC0_BASE;
}
PODSLOT_MEMC_SIZE);
base = PODSLOT_IOC0_BASE + (slot << 14);
} else
base = PODSLOT_IOC4_BASE + ((slot - 4) << 14);
#ifdef CONFIG_ARCH_RPC
if (slot < 8) {
ec_set_resource(ec, ECARD_RES_EASI,
PODSLOT_EASI_BASE + (slot << 24),
PODSLOT_EASI_SIZE, IORESOURCE_MEM);
PODSLOT_EASI_SIZE);
}
if (slot == 8) {
ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE,
NETSLOT_SIZE, IORESOURCE_MEM);
ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE);
} else
#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,
base + (slot << 14) + (i << 19),
PODSLOT_IOC_SIZE, IORESOURCE_MEM);
}
base + (i << 19), PODSLOT_IOC_SIZE);
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])) {
printk(KERN_ERR "%s: resource(s) not available\n",
ec->dev.bus_id);
ec->resource[i].end -= ec->resource[i].start;
ec->resource[i].start = 0;
ec->resource[i].flags = 0;
}
}
nomem:
return ec;
}
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);
}
static DEVICE_ATTR(irq, S_IRUGO, ecard_show_irq, NULL);
static ssize_t ecard_show_dma(struct device *dev, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
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)
{
struct expansion_card *ec = ECARD_DEV(dev);
......@@ -861,23 +893,33 @@ static ssize_t ecard_show_resources(struct device *dev, char *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)
{
struct expansion_card *ec = ECARD_DEV(dev);
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)
{
struct expansion_card *ec = ECARD_DEV(dev);
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)
......@@ -927,21 +969,13 @@ ecard_probe(int slot, card_type_t type)
ecard_t **ecp;
ecard_t *ec;
struct ex_ecid cid;
int i, rc = -ENOMEM;
int i, rc;
ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
if (!ec)
ec = ecard_alloc_card(type, slot);
if (IS_ERR(ec)) {
rc = PTR_ERR(ec);
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;
if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
......@@ -964,7 +998,7 @@ ecard_probe(int slot, card_type_t type)
ec->cid.fiqmask = cid.r_fiqmask;
ec->cid.fiqoff = ecard_gets24(cid.r_fiqoff);
ec->fiqaddr =
ec->irqaddr = (unsigned char *)ioaddr(ec->podaddr);
ec->irqaddr = (void __iomem *)ioaddr(ec->podaddr);
if (ec->cid.is) {
ec->irqmask = ec->cid.irqmask;
......@@ -983,14 +1017,6 @@ ecard_probe(int slot, card_type_t type)
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
*/
......@@ -1017,17 +1043,12 @@ ecard_probe(int slot, card_type_t type)
slot_to_expcard[slot] = ec;
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;
nodev:
kfree(ec);
nomem:
nodev:
ecard_free_card(ec);
nomem:
return rc;
}
......@@ -1128,9 +1149,15 @@ static void ecard_drv_shutdown(struct device *dev)
if (drv->shutdown)
drv->shutdown(ec);
ecard_release(ec);
/*
* If this card has a loader, call the reset handler.
*/
if (ec->loader) {
req.fn = ecard_task_reset;
req.ec = ec;
ecard_call(&req);
}
}
int ecard_register_driver(struct ecard_driver *drv)
......@@ -1165,6 +1192,7 @@ static int ecard_match(struct device *_dev, struct device_driver *_drv)
struct bus_type ecard_bus_type = {
.name = "ecard",
.dev_attrs = ecard_dev_attrs,
.match = ecard_match,
};
......@@ -1176,7 +1204,7 @@ static int ecard_bus_init(void)
postcore_initcall(ecard_bus_init);
EXPORT_SYMBOL(ecard_readchunk);
EXPORT_SYMBOL(ecard_address);
EXPORT_SYMBOL(__ecard_address);
EXPORT_SYMBOL(ecard_register_driver);
EXPORT_SYMBOL(ecard_remove_driver);
EXPORT_SYMBOL(ecard_bus_type);
......@@ -155,8 +155,8 @@ struct expansion_card {
struct resource resource[ECARD_NUM_RESOURCES];
/* Public data */
volatile unsigned char *irqaddr; /* address of IRQ register */
volatile unsigned char *fiqaddr; /* address of FIQ register */
void __iomem *irqaddr; /* address of IRQ register */
void __iomem *fiqaddr; /* address of FIQ register */
unsigned char irqmask; /* IRQ mask */
unsigned char fiqmask; /* FIQ mask */
unsigned char claimed; /* Card claimed? */
......@@ -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);
/*
* 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
......
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