Пример #1
0
/*
 * This function is scheduled by card detect interrupt handler.
 *
 * When card state is changed, this function call mmc_detect_change().
 * Upper layer of the mmc driver recognizes insertion/removal of the card
 * when mmc_detect_change() function is called.
 */
static void pollux_sdi_card_detect(struct work_struct *work)
{
	struct pollux_sdi_host *host;
	int delay = 0;
	int ret;

	host = container_of(work, struct pollux_sdi_host, card_detect_work);

	/*
	 * Initialize pollux SDI
	 */
	ret = sdmmc_init(host);
	if(ret != 0)
	{
		printk(KERN_ERR "pollux SD %d channel Initialize error\n", host->channel);
		return;
	}

	aprintk("Card detect state changed\n");
	if(host->cd_state == SD_INSERTED)
		delay = 200;
	else
		delay = 50;
 	
 	mmc_detect_change(host->mmc, msecs_to_jiffies(delay)); // number of jiffies to wait before queueing
}
Пример #2
0
static int diag_sd_init(char *argv[], const char *test_name, int verbose)
{
	int rval = 0;
	int slot, type;

	putstr("running SD ");
	putstr(test_name);
	putstr(" test ...\r\n");
	putstr("press any key to terminate!\r\n");

	if (strcmp(argv[0], "sd") == 0) {
		slot = SCARDMGR_SLOT_SD;
	} else if (strcmp(argv[0], "sdio") == 0) {
		slot = SCARDMGR_SLOT_SDIO;
	} else if (strcmp(argv[0], "sd2") == 0) {
		slot = SCARDMGR_SLOT_SD2;
	} else {
		slot = SCARDMGR_SLOT_SD;
	}

	if (strcmp(argv[1], "sd") == 0) {
		type = SDMMC_TYPE_SD;
	} else if (strcmp(argv[1], "sdhc") == 0) {
		type = SDMMC_TYPE_SDHC;
	} else if (strcmp(argv[1], "mmc") == 0) {
		type = SDMMC_TYPE_MMC;
	} else if (strcmp(argv[1], "MoviNAND") == 0) {
		type = SDMMC_TYPE_MOVINAND;
	} else {
		type = SDMMC_TYPE_AUTO;
	}

	timer_reset_count(TIMER2_ID);
	timer_enable(TIMER2_ID);
	rval = sdmmc_init(slot, type);
	timer_disable(TIMER2_ID);
	if (verbose) {
		putstr("\r\nInit takes: ");
		putdec(timer_get_count(TIMER2_ID));
		putstr("mS\r\n");
		putstr("SD clock: ");
		putdec(get_sd_freq_hz());
		putstr("Hz\r\n");
#if (SD_HAS_SDXC_CLOCK == 1)
		putstr("SDXC clock: ");
#if (CHIP_REV == A7S)
		putdec((u32)amb_get_sdio_clock_frequency(HAL_BASE_VP));
#else
		putdec((u32)amb_get_sdxc_clock_frequency(HAL_BASE_VP));
#endif
		putstr("Hz\r\n");
#endif
		putstr("total_secs: ");
		putdec(sdmmc_get_total_sectors());
		putstr("\r\n");
	}

	return rval;
}
Пример #3
0
int pollux_sdi_probe1(void)
{
	struct mmc_host 	*mmc;
	struct pollux_sdi_host 	*host;
	int ret = 0;
	struct resource *res;


	/* 
	 * Allocate memory space for host specific data structure 
	 */
	dprintk("sdi: 1\n");
	mmc = mmc_alloc_host(sizeof(struct pollux_sdi_host), &pbdev->dev);
	if (!mmc) {
		ret = -ENOMEM;
		goto probe_out;
	}
	
	printk(KERN_INFO "======================mmc: %p, private: %p, sizeof(private) = %d\n", mmc, &(mmc->private), sizeof(mmc->private) );


	/*
	 * Set host specific pointer to allocated space
	 */
	dprintk("sdi: 2\n");
	host = mmc_priv(mmc);
	
	printk(KERN_INFO "==================host: %p\n", host);


	/* 
	 * Initialize host specific data
	 */
	dprintk("sdi: 3\n");
	/* Set value of mmc structure */
	mmc->ops			= &pollux_sdi_ops;
	mmc->f_min			=   400000;
	mmc->f_max			= 33000000;
	mmc->caps			= MMC_CAP_4_BIT_DATA;	
		/*
		 * Set the maximum segment size.  Since we aren't doing DMA
		 * we are only limited by the data length register.
		 */
	mmc->max_seg_size	= 64 * 512;
	mmc->max_phys_segs	= 1;
	mmc->max_blk_size   = 2048;
	mmc->max_blk_count  = 64;
	mmc->ocr_avail = MMC_VDD_32_33;

	spin_lock_init( &host->complete_lock );

	/* 
	 * Set host specific structure 
	 */
	host->mmc				= mmc;
	host->dma				= 0;
	host->size				= 0;
	host->irq_cd			= 0;
	host->cd_state			= 0;
	host->clock				= 0;
	host->cd_state			= SD_INSERTED;
	host->readonly			= 0;
	host->bus_width 		= 0;
	
#if 0	
	aprintk("pdev.id = %d\n", pdev->id);
	host->channel           = 0; // sdmmc channel 0로 일단 세팅 
#else
	aprintk("pdev.id = %d\n", pbdev->id);
	host->channel           = pbdev->id; // sdmmc channel 0로 일단 세팅 
#endif	
	
	if( host->channel == 0 )
		strcpy(host->hname, POLLUX_SDI0_NAME);
	else
		strcpy(host->hname, POLLUX_SDI1_NAME);
	
	res = platform_get_resource(pbdev, IORESOURCE_MEM, 0); // MEM resource #0, Virtual memory of sdmmc base address
	if( res == 0 )
	{
		printk("POLLUX_SDI: error......get memory base resources\n");
		ret = -EINVAL;
		goto probe_out;
	}
	host->baseaddr = (u32)res->start;
	

	res = platform_get_resource(pbdev, IORESOURCE_IO, 0); // IO resource #0, card detection gpio number
	if( res == 0 )
	{
		printk("POLLUX_SDI: error......get resources 2\n");
		ret = -EINVAL;
		goto probe_out;
	}
	gprintk("cd gpio = %d\n", res->start );
	host->cdpin = (int)res->start;
	
	
	res = platform_get_resource(pbdev, IORESOURCE_IO, 1); // IO resource #1, write protection gpio number
	if( res == 0 )
	{
		printk("POLLUX_SDI: error......get resources 3\n");
		ret = -EINVAL;
		goto probe_out;
	}
	gprintk("wp gpio = %d\n", res->start );
	host->wppin = (int)res->start;


	/*
	 * Get SD/MMC controller IRQ
	 */
	dprintk("sdi: 5 \n");	
	host->irq = platform_get_irq(pbdev, 0);
	if (host->irq == 0) 
	{
		printk(KERN_INFO "failed to get interrupt resouce.\n");
		ret = -EINVAL;
		goto probe_out;
	}
	
	/*
	 * Initialize GPIO prototype.
	 * GPIO pin is used for card detection and write protection state detection 
	 */
	host->irq_cd = platform_get_irq(pbdev, 1);
	aprintk("SDI___________________IRQ_CD = %d\n", host->irq_cd );
	if( host->irq_cd == 0 ) 
	{
		printk(KERN_INFO "failed to get card detection interrupt resource.\n");
		ret = -EINVAL;
		goto probe_out;
	}


	/*
	 * Initialize SD controller prototype  from sdmmc.cpp of wince bsp
	 */
	
	MES_SDHC_Initialize(); //mes_sdhc.c 의 해당 레지스터 block 초기화 루틴, 두번 호출이 안되도록 세팅이 되어 있음.
	
#if 1	
	/*
	 * Initialize MP2530F SDI
	 */
	ret = sdmmc_init(host);
	if(ret != 0)
	{
		ret = -EINVAL;
		goto probe_out;
	}
#endif	

//return 0; // ghcstop for debugging



	/*
	 * Register handler for host interupt
	 */
	dprintk("sdi: 6 - SD IRQ number is %d\n", host->irq);
	if(request_irq(host->irq, pollux_sdi_irq, 0, POLLUX_SDI0_NAME, host)) 
	{
		printk(KERN_INFO "failed to request sdi interrupt.\n");
		ret = -ENOENT;
		goto probe_out;
	}


	/*
	 * Read current card state 
	 */

	host->readonly =  pollux_gpio_getpin(host->wppin); // low면 write protected, high면 write enable ==> low active
	host->cd_state = !pollux_gpio_getpin(host->cdpin); // low면 Inserted, high면 ejected. ==> 그러므로 !로 뒤집음
	
	
	gprintk("host->readonly = %d, host->cd_state = %d, pollux_get_gpio_func(host->cdpin) = %d\n", host->readonly, host->cd_state, pollux_get_gpio_func(host->cdpin) );

	/*
	 * Register interrupt handler for card detection 
	 */
	INIT_WORK(&host->card_detect_work, pollux_sdi_card_detect);
#if 1
	if( host->cd_state ) // inserted
		set_irq_type(host->irq_cd, IRQT_RISING);
	else
		set_irq_type( host->irq_cd, IRQT_FALLING);
		
		
	//if(request_irq(host->irq_cd, pollux_sdi_irq_cd, 0, POLLUX_SDI0_NAME, host)) 
	if(request_irq(host->irq_cd, pollux_sdi_irq_cd, 0, host->hname, host)) 
	{
		printk(KERN_WARNING "failed to request card detect interrupt.\n" );
		ret = -ENOENT;
		goto probe_free_irq;
	}
#endif


	/*
	 * Register MP2530F host driver
	 */
	dprintk("sdi: 8\n");
	if((ret = mmc_add_host(mmc)))
	{
		printk(KERN_INFO "failed to add mmc host.\n");
		goto free_resource;
	}

	platform_set_drvdata(pbdev, mmc);

	printk(KERN_INFO "initialization done.\n");
	
	
	//mmc_detect_change(host->mmc, 100); // number of jiffies to wait before queueing	

	return ret;

free_resource:
    free_irq(host->irq_cd, host);	/* unregister card detection interrupt handler */

probe_free_irq:
 	free_irq(host->irq, host);	/* unregister host controller interrupt handler */

probe_out:
	return ret;
}