From ae2f1851ee9c68f043c249bcadabaaa8af4a8553 Mon Sep 17 00:00:00 2001 From: xbw Date: Tue, 13 Mar 2012 11:40:16 +0800 Subject: [PATCH] add the SDMMC driver into RK30-SDK --- arch/arm/mach-rk30/board-rk30-sdk.c | 546 ++++++++++++++++++++++++++++ drivers/mmc/core/mmc.c | 12 +- drivers/mmc/host/rk29_sdmmc.c | 106 +++++- drivers/mmc/host/rk29_sdmmc.h | 28 ++ 4 files changed, 681 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-rk30/board-rk30-sdk.c b/arch/arm/mach-rk30/board-rk30-sdk.c index 28e997fcf6af..dfd2ceafddaa 100755 --- a/arch/arm/mach-rk30/board-rk30-sdk.c +++ b/arch/arm/mach-rk30/board-rk30-sdk.c @@ -872,6 +872,552 @@ static void __init rk30_i2c_register_board_info(void) } //end of i2c + +/************************************************************************************************** + * SDMMC devices, include the module of SD,MMC,sdio,and some BT.noted by xbw at 2012-03-05 +**************************************************************************************************/ +#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) +#define SDMMC0_WRITE_PROTECT_PIN RK30_PIN3_PB7 //According to your own project to set the value of write-protect-pin. +#endif + + +#if defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT) +#define SDMMC1_WRITE_PROTECT_PIN RK30_PIN3_PC7 //According to your own project to set the value of write-protect-pin. +#endif + +#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(GPIO3B_GPIO3B0,GPIO_HIGH);//set mmc0-clk to high + gpio_direction_output(GPIO3B_GPIO3B1,GPIO_HIGH);// set mmc0-cmd to high. + gpio_direction_output(GPIO3B_GPIO3B2,GPIO_HIGH);//set mmc0-data0 to high. + gpio_direction_output(GPIO3B_GPIO3B3,GPIO_HIGH);//set mmc0-data1 to high. + gpio_direction_output(GPIO3B_GPIO3B4,GPIO_HIGH);//set mmc0-data2 to high. + gpio_direction_output(GPIO3B_GPIO3B5,GPIO_HIGH);//set mmc0-data3 to high. + + mdelay(30); + } + else + { + rk30_mux_api_set(GPIO3B0_SDMMC0CLKOUT_NAME, GPIO3B_GPIO3B0); + gpio_request(RK30_PIN3_PB0, "mmc0-clk"); + gpio_direction_output(RK30_PIN3_PB0,GPIO_LOW);//set mmc0-clk to low. + + rk30_mux_api_set(GPIO3B1_SDMMC0CMD_NAME, GPIO3B_GPIO3B1); + gpio_request(RK30_PIN3_PB1, "mmc0-cmd"); + gpio_direction_output(RK30_PIN3_PB1,GPIO_LOW);//set mmc0-cmd to low. + + rk30_mux_api_set(GPIO3B2_SDMMC0DATA0_NAME, GPIO3B_GPIO3B2); + gpio_request(RK30_PIN3_PB2, "mmc0-data0"); + gpio_direction_output(RK30_PIN3_PB2,GPIO_LOW);//set mmc0-data0 to low. + + rk30_mux_api_set(GPIO3B3_SDMMC0DATA1_NAME, GPIO3B_GPIO3B3); + gpio_request(RK30_PIN3_PB3, "mmc0-data1"); + gpio_direction_output(RK30_PIN3_PB3,GPIO_LOW);//set mmc0-data1 to low. + + rk30_mux_api_set(GPIO3B4_SDMMC0DATA2_NAME, GPIO3B_GPIO3B4); + gpio_request(RK30_PIN3_PB4, "mmc0-data2"); + gpio_direction_output(RK30_PIN3_PB4,GPIO_LOW);//set mmc0-data2 to low. + + rk30_mux_api_set(GPIO3B5_SDMMC0DATA3_NAME, GPIO3B_GPIO3B5); + gpio_request(RK30_PIN3_PB5, "mmc0-data3"); + gpio_direction_output(RK30_PIN3_PB5,GPIO_LOW);//set mmc0-data3 to low. + + mdelay(30); + } + #endif + } + break; + + case 1://mmc1 + { + #ifdef CONFIG_SDMMC1_RK29 + if(on) + { + gpio_direction_output(RK30_PIN3_PC5,GPIO_HIGH);//set mmc1-clk to high + gpio_direction_output(RK30_PIN3_PC0,GPIO_HIGH);//set mmc1-cmd to high. + gpio_direction_output(RK30_PIN3_PC1,GPIO_HIGH);//set mmc1-data0 to high. + gpio_direction_output(RK30_PIN3_PC2,GPIO_HIGH);//set mmc1-data1 to high. + gpio_direction_output(RK30_PIN3_PC3,GPIO_HIGH);//set mmc1-data2 to high. + gpio_direction_output(RK30_PIN3_PC5,GPIO_HIGH);//set mmc1-data3 to high. + mdelay(100); + } + else + { + rk30_mux_api_set(GPIO3C5_SDMMC1CLKOUT_NAME, GPIO3C_GPIO3C5); + gpio_request(RK30_PIN3_PC5, "mmc1-clk"); + gpio_direction_output(RK30_PIN3_PC5,GPIO_LOW);//set mmc1-clk to low. + + rk30_mux_api_set(GPIO3C0_SMMC1CMD_NAME, GPIO3C_GPIO3C0); + gpio_request(RK30_PIN3_PC0, "mmc1-cmd"); + gpio_direction_output(RK30_PIN3_PC0,GPIO_LOW);//set mmc1-cmd to low. + + rk30_mux_api_set(GPIO3C1_SDMMC1DATA0_NAME, GPIO3C_GPIO3C1); + gpio_request(RK30_PIN3_PC1, "mmc1-data0"); + gpio_direction_output(RK30_PIN3_PC1,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: + { + rk30_mux_api_set(GPIO3B3_SDMMC0DATA1_NAME, GPIO3B_SDMMC0_DATA1); + rk30_mux_api_set(GPIO3B4_SDMMC0DATA2_NAME, GPIO3B_SDMMC0_DATA2); + rk30_mux_api_set(GPIO3B5_SDMMC0DATA3_NAME, GPIO3B_SDMMC0_DATA3); + } + break; + + case 0x10000://SDMMC_CTYPE_8BIT: + break; + case 0xFFFF: //gpio_reset + { + rk30_mux_api_set(GPIO3A7_SDMMC0PWREN_NAME, GPIO3A_GPIO3A7); + gpio_request(RK30_PIN3_PA7,"sdmmc-power"); + gpio_direction_output(RK30_PIN3_PA7,GPIO_HIGH); //power-off + + rk29_sdmmc_gpio_open(0, 0); + + gpio_direction_output(RK30_PIN3_PA7,GPIO_LOW); //power-on + + rk29_sdmmc_gpio_open(0, 1); + } + break; + + default: //case 0://SDMMC_CTYPE_1BIT: + { + rk30_mux_api_set(GPIO3B1_SDMMC0CMD_NAME, GPIO3B_SDMMC0_CMD); + rk30_mux_api_set(GPIO3B0_SDMMC0CLKOUT_NAME, GPIO3B_SDMMC0_CLKOUT); + rk30_mux_api_set(GPIO3B2_SDMMC0DATA0_NAME, GPIO3B_SDMMC0_DATA0); + + rk30_mux_api_set(GPIO3B3_SDMMC0DATA1_NAME, GPIO3B_GPIO3B3); + gpio_request(RK30_PIN3_PB3, "mmc0-data1"); + gpio_direction_output(RK30_PIN3_PB3,GPIO_HIGH);//set mmc0-data1 to high. + + rk30_mux_api_set(GPIO3B4_SDMMC0DATA2_NAME, GPIO3B_GPIO3B4); + gpio_request(RK30_PIN3_PB4, "mmc0-data2"); + gpio_direction_output(RK30_PIN3_PB4,GPIO_HIGH);//set mmc0-data2 to high. + + rk30_mux_api_set(GPIO3B5_SDMMC0DATA3_NAME, GPIO3B_GPIO3B5); + gpio_request(RK30_PIN3_PB5, "mmc0-data3"); + gpio_direction_output(RK30_PIN3_PB5,GPIO_HIGH);//set mmc0-data3 to high. + } + break; + } +} + +static void rk29_sdmmc_set_iomux_mmc1(unsigned int bus_width) +{ + rk30_mux_api_set(GPIO3C0_SMMC1CMD_NAME, GPIO3C_SMMC1_CMD); + rk30_mux_api_set(GPIO3C5_SDMMC1CLKOUT_NAME, GPIO3C_SDMMC1_CLKOUT); + rk30_mux_api_set(GPIO3C1_SDMMC1DATA0_NAME, GPIO3C_SDMMC1_DATA0); + rk30_mux_api_set(GPIO3C2_SDMMC1DATA1_NAME, GPIO3C_SDMMC1_DATA1); + rk30_mux_api_set(GPIO3C3_SDMMC1DATA2_NAME, GPIO3C_SDMMC1_DATA2); + rk30_mux_api_set(GPIO3C4_SDMMC1DATA3_NAME, GPIO3C_SDMMC1_DATA3); +} + +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_SDMMC0_RK29 +static int rk29_sdmmc0_cfg_gpio(void) +{ +#ifdef CONFIG_SDMMC_RK29_OLD + rk30_mux_api_set(GPIO3B1_SDMMC0CMD_NAME, GPIO3B_SDMMC0_CMD); + rk30_mux_api_set(GPIO3B0_SDMMC0CLKOUT_NAME, GPIO3B_SDMMC0_CLKOUT); + rk30_mux_api_set(GPIO3B2_SDMMC0DATA0_NAME, GPIO3B_SDMMC0_DATA0); + rk30_mux_api_set(GPIO3B3_SDMMC0DATA1_NAME, GPIO3B_SDMMC0_DATA1); + rk30_mux_api_set(GPIO3B4_SDMMC0DATA2_NAME, GPIO3B_SDMMC0_DATA2); + rk30_mux_api_set(GPIO3B5_SDMMC0DATA3_NAME, GPIO3B_SDMMC0_DATA3); + + rk30_mux_api_set(GPIO3B6_SDMMC0DETECTN_NAME, GPIO3B_GPIO3B6); + + rk30_mux_api_set(GPIO3A7_SDMMC0PWREN_NAME, GPIO3A_GPIO3A7); + gpio_request(RK30_PIN3_PA7,"sdmmc-power"); + gpio_direction_output(RK30_PIN3_PA7,GPIO_LOW); + +#else + rk29_sdmmc_set_iomux(0, 0xFFFF); + + rk30_mux_api_set(GPIO3B6_SDMMC0DETECTN_NAME, GPIO3B_SDMMC0_DETECT_N); + + #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; +} + +#define CONFIG_SDMMC0_USE_DMA +struct rk29_sdmmc_platform_data default_sdmmc0_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|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, +#else + .use_dma = 0, +#endif + .detect_irq = RK30_PIN3_PB6, // INVALID_GPIO + .enable_sd_wakeup = 0, + +#if defined(CONFIG_SDMMC0_RK29_WRITE_PROTECT) + .write_prt = SDMMC0_WRITE_PROTECT_PIN, +#else + .write_prt = INVALID_GPIO, +#endif +}; +#endif//endif--#ifdef CONFIG_SDMMC0_RK29 + +#ifdef CONFIG_SDMMC1_RK29 +#define CONFIG_SDMMC1_USE_DMA +static int rk29_sdmmc1_cfg_gpio(void) +{ +#if defined(CONFIG_SDMMC_RK29_OLD) + rk30_mux_api_set(GPIO3C0_SMMC1CMD_NAME, GPIO3C_SMMC1_CMD); + rk30_mux_api_set(GPIO3C5_SDMMC1CLKOUT_NAME, GPIO3C_SDMMC1_CLKOUT); + rk30_mux_api_set(GPIO3C1_SDMMC1DATA0_NAME, GPIO3C_SDMMC1_DATA0); + rk30_mux_api_set(GPIO3C2_SDMMC1DATA1_NAME, GPIO3C_SDMMC1_DATA1); + rk30_mux_api_set(GPIO3C3_SDMMC1DATA2_NAME, GPIO3C_SDMMC1_DATA2); + rk30_mux_api_set(GPIO3C4_SDMMC1DATA3_NAME, GPIO3C_SDMMC1_DATA3); + //rk30_mux_api_set(GPIO3C6_SDMMC1DETECTN_NAME, GPIO3C_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; +} + + + +#define RK29SDK_WIFI_SDIO_CARD_DETECT_N RK30_PIN6_PB2 + +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, +#endif +#if 0 + .detect_irq = RK29SDK_WIFI_SDIO_CARD_DETECT_N, +#endif + +#if defined(CONFIG_SDMMC1_RK29_WRITE_PROTECT) + .write_prt = SDMMC1_WRITE_PROTECT_PIN, +#else + .write_prt = INVALID_GPIO, +#endif + +#else + .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 RK30_PIN3_PD0 +#define RK29SDK_WIFI_GPIO_RESET_N RK30_PIN3_PD2 +#define RK29SDK_BT_GPIO_RESET_N RK30_PIN3_PD1 + +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; + +static int rk29sdk_wifi_status(struct device *dev) +{ + return rk29sdk_wifi_cd; +} + +static int rk29sdk_wifi_status_register(void (*callback)(int card_present, void *dev_id), void *dev_id) +{ + if(wifi_status_cb) + return -EAGAIN; + wifi_status_cb = callback; + wifi_status_cb_devid = dev_id; + return 0; +} + +static int rk29sdk_wifi_bt_gpio_control_init(void) +{ + if (gpio_request(RK29SDK_WIFI_BT_GPIO_POWER_N, "wifi_bt_power")) { + pr_info("%s: request wifi_bt power gpio failed\n", __func__); + return -1; + } + + if (gpio_request(RK29SDK_WIFI_GPIO_RESET_N, "wifi reset")) { + pr_info("%s: request wifi reset gpio failed\n", __func__); + gpio_free(RK29SDK_WIFI_BT_GPIO_POWER_N); + return -1; + } + + if (gpio_request(RK29SDK_BT_GPIO_RESET_N, "bt reset")) { + pr_info("%s: request bt reset gpio failed\n", __func__); + gpio_free(RK29SDK_WIFI_GPIO_RESET_N); + return -1; + } + + gpio_direction_output(RK29SDK_WIFI_BT_GPIO_POWER_N, GPIO_LOW); + 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(GPIO3C2_SDMMC1DATA1_NAME, GPIO3C_GPIO3C2); + gpio_request(RK30_PIN3_PC2, "mmc1-data1"); + gpio_direction_output(RK30_PIN3_PC2,GPIO_LOW);//set mmc1-data1 to low. + + rk29_mux_api_set(GPIO3C3_SDMMC1DATA2_NAME, GPIO3C_GPIO3C3); + gpio_request(RK30_PIN3_PC3, "mmc1-data2"); + gpio_direction_output(RK30_PIN3_PC3,GPIO_LOW);//set mmc1-data2 to low. + + rk29_mux_api_set(GPIO3C4_SDMMC1DATA3_NAME, GPIO3C_GPIO3C4); + gpio_request(RK30_PIN3_PC4, "mmc1-data3"); + gpio_direction_output(RK30_PIN3_PC4,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; +} + +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 + { + pr_info("wifi shouldn't shut off power, bt is using it!\n"); + } + gpio_set_value(RK29SDK_WIFI_GPIO_RESET_N, GPIO_LOW); + + } + + rk29sdk_wifi_power_state = on; + return 0; +} + +static int rk29sdk_wifi_reset_state; +static int rk29sdk_wifi_reset(int on) +{ + pr_info("%s: %d\n", __func__, on); + gpio_set_value(RK29SDK_WIFI_GPIO_RESET_N, on); + mdelay(100); + rk29sdk_wifi_reset_state = on; + return 0; +} + +int rk29sdk_wifi_set_carddetect(int val) +{ + pr_info("%s:%d\n", __func__, val); + rk29sdk_wifi_cd = val; + if (wifi_status_cb){ + wifi_status_cb(val, wifi_status_cb_devid); + }else { + pr_warning("%s, nobody to notify\n", __func__); + } + return 0; +} +EXPORT_SYMBOL(rk29sdk_wifi_set_carddetect); + +static struct wifi_mem_prealloc wifi_mem_array[PREALLOC_WLAN_SEC_NUM] = { + {NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER)}, + {NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER)}, + {NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER)}, + {NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER)} +}; + +static void *rk29sdk_mem_prealloc(int section, unsigned long size) +{ + if (section == PREALLOC_WLAN_SEC_NUM) + return wlan_static_skb; + + if ((section < 0) || (section > PREALLOC_WLAN_SEC_NUM)) + return NULL; + + if (wifi_mem_array[section].size < size) + return NULL; + + return wifi_mem_array[section].mem_ptr; +} + +int __init rk29sdk_init_wifi_mem(void) +{ + int i; + int j; + + for (i = 0 ; i < WLAN_SKB_BUF_NUM ; i++) { + wlan_static_skb[i] = dev_alloc_skb( + ((i < (WLAN_SKB_BUF_NUM / 2)) ? 4096 : 8192)); + + if (!wlan_static_skb[i]) + goto err_skb_alloc; + } + + for (i = 0 ; i < PREALLOC_WLAN_SEC_NUM ; i++) { + wifi_mem_array[i].mem_ptr = + kmalloc(wifi_mem_array[i].size, GFP_KERNEL); + + if (!wifi_mem_array[i].mem_ptr) + goto err_mem_alloc; + } + return 0; + +err_mem_alloc: + pr_err("Failed to mem_alloc for WLAN\n"); + for (j = 0 ; j < i ; j++) + kfree(wifi_mem_array[j].mem_ptr); + + i = WLAN_SKB_BUF_NUM; + +err_skb_alloc: + pr_err("Failed to skb_alloc for WLAN\n"); + for (j = 0 ; j < i ; j++) + dev_kfree_skb(wlan_static_skb[j]); + + return -ENOMEM; +} + +static struct wifi_platform_data rk29sdk_wifi_control = { + .set_power = rk29sdk_wifi_power, + .set_reset = rk29sdk_wifi_reset, + .set_carddetect = rk29sdk_wifi_set_carddetect, + .mem_prealloc = rk29sdk_mem_prealloc, +}; +static struct platform_device rk29sdk_wifi_device = { + .name = "bcm4329_wlan", + .id = 1, + .dev = { + .platform_data = &rk29sdk_wifi_control, + }, +}; +#endif + + +/* bluetooth rfkill device */ +static struct platform_device rk29sdk_rfkill = { + .name = "rk29sdk_rfkill", + .id = -1, +}; + +/************************************************************************************************** + * the end of setting for SDMMC devices +**************************************************************************************************/ + static void __init machine_rk30_board_init(void) { rk30_i2c_register_board_info(); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index cb81f94e542f..55ef827c41ee 100755 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -440,7 +440,17 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) goto out; /* only compare read only fields */ - err = (!(card->ext_csd.raw_partition_support == + //err = (!(card->ext_csd.raw_partition_support == + err = !((card->ext_csd.raw_partition_support == + /*Modifyed by xbw at 2012-03-05 + + commit dd13b4ed4650bb3a7d6c86b549ab66a6aa0c00d8 + Author: Jurgen Heeks + Date: Wed Feb 1 13:30:55 2012 +0100 + + mmc: core: Fix comparison issue in mmc_compare_ext_csds + */ + bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) && (card->ext_csd.raw_erased_mem_count == bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) && diff --git a/drivers/mmc/host/rk29_sdmmc.c b/drivers/mmc/host/rk29_sdmmc.c index 708cc8bbb59c..89ce30fd562f 100755 --- a/drivers/mmc/host/rk29_sdmmc.c +++ b/drivers/mmc/host/rk29_sdmmc.c @@ -65,16 +65,20 @@ int debug_level = 5; #define RK29_SDMMC_ERROR_FLAGS (SDMMC_INT_FRUN | SDMMC_INT_HLE ) +#ifdef CONFIG_ARCH_RK29 #define RK29_SDMMC_INTMASK_USEDMA (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD) #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 ) - +#else +#define RK29_SDMMC_INTMASK_USEDMA (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD) +#define RK29_SDMMC_INTMASK_USEIO (SDMMC_INT_CMD_DONE | SDMMC_INT_DTO | SDMMC_INT_UNBUSY |RK29_SDMMC_ERROR_FLAGS | SDMMC_INT_CD| SDMMC_INT_TXDR | SDMMC_INT_RXDR ) +#endif #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 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.14 The last modify date is 2011-11-17,modifyed by XBW." +#define RK29_SDMMC_VERSION "Ver.3.02 The last modify date is 2012-03-12,modifyed by XBW." #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) #define RK29_CTRL_SDMMC_ID 0 //mainly used by SDMMC @@ -343,6 +347,24 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD) if(RK29_CTRL_SDMMC_ID == host->pdev->id) { +#if 1 //to wirte log in log-file-system during the stage of umount. Modifyed by xbw at 2011-12-26 + if(!strncmp(buf, "sd-Unmounting", strlen("sd-Unmounting"))) + { + if(unmounting_times++%10 == 0) + { + printk(".%d.. MMC0 receive the message Unmounting(waitTimes=%d) from VOLD.====xbw[%s]====\n", \ + __LINE__, unmounting_times, host->dma_name); + } + + if(0 == host->mmc->re_initialized_flags) + mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY*2)); + } + else if(!strncmp(buf, "sd-Idle-Unmounted", strlen("sd-Idle-Unmounted"))) + { + if(0 == host->mmc->re_initialized_flags) + mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY*2)); + } +#else if(!strncmp(buf, "sd-Unmounting", strlen("sd-Unmounting"))) { if(unmounting_times++%10 == 0) @@ -352,7 +374,8 @@ ssize_t rk29_sdmmc_progress_store(struct kobject *kobj, struct kobj_attribute *a } host->mmc->re_initialized_flags = 0; mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(RK29_SDMMC_REMOVAL_DELAY*2)); - } + } +#endif else if( !strncmp(buf, "sd-No-Media", strlen("sd-No-Media"))) { printk(".%d.. MMC0 receive the message No-Media from VOLD. waitTimes=%d ====xbw[%s]====\n" ,\ @@ -445,7 +468,7 @@ struct kobj_attribute mmc_reset_attrs = { .attr = { .name = "rescan", - .mode = 0766}, + .mode = 0764}, .show = NULL, .store = rk29_sdmmc_progress_store, }; @@ -1095,8 +1118,8 @@ static int rk29_sdmmc_prepare_write_data(struct rk29_sdmmc *host, struct mmc_dat { host->dodma = 0; - printk("%s..%d... CMD%d setupDMA failure!!!!! ==xbw[%s]==\n", \ - __FUNCTION__, __LINE__, host->cmd->opcode, host->dma_name); + printk("%s..%d... CMD%d setupDMA failure!!!!! pre_cmd=%d ==xbw[%s]==\n", \ + __FUNCTION__, __LINE__, host->cmd->opcode,host->old_cmd, host->dma_name); host->errorstep = 0x81; @@ -1407,8 +1430,11 @@ int rk29_sdmmc_reset_controller(struct rk29_sdmmc *host) } /* reset */ +#ifdef CONFIG_ARCH_RK29 rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET )); - +#else + rk29_sdmmc_write(host->regs, SDMMC_CTRL,(SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET)); +#endif timeOut = 1000; value = rk29_sdmmc_read(host->regs, SDMMC_CTRL); while (( value & (SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_RESET)) && (timeOut > 0)) @@ -2978,6 +3004,16 @@ static irqreturn_t rk29_sdmmc_interrupt(int irq, void *dev_id) goto Exit_INT; } +#ifndef CONFIG_ARCH_RK29 + if(pending & SDMMC_INT_UNBUSY) + { + // printk("%d..%s: ==test=== xbw======\n", __LINE__, __FUNCTION__); + // rk29_sdmmc_regs_printk(host); + rk29_sdmmc_write(host->regs, SDMMC_RINTSTS,SDMMC_INT_UNBUSY); + goto Exit_INT; + } +#endif + if (pending & SDMMC_INT_RXDR) { xbwprintk(6, "%s..%d.. SDMMC_INT_RXDR INT=0x%x ====xbw[%s]====\n", \ @@ -3017,7 +3053,7 @@ static void rk29_sdmmc_detect_change(unsigned long data) smp_rmb(); - if(RK29_CTRL_SDMMC_ID == host->pdev->id) + if((RK29_CTRL_SDMMC_ID == host->pdev->id) && rk29_sdmmc_get_cd(host->mmc)) { host->mmc->re_initialized_flags =1; } @@ -3126,8 +3162,14 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&host->queue); #endif +#ifdef CONFIG_ARCH_RK29 host->clk = clk_get(&pdev->dev, "mmc"); - +#elif CONFIG_ARCH_RK30 + host->clk = clk_get(&pdev->dev, "sdmmc"); +#endif + +#if 0 //ÔÝʱÆÁ±Î£¬RK30 CLOCKÄ£¿é»¹Î´ÕûÀíºÃ¡£ !!!!!!!!!!!!!!!!!!!!! + #if RK29_SDMMC_DEFAULT_SDIO_FREQ clk_set_rate(host->clk,SDHC_FPP_FREQ); #else @@ -3137,9 +3179,16 @@ static int rk29_sdmmc_probe(struct platform_device *pdev) clk_set_rate(host->clk,RK29_MAX_SDIO_FREQ); #endif - + +#endif + clk_enable(host->clk); + +#ifdef CONFIG_ARCH_RK29 clk_enable(clk_get(&pdev->dev, "hclk_mmc")); +#elif CONFIG_ARCH_RK30 + clk_enable(clk_get(&pdev->dev, "hclk_sdmmc")); +#endif ret = -ENOMEM; host->regs = ioremap(regs->start, regs->end - regs->start + 1); @@ -3415,6 +3464,7 @@ static int __exit rk29_sdmmc_remove(struct platform_device *pdev) #ifdef CONFIG_PM +#ifdef CONFIG_ARCH_RK29 static irqreturn_t det_keys_isr(int irq, void *dev_id) { struct rk29_sdmmc *host = dev_id; @@ -3449,7 +3499,43 @@ static void rk29_sdmmc_sdcard_resume(struct rk29_sdmmc *host) gpio_free(RK29_PIN2_PA2); rk29_mux_api_set(GPIO2A2_SDMMC0DETECTN_NAME, GPIO2L_SDMMC0_DETECT_N); } +#else +static irqreturn_t det_keys_isr(int irq, void *dev_id) +{ + struct rk29_sdmmc *host = dev_id; + dev_info(&host->pdev->dev, "sd det_gpio changed(%s), send wakeup key!\n", + gpio_get_value(RK30_PIN3_PB6)?"removed":"insert"); + rk29_sdmmc_detect_change((unsigned long)dev_id); + + return IRQ_HANDLED; +} +static int rk29_sdmmc_sdcard_suspend(struct rk29_sdmmc *host) +{ + int ret = 0; + rk29_mux_api_set(GPIO3B6_SDMMC0DETECTN_NAME, GPIO3B_GPIO3B6); + gpio_request(RK30_PIN3_PB6, "sd_detect"); + gpio_direction_input(RK30_PIN3_PB6); + + host->gpio_irq = gpio_to_irq(RK30_PIN3_PB6); + ret = request_irq(host->gpio_irq, det_keys_isr, + (gpio_get_value(RK30_PIN3_PB6))?IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING, + "sd_detect", + host); + + enable_irq_wake(host->gpio_irq); + + return ret; +} +static void rk29_sdmmc_sdcard_resume(struct rk29_sdmmc *host) +{ + disable_irq_wake(host->gpio_irq); + free_irq(host->gpio_irq,host); + gpio_free(RK30_PIN3_PB6); + rk29_mux_api_set(GPIO3B6_SDMMC0DETECTN_NAME, GPIO3B_SDMMC0_DETECT_N); +} + +#endif static int rk29_sdmmc_suspend(struct platform_device *pdev, pm_message_t state) diff --git a/drivers/mmc/host/rk29_sdmmc.h b/drivers/mmc/host/rk29_sdmmc.h index fd59b868ce2a..3802c0f5ebda 100755 --- a/drivers/mmc/host/rk29_sdmmc.h +++ b/drivers/mmc/host/rk29_sdmmc.h @@ -44,7 +44,20 @@ #define SDMMC_TCBCNT (0x05c) //Transferred CIU card byte count #define SDMMC_TBBCNT (0x060) //Transferred host/DMA to/from BIU_FIFO byte count #define SDMMC_DEBNCE (0x064) //Card detect debounce register +#define SDMMC_USRID (0x068) //User ID register + +#ifdef CONFIG_ARCH_RK29 #define SDMMC_DATA (0x100) +#else +#define SDMMC_VERID (0x06c) //Version ID register +#define SDMMC_UHS_REG (0x074) //UHS-I register +#define SDMMC_RST_n (0x068) //Hardware reset register +#define SDMMC_CARDTHRCTL (0x100) //Card Read Threshold Enable +#define SDMMC_BACK_END_POWER (0x104) //Back-end Power +#define SDMMC_FIFO_BASE (0x200) // + +#define SDMMC_DATA SDMMC_FIFO_BASE +#endif #define RK2818_BIT(n) (1<<(n)) #define RK_CLEAR_BIT(n) (0<<(n)) @@ -87,7 +100,13 @@ #define SDMMC_CTYPE_1BIT RK_CLEAR_BIT(0) /* Interrupt status & mask register defines(base+0x24) */ +#ifdef CONFIG_ARCH_RK29 #define SDMMC_INT_SDIO RK2818_BIT(16) //SDIO interrupt +#else +#define SDMMC_INT_SDIO RK2818_BIT(24) //SDIO interrupt +#define SDMMC_INT_UNBUSY RK2818_BIT(16) //data no busy interrupt +#endif + #define SDMMC_INT_EBE RK2818_BIT(15) //End Bit Error(read)/Write no CRC #define SDMMC_INT_ACD RK2818_BIT(14) //Auto Command Done #define SDMMC_INT_SBE RK2818_BIT(13) //Start Bit Error @@ -153,6 +172,7 @@ #define SD_MSIZE_128 (0x6 << 28) #define SD_MSIZE_256 (0x7 << 28) +#ifdef CONFIG_ARCH_RK29 #define FIFO_DEPTH (0x20) //FIFO depth = 32 word #define RX_WMARK_SHIFT (16) #define TX_WMARK_SHIFT (0) @@ -160,7 +180,15 @@ /* FIFO watermark */ #define RX_WMARK (0xF) //RX watermark level set to 15 #define TX_WMARK (0x10) //TX watermark level set to 16 +#else +#define FIFO_DEPTH (0x100) //FIFO depth = 256 word +#define RX_WMARK_SHIFT (16) +#define TX_WMARK_SHIFT (0) +/* FIFO watermark */ +#define RX_WMARK (FIFO_DEPTH/2-1) //RX watermark level set to 127 +#define TX_WMARK (FIFO_DEPTH/2) //TX watermark level set to 128 +#endif /* CDETECT register defines (base+0x50)*/ #define SDMMC_CARD_DETECT_N RK2818_BIT(0) //0--represents presence of card. -- 2.34.1