mirror of
https://github.com/hardkernel/linux.git
synced 2026-04-20 04:21:14 +09:00
add the SDMMC driver into RK30-SDK
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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]) &&
|
||||
|
||||
@@ -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 //<2F><>ʱ<EFBFBD><CAB1><EFBFBD>Σ<EFBFBD>RK30 CLOCKģ<4B>黹δ<E9BBB9><CEB4><EFBFBD><EFBFBD><EFBFBD>á<EFBFBD> !!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
#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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user