Ejemplo n.º 1
0
static int at91_cf_remove(struct platform_device *pdev)
{
	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);

	pcmcia_unregister_socket(&cf->socket);
	device_init_wakeup(&pdev->dev, 0);

	return 0;
}
Ejemplo n.º 2
0
static int __devexit xxs1500_pcmcia_remove(struct platform_device *pdev)
{
	struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);

	pcmcia_unregister_socket(&sock->socket);
	free_irq(gpio_to_irq(GPIO_CDA), sock);
	iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
	kfree(sock);

	return 0;
}
Ejemplo n.º 3
0
static void __exit exit_m32r_pcc(void)
{
	int i;

	for (i = 0; i < pcc_sockets; i++)
		if (socket[i].flags & IS_REGISTERED)
			pcmcia_unregister_socket(&socket[i].socket);

	platform_device_unregister(&pcc_device);
	if (poll_interval != 0)
		del_timer_sync(&poll_timer);

	platform_driver_unregister(&pcc_driver);
} /* exit_m32r_pcc */
Ejemplo n.º 4
0
static int __devexit bfin_cf_remove(struct platform_device *pdev)
{
    struct bfin_cf_socket *cf = platform_get_drvdata(pdev);

    gpio_free(cf->cd_pfx);
    cf->active = 0;
    pcmcia_unregister_socket(&cf->socket);
    del_timer_sync(&cf->timer);
    iounmap((void __iomem *)cf->socket.io_offset);
    release_mem_region(cf->phys_cf_io, SZ_8K);
    platform_set_drvdata(pdev, NULL);
    kfree(cf);
    return 0;
}
Ejemplo n.º 5
0
static int __exit at91_cf_remove(struct platform_device *pdev)
{
	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
	struct at91_cf_data	*board = cf->board;
	struct resource		*io = cf->socket.io[0].res;

	pcmcia_unregister_socket(&cf->socket);
	if (board->irq_pin)
		free_irq(board->irq_pin, cf);
	device_init_wakeup(&pdev->dev, 0);
	free_irq(board->det_pin, cf);
	iounmap((void __iomem *) cf->socket.io_offset);
	release_mem_region(io->start, io->end + 1 - io->start);

	kfree(cf);
	return 0;
}
Ejemplo n.º 6
0
static int __exit at91_cf_remove(struct device *dev)
{
	struct at91_cf_socket	*cf = dev_get_drvdata(dev);
	struct resource		*io = cf->socket.io[0].res;
	unsigned int		csa;

	pcmcia_unregister_socket(&cf->socket);
	free_irq(cf->board->irq_pin, cf);
	free_irq(cf->board->det_pin, cf);
	iounmap((void __iomem *) cf->socket.io_offset);
	release_mem_region(io->start, io->end + 1 - io->start);

	csa = at91_sys_read(AT91_EBI_CSA);
	at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);

	kfree(cf);
	return 0;
}
Ejemplo n.º 7
0
static void __exit exit_tcic(void)
{
    int i;

    del_timer_sync(&poll_timer);
    if (cs_irq != 0) {
	tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
	free_irq(cs_irq, tcic_interrupt);
    }
    release_region(tcic_base, 16);

    for (i = 0; i < sockets; i++) {
	    pcmcia_unregister_socket(&socket_table[i].socket);	    
    }

    platform_device_unregister(&tcic_device);
    platform_driver_unregister(&tcic_driver);
} /* exit_tcic */
Ejemplo n.º 8
0
void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
{
	mutex_lock(&soc_pcmcia_sockets_lock);
	del_timer_sync(&skt->poll_timer);

	pcmcia_unregister_socket(&skt->socket);

	soc_pcmcia_hw_shutdown(skt);

	/* should not be required; violates some lowlevel drivers */
	soc_common_pcmcia_config_skt(skt, &dead_socket);

	list_del(&skt->node);
	mutex_unlock(&soc_pcmcia_sockets_lock);

	iounmap(skt->virt_io);
	skt->virt_io = NULL;
	release_resource(&skt->res_attr);
	release_resource(&skt->res_mem);
	release_resource(&skt->res_io);
	release_resource(&skt->res_skt);
}
Ejemplo n.º 9
0
static int __exit at91_cf_remove(struct platform_device *pdev)
{
	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
	struct at91_cf_data	*board = cf->board;
	struct resource		*io = cf->socket.io[0].res;

	pcmcia_unregister_socket(&cf->socket);
	release_mem_region(io->start, resource_size(io));
	iounmap((void __iomem *) cf->socket.io_offset);
	if (gpio_is_valid(board->irq_pin)) {
		free_irq(gpio_to_irq(board->irq_pin), cf);
		gpio_free(board->irq_pin);
	}
	if (gpio_is_valid(board->vcc_pin))
		gpio_free(board->vcc_pin);
	gpio_free(board->rst_pin);
	device_init_wakeup(&pdev->dev, 0);
	free_irq(gpio_to_irq(board->det_pin), cf);
	gpio_free(board->det_pin);
	kfree(cf);
	return 0;
}
Ejemplo n.º 10
0
static int __devexit electra_cf_remove(struct of_device *ofdev)
{
	struct device *device = &ofdev->dev;
	struct electra_cf_socket *cf;

	cf = dev_get_drvdata(device);

	cf->active = 0;
	pcmcia_unregister_socket(&cf->socket);
	free_irq(cf->irq, cf);
	del_timer_sync(&cf->timer);

	__iounmap_at(cf->io_virt, cf->io_size);
	iounmap(cf->mem_base);
	iounmap(cf->gpio_base);
	release_mem_region(cf->mem_phys, cf->mem_size);
	release_region(cf->io_base, cf->io_size);

	kfree(cf);

	return 0;
}
Ejemplo n.º 11
0
int soc_common_drv_pcmcia_remove(struct device *dev)
{
	struct skt_dev_info *sinfo = dev_get_drvdata(dev);
	int i;

	dev_set_drvdata(dev, NULL);

	mutex_lock(&soc_pcmcia_sockets_lock);
	for (i = 0; i < sinfo->nskt; i++) {
		struct soc_pcmcia_socket *skt = &sinfo->skt[i];

		del_timer_sync(&skt->poll_timer);

		pcmcia_unregister_socket(&skt->socket);

		flush_scheduled_work();

		skt->ops->hw_shutdown(skt);

		soc_common_pcmcia_config_skt(skt, &dead_socket);

		list_del(&skt->node);
		iounmap(skt->virt_io);
		skt->virt_io = NULL;
		release_resource(&skt->res_attr);
		release_resource(&skt->res_mem);
		release_resource(&skt->res_io);
		release_resource(&skt->res_skt);
	}
	if (list_empty(&soc_pcmcia_sockets))
		soc_pcmcia_cpufreq_unregister();

	mutex_unlock(&soc_pcmcia_sockets_lock);

	kfree(sinfo);

	return 0;
}
Ejemplo n.º 12
0
void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
{
	mutex_lock(&soc_pcmcia_sockets_lock);
	del_timer_sync(&skt->poll_timer);

	pcmcia_unregister_socket(&skt->socket);

	flush_scheduled_work();

	skt->ops->hw_shutdown(skt);

	soc_common_pcmcia_config_skt(skt, &dead_socket);

	list_del(&skt->node);
	mutex_unlock(&soc_pcmcia_sockets_lock);

	iounmap(skt->virt_io);
	skt->virt_io = NULL;
	release_resource(&skt->res_attr);
	release_resource(&skt->res_mem);
	release_resource(&skt->res_io);
	release_resource(&skt->res_skt);
}
Ejemplo n.º 13
0
int au1x00_drv_pcmcia_remove(struct platform_device *dev)
{
	struct skt_dev_info *sinfo = platform_get_drvdata(dev);
	int i;

	mutex_lock(&pcmcia_sockets_lock);
	platform_set_drvdata(dev, NULL);

	for (i = 0; i < sinfo->nskt; i++) {
		struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i);

		del_timer_sync(&skt->poll_timer);
		pcmcia_unregister_socket(&skt->socket);
		skt->ops->hw_shutdown(skt);
		au1x00_pcmcia_config_skt(skt, &dead_socket);
		iounmap(skt->virt_io + (u32)mips_io_port_base);
		skt->virt_io = NULL;
	}

	kfree(sinfo);
	mutex_unlock(&pcmcia_sockets_lock);
	return 0;
}
Ejemplo n.º 14
0
void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
{
	del_timer_sync(&skt->poll_timer);

	pcmcia_unregister_socket(&skt->socket);

#ifdef CONFIG_CPU_FREQ
	if (skt->ops->frequency_change)
		cpufreq_unregister_notifier(&skt->cpufreq_nb,
					    CPUFREQ_TRANSITION_NOTIFIER);
#endif

	soc_pcmcia_hw_shutdown(skt);

	/* should not be required; violates some lowlevel drivers */
	soc_common_pcmcia_config_skt(skt, &dead_socket);

	iounmap(skt->virt_io);
	skt->virt_io = NULL;
	release_resource(&skt->res_attr);
	release_resource(&skt->res_mem);
	release_resource(&skt->res_io);
	release_resource(&skt->res_skt);
}
Ejemplo n.º 15
0
int au1x00_drv_pcmcia_remove(struct device *dev)
{
	struct skt_dev_info *sinfo = dev_get_drvdata(dev);
	int i;

	down(&pcmcia_sockets_lock);
	dev_set_drvdata(dev, NULL);

	for (i = 0; i < sinfo->nskt; i++) {
		struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i);

		del_timer_sync(&skt->poll_timer);
		pcmcia_unregister_socket(&skt->socket);
		flush_scheduled_work();
		skt->ops->hw_shutdown(skt);
		au1x00_pcmcia_config_skt(skt, &dead_socket);
		iounmap(skt->virt_io);
		skt->virt_io = NULL;
	}

	kfree(sinfo);
	up(&pcmcia_sockets_lock);
	return 0;
}
Ejemplo n.º 16
0
int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr)
{
	struct skt_dev_info *sinfo;
	struct au1000_pcmcia_socket *skt;
	int ret, i;

	sinfo = kzalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
	if (!sinfo) {
		ret = -ENOMEM;
		goto out;
	}

	sinfo->nskt = nr;

	/*
	 * Initialise the per-socket structure.
	 */
	for (i = 0; i < nr; i++) {
		skt = PCMCIA_SOCKET(i);
		memset(skt, 0, sizeof(*skt));

		skt->socket.resource_ops = &pccard_static_ops;
		skt->socket.ops = &au1x00_pcmcia_operations;
		skt->socket.owner = ops->owner;
		skt->socket.dev.parent = dev;

		init_timer(&skt->poll_timer);
		skt->poll_timer.function = au1x00_pcmcia_poll_event;
		skt->poll_timer.data = (unsigned long)skt;
		skt->poll_timer.expires = jiffies + AU1000_PCMCIA_POLL_PERIOD;

		skt->nr		= first + i;
		skt->irq	= 255;
		skt->dev	= dev;
		skt->ops	= ops;

		skt->res_skt.name	= skt_names[skt->nr];
		skt->res_io.name	= "io";
		skt->res_io.flags	= IORESOURCE_MEM | IORESOURCE_BUSY;
		skt->res_mem.name	= "memory";
		skt->res_mem.flags	= IORESOURCE_MEM;
		skt->res_attr.name	= "attribute";
		skt->res_attr.flags	= IORESOURCE_MEM;

		/*
		 * 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.
		 */
		if (i == 0) {
			skt->virt_io = (void *)
				(ioremap((phys_t)AU1X_SOCK0_IO, 0x1000) -
				(u32)mips_io_port_base);
			skt->phys_attr = AU1X_SOCK0_PHYS_ATTR;
			skt->phys_mem = AU1X_SOCK0_PHYS_MEM;
		}
		else  {
			skt->virt_io = (void *)
				(ioremap((phys_t)AU1X_SOCK1_IO, 0x1000) -
				(u32)mips_io_port_base);
			skt->phys_attr = AU1X_SOCK1_PHYS_ATTR;
			skt->phys_mem = AU1X_SOCK1_PHYS_MEM;
		}
		pcmcia_base_vaddrs[i] = (u32 *)skt->virt_io;
		ret = ops->hw_init(skt);

		skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
		skt->socket.irq_mask = 0;
		skt->socket.map_size = MAP_SIZE;
		skt->socket.pci_irq = skt->irq;
		skt->socket.io_offset = (unsigned long)skt->virt_io;

		skt->status = au1x00_pcmcia_skt_state(skt);

		ret = pcmcia_register_socket(&skt->socket);
		if (ret)
			goto out_err;

		WARN_ON(skt->socket.sock != i);

		add_timer(&skt->poll_timer);
	}

	dev_set_drvdata(dev, sinfo);
	return 0;


out_err:
	flush_scheduled_work();
	ops->hw_shutdown(skt);
	while (i-- > 0) {
		skt = PCMCIA_SOCKET(i);

		del_timer_sync(&skt->poll_timer);
		pcmcia_unregister_socket(&skt->socket);
		flush_scheduled_work();
		if (i == 0) {
			iounmap(skt->virt_io + (u32)mips_io_port_base);
			skt->virt_io = NULL;
		}
#ifndef CONFIG_MIPS_XXS1500
		else {
			iounmap(skt->virt_io + (u32)mips_io_port_base);
			skt->virt_io = NULL;
		}
#endif
		ops->hw_shutdown(skt);

	}
	kfree(sinfo);
out:
	return ret;
}
Ejemplo n.º 17
0
int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
{
	int ret;

	skt->cs_state = dead_socket;

	setup_timer(&skt->poll_timer, soc_common_pcmcia_poll_event,
		    (unsigned long)skt);
	skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;

	ret = request_resource(&iomem_resource, &skt->res_skt);
	if (ret)
		goto out_err_1;

	ret = request_resource(&skt->res_skt, &skt->res_io);
	if (ret)
		goto out_err_2;

	ret = request_resource(&skt->res_skt, &skt->res_mem);
	if (ret)
		goto out_err_3;

	ret = request_resource(&skt->res_skt, &skt->res_attr);
	if (ret)
		goto out_err_4;

	skt->virt_io = ioremap(skt->res_io.start, 0x10000);
	if (skt->virt_io == NULL) {
		ret = -ENOMEM;
		goto out_err_5;
	}

	/*
	 * We initialize default socket timing here, because
	 * we are not guaranteed to see a SetIOMap operation at
	 * runtime.
	 */
	skt->ops->set_timing(skt);

	ret = soc_pcmcia_hw_init(skt);
	if (ret)
		goto out_err_6;

	skt->socket.ops = &soc_common_pcmcia_operations;
	skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
	skt->socket.resource_ops = &pccard_static_ops;
	skt->socket.irq_mask = 0;
	skt->socket.map_size = PAGE_SIZE;
	skt->socket.io_offset = (unsigned long)skt->virt_io;

	skt->status = soc_common_pcmcia_skt_state(skt);

#ifdef CONFIG_CPU_FREQ
	if (skt->ops->frequency_change) {
		skt->cpufreq_nb.notifier_call = soc_common_pcmcia_cpufreq_nb;

		ret = cpufreq_register_notifier(&skt->cpufreq_nb,
						CPUFREQ_TRANSITION_NOTIFIER);
		if (ret < 0)
			dev_err(skt->socket.dev.parent,
				"unable to register CPU frequency change notifier for PCMCIA (%d)\n",
				ret);
	}
#endif

	ret = pcmcia_register_socket(&skt->socket);
	if (ret)
		goto out_err_7;

	ret = device_create_file(&skt->socket.dev, &dev_attr_status);
	if (ret)
		goto out_err_8;

	return ret;

 out_err_8:
	del_timer_sync(&skt->poll_timer);
	pcmcia_unregister_socket(&skt->socket);

 out_err_7:
	soc_pcmcia_hw_shutdown(skt);
 out_err_6:
	iounmap(skt->virt_io);
 out_err_5:
	release_resource(&skt->res_attr);
 out_err_4:
	release_resource(&skt->res_mem);
 out_err_3:
	release_resource(&skt->res_io);
 out_err_2:
	release_resource(&skt->res_skt);
 out_err_1:

	return ret;
}
Ejemplo n.º 18
0
static int __init init_tcic(void)
{
    int i, sock, ret = 0;
    u_int mask, scan;

    if (platform_driver_register(&tcic_driver))
	return -1;
    
    printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
    sock = 0;

    if (!request_region(tcic_base, 16, "tcic-2")) {
	printk("could not allocate ports,\n ");
	platform_driver_unregister(&tcic_driver);
	return -ENODEV;
    }
    else {
	tcic_setw(TCIC_ADDR, 0);
	if (tcic_getw(TCIC_ADDR) == 0) {
	    tcic_setw(TCIC_ADDR, 0xc3a5);
	    if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
	}
	if (sock == 0) {
	    /* See if resetting the controller does any good */
	    tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
	    tcic_setb(TCIC_SCTRL, 0);
	    tcic_setw(TCIC_ADDR, 0);
	    if (tcic_getw(TCIC_ADDR) == 0) {
		tcic_setw(TCIC_ADDR, 0xc3a5);
		if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
	    }
	}
    }
    if (sock == 0) {
	printk("not found.\n");
	release_region(tcic_base, 16);
	platform_driver_unregister(&tcic_driver);
	return -ENODEV;
    }

    sockets = 0;
    for (i = 0; i < sock; i++) {
	if ((i == ignore) || is_active(i)) continue;
	socket_table[sockets].psock = i;
	socket_table[sockets].id = get_tcic_id();

	socket_table[sockets].socket.owner = THIS_MODULE;
	/* only 16-bit cards, memory windows must be size-aligned */
	/* No PCI or CardBus support */
	socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
	/* irq 14, 11, 10, 7, 6, 5, 4, 3 */
	socket_table[sockets].socket.irq_mask = 0x4cf8;
	/* 4K minimum window size */
	socket_table[sockets].socket.map_size = 0x1000;		
	sockets++;
    }

    switch (socket_table[0].id) {
    case TCIC_ID_DB86082:
	printk("DB86082"); break;
    case TCIC_ID_DB86082A:
	printk("DB86082A"); break;
    case TCIC_ID_DB86084:
	printk("DB86084"); break;
    case TCIC_ID_DB86084A:
	printk("DB86084A"); break;
    case TCIC_ID_DB86072:
	printk("DB86072"); break;
    case TCIC_ID_DB86184:
	printk("DB86184"); break;
    case TCIC_ID_DB86082B:
	printk("DB86082B"); break;
    default:
	printk("Unknown ID 0x%02x", socket_table[0].id);
    }
    
    /* Set up polling */
    poll_timer.function = &tcic_timer;
    poll_timer.data = 0;
    init_timer(&poll_timer);

    /* Build interrupt mask */
    printk(KERN_CONT ", %d sockets\n", sockets);
    printk(KERN_INFO "  irq list (");
    if (irq_list_count == 0)
	mask = irq_mask;
    else
	for (i = mask = 0; i < irq_list_count; i++)
	    mask |= (1<<irq_list[i]);

    /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
    mask &= 0x4cf8;
    /* Scan interrupts */
    mask = irq_scan(mask);
    for (i=0;i<sockets;i++)
	    socket_table[i].socket.irq_mask = mask;
    
    /* Check for only two interrupts available */
    scan = (mask & (mask-1));
    if (((scan & (scan-1)) == 0) && (poll_interval == 0))
	poll_interval = HZ;
    
    if (poll_interval == 0) {
	/* Avoid irq 12 unless it is explicitly requested */
	u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
	for (i = 15; i > 0; i--)
	    if ((cs_mask & (1 << i)) &&
		(request_irq(i, tcic_interrupt, 0, "tcic",
			     tcic_interrupt) == 0))
		break;
	cs_irq = i;
	if (cs_irq == 0) poll_interval = HZ;
    }
    
    if (socket_table[0].socket.irq_mask & (1 << 11))
	printk("sktirq is irq 11, ");
    if (cs_irq != 0)
	printk("status change on irq %d\n", cs_irq);
    else
	printk("polled status, interval = %d ms\n",
	       poll_interval * 1000 / HZ);
    
    for (i = 0; i < sockets; i++) {
	tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
	socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
    }
    
    /* jump start interrupt handler, if needed */
    tcic_interrupt(0, NULL);

    platform_device_register(&tcic_device);

    for (i = 0; i < sockets; i++) {
	    socket_table[i].socket.ops = &tcic_operations;
	    socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
	    socket_table[i].socket.dev.parent = &tcic_device.dev;
	    ret = pcmcia_register_socket(&socket_table[i].socket);
	    if (ret && i)
		    pcmcia_unregister_socket(&socket_table[0].socket);
    }
    
    return ret;

    return 0;
    
} /* init_tcic */
Ejemplo n.º 19
0
int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
{
	int ret;

	init_timer(&skt->poll_timer);
	skt->poll_timer.function = soc_common_pcmcia_poll_event;
	skt->poll_timer.data = (unsigned long)skt;
	skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;

	ret = request_resource(&iomem_resource, &skt->res_skt);
	if (ret)
		goto out_err_1;

	ret = request_resource(&skt->res_skt, &skt->res_io);
	if (ret)
		goto out_err_2;

	ret = request_resource(&skt->res_skt, &skt->res_mem);
	if (ret)
		goto out_err_3;

	ret = request_resource(&skt->res_skt, &skt->res_attr);
	if (ret)
		goto out_err_4;

	skt->virt_io = ioremap(skt->res_io.start, 0x10000);
	if (skt->virt_io == NULL) {
		ret = -ENOMEM;
		goto out_err_5;
	}

	mutex_lock(&soc_pcmcia_sockets_lock);

	list_add(&skt->node, &soc_pcmcia_sockets);

	/*
	 * We initialize default socket timing here, because
	 * we are not guaranteed to see a SetIOMap operation at
	 * runtime.
	 */
	skt->ops->set_timing(skt);

	ret = skt->ops->hw_init(skt);
	if (ret)
		goto out_err_6;

	skt->socket.ops = &soc_common_pcmcia_operations;
	skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
	skt->socket.resource_ops = &pccard_static_ops;
	skt->socket.irq_mask = 0;
	skt->socket.map_size = PAGE_SIZE;
	skt->socket.io_offset = (unsigned long)skt->virt_io;

	skt->status = soc_common_pcmcia_skt_state(skt);

	ret = pcmcia_register_socket(&skt->socket);
	if (ret)
		goto out_err_7;

	add_timer(&skt->poll_timer);

	mutex_unlock(&soc_pcmcia_sockets_lock);

	ret = device_create_file(&skt->socket.dev, &dev_attr_status);
	if (ret)
		goto out_err_8;

	return ret;

 out_err_8:
	mutex_lock(&soc_pcmcia_sockets_lock);
	del_timer_sync(&skt->poll_timer);
	pcmcia_unregister_socket(&skt->socket);

 out_err_7:
	flush_scheduled_work();

	skt->ops->hw_shutdown(skt);
 out_err_6:
	list_del(&skt->node);
	mutex_unlock(&soc_pcmcia_sockets_lock);
	iounmap(skt->virt_io);
 out_err_5:
	release_resource(&skt->res_attr);
 out_err_4:
	release_resource(&skt->res_mem);
 out_err_3:
	release_resource(&skt->res_io);
 out_err_2:
	release_resource(&skt->res_skt);
 out_err_1:

	return ret;
}
Ejemplo n.º 20
0
int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,
				struct skt_dev_info *sinfo)
{
	struct soc_pcmcia_socket *skt;
	int ret, i;

