emmc: add emmc driver support on m8b

PD#141217: initial add emmc dirver support on m8b
1) add emmc driver support
HS200 mode 85M
2) add sd driver support
HS mode 38M

test on m8b_m200.

Change-Id: I1575c45af2e1246019d54a8092ee29e1da0a1a70
Signed-off-by: Nan Li <nan.li@amlogic.com>
This commit is contained in:
Nan Li
2017-04-11 14:57:52 +08:00
committed by Jianxin Pan
parent eac32a1357
commit 46148b7e38
14 changed files with 4502 additions and 37 deletions

View File

@@ -13781,6 +13781,17 @@ F: drivers/amlogic/media/video_processor/Kconfig
F: drivers/amlogic/media/video_processor/Makefile
F: drivers/amlogic/media/video_processor/ionvideo/*
AMLOGIC EMMC S805 DRIVER SUPPORT
M: Nan Li <nan.li@amlogic.com>
F: arch/arm/boot/dts/amlogic/meson8b.dtsi
F: arch/arm/boot/dts/amlogic/meson8b_m200.dts
F: drivers/amlogic/emmc/aml_sdhc_m8.c
F: drivers/amlogic/emmc/aml_sdio.c
F: drivers/amlogic/emmc/Kconfig
F: drivers/amlogic/emmc/Makefile
F: include/linux/amlogic/sd.h
F: include/linux/amlogic/cpu_version.h
AMLOGIC PINCTRL SUPPORT FOR M8B
M: Xingyu Chen <xingyu.chen@amlogic.com>
F: drivers/amlogic/pinctrl/pinctrl-meson8b.c

View File

@@ -18,6 +18,7 @@
#include <dt-bindings/clock/meson8b-clkc.h>
#include <dt-bindings/gpio/meson8b-gpio.h>
#include <dt-bindings/reset/amlogic,meson8b-reset.h>
#include <dt-bindings/gpio/gpio.h>
#include "skeleton.dtsi"
/ {
@@ -209,6 +210,158 @@
interrupt-controller;
#interrupt-cells = <2>;
};
emmc_clk_cmd_pins:emmc_clk_cmd_pins {
mux {
groups = "sd_cmd_c",
"sd_clk_c";
function = "sd_c";
input-enable;
bias-pull-up;
};
};
emmc_all_pins:emmc_all_pins {
mux {
groups = "sd_d0_c",
"sd_d1_c",
"sd_d2_c",
"sd_d3_c",
"sd_cmd_c",
"sd_clk_c";
function = "sd_c";
input-enable;
bias-pull-up;
};
};
sd_clk_cmd_pins:sd_clk_cmd_pins{
mux {
groups = "sd_cmd_b",
"sd_clk_b";
function = "sd_b";
input-enable;
bias-pull-up;
};
};
sd_1bit_pins:sd_1bit_pins{
mux {
groups = "sd_d1_b",
"sd_d2_b",
"sd_d3_b",
"sd_cmd_b",
"sd_clk_b";
function = "sd_b";
input-enable;
bias-pull-up;
};
};
sd_all_pins:sd_all_pins{
mux {
groups = "sd_d0_b",
"sd_d1_b",
"sd_d2_b",
"sd_d3_b",
"sd_cmd_b",
"sd_clk_b";
function = "sd_b";
input-enable;
bias-pull-up;
};
};
sdio_clk_cmd_pins:sdio_clk_cmd_pins {
mux {
groups = "sd_clk_a",
"sd_cmd_a";
function = "sd_a";
input-enable;
bias-pull-up;
};
};
sdio_all_pins:sdio_all_pins {
mux {
groups = "sd_d0_a",
"sd_d1_a",
"sd_d2_a",
"sd_d3_a",
"sd_clk_a",
"sd_cmd_a";
function = "sd_a";
input-enable;
bias-pull-up;
};
};
sdhc_emmc_clk_cmd_pins:sdhc_emmc_clk_cmd_pins {
mux {
groups = "sdxc_clk_c",
"sdxc_cmd_c";
function = "sdxc_c";
input-enable;
bias-pull-up;
};
};
sdhc_emmc_all_pins:sdhc_emmc_all_pins {
mux {
groups = "sdxc_d0_c",
"sdxc_d13_c",
"sdxc_d47_c",
"sdxc_clk_c",
"sdxc_cmd_c";
function = "sdxc_c";
input-enable;
bias-pull-up;
};
};
sdhc_sd_clk_cmd_pins:sdhc_sd_clk_cmd_pins {
mux {
groups = "sdxc_clk_b",
"sdxc_cmd_b";
function = "sdxc_b";
input-enable;
bias-pull-up;
};
};
sdhc_sd_all_pins:sdhc_sd_all_pins {
mux {
groups = "sdxc_d0_b",
"sdxc_d13_b",
"sdxc_clk_b",
"sdxc_cmd_b";
function = "sdxc_b";
input-enable;
bias-pull-up;
};
};
sdhc_sdio_clk_cmd_pins:sdhc_sdio_clk_cmd_pins {
mux {
groups = "sdxc_clk_a",
"sdxc_cmd_a";
function = "sdxc_a";
input-enable;
bias-pull-up;
};
};
sdhc_sdio_all_pins:sdhc_sdio_all_pins {
mux {
groups = "sdxc_d0_1_a",
"sdxc_d13_1_a",
"sdxc_clk_a",
"sdxc_cmd_a";
function = "sdxc_a";
input-enable;
bias-pull-up;
};
};
};
pinctrl_aobus: pinctrl@c8100084 {

View File

@@ -30,6 +30,159 @@
reg = <0x00000000 0x40000000>;
linux,usable-memory = <0x00200000 0x3fe00000>;
};
sdio {
compatible = "amlogic, aml_sdio";
dev_name = "aml_sdio.0";
status = "okay";
interrupts = <0 28 1>;
reg = <0xc1108c20 0x20>;
pinctrl-names = "sd_clk_cmd_pins",
"sd_all_pins",
"emmc_clk_cmd_pins",
"emmc_all_pins",
"sdio_clk_cmd_pins",
"sdio_all_pins",
"sd_1bit_pins";
pinctrl-0 = <&sd_clk_cmd_pins>;
pinctrl-1 = <&sd_all_pins>;
pinctrl-2 = <&emmc_clk_cmd_pins>;
pinctrl-3 = <&emmc_all_pins>;
pinctrl-4 = <&sdio_clk_cmd_pins>;
pinctrl-5 = <&sdio_all_pins>;
pinctrl-6 = <&sd_1bit_pins>;
clocks = <&clkc CLKID_SDIO>;
clock-names = "core";
sd {
status = "okay";
port = <1>;
/* 0:sdio_a,
* 1:sdio_b,
* 2:sdio_c,
* 3:sdhc_a,
* 4:sdhc_b,
* 5:sdhc_c
*/
pinname = "sd";
ocr_avail = <0x200000>; /**VDD voltage 3.3 ~ 3.4 */
caps = "MMC_CAP_4_BIT_DATA",
"MMC_CAP_MMC_HIGHSPEED",
"MMC_CAP_SD_HIGHSPEED";
f_min = <300000>;
f_max = <50000000>;
f_max_w = <50000000>;
max_req_size = <0x20000>; /*128KB*/
gpio_dat3 = <&gpio CARD_4 GPIO_ACTIVE_HIGH>;
jtag_pin = <&gpio CARD_0 GPIO_ACTIVE_HIGH>;
gpio_cd = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
gpio_ro = <&gpio GPIODV_25 GPIO_ACTIVE_HIGH>;
card_type = <5>;
/* 0:unknown,
* 1:mmc card(include eMMC),
* 2:sd card(include tSD),
* 3:sdio device(ie:sdio-wifi),
* 4:SD combo (IO+mem) card,
* 5:NON sdio device(means sd/mmc card),
* other:reserved
*/
};
};
sdhc {
compatible = "amlogic, aml_sdhc";
dev_name = "aml_sdhc.0";
status = "okay";
interrupts = <0 78 1>;
reg = <0xc1108e00 0x3c>;
pinctrl-names = "sdhc_sd_clk_cmd_pins",
"sdhc_sd_all_pins",
"sdhc_emmc_clk_cmd_pins",
"sdhc_emmc_all_pins",
"sdhc_sdio_clk_cmd_pins",
"sdhc_sdio_all_pins";
pinctrl-0 = <&sdhc_sd_clk_cmd_pins>;
pinctrl-1 = <&sdhc_sd_all_pins>;
pinctrl-2 = <&sdhc_emmc_clk_cmd_pins>;
pinctrl-3 = <&sdhc_emmc_all_pins>;
pinctrl-4 = <&sdhc_sdio_clk_cmd_pins>;
pinctrl-5 = <&sdhc_sdio_all_pins>;
clocks = <&clkc CLKID_SDHC>,
<&clkc CLKID_FCLK_DIV3>;
clock-names = "core", "div3";
emmc {
status = "okay";
port = <5>;
/* 0:sdio_a,
* 1:sdio_b,
* 2:sdio_c,
* 3:sdhc_a,
* 4:sdhc_b,
* 5:sdhc_c
*/
pinname = "emmc";
ocr_avail = <0x00200080>;
/* 3.3:0x200000, 1.8+3.3:0x00200080 */
caps = "MMC_CAP_8_BIT_DATA",
"MMC_CAP_MMC_HIGHSPEED",
"MMC_CAP_SD_HIGHSPEED",
"MMC_CAP_NONREMOVABLE",
"MMC_CAP_ERASE",
"MMC_CAP_HW_RESET";
caps2 = "MMC_CAP2_HS200_1_8V_SDR";
f_min = <300000>;
f_max = <100000000>;
max_req_size = <0x20000>; /* 128KB */
gpio_dat3 = <&gpio BOOT_3 GPIO_ACTIVE_HIGH>;
hw_reset = <&gpio BOOT_9 GPIO_ACTIVE_HIGH>;
card_type = <1>;
/* 0:unknown,
* 1:mmc card(include eMMC),
* 2:sd card(include tSD),
* 3:sdio device(ie:sdio-wifi),
* 4:SD combo (IO+mem) card,
* 5:NON sdio device(means sd/mmc card),
* other:reserved
*/
};
sdio {
status = "okay";
port = <3>;
/* 0:sdio_a,
* 1:sdio_b,
* 2:sdio_c,
* 3:sdhc_a,
* 4:sdhc_b,
* 5:sdhc_c
*/
pinname = "sdio";
ocr_avail = <0x00200080>;
/* 3.3:0x200000, 1.8+3.3:0x00200080 */
caps = "MMC_CAP_4_BIT_DATA",
"MMC_CAP_MMC_HIGHSPEED",
"MMC_CAP_SD_HIGHSPEED",
"MMC_CAP_NONREMOVABLE",
"MMC_CAP_UHS_SDR12",
"MMC_CAP_UHS_SDR25",
"MMC_CAP_UHS_SDR50",
"MMC_CAP_UHS_SDR104",
"MMC_PM_KEEP_POWER";
f_min = <300000>;
f_max = <100000000>;
max_req_size = <0x20000>; /* 128KB */
card_type = <3>;
/* 0:unknown,
* 1:mmc card(include eMMC),
* 2:sd card(include tSD),
* 3:sdio device(ie:sdio-wifi),
* 4:SD combo (IO+mem) card,
* 5:NON sdio device(means sd/mmc card),
* other:reserved
*/
};
};
};
&uart_AO {

View File

@@ -54,6 +54,8 @@ CONFIG_AMLOGIC_CLK=y
CONFIG_AMLOGIC_M8B_CLK=y
CONFIG_AMLOGIC_CRYPTO=y
CONFIG_AMLOGIC_CRYPTO_BLKMV=y
CONFIG_AMLOGIC_MMC=y
CONFIG_AMLOGIC_M8B_MMC=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DMA_CMA=y
@@ -106,6 +108,8 @@ CONFIG_USB_CONFIGFS_F_MTP=y
CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16
CONFIG_STAGING=y
CONFIG_CHROME_PLATFORMS=y
CONFIG_ARM_TIMER_SP804=y

View File

@@ -16,4 +16,15 @@ config AMLOGIC_MMC
MMC 5.1 compliant and supports SD, eMMC and SDIO interfaces.
If you have a controller with this interface, say Y here.
config AMLOGIC_M8B_MMC
bool "Amlogic M8B Multimedia Card support"
depends on AMLOGIC_MMC
default n
help
This selects support for the Amlogic SD/MMC Host Controller
found on the S805/M8B family of SoCs. This controller is
MMC 5.1 compliant and supports SD, eMMC and SDIO interfaces.
If you have a controller with this interface, say Y here.
endmenu

View File

@@ -3,3 +3,5 @@
#
obj-$(CONFIG_AMLOGIC_MMC) += amlsd.o amlsd_of.o emmc_partitions.o aml_sd_emmc.o emmc_key.o
obj-$(CONFIG_AMLOGIC_M8B_MMC) += aml_sdhc_m8.o aml_sdio.o

View File

@@ -2779,7 +2779,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
goto free_host;
}
if (amlsd_get_platform_data(pdata, mmc, 0))
if (amlsd_get_platform_data(pdev, pdata, mmc, 0))
mmc_free_host(mmc);
if (aml_card_type_mmc(pdata))

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -37,8 +37,10 @@
#include <linux/highmem.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
/* #include <linux/amlogic/aml_gpio_consumer.h> */
#include <linux/amlogic/amlsd.h>
#ifdef CONFIG_AMLOGIC_M8B_MMC
#include <linux/amlogic/gpio-amlogic.h>
#endif
const u8 tuning_blk_pattern_4bit[64] = {
0xff, 0x0f, 0xff, 0x00, 0xff, 0xcc, 0xc3, 0xcc,
@@ -109,9 +111,19 @@ static int aml_is_card_insert(struct amlsd_platform *pdata)
return ret;
}
#ifdef CONFIG_AMLOGIC_M8B_MMC
int aml_sd_uart_detect(struct amlsd_platform *pdata)
#else
int aml_sd_uart_detect(struct amlsd_host *host)
#endif
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct mmc_host *mmc = pdata->mmc;
#else
struct amlsd_platform *pdata = host->pdata;
struct mmc_host *mmc = host->mmc;
#endif
if (aml_is_card_insert(pdata)) {
if (pdata->is_in)
@@ -119,7 +131,7 @@ int aml_sd_uart_detect(struct amlsd_host *host)
pdata->is_in = true;
pr_info("normal card in\n");
if (pdata->caps & MMC_CAP_4_BIT_DATA)
host->mmc->caps |= MMC_CAP_4_BIT_DATA;
mmc->caps |= MMC_CAP_4_BIT_DATA;
} else {
if (!pdata->is_in)
return 1;
@@ -127,14 +139,14 @@ int aml_sd_uart_detect(struct amlsd_host *host)
pr_info("card out\n");
pdata->is_tuned = false;
if (host->mmc && host->mmc->card)
mmc_card_set_removed(host->mmc->card);
if (mmc && mmc->card)
mmc_card_set_removed(mmc->card);
/* switch to 3.3V */
aml_sd_voltage_switch(host->mmc,
aml_sd_voltage_switch(mmc,
MMC_SIGNAL_VOLTAGE_330);
if (pdata->caps & MMC_CAP_4_BIT_DATA)
host->mmc->caps |= MMC_CAP_4_BIT_DATA;
mmc->caps |= MMC_CAP_4_BIT_DATA;
}
return 0;
}
@@ -142,8 +154,15 @@ int aml_sd_uart_detect(struct amlsd_host *host)
static int card_dealed;
irqreturn_t aml_irq_cd_thread(int irq, void *data)
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = (struct amlsd_platform *)data;
struct mmc_host *mmc = pdata->mmc;
struct amlsd_host *host = pdata->host;
#else
struct amlsd_host *host = (struct amlsd_host *)data;
struct amlsd_platform *pdata = host->pdata;
struct mmc_host *mmc = host->mmc;
#endif
int ret = 0;
mutex_lock(&pdata->in_out_lock);
@@ -152,7 +171,11 @@ irqreturn_t aml_irq_cd_thread(int irq, void *data)
mutex_unlock(&pdata->in_out_lock);
return IRQ_HANDLED;
}
#ifdef CONFIG_AMLOGIC_M8B_MMC
ret = aml_sd_uart_detect(pdata);
#else
ret = aml_sd_uart_detect(host);
#endif
if (ret == 1) {/* the same as the last*/
mutex_unlock(&pdata->in_out_lock);
return IRQ_HANDLED;
@@ -164,9 +187,9 @@ irqreturn_t aml_irq_cd_thread(int irq, void *data)
/* mdelay(500); */
if (pdata->is_in)
mmc_detect_change(host->mmc, msecs_to_jiffies(100));
mmc_detect_change(mmc, msecs_to_jiffies(100));
else
mmc_detect_change(host->mmc, msecs_to_jiffies(0));
mmc_detect_change(mmc, msecs_to_jiffies(0));
card_dealed = 0;
return IRQ_HANDLED;
@@ -180,7 +203,12 @@ irqreturn_t aml_sd_irq_cd(int irq, void *dev_id)
static int aml_cmd_invalid(struct mmc_host *mmc, struct mmc_request *mrq)
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = mmc_priv(mmc);
struct amlsd_host *host = pdata->host;
#else
struct amlsd_host *host = mmc_priv(mmc);
#endif
unsigned long flags;
spin_lock_irqsave(&host->mrq_lock, flags);
@@ -193,7 +221,12 @@ static int aml_cmd_invalid(struct mmc_host *mmc, struct mmc_request *mrq)
static int aml_rpmb_cmd_invalid(struct mmc_host *mmc, struct mmc_request *mrq)
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = mmc_priv(mmc);
struct amlsd_host *host = pdata->host;
#else
struct amlsd_host *host = mmc_priv(mmc);
#endif
unsigned long flags;
spin_lock_irqsave(&host->mrq_lock, flags);
@@ -208,8 +241,12 @@ static int aml_rpmb_cmd_invalid(struct mmc_host *mmc, struct mmc_request *mrq)
int aml_check_unsupport_cmd(struct mmc_host *mmc, struct mmc_request *mrq)
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = mmc_priv(mmc);
#else
struct amlsd_host *host = mmc_priv(mmc);
struct amlsd_platform *pdata = host->pdata;
#endif
u32 opcode, arg;
opcode = mrq->cmd->opcode;
@@ -276,6 +313,7 @@ int aml_check_unsupport_cmd(struct mmc_host *mmc, struct mmc_request *mrq)
int aml_sd_voltage_switch(struct mmc_host *mmc, char signal_voltage)
{
#ifndef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_host *host = mmc_priv(mmc);
struct amlsd_platform *pdata = host->pdata;
int ret = 0;
@@ -311,12 +349,41 @@ int aml_sd_voltage_switch(struct mmc_host *mmc, char signal_voltage)
return -EINVAL;
host->sd_sdio_switch_volat_done = 1;
#endif
return 0;
}
/* boot9 here */
void aml_emmc_hw_reset(struct mmc_host *mmc)
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = mmc_priv(mmc);
void __iomem *hw_ctrl;
if (!aml_card_type_mmc(pdata))
return;
hw_ctrl = ioremap(P_PREG_PAD_GPIO3_EN_N, 0x200);
//boot_9 used as eMMC hw_rst pin here.
//clr nand ce1 pinmux
aml_clr_reg32_mask((hw_ctrl + (0x19 << 2)), (1<<24));
//set out
aml_clr_reg32_mask(hw_ctrl, (1<<9));
//high
aml_set_reg32_mask((hw_ctrl + (0x1 << 2)), (1<<9));
mdelay(1);
//low
aml_clr_reg32_mask((hw_ctrl + (0x1 << 2)), (1<<9));
mdelay(2);
//high
aml_set_reg32_mask((hw_ctrl + (0x1 << 2)), (1<<9));
mdelay(1);
#else
struct amlsd_host *host = mmc_priv(mmc);
struct amlsd_platform *pdata = host->pdata;
u32 ret;
@@ -350,6 +417,7 @@ void aml_emmc_hw_reset(struct mmc_host *mmc)
return;
}
mdelay(2);
#endif
}
static void sdio_rescan(struct mmc_host *mmc)
@@ -397,12 +465,37 @@ int of_amlsd_init(struct amlsd_platform *pdata)
if (pdata->gpio_cd) {
pr_info("gpio_cd = %x\n", pdata->gpio_cd);
ret = gpio_request_one(pdata->gpio_cd,
GPIOF_IN, MODULE_NAME);
GPIOF_IN, MODULE_NAME);
CHECK_RET(ret);
}
#if 0
if (pdata->gpio_ro) {
ret = amlogic_gpio_request_one(pdata->gpio_ro,
GPIOF_IN, MODULE_NAME);
if (!ret) { // ok
/* 0:pull down, 1:pull up */
ret = amlogic_set_pull_up_down(pdata->gpio_ro,
1, MODULE_NAME);
CHECK_RET(ret);
} else {
sdio_err("request gpio_ro pin fail!\n");
}
}
#endif
if (pdata->gpio_power) {
if (pdata->power_level) {
ret = gpio_request_one(pdata->gpio_power,
GPIOF_OUT_INIT_LOW, MODULE_NAME);
CHECK_RET(ret);
} else {
ret = gpio_request_one(pdata->gpio_power,
GPIOF_OUT_INIT_HIGH, MODULE_NAME);
CHECK_RET(ret);
}
}
/* if(pdata->port == MESON_SDIO_PORT_A) */
/* wifi_setup_dt(); */
/* wifi_setup_dt(); */
return 0;
}
@@ -452,14 +545,24 @@ static struct pinctrl * __must_check aml_devm_pinctrl_get_select(
void of_amlsd_xfer_pre(struct mmc_host *mmc)
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = mmc_priv(mmc);
struct amlsd_host *host = pdata->host;
#else
struct amlsd_host *host = mmc_priv(mmc);
struct amlsd_platform *pdata = host->pdata;
#endif
char pinctrl[30];
char *p = pinctrl;
int i, size = 0;
struct pinctrl *ppin;
size = sizeof(pinctrl);
#ifdef CONFIG_AMLOGIC_M8B_MMC
if (pdata->port > PORT_SDIO_C) // so it should be PORT_SDHC_X
aml_snprint(&p, &size, "sdhc_");
#endif
if (mmc->ios.chip_select == MMC_CS_DONTCARE) {
if ((mmc->caps & MMC_CAP_4_BIT_DATA)
|| (strcmp(pdata->pinname, "sd"))
@@ -542,8 +645,13 @@ void aml_snprint (char **pp, int *left_size, const char *fmt, ...)
void aml_cs_high(struct mmc_host *mmc) /* chip select high */
{
int ret;
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = mmc_priv(mmc);
struct amlsd_host *host = pdata->host;
#else
struct amlsd_host *host = mmc_priv(mmc);
struct amlsd_platform *pdata = host->pdata;
#endif
if ((mmc->ios.chip_select == MMC_CS_HIGH)
&& (pdata->gpio_dat3 != 0)) {
@@ -560,8 +668,12 @@ void aml_cs_high(struct mmc_host *mmc) /* chip select high */
void aml_cs_dont_care(struct mmc_host *mmc)
{
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct amlsd_platform *pdata = mmc_priv(mmc);
#else
struct amlsd_host *host = mmc_priv(mmc);
struct amlsd_platform *pdata = host->pdata;
#endif
if ((mmc->ios.chip_select == MMC_CS_DONTCARE)
&& (pdata->gpio_dat3 != 0)
@@ -585,3 +697,157 @@ void of_amlsd_pwr_off(struct amlsd_platform *pdata)
gpio_set_value(pdata->gpio_power, !pdata->power_level);
}
#ifdef CONFIG_AMLOGIC_M8B_MMC
/*-----------sg copy buffer------------*/
/**
* aml_sg_miter_stop - stop mapping iteration for amlogic,
* We don't disable irq in this function
*/
static void aml_sg_miter_stop(struct sg_mapping_iter *miter)
{
WARN_ON(miter->consumed > miter->length);
/* drop resources from the last iteration */
if (miter->addr) {
miter->__offset += miter->consumed;
miter->__remaining -= miter->consumed;
if (miter->__flags & SG_MITER_TO_SG)
flush_kernel_dcache_page(miter->page);
if (miter->__flags & SG_MITER_ATOMIC) {
WARN_ON_ONCE(preemptible());
kunmap_atomic(miter->addr);
} else
kunmap(miter->page);
miter->page = NULL;
miter->addr = NULL;
miter->length = 0;
miter->consumed = 0;
}
}
/**
* aml_sg_miter_next - proceed mapping iterator to the next mapping for amlogic,
* We don't disable irq in this function
*/
static bool aml_sg_miter_next(struct sg_mapping_iter *miter)
{
unsigned long flags;
sg_miter_stop(miter);
/*
* Get to the next page if necessary.
* __remaining, __offset is adjusted by sg_miter_stop
*/
if (!miter->__remaining) {
struct scatterlist *sg;
unsigned long pgoffset;
if (!__sg_page_iter_next(&miter->piter))
return false;
sg = miter->piter.sg;
pgoffset = miter->piter.sg_pgoffset;
miter->__offset = pgoffset ? 0 : sg->offset;
miter->__remaining = sg->offset + sg->length -
(pgoffset << PAGE_SHIFT) - miter->__offset;
miter->__remaining = min_t(unsigned long, miter->__remaining,
PAGE_SIZE - miter->__offset);
}
miter->page = sg_page_iter_page(&miter->piter);
miter->consumed = miter->length = miter->__remaining;
if (miter->__flags & SG_MITER_ATOMIC) {
/*pr_info(KERN_DEBUG "AML_SDHC miter_next highmem\n"); */
local_irq_save(flags);
miter->addr = kmap_atomic(miter->page) + miter->__offset;
local_irq_restore(flags);
} else
miter->addr = kmap(miter->page) + miter->__offset;
return true;
}
/*
* aml_sg_copy_buffer - Copy data between a linear buffer
* and an SG list for amlogic,
* We don't disable irq in this function
*/
EXPORT_SYMBOL(aml_sg_copy_buffer);
size_t aml_sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen, int to_buffer)
{
unsigned int offset = 0;
struct sg_mapping_iter miter;
unsigned int sg_flags = SG_MITER_ATOMIC;
unsigned long flags;
if (to_buffer)
sg_flags |= SG_MITER_FROM_SG;
else
sg_flags |= SG_MITER_TO_SG;
sg_miter_start(&miter, sgl, nents, sg_flags);
local_irq_save(flags);
while (aml_sg_miter_next(&miter) && offset < buflen) {
unsigned int len;
len = min(miter.length, buflen - offset);
if (to_buffer)
memcpy(buf + offset, miter.addr, len);
else
memcpy(miter.addr, buf + offset, len);
offset += len;
}
aml_sg_miter_stop(&miter);
local_irq_restore(flags);
return offset;
}
/*-------------------eMMC/tSD-------------------*/
int storage_flag;
bool is_emmc_exist(struct amlsd_host *host) // is eMMC/tSD exist
{
print_tmp("host->storage_flag=%d, POR_BOOT_VALUE=%d\n",
host->storage_flag, POR_BOOT_VALUE);
if ((host->storage_flag == EMMC_BOOT_FLAG)
|| (host->storage_flag == SPI_EMMC_FLAG)
|| (((host->storage_flag == 0)
|| (host->storage_flag == -1))
&& (POR_EMMC_BOOT() || POR_SPI_BOOT())))
return true;
return false;
}
/*-------------------debug---------------------*/
unsigned long sdhc_debug; // 0xffffffff;
static int __init sdhc_debug_setup(char *str)
{
ssize_t status = 0;
status = kstrtol(str, 0, &sdhc_debug);
return 1;
}
__setup("sdhc_debug=", sdhc_debug_setup);
unsigned long sdio_debug; // 0xffffff;
static int __init sdio_debug_setup(char *str)
{
ssize_t status = 0;
status = kstrtol(str, 0, &sdio_debug);
return 1;
}
__setup("sdio_debug=", sdio_debug_setup);
#endif

View File

@@ -25,11 +25,10 @@
#include <linux/mtd/partitions.h>
#include <linux/slab.h>
#include <linux/amlogic/sd.h>
/*#include <linux/of_address.h>*/
/*#include <linux/amlogic/aml_gpio_consumer.h>*/
#include <linux/gpio/consumer.h>
#include <linux/amlogic/amlsd.h>
#include <linux/amlogic/cpu_version.h>
unsigned int sd_emmc_debug;
static const struct sd_caps host_caps[] = {
@@ -119,7 +118,8 @@ static int amlsd_get_host_caps2(struct device_node *of_node,
return 0;
}
int amlsd_get_platform_data(struct amlsd_platform *pdata,
int amlsd_get_platform_data(struct platform_device *pdev,
struct amlsd_platform *pdata,
struct mmc_host *mmc, u32 index)
{
struct device_node *of_node;
@@ -127,10 +127,13 @@ int amlsd_get_platform_data(struct amlsd_platform *pdata,
u32 i, prop;
const char *str = "none";
if (!mmc->parent || !mmc->parent->of_node)
#ifdef CONFIG_AMLOGIC_M8B_MMC
of_node = pdev->dev.of_node;
#else
if (!mmc->parent)
return 0;
of_node = mmc->parent->of_node;
#endif
if (of_node) {
child = of_node->child;
WARN_ON(!child);
@@ -151,8 +154,8 @@ int amlsd_get_platform_data(struct amlsd_platform *pdata,
prop, pdata->f_min);
SD_PARSE_U32_PROP_DEC(child, "f_max",
prop, pdata->f_max);
SD_PARSE_U32_PROP_HEX(child, "max_req_size", prop,
pdata->max_req_size);
SD_PARSE_U32_PROP_HEX(child, "max_req_size",
prop, pdata->max_req_size);
SD_PARSE_GPIO_NUM_PROP(child, "gpio_cd",
str, pdata->gpio_cd);
SD_PARSE_GPIO_NUM_PROP(child, "gpio_ro",
@@ -177,20 +180,22 @@ int amlsd_get_platform_data(struct amlsd_platform *pdata,
prop, pdata->vol_switch_delay);
SD_PARSE_U32_PROP_DEC(child, "card_type",
prop, pdata->card_type);
if (aml_card_type_mmc(pdata)) {
/*tx_phase set default value first*/
if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB)
pdata->tx_phase = 1;
if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL)
pdata->tx_delay = 3;
SD_PARSE_U32_PROP_DEC(child, "tx_phase",
prop, pdata->tx_phase);
}
if (aml_card_type_non_sdio(pdata)) {
/*card in default value*/
pdata->card_in_delay = 0;
SD_PARSE_U32_PROP_DEC(child, "card_in_delay",
prop, pdata->card_in_delay);
if (get_cpu_type() > MESON_CPU_MAJOR_ID_M8B) {
if (aml_card_type_mmc(pdata)) {
/*tx_phase set default value first*/
if (get_cpu_type() == MESON_CPU_MAJOR_ID_GXTVBB)
pdata->tx_phase = 1;
if (get_cpu_type() == MESON_CPU_MAJOR_ID_TXL)
pdata->tx_delay = 3;
SD_PARSE_U32_PROP_DEC(child, "tx_phase",
prop, pdata->tx_phase);
}
if (aml_card_type_non_sdio(pdata)) {
/*card in default value*/
pdata->card_in_delay = 0;
SD_PARSE_U32_PROP_DEC(child, "card_in_delay",
prop, pdata->card_in_delay);
}
}
SD_PARSE_GPIO_NUM_PROP(child, "hw_reset",
str, pdata->hw_reset);
@@ -209,4 +214,3 @@ int amlsd_get_platform_data(struct amlsd_platform *pdata,
return 0;
}

View File

@@ -26,8 +26,8 @@
#define AML_MMC_VER_MESSAGE \
"2015-01-21: fix a bug in tuning which caused eMMC data CRC error"
extern unsigned int sdhc_debug;
extern unsigned int sdio_debug;
extern unsigned long sdhc_debug;
extern unsigned long sdio_debug;
extern unsigned int sd_emmc_debug;
extern const u8 tuning_blk_pattern_4bit[64];
extern const u8 tuning_blk_pattern_8bit[128];
@@ -49,8 +49,8 @@ extern const u8 tuning_blk_pattern_8bit[128];
#define LDO4DAC_REG_1_8_V 0x24
#define LDO4DAC_REG_2_8_V 0x4c
#define LDO4DAC_REG_3_3_V 0x60
#endif
#define AMLSD_DBG_COMMON (1<<0)
#define AMLSD_DBG_REQ (1<<1)
#define AMLSD_DBG_RESP (1<<2)
@@ -73,6 +73,12 @@ extern const u8 tuning_blk_pattern_8bit[128];
#define EMMC_DAT3_PINMUX_CLR 0
#define EMMC_DAT3_PINMUX_SET 1
#ifdef CONFIG_AMLOGIC_M8B_MMC
#define P_PERIPHS_PIN_MUX_2 (0xc1100000 + (0x202e << 2))
#define P_PREG_PAD_GPIO3_EN_N (0xc1100000 + (0x2015 << 2))
#define P_PREG_PAD_GPIO3_O (0xc1100000 + (0x2016 << 2))
#endif
#define CHECK_RET(ret) { \
if (ret) \
pr_info("[%s] gpio op failed(%d) at line %d\n",\
@@ -171,10 +177,13 @@ extern void aml_sd_emmc_print_reg(struct amlsd_host *host);
extern int add_part_table(struct mtd_partition *part, unsigned int nr_part);
extern int add_emmc_partition(struct gendisk *disk);
#endif
#ifdef CONFIG_AMLOGIC_M8B_MMC
extern size_t aml_sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
void *buf, size_t buflen, int to_buffer);
#endif
int amlsd_get_platform_data(struct amlsd_platform *pdata,
int amlsd_get_platform_data(struct platform_device *pdev,
struct amlsd_platform *pdata,
struct mmc_host *mmc, u32 index);
void of_amlsd_irq_init(struct amlsd_platform *pdata);

View File

@@ -18,6 +18,7 @@
#ifndef __PLAT_MESON_CPU_H
#define __PLAT_MESON_CPU_H
#define MESON_CPU_MAJOR_ID_M8B 0x1B
#define MESON_CPU_MAJOR_ID_GXBB 0x1F
#define MESON_CPU_MAJOR_ID_GXTVBB 0x20
#define MESON_CPU_MAJOR_ID_GXL 0x21

View File

@@ -159,6 +159,10 @@ struct amlsd_platform {
#define PORT_SDHC_B 4
#define PORT_SDHC_C 5
#ifdef CONFIG_AMLOGIC_M8B_MMC
unsigned int width;
unsigned int tune_phase; /* store tuning result */
#endif
unsigned int caps;
unsigned int caps2;
unsigned int card_capacity;
@@ -291,6 +295,9 @@ struct amlsd_host {
unsigned long mux_parent_rate[MUX_CLK_NUM_PARENTS];
struct clk_divider cfg_div;
struct clk *cfg_div_clk;
#ifdef CONFIG_AMLOGIC_M8B_MMC
struct clk *div3_clk;
#endif
struct resource *mem;
struct sd_emmc_regs *sd_emmc_regs;