in db1xxx_ss.c [424:578]
static int db1x_pcmcia_socket_probe(struct platform_device *pdev)
{
struct db1x_pcmcia_sock *sock;
struct resource *r;
int ret, bid;
sock = kzalloc(sizeof(struct db1x_pcmcia_sock), GFP_KERNEL);
if (!sock)
return -ENOMEM;
sock->nr = pdev->id;
bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
switch (bid) {
case BCSR_WHOAMI_PB1500:
case BCSR_WHOAMI_PB1500R2:
case BCSR_WHOAMI_PB1100:
sock->board_type = BOARD_TYPE_PB1100;
break;
case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR:
sock->board_type = BOARD_TYPE_DEFAULT;
break;
case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200:
sock->board_type = BOARD_TYPE_DB1200;
break;
case BCSR_WHOAMI_DB1300:
sock->board_type = BOARD_TYPE_DB1300;
break;
default:
printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid);
ret = -ENODEV;
goto out0;
}
/*
* gather resources necessary and optional nice-to-haves to
* operate a socket:
* This includes IRQs for Carddetection/ejection, the card
* itself and optional status change detection.
* Also, the memory areas covered by a socket. For these
* we require the real 36bit addresses (see the au1000.h
* header for more information).
*/
/* card: irq assigned to the card itself. */
r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card");
sock->card_irq = r ? r->start : 0;
/* insert: irq which triggers on card insertion/ejection
* BIG FAT NOTE: on DB1000/1100/1500/1550 we pass a GPIO here!
*/
r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "insert");
sock->insert_irq = r ? r->start : -1;
if (sock->board_type == BOARD_TYPE_DEFAULT) {
sock->insert_gpio = r ? r->start : -1;
sock->insert_irq = r ? gpio_to_irq(r->start) : -1;
}
/* stschg: irq which trigger on card status change (optional) */
r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg");
sock->stschg_irq = r ? r->start : -1;
/* eject: irq which triggers on ejection (DB1200/PB1200 only) */
r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eject");
sock->eject_irq = r ? r->start : -1;
ret = -ENODEV;
/* 36bit PCMCIA Attribute area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
if (!r) {
printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n",
sock->nr);
goto out0;
}
sock->phys_attr = r->start;
/* 36bit PCMCIA Memory area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
if (!r) {
printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",
sock->nr);
goto out0;
}
sock->phys_mem = r->start;
/* 36bit PCMCIA IO area address */
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
if (!r) {
printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n",
sock->nr);
goto out0;
}
sock->phys_io = r->start;
/*
* PCMCIA client drivers use the inb/outb macros to access
* the IO registers. Since mips_io_port_base is added
* to the access address of the mips implementation of
* inb/outb, we need to subtract it here because we want
* to access the I/O or MEM address directly, without
* going through this "mips_io_port_base" mechanism.
*/
sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
mips_io_port_base);
if (!sock->virt_io) {
printk(KERN_ERR "pcmcia%d: cannot remap IO area\n",
sock->nr);
ret = -ENOMEM;
goto out0;
}
sock->socket.ops = &db1x_pcmcia_operations;
sock->socket.owner = THIS_MODULE;
sock->socket.pci_irq = sock->card_irq;
sock->socket.features = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
sock->socket.map_size = MEM_MAP_SIZE;
sock->socket.io_offset = (unsigned long)sock->virt_io;
sock->socket.dev.parent = &pdev->dev;
sock->socket.resource_ops = &pccard_static_ops;
platform_set_drvdata(pdev, sock);
ret = db1x_pcmcia_setup_irqs(sock);
if (ret) {
printk(KERN_ERR "pcmcia%d cannot setup interrupts\n",
sock->nr);
goto out1;
}
set_stschg(sock, 0);
ret = pcmcia_register_socket(&sock->socket);
if (ret) {
printk(KERN_ERR "pcmcia%d failed to register\n", sock->nr);
goto out2;
}
printk(KERN_INFO "Alchemy Db/Pb1xxx pcmcia%d @ io/attr/mem %09llx"
"(%p) %09llx %09llx card/insert/stschg/eject irqs @ %d "
"%d %d %d\n", sock->nr, sock->phys_io, sock->virt_io,
sock->phys_attr, sock->phys_mem, sock->card_irq,
sock->insert_irq, sock->stschg_irq, sock->eject_irq);
return 0;
out2:
db1x_pcmcia_free_irqs(sock);
out1:
iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
out0:
kfree(sock);
return ret;
}