static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
{
	struct sdhci_host *host;
	struct sdio_dev *dev;
	struct resource *iomem;
	struct sdio_platform_cfg *hw_cfg = NULL;
	char devname[MAX_DEV_NAME_SIZE];
	int ret = 0;
	char *emmc_regulator = NULL;
#ifdef CONFIG_MACH_BCM_FPGA
	u32 of_quirks = 0;
	u32 of_quirks2 = 0;
#endif

	pr_debug("%s: ENTRY\n", __func__);

	BUG_ON(pdev == NULL);

	hw_cfg = (struct sdio_platform_cfg *)pdev->dev.platform_data;
	if (pdev->dev.of_node) {
		u32 val;
		const char *prop;
		if (!pdev->dev.platform_data)
			hw_cfg = kzalloc(sizeof(struct sdio_platform_cfg),
				GFP_KERNEL);

		if (!hw_cfg) {
			dev_err(&pdev->dev,
				"unable to allocate mem for private data\n");
			ret = -ENOMEM;
			goto err;
		}
		if (of_property_read_u32(pdev->dev.of_node, "id", &val)) {
			dev_err(&pdev->dev, "id read failed in %s\n", __func__);
			goto err_free_priv_data_mem;
		}

		hw_cfg->id = val;
		pdev->id = val;

		if (of_property_read_u32(pdev->dev.of_node, "data-pullup",
			&val)) {
			dev_err(&pdev->dev, "data-pullup read failed in %s\n",
			__func__);
			goto err_free_priv_data_mem;
		}

		hw_cfg->data_pullup = val;

		if (of_property_read_u32(pdev->dev.of_node, "devtype", &val)) {
			dev_err(&pdev->dev, "devtype read failed in %s\n",
			__func__);
			goto err_free_priv_data_mem;
		}

		hw_cfg->devtype = val;

		if (of_property_read_u32(pdev->dev.of_node, "flags", &val)) {
			dev_err(&pdev->dev, "flags read failed in %s\n",
			__func__);
			goto err_free_priv_data_mem;
		}

		hw_cfg->flags = val;

		if (of_property_read_string(pdev->dev.of_node, "peri-clk-name",
			&prop)) {
			dev_err(&pdev->dev, "peri-clk-name read failed in %s\n",
			__func__);
			goto err_free_priv_data_mem;
		}

		hw_cfg->peri_clk_name = (char *)prop;

		if (of_property_read_string(pdev->dev.of_node, "ahb-clk-name",
			&prop)) {
			dev_err(&pdev->dev, "ahb-clk-name read failed in %s\n",
			__func__);
			goto err_free_priv_data_mem;
		}

		hw_cfg->ahb_clk_name = (char *)prop;

		if (of_property_read_string(pdev->dev.of_node, "sleep-clk-name",
			&prop)) {
			dev_err(&pdev->dev, "sleep-clk-name read failed in %s\n",
			__func__);
			goto err_free_priv_data_mem;
		}

		hw_cfg->sleep_clk_name = (char *)prop;

		if (of_property_read_u32(pdev->dev.of_node, "peri-clk-rate",
			&val)) {
			dev_err(&pdev->dev, "peri-clk-rate read failed in %s\n",
			__func__);
			goto err_free_priv_data_mem;
		}

#ifdef CONFIG_MACH_BCM_FPGA
		if (of_property_read_u32(pdev->dev.of_node, "quirks", &of_quirks)) {
			pr_info("quirks = 0x%08x foud for the configuration\n", of_quirks);
		}

		if (of_property_read_u32(pdev->dev.of_node, "quirks2", &of_quirks2)) {
			pr_info("quirks2 = 0x%08x foud for the configuration\n", of_quirks2);
		}
#endif

		hw_cfg->peri_clk_rate = val;

		if (hw_cfg->devtype == SDIO_DEV_TYPE_SDMMC) {
			if (of_property_read_string(pdev->dev.of_node,
				"vddo-regulator-name", &prop)) {
				dev_err(&pdev->dev, "vddo-regulator-name read "\
				"failed in %s\n", __func__);
				goto err_free_priv_data_mem;
			}

			hw_cfg->vddo_regulator_name = (char *)prop;

			if (of_property_read_string(pdev->dev.of_node,
				"vddsdxc-regulator-name", &prop)) {
				dev_err(&pdev->dev, "vddsdxc-regulator-name"\
				"read failed in %s\n", __func__);
				goto err_free_priv_data_mem;
			}

			hw_cfg->vddsdxc_regulator_name = (char *)prop;


			if (of_property_read_u32(pdev->dev.of_node,
				"cd-gpio", &val)) {
				dev_err(&pdev->dev, "cd-gpio read failed in %s\n",
				__func__);
				hw_cfg->cd_gpio = -1;
			}

			hw_cfg->cd_gpio = val;
		}

		else if (hw_cfg->devtype == SDIO_DEV_TYPE_EMMC) {

			if (of_property_read_u32(pdev->dev.of_node,
				"is-8bit", &val)) {
				dev_err(&pdev->dev, "is-8bit read failed in %s\n",
				__func__);
				goto err_free_priv_data_mem;
			}

			hw_cfg->is_8bit = val;
			if (!(of_property_read_string(pdev->dev.of_node,
					"vddsdmmc-regulator-name", &prop)))
				emmc_regulator = (char *)prop;
		}

		pdev->dev.platform_data = hw_cfg;
	}
	if (!hw_cfg) {
			dev_err(&pdev->dev, "hw_cfg is NULL\n");
			ret = -ENOMEM;
			goto err;
	}

	if (hw_cfg->devtype >= SDIO_DEV_TYPE_MAX) {
		dev_err(&pdev->dev, "unknown device type\n");
		ret = -EFAULT;
		goto err;
	}
	pr_debug("%s: GET PLATFORM RESOURCES\n", __func__);

	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!iomem) {
		ret = -ENOMEM;
		goto err;
	}

	/* Some PCI-based MFD need the parent here */
	if (pdev->dev.parent != &platform_bus)
		host =
		    sdhci_alloc_host(pdev->dev.parent, sizeof(struct sdio_dev));
	else
		host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdio_dev));
	if (IS_ERR(host)) {
		ret = PTR_ERR(host);
		goto err;
	}

	pr_debug("%s: ALLOC HOST\n", __func__);

	host->hw_name = "bcm_kona_sd";
	host->ops = &sdhci_pltfm_ops;
	host->irq = platform_get_irq(pdev, 0);
	host->quirks = SDHCI_QUIRK_NO_CARD_NO_RESET
	    | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
	    | SDHCI_QUIRK_32BIT_DMA_ADDR
	    | SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE;

