Esempio n. 1
0
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

}
Esempio n. 2
0
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);
	}
}
Esempio n. 3
0
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));
}
Esempio n. 4
0
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;
}