diff options
author | Tom Rini <trini@konsulko.com> | 2020-11-16 18:50:32 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-11-16 18:50:32 +0300 |
commit | 530dcdd07c9870bcb22e40a72d9ffe2afc513117 (patch) | |
tree | 8bd83da4fa8d9a43d5d217f9f931256f43985634 /drivers | |
parent | e1fdb2045ad02c9d8bc5972db8f0536518c7330e (diff) | |
parent | c87eab81616d671a6004ffc95847bad21b7eb005 (diff) | |
download | u-boot-530dcdd07c9870bcb22e40a72d9ffe2afc513117.tar.xz |
Merge tag 'u-boot-amlogic-20201116' of https://gitlab.denx.de/u-boot/custodians/u-boot-amlogic
- Clock fix MMC driver for SM1 based platforms
- sync SOC Ids from Linux 5.10-rc1
- fix potential build warning on meson_dw_hdmi and meson-g12a-usb2 phy
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/meson_gx_mmc.c | 29 | ||||
-rw-r--r-- | drivers/mmc/meson_gx_mmc.h | 94 | ||||
-rw-r--r-- | drivers/phy/meson-g12a-usb2.c | 4 | ||||
-rw-r--r-- | drivers/video/meson/meson_dw_hdmi.c | 2 |
4 files changed, 122 insertions, 7 deletions
diff --git a/drivers/mmc/meson_gx_mmc.c b/drivers/mmc/meson_gx_mmc.c index 719dd1e5e5..a5e9ac5637 100644 --- a/drivers/mmc/meson_gx_mmc.c +++ b/drivers/mmc/meson_gx_mmc.c @@ -13,9 +13,17 @@ #include <mmc.h> #include <asm/io.h> #include <asm/gpio.h> -#include <asm/arch/sd_emmc.h> #include <linux/delay.h> #include <linux/log2.h> +#include "meson_gx_mmc.h" + +bool meson_gx_mmc_is_compatible(struct udevice *dev, + enum meson_gx_mmc_compatible family) +{ + enum meson_gx_mmc_compatible compat = dev_get_driver_data(dev); + + return compat == family; +} static inline void *get_regbase(const struct mmc *mmc) { @@ -42,6 +50,8 @@ static void meson_mmc_config_clock(struct mmc *mmc) if (!mmc->clock) return; + /* TOFIX This should use the proper clock taken from DT */ + /* 1GHz / CLK_MAX_DIV = 15,9 MHz */ if (mmc->clock > 16000000) { clk = SD_EMMC_CLKSRC_DIV2; @@ -52,8 +62,16 @@ static void meson_mmc_config_clock(struct mmc *mmc) } clk_div = DIV_ROUND_UP(clk, mmc->clock); - /* 180 phase core clock */ - meson_mmc_clk |= CLK_CO_PHASE_180; + /* + * SM1 SoCs doesn't work fine over 50MHz with CLK_CO_PHASE_180 + * If CLK_CO_PHASE_270 is used, it's more stable than other. + * Other SoCs use CLK_CO_PHASE_180 by default. + * It needs to find what is a proper value about each SoCs. + */ + if (meson_gx_mmc_is_compatible(mmc->dev, MMC_COMPATIBLE_SM1)) + meson_mmc_clk |= CLK_CO_PHASE_270; + else + meson_mmc_clk |= CLK_CO_PHASE_180; /* 180 phase tx clock */ meson_mmc_clk |= CLK_TX_PHASE_000; @@ -308,8 +326,9 @@ int meson_mmc_bind(struct udevice *dev) } static const struct udevice_id meson_mmc_match[] = { - { .compatible = "amlogic,meson-gx-mmc" }, - { .compatible = "amlogic,meson-axg-mmc" }, + { .compatible = "amlogic,meson-gx-mmc", .data = MMC_COMPATIBLE_GX }, + { .compatible = "amlogic,meson-axg-mmc", .data = MMC_COMPATIBLE_GX }, + { .compatible = "amlogic,meson-sm1-mmc", .data = MMC_COMPATIBLE_SM1 }, { /* sentinel */ } }; diff --git a/drivers/mmc/meson_gx_mmc.h b/drivers/mmc/meson_gx_mmc.h new file mode 100644 index 0000000000..92aec5329f --- /dev/null +++ b/drivers/mmc/meson_gx_mmc.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2016 Carlo Caione <carlo@caione.org> + */ + +#ifndef __MESON_GX_MMC_H__ +#define __MESON_GX_MMC_H__ + +#include <mmc.h> +#include <linux/bitops.h> + +enum meson_gx_mmc_compatible { + MMC_COMPATIBLE_GX, + MMC_COMPATIBLE_SM1, +}; + +#define SDIO_PORT_A 0 +#define SDIO_PORT_B 1 +#define SDIO_PORT_C 2 + +#define SD_EMMC_CLKSRC_24M 24000000 /* 24 MHz */ +#define SD_EMMC_CLKSRC_DIV2 1000000000 /* 1 GHz */ + +#define MESON_SD_EMMC_CLOCK 0x00 +#define CLK_MAX_DIV 63 +#define CLK_SRC_24M (0 << 6) +#define CLK_SRC_DIV2 (1 << 6) +#define CLK_CO_PHASE_000 (0 << 8) +#define CLK_CO_PHASE_090 (1 << 8) +#define CLK_CO_PHASE_180 (2 << 8) +#define CLK_CO_PHASE_270 (3 << 8) +#define CLK_TX_PHASE_000 (0 << 10) +#define CLK_TX_PHASE_090 (1 << 10) +#define CLK_TX_PHASE_180 (2 << 10) +#define CLK_TX_PHASE_270 (3 << 10) +#define CLK_ALWAYS_ON BIT(24) + +#define MESON_SD_EMMC_CFG 0x44 +#define CFG_BUS_WIDTH_MASK GENMASK(1, 0) +#define CFG_BUS_WIDTH_1 0 +#define CFG_BUS_WIDTH_4 1 +#define CFG_BUS_WIDTH_8 2 +#define CFG_BL_LEN_MASK GENMASK(7, 4) +#define CFG_BL_LEN_SHIFT 4 +#define CFG_BL_LEN_512 (9 << 4) +#define CFG_RESP_TIMEOUT_MASK GENMASK(11, 8) +#define CFG_RESP_TIMEOUT_256 (8 << 8) +#define CFG_RC_CC_MASK GENMASK(15, 12) +#define CFG_RC_CC_16 (4 << 12) +#define CFG_SDCLK_ALWAYS_ON BIT(18) +#define CFG_AUTO_CLK BIT(23) + +#define MESON_SD_EMMC_STATUS 0x48 +#define STATUS_MASK GENMASK(15, 0) +#define STATUS_ERR_MASK GENMASK(12, 0) +#define STATUS_RXD_ERR_MASK GENMASK(7, 0) +#define STATUS_TXD_ERR BIT(8) +#define STATUS_DESC_ERR BIT(9) +#define STATUS_RESP_ERR BIT(10) +#define STATUS_RESP_TIMEOUT BIT(11) +#define STATUS_DESC_TIMEOUT BIT(12) +#define STATUS_END_OF_CHAIN BIT(13) + +#define MESON_SD_EMMC_IRQ_EN 0x4c + +#define MESON_SD_EMMC_CMD_CFG 0x50 +#define CMD_CFG_LENGTH_MASK GENMASK(8, 0) +#define CMD_CFG_BLOCK_MODE BIT(9) +#define CMD_CFG_R1B BIT(10) +#define CMD_CFG_END_OF_CHAIN BIT(11) +#define CMD_CFG_TIMEOUT_4S (12 << 12) +#define CMD_CFG_NO_RESP BIT(16) +#define CMD_CFG_DATA_IO BIT(18) +#define CMD_CFG_DATA_WR BIT(19) +#define CMD_CFG_RESP_NOCRC BIT(20) +#define CMD_CFG_RESP_128 BIT(21) +#define CMD_CFG_CMD_INDEX_SHIFT 24 +#define CMD_CFG_OWNER BIT(31) + +#define MESON_SD_EMMC_CMD_ARG 0x54 +#define MESON_SD_EMMC_CMD_DAT 0x58 +#define MESON_SD_EMMC_CMD_RSP 0x5c +#define MESON_SD_EMMC_CMD_RSP1 0x60 +#define MESON_SD_EMMC_CMD_RSP2 0x64 +#define MESON_SD_EMMC_CMD_RSP3 0x68 + +struct meson_mmc_platdata { + struct mmc_config cfg; + struct mmc mmc; + void *regbase; + void *w_buf; +}; + +#endif diff --git a/drivers/phy/meson-g12a-usb2.c b/drivers/phy/meson-g12a-usb2.c index a1e6219758..447ce7283d 100644 --- a/drivers/phy/meson-g12a-usb2.c +++ b/drivers/phy/meson-g12a-usb2.c @@ -66,10 +66,10 @@ struct phy_meson_g12a_usb2_priv { static int phy_meson_g12a_usb2_power_on(struct phy *phy) { +#if CONFIG_IS_ENABLED(DM_REGULATOR) struct udevice *dev = phy->dev; struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev); -#if CONFIG_IS_ENABLED(DM_REGULATOR) if (priv->phy_supply) { int ret = regulator_set_enable(priv->phy_supply, true); if (ret) @@ -82,10 +82,10 @@ static int phy_meson_g12a_usb2_power_on(struct phy *phy) static int phy_meson_g12a_usb2_power_off(struct phy *phy) { +#if CONFIG_IS_ENABLED(DM_REGULATOR) struct udevice *dev = phy->dev; struct phy_meson_g12a_usb2_priv *priv = dev_get_priv(dev); -#if CONFIG_IS_ENABLED(DM_REGULATOR) if (priv->phy_supply) { int ret = regulator_set_enable(priv->phy_supply, false); if (ret) { diff --git a/drivers/video/meson/meson_dw_hdmi.c b/drivers/video/meson/meson_dw_hdmi.c index 7b2ff94eba..5d74f7f1a7 100644 --- a/drivers/video/meson/meson_dw_hdmi.c +++ b/drivers/video/meson/meson_dw_hdmi.c @@ -379,7 +379,9 @@ static int meson_dw_hdmi_probe(struct udevice *dev) struct meson_dw_hdmi *priv = dev_get_priv(dev); struct reset_ctl_bulk resets; struct clk_bulk clocks; +#if CONFIG_IS_ENABLED(DM_REGULATOR) struct udevice *supply; +#endif int ret; priv->dev = dev; |