#ifdef CONFIG_MACH_RHEA_DALTON2_EB30
        host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
#endif
#ifdef CONFIG_MACH_BCM_FPGA
	host->quirks |= of_quirks;
	host->quirks2 |= of_quirks2;
#endif

        pr_debug("%s: GET IRQ\n", __func__);

	if (hw_cfg->flags & KONA_SDIO_FLAGS_DEVICE_NON_REMOVABLE)
		host->mmc->caps |= MMC_CAP_NONREMOVABLE;

	if (!request_mem_region(iomem->start, resource_size(iomem),
				mmc_hostname(host->mmc))) {
		dev_err(&pdev->dev, "cannot request region\n");
		ret = -EBUSY;
		goto err_free_host;
	}

	host->ioaddr = ioremap(iomem->start, resource_size(iomem));
	if (!host->ioaddr) {
		dev_err(&pdev->dev, "failed to remap registers\n");
		ret = -ENOMEM;
		goto err_free_mem_region;
	}

	pr_debug("%s: MEM and IO REGION OKAY\n", __func__);

	dev = sdhci_priv(host);
	dev->dev = &pdev->dev;
	dev->host = host;
	dev->devtype = hw_cfg->devtype;
	dev->cd_gpio = hw_cfg->cd_gpio;
	host->mmc->parent = dev->dev;
	if (dev->devtype == SDIO_DEV_TYPE_WIFI)
		dev->wifi_gpio = &hw_cfg->wifi_gpio;
	if (dev->devtype == SDIO_DEV_TYPE_EMMC && emmc_regulator) {
		dev->vdd_sdxc_regulator = regulator_get(NULL, emmc_regulator);
		if (IS_ERR(dev->vdd_sdxc_regulator)) {
			dev->vdd_sdxc_regulator = NULL;
		}
	}

	if (dev->devtype == SDIO_DEV_TYPE_EMMC)
		host->detect_delay = 0;
	else
		host->detect_delay = 200;

	pr_debug("%s: DEV TYPE %x\n", __func__, dev->devtype);

	gDevs[dev->devtype] = dev;

	platform_set_drvdata(pdev, dev);

	snprintf(devname, sizeof(devname), "%s%d", DEV_NAME, pdev->id);

	/* enable clocks */
#ifdef CONFIG_MACH_BCM2850_FPGA
	if (clock) {		/* clock override */
		dev->clk_hz = clock;
	} else {
		dev->clk_hz = gClock[dev->devtype];
	}
#elif defined(CONFIG_MACH_BCM_FPGA)
	dev->clk_hz =  hw_cfg->peri_clk_rate;
