static void sdhci_s3c_set_ios(struct sdhci_host *host, struct mmc_ios *ios) { struct sdhci_s3c *ourhost = to_s3c(host); struct s3c_sdhci_platdata *pdata = ourhost->pdata; int width; sdhci_s3c_check_sclk(host); if (ios->power_mode != MMC_POWER_OFF) { switch (ios->bus_width) { case MMC_BUS_WIDTH_4: width = 4; break; case MMC_BUS_WIDTH_1: width = 1; break; default: BUG(); } if (pdata->cfg_gpio) pdata->cfg_gpio(ourhost->pdev, width); } if (pdata->cfg_card) { pdata->cfg_card(ourhost->pdev, host->ioaddr, ios, host->mmc->card); pdata->rx_cfg = 0; pdata->tx_cfg = 0; } }
/** * sdhci_s3c_get_max_clk - callback to get maximum clock frequency. * @host: The SDHCI host instance. * * Callback to return the maximum clock rate acheivable by the controller. */ static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) { struct sdhci_s3c *ourhost = to_s3c(host); struct clk *busclk; unsigned int rate, max; int clk; if(host->quirks & SDHCI_QUIRK_BROKEN_CLOCK_DIVIDER) { rate = clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX); return rate; } /* note, a reset will reset the clock source */ sdhci_s3c_check_sclk(host); for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) { busclk = ourhost->clk_bus[clk]; if (!busclk) continue; rate = clk_get_rate(busclk); if (rate > max) max = rate; } return max; }
static void sdhci_s3c_set_ios(struct sdhci_host *host, struct mmc_ios *ios) { struct sdhci_s3c *ourhost = to_s3c(host); struct s3c_sdhci_platdata *pdata = ourhost->pdata; int width; u8 tmp; sdhci_s3c_check_sclk(host); if (ios->power_mode != MMC_POWER_OFF) { switch (ios->bus_width) { case MMC_BUS_WIDTH_8: width = 8; tmp = readb(host->ioaddr + SDHCI_HOST_CONTROL); writeb(tmp | SDHCI_S3C_CTRL_8BITBUS, host->ioaddr + SDHCI_HOST_CONTROL); break; case MMC_BUS_WIDTH_4: width = 4; break; case MMC_BUS_WIDTH_1: width = 1; break; default: BUG(); } if (pdata->cfg_gpio) pdata->cfg_gpio(ourhost->pdev, width); } #ifdef CONFIG_S5PC110_DEMPSEY_BOARD if (pdata->translate_vdd) pdata->translate_vdd(ourhost->pdev, ios->vdd); #endif /* CONFIG_MACH_S5PC110_ARIES */ if (pdata->cfg_card) { pdata->cfg_card(ourhost->pdev, host->ioaddr, ios, host->mmc->card); pdata->rx_cfg = 0; pdata->tx_cfg = 0; } }
static void sdhci_s3c_set_ios(struct sdhci_host *host, struct mmc_ios *ios) { struct sdhci_s3c *ourhost = to_s3c(host); struct s3c_sdhci_platdata *pdata = ourhost->pdata; int width; u8 tmp; sdhci_s3c_check_sclk(host); if (ios->power_mode != MMC_POWER_OFF) { switch (ios->bus_width) { case MMC_BUS_WIDTH_8: width = 8; tmp = readb(host->ioaddr + SDHCI_HOST_CONTROL); writeb(tmp | SDHCI_S3C_CTRL_8BITBUS, host->ioaddr + SDHCI_HOST_CONTROL); break; case MMC_BUS_WIDTH_4: width = 4; break; case MMC_BUS_WIDTH_1: width = 1; break; default: BUG(); } if (width > pdata->max_width) { if (pdata->cfg_gpio) { pdata->cfg_gpio(ourhost->pdev, width); } } } if (pdata->cfg_card) { pdata->cfg_card(ourhost->pdev, host->ioaddr, ios, host->mmc->card); pdata->rx_cfg = 0; pdata->tx_cfg = 0; } }
static void sdhci_s3c_set_ios(struct sdhci_host *host, struct mmc_ios *ios) { struct sdhci_s3c *ourhost = to_s3c(host); struct s3c_sdhci_platdata *pdata = ourhost->pdata; int width; u8 tmp; sdhci_s3c_check_sclk(host); if (ios->power_mode != MMC_POWER_OFF) { switch (ios->bus_width) { case MMC_BUS_WIDTH_8: width = 8; tmp = readb(host->ioaddr + SDHCI_HOST_CONTROL); writeb(tmp | SDHCI_CTRL_8BITBUS, host->ioaddr + SDHCI_HOST_CONTROL); printk("%s: Enable 8Bit Data bus. ## ", mmc_hostname(host->mmc)); break; case MMC_BUS_WIDTH_4: width = 4; break; case MMC_BUS_WIDTH_1: width = 1; break; default: BUG(); } if (pdata->cfg_gpio) pdata->cfg_gpio(ourhost->pdev, width); } if (pdata->cfg_card) pdata->cfg_card(ourhost->pdev, host->ioaddr, ios, host->mmc->card); mdelay(1); }
static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host) { struct sdhci_s3c *ourhost = to_s3c(host); struct clk *busclk; unsigned int rate, max; int clk; /* note, a reset will reset the clock source */ sdhci_s3c_check_sclk(host); for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) { busclk = ourhost->clk_bus[clk]; if (!busclk) continue; rate = clk_get_rate(busclk); if (rate > max) max = rate; } return max; }
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; }