14d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/*
24d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * SDIO access interface for drivers - linux specific (pci only)
34d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *
407770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman * Copyright (C) 1999-2010, Broadcom Corporation
54d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *
64d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *      Unless you and Broadcom execute a separate written software license
74d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * agreement governing use of this software, this software is licensed to you
84d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * under the terms of the GNU General Public License version 2 (the "GPL"),
94d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * available at http://www.broadcom.com/licenses/GPLv2.php, with the
104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * following added to such license:
114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *
124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *      As a special exception, the copyright holders of this software give you
134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * permission to link this software with independent modules, and to copy and
144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * distribute the resulting executable under terms of your choice, provided that
154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * you also meet, for each linked independent module, the terms and conditions of
164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * the license of that module.  An independent module is a module which is not
174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * derived from this software.  The special exception does not apply to any
184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * modifications of the software.
194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *
204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *      Notwithstanding the above, under no circumstances may you combine this
214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * software in any way with any other Broadcom software provided under a license
224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * other than the GPL, without Broadcom's express prior written consent.
234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *
249984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt * $Id: bcmsdh_linux.c,v 1.42.10.10.2.14.4.2 2010/09/15 00:30:11 Exp $
254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/**
284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * @file bcmsdh_linux.c
294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define __UNDEF_NO_VERSION__
324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <typedefs.h>
344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <linuxver.h>
354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <linux/pci.h>
374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <linux/completion.h>
384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <osl.h>
404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <pcicfg.h>
414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmdefs.h>
424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <bcmdevs.h>
434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
44492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#if defined(OOB_INTR_ONLY)
45492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#include <linux/irq.h>
46492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidtextern void dhdsdio_isr(void * args);
47492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#include <bcmutils.h>
48492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#include <dngl_stats.h>
49492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#include <dhd.h>
50492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#endif /* defined(OOB_INTR_ONLY) */
514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270)
524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if !defined(BCMPLATFORM_BUS)
534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define BCMPLATFORM_BUS
544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* !defined(BCMPLATFORM_BUS) */
554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19))
574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#include <linux/platform_device.h>
584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* KERNEL_VERSION(2, 6, 19) */
594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* CONFIG_MACH_SANDGATE2G || CONFIG_MACH_LOGICPD_PXA270 */
604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/**
624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * SDIO Host Controller info
634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidttypedef struct bcmsdh_hc bcmsdh_hc_t;
654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstruct bcmsdh_hc {
674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_hc_t *next;
684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifdef BCMPLATFORM_BUS
694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	struct device *dev;			/* platform device handle */
704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#else
714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	struct pci_dev *dev;		/* pci device handle */
724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMPLATFORM_BUS */
734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osl_t *osh;
744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	void *regs;			/* SDIO Host Controller address */
754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_info_t *sdh;		/* SDIO Host Controller handle */
764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	void *ch;
77492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	unsigned int oob_irq;
789984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	unsigned long oob_flags; /* OOB Host specifiction as edge and etc */
799984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	bool oob_irq_registered;
809984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt#if defined(OOB_INTR_ONLY)
819984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	spinlock_t irq_lock;
829984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt#endif
834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt};
844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic bcmsdh_hc_t *sdhcinfo = NULL;
854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* driver info, initialized when bcmsdh_register is called */
874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic bcmsdh_driver_t drvinfo = {NULL, NULL};
884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* debugging macros */
904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#define SDLX_MSG(x)
914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/**
934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Checks to see if vendor and device IDs match a supported SDIO Host Controller.
944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtbool
964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtbcmsdh_chipmatch(uint16 vendor, uint16 device)
974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{
984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* Add other vendors and devices as required */
994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifdef BCMSDIOH_STD
1014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* Check for Arasan host controller */
1024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (vendor == VENDOR_SI_IMAGE) {
1034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* Check for BRCM 27XX Standard host controller */
1064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (device == BCM27XX_SDIOH_ID && vendor == VENDOR_BROADCOM) {
1074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* Check for BRCM Standard host controller */
1104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (device == SDIOH_FPGA_ID && vendor == VENDOR_BROADCOM) {
1114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* Check for TI PCIxx21 Standard host controller */
1144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI) {
1154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI) {
1184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* Ricoh R5C822 Standard SDIO Host */
1214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH) {
1224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* JMicron Standard SDIO Host */
1254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON) {
1264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMSDIOH_STD */
1304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifdef BCMSDIOH_SPI
1314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* This is the PciSpiHost. */
1324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) {
1334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		printf("Found PCI SPI Host Controller\n");
1344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return (TRUE);
1354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
1364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMSDIOH_SPI */
1384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return (FALSE);
1404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}
1414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(BCMPLATFORM_BUS)
1434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(BCMLXSDMMC)
1444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* forward declarations */
1454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint bcmsdh_probe(struct device *dev);
1464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint bcmsdh_remove(struct device *dev);
1474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_probe);
1494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_remove);
1504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#else
1524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* forward declarations */
1534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int __devinit bcmsdh_probe(struct device *dev);
1544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int __devexit bcmsdh_remove(struct device *dev);
1554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
1564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifndef BCMLXSDMMC
1584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic struct device_driver bcmsdh_driver = {
1594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	.name		= "pxa2xx-mci",
1604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	.bus		= &platform_bus_type,
1614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	.probe		= bcmsdh_probe,
1624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	.remove		= bcmsdh_remove,
1634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	.suspend	= NULL,
1644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	.resume		= NULL,
1654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	};
1664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
1674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifndef BCMLXSDMMC
1694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic
1704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
1714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint bcmsdh_probe(struct device *dev)
1724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{
1734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osl_t *osh = NULL;
1744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_hc_t *sdhc = NULL;
1754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	ulong regs = 0;
1764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_info_t *sdh = NULL;
1774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
1784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	struct platform_device *pdev;
1794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	struct resource *r;
1804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
1814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	int irq = 0;
1824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	uint32 vendevid;
1839984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	unsigned long irq_flags = 0;
1844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
1854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
1864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	pdev = to_platform_device(dev);
1874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	irq = platform_get_irq(pdev, 0);
1894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!r || irq == NO_IRQ)
1904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return -ENXIO;
1914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
1924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
193492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#if defined(OOB_INTR_ONLY)
1949984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt#ifdef HW_OOB
1959984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	irq_flags = \
1969984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
1979984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt#else
1989984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	 irq_flags = IRQF_TRIGGER_FALLING;
1999984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt#endif /* HW_OOB */
2009b66717d9e4dd32e61a03f572d4eaebbfb4ee6c3Dmitry Shmidt	irq = dhd_customer_oob_irq_map(&irq_flags);
201492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	if  (irq < 0) {
202492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt		SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__));
203492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt		return 1;
204492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	}
205492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#endif /* defined(OOB_INTR_ONLY) */
2064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* allocate SDIO Host Controller state info */
2074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) {
2084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
2094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
2104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) {
2124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: out of memory, allocated %d bytes\n",
2134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			__FUNCTION__,
2144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			MALLOCED(osh)));
2154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
2164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bzero(sdhc, sizeof(bcmsdh_hc_t));
2184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhc->osh = osh;
2194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhc->dev = (void *)dev;
2214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifdef BCMLXSDMMC
2234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(sdh = bcmsdh_attach(osh, (void *)0,
2244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	                          (void **)&regs, irq))) {
2254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
2264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
2274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#else
2294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(sdh = bcmsdh_attach(osh, (void *)r->start,
2304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	                          (void **)&regs, irq))) {
2314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
2324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
2334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
2354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhc->sdh = sdh;
236492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	sdhc->oob_irq = irq;
2379b66717d9e4dd32e61a03f572d4eaebbfb4ee6c3Dmitry Shmidt	sdhc->oob_flags = irq_flags;
2389984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	sdhc->oob_irq_registered = FALSE;	/* to make sure.. */
2399984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt#if defined(OOB_INTR_ONLY)
2409984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	spin_lock_init(&sdhc->irq_lock);
2419984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt#endif
2424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
243492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	/* chain SDIO Host Controller info together */
244492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	sdhc->next = sdhcinfo;
245492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	sdhcinfo = sdhc;
2464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* Read the vendor/device ID from the CIS */
2474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	vendevid = bcmsdh_query_device(sdh);
2484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* try to attach to the target device */
2504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(sdhc->ch = drvinfo.attach((vendevid >> 16),
2514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	                                 (vendevid & 0xFFFF), 0, 0, 0, 0,
2524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	                                (void *)regs, NULL, sdh))) {
2534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
2544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
2554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return 0;
2584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* error handling */
2604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidterr:
2614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (sdhc) {
2624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		if (sdhc->sdh)
2634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			bcmsdh_detach(sdhc->osh, sdhc->sdh);
2644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
2654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (osh)
2674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		osl_detach(osh);
2684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return -ENODEV;
2694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}
2704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifndef BCMLXSDMMC
2724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic
2734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
2744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint bcmsdh_remove(struct device *dev)
2754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{
2764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_hc_t *sdhc, *prev;
2774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osl_t *osh;
2784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
279492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	sdhc = sdhcinfo;
280492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	drvinfo.detach(sdhc->ch);
281492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	bcmsdh_detach(sdhc->osh, sdhc->sdh);
2824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* find the SDIO Host Controller state for this pdev and take it out from the list */
2834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
2844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		if (sdhc->dev == (void *)dev) {
2854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			if (prev)
2864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt				prev->next = sdhc->next;
2874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			else
2884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt				sdhcinfo = NULL;
2894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			break;
2904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		}
2914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		prev = sdhc;
2924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!sdhc) {
2944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: failed\n", __FUNCTION__));
2954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return 0;
2964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
2974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
2994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* release SDIO Host Controller info */
3004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osh = sdhc->osh;
3014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
3024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osl_detach(osh);
3034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
3044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if !defined(BCMLXSDMMC)
3054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	dev_set_drvdata(dev, NULL);
3064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* !defined(BCMLXSDMMC) */
3074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
3084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return 0;
3094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}
3104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
3114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#else /* BCMPLATFORM_BUS */
3124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
3134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if !defined(BCMLXSDMMC)
3144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* forward declarations for PCI probe and remove functions. */
3154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int __devinit bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
3164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic void __devexit bcmsdh_pci_remove(struct pci_dev *pdev);
3174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
3184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/**
3194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * pci id table
3204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
3214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic struct pci_device_id bcmsdh_pci_devid[] __devinitdata = {
3224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	{ vendor: PCI_ANY_ID,
3234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	device: PCI_ANY_ID,
3244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	subvendor: PCI_ANY_ID,
3254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	subdevice: PCI_ANY_ID,
3264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	class: 0,
3274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	class_mask: 0,
3284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	driver_data: 0,
3294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	},
3304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	{ 0, }
3314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt};
3324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtMODULE_DEVICE_TABLE(pci, bcmsdh_pci_devid);
3334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
3344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/**
3354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * SDIO Host Controller pci driver info
3364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
3374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic struct pci_driver bcmsdh_pci_driver = {
3384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	node:		{},
3394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	name:		"bcmsdh",
3404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	id_table:	bcmsdh_pci_devid,
3414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	probe:		bcmsdh_pci_probe,
3424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	remove:		bcmsdh_pci_remove,
3434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
3444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	save_state:	NULL,
3454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif
3464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	suspend:	NULL,
3474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	resume:		NULL,
3481a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt};
3494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
3504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
35107770aa679cd45674eaac3d8fb2e01a995068838Greg Goldmanextern uint sd_pci_slot;	/* Force detection to a particular PCI */
3521a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt				/* slot only . Allows for having multiple */
3531a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt				/* WL devices at once in a PC */
3541a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt				/* Only one instance of dhd will be */
3559984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt				/* usable at a time */
3561a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt				/* Upper word is bus number, */
3571a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt				/* lower word is slot number */
3581a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt				/* Default value of 0xFFFFffff turns this */
3591a9040ebea203168187d4e8f55cd5566a8eace4cDmitry Shmidt				/* off */
36007770aa679cd45674eaac3d8fb2e01a995068838Greg Goldmanmodule_param(sd_pci_slot, uint, 0);
36107770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman
36207770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman
3634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/**
3644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Detect supported SDIO Host Controller and attach if found.
3654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt *
3664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Determine if the device described by pdev is a supported SDIO Host
3674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Controller.  If so, attach to it and attach to the target device.
3684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
3694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic int __devinit
3704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtbcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{
3724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osl_t *osh = NULL;
3734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_hc_t *sdhc = NULL;
3744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	ulong regs;
3754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_info_t *sdh = NULL;
3764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	int rc;
3774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
37807770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman	if (sd_pci_slot != 0xFFFFffff) {
37907770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman		if (pdev->bus->number != (sd_pci_slot>>16) ||
38007770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman			PCI_SLOT(pdev->devfn) != (sd_pci_slot&0xffff)) {
38107770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman			SDLX_MSG(("%s: %s: bus %X, slot %X, vend %X, dev %X\n",
3829984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			          __FUNCTION__,
3839984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			          bcmsdh_chipmatch(pdev->vendor, pdev->device) ?
3849984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			          "Found compatible SDIOHC" :
3859984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			          "Probing unknown device",
3869984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			          pdev->bus->number, PCI_SLOT(pdev->devfn),
3879984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			          pdev->vendor, pdev->device));
38807770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman			return -ENODEV;
38907770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman		}
39007770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman		SDLX_MSG(("%s: %s: bus %X, slot %X, vendor %X, device %X (good PCI location)\n",
3919984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		          __FUNCTION__,
3929984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		          bcmsdh_chipmatch(pdev->vendor, pdev->device) ?
3939984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		          "Using compatible SDIOHC" :
3949984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		          "WARNING, forced use of unkown device",
3959984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		          pdev->bus->number, PCI_SLOT(pdev->devfn),
3969984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		          pdev->vendor, pdev->device));
39707770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman	}
39807770aa679cd45674eaac3d8fb2e01a995068838Greg Goldman
3994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if ((pdev->vendor == VENDOR_TI) && ((pdev->device == PCIXX21_FLASHMEDIA_ID) ||
4004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	    (pdev->device == PCIXX21_FLASHMEDIA0_ID))) {
4014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		uint32 config_reg;
4024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: Disabling TI FlashMedia Controller.\n", __FUNCTION__));
4044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
4054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
4064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			goto err;
4074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		}
4084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		config_reg = OSL_PCI_READ_CONFIG(osh, 0x4c, 4);
4104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		/*
4124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		 * Set MMC_SD_DIS bit in FlashMedia Controller.
4134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		 * Disbling the SD/MMC Controller in the FlashMedia Controller
4144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		 * allows the Standard SD Host Controller to take over control
4154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		 * of the SD Slot.
4164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		 */
4174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		config_reg |= 0x02;
4184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		OSL_PCI_WRITE_CONFIG(osh, 0x4c, 4, config_reg);
4194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		osl_detach(osh);
4204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
4214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* match this pci device with what we support */
4224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* we can't solely rely on this to believe it is our SDIO Host Controller! */
4234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!bcmsdh_chipmatch(pdev->vendor, pdev->device)) {
4244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return -ENODEV;
4254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
4264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* this is a pci device we might support */
4284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	SDLX_MSG(("%s: Found possible SDIO Host Controller: bus %d slot %d func %d irq %d\n",
4294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		__FUNCTION__,
4304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		pdev->bus->number, PCI_SLOT(pdev->devfn),
4314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		PCI_FUNC(pdev->devfn), pdev->irq));
4324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* use bcmsdh_query_device() to get the vendor ID of the target device so
4344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	 * it will eventually appear in the Broadcom string on the console
4354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	 */
4364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* allocate SDIO Host Controller state info */
4384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
4394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__));
4404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
4414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
4424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) {
4434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: out of memory, allocated %d bytes\n",
4444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			__FUNCTION__,
4454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			MALLOCED(osh)));
4464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
4474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
4484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bzero(sdhc, sizeof(bcmsdh_hc_t));
4494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhc->osh = osh;
4504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhc->dev = pdev;
4524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* map to address where host can access */
4544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	pci_set_master(pdev);
4554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	rc = pci_enable_device(pdev);
4564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (rc) {
4579984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		SDLX_MSG(("%s: Cannot enable PCI device\n", __FUNCTION__));
4584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
4594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
4604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(sdh = bcmsdh_attach(osh, (void *)(uintptr)pci_resource_start(pdev, 0),
4614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	                          (void **)&regs, pdev->irq))) {
4624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
4634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
4644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
4654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhc->sdh = sdh;
4674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* try to attach to the target device */
4694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(sdhc->ch = drvinfo.attach(VENDOR_BROADCOM, /* pdev->vendor, */
4704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	                                bcmsdh_query_device(sdh) & 0xFFFF, 0, 0, 0, 0,
4714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	                                (void *)regs, NULL, sdh))) {
4724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
4734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		goto err;
4744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
4754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* chain SDIO Host Controller info together */
4774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhc->next = sdhcinfo;
4784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdhcinfo = sdhc;
4794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return 0;
4814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* error handling */
4834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidterr:
4844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (sdhc->sdh)
4854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		bcmsdh_detach(sdhc->osh, sdhc->sdh);
4864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (sdhc)
4874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
4884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (osh)
4894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		osl_detach(osh);
4904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return -ENODEV;
4914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}
4924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
4944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/**
4954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt * Detach from target devices and SDIO Host Controller
4964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt */
4974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtstatic void __devexit
4984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtbcmsdh_pci_remove(struct pci_dev *pdev)
4994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{
5004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_hc_t *sdhc, *prev;
5014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osl_t *osh;
5024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* find the SDIO Host Controller state for this pdev and take it out from the list */
5044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
5054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		if (sdhc->dev == pdev) {
5064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			if (prev)
5074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt				prev->next = sdhc->next;
5084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			else
5094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt				sdhcinfo = NULL;
5104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt			break;
5114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		}
5124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		prev = sdhc;
5134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	}
5144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!sdhc)
5154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return;
5164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	drvinfo.detach(sdhc->ch);
5184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5194d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	bcmsdh_detach(sdhc->osh, sdhc->sdh);
5204d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5214d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	/* release SDIO Host Controller info */
5224d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osh = sdhc->osh;
5234d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	MFREE(osh, sdhc, sizeof(bcmsdh_hc_t));
5244d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	osl_detach(osh);
5254d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}
5264d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
5274d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMPLATFORM_BUS */
5284d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5294d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern int sdio_function_init(void);
5304d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5314d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtint
5324d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtbcmsdh_register(bcmsdh_driver_t *driver)
5334d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{
5344d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	int error = 0;
5354d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5364d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	drvinfo = *driver;
5374d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5384d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(BCMPLATFORM_BUS)
5394d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(BCMLXSDMMC)
5404d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
5414d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	error = sdio_function_init();
5424d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#else
5434d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	SDLX_MSG(("Intel PXA270 SDIO Driver\n"));
5444d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	error = driver_register(&bcmsdh_driver);
5454d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* defined(BCMLXSDMMC) */
5464d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return error;
5474d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* defined(BCMPLATFORM_BUS) */
5484d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5494d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
5504d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
5514d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(error = pci_module_init(&bcmsdh_pci_driver)))
5524d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return 0;
5534d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#else
5544d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (!(error = pci_register_driver(&bcmsdh_pci_driver)))
5554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		return 0;
5564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif
5574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	SDLX_MSG(("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error));
5594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMPLATFORM_BUS */
5604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	return error;
5624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}
5634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern void sdio_function_cleanup(void);
5654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtvoid
5674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtbcmsdh_unregister(void)
5684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt{
5694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0))
5704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	if (bcmsdh_pci_driver.node.next)
5714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif
5724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
5744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		driver_unregister(&bcmsdh_driver);
5754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif
5764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(BCMLXSDMMC)
5774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt	sdio_function_cleanup();
5784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMLXSDMMC */
5794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
5804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt		pci_unregister_driver(&bcmsdh_pci_driver);
5814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMPLATFORM_BUS */
5824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt}
5834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
5849984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt
5859984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt
586492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#if defined(OOB_INTR_ONLY)
5879984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidtvoid bcmsdh_oob_intr_set(bool enable)
5889984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt{
5899984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	static bool curstate = 1;
5909984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	unsigned long flags;
5919984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt
5929984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
5939984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	if (curstate != enable) {
5949984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		if (enable)
5959984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			enable_irq(sdhcinfo->oob_irq);
5969984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		else
5979984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			disable_irq_nosync(sdhcinfo->oob_irq);
5989984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		curstate = enable;
5999984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	}
6009984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
6019984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt}
6029984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt
603492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidtstatic irqreturn_t wlan_oob_irq(int irq, void *dev_id)
604492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt{
605492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	dhd_pub_t *dhdp;
606492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
607a05cf6aee61444a6f415731b3c1e9529904da85dDmitry Shmidt	dhdp = (dhd_pub_t *)dev_get_drvdata(sdhcinfo->dev);
608492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
6099984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	bcmsdh_oob_intr_set(0);
6109984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt
611492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	if (dhdp == NULL) {
612492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt		SDLX_MSG(("Out of band GPIO interrupt fired way too early\n"));
613492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt		return IRQ_HANDLED;
614492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	}
615492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
616492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	dhdsdio_isr((void *)dhdp->bus);
617492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
618492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	return IRQ_HANDLED;
619492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt}
620492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
621492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidtint bcmsdh_register_oob_intr(void * dhdp)
622492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt{
623492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	int error = 0;
624492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
625492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	SDLX_MSG(("%s Enter\n", __FUNCTION__));
626492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
627a05cf6aee61444a6f415731b3c1e9529904da85dDmitry Shmidt	dev_set_drvdata(sdhcinfo->dev, dhdp);
628492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
6299984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	if (!sdhcinfo->oob_irq_registered) {
6309984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		SDLX_MSG(("%s IRQ=%d Type=%X \n", __FUNCTION__, \
6319984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt				(int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags));
6329984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		/* Refer to customer Host IRQ docs about proper irqflags definition */
6339984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, sdhcinfo->oob_flags,
6349984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			"bcmsdh_sdmmc", NULL);
6359984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		if (error)
6369984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt			return -ENODEV;
637492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
6389984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		set_irq_wake(sdhcinfo->oob_irq, 1);
6399984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt		sdhcinfo->oob_irq_registered = TRUE;
6409984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	}
6419b66717d9e4dd32e61a03f572d4eaebbfb4ee6c3Dmitry Shmidt
642492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	return 0;
643492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt}
644492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
645492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidtvoid bcmsdh_unregister_oob_intr(void)
646492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt{
647492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	SDLX_MSG(("%s: Enter\n", __FUNCTION__));
648492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt
649492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	set_irq_wake(sdhcinfo->oob_irq, 0);
650492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	disable_irq(sdhcinfo->oob_irq);	/* just in case.. */
651492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt	free_irq(sdhcinfo->oob_irq, NULL);
6529984c42af1f24da360515edd81441ef5dfe23da4Dmitry Shmidt	sdhcinfo->oob_irq_registered = FALSE;
653492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt}
654492884be0b302c6c6ea51b360c1f7b0996d96a8bDmitry Shmidt#endif /* defined(OOB_INTR_ONLY) */
6554d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt/* Module parameters specific to each host-controller driver */
6564d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6574d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern uint sd_msglevel;	/* Debug message level */
6584d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtmodule_param(sd_msglevel, uint, 0);
6594d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6604d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern uint sd_power;	/* 0 = SD Power OFF, 1 = SD Power ON. */
6614d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtmodule_param(sd_power, uint, 0);
6624d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6634d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern uint sd_clock;	/* SD Clock Control, 0 = SD Clock OFF, 1 = SD Clock ON */
6644d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtmodule_param(sd_clock, uint, 0);
6654d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6664d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern uint sd_divisor;	/* Divisor (-1 means external clock) */
6674d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtmodule_param(sd_divisor, uint, 0);
6684d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6694d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern uint sd_sdmode;	/* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */
6704d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtmodule_param(sd_sdmode, uint, 0);
6714d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6724d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern uint sd_hiok;	/* Ok to use hi-speed mode */
6734d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtmodule_param(sd_hiok, uint, 0);
6744d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6754d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtextern uint sd_f2_blocksize;
6764d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidtmodule_param(sd_f2_blocksize, int, 0);
6774d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6784d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6794d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#ifdef BCMSDH_MODULE
6804d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_attach);
6814d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_detach);
6824d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_intr_query);
6834d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_intr_enable);
6844d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_intr_disable);
6854d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_intr_reg);
6864d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_intr_dereg);
6874d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6884d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#if defined(DHD_DEBUG)
6894d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_intr_pending);
6904d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif
6914d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
6924d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_devremove_reg);
6934d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_cfg_read);
6944d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_cfg_write);
6954d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_cis_read);
6964d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_reg_read);
6974d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_reg_write);
6984d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_regfail);
6994d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_send_buf);
7004d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_recv_buf);
7014d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
7024d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_rwdata);
7034d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_abort);
7044d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_query_device);
7054d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_query_iofnum);
7064d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_iovar_op);
7074d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_register);
7084d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_unregister);
7094d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_chipmatch);
7104d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_reset);
7114d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
7124d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_get_dstatus);
7134d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_cfg_read_word);
7144d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_cfg_write_word);
7154d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_cur_sbwad);
7164d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry ShmidtEXPORT_SYMBOL(bcmsdh_chipinfo);
7174d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt
7184d92e4c7da35860a39214c8fdb794ce0243dfabbDmitry Shmidt#endif /* BCMSDH_MODULE */
719