#else
	/* peripheral clock */
	dev->peri_clk = clk_get(&pdev->dev, hw_cfg->peri_clk_name);
	if (IS_ERR_OR_NULL(dev->peri_clk)) {
		ret = -EINVAL;
		goto err_unset_pltfm;
	}
	ret = clk_set_rate(dev->peri_clk, hw_cfg->peri_clk_rate);
	if (ret)
		goto err_peri_clk_put;

	/* sleep clock */
	dev->sleep_clk = clk_get(&pdev->dev, hw_cfg->sleep_clk_name);
	if (IS_ERR_OR_NULL(dev->sleep_clk)) {
		ret = -EINVAL;
		goto err_peri_clk_put;
	}

	ret = clk_enable(dev->sleep_clk);
	if (ret) {
		dev_err(&pdev->dev, "failed to enable sleep clock for %s\n",
			devname);
		goto err_sleep_clk_put;
	}

	ret = sdhci_pltfm_clk_enable(dev, 1);
	if (ret) {
		dev_err(&pdev->dev, "failed to initialize core clock for %s\n",
			devname);
		goto err_sleep_clk_disable;
	}

	dev->clk_hz = clk_get_rate(dev->peri_clk);
#endif

#if 0
	/***
		NANI
		To check mmc base clock
	***/
	printk( "[NANI] %s, %d : %s[%s], dev->clk_hz(%d)\n", __FUNCTION__, __LINE__, mmc_hostname(host->mmc), dev_name(mmc_dev(host->mmc)), dev->clk_hz );
	if( !strcmp( mmc_hostname(host->mmc), "mmc0" ) ) {
		// KONA_MST_CLK_SDIO2_CLKGATE(0x3F00135C)
		// KONA_MST_CLK_SDIO2_DIV(0x3F001A2C)
		// clock.c - struct bus_clk CLK_NAME(sdio2_ahb)
		// KONA_MST_CLK_BASE_ADDR : 0x3F001000
		// KPM_CLK_MGR_REG_SDIO2_CLKGATE_OFFSET : 0x0000035C
		// KPM_CLK_MGR_REG_SDIO2_DIV_OFFSET : 0x00000A2C
		printk( "[NANI] %s, %d : KONA_MST_CLK_SDIO2_CLKGATE == %#x, KONA_MST_CLK_SDIO2_DIV == %#x\n",
			__FUNCTION__, __LINE__, readl( IO_PHYS_TO_VIRT(0x3F001000) + 0x0000035C ), readl( IO_PHYS_TO_VIRT(0x3F001000) + 0x00000A2C ) );
	} else if( !strcmp( mmc_hostname(host->mmc), "mmc2" ) ) {
		// KONA_MST_CLK_SDIO1_CLKGATE(0x3F001358)
		// KONA_MST_CLK_SDIO1_DIV(0x3F001A28)
		// clock.c - struct bus_clk CLK_NAME(sdio1_ahb)
		// KONA_MST_CLK_BASE_ADDR : 0x3F001000
		// KPM_CLK_MGR_REG_SDIO1_CLKGATE_OFFSET : 0x00000358
		// KPM_CLK_MGR_REG_SDIO1_DIV_OFFSET : 0x00000A28
		printk( "[NANI] %s, %d : KONA_MST_CLK_SDIO1_CLKGATE == %#x, KONA_MST_CLK_SDIO1_DIV == %#x\n",
			__FUNCTION__, __LINE__, readl( IO_PHYS_TO_VIRT(0x3F001000) + 0x00000358 ), readl( IO_PHYS_TO_VIRT(0x3F001000) + 0x00000A28 ) );
	} else {
	}
