Пример #1
0
static void sprd_sdio_card_remove(struct mmc_card *card) {
    struct mmc_host *host = card->host;
    if (mmc_card_sdio(card)) {
        if(host->caps & MMC_CAP_POWER_OFF_CARD) {
            pm_suspend_ignore_children(mmc_classdev(host), true);  
            pm_runtime_idle(mmc_classdev(host)); 
        }
    }
}
Пример #2
0
static void sprd_sdio_card_remove(struct mmc_card *card) {
    struct mmc_host *host = card->host;
    if (mmc_card_sdio(card)) {
        if(host->caps & MMC_CAP_POWER_OFF_CARD) {
            pm_suspend_ignore_children(mmc_classdev(host), true);  // avoid mmc_attach_sdio->pm_runtime_set_active returning with error -16
            pm_runtime_idle(mmc_classdev(host)); // make platform devices runtime suspendable
        }
    }
}
Пример #3
0
static int sprd_sdio_card_probe(struct mmc_card *card) {
    struct mmc_host *host = card->host;
    if (mmc_card_sdio(card)) {
        if(host->caps & MMC_CAP_POWER_OFF_CARD) {
            pm_runtime_no_callbacks(&card->dev); 
            pm_suspend_ignore_children(mmc_classdev(host), false); 
            return 0;
        }
    }
    return -EINVAL;
}
Пример #4
0
static int sprd_sdio_card_probe(struct mmc_card *card) {
    struct mmc_host *host = card->host;
    if (mmc_card_sdio(card)) {
        if(host->caps & MMC_CAP_POWER_OFF_CARD) {
            pm_runtime_no_callbacks(&card->dev); // avoid default sdio bus runtime calling
            pm_suspend_ignore_children(mmc_classdev(host), false); // paired with remove function
        }
        return 0;
    }
    return -EINVAL;
}
Пример #5
0
/*
 * Allocate and initialise a new MMC card structure.
 */
struct mmc_card *mmc_alloc_card(struct mmc_host *host)
{
	struct mmc_card *card;

	card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
	if (!card)
		return ERR_PTR(-ENOMEM);

	card->host = host;

	device_initialize(&card->dev);

	card->dev.parent = mmc_classdev(host);
	card->dev.bus = &mmc_bus_type;
	card->dev.release = mmc_release_card;

	return card;
}
Пример #6
0
/*
 * Allocate and initialise a new MMC card structure.
 */
struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
{
	struct mmc_card *card;

	card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
	if (!card)
		return ERR_PTR(-ENOMEM);

	card->host = host;

	device_initialize(&card->dev);

	card->dev.parent = mmc_classdev(host);
	card->dev.bus = &mmc_bus_type;
	card->dev.release = mmc_release_card;
	card->dev.type = type;

	spin_lock_init(&card->wr_pack_stats.lock);

	return card;
}
Пример #7
0
/*
 * Allocate and initialise a new MMC card structure.
 */
struct mmc_card *mmc_alloc_card(struct mmc_host *host, struct device_type *type)
{
	struct mmc_card *card;
	DBG("[%s] s\n",__func__);
	
	card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
	if (!card) {
		DBG("[%s] e1\n",__func__);
		return ERR_PTR(-ENOMEM);
	}

	card->host = host;

	device_initialize(&card->dev);

	card->dev.parent = mmc_classdev(host);
	card->dev.bus = &mmc_bus_type;
	card->dev.release = mmc_release_card;
	card->dev.type = type;

	DBG("[%s] e2\n",__func__);
	return card;
}
Пример #8
0
static int __devinit sdhci_sprd_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct sdhci_host *host;
	struct resource *res;
	int ret, irq;
#ifdef CONFIG_MMC_CARD_HOTPLUG
	int sd_detect_gpio;
	int detect_irq;
#endif
	struct sprd_host_data *host_data;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(dev, "no irq specified\n");
		return irq;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "no memory specified\n");
		return -ENOENT;
	}

	if(pdev->id == 0)
	{
		sd_buffer_pre_alloc();
	}

	host = sdhci_alloc_host(dev, sizeof(struct sprd_host_data));
	if (IS_ERR(host)) {
		dev_err(dev, "sdhci_alloc_host() failed\n");
		return PTR_ERR(host);
	}

	host_data = sdhci_priv(host);
	host_data->platdata = dev_get_platdata(dev);
	host_data->clk_enable = 0;
	BUG_ON(NULL == host_data->platdata);
	printk("sdio probe %s, vdd %s (%d), clk %s parent %s\n",
		host_data->platdata->hw_name,
		host_data->platdata->vdd_name,	host_data->platdata->volt_level,
		host_data->platdata->clk_name, host_data->platdata->clk_parent);

	platform_set_drvdata(pdev, host);
	host->vmmc = NULL;
	host->vmmc_ext = NULL;
	host->ioaddr = (void __iomem *)res->start;
	printk("sdio: host->ioaddr:0x%x\n", (u32)host->ioaddr);
	host->hw_name = (host_data->platdata->hw_name)?
		host_data->platdata->hw_name:pdev->name;
	host->ops = &sdhci_sprd_ops;
	host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |\
		SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |\
		SDHCI_QUIRK_BROKEN_CARD_DETECTION|\
		SDHCI_QUIRK_INVERTED_WRITE_PROTECT;
	host->irq = irq;
