/* * 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 }
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; }
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; }