#endif

	dev->suspended = 0;

	if (hw_cfg->vddo_regulator_name) {
		ret =
		    sdhci_pltfm_regulator_init(dev,
					       hw_cfg->vddo_regulator_name);
#ifndef BCM_REGULATOR_SKIP_QUIRK
		if (ret < 0)
			goto err_term_clk;
#endif
	}

	if (hw_cfg->vddsdxc_regulator_name &&
			dev->devtype == SDIO_DEV_TYPE_SDMMC) {
		ret =
		    sdhci_pltfm_regulator_sdxc_init(dev,
					       hw_cfg->vddsdxc_regulator_name);
#ifndef BCM_REGULATOR_SKIP_QUIRK
		if (ret < 0)
			goto err_term_clk;
#endif
	}
	if (sd_detection_cmd_dev == NULL){
	sd_detection_cmd_dev =
		device_create(sec_class, NULL, 0,
				NULL, "sdcard");
	if (IS_ERR(sd_detection_cmd_dev))
		pr_err("Fail to create sysfs dev\n");

	if (device_create_file(sd_detection_cmd_dev,
				&dev_attr_status) < 0)
		pr_err("Fail to create sysfs file\n");
	}

	mutex_init(&dev->regulator_lock);
	kona_sdio_regulator_power(dev, 1);

	ret = bcm_kona_sd_reset(dev);
	if (ret)
		goto err_term_clk;

	ret = bcm_kona_sd_init(dev);
	if (ret)
		goto err_reset;

	if (hw_cfg->is_8bit)
		host->mmc->caps |= MMC_CAP_8_BIT_DATA;

	/* Note that sdhci_add_host calls --> mmc_add_host, which in turn
	 * checks for the flag MMC_PM_IGNORE_PM_NOTIFY before registering a PM
	 * notifier for the specific instance of SDIO host controller. For
	 * WiFi case, we don't want to get notified, becuase then from there
	 * mmc_power_off is called which will reset the Host registers that
	 * needs to be re-programmed by starting SDIO handsake again. We want
	 * to prevent this in case of WiFi. So enable MMC_PM_IGNORE_PM_NOTIFY
	 * flag, so that notifier never gets registered.
	 */
	if (dev->devtype == SDIO_DEV_TYPE_WIFI) {
		/* The Wireless LAN drivers call the API sdio_get_host_pm_caps
		 * to know the PM capabilities of the driver, which would
		 * return pm_caps. While the internal code decides based on
		 * pm_flags, the pm_caps also should reflect the same.
		 */
		host->mmc->pm_caps =
		    MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY;
		host->mmc->pm_flags =
		    MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY;
	}

#if !defined(CONFIG_MACH_BCM_FPGA_E)
	/* Enable 1.8V DDR operation for e.MMC */
	if (dev->devtype == SDIO_DEV_TYPE_EMMC)
		host->mmc->caps |= MMC_CAP_1_8V_DDR;
#endif

	/* Don't issue SLEEP command to e.MMC device */
	if (dev->devtype == SDIO_DEV_TYPE_EMMC)
		/*host->mmc->caps2 |= MMC_CAP2_NO_SLEEP_CMD;*/
		host->mmc->pm_flags = MMC_PM_KEEP_POWER;

	/*
	 * This has to be done before sdhci_add_host.
	 * As soon as we add the host, request
	 * starts. If we dont enable this here, the
	 * runtime get and put of sdhci will fallback to
	 * clk_enable and clk_disable which will conflict
	 * with the PM runtime when it gets enabled just
	 * after sdhci_add_host. Now with this, the RPM
	 * calls will fail until RPM is enabled, but things
	 * will work well, as we have clocks enabled till the
	 * probe ends.
	 */

	dev->runtime_pm_enabled = 1;

	ret = sdhci_add_host(host);
	if (ret)
		goto err_reset;

	ret = proc_init(pdev);
	if (ret)
		goto err_rm_host;

	/* Should be done only after sdhci_add_host */
	sdhci_pltfm_runtime_pm_init(dev->dev);

	if (dev->devtype == SDIO_DEV_TYPE_SDMMC) {
		/* support SD card detect interrupts for insert/removal */
		host->mmc->card_detect_cap = true;
	}

	/* if device is eMMC, emulate card insert right here */
	if (dev->devtype == SDIO_DEV_TYPE_EMMC) {
		ret = bcm_kona_sd_card_emulate(dev, 1);
		if (ret) {
			dev_err(&pdev->dev,
				"unable to emulate card insertion\n");
			goto err_proc_term;
		}
		pr_info("%s: card insert emulated!\n", devname);
	} else if (dev->devtype == SDIO_DEV_TYPE_SDMMC && dev->cd_gpio >= 0) {

		dev->cd_int_wake_lock_name = kasprintf(GFP_KERNEL,
				"%s_cd_int", devname);

		if (!dev->cd_int_wake_lock_name) {
			dev_err(&pdev->dev,
				"error allocating mem for wake_lock_name\n");
			goto err_proc_term;
		}

		wake_lock_init(&dev->cd_int_wake_lock, WAKE_LOCK_SUSPEND,
				dev->cd_int_wake_lock_name);


		ret = gpio_request(dev->cd_gpio, "sdio cd");

		if (ret < 0) {
			dev_err(&pdev->dev, "Unable to request GPIO pin %d\n",
				dev->cd_gpio);
			goto err_proc_term;
		}
		gpio_direction_input(dev->cd_gpio);

		ret = request_threaded_irq(gpio_to_irq(dev->cd_gpio),
					   NULL,
					   sdhci_pltfm_cd_interrupt,
					   IRQF_TRIGGER_FALLING |
					   IRQF_TRIGGER_RISING |
					   IRQF_NO_SUSPEND, "sdio cd", dev);
		if (ret) {
			dev_err(&pdev->dev,
				"Unable to request card detection irq=%d"
				" for gpio=%d\n",
				gpio_to_irq(dev->cd_gpio), dev->cd_gpio);
			goto err_free_cd_gpio;
		}

		/* Set debounce for SD Card detect to maximum value (128ms)
		 *
		 * NOTE-1: If gpio_set_debounce() returns error we still
		 * continue with the default debounce value set. Another reason
		 * for doing this is that on rhea-ray boards the SD Detect GPIO
		 * is on GPIO Expander and gpio_set_debounce() will return error
		 * and if we return error from here, then probe() would fail and
		 * SD detection would always fail.
		 *
		 * NOTE-2: We also give a msleep() of the "debounce" time here
		 * so that we give enough time for the debounce to stabilize
		 * before we read the gpio value in gpio_get_value_cansleep().
		 */
		ret =
		    gpio_set_debounce(dev->cd_gpio,
				      (SD_DETECT_GPIO_DEBOUNCE_128MS * 1000));
		if (ret < 0) {
			dev_err(&pdev->dev, "%s: gpio set debounce failed."
				"default debounce value assumed\n", __func__);
		}

		/* Sleep for 128ms to allow debounce to stabilize */
		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);

		/*
		 * Since the card detection GPIO interrupt is configured to be
		 * edge sensitive, check the initial GPIO value here, emulate
		 * only if the card is present
		 */
		if (gpio_get_value_cansleep(dev->cd_gpio) == 0)		{
			printk("%s - external SD Card is detected by GPIO\n",__func__);
			bcm_kona_sd_card_emulate(dev, 1);
		} else {
			printk("%s - SD Card is Not detected by GPIO-->Disable SDXLDO\n",__func__);
			/* If card is not present disable the regulator */
			kona_sdio_regulator_power(dev, 0);
		}

	}

	/* Force insertion interrupt, in case of no card detect registered.
	 */
	if (dev->cd_gpio < 0)
		bcm_kona_sd_card_emulate(dev, 1);
