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
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 / */
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{
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{
};
};
+ 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 */
# 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
#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)
}
/* 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)
{
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;
}
/*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;
.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;
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);
}
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;
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;
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);
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;
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 */
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 */
--- /dev/null
+/*
+ * 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;
+ *}
+ */
+
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*/
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
#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;
#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
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 */
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;
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.
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. */
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;
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.
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.
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