	mutex_lock(&soc_pcmcia_sockets_lock);

	/*
	 * Initialise the per-socket structure.
	 */
	for (i = 0; i < sinfo->nskt; i++) {
		skt = &sinfo->skt[i];

		skt->socket.ops = &soc_common_pcmcia_operations;
		skt->socket.owner = ops->owner;
		skt->socket.dev.parent = dev;

		init_timer(&skt->poll_timer);
		skt->poll_timer.function = soc_common_pcmcia_poll_event;
		skt->poll_timer.data = (unsigned long)skt;
		skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD;

		skt->dev	= dev;
		skt->ops	= ops;

		ret = request_resource(&iomem_resource, &skt->res_skt);
		if (ret)
			goto out_err_1;

		ret = request_resource(&skt->res_skt, &skt->res_io);
		if (ret)
			goto out_err_2;

		ret = request_resource(&skt->res_skt, &skt->res_mem);
		if (ret)
			goto out_err_3;

		ret = request_resource(&skt->res_skt, &skt->res_attr);
		if (ret)
			goto out_err_4;

		skt->virt_io = ioremap(skt->res_io.start, 0x10000);
		if (skt->virt_io == NULL) {
			ret = -ENOMEM;
			goto out_err_5;
		}

		if (list_empty(&soc_pcmcia_sockets))
			soc_pcmcia_cpufreq_register();

		list_add(&skt->node, &soc_pcmcia_sockets);

		/*
		 * We initialize default socket timing here, because
		 * we are not guaranteed to see a SetIOMap operation at
		 * runtime.
		 */
		ops->set_timing(skt);

		ret = ops->hw_init(skt);
		if (ret)
			goto out_err_6;

		skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD;
		skt->socket.resource_ops = &pccard_static_ops;
		skt->socket.irq_mask = 0;
		skt->socket.map_size = PAGE_SIZE;
		skt->socket.pci_irq = skt->irq;
		skt->socket.io_offset = (unsigned long)skt->virt_io;

		skt->status = soc_common_pcmcia_skt_state(skt);

		ret = pcmcia_register_socket(&skt->socket);
		if (ret)
			goto out_err_7;

		WARN_ON(skt->socket.sock != i);

		add_timer(&skt->poll_timer);

		ret = device_create_file(&skt->socket.dev, &dev_attr_status);
		if (ret)
			goto out_err_8;
	}

	dev_set_drvdata(dev, sinfo);
	ret = 0;
	goto out;

	do {
		skt = &sinfo->skt[i];

		device_remove_file(&skt->socket.dev, &dev_attr_status);
 out_err_8:
		del_timer_sync(&skt->poll_timer);
		pcmcia_unregister_socket(&skt->socket);

 out_err_7:
		flush_scheduled_work();

		ops->hw_shutdown(skt);
 out_err_6:
 		list_del(&skt->node);
		iounmap(skt->virt_io);
 out_err_5:
		release_resource(&skt->res_attr);
 out_err_4:
		release_resource(&skt->res_mem);
 out_err_3:
		release_resource(&skt->res_io);
 out_err_2:
		release_resource(&skt->res_skt);
 out_err_1:
		i--;
	} while (i > 0);

	kfree(sinfo);

 out:
	mutex_unlock(&soc_pcmcia_sockets_lock);
	return ret;
}