#ifdef CONFIG_BRCM_UNIFIED_DHD_SUPPORT
	if ((dev->devtype == SDIO_DEV_TYPE_WIFI) &&
	    (hw_cfg->register_status_notify != NULL)) {
		hw_cfg->register_status_notify(kona_sdio_status_notify_cb,
					       host);
	}
	pr_debug("%s: CALL BACK IS REGISTERED\n", __func__);

#endif

	atomic_set(&dev->initialized, 1);
	sdhci_pltfm_clk_enable(dev, 0);

	pr_info("%s: initialized properly\n", devname);

	return 0;

err_free_cd_gpio:
	if (dev->devtype == SDIO_DEV_TYPE_SDMMC && dev->cd_gpio >= 0)
		gpio_free(dev->cd_gpio);

err_proc_term:
	proc_term(pdev);

err_rm_host:
	sdhci_remove_host(host, 0);

err_reset:
	bcm_kona_sd_reset(dev);

err_term_clk:
	sdhci_pltfm_clk_enable(dev, 0);

#if !defined(CONFIG_MACH_BCM2850_FPGA) && !defined(CONFIG_MACH_BCM_FPGA)
err_sleep_clk_disable:
	clk_disable(dev->sleep_clk);

err_sleep_clk_put:
	clk_put(dev->sleep_clk);

err_peri_clk_put:
	clk_put(dev->peri_clk);

err_unset_pltfm:
	platform_set_drvdata(pdev, NULL);
	iounmap(host->ioaddr);
#endif

err_free_mem_region:
	release_mem_region(iomem->start, resource_size(iomem));

err_free_host:
	sdhci_free_host(host);

err_free_priv_data_mem:
	if (pdev->dev.of_node) {
		ret = -EFAULT;
		kfree(hw_cfg);
	}
