add the SDMMC driver into RK30-SDK
authorxbw <xbw@rock-chips.com>
Tue, 13 Mar 2012 03:40:16 +0000 (11:40 +0800)
committerxbw <xbw@rock-chips.com>
Tue, 13 Mar 2012 03:40:16 +0000 (11:40 +0800)
arch/arm/mach-rk30/board-rk30-sdk.c
drivers/mmc/core/mmc.c
drivers/mmc/host/rk29_sdmmc.c
drivers/mmc/host/rk29_sdmmc.h

index 28e997fcf6afd2d998c307bffae3dfbd969dd1f2..dfd2ceafddaa74030e8e7638451bc92011de6840 100755 (executable)
@@ -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();
index cb81f94e542f536f29855690b7c43ab02d778651..55ef827c41eed6e497a3b480c84fd6886b43e784 100755 (executable)
@@ -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 <jurgen.heeks@nokia.com>
+                                                        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]) &&
index 708cc8bbb59cbb2267cc215d1af2ccb5f691aa67..89ce30fd562f8c397f9a97c612db39a8a3e307e2 100755 (executable)
@@ -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)
index fd59b868ce2a419c2c822f13b323b165c16ae74b..3802c0f5ebda2e291f31faed0bc8b522654aa843 100755 (executable)
 #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))
 #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
 #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)
 /* 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.