From a86175882adcffc20fc9ef03633b18de592c8228 Mon Sep 17 00:00:00 2001 From: xbw Date: Sat, 22 Oct 2011 11:19:06 +0800 Subject: [PATCH] Optimize the powe up and down of wifi and SDcard module --- arch/arm/mach-rk29/board-rk29-ddr3sdk.c | 327 ++++++++++++++++++++++-- arch/arm/mach-rk29/include/mach/board.h | 1 + drivers/mmc/core/core.c | 14 +- drivers/mmc/core/sdio.c | 4 + drivers/mmc/host/Kconfig | 25 +- drivers/mmc/host/rk29_sdmmc.c | 324 +++++++++++++++-------- include/linux/mmc/host.h | 3 + 7 files changed, 572 insertions(+), 126 deletions(-) mode change 100644 => 100755 drivers/mmc/core/sdio.c diff --git a/arch/arm/mach-rk29/board-rk29-ddr3sdk.c b/arch/arm/mach-rk29/board-rk29-ddr3sdk.c index 8499e1e44caa..b4a4239912a6 100755 --- a/arch/arm/mach-rk29/board-rk29-ddr3sdk.c +++ b/arch/arm/mach-rk29/board-rk29-ddr3sdk.c @@ -1835,23 +1835,256 @@ static struct platform_device rk29_device_pwm_regulator = { /***************************************************************************************** * SDMMC devices *****************************************************************************************/ +#if !defined(CONFIG_SDMMC_RK29_OLD) +static void rk29_sdmmc_gpio_open(int device_id, int on) +{ + switch(device_id) + { + case 0://mmc0 + { + #ifdef CONFIG_SDMMC0_RK29 + if(on) + { + gpio_direction_output(RK29_PIN1_PD0,GPIO_HIGH);//set mmc0-clk to high + gpio_direction_output(RK29_PIN1_PD1,GPIO_HIGH);//set mmc0-cmd to high. + gpio_direction_output(RK29_PIN1_PD2,GPIO_HIGH);//set mmc0-data0 to high. + gpio_direction_output(RK29_PIN1_PD3,GPIO_HIGH);//set mmc0-data1 to high. + gpio_direction_output(RK29_PIN1_PD4,GPIO_HIGH);//set mmc0-data2 to high. + gpio_direction_output(RK29_PIN1_PD5,GPIO_HIGH);//set mmc0-data3 to high. + + mdelay(30); + } + else + { + rk29_mux_api_set(GPIO1D0_SDMMC0CLKOUT_NAME, GPIO1H_GPIO1_D0); + gpio_request(RK29_PIN1_PD0, "mmc0-clk"); + gpio_direction_output(RK29_PIN1_PD0,GPIO_LOW);//set mmc0-clk to low. + + rk29_mux_api_set(GPIO1D1_SDMMC0CMD_NAME, GPIO1H_GPIO1_D1); + gpio_request(RK29_PIN1_PD1, "mmc0-cmd"); + gpio_direction_output(RK29_PIN1_PD1,GPIO_LOW);//set mmc0-cmd to low. + + rk29_mux_api_set(GPIO1D2_SDMMC0DATA0_NAME, GPIO1H_GPIO1D2); + gpio_request(RK29_PIN1_PD2, "mmc0-data0"); + gpio_direction_output(RK29_PIN1_PD2,GPIO_LOW);//set mmc0-data0 to low. + + rk29_mux_api_set(GPIO1D3_SDMMC0DATA1_NAME, GPIO1H_GPIO1D3); + gpio_request(RK29_PIN1_PD3, "mmc0-data1"); + gpio_direction_output(RK29_PIN1_PD3,GPIO_LOW);//set mmc0-data1 to low. + + rk29_mux_api_set(GPIO1D4_SDMMC0DATA2_NAME, GPIO1H_GPIO1D4); + gpio_request(RK29_PIN1_PD4, "mmc0-data2"); + gpio_direction_output(RK29_PIN1_PD4,GPIO_LOW);//set mmc0-data2 to low. + + rk29_mux_api_set(GPIO1D5_SDMMC0DATA3_NAME, GPIO1H_GPIO1D5); + gpio_request(RK29_PIN1_PD5, "mmc0-data3"); + gpio_direction_output(RK29_PIN1_PD5,GPIO_LOW);//set mmc0-data3 to low. + + mdelay(30); + } + #endif + } + break; + + case 1://mmc1 + { + #ifdef CONFIG_SDMMC1_RK29 + if(on) + { + gpio_direction_output(RK29_PIN1_PC7,GPIO_HIGH);//set mmc1-clk to high + gpio_direction_output(RK29_PIN1_PC2,GPIO_HIGH);//set mmc1-cmd to high. + gpio_direction_output(RK29_PIN1_PC3,GPIO_HIGH);//set mmc1-data0 to high. + gpio_direction_output(RK29_PIN1_PC4,GPIO_HIGH);//set mmc1-data1 to high. + gpio_direction_output(RK29_PIN1_PC5,GPIO_HIGH);//set mmc1-data2 to high. + gpio_direction_output(RK29_PIN1_PC6,GPIO_HIGH);//set mmc1-data3 to high. + mdelay(100); + } + else + { + rk29_mux_api_set(GPIO1C7_SDMMC1CLKOUT_NAME, GPIO1H_GPIO1C7); + gpio_request(RK29_PIN1_PC7, "mmc1-clk"); + gpio_direction_output(RK29_PIN1_PC7,GPIO_LOW);//set mmc1-clk to low. + + rk29_mux_api_set(GPIO1C2_SDMMC1CMD_NAME, GPIO1H_GPIO1C2); + gpio_request(RK29_PIN1_PC2, "mmc1-cmd"); + gpio_direction_output(RK29_PIN1_PC2,GPIO_LOW);//set mmc1-cmd to low. + + rk29_mux_api_set(GPIO1C3_SDMMC1DATA0_NAME, GPIO1H_GPIO1C3); + gpio_request(RK29_PIN1_PC3, "mmc1-data0"); + gpio_direction_output(RK29_PIN1_PC3,GPIO_LOW);//set mmc1-data0 to low. + + mdelay(100); + } + #endif + } + break; + + case 2: //mmc2 + break; + + default: + break; + } +} + +static void rk29_sdmmc_set_iomux_mmc0(unsigned int bus_width) +{ + switch (bus_width) + { + + case 1://SDMMC_CTYPE_4BIT: + { + rk29_mux_api_set(GPIO1D3_SDMMC0DATA1_NAME, GPIO1H_SDMMC0_DATA1); + rk29_mux_api_set(GPIO1D4_SDMMC0DATA2_NAME, GPIO1H_SDMMC0_DATA2); + rk29_mux_api_set(GPIO1D5_SDMMC0DATA3_NAME, GPIO1H_SDMMC0_DATA3); + } + break; + + case 0x10000://SDMMC_CTYPE_8BIT: + break; + case 0xFFFF: //gpio_reset + { + rk29_mux_api_set(GPIO5D5_SDMMC0PWREN_NAME, GPIO5H_GPIO5D5); + gpio_request(RK29_PIN5_PD5,"sdmmc-power"); + gpio_direction_output(RK29_PIN5_PD5,GPIO_HIGH); //power-off + + rk29_sdmmc_gpio_open(0, 0); + + gpio_direction_output(RK29_PIN5_PD5,GPIO_LOW); //power-on + + rk29_sdmmc_gpio_open(0, 1); + } + break; + + default: //case 0://SDMMC_CTYPE_1BIT: + { + rk29_mux_api_set(GPIO1D1_SDMMC0CMD_NAME, GPIO1H_SDMMC0_CMD); + rk29_mux_api_set(GPIO1D0_SDMMC0CLKOUT_NAME, GPIO1H_SDMMC0_CLKOUT); + rk29_mux_api_set(GPIO1D2_SDMMC0DATA0_NAME, GPIO1H_SDMMC0_DATA0); + + rk29_mux_api_set(GPIO1D3_SDMMC0DATA1_NAME, GPIO1H_GPIO1D3); + gpio_request(RK29_PIN1_PD3, "mmc0-data1"); + gpio_direction_output(RK29_PIN1_PD3,GPIO_HIGH); + + rk29_mux_api_set(GPIO1D4_SDMMC0DATA2_NAME, GPIO1H_GPIO1D4); + gpio_request(RK29_PIN1_PD4, "mmc0-data2"); + gpio_direction_output(RK29_PIN1_PD4,GPIO_HIGH); + + rk29_mux_api_set(GPIO1D5_SDMMC0DATA3_NAME, GPIO1H_GPIO1D5); + gpio_request(RK29_PIN1_PD5, "mmc0-data3"); + gpio_direction_output(RK29_PIN1_PD5,GPIO_HIGH); + } + break; + } +} + +static void rk29_sdmmc_set_iomux_mmc1(unsigned int bus_width) +{ +#if 0 + switch (bus_width) + { + + case 1://SDMMC_CTYPE_4BIT: + { + rk29_mux_api_set(GPIO1C2_SDMMC1CMD_NAME, GPIO1H_SDMMC1_CMD); + rk29_mux_api_set(GPIO1C7_SDMMC1CLKOUT_NAME, GPIO1H_SDMMC1_CLKOUT); + rk29_mux_api_set(GPIO1C3_SDMMC1DATA0_NAME, GPIO1H_SDMMC1_DATA0); + rk29_mux_api_set(GPIO1C4_SDMMC1DATA1_NAME, GPIO1H_SDMMC1_DATA1); + rk29_mux_api_set(GPIO1C5_SDMMC1DATA2_NAME, GPIO1H_SDMMC1_DATA2); + rk29_mux_api_set(GPIO1C6_SDMMC1DATA3_NAME, GPIO1H_SDMMC1_DATA3); + } + break; + + case 0x10000://SDMMC_CTYPE_8BIT: + break; + case 0xFFFF: + { + rk29_sdmmc_gpio_open(1, 0); + rk29_sdmmc_gpio_open(1, 1); + } + break; + + default: //case 0://SDMMC_CTYPE_1BIT: + { + rk29_mux_api_set(GPIO1C2_SDMMC1CMD_NAME, GPIO1H_SDMMC1_CMD); + rk29_mux_api_set(GPIO1C7_SDMMC1CLKOUT_NAME, GPIO1H_SDMMC1_CLKOUT); + rk29_mux_api_set(GPIO1C3_SDMMC1DATA0_NAME, GPIO1H_SDMMC1_DATA0); + + rk29_mux_api_set(GPIO1C4_SDMMC1DATA1_NAME, GPIO1H_GPIO1C4); + gpio_request(RK29_PIN1_PC4, "mmc1-data1"); + gpio_direction_output(RK29_PIN1_PC4,GPIO_HIGH); + + rk29_mux_api_set(GPIO1C5_SDMMC1DATA2_NAME, GPIO1H_GPIO1C5); + gpio_request(RK29_PIN1_PC5, "mmc1-data2"); + gpio_direction_output(RK29_PIN1_PC5,GPIO_HIGH); + + rk29_mux_api_set(GPIO1C6_SDMMC1DATA3_NAME, GPIO1H_GPIO1C6); + gpio_request(RK29_PIN1_PC6, "mmc1-data3"); + gpio_direction_output(RK29_PIN1_PC6,GPIO_HIGH); + + } + break; + } +#else + rk29_mux_api_set(GPIO1C2_SDMMC1CMD_NAME, GPIO1H_SDMMC1_CMD); + rk29_mux_api_set(GPIO1C7_SDMMC1CLKOUT_NAME, GPIO1H_SDMMC1_CLKOUT); + rk29_mux_api_set(GPIO1C3_SDMMC1DATA0_NAME, GPIO1H_SDMMC1_DATA0); + rk29_mux_api_set(GPIO1C4_SDMMC1DATA1_NAME, GPIO1H_SDMMC1_DATA1); + rk29_mux_api_set(GPIO1C5_SDMMC1DATA2_NAME, GPIO1H_SDMMC1_DATA2); + rk29_mux_api_set(GPIO1C6_SDMMC1DATA3_NAME, GPIO1H_SDMMC1_DATA3); + +#endif +} + +static void rk29_sdmmc_set_iomux_mmc2(unsigned int bus_width) +{ + ;// +} + + +static void rk29_sdmmc_set_iomux(int device_id, unsigned int bus_width) +{ + switch(device_id) + { + case 0: + #ifdef CONFIG_SDMMC0_RK29 + rk29_sdmmc_set_iomux_mmc0(bus_width); + #endif + break; + case 1: + #ifdef CONFIG_SDMMC1_RK29 + rk29_sdmmc_set_iomux_mmc1(bus_width); + #endif + break; + case 2: + rk29_sdmmc_set_iomux_mmc2(bus_width); + break; + default: + break; + } +} + +#endif + +#ifdef CONFIG_WIFI_CONTROL_FUNC +static int rk29sdk_wifi_status(struct device *dev); +static int rk29sdk_wifi_status_register(void (*callback)(int card_presend, void *dev_id), void *dev_id); +#endif + #ifdef CONFIG_SDMMC0_RK29 static int rk29_sdmmc0_cfg_gpio(void) { - rk29_mux_api_set(GPIO1D1_SDMMC0CMD_NAME, GPIO1H_SDMMC0_CMD); +#ifdef CONFIG_SDMMC_RK29_OLD + rk29_mux_api_set(GPIO1D1_SDMMC0CMD_NAME, GPIO1H_SDMMC0_CMD); rk29_mux_api_set(GPIO1D0_SDMMC0CLKOUT_NAME, GPIO1H_SDMMC0_CLKOUT); rk29_mux_api_set(GPIO1D2_SDMMC0DATA0_NAME, GPIO1H_SDMMC0_DATA0); rk29_mux_api_set(GPIO1D3_SDMMC0DATA1_NAME, GPIO1H_SDMMC0_DATA1); rk29_mux_api_set(GPIO1D4_SDMMC0DATA2_NAME, GPIO1H_SDMMC0_DATA2); rk29_mux_api_set(GPIO1D5_SDMMC0DATA3_NAME, GPIO1H_SDMMC0_DATA3); - -#ifdef CONFIG_SDMMC_RK29_OLD + rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_GPIO2A2); -#else - rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_SDMMC0_DETECT_N);//Modifyed by xbw. -#endif - rk29_mux_api_set(GPIO5D5_SDMMC0PWREN_NAME, GPIO5H_GPIO5D5); ///GPIO5H_SDMMC0_PWR_EN); ///GPIO5H_GPIO5D5); + rk29_mux_api_set(GPIO5D5_SDMMC0PWREN_NAME, GPIO5H_GPIO5D5); ///GPIO5H_SDMMC0_PWR_EN); ///GPIO5H_GPIO5D5); gpio_request(RK29_PIN5_PD5,"sdmmc"); #if 0 gpio_set_value(RK29_PIN5_PD5,GPIO_HIGH); @@ -1861,9 +2094,16 @@ static int rk29_sdmmc0_cfg_gpio(void) gpio_direction_output(RK29_PIN5_PD5,GPIO_LOW); #endif -#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) +#else + rk29_sdmmc_set_iomux(0, 0xFFFF); + + rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_SDMMC0_DETECT_N);//Modifyed by xbw. + + #if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) gpio_request(SDMMC0_WRITE_PROTECT_PIN,"sdmmc-wp"); gpio_direction_input(SDMMC0_WRITE_PROTECT_PIN); + #endif + #endif return 0; @@ -1876,6 +2116,11 @@ struct rk29_sdmmc_platform_data default_sdmmc0_data = { MMC_VDD_33_34|MMC_VDD_34_35| MMC_VDD_35_36), .host_caps = (MMC_CAP_4_BIT_DATA|MMC_CAP_MMC_HIGHSPEED|MMC_CAP_SD_HIGHSPEED), .io_init = rk29_sdmmc0_cfg_gpio, + +#if !defined(CONFIG_SDMMC_RK29_OLD) + .set_iomux = rk29_sdmmc_set_iomux, +#endif + .dma_name = "sd_mmc", #ifdef CONFIG_SDMMC0_USE_DMA .use_dma = 1, @@ -1896,6 +2141,7 @@ struct rk29_sdmmc_platform_data default_sdmmc0_data = { #define CONFIG_SDMMC1_USE_DMA static int rk29_sdmmc1_cfg_gpio(void) { +#if defined(CONFIG_SDMMC_RK29_OLD) rk29_mux_api_set(GPIO1C2_SDMMC1CMD_NAME, GPIO1H_SDMMC1_CMD); rk29_mux_api_set(GPIO1C7_SDMMC1CLKOUT_NAME, GPIO1H_SDMMC1_CLKOUT); rk29_mux_api_set(GPIO1C3_SDMMC1DATA0_NAME, GPIO1H_SDMMC1_DATA0); @@ -1904,17 +2150,19 @@ static int rk29_sdmmc1_cfg_gpio(void) rk29_mux_api_set(GPIO1C6_SDMMC1DATA3_NAME, GPIO1H_SDMMC1_DATA3); //rk29_mux_api_set(GPIO1C0_UART0CTSN_SDMMC1DETECTN_NAME, GPIO1H_SDMMC1_DETECT_N); +#else + #if defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT) gpio_request(SDMMC1_WRITE_PROTECT_PIN,"sdio-wp"); gpio_direction_input(SDMMC1_WRITE_PROTECT_PIN); #endif + +#endif + return 0; } -#ifdef CONFIG_WIFI_CONTROL_FUNC -static int rk29sdk_wifi_status(struct device *dev); -static int rk29sdk_wifi_status_register(void (*callback)(int card_presend, void *dev_id), void *dev_id); -#endif + #define RK29SDK_WIFI_SDIO_CARD_DETECT_N RK29_PIN1_PD6 @@ -1922,15 +2170,28 @@ struct rk29_sdmmc_platform_data default_sdmmc1_data = { .host_ocr_avail = (MMC_VDD_25_26|MMC_VDD_26_27|MMC_VDD_27_28|MMC_VDD_28_29| MMC_VDD_29_30|MMC_VDD_30_31|MMC_VDD_31_32| MMC_VDD_32_33|MMC_VDD_33_34), + +#if !defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD) .host_caps = (MMC_CAP_4_BIT_DATA|MMC_CAP_SDIO_IRQ| MMC_CAP_MMC_HIGHSPEED|MMC_CAP_SD_HIGHSPEED), +#else + .host_caps = (MMC_CAP_4_BIT_DATA|MMC_CAP_MMC_HIGHSPEED|MMC_CAP_SD_HIGHSPEED), +#endif + .io_init = rk29_sdmmc1_cfg_gpio, + +#if !defined(CONFIG_SDMMC_RK29_OLD) + .set_iomux = rk29_sdmmc_set_iomux, +#endif + .dma_name = "sdio", #ifdef CONFIG_SDMMC1_USE_DMA .use_dma = 1, #else .use_dma = 0, #endif + +#if !defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD) #ifdef CONFIG_WIFI_CONTROL_FUNC .status = rk29sdk_wifi_status, .register_status_notify = rk29sdk_wifi_status_register, @@ -1943,11 +2204,21 @@ struct rk29_sdmmc_platform_data default_sdmmc1_data = { .write_prt = SDMMC1_WRITE_PROTECT_PIN, #else .write_prt = INVALID_GPIO, -#endif +#endif -}; +#else +//for wifi develop board + .detect_irq = INVALID_GPIO, + .enable_sd_wakeup = 0, #endif +}; +#endif ////endif--#ifdef CONFIG_SDMMC1_RK29 + + +int rk29sdk_wifi_power_state = 0; +int rk29sdk_bt_power_state = 0; + #ifdef CONFIG_WIFI_CONTROL_FUNC #define RK29SDK_WIFI_BT_GPIO_POWER_N RK29_PIN5_PD6 #define RK29SDK_WIFI_GPIO_RESET_N RK29_PIN6_PC0 @@ -1956,8 +2227,6 @@ struct rk29_sdmmc_platform_data default_sdmmc1_data = { static int rk29sdk_wifi_cd = 0; /* wifi virtual 'card detect' status */ static void (*wifi_status_cb)(int card_present, void *dev_id); static void *wifi_status_cb_devid; -int rk29sdk_wifi_power_state = 0; -int rk29sdk_bt_power_state = 0; static int rk29sdk_wifi_status(struct device *dev) { @@ -1996,6 +2265,22 @@ static int rk29sdk_wifi_bt_gpio_control_init(void) gpio_direction_output(RK29SDK_WIFI_GPIO_RESET_N, GPIO_LOW); gpio_direction_output(RK29SDK_BT_GPIO_RESET_N, GPIO_LOW); + #if defined(CONFIG_SDMMC1_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + + rk29_mux_api_set(GPIO1C4_SDMMC1DATA1_NAME, GPIO1H_GPIO1C4); + gpio_request(RK29_PIN1_PC4, "mmc1-data1"); + gpio_direction_output(RK29_PIN1_PC4,GPIO_LOW);//set mmc1-data1 to low. + + rk29_mux_api_set(GPIO1C5_SDMMC1DATA2_NAME, GPIO1H_GPIO1C5); + gpio_request(RK29_PIN1_PC5, "mmc1-data2"); + gpio_direction_output(RK29_PIN1_PC5,GPIO_LOW);//set mmc1-data2 to low. + + rk29_mux_api_set(GPIO1C6_SDMMC1DATA3_NAME, GPIO1H_GPIO1C6); + gpio_request(RK29_PIN1_PC6, "mmc1-data3"); + gpio_direction_output(RK29_PIN1_PC6,GPIO_LOW);//set mmc1-data3 to low. + + rk29_sdmmc_gpio_open(1, 0); //added by xbw at 2011-10-13 + #endif pr_info("%s: init finished\n",__func__); return 0; @@ -2006,12 +2291,22 @@ static int rk29sdk_wifi_power(int on) pr_info("%s: %d\n", __func__, on); if (on){ gpio_set_value(RK29SDK_WIFI_BT_GPIO_POWER_N, GPIO_HIGH); + + #if defined(CONFIG_SDMMC1_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + rk29_sdmmc_gpio_open(1, 1); //added by xbw at 2011-10-13 + #endif + gpio_set_value(RK29SDK_WIFI_GPIO_RESET_N, GPIO_HIGH); mdelay(100); pr_info("wifi turn on power\n"); }else{ if (!rk29sdk_bt_power_state){ gpio_set_value(RK29SDK_WIFI_BT_GPIO_POWER_N, GPIO_LOW); + + #if defined(CONFIG_SDMMC1_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + rk29_sdmmc_gpio_open(1, 0); //added by xbw at 2011-10-13 + #endif + mdelay(100); pr_info("wifi shut off power\n"); }else diff --git a/arch/arm/mach-rk29/include/mach/board.h b/arch/arm/mach-rk29/include/mach/board.h index 039cc173cb9b..7cec44db21f5 100755 --- a/arch/arm/mach-rk29/include/mach/board.h +++ b/arch/arm/mach-rk29/include/mach/board.h @@ -139,6 +139,7 @@ struct rk29_sdmmc_platform_data { char dma_name[8]; int (*io_init)(void); int (*io_deinit)(void); + void (*set_iomux)(int device_id, unsigned int bus_width);//added by xbw at 2011-10-13 int (*status)(struct device *); int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id); int detect_irq; diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 314b4ae171a4..20f9b82b0d53 100755 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -208,7 +208,8 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) ) { - waittime = wait_for_completion_timeout(&complete,HZ*2); //sdio; for cmd dead. Modifyed by xbw at 2011-06-02 + multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1; + waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //sdio; for cmd dead. Modifyed by xbw at 2011-06-02 } else { @@ -221,7 +222,7 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) multi += (datasize%unit)?1:0; multi = (multi>0) ? multi : 1; multi += (mrq->cmd->retries>0)?1:0; - waittime = wait_for_completion_timeout(&complete,HZ*5*multi); //It should be longer than bottom driver's time,due to the sum of two cmd time. + waittime = wait_for_completion_timeout(&complete,HZ*7*multi); //It should be longer than bottom driver's time,due to the sum of two cmd time. //modifyed by xbw at 2011-10-08 // //example: @@ -230,7 +231,8 @@ void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq) } else { - waittime = wait_for_completion_timeout(&complete,HZ*2); + multi = (mrq->cmd->retries>0)?mrq->cmd->retries:1; + waittime = wait_for_completion_timeout(&complete,HZ*7*multi); } } @@ -1164,8 +1166,9 @@ void mmc_rescan(struct work_struct *work) */ //mmc_send_if_cond(host, host->ocr_avail); //deleted by xbw@2011-04-09 - +#if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) if( strncmp( mmc_hostname(host) ,"mmc0" , strlen("mmc0")) ){ +#endif /* * First we search for SDIO... */ @@ -1187,8 +1190,9 @@ void mmc_rescan(struct work_struct *work) extend_wakelock = 1; goto out; } +#if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) } - +#endif /* * ...then normal SD... diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c old mode 100644 new mode 100755 index 7280140bfea7..5e98695bae99 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -647,6 +647,10 @@ int sdio_reset_comm(struct mmc_card *card) printk("%s():\n", __func__); mmc_claim_host(host); + +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) + host->sdmmc_host_hw_init(mmc_priv(host)); //added by xbw , at 2011-10-18 +#endif mmc_go_idle(host); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 85df780a5e0a..f7e229dd632d 100755 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -27,16 +27,21 @@ if SDMMC_RK29 config SDMMC0_RK29_WRITE_PROTECT bool "Write-protect for SDMMC0" + default n depends on SDMMC0_RK29 help You will add the feature of write-protect for sdmmc-card if you say Yes. Please note that this feature requires hardware support. -# config EMMC_RK29 -# tristate "RK29 EMMC controller support(sdmmc)" -# default y -# depends on SDMMC0_RK29 + +# config USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD +# depends on SDMMC0_RK29 +# bool "Switch the driver SDMMC0 for the debug of wifi_develop_board." +# default n # help -# This supports the use of the EMMC controller on Rk29 processors. +# In order to debug the Wifi development board using SD interface, +# we can switch the driver SDMMC0. + + config SDMMC1_RK29 tristate "RK29 SDMMC1 controller support(sdio)" default y @@ -45,10 +50,20 @@ if SDMMC_RK29 This supports the use of the SDMMC1 controller on Rk29 processors. config SDMMC1_RK29_WRITE_PROTECT bool "Write-protect for SDMMC1" + default n depends on SDMMC1_RK29 help You will add the feature of write-protect for sdio-card if you say Yes. Please note that this feature requires hardware support. + +# config USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD +# depends on SDMMC1_RK29 +# bool "Switch the driver SDMMC1 for the debug of wifi_develop_board." +# default n +# help +# In order to debug the Wifi development board using SD interface, +# we can switch the driver SDMMC1. + endif config MMC_ARMMMCI diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index 216353d21309..107c5dfe3dcf 100755 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -52,7 +52,7 @@ #define RK29_SDMMC_xbw_Debug 0 #if RK29_SDMMC_xbw_Debug -int debug_level = 4; +int debug_level = 5; #define xbwprintk(n, format, arg...) \ if (n <= debug_level) { \ printk(format,##arg); \ @@ -67,16 +67,22 @@ int debug_level = 4; #define RK29_SDMMC_INTMASK_USEIO (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR ) -#define RK29_SDMMC_SEND_START_TIMEOUT 1000 //The time interval from the time SEND_CMD to START_CMD_BIT cleared. +#define RK29_SDMMC_SEND_START_TIMEOUT 3000 //The time interval from the time SEND_CMD to START_CMD_BIT cleared. #define RK29_ERROR_PRINTK_INTERVAL 200 //The time interval between the two printk for the same error. -#define RK29_SDMMC_WAIT_DTO_INTERNVAL 1000 //The time interval from the CMD_DONE_INT to DTO_INT -#define RK29_SDMMC_REMOVAL_DELAY 1000 //The time interval from the CD_INT to detect_timer react. +#define RK29_SDMMC_WAIT_DTO_INTERNVAL 4500 //The time interval from the CMD_DONE_INT to DTO_INT +#define RK29_SDMMC_REMOVAL_DELAY 2000 //The time interval from the CD_INT to detect_timer react. -#define RK29_SDMMC_VERSION "Ver.2.11 The last modify date is 2011-10-08,modifyed by XBW." +#define RK29_SDMMC_VERSION "Ver.2.13 The last modify date is 2011-10-19,modifyed by XBW." +#if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) #define RK29_CTRL_SDMMC_ID 0 //mainly used by SDMMC #define RK29_CTRL_SDIO1_ID 1 //mainly used by sdio-wifi #define RK29_CTRL_SDIO2_ID 2 //mainly used by sdio-card +#else +#define RK29_CTRL_SDMMC_ID 5 +#define RK29_CTRL_SDIO1_ID 1 +#define RK29_CTRL_SDIO2_ID 2 +#endif #define RK29_SDMMC_NOTIFY_REMOVE_INSERTION /* use sysfs to notify the removal or insertion of sd-card*/ //#define RK29_SDMMC_LIST_QUEUE /* use list-queue for multi-card*/ @@ -206,6 +212,8 @@ struct rk29_sdmmc { int write_protect; #endif + void (*set_iomux)(int device_id, unsigned int bus_width); + }; @@ -225,6 +233,7 @@ static struct rk29_sdmmc *globalSDhost[3]; static void rk29_sdmmc_start_error(struct rk29_sdmmc *host); static int rk29_sdmmc_clear_fifo(struct rk29_sdmmc *host); +int rk29_sdmmc_hw_init(void *data); static void rk29_sdmmc_write(unsigned char __iomem *regbase, unsigned int regOff,unsigned int val) { @@ -287,7 +296,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a //envalue the address of host base on input-parameter. if( !strncmp(buf,"sd-" , strlen("sd-")) ) { - host = (struct rk29_sdmmc *)globalSDhost[RK29_CTRL_SDMMC_ID]; + host = (struct rk29_sdmmc *)globalSDhost[0]; if(!host) { printk("%s..%d.. fail to call progress_store because the host is null. ==xbw==\n",__FUNCTION__,__LINE__); @@ -329,6 +338,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a * insert card state-change: No-Media ==> Pending ==> Idle-Unmounted ==> Checking ==>Mounted * remove card state-change: Unmounting ==> Idle-Unmounted ==> No-Media */ + #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) if(RK29_CTRL_SDMMC_ID == host->pdev->id) { if(!strncmp(buf, "sd-Unmounting", strlen("sd-Unmounting"))) @@ -366,6 +376,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a else if( !strncmp(buf,"sd-reset" , strlen("sd-reset")) ) { printk(".%d.. Now manual reset for SDMMC0. ====xbw[%s]====\n",__LINE__, host->dma_name); + rk29_sdmmc_hw_init(host); mmc_detect_change(host->mmc, 0); } else if( !strncmp(buf, "sd-regs", strlen("sd-regs"))) @@ -375,6 +386,22 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a } } + #else + if(0 == host->pdev->id) + { + if( !strncmp(buf,"sd-reset" , strlen("sd-reset")) ) + { + printk(".%d.. Now manual reset for SDMMC0. ====xbw[%s]====\n",__LINE__, host->dma_name); + rk29_sdmmc_hw_init(host); + mmc_detect_change(host->mmc, 0); + } + else if( !strncmp(buf, "sd-regs", strlen("sd-regs"))) + { + printk(".%d.. Now printk the register of SDMMC0. ====xbw[%s]====\n",__LINE__, host->dma_name); + rk29_sdmmc_regs_printk(host); + } + } + #endif else if(RK29_CTRL_SDIO1_ID == host->pdev->id) { if( !strncmp(buf, "sdio1-regs", strlen("sdio1-regs"))) @@ -385,6 +412,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a else if( !strncmp(buf,"sdio1-reset" , strlen("sdio1-reset")) ) { printk(".%d.. Now manual reset for SDMMC1. ====xbw[%s]====\n",__LINE__, host->dma_name); + rk29_sdmmc_hw_init(host); mmc_detect_change(host->mmc, 0); } } @@ -398,6 +426,7 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a else if( !strncmp(buf,"sdio2-reset" , strlen("sdio2-reset")) ) { printk(".%d.. Now manual reset for SDMMC2. ====xbw[%s]====\n",__LINE__, host->dma_name); + rk29_sdmmc_hw_init(host); mmc_detect_change(host->mmc, 0); } } @@ -414,7 +443,7 @@ struct kobj_attribute mmc_reset_attrs = { .attr = { .name = "rescan", - .mode = 0777}, + .mode = 0766}, .show = NULL, .store = rk29_sdmmc_progress_store, }; @@ -702,7 +731,7 @@ void rk29_sdmmc_set_frq(struct rk29_sdmmc *host) static int rk29_sdmmc_start_command(struct rk29_sdmmc *host, struct mmc_command *cmd, u32 cmd_flags) { - int tmo = RK29_SDMMC_SEND_START_TIMEOUT*3; + int tmo = RK29_SDMMC_SEND_START_TIMEOUT*10;//wait 60ms cycle. host->cmd = cmd; host->old_cmd = cmd->opcode; @@ -1292,10 +1321,10 @@ static void rk29_sdmmc_submit_data(struct rk29_sdmmc *host, struct mmc_data *dat static int sdmmc_send_cmd_start(struct rk29_sdmmc *host, unsigned int cmd) { - int tmo = RK29_SDMMC_SEND_START_TIMEOUT*3;; + int tmo = RK29_SDMMC_SEND_START_TIMEOUT*10;//wait 60ms cycle. rk29_sdmmc_write(host->regs, SDMMC_CMD, SDMMC_CMD_START | cmd); - while (--tmo && readl(host->regs + SDMMC_CMD) & SDMMC_CMD_START) + while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START)) { udelay(2); } @@ -1315,16 +1344,41 @@ static int sdmmc_send_cmd_start(struct rk29_sdmmc *host, unsigned int cmd) static int rk29_sdmmc_get_cd(struct mmc_host *mmc) { struct rk29_sdmmc *host = mmc_priv(mmc); - u32 cdetect; + u32 cdetect=1; -#ifdef CONFIG_PM - if(host->gpio_det == INVALID_GPIO) - return 1; -#endif + switch(host->pdev->id) + { + case 0: + { + #ifdef CONFIG_PM + if(host->gpio_det == INVALID_GPIO) + return 1; + #endif - cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT); + cdetect = rk29_sdmmc_read(host->regs, SDMMC_CDETECT); + + cdetect = (cdetect & SDMMC_CARD_DETECT_N)?0:1; + + break; + } - return (cdetect & SDMMC_CARD_DETECT_N)?0:1; + case 1: + { + #if defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD) + cdetect = 1; + #else + cdetect = test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags)?1:0; + #endif + break; + } + + default: + cdetect = 1; + break; + + } + + return cdetect; } @@ -1400,7 +1454,26 @@ int rk29_sdmmc_reset_controller(struct rk29_sdmmc *host) } else { - rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO); + if(0== host->pdev->id) + { + #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO); + #else + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA); + #endif + } + else if(1== host->pdev->id) + { + #if !defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD) + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO); + #else + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA); + #endif + } + else + { + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO); + } } } else @@ -1411,7 +1484,26 @@ int rk29_sdmmc_reset_controller(struct rk29_sdmmc *host) } else { - rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO | SDMMC_INT_SDIO); + if(0== host->pdev->id) + { + #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO | SDMMC_INT_SDIO); + #else + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO); + #endif + } + else if(1== host->pdev->id) + { + #if !defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD) + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO | SDMMC_INT_SDIO); + #else + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEIO); + #endif + } + else + { + rk29_sdmmc_write(host->regs, SDMMC_INTMASK,RK29_SDMMC_INTMASK_USEDMA | SDMMC_INT_SDIO); + } } } @@ -1436,7 +1528,7 @@ static int rk29_sdmmc_control_clock(struct rk29_sdmmc *host, bool enable) tmo = 1000; while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START)) { - cpu_relax(); + udelay(1);//cpu_relax(); } if(!tmo) { @@ -1482,7 +1574,7 @@ static int rk29_sdmmc_control_clock(struct rk29_sdmmc *host, bool enable) return SDM_SUCCESS; Error_exit: - printk("\n%s....%d.. control clock fail!!! Enable=%d, ret=%d ===xbw[%s]====\n",\ + printk("\n%s....%d.. control clock fail!!! Enable=%d, ret=0x%x ===xbw[%s]====\n",\ __FILE__,__LINE__,enable,ret, host->dma_name); return ret; @@ -1543,7 +1635,7 @@ int rk29_sdmmc_change_clk_div(struct rk29_sdmmc *host, u32 freqHz) tmo = 1000; while (--tmo && (rk29_sdmmc_read(host->regs, SDMMC_CMD) & SDMMC_CMD_START)) { - cpu_relax(); + udelay(1);//cpu_relax(); } if(!tmo) { @@ -1580,19 +1672,24 @@ int rk29_sdmmc_change_clk_div(struct rk29_sdmmc *host, u32 freqHz) SetFreq_error: - printk("%s..%s..%d.. change division fail, ret=%d !!! ====xbw[%s]====\n",\ - __FILE__, __FUNCTION__,__LINE__,ret, host->dma_name); + printk("%s..%d.. change division fail, errorStep=0x%x,ret=%d !!! ====xbw[%s]====\n",\ + __FILE__, __LINE__,host->errorstep,ret, host->dma_name); return ret; } - - -static int rk29_sdmmc_hw_init(struct rk29_sdmmc *host) +int rk29_sdmmc_hw_init(void *data) { + struct rk29_sdmmc *host = (struct rk29_sdmmc *)data; + + //set the iomux + host->ctype = SDMMC_CTYPE_1BIT; + host->set_iomux(host->pdev->id, host->ctype); + /* reset controller */ rk29_sdmmc_reset_controller(host); + rk29_sdmmc_change_clk_div(host, FOD_FREQ); return SDM_SUCCESS; @@ -1600,23 +1697,6 @@ static int rk29_sdmmc_hw_init(struct rk29_sdmmc *host) -int rk29_sdmmc_set_iomux(struct rk29_sdmmc *host) -{ - #if 0 - switch (host->busWidth) - { - case - rk29_mux_api_set(GPIO1D1_SDMMC0CMD_NAME, GPIO1H_SDMMC0_CMD); - rk29_mux_api_set(GPIO1D0_SDMMC0CLKOUT_NAME, GPIO1H_SDMMC0_CLKOUT); - rk29_mux_api_set(GPIO1D2_SDMMC0DATA0_NAME, GPIO1H_SDMMC0_DATA0); - rk29_mux_api_set(GPIO1D3_SDMMC0DATA1_NAME, GPIO1H_SDMMC0_DATA1); - rk29_mux_api_set(GPIO1D4_SDMMC0DATA2_NAME, GPIO1H_SDMMC0_DATA2); - } - #endif - - return 0; -} - int rk29_sdmmc_set_buswidth(struct rk29_sdmmc *host) { //int ret; @@ -1630,7 +1710,8 @@ int rk29_sdmmc_set_buswidth(struct rk29_sdmmc *host) default: return SDM_PARAM_ERROR; } - rk29_sdmmc_set_iomux(host); + + host->set_iomux(host->pdev->id, host->ctype); /* Set the current bus width */ rk29_sdmmc_write(host->regs, SDMMC_CTYPE, host->ctype); @@ -1891,6 +1972,7 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) __FUNCTION__, __LINE__, host->dma_name, host->dma_name); host->state = STATE_IDLE; + rk29_sdmmc_write(host->regs, SDMMC_RINTSTS, 0xFFFFFFFF); spin_unlock_irqrestore(&host->lock, iflags); mmc_request_done(mmc, mrq); return; @@ -1949,27 +2031,26 @@ static void rk29_sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) { host->old_cmd = mrq->cmd->opcode; host->error_times = 0; - } + } } } else { host->old_cmd = mrq->cmd->opcode; host->error_times = 0; + + if(!test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags)) + { + host->state = STATE_IDLE; + mrq->cmd->error = -ENOMEDIUM; + spin_unlock_irqrestore(&host->lock, iflags); + mmc_request_done(mmc, mrq); + return; + } + } - #if 1 - if(0 == host->mmc->doneflag) - { - host->state = STATE_IDLE; - } - - if(host->state != STATE_IDLE) - { - printk("%s..%d..state Error! ,old_state=%d, OldCMD=%d ,NewCMD%2d,arg=0x%x ===xbw[%s]===\n", \ - __FUNCTION__, __LINE__, host->state, host->cmd->opcode,mrq->cmd->opcode,mrq->cmd->arg, host->dma_name); - } - + #if 1 host->new_mrq = mrq; spin_unlock_irqrestore(&host->lock, iflags); @@ -2021,25 +2102,28 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) spin_lock_irqsave(&host->lock, iflags); - /* - * Waiting SDIO controller to be IDLE. - */ - while (timeout-- > 0) - { - value = rk29_sdmmc_read(host->regs, SDMMC_STATUS); - if ((value & SDMMC_STAUTS_DATA_BUSY) == 0 &&(value & SDMMC_CMD_FSM_MASK) == SDMMC_CMD_FSM_IDLE) - { - break; - } - - mdelay(1); - } - if (timeout <= 0) - { - printk("%s..%d...Waiting for SDMMC%d controller to be IDLE timeout.==xbw[%s]===\n", \ - __FUNCTION__, __LINE__, host->pdev->id, host->dma_name); + if(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags) || (RK29_CTRL_SDMMC_ID == host->pdev->id)) + { + /* + * Waiting SDIO controller to be IDLE. + */ + while (timeout-- > 0) + { + value = rk29_sdmmc_read(host->regs, SDMMC_STATUS); + if ((value & SDMMC_STAUTS_DATA_BUSY) == 0 &&(value & SDMMC_CMD_FSM_MASK) == SDMMC_CMD_FSM_IDLE) + { + break; + } + + mdelay(1); + } + if (timeout <= 0) + { + printk("%s..%d...Waiting for SDMMC%d controller to be IDLE timeout.==xbw[%s]===\n", \ + __FUNCTION__, __LINE__, host->pdev->id, host->dma_name); - goto out; + goto out; + } } //if(host->bus_mode != ios->power_mode) @@ -2088,7 +2172,9 @@ static void rk29_sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } - + if(!(test_bit(RK29_SDMMC_CARD_PRESENT, &host->flags) || (RK29_CTRL_SDIO1_ID != host->pdev->id))) + goto out; //exit the set_ios directly if the SDIO is not present. + if(host->ctype != ios->bus_width) { switch (ios->bus_width) @@ -2128,25 +2214,41 @@ out: static int rk29_sdmmc_get_ro(struct mmc_host *mmc) { struct rk29_sdmmc *host = mmc_priv(mmc); - -#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT) - int ret; - - if(INVALID_GPIO == host->write_protect) - ret = 0;//no write-protect - else - ret = gpio_get_value(host->write_protect)?1:0; - - xbwprintk(7,"%s..%d.. write_prt_pin=%d, get_ro=%d ===xbw[%s]===\n",\ - __FUNCTION__, __LINE__,host->write_protect, ret, host->dma_name); + int ret=0; + + switch(host->pdev->id) + { + case 0: + { + #if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) || defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT) + if(INVALID_GPIO == host->write_protect) + ret = 0;//no write-protect + else + ret = gpio_get_value(host->write_protect)?1:0; + + xbwprintk(7,"%s..%d.. write_prt_pin=%d, get_ro=%d ===xbw[%s]===\n",\ + __FUNCTION__, __LINE__,host->write_protect, ret, host->dma_name); + + #else + u32 wrtprt = rk29_sdmmc_read(host->regs, SDMMC_WRTPRT); + + ret = (wrtprt & SDMMC_WRITE_PROTECT)?1:0; + #endif + + break; + } + case 1: + ret = 0;//no write-protect + break; + + default: + ret = 0; + break; + } + return ret; - -#else - u32 wrtprt = rk29_sdmmc_read(host->regs, SDMMC_WRTPRT); - - return (wrtprt & SDMMC_WRITE_PROTECT)?1:0; -#endif + } @@ -2231,6 +2333,8 @@ static const struct mmc_host_ops rk29_sdmmc_ops[] = { { .request = rk29_sdmmc_request, .set_ios = rk29_sdmmc_set_ios, + .get_ro = rk29_sdmmc_get_ro, + .get_cd = rk29_sdmmc_get_cd, .enable_sdio_irq = rk29_sdmmc_enable_sdio_irq, .init_card = rk29_sdmmc_init_card, }, @@ -2719,7 +2823,7 @@ static inline void rk29_sdmmc_cmd_interrupt(struct rk29_sdmmc *host, u32 status) multi += ((rk29_sdmmc_read(host->regs, SDMMC_BYTCNT)%unit) ? 1 :0 ); multi = (multi>0) ? multi : 1; multi += (host->cmd->retries>2)?2:host->cmd->retries; - mod_timer(&host->DTO_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_WAIT_DTO_INTERNVAL*multi)); + mod_timer(&host->DTO_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_WAIT_DTO_INTERNVAL*multi));//max wait 8s larger } smp_wmb(); @@ -2927,12 +3031,14 @@ static void rk29_sdmmc1_check_status(unsigned long data) unsigned int status; status = pdata->status(mmc_dev(host->mmc)); - + + pr_info("%s: slot status change detected(%d-%d)\n",mmc_hostname(host->mmc), host->oldstatus, status); + if (status ^ host->oldstatus) - { - pr_info("%s: slot status change detected(%d-%d)\n",mmc_hostname(host->mmc), host->oldstatus, status); + { if (status) { + rk29_sdmmc_hw_init(host); set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(200)); } @@ -2949,7 +3055,7 @@ static void rk29_sdmmc1_check_status(unsigned long data) static void rk29_sdmmc1_status_notify_cb(int card_present, void *dev_id) { struct rk29_sdmmc *host = dev_id; - printk(KERN_INFO "%s, card_present %d\n", mmc_hostname(host->mmc), card_present); + //printk(KERN_INFO "%s, card_present %d\n", mmc_hostname(host->mmc), card_present); rk29_sdmmc1_check_status((unsigned long)host); } @@ -3007,6 +3113,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) #ifdef CONFIG_PM host->gpio_det = pdata->detect_irq; #endif + host->set_iomux = pdata->set_iomux; if(pdata->io_init) pdata->io_init(); @@ -3062,6 +3169,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) mmc->caps = pdata->host_caps; mmc->re_initialized_flags = 1; mmc->doneflag = 1; + mmc->sdmmc_host_hw_init = rk29_sdmmc_hw_init; /* * We can do SGIO @@ -3186,6 +3294,22 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) clear_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); } } + else + { + #if defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) + if(0== host->pdev->id) + { + set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); + } + #endif + + #if defined(CONFIG_USE_SDMMC1_FOR_WIFI_DEVELOP_BOARD) + if(1== host->pdev->id) + { + set_bit(RK29_SDMMC_CARD_PRESENT, &host->flags); + } + #endif + } /* sdmmc1 wifi card slot status initially */ @@ -3206,7 +3330,7 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) #ifdef RK29_SDMMC_NOTIFY_REMOVE_INSERTION globalSDhost[pdev->id] = (struct rk29_sdmmc *)host; - if(RK29_CTRL_SDMMC_ID== host->pdev->id) + if(0== host->pdev->id) { rk29_sdmmc_progress_add_attr(pdev); } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 4125ef55faee..2b3d83ba6a9c 100755 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -203,8 +203,11 @@ struct mmc_host { #define MMC_BUSRESUME_MANUAL_RESUME (1 << 0) #define MMC_BUSRESUME_NEEDS_RESUME (1 << 1) +#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD) unsigned int re_initialized_flags; //in order to begin the rescan ; added by xbw@2011-04-07 unsigned int doneflag;//added by xbw at 2011-08-27 + int (*sdmmc_host_hw_init)(void *data); +#endif unsigned int sdio_irqs; struct task_struct *sdio_irq_thread; -- 2.34.1