err:
	pr_err("Probing of sdhci-pltfm %d failed: %d\n", pdev->id,
	       ret);
	return ret;
}
Exemplo n.º 2
0
static int __devinit sdhci_pltfm_probe(struct platform_device *pdev)
{
	struct sdhci_host *host;
	struct sdio_dev *dev;
	struct resource *iomem;
	struct sdio_platform_cfg *hw_cfg;
	char devname[MAX_DEV_NAME_SIZE];
	int ret;

	pr_debug("%s: ENTRY\n", __func__);

	BUG_ON(pdev == NULL);

	if (pdev->dev.platform_data == NULL) {
		dev_err(&pdev->dev, "platform_data missing\n");
		ret = -EFAULT;
		goto err;
	}

	pr_debug("%s: GET PLATFORM DATA\n", __func__);

	hw_cfg = (struct sdio_platform_cfg *)pdev->dev.platform_data;
	if (hw_cfg->devtype >= SDIO_DEV_TYPE_MAX) {
		dev_err(&pdev->dev, "unknown device type\n");
		ret = -EFAULT;
		goto err;
	}

	pr_debug("%s: GET PLATFORM RESOURCES\n", __func__);

	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!iomem) {
		ret = -ENOMEM;
		goto err;
	}

	/* Some PCI-based MFD need the parent here */
	if (pdev->dev.parent != &platform_bus)
		host =
		    sdhci_alloc_host(pdev->dev.parent, sizeof(struct sdio_dev));
	else
		host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdio_dev));
	if (IS_ERR(host)) {
		ret = PTR_ERR(host);
		goto err;
	}

	pr_debug("%s: ALLOC HOST\n", __func__);

	host->hw_name = "bcm_kona_sd";
	host->ops = &sdhci_pltfm_ops;
	host->irq = platform_get_irq(pdev, 0);
	host->quirks = SDHCI_QUIRK_NO_CARD_NO_RESET
	    | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
	    | SDHCI_QUIRK_32BIT_DMA_ADDR
	    | SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE;

	pr_debug("%s: GET IRQ\n", __func__);

	if (hw_cfg->flags & KONA_SDIO_FLAGS_DEVICE_NON_REMOVABLE)
		host->mmc->caps |= MMC_CAP_NONREMOVABLE;

	if (!request_mem_region(iomem->start, resource_size(iomem),
				mmc_hostname(host->mmc))) {
		dev_err(&pdev->dev, "cannot request region\n");
		ret = -EBUSY;
		goto err_free_host;
	}

	host->ioaddr = ioremap(iomem->start, resource_size(iomem));
	if (!host->ioaddr) {
		dev_err(&pdev->dev, "failed to remap registers\n");
		ret = -ENOMEM;
		goto err_free_mem_region;
	}

	pr_debug("%s: MEM and IO REGION OKAY\n", __func__);

	dev = sdhci_priv(host);
	dev->dev = &pdev->dev;
	dev->host = host;
	dev->devtype = hw_cfg->devtype;

	dev->cd_gpio = hw_cfg->cd_gpio;
	dev->wp_gpio = hw_cfg->wp_gpio;
	if (dev->devtype == SDIO_DEV_TYPE_WIFI)
		dev->wifi_gpio = &hw_cfg->wifi_gpio;

	/*
	 * In the corresponding mmc_host->caps filed, need to
	 * expose the MMC_CAP_DISABLE capability only for SD Card interface.
	 * Note that for now we are exposing Dynamic Power Management
	 * capability on the interface that suppors SD Card.
	 *
	 * When we finally decide to do away with managing clocks from sdhci.c
	 * and when we enable the DISABLED state management, we need to
	 * enable this capability for ALL SDIO interfaces. For WLAN interface
	 * we should ensure that the regulator is NOT turned OFF so that the
	 * handshakes need not happen again.
	 */
	if (dev->devtype == SDIO_DEV_TYPE_SDMMC) {
		host->mmc->caps |= MMC_CAP_DISABLE;
		/*
		 * There are multiple paths that can trigger disable work.
		 * One common path is from
		 * mmc/card/block.c function,  mmc_blk_issue_rq after the
		 * transfer is done.
		 * mmc_release_host-->mmc_host_lazy_disable, this starts the
		 * mmc disable work only if host->disable_delay is non zero.
		 * So we need to set disable_delay otherwise the work will never
		 * get scheduled.
		 */
		mmc_set_disable_delay(host->mmc, KONA_SDMMC_DISABLE_DELAY);
	}

	pr_debug("%s: DEV TYPE %x\n", __func__, dev->devtype);

	gDevs[pdev->id] = dev;

	platform_set_drvdata(pdev, dev);

	snprintf(devname, sizeof(devname), "%s%d", DEV_NAME, pdev->id);

	/* enable clocks */
#if defined(CONFIG_MACH_BCM2850_FPGA) || defined(CONFIG_MACH_CAPRI_FPGA)
	if (clock) {		/* clock override */
		dev->clk_hz = clock;
	} else {
		dev->clk_hz = gClock[dev->devtype];
	}
