static int __devinit sdhci_of_probe(struct of_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->node; struct sdhci_of_data *sdhci_of_data = match->data; struct sdhci_host *host; struct sdhci_of_host *of_host; const u32 *clk; int size; int ret; if (!of_device_is_available(np)) return -ENODEV; host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host)); if (!host) return -ENOMEM; of_host = sdhci_priv(host); dev_set_drvdata(&ofdev->dev, host); host->ioaddr = of_iomap(np, 0); if (!host->ioaddr) { ret = -ENOMEM; goto err_addr_map; } host->irq = irq_of_parse_and_map(np, 0); if (!host->irq) { ret = -EINVAL; goto err_no_irq; } host->hw_name = dev_name(&ofdev->dev); if (sdhci_of_data) { host->quirks = sdhci_of_data->quirks; host->ops = &sdhci_of_data->ops; } clk = of_get_property(np, "clock-frequency", &size); if (clk && size == sizeof(*clk) && *clk) of_host->clock = *clk; ret = sdhci_add_host(host); if (ret) goto err_add_host; return 0; err_add_host: irq_dispose_mapping(host->irq); err_no_irq: iounmap(host->ioaddr); err_addr_map: sdhci_free_host(host); return ret; }
struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, const struct sdhci_pltfm_data *pdata, size_t priv_size) { struct sdhci_host *host; struct resource *iomem; void __iomem *ioaddr; int irq, ret; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); ioaddr = devm_ioremap_resource(&pdev->dev, iomem); if (IS_ERR(ioaddr)) { ret = PTR_ERR(ioaddr); goto err; } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "failed to get IRQ number\n"); ret = irq; goto err; } host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pltfm_host) + priv_size); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } host->ioaddr = ioaddr; host->irq = irq; host->hw_name = dev_name(&pdev->dev); if (pdata && pdata->ops) host->ops = pdata->ops; else host->ops = &sdhci_pltfm_ops; if (pdata) { host->quirks = pdata->quirks; host->quirks2 = pdata->quirks2; } /* * Some platforms need to probe the controller to be able to * determine which caps should be used. */ if (host->ops && host->ops->platform_init) host->ops->platform_init(host); platform_set_drvdata(pdev, host); return host; err: dev_err(&pdev->dev, "%s failed %d\n", __func__, ret); return ERR_PTR(ret); }
static int __devinit sdhci_brcm_probe(struct platform_device *pdev) { struct sdhci_host *host; struct resource *mres, *ires; int mres_size; int err; mres = platform_get_resource(pdev, IORESOURCE_MEM, 0); ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!mres || !ires) { dev_err(&pdev->dev, "can't get resources\n"); return -EIO; } mres_size = mres->end - mres->start + 1; if (!request_mem_region(mres->start, mres_size, DRV_NAME)) { dev_err(&pdev->dev, "can't request memory\n"); return -EBUSY; } host = sdhci_alloc_host(&pdev->dev, 0); if (!host) { dev_err(&pdev->dev, "out of memory\n"); return -ENOMEM; } dev_set_drvdata(&pdev->dev, host); host->hw_name = DRV_NAME; host->ops = &sdhci_brcm_ops; host->flags = 0; #if defined(CONFIG_BCM7635) host->quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; #else host->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; #endif host->irq = ires->start; host->ioaddr = ioremap(mres->start, mres_size); HIF_ACK_IRQ(SDIO); HIF_ENABLE_IRQ(SDIO); err = sdhci_add_host(host); if (err < 0) { dev_err(&pdev->dev, "can't register controller (error %d)\n", err); sdhci_free_host(host); return err; } return 0; }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } 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; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; platform_set_drvdata(pdev, host); sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char *name = pdata->clocks[ptr]; if (name == NULL) continue; clk = clk_get(dev, name); if (IS_ERR(clk)) { dev_err(dev, "failed to get clock %s\n", name); continue; } clks++; sc->clk_bus[ptr] = clk; clk_enable(clk); dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE; #ifndef CONFIG_MMC_SDHCI_S3C_DMA host->quirks |= SDHCI_QUIRK_BROKEN_DMA; host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; #endif host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, struct sdhci_pltfm_data *pdata) { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct device_node *np = pdev->dev.of_node; struct resource *iomem; int ret; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { ret = -ENOMEM; goto err; } if (resource_size(iomem) < 0x100) dev_err(&pdev->dev, "Invalid iomem size!\n"); /* Some PCI-based MFD need the parent here */ if (pdev->dev.parent != &platform_bus && !np) host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host)); else host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host)); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } pltfm_host = sdhci_priv(host); host->hw_name = dev_name(&pdev->dev); if (pdata && pdata->ops) host->ops = pdata->ops; else host->ops = &sdhci_pltfm_ops; if (pdata) { host->quirks = pdata->quirks; host->quirks2 = pdata->quirks2; } host->irq = platform_get_irq(pdev, 0); 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_request; } host->ioaddr = ioremap(iomem->start, resource_size(iomem)); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); ret = -ENOMEM; goto err_remap; } platform_set_drvdata(pdev, host); return host; err_remap: release_mem_region(iomem->start, resource_size(iomem)); err_request: sdhci_free_host(host); err: dev_err(&pdev->dev, "%s failed %d\n", __func__, ret); return ERR_PTR(ret); }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } 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; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; sc->ext_cd_gpio = -1; platform_set_drvdata(pdev, host); sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char *name = pdata->clocks[ptr]; if (name == NULL) continue; clk = clk_get(dev, name); if (IS_ERR(clk)) { dev_err(dev, "failed to get clock %s\n", name); continue; } clks++; sc->clk_bus[ptr] = clk; clk_enable(clk); sc->cur_clk = ptr; dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; #ifndef CONFIG_MMC_SDHCI_S3C_DMA /* we currently see overruns on errors, so disable the SDMA * support as well. */ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; if (pdata->cd_type == S3C_SDHCI_CD_NONE) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; /* IF SD controller's WP pin donsn't connected with SD card and there is an * allocated GPIO for getting WP data form SD card, use this quirk and send * the GPIO number in pdata->wp_gpio. */ if (pdata->has_wp_gpio && gpio_is_valid(pdata->wp_gpio)) { sdhci_s3c_ops.get_ro = sdhci_s3c_get_ro; host->quirks |= SDHCI_QUIRK_NO_WP_BIT; sdhci_s3c_cfg_wp(pdata->wp_gpio); } host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #ifdef CONFIG_ARCH_S5PV310 host->quirks |= SDHCI_QUIRK_NONSTANDARD_CLOCK; host->quirks |= SDHCI_QUIRK_BROKEN_CLOCK_DIVIDER; #endif if(pdata->host_caps) host->mmc->caps |= pdata->host_caps; /* Fill External GPIO Value */ if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) { pr_info("%s : S3C_SDHCI_CD_PERMANENT\n", __func__); if(gpio_is_valid(pdata->ext_cd_gpio)) { pr_info("%s : MMC GPIO Level is %d\n", __func__ , gpio_get_value(pdata->ext_cd_gpio)); gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD"); sc->ext_cd_gpio = gpio_get_value(pdata->ext_cd_gpio); } } if (pdata->cd_type == S3C_SDHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) { pr_info("%s : S3C_SDHCI_CD_GPIO\n", __func__); gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD"); sc->ext_cd_gpio = pdata->ext_cd_gpio; sc->regulator_workq = create_singlethread_workqueue("ktflash_requlatord"); if (!sc->regulator_workq) { pr_info("%s : ERROR: workqueue for Tflash's regulator.\n" "Regulator for Tflash will be always ON\n", __func__); } INIT_DELAYED_WORK(&sc->regul_work, sdhci_s3c_requlator_work); sc->ext_cd_irq = gpio_to_irq(pdata->ext_cd_gpio); if (sc->ext_cd_irq && request_irq(sc->ext_cd_irq, sdhci_s3c_gpio_card_detect_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), sc)) { dev_err(&pdev->dev, "cannot request irq for card detect\n"); sc->ext_cd_irq = 0; } if (tflash_detection_cmd_dev == NULL && sc->ext_cd_gpio) { tflash_detection_cmd_dev = device_create(sec_class, NULL, 0, NULL, "tctest"); if (IS_ERR(tflash_detection_cmd_dev)) pr_err("%s : Failed to create device(ts)!\n", __func__); if (device_create_file(tflash_detection_cmd_dev, &dev_attr_tftest) < 0) pr_err("%s : Failed to create device file(%s)!\n", __func__, dev_attr_tftest.attr.name); dev_set_drvdata(tflash_detection_cmd_dev, sc); } /* T-Flash EINT for CD SHOULD be wakeup source */ set_irq_wake(sc->ext_cd_irq, 1); } /* Call sdhci_host */ ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) { host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; host->mmc->caps |= MMC_CAP_NONREMOVABLE; } /* pdata->ext_cd_init might call sdhci_s3c_notify_change immediately, so it can be called only after sdhci_add_host() */ if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init) { pr_info("%s : S3C_SDHCI_CD_EXTERNAL and external init\n", __func__); pdata->ext_cd_init(&sdhci_s3c_notify_change); } if (pdata->cd_type == S3C_SDHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) { host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; } return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
static int __devinit sdhci_hlwd_probe(struct of_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->node; struct sdhci_hlwd_data *sdhci_hlwd_data = match->data; struct sdhci_host *host; struct sdhci_hlwd_host *hlwd_host; struct resource res; int error; if (starlet_get_ipc_flavour() != STARLET_IPC_MINI) { error = -ENODEV; goto out; } if (!of_device_is_available(np)) { error = -ENODEV; goto out; } host = sdhci_alloc_host(&ofdev->dev, sizeof(*hlwd_host)); if (!host) { DBG("unable to allocate sdhci_host\n"); error = -ENODEV; goto out; } dev_set_drvdata(&ofdev->dev, host); error = of_address_to_resource(np, 0, &res); if (error) { DBG("of_address_to_resource failed (%d)\n", error); goto err_no_address; } host->ioaddr = ioremap(res.start, resource_size(&res)); if (!host->ioaddr) { DBG("ioremap failed\n"); error = -EINVAL; goto err_ioremap; } host->irq = irq_of_parse_and_map(np, 0); if (!host->irq) { DBG("irq_of_parse_and_map failed\n"); error = -EINVAL; goto err_no_irq; } host->hw_name = dev_name(&ofdev->dev); if (sdhci_hlwd_data) { host->quirks = sdhci_hlwd_data->quirks; host->ops = &sdhci_hlwd_data->ops; } error = sdhci_add_host(host); if (error) { DBG("sdhci_add_host failed\n"); goto err_add_host; } return 0; err_add_host: irq_dispose_mapping(host->irq); err_no_irq: iounmap(host->ioaddr); err_ioremap: err_no_address: sdhci_free_host(host); out: return error; }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } 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; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; sc->ext_cd_gpio = -1; /* invalid gpio number */ platform_set_drvdata(pdev, host); sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char name[14]; snprintf(name, 14, "mmc_busclk.%d", ptr); clk = clk_get(dev, name); if (IS_ERR(clk)) { continue; } clks++; sc->clk_bus[ptr] = clk; /* * save current clock index to know which clock bus * is used later in overriding functions. */ sc->cur_clk = ptr; clk_enable(clk); dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #ifndef CONFIG_MMC_SDHCI_S3C_DMA /* we currently see overruns on errors, so disable the SDMA * support as well. */ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; /* This host supports the Auto CMD12 */ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; /* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */ host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC; if (pdata->cd_type == S3C_SDHCI_CD_NONE || pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->mmc->caps = MMC_CAP_NONREMOVABLE; if (pdata->host_caps) host->mmc->caps |= pdata->host_caps; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; /* * If controller does not have internal clock divider, * we can use overriding functions instead of default. */ if (pdata->clk_type) { sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; } /* It supports additional host capabilities if needed */ if (pdata->host_caps) host->mmc->caps |= pdata->host_caps; ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } /* The following two methods of card detection might call sdhci_s3c_notify_change() immediately, so they can be called only after sdhci_add_host(). Setup errors are ignored. */ if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init) pdata->ext_cd_init(&sdhci_s3c_notify_change); if (pdata->cd_type == S3C_SDHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) sdhci_s3c_setup_card_detect_gpio(sc); return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, const struct sdhci_pltfm_data *pdata, size_t priv_size) { struct sdhci_host *host; struct resource *iomem; int ret; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { ret = -ENOMEM; goto err; } if (resource_size(iomem) < 0x100) dev_err(&pdev->dev, "Invalid iomem size!\n"); host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pltfm_host) + priv_size); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } host->hw_name = dev_name(&pdev->dev); if (pdata && pdata->ops) host->ops = pdata->ops; else host->ops = &sdhci_pltfm_ops; if (pdata) { host->quirks = pdata->quirks; host->quirks2 = pdata->quirks2; } host->irq = platform_get_irq(pdev, 0); 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_request; } host->ioaddr = ioremap(iomem->start, resource_size(iomem)); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); ret = -ENOMEM; goto err_remap; } /* * Some platforms need to probe the controller to be able to * determine which caps should be used. */ if (host->ops && host->ops->platform_init) host->ops->platform_init(host); platform_set_drvdata(pdev, host); return host; err_remap: release_mem_region(iomem->start, resource_size(iomem)); err_request: sdhci_free_host(host); err: dev_err(&pdev->dev, "%s failed %d\n", __func__, ret); return ERR_PTR(ret); }
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 *sd_detect; 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; } 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->clk_enable = 1; platform_set_drvdata(pdev, host); host->vmmc = NULL; host->ioaddr = (void __iomem *)res->start; pr_debug("sdio: host->ioaddr:0x%x\n", (unsigned int)host->ioaddr); if (0 == pdev->id){ host->hw_name = "Spread SDIO host0"; }else if(1 == pdev->id){ host->hw_name = "Spread SDIO host1"; } else if(2 == pdev->id){ host->hw_name = "Spread SDIO host2"; } else if(3 == pdev->id){ host->hw_name = "Spread EMMC host0"; host->mmc->caps |= MMC_CAP_8_BIT_DATA /*| MMC_CAP_1_8V_DDR*/; } host->ops = &sdhci_sprd_ops; /* * SC8810G don't have timeout value and cann't find card *insert, write protection... * too sad */ 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 gpio_detect = 777; sd_detect = dev_get_platdata(dev); if(sd_detect && (*sd_detect > 0)){ sd_detect_gpio = *sd_detect; 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"); } gpio_export( sd_detect_gpio, 1); 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; } gpio_detect = sd_detect_gpio; host_data->detect_irq = detect_irq; }else{ printk("%s, sd_detect_gpio == 0 \n", __func__ ); } #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"); } host->clk = NULL; sdhci_module_init(host); host->mmc->caps |= MMC_CAP_HW_RESET; host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; host->mmc->pm_caps |= (MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ); #ifdef CONFIG_MACH_KYLEW if(pdev->id == 1){ host->mmc->pm_caps |= MMC_CAP_NONREMOVABLE; pm_runtime_disable(&(pdev)->dev); /* temprarily disable runtime case because of error arising when turn on*/ } else if(pdev->id == 0) { host->mmc->pm_flags |= MMC_PM_KEEP_POWER; pm_runtime_disable(&(pdev)->dev); } #elif defined (CONFIG_ARCH_SC7710) if(pdev->id == 1){ host->mmc->pm_caps |= MMC_CAP_NONREMOVABLE; // pm_runtime_disable(&(pdev)->dev); } else if(pdev->id == 2) { host->mmc->pm_flags |= MMC_PM_KEEP_POWER; // pm_runtime_disable(&(pdev)->dev); } #elif defined (CONFIG_MACH_SP7702) if(pdev->id == 1){ host->mmc->pm_flags |= MMC_PM_KEEP_POWER; pm_runtime_disable(&(pdev)->dev); } #else if(pdev->id == 1){ host->mmc->pm_caps |= MMC_CAP_NONREMOVABLE; } switch(pdev->id) { case 1://eMMC host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY ;//| MMC_PM_KEEP_POWER; host->mmc->caps |= MMC_CAP_NONREMOVABLE | MMC_CAP_1_8V_DDR; break; case 0://SD host->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; break; default: break; } #endif ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } #if defined(CONFIG_MACH_KYLEW) || defined(CONFIG_MACH_SP7702)|| defined(CONFIG_MACH_MINT) sdhci_sprd_fix_controller_1p8v(host); #endif #ifdef CONFIG_MMC_BUS_SCAN if (pdev->id == 1) sdhci_host_g = host; #endif #ifdef CONFIG_PM_RUNTIME switch(pdev->id) { case 1: case 0: pm_suspend_ignore_children(&pdev->dev, true); pm_runtime_set_active(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 500); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); default: break; } #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; }
static int sdhci_bcm2708_probe(struct platform_device *pdev) { struct sdhci_host *host; struct resource *iomem; struct sdhci_bcm2708_priv *host_priv; int ret; BUG_ON(pdev == NULL); iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { ret = -ENOMEM; goto err; } if (resource_size(iomem) != 0x100) dev_err(&pdev->dev, "Invalid iomem size. You may " "experience problems.\n"); if (pdev->dev.parent) host = sdhci_alloc_host(pdev->dev.parent, sizeof(struct sdhci_bcm2708_priv)); else host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_bcm2708_priv)); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } if (missing_status) { sdhci_bcm2708_ops.missing_status = sdhci_bcm2708_missing_status; } if( spurious_crc_acmd51 ) { sdhci_bcm2708_ops.spurious_crc_acmd51 = sdhci_bcm2708_quirk_spurious_crc_acmd51; } printk("sdhci: %s low-latency mode\n",enable_llm?"Enable":"Disable"); host->hw_name = "BCM2708_Arasan"; host->ops = &sdhci_bcm2708_ops; host->irq = platform_get_irq(pdev, 0); host->second_irq = 0; host->quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_MISSING_CAPS | SDHCI_QUIRK_NO_HISPD_BIT | (sync_after_dma ? 0:SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12); #ifdef CONFIG_MMC_SDHCI_BCM2708_DMA host->flags = SDHCI_USE_PLATDMA; #endif 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_request; } host->ioaddr = ioremap(iomem->start, resource_size(iomem)); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); ret = -ENOMEM; goto err_remap; } host_priv = SDHCI_HOST_PRIV(host); #ifdef CONFIG_MMC_SDHCI_BCM2708_DMA host_priv->dma_wanted = 0; #ifdef CHECK_DMA_USE host_priv->dmas_pending = 0; host_priv->when_started = 0; host_priv->when_reset = 0; host_priv->when_stopped = 0; #endif host_priv->sg_ix = 0; host_priv->sg_done = 0; host_priv->complete = NULL; host_priv->dma_waits = SDHCI_BCM_DMA_WAITS; host_priv->cb_base = dma_alloc_writecombine(&pdev->dev, SZ_4K, &host_priv->cb_handle, GFP_KERNEL); if (!host_priv->cb_base) { dev_err(&pdev->dev, "cannot allocate DMA CBs\n"); ret = -ENOMEM; goto err_alloc_cb; } ret = bcm_dma_chan_alloc(BCM_DMA_FEATURE_FAST, &host_priv->dma_chan_base, &host_priv->dma_irq); if (ret < 0) { dev_err(&pdev->dev, "couldn't allocate a DMA channel\n"); goto err_add_dma; } host_priv->dma_chan = ret; ret = request_irq(host_priv->dma_irq, sdhci_bcm2708_dma_irq,0,//IRQF_SHARED, DRIVER_NAME " (dma)", host); if (ret) { dev_err(&pdev->dev, "cannot set DMA IRQ\n"); goto err_add_dma_irq; } host->second_irq = host_priv->dma_irq; DBG("DMA CBs %p handle %08X DMA%d %p DMA IRQ %d\n", host_priv->cb_base, (unsigned)host_priv->cb_handle, host_priv->dma_chan, host_priv->dma_chan_base, host_priv->dma_irq); // we support 3.3V host->caps |= SDHCI_CAN_VDD_330; if (allow_highspeed) host->mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; /* single block writes cause data loss with some SD cards! */ host->mmc->caps2 |= MMC_CAP2_FORCE_MULTIBLOCK; #endif ret = sdhci_add_host(host); if (ret) goto err_add_host; platform_set_drvdata(pdev, host); ret = device_create_file(&pdev->dev, &dev_attr_use_dma); ret = device_create_file(&pdev->dev, &dev_attr_dma_wait); ret = device_create_file(&pdev->dev, &dev_attr_status); #ifdef CONFIG_MMC_SDHCI_BCM2708_DMA /* enable extension fifo for paced DMA transfers */ sdhci_bcm2708_writel(host, 1, REG_EXRDFIFO_EN); sdhci_bcm2708_writel(host, 4, REG_EXRDFIFO_CFG); #endif printk(KERN_INFO "%s: BCM2708 SDHC host at 0x%08llx DMA %d IRQ %d\n", mmc_hostname(host->mmc), (unsigned long long)iomem->start, host_priv->dma_chan, host_priv->dma_irq); return 0; err_add_host: #ifdef CONFIG_MMC_SDHCI_BCM2708_DMA free_irq(host_priv->dma_irq, host); err_add_dma_irq: bcm_dma_chan_free(host_priv->dma_chan); err_add_dma: dma_free_writecombine(&pdev->dev, SZ_4K, host_priv->cb_base, host_priv->cb_handle); err_alloc_cb: #endif iounmap(host->ioaddr); err_remap: release_mem_region(iomem->start, resource_size(iomem)); err_request: sdhci_free_host(host); err: dev_err(&pdev->dev, "probe failed, err %d\n", ret); return ret; }
static int sdhci_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; acpi_handle handle = ACPI_HANDLE(dev); struct acpi_device *device; struct sdhci_acpi_host *c; struct sdhci_host *host; struct resource *iomem; resource_size_t len; const char *hid; const char *uid; int err; if (acpi_bus_get_device(handle, &device)) return -ENODEV; if (acpi_bus_get_status(device) || !device->status.present) return -ENODEV; hid = acpi_device_hid(device); uid = device->pnp.unique_id; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) return -ENOMEM; len = resource_size(iomem); if (len < 0x100) dev_err(dev, "Invalid iomem size!\n"); if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) return -ENOMEM; host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); if (IS_ERR(host)) return PTR_ERR(host); c = sdhci_priv(host); c->host = host; c->slot = sdhci_acpi_get_slot(hid, uid); c->pdev = pdev; c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); platform_set_drvdata(pdev, c); host->hw_name = "ACPI"; host->ops = &sdhci_acpi_ops_dflt; host->irq = platform_get_irq(pdev, 0); host->ioaddr = devm_ioremap_nocache(dev, iomem->start, resource_size(iomem)); if (host->ioaddr == NULL) { err = -ENOMEM; goto err_free; } if (c->slot) { if (c->slot->probe_slot) { err = c->slot->probe_slot(pdev, hid, uid); if (err) goto err_free; } if (c->slot->chip) { host->ops = c->slot->chip->ops; host->quirks |= c->slot->chip->quirks; host->quirks2 |= c->slot->chip->quirks2; host->mmc->caps |= c->slot->chip->caps; host->mmc->caps2 |= c->slot->chip->caps2; host->mmc->pm_caps |= c->slot->chip->pm_caps; } host->quirks |= c->slot->quirks; host->quirks2 |= c->slot->quirks2; host->mmc->caps |= c->slot->caps; host->mmc->caps2 |= c->slot->caps2; host->mmc->pm_caps |= c->slot->pm_caps; } host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL); if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0, NULL)) { dev_warn(dev, "failed to setup card detect gpio\n"); c->use_runtime_pm = false; } } err = sdhci_add_host(host); if (err) goto err_free; if (c->use_runtime_pm) { pm_runtime_set_active(dev); pm_suspend_ignore_children(dev, 1); pm_runtime_set_autosuspend_delay(dev, 50); pm_runtime_use_autosuspend(dev); pm_runtime_enable(dev); } return 0; err_free: sdhci_free_host(c->host); return err; }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } 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; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; platform_set_drvdata(pdev, host); sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char *name = pdata->clocks[ptr]; if (name == NULL) continue; clk = clk_get(dev, name); if (IS_ERR(clk)) { dev_err(dev, "failed to get clock %s\n", name); continue; } clks++; sc->clk_bus[ptr] = clk; clk_enable(clk); dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); if (pdata->get_ro) sdhci_s3c_ops.get_ro = sdhci_s3c_get_ro; host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; host->quirks |= SDHCI_QUIRK_BROKEN_CARD_PRESENT_BIT; host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; #ifndef CONFIG_MMC_SDHCI_S3C_DMA /* we currently see overruns on errors, so disable the SDMA * support as well. */ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; /* PIO currently has problems with multi-block IO */ host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; if (pdata->host_caps) host->mmc->caps = pdata->host_caps; else host->mmc->caps = 0; /* Set pm_flags for built_in device */ host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY; if (pdata->built_in) host->mmc->pm_flags = MMC_PM_KEEP_POWER | MMC_PM_IGNORE_PM_NOTIFY; /* to add external irq as a card detect signal */ if (pdata->cfg_ext_cd) { pdata->cfg_ext_cd(); if (pdata->detect_ext_cd()) host->flags |= SDHCI_DEVICE_ALIVE; } /* to configure gpio pin as a card write protection signal */ if (pdata->cfg_wp) pdata->cfg_wp(); ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } /* register external irq here (after all init is done) */ if (pdata->cfg_ext_cd) { ret = request_irq(pdata->ext_cd, sdhci_irq_cd, IRQF_SHARED, mmc_hostname(host->mmc), sc); if(ret) goto err_add_host; } #if SD_DYNAMIC if (strcmp(mmc_hostname(host->mmc),"mmc1")==0) { int retval=0; spin_lock_init(&s3c_sd_changed_lock); INIT_WORK(&sd_monitor_work, sd_extr_work); s3c_gpio_cfgpin(SD_DET_WAKE, S3C_GPIO_SFN(0xf)); s3c_gpio_setpull(SD_DET_WAKE, 0); retval = request_irq(__gpio_to_irq(SD_DET_WAKE), s3c_sdhci_power_irq, IRQ_TYPE_EDGE_BOTH, sd_driver_name, NULL); if (retval != 0) { printk(KERN_ERR "%s: can't get irq %i, err %d\n", sd_driver_name, __gpio_to_irq(SD_DET_WAKE), retval); } printk(KERN_ERR "%s: get irq %i, err %d\n", sd_driver_name, __gpio_to_irq(SD_DET_WAKE), retval); } #endif return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
int __init tegra_sdhci_probe(struct platform_device *pdev) { struct sdhci_host *sdhost; struct tegra_sdhci *host; struct tegra_sdhci_platform_data *plat = pdev->dev.platform_data; struct resource *res; int ret = -ENODEV; static int pmu_count=0; int enable=0; if (pdev->id == -1) { dev_err(&pdev->dev, "dynamic instance assignment not allowed\n"); return -ENODEV; } sdhost = sdhci_alloc_host(&pdev->dev, sizeof(struct tegra_sdhci)); if (IS_ERR_OR_NULL(sdhost)) { dev_err(&pdev->dev, "unable to allocate driver structure\n"); return (!sdhost) ? -ENOMEM : PTR_ERR(sdhost); } sdhost->hw_name = dev_name(&pdev->dev); host = sdhci_priv(sdhost); host->hOdmSdio = NvOdmSdioOpen(pdev->id); if (!host->hOdmSdio) dev_info(&pdev->dev, "no ODM SDIO adaptation\n"); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "no memory I/O resource provided\n"); ret = -ENODEV; goto err_sdhci_alloc; } if (!request_mem_region(res->start, res_size(res), dev_name(&pdev->dev))) { dev_err(&pdev->dev, "memory in use\n"); ret = -EBUSY; goto err_sdhci_alloc; } sdhost->ioaddr = ioremap(res->start, res_size(res)); if (!sdhost->ioaddr) { dev_err(&pdev->dev, "failed to map registers\n"); ret = -ENXIO; goto err_request_mem; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(&pdev->dev, "no IRQ resource provided\n"); ret = -ENODEV; goto err_ioremap; } sdhost->irq = res->start; host->clk = clk_get(&pdev->dev, NULL); if (!host->clk) { dev_err(&pdev->dev, "unable to get clock\n"); ret = -ENODEV; goto err_ioremap; } host->pdev = pdev; host->pinmux = plat->pinmux; host->nr_pins = plat->nr_pins; host->gpio_cd = plat->gpio_nr_cd; host->gpio_polarity_cd = plat->gpio_polarity_cd; host->gpio_wp = plat->gpio_nr_wp; host->gpio_polarity_wp = plat->gpio_polarity_wp; //add by navy host->gpio_en = plat->gpio_nr_en; host->gpio_polarity_en = plat->gpio_polarity_en; //add end host->card_always_on = plat->is_always_on; dev_dbg(&pdev->dev, "write protect: %d card detect: %d\n", host->gpio_wp, host->gpio_cd); host->irq_cd = -1; host->debounce = plat->debounce; if (plat->max_clk) host->max_clk = min_t(unsigned int, 52000000, plat->max_clk); else {
struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, struct sdhci_pltfm_data *pdata) { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct device_node *np = pdev->dev.of_node; struct resource *iomem; int ret; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { ret = -ENOMEM; goto err; } if (resource_size(iomem) < 0x100) dev_err(&pdev->dev, "Invalid iomem size!\n"); /* Some PCI-based MFD need the parent here */ if (pdev->dev.parent != &platform_bus && !np) host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host)); else host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host)); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } pltfm_host = sdhci_priv(host); #ifdef CONFIG_ARCH_DOVE struct sdhci_dove_int_wa *data = (struct sdhci_dove_int_wa *) pdev->dev.platform_data; if (data) { dev_dbg(&pdev->dev, " request wa irq\n"); pltfm_host->dove_card_int_wa = 1; pltfm_host->dove_int_wa_info.irq = data->irq; pltfm_host->dove_int_wa_info.gpio = data->gpio; pltfm_host->dove_int_wa_info.func_select_bit = data->func_select_bit; pltfm_host->dove_int_wa_info.status = 0; //disabled ret = devm_request_irq(&pdev->dev, pltfm_host->dove_int_wa_info.irq, sdhci_dove_gpio_irq, IRQF_DISABLED, mmc_hostname(host->mmc), host); if(ret) { dev_err(&pdev->dev, "cannot request wa irq\n"); goto err; } /* to balance disable/enable_irq */ disable_irq_nosync(pltfm_host->dove_int_wa_info.irq); } else { dev_dbg(&pdev->dev, " no request wa irq\n"); pltfm_host->dove_card_int_wa = 0; } #endif host->hw_name = dev_name(&pdev->dev); if (pdata && pdata->ops) host->ops = pdata->ops; else host->ops = &sdhci_pltfm_ops; if (pdata) host->quirks = pdata->quirks; host->irq = platform_get_irq(pdev, 0); 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_request; } host->ioaddr = ioremap(iomem->start, resource_size(iomem)); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); ret = -ENOMEM; goto err_remap; } platform_set_drvdata(pdev, host); return host; err_remap: release_mem_region(iomem->start, resource_size(iomem)); err_request: sdhci_free_host(host); err: dev_err(&pdev->dev, "%s failed %d\n", __func__, ret); return ERR_PTR(ret); }
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; }
static int __devinit sdhci_of_probe(struct platform_device *ofdev) { const struct of_device_id *match; struct device_node *np = ofdev->dev.of_node; struct sdhci_of_data *sdhci_of_data; struct sdhci_host *host; struct sdhci_of_host *of_host; const __be32 *clk; int size; int ret; match = of_match_device(sdhci_of_match, &ofdev->dev); if (!match) return -EINVAL; sdhci_of_data = match->data; if (!of_device_is_available(np)) return -ENODEV; host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host)); if (IS_ERR(host)) return -ENOMEM; of_host = sdhci_priv(host); dev_set_drvdata(&ofdev->dev, host); host->ioaddr = of_iomap(np, 0); if (!host->ioaddr) { ret = -ENOMEM; goto err_addr_map; } host->irq = irq_of_parse_and_map(np, 0); if (!host->irq) { ret = -EINVAL; goto err_no_irq; } host->hw_name = dev_name(&ofdev->dev); if (sdhci_of_data) { host->quirks = sdhci_of_data->quirks; host->ops = &sdhci_of_data->ops; } if (of_get_property(np, "sdhci,auto-cmd12", NULL)) host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; if (of_get_property(np, "sdhci,1-bit-only", NULL)) host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; if (sdhci_of_wp_inverted(np)) host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; clk = of_get_property(np, "clock-frequency", &size); if (clk && size == sizeof(*clk) && *clk) of_host->clock = be32_to_cpup(clk); ret = sdhci_add_host(host); if (ret) goto err_add_host; return 0; err_add_host: irq_dispose_mapping(host->irq); err_no_irq: iounmap(host->ioaddr); err_addr_map: sdhci_free_host(host); return ret; }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } 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; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; sc->ext_cd_gpio = -1; /* invalid gpio number */ platform_set_drvdata(pdev, host); sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char *name = pdata->clocks[ptr]; if (name == NULL) continue; clk = clk_get(dev, name); if (IS_ERR(clk)) { dev_err(dev, "failed to get clock %s\n", name); continue; } clks++; sc->clk_bus[ptr] = clk; /* * save current clock index to know which clock bus * is used later in overriding functions. */ sc->cur_clk = ptr; clk_enable(clk); dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; #ifndef CONFIG_MMC_SDHCI_S3C_DMA /* we currently see overruns on errors, so disable the SDMA * support as well. */ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; /* This host supports the Auto CMD12 */ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; if (pdata->cd_type == S3C_SDHCI_CD_NONE) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->mmc->caps = MMC_CAP_NONREMOVABLE; if (pdata->host_caps) host->mmc->caps |= pdata->host_caps; /* if vmmc_name is in pdata */ if (pdata->vmmc_name) host->vmmc_name = pdata->vmmc_name; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; /* * If controller does not have internal clock divider, * we can use overriding functions instead of default. */ if (pdata->clk_type) { sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; } /* It supports additional host capabilities if needed */ if (pdata->host_caps) host->mmc->caps |= pdata->host_caps; /* for BCM WIFI */ if (pdata->pm_flags) host->mmc->pm_flags |= pdata->pm_flags; #ifdef CONFIG_MACH_MIDAS_01_BD /* before calling shhci_add_host, you should turn vdd_tflash on */ sdhci_s3c_vtf_on_off(1); #endif /* To turn on vmmc regulator only if sd card exists, GPIO pin for card detection should be initialized. Moved from sdhci_s3c_setup_card_detect_gpio() function */ if (pdata->cd_type == S3C_SDHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) { if (gpio_request(pdata->ext_cd_gpio, "SDHCI EXT CD") == 0) { sc->ext_cd_gpio = pdata->ext_cd_gpio; sc->ext_cd_gpio_invert = pdata->ext_cd_gpio_invert; mmc_host_sd_set_present(host->mmc); if (sd_detection_cmd_dev == NULL && sc->ext_cd_gpio) { 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"); dev_set_drvdata(sd_detection_cmd_dev, sc); } #ifdef CONFIG_MIDAS_COMMON /* set TF_EN gpio as OUTPUT */ gpio_request(GPIO_TF_EN, "TF_EN"); gpio_direction_output(GPIO_TF_EN, 1); s3c_gpio_cfgpin(GPIO_TF_EN, S3C_GPIO_SFN(1)); s3c_gpio_setpull(GPIO_TF_EN, S3C_GPIO_PULL_NONE); #endif } else { dev_err(dev, "cannot request gpio for card detect\n"); } } #ifdef CONFIG_MACH_PX /* * sdhc which has S3C_SDHCI_CD_EXTERNAL flag means a wifi * on PX projects. */ if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL) { /* w/a for h/w sdio interrupt */ host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST; } #endif ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } /* if it is set SDHCI_QUIRK_BROKEN_CARD_DETECTION before calling sdhci_add_host, in sdhci_add_host, MMC_CAP_NEEDS_POLL flag will be set. The flag S3C_SDHCI_CD_PERMANENT dose not need to detect a card by polling. */ if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT || \ pdata->cd_type == S3C_SDHCI_CD_GPIO) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; /* The following two methods of card detection might call sdhci_s3c_notify_change() immediately, so they can be called only after sdhci_add_host(). Setup errors are ignored. */ if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init) { pdata->ext_cd_init(&sdhci_s3c_notify_change); #ifdef CONFIG_MACH_PX if (pdata->ext_pdev) pdata->ext_pdev(pdev); #endif } #ifdef CONFIG_MACH_U1_NA_SPR if (pdata->cd_type == S3C_SDHCI_CD_GPIO && pdata->ext_cd_init) pdata->ext_cd_init(&sdhci_s3c_notify_change); #endif if (pdata->cd_type == S3C_SDHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) sdhci_s3c_setup_card_detect_gpio(sc); #ifdef CONFIG_MACH_MIDAS_01_BD /* if card dose not exist, it should turn vtf off */ if (pdata->cd_type == S3C_SDHCI_CD_GPIO && sdhci_s3c_get_card_exist(host)) sdhci_s3c_vtf_on_off(1); else sdhci_s3c_vtf_on_off(0); #endif return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
static int __devinit sdhci_of_probe(struct of_device *ofdev, const struct of_device_id *match) { struct device_node *np = ofdev->dev.of_node; struct sdhci_of_data *sdhci_of_data = match->data; struct sdhci_host *host; struct sdhci_of_host *of_host; const u32 *clk; int size; int ret; if (!of_device_is_available(np)) return -ENODEV; host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host)); if (IS_ERR(host)) return -ENOMEM; of_host = sdhci_priv(host); dev_set_drvdata(&ofdev->dev, host); host->ioaddr = of_iomap(np, 0); if (!host->ioaddr) { ret = -ENOMEM; goto err_addr_map; } host->irq = irq_of_parse_and_map(np, 0); if (!host->irq) { ret = -EINVAL; goto err_no_irq; } host->hw_name = dev_name(&ofdev->dev); if (sdhci_of_data) { host->quirks = sdhci_of_data->quirks; host->ops = &sdhci_of_data->ops; } if (of_get_property(np, "sdhci,1-bit-only", NULL)) host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; if (sdhci_of_wp_inverted(np)) host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; if (of_get_property(np, "fsl,sdhci-dma-broken", NULL)) host->quirks |= SDHCI_QUIRK_BROKEN_DMA; if (of_get_property(np, "fsl,sdhci-ahb2mag-irq-bypass", NULL)) host->quirks |= SDHCI_QUIRK_SET_AHB2MAG_IRQ_BYPASS; if (of_get_property(np, "fsl,sdhci-adjust-timeout", NULL)) host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; clk = of_get_property(np, "clock-frequency", &size); if (clk && size == sizeof(*clk) && *clk) of_host->clock = *clk; ret = sdhci_add_host(host); if (ret) goto err_add_host; return 0; err_add_host: irq_dispose_mapping(host->irq); err_no_irq: iounmap(host->ioaddr); err_addr_map: sdhci_free_host(host); return ret; }
static int sdhci_acpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; acpi_handle handle = ACPI_HANDLE(dev); struct acpi_device *device; struct sdhci_acpi_host *c; struct sdhci_host *host; struct resource *iomem; resource_size_t len; const char *hid; int err; if (acpi_bus_get_device(handle, &device)) return -ENODEV; if (acpi_bus_get_status(device) || !device->status.present) return -ENODEV; hid = acpi_device_hid(device); iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) return -ENOMEM; len = resource_size(iomem); if (len < 0x100) dev_err(dev, "Invalid iomem size!\n"); if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev))) return -ENOMEM; host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host)); if (IS_ERR(host)) return PTR_ERR(host); c = sdhci_priv(host); c->host = host; c->slot = sdhci_acpi_get_slot(handle, hid); c->pdev = pdev; c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM); platform_set_drvdata(pdev, c); host->hw_name = "ACPI"; host->ops = &sdhci_acpi_ops_dflt; host->irq = platform_get_irq(pdev, 0); host->ioaddr = devm_ioremap_nocache(dev, iomem->start, resource_size(iomem)); if (host->ioaddr == NULL) { err = -ENOMEM; goto err_free; } if (!dev->dma_mask) { u64 dma_mask; if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) { /* 64-bit DMA is not supported at present */ dma_mask = DMA_BIT_MASK(32); } else { dma_mask = DMA_BIT_MASK(32); } err = dma_coerce_mask_and_coherent(dev, dma_mask); if (err) goto err_free; } if (c->slot) { if (c->slot->chip) { host->ops = c->slot->chip->ops; host->quirks |= c->slot->chip->quirks; host->quirks2 |= c->slot->chip->quirks2; host->mmc->caps |= c->slot->chip->caps; host->mmc->caps2 |= c->slot->chip->caps2; host->mmc->pm_caps |= c->slot->chip->pm_caps; } host->quirks |= c->slot->quirks; host->quirks2 |= c->slot->quirks2; host->mmc->caps |= c->slot->caps; host->mmc->caps2 |= c->slot->caps2; host->mmc->pm_caps |= c->slot->pm_caps; } host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP; err = sdhci_add_host(host); if (err) goto err_free; if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) { if (sdhci_acpi_add_own_cd(dev, host->mmc)) c->use_runtime_pm = false; } if (c->use_runtime_pm) { pm_runtime_set_active(dev); pm_suspend_ignore_children(dev, 1); pm_runtime_set_autosuspend_delay(dev, 50); pm_runtime_use_autosuspend(dev); pm_runtime_enable(dev); } return 0; err_free: sdhci_free_host(c->host); return err; }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } 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; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; platform_set_drvdata(pdev, host); sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char *name = pdata->clocks[ptr]; if (name == NULL) continue; clk = clk_get(dev, name); if (IS_ERR(clk)) { dev_err(dev, "failed to get clock %s\n", name); continue; } clks++; sc->clk_bus[ptr] = clk; clk_enable(clk); dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; #ifndef CONFIG_MMC_SDHCI_S3C_DMA /* we currently see overruns on errors, so disable the SDMA * support as well. */ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
static int sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata; struct sdhci_s3c_drv_data *drv_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdev->dev.platform_data && !pdev->dev.of_node) { dev_err(dev, "no device data specified\n"); return -ENOENT; } irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "no irq specified\n"); return irq; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } sc = sdhci_priv(host); pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) { ret = -ENOMEM; goto err_pdata_io_clk; } if (pdev->dev.of_node) { ret = sdhci_s3c_parse_dt(&pdev->dev, host, pdata); if (ret) goto err_pdata_io_clk; } else { memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); sc->ext_cd_gpio = -1; /* invalid gpio number */ } drv_data = sdhci_s3c_get_driver_data(pdev); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; platform_set_drvdata(pdev, host); sc->clk_io = devm_clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_pdata_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_prepare_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char name[14]; snprintf(name, 14, "mmc_busclk.%d", ptr); clk = devm_clk_get(dev, name); if (IS_ERR(clk)) continue; clks++; sc->clk_bus[ptr] = clk; /* * save current clock index to know which clock bus * is used later in overriding functions. */ sc->cur_clk = ptr; dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } #ifndef CONFIG_PM_RUNTIME clk_prepare_enable(sc->clk_bus[sc->cur_clk]); #endif res = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->ioaddr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(host->ioaddr)) { ret = PTR_ERR(host->ioaddr); goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, pdata->max_width); host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; if (drv_data) host->quirks |= drv_data->sdhci_quirks; #ifndef CONFIG_MMC_SDHCI_S3C_DMA /* we currently see overruns on errors, so disable the SDMA * support as well. */ host->quirks |= SDHCI_QUIRK_BROKEN_DMA; #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ; /* This host supports the Auto CMD12 */ host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12; /* Samsung SoCs need BROKEN_ADMA_ZEROLEN_DESC */ host->quirks |= SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC; if (pdata->cd_type == S3C_SDHCI_CD_NONE || pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION; if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->mmc->caps = MMC_CAP_NONREMOVABLE; switch (pdata->max_width) { case 8: host->mmc->caps |= MMC_CAP_8_BIT_DATA; case 4: host->mmc->caps |= MMC_CAP_4_BIT_DATA; break; } if (pdata->pm_caps) host->mmc->pm_caps |= pdata->pm_caps; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; /* * If controller does not have internal clock divider, * we can use overriding functions instead of default. */ if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) { pax_open_kernel(); *(void **)&sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; *(void **)&sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; *(void **)&sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; pax_close_kernel(); } /* It supports additional host capabilities if needed */ if (pdata->host_caps) host->mmc->caps |= pdata->host_caps; if (pdata->host_caps2) host->mmc->caps2 |= pdata->host_caps2; pm_runtime_enable(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); pm_suspend_ignore_children(&pdev->dev, 1); ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); pm_runtime_forbid(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); goto err_req_regs; } /* The following two methods of card detection might call sdhci_s3c_notify_change() immediately, so they can be called only after sdhci_add_host(). Setup errors are ignored. */ if (pdata->cd_type == S3C_SDHCI_CD_EXTERNAL && pdata->ext_cd_init) pdata->ext_cd_init(&sdhci_s3c_notify_change); if (pdata->cd_type == S3C_SDHCI_CD_GPIO && gpio_is_valid(pdata->ext_cd_gpio)) sdhci_s3c_setup_card_detect_gpio(sc); #ifdef CONFIG_PM_RUNTIME if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) clk_disable_unprepare(sc->clk_io); #endif return 0; err_req_regs: #ifndef CONFIG_PM_RUNTIME clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); #endif err_no_busclks: clk_disable_unprepare(sc->clk_io); err_pdata_io_clk: sdhci_free_host(host); return ret; }
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; }
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; }
static int __devinit tegra_sdhci_probe(struct platform_device *pdev) { int rc; struct tegra_sdhci_platform_data *plat; struct sdhci_host *sdhci; struct tegra_sdhci_host *host; struct resource *res; int irq; void __iomem *ioaddr; plat = pdev->dev.platform_data; if (plat == NULL) return -ENXIO; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) return -ENODEV; irq = res->start; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) return -ENODEV; ioaddr = ioremap(res->start, res->end - res->start); sdhci = sdhci_alloc_host(&pdev->dev, sizeof(struct tegra_sdhci_host)); if (IS_ERR(sdhci)) { rc = PTR_ERR(sdhci); goto err_unmap; } host = sdhci_priv(sdhci); host->sdhci = sdhci; host->card_always_on = (plat->power_gpio == -1) ? 1 : 0; host->wp_gpio = plat->wp_gpio; host->clk = clk_get(&pdev->dev, plat->clk_id); if (IS_ERR(host->clk)) { rc = PTR_ERR(host->clk); goto err_free_host; } rc = clk_enable(host->clk); if (rc != 0) goto err_clkput; host->clk_enabled = 1; sdhci->hw_name = "tegra"; sdhci->ops = &tegra_sdhci_ops; sdhci->irq = irq; sdhci->ioaddr = ioaddr; sdhci->version = SDHCI_SPEC_200; sdhci->quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_SINGLE_POWER_WRITE | SDHCI_QUIRK_ENABLE_INTERRUPT_AT_BLOCK_GAP | SDHCI_QUIRK_BROKEN_WRITE_PROTECT | SDHCI_QUIRK_BROKEN_CTRL_HISPD | SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_8_BIT_DATA | SDHCI_QUIRK_NO_VERSION_REG | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | SDHCI_QUIRK_RUNTIME_DISABLE; if (plat->force_hs != 0) sdhci->quirks |= SDHCI_QUIRK_FORCE_HIGH_SPEED_MODE; #ifdef CONFIG_MMC_EMBEDDED_SDIO mmc_set_embedded_sdio_data(sdhci->mmc, &plat->cis, &plat->cccr, plat->funcs, plat->num_funcs); #endif if (host->card_always_on) sdhci->mmc->pm_flags |= MMC_PM_IGNORE_PM_NOTIFY; rc = sdhci_add_host(sdhci); if (rc) goto err_clk_disable; platform_set_drvdata(pdev, host); if (plat->cd_gpio != -1) { rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, mmc_hostname(sdhci->mmc), sdhci); if (rc) goto err_remove_host; } else if (plat->register_status_notify) { plat->register_status_notify( tegra_sdhci_status_notify_cb, sdhci); } if (plat->board_probe) plat->board_probe(pdev->id, sdhci->mmc); printk(KERN_INFO "sdhci%d: initialized irq %d ioaddr %p\n", pdev->id, sdhci->irq, sdhci->ioaddr); return 0; err_remove_host: sdhci_remove_host(sdhci, 1); err_clk_disable: clk_disable(host->clk); err_clkput: clk_put(host->clk); err_free_host: if (sdhci) sdhci_free_host(sdhci); err_unmap: iounmap(sdhci->ioaddr); return rc; }
static int sdhci_f_sdh30_probe(struct platform_device *pdev) { struct sdhci_host *host; struct device *dev = &pdev->dev; struct resource *res; int irq, ctrl = 0, ret = 0; struct f_sdhost_priv *priv; u32 reg = 0; irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(dev, "%s: no irq specified\n", __func__); return irq; } host = sdhci_alloc_host(dev, sizeof(struct f_sdhost_priv)); if (IS_ERR(host)) return PTR_ERR(host); priv = sdhci_priv(host); priv->dev = dev; host->quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | SDHCI_QUIRK_INVERTED_WRITE_PROTECT; host->quirks2 = SDHCI_QUIRK2_SUPPORT_SINGLE | SDHCI_QUIRK2_TUNING_WORK_AROUND; ret = mmc_of_parse(host->mmc); if (ret) goto err; platform_set_drvdata(pdev, host); sdhci_get_of_property(pdev); host->hw_name = "f_sdh30"; host->ops = &sdhci_f_sdh30_ops; host->irq = irq; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->ioaddr = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(host->ioaddr)) { ret = PTR_ERR(host->ioaddr); goto err; } priv->clk_iface = devm_clk_get(&pdev->dev, "iface"); if (IS_ERR(priv->clk_iface)) { ret = PTR_ERR(priv->clk_iface); goto err; } ret = clk_prepare_enable(priv->clk_iface); if (ret) goto err; priv->clk = devm_clk_get(&pdev->dev, "core"); if (IS_ERR(priv->clk)) { ret = PTR_ERR(priv->clk); goto err_clk; } ret = clk_prepare_enable(priv->clk); if (ret) goto err_clk; /* init vendor specific regs */ ctrl = sdhci_readw(host, F_SDH30_AHB_CONFIG); ctrl |= F_SDH30_SIN | F_SDH30_AHB_INCR_16 | F_SDH30_AHB_INCR_8 | F_SDH30_AHB_INCR_4; ctrl &= ~(F_SDH30_AHB_BIGED | F_SDH30_BUSLOCK_EN); sdhci_writew(host, ctrl, F_SDH30_AHB_CONFIG); reg = sdhci_readl(host, F_SDH30_ESD_CONTROL); sdhci_writel(host, reg & ~F_SDH30_EMMC_RST, F_SDH30_ESD_CONTROL); msleep(20); sdhci_writel(host, reg | F_SDH30_EMMC_RST, F_SDH30_ESD_CONTROL); reg = sdhci_readl(host, SDHCI_CAPABILITIES); if (reg & SDHCI_CAN_DO_8BIT) priv->vendor_hs200 = F_SDH30_EMMC_HS200; ret = sdhci_add_host(host); if (ret) goto err_add_host; return 0; err_add_host: clk_disable_unprepare(priv->clk); err_clk: clk_disable_unprepare(priv->clk_iface); err: sdhci_free_host(host); return ret; }
static int __devinit sdhci_probe(struct platform_device *pdev) { struct sdhci_host *host; struct resource *iomem; struct spear_sdhci *sdhci; int ret; BUG_ON(pdev == NULL); iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { ret = -ENOMEM; dev_dbg(&pdev->dev, "memory resource not defined\n"); goto err; } if (!request_mem_region(iomem->start, resource_size(iomem), "spear-sdhci")) { ret = -EBUSY; dev_dbg(&pdev->dev, "cannot request region\n"); goto err; } sdhci = kzalloc(sizeof(*sdhci), GFP_KERNEL); if (!sdhci) { ret = -ENOMEM; dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); goto err_kzalloc; } /* clk enable */ sdhci->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(sdhci->clk)) { ret = PTR_ERR(sdhci->clk); dev_dbg(&pdev->dev, "Error getting clock\n"); goto err_clk_get; } ret = clk_enable(sdhci->clk); if (ret) { dev_dbg(&pdev->dev, "Error enabling clock\n"); goto err_clk_enb; } /* overwrite platform_data */ sdhci->data = dev_get_platdata(&pdev->dev); pdev->dev.platform_data = sdhci; if (pdev->dev.parent) host = sdhci_alloc_host(pdev->dev.parent, 0); else host = sdhci_alloc_host(&pdev->dev, 0); if (IS_ERR(host)) { ret = PTR_ERR(host); dev_dbg(&pdev->dev, "error allocating host\n"); goto err_alloc_host; } host->hw_name = "sdhci"; host->ops = &sdhci_pltfm_ops; host->irq = platform_get_irq(pdev, 0); host->quirks = SDHCI_QUIRK_BROKEN_ADMA; host->ioaddr = ioremap(iomem->start, resource_size(iomem)); if (!host->ioaddr) { ret = -ENOMEM; dev_dbg(&pdev->dev, "failed to remap registers\n"); goto err_ioremap; } ret = sdhci_add_host(host); if (ret) { dev_dbg(&pdev->dev, "error adding host\n"); goto err_add_host; } platform_set_drvdata(pdev, host); /* * It is optional to use GPIOs for sdhci Power control & sdhci card * interrupt detection. If sdhci->data is NULL, then use original sdhci * lines otherwise GPIO lines. * If GPIO is selected for power control, then power should be disabled * after card removal and should be enabled when card insertion * interrupt occurs */ if (!sdhci->data) return 0; if (sdhci->data->card_power_gpio >= 0) { int val = 0; ret = gpio_request(sdhci->data->card_power_gpio, "sdhci"); if (ret < 0) { dev_dbg(&pdev->dev, "gpio request fail: %d\n", sdhci->data->card_power_gpio); goto err_pgpio_request; } if (sdhci->data->power_always_enb) val = sdhci->data->power_active_high; else val = !sdhci->data->power_active_high; ret = gpio_direction_output(sdhci->data->card_power_gpio, val); if (ret) { dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", sdhci->data->card_power_gpio); goto err_pgpio_direction; } gpio_set_value(sdhci->data->card_power_gpio, 1); } if (sdhci->data->card_int_gpio >= 0) { ret = gpio_request(sdhci->data->card_int_gpio, "sdhci"); if (ret < 0) { dev_dbg(&pdev->dev, "gpio request fail: %d\n", sdhci->data->card_int_gpio); goto err_igpio_request; } ret = gpio_direction_input(sdhci->data->card_int_gpio); if (ret) { dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", sdhci->data->card_int_gpio); goto err_igpio_direction; } ret = request_irq(gpio_to_irq(sdhci->data->card_int_gpio), sdhci_gpio_irq, IRQF_TRIGGER_LOW, mmc_hostname(host->mmc), pdev); if (ret) { dev_dbg(&pdev->dev, "gpio request irq fail: %d\n", sdhci->data->card_int_gpio); goto err_igpio_request_irq; } } return 0; err_igpio_request_irq: err_igpio_direction: if (sdhci->data->card_int_gpio >= 0) gpio_free(sdhci->data->card_int_gpio); err_igpio_request: err_pgpio_direction: if (sdhci->data->card_power_gpio >= 0) gpio_free(sdhci->data->card_power_gpio); err_pgpio_request: platform_set_drvdata(pdev, NULL); sdhci_remove_host(host, 1); err_add_host: iounmap(host->ioaddr); err_ioremap: sdhci_free_host(host); err_alloc_host: clk_disable(sdhci->clk); err_clk_enb: clk_put(sdhci->clk); err_clk_get: kfree(sdhci); err_kzalloc: release_mem_region(iomem->start, resource_size(iomem)); err: dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret); return ret; }
static int __devinit sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; struct resource *res; int ret, irq, ptr, clks; if (!pdata) { dev_err(dev, "no device data specified\n"); return -ENOENT; } 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; } host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c)); if (IS_ERR(host)) { dev_err(dev, "sdhci_alloc_host() failed\n"); return PTR_ERR(host); } pdata->sdhci_host = host; sc = sdhci_priv(host); platform_set_drvdata(pdev, host); sc->host = host; sc->pdev = pdev; sc->pdata = pdata; sc->clk_io = clk_get(dev, "hsmmc"); if (IS_ERR(sc->clk_io)) { dev_err(dev, "failed to get io clock\n"); ret = PTR_ERR(sc->clk_io); goto err_io_clk; } /* enable the local io clock and keep it running for the moment. */ clk_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; char *name = pdata->clocks[ptr]; if (name == NULL) continue; clk = clk_get(dev, name); if (IS_ERR(clk)) { dev_err(dev, "failed to get clock %s\n", name); continue; } clks++; sc->clk_bus[ptr] = clk; clk_enable(clk); dev_info(dev, "clock source %d: %s (%ld Hz)\n", ptr, name, clk_get_rate(clk)); } if (clks == 0) { dev_err(dev, "failed to find any bus clocks\n"); ret = -ENOENT; goto err_no_busclks; } sc->ioarea = request_mem_region(res->start, resource_size(res), mmc_hostname(host->mmc)); if (!sc->ioarea) { dev_err(dev, "failed to reserve register area\n"); ret = -ENXIO; goto err_req_regs; } host->ioaddr = ioremap_nocache(res->start, resource_size(res)); if (!host->ioaddr) { dev_err(dev, "failed to map registers\n"); ret = -ENXIO; goto err_req_regs; } /* Ensure we have minimal gpio selected CMD/CLK/Detect */ if (pdata->cfg_gpio) pdata->cfg_gpio(pdev, 0); sdhci_s3c_check_sclk(host); host->hw_name = "samsung-hsmmc"; host->ops = &sdhci_s3c_ops; host->quirks = 0; host->irq = irq; /* Setup quirks for the controller */ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; host->flags = SDHCI_USE_DMA; /* It seems we do not get an DATA transfer complete on non-busy * transfers, not sure if this is a problem with this specific * SDHCI block, or a missing configuration that needs to be set. */ host->quirks |= SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY; host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); host->quirks |= SDHCI_QUIRK_NO_HISPD_BIT; if (pdata->host_caps) host->mmc->caps = pdata->host_caps; else host->mmc->caps = 0; /* to add external irq as a card detect signal */ if (pdata->cfg_ext_cd) { pdata->cfg_ext_cd(); if (pdata->detect_ext_cd()) host->flags |= SDHCI_DEVICE_ALIVE; } ret = sdhci_add_host(host); if (ret) { dev_err(dev, "sdhci_add_host() failed\n"); goto err_add_host; } /* register external irq here (after all init is done) */ if (pdata->cfg_ext_cd) { ret = request_irq(pdata->ext_cd, sdhci_irq_cd, IRQF_SHARED, mmc_hostname(host->mmc), sc); if(ret) goto err_add_host; } return 0; err_add_host: release_resource(sc->ioarea); kfree(sc->ioarea); err_req_regs: for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); } err_no_busclks: clk_disable(sc->clk_io); clk_put(sc->clk_io); err_io_clk: sdhci_free_host(host); return ret; }
static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) { struct sdhci_pltfm_data *pdata = pdev->dev.platform_data; const struct platform_device_id *platid = platform_get_device_id(pdev); struct sdhci_host *host; struct resource *iomem; int ret; if (!pdata && platid && platid->driver_data) pdata = (void *)platid->driver_data; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { ret = -ENOMEM; goto err; } if (resource_size(iomem) < 0x100) dev_err(&pdev->dev, "Invalid iomem size. You may " "experience problems.\n"); if (pdev->dev.parent) host = sdhci_alloc_host(pdev->dev.parent, 0); else host = sdhci_alloc_host(&pdev->dev, 0); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } host->hw_name = "platform"; if (pdata && pdata->ops) host->ops = pdata->ops; else host->ops = &sdhci_pltfm_ops; if (pdata) host->quirks = pdata->quirks; host->irq = platform_get_irq(pdev, 0); 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_request; } host->ioaddr = ioremap(iomem->start, resource_size(iomem)); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); ret = -ENOMEM; goto err_remap; } if (pdata && pdata->init) { ret = pdata->init(host); if (ret) goto err_plat_init; } ret = sdhci_add_host(host); if (ret) goto err_add_host; platform_set_drvdata(pdev, host); return 0; err_add_host: if (pdata && pdata->exit) pdata->exit(host); err_plat_init: iounmap(host->ioaddr); err_remap: release_mem_region(iomem->start, resource_size(iomem)); err_request: sdhci_free_host(host); err: printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret); return ret; }
static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) { //HTC_CSP_START #if defined(CONFIG_MACH_ENDEAVORU) || defined(CONFIG_MACH_ENDEAVORTD) int addr = 0; #endif //HTC_CSP_END const struct platform_device_id *platid = platform_get_device_id(pdev); struct sdhci_pltfm_data *pdata; struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; struct resource *iomem; int ret; if (platid && platid->driver_data) pdata = (void *)platid->driver_data; else pdata = pdev->dev.platform_data; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iomem) { ret = -ENOMEM; goto err; } //HTC_CSP_START #if defined(CONFIG_MACH_ENDEAVORU) || defined(CONFIG_MACH_ENDEAVORTD) addr = iomem->start; //printk(KERN_INFO "start addr = 0x%x\n", addr); #endif //HTC_CSP_END if (resource_size(iomem) < 0x100) dev_err(&pdev->dev, "Invalid iomem size. You may " "experience problems.\n"); /* Some PCI-based MFD need the parent here */ if (pdev->dev.parent != &platform_bus) host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host)); else host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host)); if (IS_ERR(host)) { ret = PTR_ERR(host); goto err; } pltfm_host = sdhci_priv(host); host->hw_name = "platform"; if (pdata && pdata->ops) host->ops = pdata->ops; else host->ops = &sdhci_pltfm_ops; if (pdata) host->quirks = pdata->quirks; host->irq = platform_get_irq(pdev, 0); if (!request_mem_region(iomem->start, resource_size(iomem), mmc_hostname(host->mmc))) { dev_err(&pdev->dev, "cannot request region\n"); printk(KERN_INFO "%s: cannot request region\n", __func__); ret = -EBUSY; goto err_request; } host->ioaddr = ioremap(iomem->start, resource_size(iomem)); if (!host->ioaddr) { dev_err(&pdev->dev, "failed to remap registers\n"); ret = -ENOMEM; goto err_remap; } if (pdata && pdata->init) { ret = pdata->init(host, pdata); if (ret) goto err_plat_init; } ret = sdhci_add_host(host); if (ret) goto err_add_host; platform_set_drvdata(pdev, host); //HTC_CSP_START #if defined(CONFIG_MACH_ENDEAVORU) || defined(CONFIG_MACH_ENDEAVORTD) //printk(KERN_INFO "[SD] SdioDrv_probe pdev:0x%x mmc:0x%x mmc->index=%d pdev->resource[1].start=%x, addr=%x\n", // (int)pdev, host->mmc, host->mmc->index, pdev->resource[1].start, addr); if (addr == TEGRA_SDMMC3_BASE) { // printk(KERN_INFO "[SD] Save sdmmc3 dev, mmc\n"); // printk(KERN_INFO "[SD] SdioDrv_probe pdev:0x%x mmc:0x%x mmc->index=%d pdev->resource[1].start=%x, addr=%x\n", // (int)pdev, host->mmc, host->mmc->index, pdev->resource[1].start, addr); g_wlan_sdioDrv.pdev = pdev; g_wlan_sdioDrv.mmc = host->mmc; //TODO wlan_perf_lock = 0; } #endif //HTC_CSP_END return 0; err_add_host: if (pdata && pdata->exit) pdata->exit(host); err_plat_init: iounmap(host->ioaddr); err_remap: release_mem_region(iomem->start, resource_size(iomem)); err_request: sdhci_free_host(host); err: printk(KERN_ERR"Probing of sdhci-pltfm failed: %d\n", ret); return ret; }