emmc/sdio: support emmc/sdio driver for new host controller
authorLong Yu <long.yu@amlogic.com>
Tue, 16 May 2017 15:26:41 +0000 (23:26 +0800)
committerVictor Wan <victor.wan@amlogic.com>
Sat, 27 May 2017 10:06:04 +0000 (03:06 -0700)
PD#142470: emmc/sdio: support emmc/sdio driver for new host controller
1. add emmc support
2. support emmc DDR52 Busmode
3. add sdio support
4: axg_s400: disabled emmc function

Change-Id: Iaccca580393477f0ad96e7638dfa4d9e2809c37d
Signed-off-by: Long Yu <long.yu@amlogic.com>
13 files changed:
MAINTAINERS
arch/arm64/boot/dts/amlogic/axg_a113d_skt.dts
arch/arm64/boot/dts/amlogic/axg_s400.dts
arch/arm64/boot/dts/amlogic/axg_s420.dts
arch/arm64/boot/dts/amlogic/mesonaxg.dtsi
drivers/amlogic/mmc/Makefile
drivers/amlogic/mmc/aml_sd_emmc.c
drivers/amlogic/mmc/aml_sd_emmc_v3.c [new file with mode: 0644]
drivers/amlogic/mmc/amlsd_of.c
include/linux/amlogic/aml_sd_emmc_internal.h [new file with mode: 0644]
include/linux/amlogic/aml_sd_emmc_v3.h [new file with mode: 0644]
include/linux/amlogic/amlsd.h
include/linux/amlogic/sd.h

index b588b9e..ede7736 100644 (file)
@@ -13910,3 +13910,9 @@ F: drivers/amlogic/pci/pcie-amlogic.c
 F: drivers/amlogic/pci/pcie-amlogic.h
 F: drivers/amlogic/pci/Kconfig
 F: drivers/amlogic/pci/Makefile
+
+AMLOGIC AXG ADD EMMC AND SDIO SUPPORT FOR NEW HOST CONTROLLER
+M:     Long Yu <long.yu@amlogic.com>
+F:     drivers/amlogic/mmc/aml_sd_emmc_v3.c
+F:     include/linux/amlogic/aml_sd_emmc_internal.h
+F:     include/linux/amlogic/aml_sd_emmc_v3.h
index bb4b59e..ad8809d 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&b_uart_pins>;
        };