#else
	/* peripheral clock */
	dev->peri_clk = clk_get(&pdev->dev, "peri_clk");
	if (IS_ERR_OR_NULL(dev->peri_clk)) {
		ret = -EINVAL;
		goto err_unset_pltfm;
	}
	ret = clk_set_rate(dev->peri_clk, hw_cfg->peri_clk_rate);
	if (ret)
		goto err_peri_clk_put;

	/* sleep clock */
	dev->sleep_clk = clk_get(&pdev->dev, "sleep_clk");
	if (IS_ERR_OR_NULL(dev->sleep_clk)) {
		ret = -EINVAL;
		goto err_peri_clk_put;
	}

	ret = clk_enable(dev->sleep_clk);
	if (ret) {
		dev_err(&pdev->dev, "failed to enable sleep clock for %s\n",
			devname);
		goto err_sleep_clk_put;
	}

	ret = sdhci_pltfm_clk_enable(host, 1);
	if (ret) {
		dev_err(&pdev->dev, "failed to initialize core clock for %s\n",
			devname);
		goto err_sleep_clk_disable;
	}
	dev->clk_hz = clk_get_rate(dev->peri_clk);
#endif

	dev->suspended = 0;
	ret = sdhci_pltfm_regulator_init(pdev, hw_cfg);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to initialize regulator for %s\n",
				devname);
			goto err_term_clk;
	}

	/*
	 * Regulators are NOT turned ON in the above functions.
	 * So leave them in OFF state and they'll be handled
	 * appropriately in enable path.
	 */
	dev->dpm_state = OFF;

	if (sd_detection_cmd_dev == NULL){
		sd_detection_cmd_dev = device_create(sec_class, NULL, 0, NULL, "sdcard");
		if (IS_ERR(sd_detection_cmd_dev))
			pr_err("Fail to create sysfs dev\n");

		if (device_create_file(sd_detection_cmd_dev, &dev_attr_status) < 0)
			pr_err("Fail to create sysfs file\n");
	}


	ret = bcm_kona_sd_reset(dev);
	if (ret)
		goto err_term_regulator;

	ret = bcm_kona_sd_init(dev);
	if (ret)
		goto err_reset;

	if (hw_cfg->is_8bit)
		host->mmc->caps |= MMC_CAP_8_BIT_DATA;

	/* Note that sdhci_add_host calls --> mmc_add_host, which in turn
	 * checks for the flag MMC_PM_IGNORE_PM_NOTIFY before registering a PM
	 * notifier for the specific instance of SDIO host controller. For
	 * WiFi case, we don't want to get notified, becuase then from there
	 * mmc_power_off is called which will reset the Host registers that
	 * needs to be re-programmed by starting SDIO handsake again. We want
	 * to prevent this in case of WiFi. So enable MMC_PM_IGNORE_PM_NOTIFY
	 * flag, so that notifier never gets registered.
	 */
	if (dev->devtype == SDIO_DEV_TYPE_WIFI) {
		/* The Wireless LAN drivers call the API sdio_get_host_pm_caps
		 * to know the PM capabilities of the driver, which would
		 * return pm_caps. While the internal code decides based on
		 * pm_flags, the pm_caps also should reflect the same.
		 */
		host->mmc->pm_caps =
		    MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY;
		host->mmc->pm_flags =
		    MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY;
	}

	/* Enable 1.8V DDR operation for e.MMC */
	if (dev->devtype == SDIO_DEV_TYPE_EMMC)
		host->mmc->caps |= MMC_CAP_1_8V_DDR;

	/*
	 * Temporary UHS support only for eMMC as it does not need volatge level
	 * adjustment. The SD card will not be able to support UHS until the PMU
	 * regulator framework is integrated
	 */
	if (hw_cfg->tmp_uhs)
		host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_UHS_DDR50;

	ret = sdhci_add_host(host);
	if (ret)
		goto err_reset;

	ret = proc_init(pdev);
	if (ret)
		goto err_rm_host;

	/* if device is eMMC, emulate card insert right here */
	if (dev->devtype == SDIO_DEV_TYPE_EMMC) {
		ret = bcm_kona_sd_card_emulate(dev, 1);
		if (ret) {
			dev_err(&pdev->dev,
				"unable to emulate card insertion\n");
			goto err_proc_term;
		}
		pr_info("%s: card insert emulated!\n", devname);
	} else if (dev->devtype == SDIO_DEV_TYPE_SDMMC && dev->cd_gpio >= 0) {
		ret = gpio_request(dev->cd_gpio, "sdio cd");

		if (ret < 0) {
			dev_err(&pdev->dev, "Unable to request GPIO pin %d\n",
				dev->cd_gpio);
			goto err_proc_term;
		}
		gpio_direction_input(dev->cd_gpio);

		/* support SD card detect interrupts for insert/removal */
		host->mmc->card_detect_cap = true;

		/* Set debounce for SD Card detect to maximum value (128ms)
		 *
		 * NOTE-1: If gpio_set_debounce() returns error we still
		 * continue with the default debounce value set. Another reason
		 * for doing this is that on rhea-ray boards the SD Detect GPIO
		 * is on GPIO Expander and gpio_set_debounce() will return error
		 * and if we return error from here, then probe() would fail and
		 * SD detection would always fail.
		 *
		 * NOTE-2: We also give a msleep() of the "debounce" time here
		 * so that we give enough time for the debounce to stabilize
		 * before we read the gpio value in gpio_get_value_cansleep().
		 */
		ret =
		    gpio_set_debounce(dev->cd_gpio,
				      (SD_DETECT_GPIO_DEBOUNCE_128MS * 1000));
		if (ret < 0) {
			dev_err(&pdev->dev, "%s: gpio set debounce failed."
				"default debounce value assumed\n", __func__);
		}

		/* Sleep for 128ms to allow debounce to stabilize */
		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);

		/* request irq for cd_gpio after the gpio debounce is
		 * stabilized, otherwise, some bogus gpio interrupts might be
		 * triggered.
		 */
		ret = request_threaded_irq(gpio_to_irq(dev->cd_gpio),
					   NULL,
					   sdhci_pltfm_cd_interrupt,
					   IRQF_TRIGGER_FALLING |
					   IRQF_TRIGGER_RISING |
					   IRQF_NO_SUSPEND, "sdio cd", dev);
		if (ret) {
			dev_err(&pdev->dev,
				"Unable to request card detection irq=%d"
				" for gpio=%d\n",
				gpio_to_irq(dev->cd_gpio), dev->cd_gpio);
			goto err_free_cd_gpio;
		}

		if (dev->wp_gpio >= 0) {
			ret = gpio_request(dev->wp_gpio, "sdio wp");
			if (ret < 0) {
				dev_err(&pdev->dev, "Unable to request WP pin %d\n", dev->wp_gpio);
				dev->wp_gpio = -1;
			} else {
				gpio_direction_input(dev->wp_gpio);
			}
		}

		/*
		 * Since the card detection GPIO interrupt is configured to be
		 * edge sensitive, check the initial GPIO value here, emulate
		 * only if the card is present
		 */
		if (gpio_get_value_cansleep(dev->cd_gpio) == 0)
			bcm_kona_sd_card_emulate(dev, 1);
	}
#ifdef CONFIG_BRCM_UNIFIED_DHD_SUPPORT
	if ((dev->devtype == SDIO_DEV_TYPE_WIFI) &&
	    (hw_cfg->register_status_notify != NULL)) {
		hw_cfg->register_status_notify(kona_sdio_status_notify_cb,
					       host);
	}
	pr_debug("%s: CALL BACK IS REGISTERED\n", __func__);

#endif

	if (dev->vdd_sdxc_regulator)
		if (regulator_is_enabled(dev->vdd_sdxc_regulator) > 0)
			regulator_disable(dev->vdd_sdxc_regulator);

	if (dev->vddo_sd_regulator)
		if (regulator_is_enabled(dev->vddo_sd_regulator) > 0)
			regulator_disable(dev->vddo_sd_regulator);

	atomic_set(&dev->initialized, 1);
	sdhci_pltfm_clk_enable(host, 0);

#ifdef CONFIG_ARCH_CAPRI
	/*
	 * If the device is WiFi, disable pullup and enable pulldown on SDIO
	 * pins by default, to save power. Pullup only needs to be enabled
	 * when WiFi is in use
	 */
	if (dev->devtype == SDIO_DEV_TYPE_WIFI)
		capri_pm_sdio_pinmux_ctrl(pdev->id, 1);
#endif

	pr_info("%s: initialized properly\n", devname);

	return 0;

err_free_cd_gpio:
	if (dev->devtype == SDIO_DEV_TYPE_SDMMC && dev->cd_gpio >= 0)
		gpio_free(dev->cd_gpio);

err_proc_term:
	proc_term(pdev);

err_rm_host:
	sdhci_remove_host(host, 0);

err_reset:
	bcm_kona_sd_reset(dev);

err_term_regulator:
	sdhci_pltfm_regulator_term(pdev);

err_term_clk:
	sdhci_pltfm_clk_enable(host, 0);

#ifndef CONFIG_MACH_BCM2850_FPGA
err_sleep_clk_disable:
	clk_disable(dev->sleep_clk);

err_sleep_clk_put:
	clk_put(dev->sleep_clk);

err_peri_clk_put:
	clk_put(dev->peri_clk);
#endif

err_unset_pltfm:
	platform_set_drvdata(pdev, NULL);
	iounmap(host->ioaddr);

err_free_mem_region:
	release_mem_region(iomem->start, resource_size(iomem));

err_free_host:
	sdhci_free_host(host);

err:
	pr_err("Probing of sdhci-pltfm %d failed: %d\n", pdev->id,
	       ret);
	return ret;
}