#ifdef CONFIG_MMC_CARD_HOTPLUG
	sd_detect_gpio = host_data->platdata->detect_gpio;
	if(sd_detect_gpio > 0){
		pr_info("%s, sd_detect_gpio:%d\n", __func__, sd_detect_gpio);

		if (0 == pdev->id){
			ret = gpio_request(sd_detect_gpio, "sdio0_detect");
		}else{
			ret = gpio_request(sd_detect_gpio, "sdio1_detect");
		}

		if (ret) {
			dev_err(dev, "cannot request gpio\n");
			return -1;
		}

		ret = gpio_direction_input(sd_detect_gpio);
		if (ret) {
			dev_err(dev, "gpio can not change to input\n");
			return -1;
		}

		detect_irq = gpio_to_irq(sd_detect_gpio);
		if (detect_irq < 0){
			dev_err(dev, "cannot alloc detect irq\n");
			return -1;
		}
		host_data->detect_irq = detect_irq;
	}else if (host_data->platdata->register_status_notify) {
		host_data->platdata->register_status_notify(sdhci_status_notify_cb, host);
	} else if (!host_data->platdata->status) {
		printk("%s: No card detect facilities available\n",
				mmc_hostname(host->mmc));
	}else{
		printk("%s, sd_detect_gpio == 0 \n", __func__ );
	}
#endif

	if(host_data->platdata->vdd_name) {
		host->vmmc = regulator_get(NULL, host_data->platdata->vdd_name);
		BUG_ON(IS_ERR(host->vmmc));
		
		if(!is_sd_slot(host))
			regulator_enable(host->vmmc);
	}
	if(host_data->platdata->vdd_ext_name) {
		host->vmmc_ext = regulator_get(NULL, host_data->platdata->vdd_ext_name);
		BUG_ON(IS_ERR(host->vmmc_ext));
		regulator_enable(host->vmmc_ext);
	}

	host->clk = NULL;
	sdhci_module_init(host);

	switch(pdev->id) {
		case 0:
			host->mmc->pm_flags |= MMC_PM_ONLY_USED_SDIO0_SHARK;
			host->caps = sdhci_readl(host, SDHCI_CAPABILITIES) & (~(SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_180));
			host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
			host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY;
			break;
		case 1:
		        host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY|MMC_PM_KEEP_POWER |MMC_PM_DISABLE_TIMEOUT_IRQ;
                host->mmc->pm_caps |= MMC_PM_KEEP_POWER |MMC_PM_DISABLE_TIMEOUT_IRQ;
				#ifdef CONFIG_SDIO_CARD
                host->mmc->caps |= MMC_CAP_4_BIT_DATA |MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD;
				#else
				host->mmc->caps |= MMC_CAP_4_BIT_DATA |MMC_CAP_NONREMOVABLE;
				#endif
			break;
		case 2:
			host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY | MMC_PM_KEEP_POWER;
			host->mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD;
			break;
		case 3:
			host->caps = sdhci_readl(host, SDHCI_CAPABILITIES) & (~(SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_300));
			host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
			host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY | MMC_PM_KEEP_POWER;
			host->mmc->caps |= MMC_CAP_NONREMOVABLE | MMC_CAP_8_BIT_DATA | MMC_CAP_HW_RESET;
			break;
		default:
			BUG();
			break;
	}

#ifdef CONFIG_PM_RUNTIME
		switch(pdev->id) {
			case 1:
			case 2:
                        #ifdef CONFIG_SDIO_CARD
			pm_runtime_set_active(&pdev->dev);
			pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
			pm_runtime_use_autosuspend(&pdev->dev);
			pm_runtime_enable(&pdev->dev);
			pm_runtime_no_callbacks(mmc_classdev(host->mmc));
			pm_suspend_ignore_children(mmc_classdev(host->mmc), true);
			pm_runtime_set_active(mmc_classdev(host->mmc));
			pm_runtime_enable(mmc_classdev(host->mmc));
                        #endif
			break;
			case 3:
			case 0:
			pm_suspend_ignore_children(&pdev->dev, true);
			pm_runtime_set_active(&pdev->dev);
			pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
			pm_runtime_use_autosuspend(&pdev->dev);
			pm_runtime_enable(&pdev->dev);
			default:
			break;
			}
#endif

	ret = sdhci_add_host(host);
	if (ret) {
		dev_err(dev, "sdhci_add_host() failed\n");
		goto err_add_host;
	}

#ifdef CONFIG_MMC_BUS_SCAN
	if (pdev->id == 1)
		sdhci_host_g = host;
#endif

	return 0;

err_add_host:
#ifdef CONFIG_PM_RUNTIME
	pm_runtime_disable(&(pdev)->dev);
	pm_runtime_set_suspended(&(pdev)->dev);
#endif
	if (host_data->clk_enable) {
		clk_disable(host->clk);
		host_data->clk_enable = 0;
	}
	sdhci_free_host(host);
	return ret;
}