+
+       sd_emmc_c: emmc@ffe07000 {
+               status = "okay";
+               compatible = "amlogic, meson-aml-mmc";
+               reg = <0x0 0xffe07000 0x0 0x2000>;
+               interrupts = <0 218 1>;
+               pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins";
+               pinctrl-0 = <&emmc_clk_cmd_pins>;
+               pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>;
+               clocks = <&clkc CLKID_SD_EMMC_C>,
+                          <&clkc CLKID_SD_EMMC_C_P0_COMP>,
+                          <&clkc CLKID_FCLK_DIV2>;
+               clock-names = "core", "clkin0", "clkin1";
+
+               bus-width = <8>;
+               cap-sd-highspeed;
+               cap-mmc-highspeed;
+               mmc-ddr-1_8v;
+               mmc-hs200-1_8v;
+
+               max-frequency = <200000000>;
+               non-removable;
+               disable-wp;
+               emmc {
+                       status = "disabled";
+                       pinname = "emmc";
+                       ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */
+                       caps = "MMC_CAP_8_BIT_DATA",
+                                "MMC_CAP_MMC_HIGHSPEED",
+                                "MMC_CAP_SD_HIGHSPEED",
+                                "MMC_CAP_NONREMOVABLE",
+                                "MMC_CAP_1_8V_DDR",
+                                "MMC_CAP_HW_RESET",
+                                "MMC_CAP_ERASE",
+                                "MMC_CAP_CMD23";
+                       /*caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400";*/
+                       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>;
+                       pinmux_base = <0xff634400>;
+                       card_type = <1>;
+                       /* 1:mmc card(include eMMC),
+                        * 2:sd card(include tSD)
+                        */
+               };
+       };
+
+       partitions: partitions{
+               parts = <11>;
+               part-0 = <&logo>;
+               part-1 = <&recovery>;
+               part-2 = <&rsv>;
+               part-3 = <&tee>;
+               part-4 = <&crypt>;
+               part-5 = <&misc>;
+               part-6 = <&instaboot>;
+               part-7 = <&boot>;
+               part-8 = <&system>;
+               part-9 = <&cache>;
+               part-10 = <&data>;
+
+               logo:logo{
+                       pname = "logo";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               recovery:recovery{
+                       pname = "recovery";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               rsv:rsv{
+                       pname = "rsv";
+                       size = <0x0 0x800000>;
+                       mask = <1>;
+               };
+               tee:tee{
+                       pname = "tee";
+                       size = <0x0 0x800000>;
+                       mask = <1>;
+               };
+               crypt:crypt{
+                       pname = "crypt";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               misc:misc{
+                       pname = "misc";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               instaboot:instaboot{
+                       pname = "instaboot";
+                       size = <0x0 0x400000>;
+                       mask = <1>;
+               };
+               boot:boot
+               {
+                       pname = "boot";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               system:system
+               {
+                       pname = "system";
+                       size = <0x0 0x80000000>;
+                       mask = <1>;
+               };
+               cache:cache
+               {
+                       pname = "cache";
+                       size = <0x0 0x20000000>;
+                       mask = <2>;
+               };
+               data:data
+               {
+                       pname = "data";
+                       size = <0xffffffff 0xffffffff>;
+                       mask = <4>;
+               };
+       };
+
 }; /* end of / */
 
 
index 959f104..efad117 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&b_uart_pins>;
        };
+       wifi{
+               compatible = "amlogic, aml_wifi";
+               dev_name = "aml_wifi";
+               status = "okay";
+               interrupt_pin = <&gpio       GPIOX_7       GPIO_ACTIVE_HIGH>;
+               interrupts = <  0 68 4>;
+               irq_trigger_type = "GPIO_IRQ_LOW";
+               power_on_pin = <&gpio       GPIOX_6       GPIO_ACTIVE_HIGH>;
+//             pinctrl-names = "wifi_32k_pins";
+//             pinctrl-0 = <&wifi_32k_pins>;
+//             pwm_config = <&wifi_pwm_conf>;
+       };
+
+       sd_emmc_c: emmc@ffe07000 {
+               status = "disabled";
+               compatible = "amlogic, meson-aml-mmc";
+               reg = <0x0 0xffe07000 0x0 0x2000>;
+               interrupts = <0 218 1>;
+               pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins";
+               pinctrl-0 = <&emmc_clk_cmd_pins>;
+               pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>;
+               clocks = <&clkc CLKID_SD_EMMC_C>,
+                          <&clkc CLKID_SD_EMMC_C_P0_COMP>,
+                          <&clkc CLKID_FCLK_DIV2>;
+               clock-names = "core", "clkin0", "clkin1";
+
+               bus-width = <8>;
+               cap-sd-highspeed;
+               cap-mmc-highspeed;
+               mmc-ddr-1_8v;
+               mmc-hs200-1_8v;
+
+               max-frequency = <200000000>;
+               non-removable;
+               disable-wp;
+               emmc {
+                       status = "disabled";
+                       pinname = "emmc";
+                       ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */
+                       caps = "MMC_CAP_8_BIT_DATA",
+                                "MMC_CAP_MMC_HIGHSPEED",
+                                "MMC_CAP_SD_HIGHSPEED",
+                                "MMC_CAP_NONREMOVABLE",
+                                "MMC_CAP_1_8V_DDR",
+                                "MMC_CAP_HW_RESET",
+                                "MMC_CAP_ERASE",
+                                "MMC_CAP_CMD23";
+                       /*caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400";*/
+                       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>;
+                       pinmux_base = <0xff634400>;
+                       card_type = <1>;
+                       /* 1:mmc card(include eMMC),
+                        * 2:sd card(include tSD)
+                        */
+               };
+       };
+
+       sd_emmc_b:sdio@ffe05000 {
+               status = "okay";
+               compatible = "amlogic, meson-aml-mmc";
+               reg = <0x0 0xffe05000 0x0 0x2000>;
+               interrupts = <0 217 4>;
+               pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins";
+               pinctrl-0 = <&sdio_clk_cmd_pins>;
+               pinctrl-1 = <&sdio_all_pins>;
+               clocks = <&clkc CLKID_SD_EMMC_B>,
+                          <&clkc CLKID_SD_EMMC_B_P0_COMP>,
+                          <&clkc CLKID_FCLK_DIV2>;
+               clock-names = "core", "clkin0", "clkin1";
+
+               bus-width = <4>;
+               cap-sd-highspeed;
+               cap-mmc-highspeed;
+               max-frequency = <100000000>;
+               non-removable;
+               disable-wp;
+               sdio {
+                       status = "disabled";
+                       pinname = "sdio";
+                       ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */
+                       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",
+                                "MMC_CAP_SDIO_IRQ";
+                       f_min = <400000>;
+                       f_max = <200000000>;
+                       max_req_size = <0x20000>; /**128KB*/
+                       pinmux_base = <0xff634400>;
+                       card_type = <3>;
+                       /* 3:sdio device(ie:sdio-wifi),
+                        * 4:SD combo (IO+mem) card
+                        */
+               };
+       };
+
+       partitions: partitions{
+               parts = <11>;
+               part-0 = <&logo>;
+               part-1 = <&recovery>;
+               part-2 = <&rsv>;
+               part-3 = <&tee>;
+               part-4 = <&crypt>;
+               part-5 = <&misc>;
+               part-6 = <&instaboot>;
+               part-7 = <&boot>;
+               part-8 = <&system>;
+               part-9 = <&cache>;
+               part-10 = <&data>;
+
+               logo:logo{
+                       pname = "logo";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               recovery:recovery{
+                       pname = "recovery";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               rsv:rsv{
+                       pname = "rsv";
+                       size = <0x0 0x800000>;
+                       mask = <1>;
+               };
+               tee:tee{
+                       pname = "tee";
+                       size = <0x0 0x800000>;
+                       mask = <1>;
+               };
+               crypt:crypt{
+                       pname = "crypt";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               misc:misc{
+                       pname = "misc";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               instaboot:instaboot{
+                       pname = "instaboot";
+                       size = <0x0 0x400000>;
+                       mask = <1>;
+               };
+               boot:boot
+               {
+                       pname = "boot";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               system:system
+               {
+                       pname = "system";
+                       size = <0x0 0x80000000>;
+                       mask = <1>;
+               };
+               cache:cache
+               {
+                       pname = "cache";
+                       size = <0x0 0x20000000>;
+                       mask = <2>;
+               };
+               data:data
+               {
+                       pname = "data";
+                       size = <0xffffffff 0xffffffff>;
+                       mask = <4>;
+               };
+       };
+
 }; /* end of / */
 
 &spicc_a{
index 81b722f..1294d55 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&b_uart_pins>;
        };
+       wifi{
+               compatible = "amlogic, aml_wifi";
+               dev_name = "aml_wifi";
+               status = "okay";
+               interrupt_pin = <&gpio       GPIOX_6       GPIO_ACTIVE_HIGH>;
+               interrupts = <  0 67 4>;
+               irq_trigger_type = "GPIO_IRQ_LOW";
+               power_on_pin = <&gpio       GPIOX_7       GPIO_ACTIVE_HIGH>;
+//             pinctrl-names = "wifi_32k_pins";
+//             pinctrl-0 = <&wifi_32k_pins>;
+//             pwm_config = <&wifi_pwm_conf>;
+       };
+       sd_emmc_c: emmc@ffe07000 {
+               status = "disabled";
+               compatible = "amlogic, meson-aml-mmc";
+               reg = <0x0 0xffe07000 0x0 0x2000>;
+               interrupts = <0 218 1>;
+               pinctrl-names = "emmc_clk_cmd_pins", "emmc_all_pins";
+               pinctrl-0 = <&emmc_clk_cmd_pins>;
+               pinctrl-1 = <&emmc_conf_pull_up &emmc_conf_pull_done>;
+               clocks = <&clkc CLKID_SD_EMMC_C>,
+                          <&clkc CLKID_SD_EMMC_C_P0_COMP>,
+                          <&clkc CLKID_FCLK_DIV2>;
+               clock-names = "core", "clkin0", "clkin1";
+
+               bus-width = <8>;
+               cap-sd-highspeed;
+               cap-mmc-highspeed;
+               mmc-ddr-1_8v;
+               mmc-hs200-1_8v;
+
+               max-frequency = <200000000>;
+               non-removable;
+               disable-wp;
+               emmc {
+                       status = "disabled";
+                       pinname = "emmc";
+                       ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */
+                       caps = "MMC_CAP_8_BIT_DATA",
+                                "MMC_CAP_MMC_HIGHSPEED",
+                                "MMC_CAP_SD_HIGHSPEED",
+                                "MMC_CAP_NONREMOVABLE",
+                                "MMC_CAP_1_8V_DDR",
+                                "MMC_CAP_HW_RESET",
+                                "MMC_CAP_ERASE",
+                                "MMC_CAP_CMD23";
+                       /*caps2 = "MMC_CAP2_HS200", "MMC_CAP2_HS400";*/
+                       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>;
+                       pinmux_base = <0xff634400>;
+                       card_type = <1>;
+                       /* 1:mmc card(include eMMC),
+                        * 2:sd card(include tSD)
+                        */
+               };
+       };
+
+       sd_emmc_b:sdio@ffe05000 {
+               status = "okay";
+               compatible = "amlogic, meson-aml-mmc";
+               reg = <0x0 0xffe05000 0x0 0x2000>;
+               interrupts = <0 217 4>;
+               pinctrl-names = "sdio_clk_cmd_pins", "sdio_all_pins";
+               pinctrl-0 = <&sdio_clk_cmd_pins>;
+               pinctrl-1 = <&sdio_all_pins>;
+               clocks = <&clkc CLKID_SD_EMMC_B>,
+                          <&clkc CLKID_SD_EMMC_B_P0_COMP>,
+                          <&clkc CLKID_FCLK_DIV2>;
+               clock-names = "core", "clkin0", "clkin1";
+
+               bus-width = <4>;
+               cap-sd-highspeed;
+               cap-mmc-highspeed;
+               max-frequency = <100000000>;
+               non-removable;
+               disable-wp;
+               sdio {
+                       status = "disabled";
+                       pinname = "sdio";
+                       ocr_avail = <0x200080>; /**VDD voltage 3.3 ~ 3.4 */
+                       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",
+                                "MMC_CAP_SDIO_IRQ";
+                       f_min = <400000>;
+                       f_max = <200000000>;
+                       max_req_size = <0x20000>; /**128KB*/
+                       pinmux_base = <0xff634400>;
+                       card_type = <3>;
+                       /* 3:sdio device(ie:sdio-wifi),
+                        * 4:SD combo (IO+mem) card
+                        */
+               };
+       };
+
+       partitions: partitions{
+               parts = <11>;
+               part-0 = <&logo>;
+               part-1 = <&recovery>;
+               part-2 = <&rsv>;
+               part-3 = <&tee>;
+               part-4 = <&crypt>;
+               part-5 = <&misc>;
+               part-6 = <&instaboot>;
+               part-7 = <&boot>;
+               part-8 = <&system>;
+               part-9 = <&cache>;
+               part-10 = <&data>;
+
+               logo:logo{
+                       pname = "logo";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               recovery:recovery{
+                       pname = "recovery";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               rsv:rsv{
+                       pname = "rsv";
+                       size = <0x0 0x800000>;
+                       mask = <1>;
+               };
+               tee:tee{
+                       pname = "tee";
+                       size = <0x0 0x800000>;
+                       mask = <1>;
+               };
+               crypt:crypt{
+                       pname = "crypt";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               misc:misc{
+                       pname = "misc";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               instaboot:instaboot{
+                       pname = "instaboot";
+                       size = <0x0 0x400000>;
+                       mask = <1>;
+               };
+               boot:boot
+               {
+                       pname = "boot";
+                       size = <0x0 0x2000000>;
+                       mask = <1>;
+               };
+               system:system
+               {
+                       pname = "system";
+                       size = <0x0 0x80000000>;
+                       mask = <1>;
+               };
+               cache:cache
+               {
+                       pname = "cache";
+                       size = <0x0 0x20000000>;
+                       mask = <2>;
+               };
+               data:data
+               {
+                       pname = "data";
+                       size = <0xffffffff 0xffffffff>;
+                       mask = <4>;
+               };
+       };
 }; /* end of / */
 
 &spicc_a{
index 6390ad6..f0b81a9 100644 (file)
                };
        };
 
+       emmc_clk_cmd_pins:emmc_clk_cmd_pins {
+               mux {
+                       pins = "BOOT_8",
+                               "BOOT_10";
+                       function = "emmc";
+                       input-enable;
+                       bias-pull-up;
+               };
+       };
+
+
+       emmc_conf_pull_up:emmc_conf_pull_up {
+               mux {
+                       pins = "BOOT_0","BOOT_1","BOOT_2",
+                               "BOOT_3","BOOT_4","BOOT_5","BOOT_6",
+                               "BOOT_7","BOOT_8","BOOT_10";
+                       function = "emmc";
+                       input-enable;
+                       bias-pull-up;
+               };
+       };
+
+       emmc_conf_pull_done:emmc_conf_pull_done {
+               mux {
+                       groups = "BOOT_13";
+                       function = "emmc";
+                       input-enable;
+                       bias-pull-down;
+               };
+       };
+
+       sdio_clk_cmd_pins:sdio_clk_cmd_pins {
+               mux {
+                       groups = "GPIOX_4",
+                               "GPIOX_5";
+                       function = "sdio";
+                       input-enable;
+                       bias-pull-up;
+               };
+       };
+
+       sdio_all_pins:sdio_all_pins {
+               mux {
+                       groups = "GPIOX_0",
+                               "GPIOX_1",
+                               "GPIOX_2",
+                               "GPIOX_3",
+                               "GPIOX_4",
+                               "GPIOX_5";
+                       function = "sdio";
+                       input-enable;
+                       bias-pull-up;
+               };
+       };
+
 }; /* end of pinctrl_periphs */
 
index db585e9..a86fd0b 100644 (file)
@@ -2,6 +2,6 @@
 # Amlogic MMC specific Makefile
 #
 
-obj-$(CONFIG_AMLOGIC_MMC)      += amlsd.o amlsd_of.o emmc_partitions.o aml_sd_emmc.o emmc_key.o
+obj-$(CONFIG_AMLOGIC_MMC)      += amlsd.o amlsd_of.o emmc_partitions.o aml_sd_emmc.o emmc_key.o aml_sd_emmc_v3.o
 
 obj-$(CONFIG_AMLOGIC_M8B_MMC)  += aml_sdhc_m8.o aml_sdio.o
index c55c8bf..6599bc5 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/amlogic/cpu_version.h>
 #include <linux/mmc/emmc_partitions.h>
 #include <linux/amlogic/amlsd.h>
-
+#include <linux/amlogic/aml_sd_emmc_v3.h>
 struct mmc_host *sdio_host;
 
 static unsigned int log2i(unsigned int val)
@@ -710,7 +710,7 @@ static int aml_tuning_adj(struct mmc_host *mmc, u32 opcode,
 }
 
 /* TODO....., based on new tuning function */
-static int aml_sd_emmc_execute_tuning_(struct mmc_host *mmc, u32 opcode,
+int aml_sd_emmc_execute_tuning_(struct mmc_host *mmc, u32 opcode,
                                        struct aml_tuning_data *tuning_data,
                                        u32 adj_win_start)
 {
@@ -1226,7 +1226,7 @@ static int meson_mmc_clk_set_rate(struct amlsd_host *host,
        return ret;
 }
 
-static int aml_emmc_clktree_init(struct amlsd_host *host)
+int aml_emmc_clktree_init(struct amlsd_host *host)
 {
        int i, ret = 0;
        unsigned int f_min = UINT_MAX, mux_parent_count = 0;
@@ -1418,7 +1418,7 @@ static void aml_sd_emmc_set_timing(
 }
 
 /*setup bus width, 1bit, 4bits, 8bits*/
-static void aml_sd_emmc_set_buswidth(
+void aml_sd_emmc_set_buswidth(
                struct amlsd_host *host, u32 busw_ios)
 {
        u32 vconf;
@@ -2684,6 +2684,18 @@ static const struct mmc_host_ops meson_mmc_ops = {
        .hw_reset = aml_emmc_hw_reset,
 };
 
+static const struct mmc_host_ops meson_mmc_ops_v3 = {
+       .request = meson_mmc_request,
+       .set_ios = meson_mmc_set_ios_v3,
+       .enable_sdio_irq = aml_sd_emmc_enable_sdio_irq,
+       .get_cd = meson_mmc_get_cd,
+       .get_ro = aml_sd_emmc_get_ro,
+       .start_signal_voltage_switch = aml_signal_voltage_switch,
+       .card_busy = aml_sd_emmc_card_busy,
+       .execute_tuning = aml_mmc_execute_tuning_v3,
+       .hw_reset = aml_emmc_hw_reset,
+};
+
 static void aml_reg_print(struct amlsd_host *host)
 {
        struct amlsd_platform *pdata = host->pdata;
@@ -2718,7 +2730,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
        host->pdev = pdev;
        host->dev = &pdev->dev;
        dev_set_drvdata(&pdev->dev, host);
-
+       if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXLX))
+               host->ctrl_ver = 3;
        host->pinmux_base = ioremap(0xc8834400, 0x200);
        res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        host->base = devm_ioremap_resource(&pdev->dev, res_mem);
@@ -2735,8 +2748,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_threaded_irq(&pdev->dev, host->irq,
-                                       meson_mmc_irq, meson_mmc_irq_thread,
-                                       IRQF_SHARED, "meson-aml-mmc", host);
+                       meson_mmc_irq, meson_mmc_irq_thread,
+                       IRQF_SHARED, "meson-aml-mmc", host);
        if (ret)
                goto free_host;
 
@@ -2769,7 +2782,10 @@ static int meson_mmc_probe(struct platform_device *pdev)
        host->init_flag = 1;
        host->is_gated = false;
 
-       ret = meson_mmc_clk_init(host);
+       if (host->ctrl_ver >= 3)
+               ret = meson_mmc_clk_init_v3(host);
+       else
+               ret = meson_mmc_clk_init(host);
        if (ret)
                goto free_host;
 
@@ -2782,7 +2798,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (amlsd_get_platform_data(pdev, pdata, mmc, 0))
                mmc_free_host(mmc);
 
-       if (aml_card_type_mmc(pdata))
+       if (aml_card_type_mmc(pdata)
+                       && (host->ctrl_ver < 3))
                /**set emmc tx_phase regs here base on dts**/
                aml_sd_emmc_tx_phase_set(host);
 
@@ -2790,6 +2807,10 @@ static int meson_mmc_probe(struct platform_device *pdev)
 
        if (pdata->caps & MMC_PM_KEEP_POWER)
                mmc->pm_caps |= MMC_PM_KEEP_POWER;
+       if (pdata->base != 0) {
+               iounmap(host->pinmux_base);
+               host->pinmux_base = ioremap(pdata->base, 0x200);
+       }
        host->init_flag = 1;
        host->version = AML_MMC_VERSION;
        host->pinctrl = NULL;
@@ -2803,8 +2824,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
        mmc->max_seg_size = mmc->max_req_size;
        mmc->max_segs = 1024;
        mmc->ocr_avail = pdata->ocr_avail;
-       mmc->caps |= pdata->caps;
-       mmc->caps2 |= pdata->caps2;
+       mmc->caps = pdata->caps;
+       mmc->caps2 = pdata->caps2;
        mmc->f_min = pdata->f_min;
        mmc->f_max = pdata->f_max;
        mmc->max_current_180 = 300; /* 300 mA in 1.8V */
@@ -2836,7 +2857,10 @@ static int meson_mmc_probe(struct platform_device *pdev)
 
        if (pdata->port_init)
                pdata->port_init(pdata);
-       mmc->ops = &meson_mmc_ops;
+       if (host->ctrl_ver >= 3)
+               mmc->ops = &meson_mmc_ops_v3;
+       else
+               mmc->ops = &meson_mmc_ops;
        aml_reg_print(host);
        ret = mmc_add_host(mmc);
        if (ret) { /* error */
diff --git a/drivers/amlogic/mmc/aml_sd_emmc_v3.c b/drivers/amlogic/mmc/aml_sd_emmc_v3.c
new file mode 100644 (file)
index 0000000..fdb684b
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * drivers/amlogic/mmc/aml_sd_emmc_v3.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regulator/consumer.h>
+#include <linux/highmem.h>
+#include <linux/amlogic/sd.h>
+#include <linux/amlogic/cpu_version.h>
+#include <linux/mmc/emmc_partitions.h>
+#include <linux/amlogic/amlsd.h>
+#include <linux/amlogic/aml_sd_emmc_internal.h>
+
+int meson_mmc_clk_init_v3(struct amlsd_host *host)
+{
+       int ret = 0;
+       u32 vclkc = 0;
+       struct sd_emmc_clock_v3 *pclkc = (struct sd_emmc_clock_v3 *)&vclkc;
+       u32 vconf = 0;
+       struct sd_emmc_config *pconf = (struct sd_emmc_config *)&vconf;
+       struct amlsd_platform *pdata = host->pdata;
+
+       ret = aml_emmc_clktree_init(host);
+       if (ret)
+               return ret;
+
+       /* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
+       vclkc = 0;
+       pclkc->div = 60;         /* 400KHz */
+       pclkc->src = 0;   /* 0: Crystal 24MHz */
+       pclkc->core_phase = 2;    /* 2: 180 phase */
+       pclkc->rx_phase = 0;
+       pclkc->tx_phase = 0;
+       pclkc->always_on = 1;     /* Keep clock always on */
+       writel(vclkc, host->base + SD_EMMC_CLOCK);
+       pdata->clkc = vclkc;
+
+       vconf = 0;
+       /* 1bit mode */
+       pconf->bus_width = 0;
+       /* 512byte block length */
+       pconf->bl_len = 9;
+       /* 64 CLK cycle, here 2^8 = 256 clk cycles */
+       pconf->resp_timeout = 8;
+       /* 1024 CLK cycle, Max. 100mS. */
+       pconf->rc_cc = 4;
+       pconf->err_abort = 0;
+       pconf->auto_clk = 1;
+       writel(vconf, host->base + SD_EMMC_CFG);
+
+       writel(0xffff, host->base + SD_EMMC_STATUS);
+       writel(SD_EMMC_IRQ_ALL, host->base + SD_EMMC_IRQ_EN);
+
+       return ret;
+}
+
+static int meson_mmc_clk_set_rate_v3(struct amlsd_host *host,
+               unsigned long clk_ios)
+{
+       struct mmc_host *mmc = host->mmc;
+       int ret = 0;
+#ifdef SD_EMMC_CLK_CTRL
+       u32 clk_rate, clk_div, clk_src_sel;
+       struct amlsd_platform *pdata = host->pdata;
+#else
+       u32 vcfg = 0;
+       struct sd_emmc_config *conf = (struct sd_emmc_config *)&vcfg;
+#endif
+
+#ifdef SD_EMMC_CLK_CTRL
+       if (clk_ios == 0) {
+               aml_mmc_clk_switch_off(host);
+               return ret;
+       }
+
+       clk_src_sel = SD_EMMC_CLOCK_SRC_OSC;
+       if (clk_ios < 20000000)
+               clk_src_sel = SD_EMMC_CLOCK_SRC_OSC;
+       else
+               clk_src_sel = SD_EMMC_CLOCK_SRC_FCLK_DIV2;
+#endif
+
+       if (clk_ios) {
+               if (WARN_ON(clk_ios > mmc->f_max))
+                       clk_ios = mmc->f_max;
+               else if (WARN_ON(clk_ios < mmc->f_min))
+                       clk_ios = mmc->f_min;
+       }
+
+#ifdef SD_EMMC_CLK_CTRL
+       WARN_ON(clk_src_sel > SD_EMMC_CLOCK_SRC_FCLK_DIV2);
+       switch (clk_src_sel) {
+       case SD_EMMC_CLOCK_SRC_OSC:
+               clk_rate = 24000000;
+               break;
+       case SD_EMMC_CLOCK_SRC_FCLK_DIV2:
+               clk_rate = 1000000000;
+               break;
+       default:
+               pr_err("%s: clock source error: %d\n",
+                       mmc_hostname(host->mmc), clk_src_sel);
+               ret = -1;
+       }
+       clk_div = (clk_rate / clk_ios) + (!!(clk_rate % clk_ios));
+
+       aml_mmc_clk_switch(host, clk_div, clk_src_sel);
+       pdata->clkc = readl(host->base + SD_EMMC_CLOCK);
+
+       mmc->actual_clock = clk_rate / clk_div;
+#else
+       if (clk_ios == mmc->actual_clock)
+               return 0;
+
+       /* stop clock */
+       vcfg = readl(host->base + SD_EMMC_CFG);
+       if (!conf->stop_clk) {
+               conf->stop_clk = 1;
+               writel(vcfg, host->base + SD_EMMC_CFG);
+       }
+
+       dev_dbg(host->dev, "change clock rate %u -> %lu\n",
+               mmc->actual_clock, clk_ios);
+       ret = clk_set_rate(host->cfg_div_clk, clk_ios);
+       if (clk_ios && clk_ios != clk_get_rate(host->cfg_div_clk))
+               dev_warn(host->dev, "divider requested rate %lu != actual rate %lu: ret=%d\n",
+                        clk_ios, clk_get_rate(host->cfg_div_clk), ret);
+       else
+               mmc->actual_clock = clk_ios;
+
+       /* (re)start clock, if non-zero */
+       if (clk_ios) {
+               vcfg = readl(host->base + SD_EMMC_CFG);
+               conf->stop_clk = 0;
+               writel(vcfg, host->base + SD_EMMC_CFG);
+       }
+#endif
+
+       return ret;
+}
+
+static void aml_sd_emmc_set_timing_v3(struct amlsd_host *host,
+                               u32 timing)
+{
+       struct amlsd_platform *pdata = host->pdata;
+       u32 vctrl;
+       struct sd_emmc_config *ctrl = (struct sd_emmc_config *)&vctrl;
+       u32 vclkc;
+       struct sd_emmc_clock_v3 *clkc = (struct sd_emmc_clock_v3 *)&vclkc;
+       u32 adjust;
+       struct sd_emmc_adjust_v3 *gadjust = (struct sd_emmc_adjust_v3 *)&adjust;
+       u8 clk_div = 0;
+       u32 clk_rate = 1000000000;
+
+       vctrl = readl(host->base + SD_EMMC_CFG);
+       if ((timing == MMC_TIMING_MMC_HS400) ||
+                        (timing == MMC_TIMING_MMC_DDR52) ||
+                                (timing == MMC_TIMING_UHS_DDR50)) {
+               if (timing == MMC_TIMING_MMC_HS400) {
+                       /*ctrl->chk_ds = 1;*/
+                       if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX) {
+                               adjust = readl(host->base + SD_EMMC_ADJUST_V3);
+                               gadjust->ds_enable = 1;
+                               writel(adjust, host->base + SD_EMMC_ADJUST_V3);
+                               /*host->tuning_mode = AUTO_TUNING_MODE;*/
+                       }
+               }
+               vclkc = readl(host->base + SD_EMMC_CLOCK_V3);
+               ctrl->ddr = 1;
+               clk_div = clkc->div;
+               if (clk_div & 0x01)
+                       clk_div++;
+               clkc->div = clk_div / 2;
+               writel(vclkc, host->base + SD_EMMC_CLOCK_V3);
+               pdata->clkc = vclkc;
+               host->mmc->actual_clock = clk_rate / clk_div;
+               pr_info("%s: try set sd/emmc to DDR mode\n",
+                       mmc_hostname(host->mmc));
+       } else
+               ctrl->ddr = 0;
+
+       writel(vctrl, host->base + SD_EMMC_CFG);
+       sd_emmc_dbg(AMLSD_DBG_IOS, "sd emmc is %s\n",
+                       ctrl->ddr?"DDR mode":"SDR mode");
+}
+
+/*call by mmc, power on, power off ...*/
+static void aml_sd_emmc_set_power_v3(struct amlsd_host *host,
+                                       u32 power_mode)
+{
+       struct amlsd_platform *pdata = host->pdata;
+
+       switch (power_mode) {
+       case MMC_POWER_ON:
+               if (pdata->pwr_pre)
+                       pdata->pwr_pre(pdata);
+               if (pdata->pwr_on)
+                       pdata->pwr_on(pdata);
+               break;
+       case MMC_POWER_UP:
+               break;
+       case MMC_POWER_OFF:
+               writel(0, host->base + SD_EMMC_DELAY1_V3);
+               writel(0, host->base + SD_EMMC_DELAY2_V3);
+               writel(0, host->base + SD_EMMC_ADJUST_V3);
+               break;
+       default:
+               if (pdata->pwr_pre)
+                       pdata->pwr_pre(pdata);
+               if (pdata->pwr_off)
+                       pdata->pwr_off(pdata);
+               break;
+       }
+}
+
+void meson_mmc_set_ios_v3(struct mmc_host *mmc,
+                               struct mmc_ios *ios)
+{
+       struct amlsd_host *host = mmc_priv(mmc);
+       struct amlsd_platform *pdata = host->pdata;
+
+       if (!pdata->is_in)
+               return;
+       /*Set Power*/
+       aml_sd_emmc_set_power_v3(host, ios->power_mode);
+
+       /*Set Clock*/
+       meson_mmc_clk_set_rate_v3(host, ios->clock);
+
+       /*Set Bus Width*/
+       aml_sd_emmc_set_buswidth(host, ios->bus_width);
+
+       /* Set Date Mode */
+       aml_sd_emmc_set_timing_v3(host, ios->timing);
+
+       if (ios->chip_select == MMC_CS_HIGH)
+               aml_cs_high(mmc);
+       else if (ios->chip_select == MMC_CS_DONTCARE)
+               aml_cs_dont_care(mmc);
+}
+
+int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode)
+{
+       struct amlsd_host *host = mmc_priv(mmc);
+       struct aml_tuning_data tuning_data;
+       int err;
+       u32 adj_win_start = 100;
+       u32 intf3;
+
+       if (opcode == MMC_SEND_TUNING_BLOCK_HS200) {
+               if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) {
+                       tuning_data.blk_pattern = tuning_blk_pattern_8bit;
+                       tuning_data.blksz = sizeof(tuning_blk_pattern_8bit);
+               } else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
+                       tuning_data.blk_pattern = tuning_blk_pattern_4bit;
+                       tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
+               } else {
+                       return -EINVAL;
+               }
+       } else if (opcode == MMC_SEND_TUNING_BLOCK) {
+               tuning_data.blk_pattern = tuning_blk_pattern_4bit;
+               tuning_data.blksz = sizeof(tuning_blk_pattern_4bit);
+       } else {
+               sd_emmc_err("Undefined command(%d) for tuning\n", opcode);
+               return -EINVAL;
+       }
+
+       intf3 = readl(host->base + SD_EMMC_INTF3);
+       intf3 |= (1 << 22);
+       writel(intf3, host->base + SD_EMMC_INTF3);
+       err = aml_sd_emmc_execute_tuning_(mmc, opcode,
+                       &tuning_data, adj_win_start);
+
+       pr_info("%s: gclock=0x%x, gdelay1=0x%x, gdelay2=0x%x,intf3=0x%x\n",
+               mmc_hostname(mmc), readl(host->base + SD_EMMC_CLOCK_V3),
+               readl(host->base + SD_EMMC_DELAY1_V3),
+               readl(host->base + SD_EMMC_DELAY2_V3),
+               readl(host->base + SD_EMMC_INTF3));
+       return err;
+}
+
+/*static int aml_sd_emmc_cali_v3(struct mmc_host *mmc,
+ *     u8 opcode, u8 *blk_test, u32 blksz, u32 blocks)
+ *{
+ *     struct amlsd_host *host = mmc_priv(mmc);
+ *     struct mmc_request mrq = {NULL};
+ *     struct mmc_command cmd = {0};
+ *     struct mmc_command stop = {0};
+ *     struct mmc_data data = {0};
+ *     struct scatterlist sg;
+ *
+ *     cmd.opcode = opcode;
+ *     cmd.arg = ((SZ_1M * (36 + 3)) / 512);
+ *     cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+ *
+ *     stop.opcode = MMC_STOP_TRANSMISSION;
+ *     stop.arg = 0;
+ *     stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
+ *
+ *     data.blksz = blksz;
+ *     data.blocks = blocks;
+ *     data.flags = MMC_DATA_READ;
+ *     data.sg = &sg;
+ *     data.sg_len = 1;
+ *
+ *     memset(blk_test, 0, blksz * data.blocks);
+ *     sg_init_one(&sg, blk_test, blksz * data.blocks);
+ *
+ *     mrq.cmd = &cmd;
+ *     mrq.stop = &stop;
+ *     mrq.data = &data;
+ *     host->mrq = &mrq;
+ *     mmc_wait_for_req(mmc, &mrq);
+ *     return data.error | cmd.error;
+ *}
+ */
+
index 0282cf0..e803944 100644 (file)
@@ -180,6 +180,8 @@ int amlsd_get_platform_data(struct platform_device *pdev,
                                prop, pdata->vol_switch_delay);
                SD_PARSE_U32_PROP_DEC(child, "card_type",
                                prop, pdata->card_type);
+               SD_PARSE_U32_PROP_HEX(child, "pinmux_base",
+                               prop, pdata->base);
                if (get_cpu_type() > MESON_CPU_MAJOR_ID_M8B) {
                        if (aml_card_type_mmc(pdata)) {
                                /*tx_phase set default value first*/
diff --git a/include/linux/amlogic/aml_sd_emmc_internal.h b/include/linux/amlogic/aml_sd_emmc_internal.h
new file mode 100644 (file)
index 0000000..bf3bd82
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * include/linux/amlogic/aml_sd_emmc_internal.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AML_SD_EMMC_INTERNAL_H__
+
+#define __AML_SD_EMMC_INTERNAL_H__
+extern int aml_emmc_clktree_init(struct amlsd_host *host);
+
+extern int meson_mmc_clk_init_v3(struct amlsd_host *host);
+
+extern void meson_mmc_set_ios_v3(struct mmc_host *mmc, struct mmc_ios *ios);
+
+extern int aml_sd_emmc_execute_tuning_(struct mmc_host *mmc, u32 opcode,
+               struct aml_tuning_data *tuning_data, u32 adj_win_start);
+
+extern void aml_sd_emmc_set_buswidth(struct amlsd_host *host, u32 busw_ios);
+
+#endif
diff --git a/include/linux/amlogic/aml_sd_emmc_v3.h b/include/linux/amlogic/aml_sd_emmc_v3.h
new file mode 100644 (file)
index 0000000..adbc302
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * include/linux/amlogic/aml_sd_emmc_v3.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __AML_SD_EMMC_V3_H__
+
+#define __AML_SD_EMMC_V3_H__
+
+int meson_mmc_clk_init_v3(struct amlsd_host *host);
+
+void meson_mmc_set_ios_v3(struct mmc_host *mmc, struct mmc_ios *ios);
+
+int aml_mmc_execute_tuning_v3(struct mmc_host *mmc, u32 opcode);
+
+/* irqreturn_t meson_mmc_irq_v3(int irq, void *dev_id);*/
+
+/*irqreturn_t meson_mmc_irq_thread_v3(int irq, void *dev_id);*/
+/* int aml_post_hs400_timming(struct mmc_host *mmc); */
+
+/* extern ssize_t emmc_eyetest_show(struct device *dev,
+ *             struct device_attribute *attr, char *buf);
+ */
+
+/* extern ssize_t emmc_clktest_show(struct device *dev,
+ *             struct device_attribute *attr, char *buf);
+ */
+
+/* DEVICE_ATTR(emmc_eyetest, S_IRUGO, emmc_eyetest_show, NULL);*/
+/*DEVICE_ATTR(emmc_clktest, S_IRUGO, emmc_clktest_show, NULL);*/
+
+#endif
index af2c925..bbafd0e 100644 (file)
 #define AMLSD_H
 #include <linux/of_gpio.h>
 
-#define AML_MMC_MAJOR_VERSION   1
-#define AML_MMC_MINOR_VERSION   07
+#define AML_MMC_MAJOR_VERSION   3
+#define AML_MMC_MINOR_VERSION   02
 #define AML_MMC_VERSION \
        ((AML_MMC_MAJOR_VERSION << 8) | AML_MMC_MINOR_VERSION)
 #define AML_MMC_VER_MESSAGE \
-       "2015-01-21: fix a bug in tuning which caused eMMC data CRC error"
+       "2017-05-15: New Emmc Host Controller"
 
 extern unsigned long sdhc_debug;
 extern unsigned long sdio_debug;
index 19a142f..36d5c24 100644 (file)
 #define SD_EMMC_CMD_RSP2 0x64
 #define SD_EMMC_CMD_RSP3 0x68
 
+#define SD_EMMC_CLOCK_V3 0x0
+#define SD_EMMC_DELAY1_V3 0x4
+#define SD_EMMC_DELAY2_V3 0x8
+#define SD_EMMC_ADJUST_V3 0X10
+#define SD_EMMC_ADJ_IDX_LOG 0x20
+#define SD_EMMC_CLKTEST_LOG    0x24
+#define SD_EMMC_CLKTEST_OUT    0x28
+#define SD_EMMC_EYETEST_LOG    0x2C
+#define SD_EMMC_EYETEST_OUT0 0x30
+#define SD_EMMC_EYETEST_OUT1 0x34
+#define SD_EMMC_INTF3  0x38
+
 #define   CLK_DIV_SHIFT 0
 #define   CLK_DIV_WIDTH 6
 #define   CLK_DIV_MASK 0x3f
@@ -195,6 +207,7 @@ struct amlsd_platform {
        unsigned int hw_reset;
        unsigned int jtag_pin;
        int is_sduart;
+       unsigned int base;
        unsigned int card_in_delay;
        bool is_in;
        bool is_tuned;          /* if card has been tuning */
@@ -392,6 +405,7 @@ struct amlsd_host {
        int              storage_flag;
        /* bit[7-0]--minor version, bit[31-8]--major version */
        int              version;
+       int ctrl_ver;
        unsigned long   clksrc_rate;
        struct aml_emmc_adjust emmc_adj;
        struct aml_emmc_rxclk emmc_rxclk;
@@ -1102,6 +1116,47 @@ struct sd_emmc_regs {
        u32 gping[128]; /* 0x400 */
        u32 gpong[128]; /* 0x800 */
 };
+struct sd_emmc_regs_v3 {
+       u32 gclock;      /* 0x00 */
+       u32 gdelay1;     /* 0x04 */
+       u32 gdelay2;/*0x08*/
+       u32 gadjust;    /* 0x0c */
+       u32 gcalout[4]; /* 0x10~0x1c */
+       u32 adj_idx_log;/*20*/
+       u32 clktest_log;/*0x24*/
+       u32 clktest_out;/*0x28*/
+       u32 eyetest_log;/*0x2c*/
+       u32 eyetest_out0;/*0x30*/
+       u32 eyetest_out1;/*0x34*/
+       u32 intf3;/*0x38*/
+       u32 reserved3c;/*0x3c*/
+       u32 gstart;      /* 0x40 */
+       u32 gcfg;          /* 0x44 */
+       u32 gstatus;    /* 0x48 */
+       u32 girq_en;    /* 0x4c */
+       u32 gcmd_cfg;   /* 0x50 */
+       u32 gcmd_arg;   /* 0x54 */
+       u32 gcmd_dat;   /* 0x58 */
+       u32 gcmd_rsp0;   /* 0x5c */
+       u32 gcmd_rsp1;  /* 0x60 */
+       u32 gcmd_rsp2;  /* 0x64 */
+       u32 gcmd_rsp3;  /* 0x68 */
+       u32 reserved_6c;           /* 0x6c */
+       u32 gcurr_cfg;  /* 0x70 */
+       u32 gcurr_arg;  /* 0x74 */
+       u32 gcurr_dat;  /* 0x78 */
+       u32 gcurr_rsp;  /* 0x7c */
+       u32 gnext_cfg;  /* 0x80 */
+       u32 gnext_arg;  /* 0x84 */
+       u32 gnext_dat;  /* 0x88 */
+       u32 gnext_rsp;  /* 0x8c */
+       u32 grxd;          /* 0x90 */
+       u32 gtxd;          /* 0x94 */
+       u32 reserved_98[90];   /* 0x98~0x1fc */
+       u32 gdesc[128]; /* 0x200 */
+       u32 gping[128]; /* 0x400 */
+       u32 gpong[128]; /* 0x800 */
+};
 struct sd_emmc_clock {
        /*[5:0]  Clock divider.
         *Frequency = clock source/cfg_div, Maximum divider 63.
@@ -1140,6 +1195,44 @@ struct sd_emmc_clock {
        u32 irq_sdio_sleep_ds:1;
        u32 reserved27:5;
 };
+struct sd_emmc_clock_v3 {
+       /*[5:0]  Clock divider.
+        *Frequency = clock source/cfg_div, Maximum divider 63.
+        */
+       u32 div:6;
+       /*[7:6]  Clock source, 0: Crystal 24MHz, 1: Fix PLL, 850MHz*/
+       u32 src:2;
+       /*[9:8]  Core clock phase. 0: 0 phase,
+        *1: 90 phase, 2: 180 phase, 3: 270 phase.
+        */
+       u32 core_phase:2;
+       /*[11:10]   TX clock phase. 0: 0 phase,
+        *1: 90 phase, 2: 180 phase, 3: 270 phase.
+        */
+       u32 tx_phase:2;
+       /*[13:12]   RX clock phase. 0: 0 phase,
+        *1: 90 phase, 2: 180 phase, 3: 270 phase.
+        */
+       u32 rx_phase:2;
+       u32 sram_pd:2;
+       /*[19:16]   TX clock delay line. 0: no delay,
+        *n: delay n*200ps. Maximum delay 3ns.
+        */
+       u32 tx_delay:6;
+       /*[23:20]   RX clock delay line. 0: no delay,
+        *n: delay n*200ps. Maximum delay 3ns.
+        */
+       u32 rx_delay:6;
+       /*[24]    1: Keep clock always on.
+        *0: Clock on/off controlled by activities.
+        */
+       u32 always_on:1;
+       /*[25]  1: enable IRQ sdio when in sleep mode. */
+       u32 irq_sdio_sleep:1;
+       /*[26]  1: select DS as IRQ source during sleep.. */
+       u32 irq_sdio_sleep_ds:1;
+       u32 reserved31:1;
+};
 struct sd_emmc_delay {
        u32 dat0:4;              /*[3:0]           Data 0 delay line. */
        u32 dat1:4;              /*[7:4]           Data 1 delay line. */
@@ -1150,6 +1243,22 @@ struct sd_emmc_delay {
        u32 dat6:4;              /*[27:24]       Data 6 delay line. */
        u32 dat7:4;              /*[31:28]       Data 7 delay line. */
 };
+struct sd_emmc_delay1_v3 {
+       u32 dat0:6;              /*[5:0]           Data 0 delay line. */
+       u32 dat1:6;              /*[11:6]          Data 1 delay line. */
+       u32 dat2:6;              /*[17:12]        Data 2 delay line. */
+       u32 dat3:6;              /*[23:18]       Data 3 delay line. */
+       u32 dat4:6;              /*[29:24]       Data 4 delay line. */
+       u32 spare:2;             /*[31:30]       Data 5 delay line. */
+};
+struct sd_emmc_delay2_v3 {
+       u32 dat5:6;              /*[5:0]           Data 0 delay line. */
+       u32 dat6:6;              /*[11:6]          Data 1 delay line. */
+       u32 dat7:6;              /*[17:12]        Data 2 delay line. */
+       u32 dat8:6;              /*[23:18]       Data 3 delay line. */
+       u32 dat9:6;              /*[29:24]       Data 4 delay line. */
+       u32 spare:2;             /*[31:30]       Data 5 delay line. */
+};
 struct sd_emmc_adjust {
        /*[3:0]    Command delay line. */
        u32 cmd_delay:4;
@@ -1182,6 +1291,35 @@ struct sd_emmc_adjust {
        u32 adj_auto:1;
        u32 reserved22:9;
 };
+struct sd_emmc_adjust_v3 {
+       u32 reserved8:8;
+       /*[11:8]          Select one signal to be tested.*/
+       u32 cali_sel:4;
+       /*[12]          Enable calibration. */
+       u32 cali_enable:1;
+       /*[13]     Adjust interface timing
+        *by resampling the input signals.
+        */
+       u32 adj_enable:1;
+       /*[14]     1: test the rising edge.
+        *0: test the falling edge.
+        */
+       u32 cali_rise:1;
+       /*[15]     1: Sampling the DAT based on DS in HS400 mode.
+        *0: Sampling the DAT based on RXCLK.
+        */
+       u32 ds_enable:1;
+       /*[21:16]          Resample the input signals
+        *when clock index==adj_delay.
+        */
+       u32 adj_delay:6;
+       /*[22]     1: Use cali_dut first falling edge to adjust
+        *      the timing, set cali_enable to 1 to use this function.
+        *0: no use adj auto.
+        */
+       u32 adj_auto:1;
+       u32 reserved22:9;
+};
 struct sd_emmc_calout {
        /*[5:0]    Calibration reading.
         *The event happens at this index.
@@ -1196,6 +1334,39 @@ struct sd_emmc_calout {
        u32 cali_setup:8;
        u32 reserved16:16;
 };
+
+struct clktest_log {
+       u32 clktest_times:31;
+       u32 clktest_done:1;
+};
+
+struct clktest_out {
+       u32 clktest_out;
+};
+
+struct eyetest_log {
+       u32 eyetest_times:31;
+       u32 eyetest_done:1;
+};
+
+struct eyetest_out0 {
+       u32 eyetest_out0;
+};
+
+struct eyetest_out1 {
+       u32 eyetest_out1;
+};
+
+struct intf3 {
+       u32 clktest_exp:5;  /*[4:0]*/
+       u32 clktest_on_m:1; /*[5]*/
+       u32 eyetest_exp:5;  /*[10:6]*/
+       u32 eyetest_on:1;   /*[11]*/
+       u32 ds_sht_m:6;     /*[17:12]*/
+       u32 ds_sht_exp:4;   /*[21:18]*/
+       u32 sd_intf3:1;     /*[22]*/
+};
+
 struct sd_emmc_start {
        /*[0]   1: Read descriptor from internal SRAM,
         *limited to 32 descriptors.
@@ -1378,10 +1549,12 @@ struct sd_emmc_desc_info {
        u32 data_addr;
        u32 resp_addr;
 };
+#define P_HHI_NAND_CLK_CNTL                    (0xff63c000 + (0x97 << 2))
 #define SD_EMMC_MAX_DESC_MUN                                   512
 #define SD_EMMC_REQ_DESC_MUN                                   4
 #define SD_EMMC_CLOCK_SRC_OSC                           0 /* 24MHz */
 #define SD_EMMC_CLOCK_SRC_FCLK_DIV2               1 /* 1GHz */
+#define SD_EMMC_CLOCK_SRC_400MHZ                       4
 #define SD_EMMC_CLOCK_SRC_MPLL                         2 /* MPLL */
 #define SD_EMMC_CLOCK_SRC_DIFF_PLL                     3
 #define SD_EMMC_IRQ_ALL                                        0x3fff