Commit 06c8b667 authored by Hu Ziji's avatar Hu Ziji Committed by Ulf Hansson

mmc: sdhci-xenon: Add support to PHYs of Marvell Xenon SDHC

Marvell Xenon eMMC/SD/SDIO Host Controller contains PHY.
Multiple types of PHYs are supported.

Add support to multiple types of PHYs init and configuration.
Add register definitions of PHYs.

Xenon PHY cannot fit in kernel common PHY framework.
Xenon SDHC PHY register is a part of Xenon SDHC register set.
Besides, MMC initialization has to call several PHY functions to
complete timing setting.
Those PHY setting functions have to access SDHC registers and know
current MMC setting, such as bus width, clock frequency and
speed mode.
As a result, implement Xenon PHY in MMC host directory.
Signed-off-by: default avatarHu Ziji <huziji@marvell.com>
Signed-off-by: default avatarGregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 3a3748db
...@@ -88,4 +88,4 @@ ifeq ($(CONFIG_CB710_DEBUG),y) ...@@ -88,4 +88,4 @@ ifeq ($(CONFIG_CB710_DEBUG),y)
endif endif
obj-$(CONFIG_MMC_SDHCI_XENON) += sdhci-xenon-driver.o obj-$(CONFIG_MMC_SDHCI_XENON) += sdhci-xenon-driver.o
sdhci-xenon-driver-y += sdhci-xenon.o sdhci-xenon-driver-y += sdhci-xenon.o sdhci-xenon-phy.o
This diff is collapsed.
...@@ -257,6 +257,7 @@ static void xenon_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -257,6 +257,7 @@ static void xenon_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
} }
sdhci_set_ios(mmc, ios); sdhci_set_ios(mmc, ios);
xenon_phy_adj(host, ios);
if (host->clock > XENON_DEFAULT_SDCLK_FREQ) if (host->clock > XENON_DEFAULT_SDCLK_FREQ)
xenon_set_sdclk_off_idle(host, priv->sdhc_id, true); xenon_set_sdclk_off_idle(host, priv->sdhc_id, true);
...@@ -401,7 +402,7 @@ static int xenon_probe_dt(struct platform_device *pdev) ...@@ -401,7 +402,7 @@ static int xenon_probe_dt(struct platform_device *pdev)
} }
priv->tuning_count = tuning_count; priv->tuning_count = tuning_count;
return 0; return xenon_phy_parse_dt(np, host);
} }
static int xenon_sdhc_prepare(struct sdhci_host *host) static int xenon_sdhc_prepare(struct sdhci_host *host)
...@@ -483,7 +484,7 @@ static int xenon_probe(struct platform_device *pdev) ...@@ -483,7 +484,7 @@ static int xenon_probe(struct platform_device *pdev)
err = xenon_sdhc_prepare(host); err = xenon_sdhc_prepare(host);
if (err) if (err)
goto err_clk; goto clean_phy_param;
err = sdhci_add_host(host); err = sdhci_add_host(host);
if (err) if (err)
...@@ -493,6 +494,8 @@ static int xenon_probe(struct platform_device *pdev) ...@@ -493,6 +494,8 @@ static int xenon_probe(struct platform_device *pdev)
remove_sdhc: remove_sdhc:
xenon_sdhc_unprepare(host); xenon_sdhc_unprepare(host);
clean_phy_param:
xenon_clean_phy(host);
err_clk: err_clk:
clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(pltfm_host->clk);
free_pltfm: free_pltfm:
...@@ -505,6 +508,8 @@ static int xenon_remove(struct platform_device *pdev) ...@@ -505,6 +508,8 @@ static int xenon_remove(struct platform_device *pdev)
struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_host *host = platform_get_drvdata(pdev);
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
xenon_clean_phy(host);
xenon_sdhc_unprepare(host); xenon_sdhc_unprepare(host);
sdhci_remove_host(host, 0); sdhci_remove_host(host, 0);
......
...@@ -24,15 +24,32 @@ ...@@ -24,15 +24,32 @@
#define XENON_SYS_EXT_OP_CTRL 0x010C #define XENON_SYS_EXT_OP_CTRL 0x010C
#define XENON_MASK_CMD_CONFLICT_ERR BIT(8) #define XENON_MASK_CMD_CONFLICT_ERR BIT(8)
#define XENON_SLOT_OP_STATUS_CTRL 0x0128
#define XENON_TUN_CONSECUTIVE_TIMES_SHIFT 16
#define XENON_TUN_CONSECUTIVE_TIMES_MASK 0x7
#define XENON_TUN_CONSECUTIVE_TIMES 0x4
#define XENON_TUNING_STEP_SHIFT 12
#define XENON_TUNING_STEP_MASK 0xF
#define XENON_TUNING_STEP_DIVIDER BIT(6)
#define XENON_SLOT_EMMC_CTRL 0x0130
#define XENON_ENABLE_DATA_STROBE BIT(24)
#define XENON_SLOT_RETUNING_REQ_CTRL 0x0144 #define XENON_SLOT_RETUNING_REQ_CTRL 0x0144
/* retuning compatible */ /* retuning compatible */
#define XENON_RETUNING_COMPATIBLE 0x1 #define XENON_RETUNING_COMPATIBLE 0x1
#define XENON_SLOT_EXT_PRESENT_STATE 0x014C
#define XENON_DLL_LOCK_STATE 0x1
#define XENON_SLOT_DLL_CUR_DLY_VAL 0x0150
/* Tuning Parameter */ /* Tuning Parameter */
#define XENON_TMR_RETUN_NO_PRESENT 0xF #define XENON_TMR_RETUN_NO_PRESENT 0xF
#define XENON_DEF_TUNING_COUNT 0x9 #define XENON_DEF_TUNING_COUNT 0x9
#define XENON_DEFAULT_SDCLK_FREQ 400000 #define XENON_DEFAULT_SDCLK_FREQ 400000
#define XENON_LOWEST_SDCLK_FREQ 100000
/* Xenon specific Mode Select value */ /* Xenon specific Mode Select value */
#define XENON_CTRL_HS200 0x5 #define XENON_CTRL_HS200 0x5
...@@ -55,6 +72,28 @@ struct xenon_priv { ...@@ -55,6 +72,28 @@ struct xenon_priv {
* initialization completes. * initialization completes.
*/ */
unsigned int init_card_type; unsigned int init_card_type;
/*
* The bus_width, timing, and clock fields in below
* record the current ios setting of Xenon SDHC.
* Driver will adjust PHY setting if any change to
* ios affects PHY timing.
*/
unsigned char bus_width;
unsigned char timing;
unsigned int clock;
int phy_type;
/*
* Contains board-specific PHY parameters
* passed from device tree.
*/
void *phy_params;
struct xenon_emmc_phy_regs *emmc_phy_regs;
}; };
int xenon_phy_adj(struct sdhci_host *host, struct mmc_ios *ios);
void xenon_clean_phy(struct sdhci_host *host);
int xenon_phy_parse_dt(struct device_node *np,
struct sdhci_host *host);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment