static void ak98_group_pin_config(void) { #ifdef CONFIG_EIGHT_DATA_LINE ak98_group_config(ePIN_AS_SDMMC1); #elif defined CONFIG_FOUR_DATA_LINE ak98_group_config(ePIN_AS_SDMMC2); #endif }
void spi_pin_setup(struct ak98_spi_info *spi, int enable) { if (enable) { ak98_group_config(ePIN_AS_SPI1); } else { ak98_setpin_as_gpio(AK98_GPIO_76); ak98_setpin_as_gpio(AK98_GPIO_77); ak98_setpin_as_gpio(AK98_GPIO_78); ak98_setpin_as_gpio(AK98_GPIO_79); } }
static void ak98_sdio_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct ak98_mci_host *host = mmc_priv(mmc); hydbg("bus_mode=%d,bus_width=%d\n", ios->bus_mode, ios->bus_width); /* ak98 (and SD spec) don't support MMC_BUSMODE_OPENDRAIN */ host->bus_mode = ios->bus_mode; host->bus_width = ios->bus_width; //printk("%ubits(%u); ", (unsigned)1 >> (host->bus_width), host->bus_width); /* we can't control external power supply unit */ switch (ios->power_mode) { case MMC_POWER_UP: PK("MMC_POWER_UP; "); break; case MMC_POWER_ON: PK("MMC_POWER_ON; "); break; case MMC_POWER_OFF: PK("MMC_POWER_OFF; "); break; } ak98_group_config(ePIN_AS_SDIO); if (ios->clock != host->bus_clkrate) { #ifdef CONFIG_CPU_FREQ down(&host->freq_lock); #endif ak98sdio_set_clk(host, &mmc->ios); #ifdef CONFIG_CPU_FREQ up(&host->freq_lock); #endif } /* no matter high-speed mode or not, ak88 mci use the same timing */ //printk("ios->clock(%dkhz), host->bus_clkrate(%lukhz), host->asic_clkrate(%lumhz), MMC_CLK_CTRL(0x%08x)\n", // ios->clock/1000, host->bus_clkrate/1000, host->asic_clkrate/1000000, readl(host->base + AK98MCICLOCK)); }
static int __devinit ak98_sdio_probe(struct platform_device *pdev) { struct ak98_mci_platform_data *plat = pdev->dev.platform_data; struct ak98_mci_host *host; struct mmc_host *mmc; struct resource *res; int irq; int ret; /* must have platform data */ if (!plat) { ret = -EINVAL; goto out; } PK("%s\n", __func__); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); PK("res: %x, %u", res->start, resource_size(res)); res = request_mem_region(res->start, resource_size(res), DRIVER_NAME); if (!res) { ret = -EBUSY; goto out; } PK("res: %x, %u\n", res->start, resource_size(res)); mmc = mmc_alloc_host(sizeof(struct ak98_mci_host), &pdev->dev); if (!mmc) { ret = -ENOMEM; goto out; } host = mmc_priv(mmc); host->mmc = mmc; host->gpio_wp = -ENOSYS; host->gpio_cd = -ENOSYS; ak98_sdio_reset(); host->clk = clk_get(&pdev->dev, "sdio_clk"); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); host->clk = NULL; goto host_free; } ret = clk_enable(host->clk); if (ret) goto clk_free; host->plat = plat; host->asic_clkrate = ak98_get_asic_clk(); host->base = ioremap(res->start, resource_size(res)); if (!host->base) { ret = -ENOMEM; goto clk_disable; } PK("asic_clkrate: %luhz,host->base=0x%x\n", host->asic_clkrate,host->base); mmc->ops = &ak98_mci_ops; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->caps = MMC_CAP_4_BIT_DATA; #if 0 mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; #endif mmc->caps |= MMC_CAP_SDIO_IRQ; // mmc->caps |= MMC_CAP_NEEDS_POLL; mmc->f_min = host->asic_clkrate / (255+1 + 255+1); mmc->f_max = host->asic_clkrate / (0+1 + 0+1); mmc->f_max = mmc->f_max < fmax ? mmc->f_max : fmax; /* * We can do SGIO */ mmc->max_hw_segs = 16; mmc->max_phys_segs = NR_SG; /* * Since we only have a 16-bit data length register, we must * ensure that we don't exceed 2^16-1 bytes in a single request. */ mmc->max_req_size = 65535; /* * Set the maximum segment size. Since we aren't doing DMA * (yet) we are only limited by the data length register. */ mmc->max_seg_size = mmc->max_req_size; #if 0 /* * Block size can be up to 2048 bytes, but must be a power of two. */ mmc->max_blk_size = 2048; #else /* as l2 fifo limit to 512 bytes */ mmc->max_blk_size = 512; #endif /* * No limit on the number of blocks transferred. */ mmc->max_blk_count = mmc->max_req_size; spin_lock_init(&host->lock); ak98_group_config(ePIN_AS_SDIO); writel(MCI_ENABLE|MCI_FAIL_TRIGGER, host->base + AK98MCICLOCK); PK("%s: MCICLOCK: 0x%08x\n", __func__, readl(host->base + AK98MCICLOCK)); writel(0, host->base + AK98MCIMASK); PK("request irq %i\n", irq); ret = request_irq(irq, ak98_sdio_irq, IRQF_DISABLED, DRIVER_NAME " (cmd)", host); if (ret) goto unmap; host->irq_mci = irq; if(plat->gpio_cd >= 0) { host->gpio_cd = plat->gpio_cd; ak98_gpio_cfgpin(host->gpio_cd, AK98_GPIO_DIR_INPUT); ak98_gpio_pulldown(host->gpio_cd,AK98_PULLDOWN_DISABLE); ak98_gpio_pullup(host->gpio_cd, AK98_PULLUP_ENABLE); setup_timer(&host->detect_timer, ak98_sdio_detect_change, (unsigned long)host); irq = ak98_gpio_to_irq(host->gpio_cd); ret = request_irq(irq, ak98_sdio_card_detect_irq, IRQF_DISABLED, DRIVER_NAME " cd", host); printk("request gpio irq ret = %d, irq=%d", ret, irq); if (ret) goto irq_free; host->irq_cd = irq; host->irq_cd_type = IRQ_TYPE_LEVEL_LOW; } if(plat->gpio_wp >= 0) { host->gpio_wp = plat->gpio_wp; ak98_gpio_cfgpin(host->gpio_wp, AK98_GPIO_DIR_INPUT); ak98_gpio_pullup(host->gpio_wp, AK98_PULLUP_ENABLE); ak98_gpio_pulldown(host->gpio_wp,AK98_PULLDOWN_DISABLE); } platform_set_drvdata(pdev, mmc); ret = ak98sdio_cpufreq_register(host); if (ret) { goto irq_free; } ret = mmc_add_host(mmc); if (ret) { goto cpufreq_free; } PK(KERN_INFO "%s: ak98MCI at 0x%016llx irq %d\n", mmc_hostname(mmc), (unsigned long long)res->start, host->irq_mci); return 0; cpufreq_free: PK("ERR cpufreq_free\n"); ak98sdio_cpufreq_deregister(host); irq_free: PK("ERR irq_free\n"); free_irq(host->irq_mci, host); unmap: PK("ERR unmap\n"); iounmap(host->base); clk_disable: PK("ERR clk_disable\n"); clk_disable(host->clk); clk_free: PK("ERR clk_free\n"); clk_put(host->clk); host_free: PK("ERR host_free\n"); mmc_free_host(mmc); out: PK("ERR out\n"); return ret; }