static int __init omap_cf_probe()

in omap_cf.c [202:318]


static int __init omap_cf_probe(struct platform_device *pdev)
{
	unsigned		seg;
	struct omap_cf_socket	*cf;
	int			irq;
	int			status;

	seg = (int) pdev->dev.platform_data;
	if (seg == 0 || seg > 3)
		return -ENODEV;

	/* either CFLASH.IREQ (INT_1610_CF) or some GPIO */
	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return -EINVAL;

	cf = kzalloc(sizeof *cf, GFP_KERNEL);
	if (!cf)
		return -ENOMEM;
	timer_setup(&cf->timer, omap_cf_timer, 0);

	cf->pdev = pdev;
	platform_set_drvdata(pdev, cf);

	/* this primarily just shuts up irq handling noise */
	status = request_irq(irq, omap_cf_irq, IRQF_SHARED,
			driver_name, cf);
	if (status < 0)
		goto fail0;
	cf->irq = irq;
	cf->socket.pci_irq = irq;

	switch (seg) {
	/* NOTE: CS0 could be configured too ... */
	case 1:
		cf->phys_cf = OMAP_CS1_PHYS;
		break;
	case 2:
		cf->phys_cf = OMAP_CS2_PHYS;
		break;
	case 3:
		cf->phys_cf = omap_cs3_phys();
		break;
	default:
		goto  fail1;
	}
	cf->iomem.start = cf->phys_cf;
	cf->iomem.end = cf->iomem.end + SZ_8K - 1;
	cf->iomem.flags = IORESOURCE_MEM;

	/* pcmcia layer only remaps "real" memory */
	cf->socket.io_offset = (unsigned long)
			ioremap(cf->phys_cf + SZ_4K, SZ_2K);
	if (!cf->socket.io_offset) {
		status = -ENOMEM;
		goto fail1;
	}

	if (!request_mem_region(cf->phys_cf, SZ_8K, driver_name)) {
		status = -ENXIO;
		goto fail1;
	}

	/* NOTE:  CF conflicts with MMC1 */
	omap_cfg_reg(W11_1610_CF_CD1);
	omap_cfg_reg(P11_1610_CF_CD2);
	omap_cfg_reg(R11_1610_CF_IOIS16);
	omap_cfg_reg(V10_1610_CF_IREQ);
	omap_cfg_reg(W10_1610_CF_RESET);

	omap_writew(~(1 << seg), CF_CFG);

	pr_info("%s: cs%d on irq %d\n", driver_name, seg, irq);

	/* NOTE:  better EMIFS setup might support more cards; but the
	 * TRM only shows how to affect regular flash signals, not their
	 * CF/PCMCIA variants...
	 */
	pr_debug("%s: cs%d, previous ccs %08x acs %08x\n", driver_name,
		seg, omap_readl(EMIFS_CCS(seg)), omap_readl(EMIFS_ACS(seg)));
	omap_writel(0x0004a1b3, EMIFS_CCS(seg));	/* synch mode 4 etc */
	omap_writel(0x00000000, EMIFS_ACS(seg));	/* OE hold/setup */

	/* CF uses armxor_ck, which is "always" available */

	pr_debug("%s: sts %04x cfg %04x control %04x %s\n", driver_name,
		omap_readw(CF_STATUS), omap_readw(CF_CFG),
		omap_readw(CF_CONTROL),
		omap_cf_present() ? "present" : "(not present)");

	cf->socket.owner = THIS_MODULE;
	cf->socket.dev.parent = &pdev->dev;
	cf->socket.ops = &omap_cf_ops;
	cf->socket.resource_ops = &pccard_static_ops;
	cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP
				| SS_CAP_MEM_ALIGN;
	cf->socket.map_size = SZ_2K;
	cf->socket.io[0].res = &cf->iomem;

	status = pcmcia_register_socket(&cf->socket);
	if (status < 0)
		goto fail2;

	cf->active = 1;
	mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
	return 0;

fail2:
	release_mem_region(cf->phys_cf, SZ_8K);
fail1:
	if (cf->socket.io_offset)
		iounmap((void __iomem *) cf->socket.io_offset);
	free_irq(irq, cf);
fail0:
	kfree(cf);
	return status;
}