diff options
Diffstat (limited to 'drivers')
73 files changed, 4715 insertions, 293 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 4fbb63a148a..29ceab849c0 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -1,6 +1,7 @@ config AHCI bool "Support SATA controllers with driver model" depends on DM + select BLK help This enables a uclass for disk controllers in U-Boot. Various driver types can use this, such as AHCI/SATA. It does not provide any standard @@ -9,6 +10,7 @@ config AHCI config SATA bool "Support SATA controllers" + select BLK help This enables support for SATA (Serial Advanced Technology Attachment), a serial bus standard for connecting to hard drives and diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 5283d8981e0..cc75bad02b8 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -1,8 +1,5 @@ config BLK - bool # "Support block devices" - depends on DM - def_bool y if MMC || USB || SCSI || NVME || IDE || AHCI || SATA - def_bool y if EFI_MEDIA || VIRTIO_BLK || PVBLOCK + bool help Enable support for block devices, such as SCSI, MMC and USB flash sticks. These provide a block-level interface which permits @@ -100,6 +97,7 @@ config TPL_BLOCK_CACHE config EFI_MEDIA bool "Support EFI media drivers" default y if EFI || SANDBOX + select BLK help Enable this to support media devices on top of UEFI. This enables just the uclass so you also need a specific driver to make this do @@ -139,6 +137,7 @@ endif # EFI_MEDIA config IDE bool "Support IDE controllers" + select BLK help Enables support for IDE (Integrated Drive Electronics) hard drives. This allows access to raw blocks and filesystems on an IDE drive diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index ad7fed3ddaa..f9f0948ae09 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -15,6 +15,7 @@ #include <power/pmic.h> #include <spmi/spmi.h> #include <linux/bitops.h> +#include <time.h> #define REG_TYPE 0x4 #define REG_SUBTYPE 0x5 @@ -31,6 +32,7 @@ struct qcom_pmic_btn_priv { u32 status_bit; int code; struct udevice *pmic; + ulong last_release_time; }; #define PON_INT_RT_STS 0x10 @@ -42,13 +44,21 @@ struct qcom_pmic_btn_priv { static enum button_state_t qcom_pwrkey_get_state(struct udevice *dev) { struct qcom_pmic_btn_priv *priv = dev_get_priv(dev); + bool pressed; + int reg; - int reg = pmic_reg_read(priv->pmic, priv->base + PON_INT_RT_STS); + if (get_timer_us(0) - priv->last_release_time < 25000) + return BUTTON_OFF; + reg = pmic_reg_read(priv->pmic, priv->base + PON_INT_RT_STS); if (reg < 0) return 0; - return (reg & BIT(priv->status_bit)) != 0; + pressed = !!(reg & BIT(priv->status_bit)); + if (!pressed) + priv->last_release_time = get_timer_us(0); + + return pressed; } static int qcom_pwrkey_get_code(struct udevice *dev) diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index 380ab9b9b0b..94fc5e51456 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -574,6 +574,18 @@ static const struct mtk_clk_tree mt7629_clk_tree = { .muxes = top_muxes, }; +static const struct mtk_clk_tree mt7629_peri_clk_tree = { + .xtal_rate = 40 * MHZ, + .xtal2_rate = 20 * MHZ, + .gates_offs = CLK_PERI_PWM1_PD, + .fdivs_offs = CLK_TOP_TO_USB3_SYS, + .muxes_offs = CLK_TOP_AXI_SEL, + .plls = apmixed_plls, + .fclks = top_fixed_clks, + .fdivs = top_fixed_divs, + .muxes = top_muxes, +}; + static int mt7629_mcucfg_probe(struct udevice *dev) { void __iomem *base; @@ -619,7 +631,7 @@ static int mt7629_infracfg_probe(struct udevice *dev) static int mt7629_pericfg_probe(struct udevice *dev) { - return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, peri_cgs); + return mtk_common_clk_gate_init(dev, &mt7629_peri_clk_tree, peri_cgs); } static int mt7629_ethsys_probe(struct udevice *dev) diff --git a/drivers/clk/mediatek/clk-mt7981.c b/drivers/clk/mediatek/clk-mt7981.c index 97073918006..60814652322 100644 --- a/drivers/clk/mediatek/clk-mt7981.c +++ b/drivers/clk/mediatek/clk-mt7981.c @@ -359,6 +359,7 @@ static const struct mtk_parent infra_pcie_parents[] = { .id = _id, .mux_reg = (_reg) + 0x8, \ .mux_set_reg = (_reg) + 0x0, .mux_clr_reg = (_reg) + 0x4, \ .mux_shift = _shift, .mux_mask = BIT(_width) - 1, \ + .gate_shift = -1, .upd_shift = -1, \ .parent_flags = _parents, .num_parents = ARRAY_SIZE(_parents), \ .flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_MIXED, \ } diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c index c5cc77243d0..f9d6f9c1749 100644 --- a/drivers/clk/mediatek/clk-mt7986.c +++ b/drivers/clk/mediatek/clk-mt7986.c @@ -366,6 +366,7 @@ static const struct mtk_parent infra_pcie_parents[] = { .id = _id, .mux_reg = (_reg) + 0x8, \ .mux_set_reg = (_reg) + 0x0, .mux_clr_reg = (_reg) + 0x4, \ .mux_shift = _shift, .mux_mask = BIT(_width) - 1, \ + .gate_shift = -1, .upd_shift = -1, \ .parent_flags = _parents, .num_parents = ARRAY_SIZE(_parents), \ .flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_MIXED, \ } diff --git a/drivers/clk/mediatek/clk-mt7988.c b/drivers/clk/mediatek/clk-mt7988.c index 8f4e8f4e8c9..73fd9c6bea6 100644 --- a/drivers/clk/mediatek/clk-mt7988.c +++ b/drivers/clk/mediatek/clk-mt7988.c @@ -485,6 +485,7 @@ static const int infra_pcie_gfmux_tl_ck_o_p3_parents[] = { .id = _id, .mux_reg = _reg + 0x8, .mux_set_reg = _reg + 0x0, \ .mux_clr_reg = _reg + 0x4, .mux_shift = _shift, \ .mux_mask = BIT(_width) - 1, .parent = _parents, \ + .gate_shift = -1, .upd_shift = -1, \ .num_parents = ARRAY_SIZE(_parents), \ .flags = CLK_MUX_SETCLR_UPD | CLK_PARENT_TOPCKGEN, \ } diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index d76fca5dba4..cb867acc48c 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -47,6 +47,14 @@ config CLK_QCOM_QCS404 on the Snapdragon QCS404 SoC. This driver supports the clocks and resets exposed by the GCC hardware block. +config CLK_QCOM_SA8775P + bool "Qualcomm SA8775 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon SA8775 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + config CLK_QCOM_SDM845 bool "Qualcomm SDM845 GCC" select CLK_QCOM @@ -103,6 +111,14 @@ config CLK_QCOM_SC7280 on the Snapdragon SC7280 SoC. This driver supports the clocks and resets exposed by the GCC hardware block. +config CLK_QCOM_X1E80100 + bool "Qualcomm X1E80100 GCC" + select CLK_QCOM + help + Say Y here to enable support for the Global Clock Controller + on the Snapdragon X1E80100 SoC. This driver supports the clocks + and resets exposed by the GCC hardware block. + endmenu endif diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index ab33f1c5faf..1bc0f15005b 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -9,9 +9,11 @@ obj-$(CONFIG_CLK_QCOM_APQ8096) += clock-apq8096.o obj-$(CONFIG_CLK_QCOM_IPQ4019) += clock-ipq4019.o obj-$(CONFIG_CLK_QCOM_QCM2290) += clock-qcm2290.o obj-$(CONFIG_CLK_QCOM_QCS404) += clock-qcs404.o +obj-$(CONFIG_CLK_QCOM_SA8775P) += clock-sa8775p.o obj-$(CONFIG_CLK_QCOM_SC7280) += clock-sc7280.o obj-$(CONFIG_CLK_QCOM_SM6115) += clock-sm6115.o obj-$(CONFIG_CLK_QCOM_SM8150) += clock-sm8150.o obj-$(CONFIG_CLK_QCOM_SM8250) += clock-sm8250.o obj-$(CONFIG_CLK_QCOM_SM8550) += clock-sm8550.o obj-$(CONFIG_CLK_QCOM_SM8650) += clock-sm8650.o +obj-$(CONFIG_CLK_QCOM_X1E80100) += clock-x1e80100.o diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index 25ca67e537d..7687bbe6a23 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -166,6 +166,25 @@ void clk_rcg_set_rate(phys_addr_t base, uint32_t cmd_rcgr, int div, clk_bcr_update(base + cmd_rcgr); } +#define PHY_MUX_MASK GENMASK(1, 0) +#define PHY_MUX_PHY_SRC 0 +#define PHY_MUX_REF_SRC 2 + +void clk_phy_mux_enable(phys_addr_t base, uint32_t cmd_rcgr, bool enabled) +{ + u32 cfg; + + /* setup src select and divider */ + cfg = readl(base + cmd_rcgr); + cfg &= ~(PHY_MUX_MASK); + if (enabled) + cfg |= FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC); + else + cfg |= FIELD_PREP(PHY_MUX_MASK, PHY_MUX_REF_SRC); + + writel(cfg, base + cmd_rcgr); +} + const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) { if (!f) diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index 78d9b1d81ec..ff336dea39c 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -6,6 +6,7 @@ #define _CLOCK_QCOM_H #include <asm/io.h> +#include <linux/bitfield.h> #define CFG_CLK_SRC_CXO (0 << 8) #define CFG_CLK_SRC_GPLL0 (1 << 8) @@ -102,6 +103,7 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, uint32_t cmd_rcgr, int div, int m, int n, int source, u8 mnd_width); void clk_rcg_set_rate(phys_addr_t base, uint32_t cmd_rcgr, int div, int source); +void clk_phy_mux_enable(phys_addr_t base, uint32_t cmd_rcgr, bool enabled); static inline void qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) { diff --git a/drivers/clk/qcom/clock-sa8775p.c b/drivers/clk/qcom/clock-sa8775p.c new file mode 100644 index 00000000000..e31f24ed4f0 --- /dev/null +++ b/drivers/clk/qcom/clock-sa8775p.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Clock drivers for Qualcomm sa8775p + * + * (C) Copyright 2024 Linaro Ltd. + */ + +#include <linux/types.h> +#include <clk-uclass.h> +#include <dm.h> +#include <linux/delay.h> +#include <asm/io.h> +#include <linux/bug.h> +#include <linux/bitops.h> +#include <dt-bindings/clock/qcom,sa8775p-gcc.h> +#include "clock-qcom.h" + +#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038 +#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf020 + +static ulong sa8775p_set_rate(struct clk *clk, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + if (clk->id < priv->data->num_clks) + debug("%s: %s, requested rate=%ld\n", __func__, + priv->data->clks[clk->id].name, rate); + + switch (clk->id) { + case GCC_USB30_PRIM_MOCK_UTMI_CLK: + WARN(rate != 19200000, "Unexpected rate for USB30_PRIM_MOCK_UTMI_CLK: %lu\n", rate); + clk_rcg_set_rate(priv->base, USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR, 0, CFG_CLK_SRC_CXO); + return rate; + case GCC_USB30_PRIM_MASTER_CLK: + WARN(rate != 200000000, "Unexpected rate for USB30_PRIM_MASTER_CLK: %lu\n", rate); + clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, + 1, 0, 0, CFG_CLK_SRC_GPLL0_ODD, 8); + clk_rcg_set_rate(priv->base, 0xf064, 0, 0); + return rate; + default: + return 0; + } +} + +static const struct gate_clk sa8775p_clks[] = { + GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x1b088, 1), + GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x1b018, 1), + GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0x1b084, 1), + GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x1b020, 1), + GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x1b024, 1), + GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x1b05c, 1), + GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x1b060, 1), +}; + +static int sa8775p_enable(struct clk *clk) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + if (priv->data->num_clks < clk->id) { + debug("%s: unknown clk id %lu\n", __func__, clk->id); + return 0; + } + + debug("%s: clk %ld: %s\n", __func__, clk->id, sa8775p_clks[clk->id].name); + + switch (clk->id) { + case GCC_AGGRE_USB3_PRIM_AXI_CLK: + qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK); + fallthrough; + case GCC_USB30_PRIM_MASTER_CLK: + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK); + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK); + break; + } + + qcom_gate_clk_en(priv, clk->id); + + return 0; +} + +static const struct qcom_reset_map sa8775p_gcc_resets[] = { + [GCC_CAMERA_BCR] = { 0x32000 }, + [GCC_DISPLAY1_BCR] = { 0xC7000 }, + [GCC_DISPLAY_BCR] = { 0x33000 }, + [GCC_EMAC0_BCR] = { 0xB6000 }, + [GCC_EMAC1_BCR] = { 0xB4000 }, + [GCC_GPU_BCR] = { 0x7D000 }, + [GCC_MMSS_BCR] = { 0x17000 }, + [GCC_PCIE_0_BCR] = { 0xa9000 }, + [GCC_PCIE_0_LINK_DOWN_BCR] = { 0xBF000 }, + [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0xBF008 }, + [GCC_PCIE_0_PHY_BCR] = { 0xAD144 }, + [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0xBF00C }, + [GCC_PCIE_1_BCR] = { 0x77000 }, + [GCC_PCIE_1_LINK_DOWN_BCR] = { 0xAE084 }, + [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0xAE090 }, + [GCC_PCIE_1_PHY_BCR] = { 0xAE08C }, + [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0xAE094 }, + [GCC_PDM_BCR] = { 0x3F000 }, + [GCC_QUPV3_WRAPPER_0_BCR] = { 0x23000 }, + [GCC_QUPV3_WRAPPER_1_BCR] = { 0x24000 }, + [GCC_QUPV3_WRAPPER_2_BCR] = { 0x2A000 }, + [GCC_QUPV3_WRAPPER_3_BCR] = { 0xC4000 }, + [GCC_SDCC1_BCR] = { 0x20000 }, + [GCC_TSCSS_BCR] = { 0x21000 }, + [GCC_UFS_CARD_BCR] = { 0x81000 }, + [GCC_UFS_PHY_BCR] = { 0x83000 }, +}; + +static const struct qcom_power_map sa8775p_gdscs[] = { + [UFS_PHY_GDSC] = { 0x83004 }, + [USB30_PRIM_GDSC] = { 0x1B004 }, +}; + +static struct msm_clk_data sa8775_gcc_data = { + .resets = sa8775p_gcc_resets, + .num_resets = ARRAY_SIZE(sa8775p_gcc_resets), + .clks = sa8775p_clks, + .num_clks = ARRAY_SIZE(sa8775p_clks), + + .power_domains = sa8775p_gdscs, + .num_power_domains = ARRAY_SIZE(sa8775p_gdscs), + + .enable = sa8775p_enable, + .set_rate = sa8775p_set_rate, +}; + +static const struct udevice_id gcc_sa8775p_of_match[] = { + { + .compatible = "qcom,sa8775p-gcc", + .data = (ulong)&sa8775_gcc_data, + }, + { } +}; + +U_BOOT_DRIVER(gcc_sa8775p) = { + .name = "gcc_sa8775p", + .id = UCLASS_NOP, + .of_match = gcc_sa8775p_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; diff --git a/drivers/clk/qcom/clock-sm8550.c b/drivers/clk/qcom/clock-sm8550.c index c0249925cc7..62b5a409e8e 100644 --- a/drivers/clk/qcom/clock-sm8550.c +++ b/drivers/clk/qcom/clock-sm8550.c @@ -57,6 +57,16 @@ static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { { } }; +static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = { + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = { + F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0), + { } +}; + static ulong sm8550_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -84,6 +94,24 @@ static ulong sm8550_set_rate(struct clk *clk, ulong rate) case GCC_USB3_PRIM_PHY_AUX_CLK_SRC: clk_rcg_set_rate(priv->base, 0x39070, 0, 0); return TCXO_DIV2_RATE; + case GCC_PCIE_0_AUX_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_aux_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x6b074, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_PCIE_1_AUX_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_aux_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x8d07c, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_PCIE_0_PHY_RCHNG_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_phy_rchng_clk_src, rate); + clk_rcg_set_rate(priv->base, 0x6b058, freq->pre_div, freq->src); + return freq->freq; + case GCC_PCIE_1_PHY_RCHNG_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_phy_rchng_clk_src, rate); + clk_rcg_set_rate(priv->base, 0x8d060, freq->pre_div, freq->src); + return freq->freq; default: return 0; } @@ -182,6 +210,14 @@ static int sm8550_enable(struct clk *clk) qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK); qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK); break; + case GCC_PCIE_0_PIPE_CLK: + // GCC_PCIE_0_PIPE_CLK_SRC + clk_phy_mux_enable(priv->base, 0x6b070, true); + break; + case GCC_PCIE_1_PIPE_CLK: + // GCC_PCIE_1_PIPE_CLK_SRC + clk_phy_mux_enable(priv->base, 0x8d078, true); + break; } qcom_gate_clk_en(priv, clk->id); diff --git a/drivers/clk/qcom/clock-sm8650.c b/drivers/clk/qcom/clock-sm8650.c index 0ce83e9b243..9baaecb571f 100644 --- a/drivers/clk/qcom/clock-sm8650.c +++ b/drivers/clk/qcom/clock-sm8650.c @@ -54,6 +54,16 @@ static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { { } }; +static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = { + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = { + F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0), + { } +}; + static ulong sm8650_set_rate(struct clk *clk, ulong rate) { struct msm_clk_priv *priv = dev_get_priv(clk->dev); @@ -81,6 +91,24 @@ static ulong sm8650_set_rate(struct clk *clk, ulong rate) case GCC_USB3_PRIM_PHY_AUX_CLK_SRC: clk_rcg_set_rate(priv->base, 0x39070, 0, 0); return TCXO_DIV2_RATE; + case GCC_PCIE_0_AUX_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_aux_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x6b074, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_PCIE_1_AUX_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_aux_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x8d07c, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_PCIE_0_PHY_RCHNG_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_phy_rchng_clk_src, rate); + clk_rcg_set_rate(priv->base, 0x6b058, freq->pre_div, freq->src); + return freq->freq; + case GCC_PCIE_1_PHY_RCHNG_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_phy_rchng_clk_src, rate); + clk_rcg_set_rate(priv->base, 0x8d060, freq->pre_div, freq->src); + return freq->freq; default: return 0; } @@ -179,6 +207,14 @@ static int sm8650_enable(struct clk *clk) qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK); qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK); break; + case GCC_PCIE_0_PIPE_CLK: + // GCC_PCIE_0_PIPE_CLK_SRC + clk_phy_mux_enable(priv->base, 0x6b070, true); + break; + case GCC_PCIE_1_PIPE_CLK: + // GCC_PCIE_1_PIPE_CLK_SRC + clk_phy_mux_enable(priv->base, 0x8d078, true); + break; } qcom_gate_clk_en(priv, clk->id); diff --git a/drivers/clk/qcom/clock-x1e80100.c b/drivers/clk/qcom/clock-x1e80100.c new file mode 100644 index 00000000000..bd9c6ed1c8a --- /dev/null +++ b/drivers/clk/qcom/clock-x1e80100.c @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Clock drivers for Qualcomm x1e80100 + * + * (C) Copyright 2024 Linaro Ltd. + */ + +#include <clk-uclass.h> +#include <dm.h> +#include <linux/delay.h> +#include <errno.h> +#include <asm/io.h> +#include <linux/bug.h> +#include <linux/bitops.h> +#include <dt-bindings/clock/qcom,x1e80100-gcc.h> +#include <dt-bindings/clock/qcom,x1e80100-tcsr.h> + +#include "clock-qcom.h" + +/* On-board TCXO, TOFIX get from DT */ +#define TCXO_RATE 38400000 + +/* bi_tcxo_div2 divided after RPMh output */ +#define TCXO_DIV2_RATE (TCXO_RATE / 2) + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s4_clk_src[] = { + F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625), + F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625), + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625), + F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75), + F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25), + F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75), + F(75000000, CFG_CLK_SRC_GPLL0_EVEN, 4, 0, 0), + F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15), + F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25), + F(100000000, CFG_CLK_SRC_GPLL0, 6, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = { + F(400000, CFG_CLK_SRC_CXO, 12, 1, 4), + F(25000000, CFG_CLK_SRC_GPLL0_EVEN, 12, 0, 0), + F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0), + /* TOFIX F(202000000, CFG_CLK_SRC_GPLL9, 4, 0, 0), */ + { } +}; + +static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = { + F(66666667, CFG_CLK_SRC_GPLL0_EVEN, 4.5, 0, 0), + F(133333333, CFG_CLK_SRC_GPLL0, 4.5, 0, 0), + F(200000000, CFG_CLK_SRC_GPLL0, 3, 0, 0), + F(240000000, CFG_CLK_SRC_GPLL0, 2.5, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = { + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = { + F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0), + { } +}; + +static ulong x1e80100_set_rate(struct clk *clk, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + const struct freq_tbl *freq; + + switch (clk->id) { + case GCC_QUPV3_WRAP2_S5_CLK: /* UART21 */ + freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s4_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x1e500, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_SDCC2_APPS_CLK: + freq = qcom_find_freq(ftbl_gcc_sdcc2_apps_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x14018, + freq->pre_div, freq->m, freq->n, freq->src, 8); + return freq->freq; + case GCC_USB30_PRIM_MASTER_CLK: + freq = qcom_find_freq(ftbl_gcc_usb30_prim_master_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x3902c, + freq->pre_div, freq->m, freq->n, freq->src, 8); + return freq->freq; + case GCC_USB30_PRIM_MOCK_UTMI_CLK: + clk_rcg_set_rate(priv->base, 0x39044, 0, 0); + return TCXO_DIV2_RATE; + case GCC_PCIE_4_AUX_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_aux_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x6b080, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_PCIE_4_PHY_RCHNG_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_phy_rchng_clk_src, rate); + clk_rcg_set_rate(priv->base, 0x6b064, freq->pre_div, freq->src); + return freq->freq; + case GCC_PCIE_6A_AUX_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_aux_clk_src, rate); + clk_rcg_set_rate_mnd(priv->base, 0x3108c, + freq->pre_div, freq->m, freq->n, freq->src, 16); + return freq->freq; + case GCC_PCIE_6A_PHY_RCHNG_CLK: + freq = qcom_find_freq(ftbl_gcc_pcie_0_phy_rchng_clk_src, rate); + clk_rcg_set_rate(priv->base, 0x31070, freq->pre_div, freq->src); + return freq->freq; + default: + return 0; + } +} + +static const struct gate_clk x1e80100_clks[] = { + GATE_CLK(GCC_AGGRE_UFS_PHY_AXI_CLK, 0x770e4, BIT(0)), + GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0x3908c, BIT(0)), + GATE_CLK(GCC_CFG_NOC_PCIE_ANOC_SOUTH_AHB_CLK, 0x52000, BIT(20)), + GATE_CLK(GCC_CFG_NOC_PCIE_ANOC_NORTH_AHB_CLK, 0x52028, BIT(22)), + GATE_CLK(GCC_CNOC_PCIE_SOUTH_SF_AXI_CLK, 0x52028, BIT(12)), + GATE_CLK(GCC_CNOC_PCIE_NORTH_SF_AXI_CLK, 0x52008, BIT(6)), + GATE_CLK(GCC_PCIE_4_AUX_CLK, 0x52008, BIT(3)), + GATE_CLK(GCC_PCIE_4_CFG_AHB_CLK, 0x52008, BIT(2)), + GATE_CLK(GCC_PCIE_4_MSTR_AXI_CLK, 0x52008, BIT(1)), + GATE_CLK(GCC_PCIE_4_PHY_RCHNG_CLK, 0x52000, BIT(22)), + GATE_CLK(GCC_PCIE_4_PIPE_CLK, 0x52008, BIT(4)), + GATE_CLK(GCC_PCIE_4_SLV_AXI_CLK, 0x52008, BIT(0)), + GATE_CLK(GCC_PCIE_4_SLV_Q2A_AXI_CLK, 0x52008, BIT(5)), + GATE_CLK(GCC_PCIE_6A_AUX_CLK, 0x52018, BIT(24)), + GATE_CLK(GCC_PCIE_6A_CFG_AHB_CLK, 0x52018, BIT(23)), + GATE_CLK(GCC_PCIE_6A_MSTR_AXI_CLK, 0x52018, BIT(22)), + GATE_CLK(GCC_PCIE_6A_PHY_RCHNG_CLK, 0x52018, BIT(27)), + GATE_CLK(GCC_PCIE_6A_PIPE_CLK, 0x52018, BIT(26)), + GATE_CLK(GCC_PCIE_6A_SLV_AXI_CLK, 0x52018, BIT(21)), + GATE_CLK(GCC_PCIE_6A_SLV_Q2A_AXI_CLK, 0x52018, BIT(20)), + GATE_CLK(GCC_QUPV3_WRAP2_CORE_2X_CLK, 0x52010, BIT(3)), + GATE_CLK(GCC_QUPV3_WRAP2_CORE_CLK, 0x52010, BIT(0)), + GATE_CLK(GCC_QUPV3_WRAP2_S0_CLK, 0x52010, BIT(4)), + GATE_CLK(GCC_QUPV3_WRAP2_S1_CLK, 0x52010, BIT(5)), + GATE_CLK(GCC_QUPV3_WRAP2_S2_CLK, 0x52010, BIT(6)), + GATE_CLK(GCC_QUPV3_WRAP2_S3_CLK, 0x52010, BIT(7)), + GATE_CLK(GCC_QUPV3_WRAP2_S4_CLK, 0x52010, BIT(8)), + GATE_CLK(GCC_QUPV3_WRAP2_S5_CLK, 0x52010, BIT(9)), + GATE_CLK(GCC_QUPV3_WRAP2_S6_CLK, 0x52010, BIT(10)), + GATE_CLK(GCC_QUPV3_WRAP2_S7_CLK, 0x52010, BIT(17)), + GATE_CLK(GCC_QUPV3_WRAP_2_M_AHB_CLK, 0x52010, BIT(2)), + GATE_CLK(GCC_QUPV3_WRAP_2_S_AHB_CLK, 0x52010, BIT(1)), + GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0x39018, BIT(0)), + GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0x39028, BIT(0)), + GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0x39024, BIT(0)), + GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0x39060, BIT(0)), + GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0x39064, BIT(0)), + GATE_CLK(GCC_USB3_PRIM_PHY_PIPE_CLK, 0x39068, BIT(0)), +}; + +static int x1e80100_enable(struct clk *clk) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case GCC_AGGRE_USB3_PRIM_AXI_CLK: + qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK); + fallthrough; + case GCC_USB30_PRIM_MASTER_CLK: + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK); + qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK); + break; + case GCC_PCIE_4_PIPE_CLK: + // GCC_PCIE_4_PIPE_CLK_SRC + clk_phy_mux_enable(priv->base, 0x6b07c, true); + break; + case GCC_PCIE_6A_PIPE_CLK: + // GCC_PCIE_6A_PIPE_CLK_SRC + clk_phy_mux_enable(priv->base, 0x31088, true); + break; + } + + qcom_gate_clk_en(priv, clk->id); + + return 0; +} + +static const struct qcom_reset_map x1e80100_gcc_resets[] = { + [GCC_AV1E_BCR] = { 0x4a000 }, + [GCC_CAMERA_BCR] = { 0x26000 }, + [GCC_DISPLAY_BCR] = { 0x27000 }, + [GCC_GPU_BCR] = { 0x71000 }, + [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x6c014 }, + [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0x6c020 }, + [GCC_PCIE_0_PHY_BCR] = { 0x6c01c }, + [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0x6c028 }, + [GCC_PCIE_0_TUNNEL_BCR] = { 0xa0000 }, + [GCC_PCIE_1_LINK_DOWN_BCR] = { 0x8e014 }, + [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0x8e020 }, + [GCC_PCIE_1_PHY_BCR] = { 0x8e01c }, + [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0x8e024 }, + [GCC_PCIE_1_TUNNEL_BCR] = { 0x2c000 }, + [GCC_PCIE_2_LINK_DOWN_BCR] = { 0xa5014 }, + [GCC_PCIE_2_NOCSR_COM_PHY_BCR] = { 0xa5020 }, + [GCC_PCIE_2_PHY_BCR] = { 0xa501c }, + [GCC_PCIE_2_PHY_NOCSR_COM_PHY_BCR] = { 0xa5028 }, + [GCC_PCIE_2_TUNNEL_BCR] = { 0x13000 }, + [GCC_PCIE_3_BCR] = { 0x58000 }, + [GCC_PCIE_3_LINK_DOWN_BCR] = { 0xab014 }, + [GCC_PCIE_3_NOCSR_COM_PHY_BCR] = { 0xab020 }, + [GCC_PCIE_3_PHY_BCR] = { 0xab01c }, + [GCC_PCIE_3_PHY_NOCSR_COM_PHY_BCR] = { 0xab024 }, + [GCC_PCIE_4_BCR] = { 0x6b000 }, + [GCC_PCIE_4_LINK_DOWN_BCR] = { 0xb3014 }, + [GCC_PCIE_4_NOCSR_COM_PHY_BCR] = { 0xb3020 }, + [GCC_PCIE_4_PHY_BCR] = { 0xb301c }, + [GCC_PCIE_4_PHY_NOCSR_COM_PHY_BCR] = { 0xb3028 }, + [GCC_PCIE_5_BCR] = { 0x2f000 }, + [GCC_PCIE_5_LINK_DOWN_BCR] = { 0xaa014 }, + [GCC_PCIE_5_NOCSR_COM_PHY_BCR] = { 0xaa020 }, + [GCC_PCIE_5_PHY_BCR] = { 0xaa01c }, + [GCC_PCIE_5_PHY_NOCSR_COM_PHY_BCR] = { 0xaa028 }, + [GCC_PCIE_6A_BCR] = { 0x31000 }, + [GCC_PCIE_6A_LINK_DOWN_BCR] = { 0xac014 }, + [GCC_PCIE_6A_NOCSR_COM_PHY_BCR] = { 0xac020 }, + [GCC_PCIE_6A_PHY_BCR] = { 0xac01c }, + [GCC_PCIE_6A_PHY_NOCSR_COM_PHY_BCR] = { 0xac024 }, + [GCC_PCIE_6B_BCR] = { 0x8d000 }, + [GCC_PCIE_6B_LINK_DOWN_BCR] = { 0xb5014 }, + [GCC_PCIE_6B_NOCSR_COM_PHY_BCR] = { 0xb5020 }, + [GCC_PCIE_6B_PHY_BCR] = { 0xb501c }, + [GCC_PCIE_6B_PHY_NOCSR_COM_PHY_BCR] = { 0xb5024 }, + [GCC_PCIE_PHY_BCR] = { 0x6f000 }, + [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x6f00c }, + [GCC_PCIE_PHY_COM_BCR] = { 0x6f010 }, + [GCC_PCIE_RSCC_BCR] = { 0xa4000 }, + [GCC_PDM_BCR] = { 0x33000 }, + [GCC_QUPV3_WRAPPER_0_BCR] = { 0x42000 }, + [GCC_QUPV3_WRAPPER_1_BCR] = { 0x18000 }, + [GCC_QUPV3_WRAPPER_2_BCR] = { 0x1e000 }, + [GCC_QUSB2PHY_HS0_MP_BCR] = { 0x1200c }, + [GCC_QUSB2PHY_HS1_MP_BCR] = { 0x12010 }, + [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 }, + [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 }, + [GCC_QUSB2PHY_TERT_BCR] = { 0x12008 }, + [GCC_QUSB2PHY_USB20_HS_BCR] = { 0x12014 }, + [GCC_SDCC2_BCR] = { 0x14000 }, + [GCC_SDCC4_BCR] = { 0x16000 }, + [GCC_UFS_PHY_BCR] = { 0x77000 }, + [GCC_USB20_PRIM_BCR] = { 0x29000 }, + [GCC_USB30_MP_BCR] = { 0x17000 }, + [GCC_USB30_PRIM_BCR] = { 0x39000 }, + [GCC_USB30_SEC_BCR] = { 0xa1000 }, + [GCC_USB30_TERT_BCR] = { 0xa2000 }, + [GCC_USB3_MP_SS0_PHY_BCR] = { 0x19008 }, + [GCC_USB3_MP_SS1_PHY_BCR] = { 0x54008 }, + [GCC_USB3_PHY_PRIM_BCR] = { 0x50000 }, + [GCC_USB3_PHY_SEC_BCR] = { 0x2a000 }, + [GCC_USB3_PHY_TERT_BCR] = { 0xa3000 }, + [GCC_USB3_UNIPHY_MP0_BCR] = { 0x19000 }, + [GCC_USB3_UNIPHY_MP1_BCR] = { 0x54000 }, + [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 }, + [GCC_USB3PHY_PHY_SEC_BCR] = { 0x2a004 }, + [GCC_USB3PHY_PHY_TERT_BCR] = { 0xa3004 }, + [GCC_USB3UNIPHY_PHY_MP0_BCR] = { 0x19004 }, + [GCC_USB3UNIPHY_PHY_MP1_BCR] = { 0x54004 }, + [GCC_USB4_0_BCR] = { 0x9f000 }, + [GCC_USB4_0_DP0_PHY_PRIM_BCR] = { 0x50010 }, + [GCC_USB4_1_DP0_PHY_SEC_BCR] = { 0x2a010 }, + [GCC_USB4_2_DP0_PHY_TERT_BCR] = { 0xa3010 }, + [GCC_USB4_1_BCR] = { 0x2b000 }, + [GCC_USB4_2_BCR] = { 0x11000 }, + [GCC_USB_0_PHY_BCR] = { 0x50020 }, + [GCC_USB_1_PHY_BCR] = { 0x2a020 }, + [GCC_USB_2_PHY_BCR] = { 0xa3020 }, + [GCC_VIDEO_BCR] = { 0x32000 }, +}; + +static const struct qcom_power_map x1e80100_gdscs[] = { + [GCC_PCIE_0_TUNNEL_GDSC] = { 0xa0004 }, + [GCC_PCIE_1_TUNNEL_GDSC] = { 0x2c004 }, + [GCC_PCIE_2_TUNNEL_GDSC] = { 0x13004 }, + [GCC_PCIE_3_GDSC] = { 0x58004 }, + [GCC_PCIE_3_PHY_GDSC] = { 0x3e000 }, + [GCC_PCIE_4_GDSC] = { 0x6b004 }, + [GCC_PCIE_4_PHY_GDSC] = { 0x6c000 }, + [GCC_PCIE_5_GDSC] = { 0x2f004 }, + [GCC_PCIE_5_PHY_GDSC] = { 0x30000 }, + [GCC_PCIE_6_PHY_GDSC] = { 0x8e000 }, + [GCC_PCIE_6A_GDSC] = { 0x31004 }, + [GCC_PCIE_6B_GDSC] = { 0x8d004 }, + [GCC_UFS_MEM_PHY_GDSC] = { 0x9e000 }, + [GCC_UFS_PHY_GDSC] = { 0x77004 }, + [GCC_USB20_PRIM_GDSC] = { 0x29004 }, + [GCC_USB30_MP_GDSC] = { 0x17004 }, + [GCC_USB30_PRIM_GDSC] = { 0x39004 }, + [GCC_USB30_SEC_GDSC] = { 0xa1004 }, + [GCC_USB30_TERT_GDSC] = { 0xa2004 }, + [GCC_USB3_MP_SS0_PHY_GDSC] = { 0x1900c }, + [GCC_USB3_MP_SS1_PHY_GDSC] = { 0x5400c }, + [GCC_USB4_0_GDSC] = { 0x9f004 }, + [GCC_USB4_1_GDSC] = { 0x2b004 }, + [GCC_USB4_2_GDSC] = { 0x11004 }, + [GCC_USB_0_PHY_GDSC] = { 0x50024 }, + [GCC_USB_1_PHY_GDSC] = { 0x2a024 }, + [GCC_USB_2_PHY_GDSC] = { 0xa3024 }, +}; + +static struct msm_clk_data x1e80100_gcc_data = { + .resets = x1e80100_gcc_resets, + .num_resets = ARRAY_SIZE(x1e80100_gcc_resets), + .clks = x1e80100_clks, + .num_clks = ARRAY_SIZE(x1e80100_clks), + .power_domains = x1e80100_gdscs, + .num_power_domains = ARRAY_SIZE(x1e80100_gdscs), + + .enable = x1e80100_enable, + .set_rate = x1e80100_set_rate, +}; + +static const struct udevice_id gcc_x1e80100_of_match[] = { + { + .compatible = "qcom,x1e80100-gcc", + .data = (ulong)&x1e80100_gcc_data, + }, + { } +}; + +U_BOOT_DRIVER(gcc_x1e80100) = { + .name = "gcc_x1e80100", + .id = UCLASS_NOP, + .of_match = gcc_x1e80100_of_match, + .bind = qcom_cc_bind, + .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; + +/* TCSRCC */ + +static const struct gate_clk x1e80100_tcsr_clks[] = { + GATE_CLK(TCSR_PCIE_2L_4_CLKREF_EN, 0x15100, BIT(0)), + GATE_CLK(TCSR_PCIE_2L_5_CLKREF_EN, 0x15104, BIT(0)), + GATE_CLK(TCSR_PCIE_8L_CLKREF_EN, 0x15108, BIT(0)), + GATE_CLK(TCSR_USB3_MP0_CLKREF_EN, 0x1510c, BIT(0)), + GATE_CLK(TCSR_USB3_MP1_CLKREF_EN, 0x15110, BIT(0)), + GATE_CLK(TCSR_USB2_1_CLKREF_EN, 0x15114, BIT(0)), + GATE_CLK(TCSR_UFS_PHY_CLKREF_EN, 0x15118, BIT(0)), + GATE_CLK(TCSR_USB4_1_CLKREF_EN, 0x15120, BIT(0)), + GATE_CLK(TCSR_USB4_2_CLKREF_EN, 0x15124, BIT(0)), + GATE_CLK(TCSR_USB2_2_CLKREF_EN, 0x15128, BIT(0)), + GATE_CLK(TCSR_PCIE_4L_CLKREF_EN, 0x1512c, BIT(0)), + GATE_CLK(TCSR_EDP_CLKREF_EN, 0x15130, BIT(0)), +}; + +static struct msm_clk_data x1e80100_tcsrcc_data = { + .clks = x1e80100_tcsr_clks, + .num_clks = ARRAY_SIZE(x1e80100_tcsr_clks), +}; + +static int tcsrcc_x1e80100_clk_enable(struct clk *clk) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + qcom_gate_clk_en(priv, clk->id); + + return 0; +} + +static ulong tcsrcc_x1e80100_clk_get_rate(struct clk *clk) +{ + return TCXO_RATE; +} + +static int tcsrcc_x1e80100_clk_probe(struct udevice *dev) +{ + struct msm_clk_data *data = (struct msm_clk_data *)dev_get_driver_data(dev); + struct msm_clk_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->data = data; + + return 0; +} + +static struct clk_ops tcsrcc_x1e80100_clk_ops = { + .enable = tcsrcc_x1e80100_clk_enable, + .get_rate = tcsrcc_x1e80100_clk_get_rate, +}; + +static const struct udevice_id tcsrcc_x1e80100_of_match[] = { + { + .compatible = "qcom,x1e80100-tcsr", + .data = (ulong)&x1e80100_tcsrcc_data, + }, + { } +}; + +U_BOOT_DRIVER(tcsrcc_x1e80100) = { + .name = "tcsrcc_x1e80100", + .id = UCLASS_CLK, + .of_match = tcsrcc_x1e80100_of_match, + .ops = &tcsrcc_x1e80100_clk_ops, + .priv_auto = sizeof(struct msm_clk_priv), + .probe = tcsrcc_x1e80100_clk_probe, + .flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF, +}; diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index c8161827d1c..26e014d5c53 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -118,7 +118,7 @@ int oftree_new(oftree *treep) return log_msg_ret("liv", ret); tree = oftree_from_np(root); } else { - const int size = 1024; + const int size = 4096; void *fdt; ret = check_tree_count(); @@ -309,6 +309,29 @@ bool ofnode_name_eq(ofnode node, const char *name) return (strlen(name) == len) && !strncmp(node_name, name, len); } +bool ofnode_name_eq_unit(ofnode node, const char *name) +{ + const char *node_name, *p; + int len; + + assert(ofnode_valid(node)); + + node_name = ofnode_get_name(node); + + /* check the whole name */ + if (!strcmp(node_name, name)) + return true; + + /* if @name has no unit address, try the node name without it */ + len = strlen(name); + p = strchr(node_name, '@'); + if (p && !strchr(name, '@') && len == p - node_name && + !strncmp(node_name, name, len)) + return true; + + return false; +} + int ofnode_read_u8(ofnode node, const char *propname, u8 *outp) { const u8 *cell; @@ -576,14 +599,9 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) log_debug("%s: %s: ", __func__, subnode_name); if (ofnode_is_np(node)) { - struct device_node *np = ofnode_to_np(node); - - for (np = np->child; np; np = np->sibling) { - if (!strcmp(subnode_name, np->name)) - break; - } - subnode = np_to_ofnode(np); + subnode = ofnode_find_subnode_unit(node, subnode_name); } else { + /* special case to avoid code-size increase */ int ooffset = fdt_subnode_offset(ofnode_to_fdt(node), ofnode_to_offset(node), subnode_name); subnode = noffset_to_ofnode(node, ooffset); @@ -594,6 +612,26 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name) return subnode; } +ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name) +{ + ofnode subnode, found = ofnode_null(); + + assert(ofnode_valid(node)); + log_debug("%s: ", subnode_name); + + ofnode_for_each_subnode(subnode, node) { + if (ofnode_name_eq_unit(subnode, subnode_name)) { + found = subnode; + break; + } + } + + log_debug("%s\n", ofnode_valid(found) ? + ofnode_get_name(found) : "<none>"); + + return found; +} + int ofnode_read_u32_array(ofnode node, const char *propname, u32 *out_values, size_t sz) { @@ -1710,9 +1748,10 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname, int ofnode_write_prop(ofnode node, const char *propname, const void *value, int len, bool copy) { + int ret; + if (of_live_active()) { void *newval; - int ret; if (copy) { newval = malloc(len); @@ -1726,8 +1765,12 @@ int ofnode_write_prop(ofnode node, const char *propname, const void *value, free(newval); return ret; } else { - return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node), - propname, value, len); + ret = fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node), + propname, value, len); + if (ret) + return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL; + + return 0; } } @@ -2015,7 +2058,7 @@ int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep) ret = -EEXIST; } if (offset < 0) - return -EINVAL; + return offset == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL; subnode = noffset_to_ofnode(node, offset); } diff --git a/drivers/misc/qfw_acpi.c b/drivers/misc/qfw_acpi.c index 7ffed1e8c02..0d0cf764689 100644 --- a/drivers/misc/qfw_acpi.c +++ b/drivers/misc/qfw_acpi.c @@ -7,6 +7,7 @@ #define LOG_CATEGORY UCLASS_QFW #include <acpi/acpi_table.h> +#include <bloblist.h> #include <errno.h> #include <malloc.h> #include <mapmem.h> @@ -160,6 +161,15 @@ ulong write_acpi_tables(ulong addr) struct bios_linker_entry *entry; uint32_t size; struct udevice *dev; + struct acpi_ctx *ctx; + + ctx = malloc(sizeof(*ctx)); + if (!ctx) { + printf("error: out of memory for acpi ctx\n"); + return addr; + } + + acpi_setup_ctx(ctx, addr); ret = qfw_get_dev(&dev); if (ret) { @@ -257,6 +267,29 @@ ulong acpi_get_rsdp_addr(void) return file->addr; } +void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, + struct acpi_xsdt *xsdt) +{ + memset(rsdp, 0, sizeof(struct acpi_rsdp)); + + memcpy(rsdp->signature, RSDP_SIG, 8); + memcpy(rsdp->oem_id, OEM_ID, 6); + + if (rsdt) + rsdp->rsdt_address = nomap_to_sysmem(rsdt); + + if (xsdt) + rsdp->xsdt_address = nomap_to_sysmem(xsdt); + + rsdp->length = sizeof(struct acpi_rsdp); + rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; + + /* Calculate checksums */ + rsdp->checksum = table_compute_checksum(rsdp, 20); + rsdp->ext_checksum = table_compute_checksum(rsdp, + sizeof(struct acpi_rsdp)); +} + #ifndef CONFIG_X86 static int evt_write_acpi_tables(void) { @@ -264,9 +297,9 @@ static int evt_write_acpi_tables(void) void *ptr; /* Reserve 64K for ACPI tables, aligned to a 4K boundary */ - ptr = memalign(SZ_4K, SZ_64K); + ptr = bloblist_add(BLOBLISTT_ACPI_TABLES, SZ_64K, 12); if (!ptr) - return -ENOMEM; + return -ENOBUFS; addr = map_to_sysmem(ptr); /* Generate ACPI tables */ diff --git a/drivers/misc/qfw_smbios.c b/drivers/misc/qfw_smbios.c index c3e8c310d00..93c4a80286b 100644 --- a/drivers/misc/qfw_smbios.c +++ b/drivers/misc/qfw_smbios.c @@ -5,6 +5,7 @@ #define LOG_CATEGORY UCLASS_QFW +#include <bloblist.h> #include <efi_loader.h> #include <errno.h> #include <log.h> @@ -15,6 +16,7 @@ #include <tables_csum.h> #include <linux/sizes.h> #include <asm/global_data.h> +#include <linux/err.h> DECLARE_GLOBAL_DATA_PTR; @@ -105,11 +107,10 @@ out: /** * qfw_write_smbios_tables() - copy SMBIOS tables from QEMU * - * @addr: target buffer - * @size: size of target buffer + * @addr: address of target buffer * Return: 0 for success, -ve on error */ -static int qfw_write_smbios_tables(u8 *addr, uint32_t size) +ulong write_smbios_table(ulong addr) { int ret; struct udevice *dev; @@ -143,16 +144,13 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size) table = qfw_load_smbios_table(dev, &table_size, "etc/smbios/smbios-tables"); - if (table_size + sizeof(struct smbios3_entry) > size) { - free(table); - return -ENOMEM; - } - memcpy(addr, table, table_size); + memcpy((void *)addr, table, table_size); free(table); - return 0; + return addr + table_size; } +#ifndef CONFIG_X86 /** * qfw_evt_write_smbios_tables() - event handler for copying QEMU SMBIOS tables * @@ -160,9 +158,9 @@ static int qfw_write_smbios_tables(u8 *addr, uint32_t size) */ static int qfw_evt_write_smbios_tables(void) { - phys_addr_t addr; + ulong addr, end; void *ptr; - int ret; + /* * TODO: * This size is currently hard coded in lib/efi_loader/efi_smbios.c. @@ -170,22 +168,21 @@ static int qfw_evt_write_smbios_tables(void) */ uint32_t size = SZ_4K; - /* Reserve 64K for SMBIOS tables, aligned to a 4K boundary */ - ptr = memalign(SZ_4K, size); - if (!ptr) { - log_err("Out of memory\n"); - return -ENOMEM; - } + log_debug("qfw_evt_write_smbios_tables bloblist\n"); + /* Reserve 4K for SMBIOS tables, aligned to a 4K boundary */ + ptr = bloblist_add(BLOBLISTT_SMBIOS_TABLES, size, 12); + if (!ptr) + return log_msg_ret("bloblist", -ENOBUFS); + addr = map_to_sysmem(ptr); /* Generate SMBIOS tables */ - ret = qfw_write_smbios_tables(ptr, size); - if (ret) { - if (CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE)) { - log_info("Falling back to U-Boot generated SMBIOS tables\n"); - write_smbios_table(addr); - } + end = write_smbios_table(addr); + if (IS_ERR_VALUE(end)) { + log_warning("SMBIOS: Failed to write (err=%dE)\n", (int)end); } else { + if (end - addr > size) + return -ENOMEM; log_debug("SMBIOS tables copied from QEMU\n"); } @@ -193,5 +190,5 @@ static int qfw_evt_write_smbios_tables(void) return 0; } - EVENT_SPY_SIMPLE(EVT_LAST_STAGE_INIT, qfw_evt_write_smbios_tables); +#endif /* !X86 */ diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index f4fdf15242c..4827834b4aa 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -3,7 +3,8 @@ menu "MMC Host controller Support" config MMC bool "MMC/SD/SDIO card support" default ARM || PPC || SANDBOX - select DM_MMC if DM + select BLK + select DM_MMC help This selects MultiMediaCard, Secure Digital and Secure Digital I/O support. @@ -39,14 +40,14 @@ config MMC_BROKEN_CD If card detection feature is broken, just poll to detect. config DM_MMC - bool "Enable MMC controllers using Driver Model" + bool depends on DM help - This enables the MultiMediaCard (MMC) uclass which supports MMC and - Secure Digital I/O (SDIO) cards. Both removable (SD, micro-SD, etc.) - and non-removable (e.g. eMMC chip) devices are supported. These - appear as block devices in U-Boot and can support filesystems such - as EXT4 and FAT. + This enables the MultiMediaCard (MMC) driver model uclass which + supports MMC and Secure Digital I/O (SDIO) cards. Both removable (SD, + micro-SD, etc.) and non-removable (e.g. eMMC chip) devices are + supported. These appear as block devices in U-Boot and can support + filesystems such as EXT4 and FAT. config SPL_DM_MMC bool "Enable MMC controllers using Driver Model in SPL" @@ -79,7 +80,7 @@ config MMC_SDHCI_ADMA_HELPERS config MMC_SPI bool "Support for SPI-based MMC controller" - depends on DM_MMC && DM_SPI + depends on DM_SPI help This selects SPI-based MMC controllers. If you have an MMC controller on a SPI bus, say Y here. @@ -97,7 +98,6 @@ config MMC_SPI_CRC_ON config ARM_PL180_MMCI bool "ARM AMBA Multimedia Card Interface and compatible support" - depends on DM_MMC help This selects the ARM(R) AMBA(R) PrimeCell Multimedia Card Interface (PL180, PL181 and compatible) support. @@ -258,7 +258,6 @@ config MMC_DW config MMC_DW_CORTINA bool "Cortina specific extensions for Synopsys DW Memory Card Interface" - depends on DM_MMC depends on MMC_DW help This selects support for Cortina SoC specific extensions to the @@ -285,7 +284,7 @@ config MMC_DW_K3 config MMC_DW_ROCKCHIP bool "Rockchip SD/MMC controller support" - depends on DM_MMC && OF_CONTROL + depends on OF_CONTROL depends on MMC_DW help This enables support for the Rockchip SD/MMM controller, which is @@ -306,7 +305,6 @@ config MMC_DW_SOCFPGA config MMC_DW_SNPS bool "Extensions for DW Memory Card Interface used in Synopsys ARC devboards" depends on MMC_DW - depends on DM_MMC depends on OF_CONTROL depends on CLK help @@ -317,13 +315,12 @@ config NEXELL_DWMMC bool "Nexell SD/MMC controller support" depends on ARCH_NEXELL depends on MMC_DW - depends on DM_MMC depends on PINCTRL_NEXELL default y config MMC_MESON_GX bool "Meson GX EMMC controller support" - depends on DM_MMC && ARCH_MESON + depends on ARCH_MESON help Support for EMMC host controller on Meson GX ARM SoCs platform (S905) @@ -338,7 +335,7 @@ config MMC_MXC config MMC_OWL bool "Actions OWL Multimedia Card Interface support" - depends on ARCH_OWL && DM_MMC && BLK + depends on ARCH_OWL help This selects the OWL SD/MMC host controller found on board based on Actions S700/S900 SoC. @@ -366,7 +363,6 @@ config MMC_PCI config MMC_OCTEONTX bool "Marvell Octeon Multimedia Card Interface support" depends on (ARCH_OCTEON || ARCH_OCTEONTX || ARCH_OCTEONTX2) - depends on DM_MMC select MMC_SUPPORTS_TUNING if ARCH_OCTEONTX2 help This selects the Octeon Multimedia card Interface. @@ -377,7 +373,7 @@ config MMC_OCTEONTX config MVEBU_MMC bool "Kirkwood MMC controller support" - depends on DM_MMC && ARCH_KIRKWOOD + depends on ARCH_KIRKWOOD help Support for MMC host controller on Kirkwood SoCs. If you are on a Kirkwood architecture, say Y here. @@ -386,8 +382,7 @@ config MVEBU_MMC config MMC_OMAP_HS bool "TI OMAP High Speed Multimedia Card Interface support" - select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR - select DM_REGULATOR_PBIAS if DM_MMC && DM_REGULATOR + select DM_REGULATOR_PBIAS if DM_REGULATOR help This selects the TI OMAP High Speed Multimedia card Interface. If you have an omap2plus board with a Multimedia Card slot, @@ -430,7 +425,6 @@ config SH_MMCIF config MMC_UNIPHIER bool "UniPhier SD/MMC Host Controller support" depends on ARCH_UNIPHIER - depends on DM_MMC depends on OF_CONTROL help This selects support for the Matsushita SD/MMC Host Controller on @@ -439,7 +433,6 @@ config MMC_UNIPHIER config RENESAS_SDHI bool "Renesas R-Car SD/MMC Host Controller support" depends on ARCH_RENESAS - depends on DM_MMC depends on OF_CONTROL select BOUNCE_BUFFER help @@ -449,7 +442,6 @@ config RENESAS_SDHI config MMC_BCM2835 bool "BCM2835 family custom SD/MMC Host Controller support" depends on ARCH_BCM283X - depends on DM_MMC depends on OF_CONTROL default y help @@ -469,7 +461,7 @@ config JZ47XX_MMC config MMC_SANDBOX bool "Sandbox MMC support" depends on SANDBOX - depends on DM_MMC && OF_CONTROL + depends on OF_CONTROL help This select a dummy sandbox MMC driver. At present this does nothing other than allow sandbox to be build with MMC support. This @@ -559,7 +551,6 @@ config FIXED_SDHCI_ALIGNED_BUFFER config MMC_SDHCI_ASPEED bool "Aspeed SDHCI controller" depends on ARCH_ASPEED - depends on DM_MMC depends on MMC_SDHCI select MISC help @@ -571,7 +562,7 @@ config MMC_SDHCI_ASPEED config MMC_SDHCI_ATMEL bool "Atmel SDHCI controller support" depends on ARCH_AT91 - depends on DM_MMC && ARCH_AT91 + depends on ARCH_AT91 depends on MMC_SDHCI help This enables support for the Atmel SDHCI controller, which supports @@ -606,7 +597,6 @@ config MMC_SDHCI_BCMSTB config MMC_SDHCI_CADENCE bool "SDHCI support for the Cadence SD/SDIO/eMMC controller" - depends on DM_MMC depends on MMC_SDHCI depends on OF_CONTROL help @@ -618,7 +608,6 @@ config MMC_SDHCI_CADENCE config MMC_SDHCI_CV1800B bool "SDHCI support for the CV1800B SD/SDIO/eMMC controller" - depends on DM_MMC depends on MMC_SDHCI depends on OF_CONTROL help @@ -633,7 +622,7 @@ config MMC_SDHCI_AM654 bool "SDHCI Controller on TI's Am654 devices" depends on ARCH_K3 depends on MMC_SDHCI - depends on DM_MMC && OF_CONTROL && BLK + depends on OF_CONTROL depends on REGMAP select MMC_SDHCI_IO_ACCESSORS help @@ -653,7 +642,6 @@ config MMC_SDHCI_IPROC config MMC_SDHCI_F_SDH30 bool "SDHCI support for Fujitsu Semiconductor/Socionext F_SDH30" - depends on DM_MMC depends on MMC_SDHCI help This selects the Secure Digital Host Controller Interface (SDHCI) @@ -673,7 +661,6 @@ config MMC_SDHCI_KONA config MMC_SDHCI_MSM bool "Qualcomm SDHCI controller" - depends on DM_MMC depends on MMC_SDHCI help Enables support for SDHCI 2.0 controller present on some Qualcomm @@ -685,7 +672,6 @@ config MMC_SDHCI_MV bool "SDHCI support on Marvell platform" depends on ARCH_MVEBU depends on MMC_SDHCI - depends on DM_MMC help This selects the Secure Digital Host Controller Interface on Marvell platform. @@ -697,7 +683,6 @@ config MMC_SDHCI_MV config MMC_SDHCI_NPCM bool "SDHCI support on Nuvoton NPCM device" depends on MMC_SDHCI - depends on DM_MMC help This selects the Secure Digital Host Controller Interface (SDHCI) on Nuvoton NPCM device. @@ -708,7 +693,7 @@ config MMC_SDHCI_NPCM config MMC_SDHCI_PIC32 bool "Microchip PIC32 on-chip SDHCI support" - depends on DM_MMC && MACH_PIC32 + depends on MACH_PIC32 depends on MMC_SDHCI help Support for Microchip PIC32 SDHCI controller. @@ -716,7 +701,6 @@ config MMC_SDHCI_PIC32 config MMC_SDHCI_ROCKCHIP bool "Arasan SDHCI controller for Rockchip support" depends on ARCH_ROCKCHIP - depends on DM_MMC && BLK depends on MMC_SDHCI help Support for Arasan SDHCI host controller on Rockchip ARM SoCs platform @@ -735,7 +719,6 @@ config MMC_SDHCI_S5P config MMC_SDHCI_SNPS bool "Synopsys DesignWare SDHCI controller" depends on MMC_SDHCI - depends on DM_MMC help Support for DesignWare SDHCI host controller on Alibaba TH1520 SoC. This is a highly configurable and programmable, high performance @@ -753,7 +736,7 @@ config MMC_SDHCI_STI config MMC_SDHCI_XENON bool "SDHCI support for the Xenon SDHCI controller" - depends on MMC_SDHCI && DM_MMC && OF_CONTROL + depends on MMC_SDHCI && OF_CONTROL help Support for Xenon SDHCI host controller on Marvell Armada 3700 7k/8k ARM SoCs platforms @@ -764,7 +747,6 @@ config MMC_SDHCI_XENON config MMC_SDHCI_TANGIER bool "Tangier SDHCI controller support" - depends on DM_MMC && BLK depends on MMC_SDHCI help This selects support for SDHCI controller on Tanginer @@ -800,7 +782,7 @@ config TEGRA124_MMC_DISABLE_EXT_LOOPBACK config MMC_SDHCI_ZYNQ bool "Arasan SDHCI controller support" - depends on DM_MMC && OF_CONTROL && BLK + depends on OF_CONTROL depends on MMC_SDHCI help Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform @@ -842,7 +824,6 @@ config MMC_SUNXI_HAS_MODE_SWITCH config MMC_PITON bool "MMC support for OpenPiton SoC" - depends on DM_MMC && BLK help This selects support for the SD host controller on OpenPiton SoC. Note that this SD controller directly exposes the contents of the @@ -851,7 +832,7 @@ config MMC_PITON config GENERIC_ATMEL_MCI bool "Atmel Multimedia Card Interface support" - depends on DM_MMC && ARCH_AT91 + depends on ARCH_AT91 help This enables support for Atmel High Speed Multimedia Card Interface (HSMCI), which supports the MultiMedia Card (MMC) Specification V4.3, @@ -860,7 +841,7 @@ config GENERIC_ATMEL_MCI config STM32_SDMMC2 bool "STMicroelectronics STM32H7 SD/MMC Host Controller support" - depends on DM_MMC && OF_CONTROL + depends on OF_CONTROL help This selects support for the SD/MMC controller on STM32H7 SoCs. If you have a board based on such a SoC and with a SD/MMC slot, @@ -880,7 +861,6 @@ config FTSDC010_SDIO config MMC_MTK bool "MediaTek SD/MMC Card Interface support" depends on ARCH_MEDIATEK || ARCH_MTMIPS - depends on DM_MMC depends on OF_CONTROL help This selects the MediaTek(R) Secure digital and Multimedia card Interface. @@ -911,7 +891,7 @@ config FSL_ESDHC_SUPPORT_ADMA2 config FSL_ESDHC_33V_IO_RELIABILITY_WORKAROUND bool "enable eSDHC workaround for 3.3v IO reliability issue" - depends on FSL_ESDHC && DM_MMC + depends on FSL_ESDHC help When eSDHC operates at 3.3v, damage can accumulate in an internal level shifter at a higher than expected rate. The faster the interface diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index c71c1e5547c..185e8346213 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -34,7 +34,7 @@ config MTD_CONCAT config MTD_BLOCK bool "Enable block device access to MTD devices" - depends on BLK + select BLK help Enable support for block device access to MTD devices using blk_ops abstraction. diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index c027d898a64..ba77c034736 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig @@ -116,7 +116,7 @@ config MTD_UBI_FM_DEBUG config UBI_BLOCK bool "Enable UBI block device support" - depends on BLK + select BLK help Enable UBI block device support using blk_ops abstraction. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 88ff025a37b..dcf6b4c81fc 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1019,6 +1019,20 @@ config FSL_ENETC This driver supports the NXP ENETC Ethernet controller found on some of the NXP SoCs. +config FSL_ENETC_NETC_BLK_CTRL + bool "NXP ENETC NETC blocks control driver" + depends on FSL_ENETC && IMX95 + default y if IMX95 + help + This driver configures Integrated Endpoint Register Block (IERB) and + Privileged Register Block (PRB) of NETC. For i.MX platforms, it also + includes the configuration of NETCMIX block. + The IERB contains registers that are used for pre-boot initialization, + debug, and non-customer configuration. The PRB controls global reset + and global error handling for NETC. The NETCMIX block is mainly used + to set MII protocol and PCS protocol of the links, it also contains + settings for some other functions. + config MDIO_GPIO_BITBANG bool "GPIO bitbanging MDIO driver" depends on DM_MDIO && DM_GPIO diff --git a/drivers/net/Makefile b/drivers/net/Makefile index e51a917933e..c6217f08f14 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_FEC_MXC) += fec_mxc.o obj-$(CONFIG_FMAN_ENET) += fm/ obj-$(CONFIG_FMAN_ENET) += fsl_mdio.o obj-$(CONFIG_FSL_ENETC) += fsl_enetc.o fsl_enetc_mdio.o +obj-$(CONFIG_FSL_ENETC_NETC_BLK_CTRL) += fsl_enetc_netc_blk_ctrl.o obj-$(CONFIG_FSL_LS_MDIO) += fsl_ls_mdio.o obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/ obj-$(CONFIG_FSL_MC_ENET) += ldpaa_eth/ diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index a6b0bafc8c6..67ef5f34a8a 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -2,6 +2,7 @@ /* * ENETC ethernet controller driver * Copyright 2017-2021 NXP + * Copyright 2023-2025 NXP */ #include <dm.h> @@ -16,52 +17,267 @@ #include <miiphy.h> #include <linux/bug.h> #include <linux/delay.h> +#include <linux/build_bug.h> + +#ifdef CONFIG_ARCH_IMX9 +#include <asm/mach-imx/sys_proto.h> +#include <cpu_func.h> +#endif #include "fsl_enetc.h" #define ENETC_DRIVER_NAME "enetc_eth" +/* + * Calculate number of buffer descriptors per cacheline, and compile-time + * validate that: + * - the RX and TX descriptors are the same size + * - the descriptors fit exactly into cachelines without overlap + * - all descriptors fit exactly into cachelines + */ +#define ENETC_NUM_BD_IN_CL \ + ((ARCH_DMA_MINALIGN / sizeof(struct enetc_tx_bd)) + \ + BUILD_BUG_ON_ZERO(sizeof(struct enetc_tx_bd) != \ + sizeof(union enetc_rx_bd)) + \ + BUILD_BUG_ON_ZERO(ARCH_DMA_MINALIGN % sizeof(struct enetc_tx_bd)) + \ + BUILD_BUG_ON_ZERO(ARCH_DMA_MINALIGN % sizeof(union enetc_rx_bd)) + \ + BUILD_BUG_ON_ZERO(ENETC_BD_CNT % \ + (ARCH_DMA_MINALIGN / sizeof(struct enetc_tx_bd)))) + static int enetc_remove(struct udevice *dev); +static int enetc_is_imx95(struct udevice *dev) +{ + struct pci_child_plat *pplat = dev_get_parent_plat(dev); + + /* Test whether this is i.MX95 ENETCv4. This may be optimized out. */ + return IS_ENABLED(CONFIG_ARCH_IMX9) && + pplat->vendor == PCI_VENDOR_ID_PHILIPS; +} + +static int enetc_is_ls1028a(struct udevice *dev) +{ + struct pci_child_plat *pplat = dev_get_parent_plat(dev); + + /* Test whether this is LS1028A ENETC. This may be optimized out. */ + return IS_ENABLED(CONFIG_ARCH_LS1028A) && + pplat->vendor == PCI_VENDOR_ID_FREESCALE; +} + +static int enetc_dev_id(struct udevice *dev) +{ + if (enetc_is_imx95(dev)) + return PCI_DEV(pci_get_devfn(dev)) >> 3; + if (enetc_is_ls1028a(dev)) + return PCI_FUNC(pci_get_devfn(dev)); + + return 0; +} + +static void enetc_inval_rxbd(struct udevice *dev) +{ + struct enetc_priv *priv = dev_get_priv(dev); + union enetc_rx_bd *desc = &priv->enetc_rxbd[priv->rx_bdr.next_prod_idx]; + unsigned long start = rounddown((unsigned long)desc, ARCH_DMA_MINALIGN); + unsigned long end = roundup((unsigned long)desc + sizeof(*desc), + ARCH_DMA_MINALIGN); + + if (enetc_is_imx95(dev)) + invalidate_dcache_range(start, end); +} + +static void enetc_flush_bd(struct udevice *dev, int pi, bool tx) +{ + struct enetc_priv *priv = dev_get_priv(dev); + union enetc_rx_bd *rxdesc = &priv->enetc_rxbd[pi]; + struct enetc_tx_bd *txdesc = &priv->enetc_txbd[pi]; + unsigned long desc = tx ? (unsigned long)txdesc : (unsigned long)rxdesc; + unsigned long size = tx ? sizeof(*txdesc) : sizeof(*rxdesc); + unsigned long start = rounddown(desc, ARCH_DMA_MINALIGN); + unsigned long end = roundup(desc + size, ARCH_DMA_MINALIGN); + + if (enetc_is_imx95(dev)) + flush_dcache_range(start, end); +} + +static void enetc_inval_buffer(struct udevice *dev, void *buf, size_t size) +{ + unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); + unsigned long end = roundup((unsigned long)buf + size, + ARCH_DMA_MINALIGN); + + if (enetc_is_imx95(dev)) + invalidate_dcache_range(start, end); +} + +static void enetc_flush_buffer(struct udevice *dev, void *buf, size_t size) +{ + unsigned long start = rounddown((unsigned long)buf, ARCH_DMA_MINALIGN); + unsigned long end = roundup((unsigned long)buf + size, + ARCH_DMA_MINALIGN); + + if (enetc_is_imx95(dev)) + flush_dcache_range(start, end); +} + +/* register accessors */ +static u32 enetc_read_reg(void __iomem *addr) +{ + return readl(addr); +} + +static void enetc_write_reg(void __iomem *addr, u32 val) +{ + writel(val, addr); +} + +static void enetc_write(struct enetc_priv *priv, u32 off, u32 val) +{ + enetc_write_reg(priv->regs_base + off, val); +} + +/* base port register accessors */ +static void enetc_write_pmr(struct udevice *dev, u32 val) +{ + struct enetc_data *data = (struct enetc_data *)dev_get_driver_data(dev); + struct enetc_priv *priv = dev_get_priv(dev); + const u32 off = ENETC_PMR + data->reg_offset_pmr; + + enetc_write_reg(priv->port_regs + off, val); +} + +static void enetc_write_psipmar(struct udevice *dev, int n, u32 val) +{ + struct enetc_data *data = (struct enetc_data *)dev_get_driver_data(dev); + struct enetc_priv *priv = dev_get_priv(dev); + const u32 off = (n ? ENETC_PSIPMAR1 : ENETC_PSIPMAR0) + + data->reg_offset_psipmar; + + enetc_write_reg(priv->port_regs + off, val); +} + +/* port station register accessors */ +static void enetc_write_psicfgr(struct udevice *dev, int port, u32 val) +{ + struct enetc_data *data = (struct enetc_data *)dev_get_driver_data(dev); + struct enetc_priv *priv = dev_get_priv(dev); + const u32 off = ENETC_PSICFGR(port, ENETC_PSICFGR_SHIFT_LS) + + data->reg_offset_psicfgr; + + enetc_write_reg(priv->port_regs + off, val); +} + +/* port register accessors */ +static u32 enetc_read_pcapr_mdio(struct udevice *dev) +{ + struct enetc_data *data = (struct enetc_data *)dev_get_driver_data(dev); + struct enetc_priv *priv = dev_get_priv(dev); + const u32 off = ENETC_PCAPR0 + data->reg_offset_pcapr; + const u32 reg = enetc_read_reg(priv->port_regs + off); + + if (enetc_is_imx95(dev)) + return reg & ENETC_PCS_PROT; + else if (enetc_is_ls1028a(dev)) + return reg & ENETC_PCAPRO_MDIO; + + return 0; +} + +static void enetc_write_port(struct enetc_priv *priv, u32 off, u32 val) +{ + enetc_write_reg(priv->port_regs + off, val); +} + +/* MAC port register accessors */ +static u32 enetc_read_mac_port(struct udevice *dev, u32 off) +{ + struct enetc_data *data = (struct enetc_data *)dev_get_driver_data(dev); + struct enetc_priv *priv = dev_get_priv(dev); + + return enetc_read_reg(priv->port_regs + data->reg_offset_mac + off); +} + +static void enetc_write_mac_port(struct udevice *dev, u32 off, u32 val) +{ + struct enetc_data *data = (struct enetc_data *)dev_get_driver_data(dev); + struct enetc_priv *priv = dev_get_priv(dev); + + enetc_write_reg(priv->port_regs + data->reg_offset_mac + off, val); +} + +/* BDR register accessor, see also ENETC_BDR() */ +static void enetc_bdr_write(struct enetc_priv *priv, int type, int n, + u32 off, u32 val) +{ + enetc_write(priv, ENETC_BDR(type, n, off), val); +} + /* * sets the MAC address in IERB registers, this setting is persistent and * carried over to Linux. */ -static void enetc_set_ierb_primary_mac(struct udevice *dev, int devfn, - const u8 *enetaddr) -{ -#ifdef CONFIG_ARCH_LS1028A -/* - * LS1028A is the only part with IERB at this time and there are plans to change - * its structure, keep this LS1028A specific for now - */ #define IERB_BASE 0x1f0800000ULL #define IERB_PFMAC(pf, vf, n) (IERB_BASE + 0x8000 + (pf) * 0x100 + (vf) * 8 \ + (n) * 4) -static int ierb_fn_to_pf[] = {0, 1, 2, -1, -1, -1, 3}; - +static void enetc_set_ierb_primary_mac(struct udevice *dev, void *blob) +{ + static int ierb_fn_to_pf[] = { 0, 1, 2, -1, -1, -1, 3 }; + struct pci_child_plat *ppdata = dev_get_parent_plat(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + struct enetc_priv *priv = dev_get_priv(dev); + const u8 *enetaddr = pdata->enetaddr; u16 lower = *(const u16 *)(enetaddr + 4); u32 upper = *(const u32 *)enetaddr; + int devfn, offset; + char path[256]; + + if (enetc_is_imx95(dev)) { + /* + * Configure the ENETC primary MAC addresses - Set register + * PMAR0/1 for SI 0 and PSIaPMAR0/1 for SI 1, 2 .. a + * (optionally pre-configured in IERB). + */ + devfn = enetc_dev_id(dev); + if (devfn > 2) + return; + + enetc_write(priv, IMX95_ENETC_SIPMAR0, upper); + enetc_write(priv, IMX95_ENETC_SIPMAR1, lower); + + snprintf(path, 256, "/soc/pcie@%x/ethernet@%x,%x", + PCI_BUS(dm_pci_get_bdf(dev)), PCI_DEV(ppdata->devfn), + PCI_FUNC(ppdata->devfn)); + } else if (enetc_is_ls1028a(dev)) { + /* + * LS1028A is the only part with IERB at this time and + * there are plans to change its structure, keep this + * LS1028A specific for now. + */ + devfn = PCI_FUNC(ppdata->devfn); + + if (ierb_fn_to_pf[devfn] < 0) + return; - if (ierb_fn_to_pf[devfn] < 0) + out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 0), upper); + out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 1), (u32)lower); + + snprintf(path, 256, "/soc/pcie@1f0000000/ethernet@%x,%x", + PCI_DEV(ppdata->devfn), PCI_FUNC(ppdata->devfn)); + } else { return; + } - out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 0), upper); - out_le32(IERB_PFMAC(ierb_fn_to_pf[devfn], 0, 1), (u32)lower); -#endif + offset = fdt_path_offset(blob, path); + if (offset >= 0) + fdt_setprop(blob, offset, "mac-address", pdata->enetaddr, 6); } /* sets up primary MAC addresses in DT/IERB */ void fdt_fixup_enetc_mac(void *blob) { - struct pci_child_plat *ppdata; - struct eth_pdata *pdata; struct udevice *dev; struct uclass *uc; - char path[256]; - int offset; - int devfn; uclass_get(UCLASS_ETH, &uc); uclass_foreach_dev(dev, uc) { @@ -69,18 +285,7 @@ void fdt_fixup_enetc_mac(void *blob) strcmp(dev->driver->name, ENETC_DRIVER_NAME)) continue; - pdata = dev_get_plat(dev); - ppdata = dev_get_parent_plat(dev); - devfn = PCI_FUNC(ppdata->devfn); - - enetc_set_ierb_primary_mac(dev, devfn, pdata->enetaddr); - - snprintf(path, 256, "/soc/pcie@1f0000000/ethernet@%x,%x", - PCI_DEV(ppdata->devfn), PCI_FUNC(ppdata->devfn)); - offset = fdt_path_offset(blob, path); - if (offset < 0) - continue; - fdt_setprop(blob, offset, "mac-address", pdata->enetaddr, 6); + enetc_set_ierb_primary_mac(dev, blob); } } @@ -101,7 +306,7 @@ static int enetc_bind(struct udevice *dev) * PCI function # and enetc#N based on interface count */ if (ofnode_valid(dev_ofnode(dev))) - sprintf(name, "enetc-%u", PCI_FUNC(pci_get_devfn(dev))); + sprintf(name, "enetc-%u", enetc_dev_id(dev)); else sprintf(name, "enetc#%u", eth_num_devices++); device_set_name(dev, name); @@ -181,10 +386,9 @@ static int enetc_init_sgmii(struct udevice *dev) /* set up MAC for RGMII */ static void enetc_init_rgmii(struct udevice *dev, struct phy_device *phydev) { - struct enetc_priv *priv = dev_get_priv(dev); - u32 old_val, val; + u32 old_val, val, dpx = 0; - old_val = val = enetc_read_port(priv, ENETC_PM_IF_MODE); + old_val = val = enetc_read_mac_port(dev, ENETC_PM_IF_MODE); /* disable unreliable RGMII in-band signaling and force the MAC into * the speed negotiated by the PHY. @@ -202,15 +406,20 @@ static void enetc_init_rgmii(struct udevice *dev, struct phy_device *phydev) val |= ENETC_PM_IFM_SSP_10; } + if (enetc_is_imx95(dev)) + dpx = ENETC_PM_IFM_FULL_DPX_IMX; + else if (enetc_is_ls1028a(dev)) + dpx = ENETC_PM_IFM_FULL_DPX_LS; + if (phydev->duplex == DUPLEX_FULL) - val |= ENETC_PM_IFM_FULL_DPX; + val |= dpx; else - val &= ~ENETC_PM_IFM_FULL_DPX; + val &= ~dpx; if (val == old_val) return; - enetc_write_port(priv, ENETC_PM_IF_MODE, val); + enetc_write_mac_port(dev, ENETC_PM_IF_MODE, val); } /* set up MAC configuration for the given interface type */ @@ -230,9 +439,12 @@ static void enetc_setup_mac_iface(struct udevice *dev, case PHY_INTERFACE_MODE_USXGMII: case PHY_INTERFACE_MODE_10GBASER: /* set ifmode to (US)XGMII */ - if_mode = enetc_read_port(priv, ENETC_PM_IF_MODE); - if_mode &= ~ENETC_PM_IF_IFMODE_MASK; - enetc_write_port(priv, ENETC_PM_IF_MODE, if_mode); + if_mode = enetc_read_mac_port(dev, ENETC_PM_IF_MODE); + if (enetc_is_imx95(dev)) + if_mode &= ~ENETC_PM_IF_IFMODE_MASK_IMX; + else if (enetc_is_ls1028a(dev)) + if_mode &= ~ENETC_PM_IF_IFMODE_MASK_LS; + enetc_write_mac_port(dev, ENETC_PM_IF_MODE, if_mode); break; }; } @@ -263,7 +475,7 @@ static void enetc_start_pcs(struct udevice *dev) struct enetc_priv *priv = dev_get_priv(dev); /* register internal MDIO for debug purposes */ - if (enetc_read_port(priv, ENETC_PCAPR0) & ENETC_PCAPRO_MDIO) { + if (enetc_read_pcapr_mdio(dev)) { priv->imdio.read = enetc_mdio_read; priv->imdio.write = enetc_mdio_write; priv->imdio.priv = priv->port_regs + ENETC_PM_IMDIO_BASE; @@ -375,6 +587,21 @@ static int enetc_remove(struct udevice *dev) return 0; } +static int enetc_imx95_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *plat = dev_get_plat(dev); + struct enetc_priv *priv = dev_get_priv(dev); + u8 *addr = plat->enetaddr; + + u16 lower = *(const u16 *)(addr + 4); + u32 upper = *(const u32 *)addr; + + enetc_write_port(priv, IMX95_ENETC_PMAR0, upper); + enetc_write_port(priv, IMX95_ENETC_PMAR1, lower); + + return 0; +} + /* * LS1028A is the only part with IERB at this time and there are plans to * change its structure, keep this LS1028A specific for now. @@ -413,39 +640,46 @@ static int enetc_ls1028a_write_hwaddr(struct udevice *dev) static int enetc_write_hwaddr(struct udevice *dev) { struct eth_pdata *plat = dev_get_plat(dev); - struct enetc_priv *priv = dev_get_priv(dev); u8 *addr = plat->enetaddr; - if (IS_ENABLED(CONFIG_ARCH_LS1028A)) + if (enetc_is_imx95(dev)) + return enetc_imx95_write_hwaddr(dev); + if (enetc_is_ls1028a(dev)) return enetc_ls1028a_write_hwaddr(dev); u16 lower = *(const u16 *)(addr + 4); u32 upper = *(const u32 *)addr; - enetc_write_port(priv, ENETC_PSIPMAR0, upper); - enetc_write_port(priv, ENETC_PSIPMAR1, lower); + enetc_write_psipmar(dev, 0, upper); + enetc_write_psipmar(dev, 1, lower); return 0; } /* Configure port parameters (# of rings, frame size, enable port) */ -static void enetc_enable_si_port(struct enetc_priv *priv) +static void enetc_enable_si_port(struct udevice *dev) { - u32 val; + struct enetc_priv *priv = dev_get_priv(dev); + u32 val = ENETC_PM_CC_TXP_IMX | ENETC_PM_CC_TX | ENETC_PM_CC_RX; /* set Rx/Tx BDR count */ - val = ENETC_PSICFGR_SET_TXBDR(ENETC_TX_BDR_CNT); - val |= ENETC_PSICFGR_SET_RXBDR(ENETC_RX_BDR_CNT); - enetc_write_port(priv, ENETC_PSICFGR(0), val); + enetc_write_psicfgr(dev, 0, ENETC_PSICFGR_SET_BDR(ENETC_RX_BDR_CNT, + ENETC_TX_BDR_CNT)); /* set Rx max frame size */ - enetc_write_port(priv, ENETC_PM_MAXFRM, ENETC_RX_MAXFRM_SIZE); + enetc_write_mac_port(dev, ENETC_PM_MAXFRM, ENETC_RX_MAXFRM_SIZE); /* enable MAC port */ - enetc_write_port(priv, ENETC_PM_CC, ENETC_PM_CC_RX_TX_EN); + if (enetc_is_ls1028a(dev)) + val |= ENETC_PM_CC_TXP_LS | ENETC_PM_CC_PROMIS; + enetc_write_mac_port(dev, ENETC_PM_CC, val); /* enable port */ - enetc_write_port(priv, ENETC_PMR, ENETC_PMR_SI0_EN); + if (enetc_is_imx95(dev)) + enetc_write_port(priv, ENETC_POR, 0x0); + enetc_write_pmr(dev, ENETC_PMR_SI0_EN); /* set SI cache policy */ - enetc_write(priv, ENETC_SICAR0, - ENETC_SICAR_RD_CFG | ENETC_SICAR_WR_CFG); + enetc_write(priv, ENETC_SICAR0, ENETC_SICAR_WR_CFG | + (enetc_is_imx95(dev) ? + ENETC_SICAR_RD_CFG_IMX : + ENETC_SICAR_RD_CFG_LS)); /* enable SI */ enetc_write(priv, ENETC_SIMR, ENETC_SIMR_EN); } @@ -536,6 +770,8 @@ static void enetc_setup_rx_bdr(struct udevice *dev) priv->enetc_rxbd[i].w.addr = enetc_rxb_address(dev, i); /* each RX buffer must be aligned to 64B */ WARN_ON(priv->enetc_rxbd[i].w.addr & (ARCH_DMA_MINALIGN - 1)); + + enetc_flush_bd(dev, i, false); } /* reset producer (ENETC owned) and consumer (SW owned) index */ @@ -556,6 +792,7 @@ static void enetc_setup_rx_bdr(struct udevice *dev) */ static int enetc_start(struct udevice *dev) { + int ret; struct enetc_priv *priv = dev_get_priv(dev); /* reset and enable the PCI device */ @@ -563,15 +800,19 @@ static int enetc_start(struct udevice *dev) dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - enetc_enable_si_port(priv); + enetc_enable_si_port(dev); /* setup Tx/Rx buffer descriptors */ enetc_setup_tx_bdr(dev); enetc_setup_rx_bdr(dev); + ret = phy_startup(priv->phy); + if (ret) + return ret; + enetc_setup_mac_iface(dev, priv->phy); - return phy_startup(priv->phy); + return 0; } /* @@ -614,6 +855,8 @@ static int enetc_send(struct udevice *dev, void *packet, int length) enetc_dbg(dev, "TxBD[%d]send: pkt_len=%d, buff @0x%x%08x\n", pi, length, upper_32_bits((u64)nv_packet), lower_32_bits((u64)nv_packet)); + enetc_flush_buffer(dev, packet, length); + /* prepare Tx BD */ memset(&priv->enetc_txbd[pi], 0x0, sizeof(struct enetc_tx_bd)); priv->enetc_txbd[pi].addr = @@ -621,7 +864,10 @@ static int enetc_send(struct udevice *dev, void *packet, int length) priv->enetc_txbd[pi].buf_len = cpu_to_le16(length); priv->enetc_txbd[pi].frm_len = cpu_to_le16(length); priv->enetc_txbd[pi].flags = cpu_to_le16(ENETC_TXBD_FLAGS_F); + dmb(); + enetc_flush_bd(dev, pi, true); + /* send frame: increment producer index */ pi = (pi + 1) % txr->bd_count; txr->next_prod_idx = pi; @@ -643,15 +889,15 @@ static int enetc_recv(struct udevice *dev, int flags, uchar **packetp) { struct enetc_priv *priv = dev_get_priv(dev); struct bd_ring *rxr = &priv->rx_bdr; - int tries = ENETC_POLL_TRIES; int pi = rxr->next_prod_idx; - int ci = rxr->next_cons_idx; + int tries = ENETC_POLL_TRIES; u32 status; int len; u8 rdy; do { dmb(); + enetc_inval_rxbd(dev); status = le32_to_cpu(priv->enetc_rxbd[pi].r.lstatus); /* check if current BD is ready to be consumed */ rdy = ENETC_RXBD_STATUS_R(status); @@ -663,45 +909,142 @@ static int enetc_recv(struct udevice *dev, int flags, uchar **packetp) dmb(); len = le16_to_cpu(priv->enetc_rxbd[pi].r.buf_len); *packetp = (uchar *)enetc_rxb_address(dev, pi); + enetc_inval_buffer(dev, *packetp, len); enetc_dbg(dev, "RxBD[%d]: len=%d err=%d pkt=0x%x%08x\n", pi, len, ENETC_RXBD_STATUS_ERRORS(status), upper_32_bits((u64)*packetp), lower_32_bits((u64)*packetp)); - /* BD clean up and advance to next in ring */ - memset(&priv->enetc_rxbd[pi], 0, sizeof(union enetc_rx_bd)); - priv->enetc_rxbd[pi].w.addr = enetc_rxb_address(dev, pi); + return len; +} + +static int enetc_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + const int bd_num_in_cl = enetc_is_imx95(dev) ? ENETC_NUM_BD_IN_CL : 1; + struct enetc_priv *priv = dev_get_priv(dev); + struct bd_ring *rxr = &priv->rx_bdr; + int pi = rxr->next_prod_idx; + int ci = rxr->next_cons_idx; + uchar *packet_expected; + int i; + + packet_expected = (uchar *)enetc_rxb_address(dev, pi); + if (packet != packet_expected) { + printf("%s: Unexpected packet (expected %p)\n", __func__, + packet_expected); + return -EINVAL; + } + rxr->next_prod_idx = (pi + 1) % rxr->bd_count; ci = (ci + 1) % rxr->bd_count; rxr->next_cons_idx = ci; dmb(); - /* free up the slot in the ring for HW */ - enetc_write_reg(rxr->cons_idx, ci); - return len; + if ((pi + 1) % bd_num_in_cl == 0) { + /* BD clean up and advance to next in ring */ + for (i = 0; i < bd_num_in_cl; i++) { + memset(&priv->enetc_rxbd[pi - i], 0, sizeof(union enetc_rx_bd)); + priv->enetc_rxbd[pi - i].w.addr = enetc_rxb_address(dev, pi - i); + } + + /* Will flush all bds in one cacheline */ + enetc_flush_bd(dev, pi - bd_num_in_cl + 1, false); + + /* free up the slot in the ring for HW */ + enetc_write_reg(rxr->cons_idx, ci); + } + + return 0; } -static const struct eth_ops enetc_ops = { +#if IS_ENABLED(CONFIG_ARCH_IMX9) +static int enetc_read_rom_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + unsigned int dev_id = enetc_dev_id(dev); + unsigned char *mac = pdata->enetaddr; + + if (dev_id > 2) + return -EINVAL; + + imx_get_mac_from_fuse(dev_id, mac); + + return !is_valid_ethaddr(mac); +} + +static const struct eth_ops enetc_ops_imx = { + .start = enetc_start, + .send = enetc_send, + .recv = enetc_recv, + .stop = enetc_stop, + .free_pkt = enetc_free_pkt, + .write_hwaddr = enetc_write_hwaddr, + .read_rom_hwaddr = enetc_read_rom_hwaddr, +}; + +U_BOOT_DRIVER(eth_enetc_imx) = { + .name = ENETC_DRIVER_NAME, + .id = UCLASS_ETH, + .bind = enetc_bind, + .probe = enetc_probe, + .remove = enetc_remove, + .ops = &enetc_ops_imx, + .priv_auto = sizeof(struct enetc_priv), + .plat_auto = sizeof(struct eth_pdata), +}; + +static const struct enetc_data enetc_data_imx = { + .reg_offset_pmr = ENETC_PMR_OFFSET_IMX, + .reg_offset_psipmar = ENETC_PSIPMARn_OFFSET_IMX, + .reg_offset_pcapr = ENETC_PCAPR_OFFSET_IMX, + .reg_offset_psicfgr = ENETC_PSICFGR_OFFSET_IMX, + .reg_offset_mac = ENETC_PM_OFFSET_IMX, +}; + +static struct pci_device_id enetc_ids_imx[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_ENETC4_ETH), + .driver_data = (ulong)&enetc_data_imx, + }, + {} +}; + +U_BOOT_PCI_DEVICE(eth_enetc_imx, enetc_ids_imx); +#endif + +static const struct eth_ops enetc_ops_ls = { .start = enetc_start, .send = enetc_send, .recv = enetc_recv, .stop = enetc_stop, + .free_pkt = enetc_free_pkt, .write_hwaddr = enetc_write_hwaddr, }; -U_BOOT_DRIVER(eth_enetc) = { +U_BOOT_DRIVER(eth_enetc_ls) = { .name = ENETC_DRIVER_NAME, .id = UCLASS_ETH, .bind = enetc_bind, .probe = enetc_probe, .remove = enetc_remove, - .ops = &enetc_ops, + .ops = &enetc_ops_ls, .priv_auto = sizeof(struct enetc_priv), .plat_auto = sizeof(struct eth_pdata), }; -static struct pci_device_id enetc_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_ETH) }, +static const struct enetc_data enetc_data_ls = { + .reg_offset_pmr = ENETC_PMR_OFFSET_LS, + .reg_offset_psipmar = ENETC_PSIPMARn_OFFSET_LS, + .reg_offset_pcapr = ENETC_PCAPR_OFFSET_LS, + .reg_offset_psicfgr = ENETC_PSICFGR_OFFSET_LS, + .reg_offset_mac = ENETC_PM_OFFSET_LS, +}; + +static struct pci_device_id enetc_ids_ls[] = { + { + PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_ETH), + .driver_data = (ulong)&enetc_data_ls, + }, {} }; -U_BOOT_PCI_DEVICE(eth_enetc, enetc_ids); +U_BOOT_PCI_DEVICE(eth_enetc_ls, enetc_ids_ls); diff --git a/drivers/net/fsl_enetc.h b/drivers/net/fsl_enetc.h index f2acf367aa3..804df853bf5 100644 --- a/drivers/net/fsl_enetc.h +++ b/drivers/net/fsl_enetc.h @@ -12,7 +12,9 @@ /* PCI function IDs */ #define PCI_DEVICE_ID_ENETC_ETH 0xE100 +#define PCI_DEVICE_ID_ENETC4_ETH 0xE101 #define PCI_DEVICE_ID_ENETC_MDIO 0xEE01 +#define PCI_DEVICE_ID_ENETC4_EMDIO 0xEE00 /* ENETC Ethernet controller registers */ /* Station interface register offsets */ @@ -22,7 +24,8 @@ /* write cache cfg: snoop, no allocate, data & BD coherent */ #define ENETC_SICAR_WR_CFG 0x6767 /* read cache cfg: coherent copy, look up, don't alloc in cache */ -#define ENETC_SICAR_RD_CFG 0x27270000 +#define ENETC_SICAR_RD_CFG_LS 0x27270000 +#define ENETC_SICAR_RD_CFG_IMX 0x2b2b0000 #define ENETC_SIROCT 0x300 #define ENETC_SIRFRM 0x308 #define ENETC_SITOCT 0x320 @@ -57,32 +60,60 @@ enum enetc_bdr_type {TX, RX}; #define ENETC_PORT_REGS_OFF 0x10000 /* Port registers */ +#define ENETC_PMR_OFFSET_IMX 0x0010 +#define ENETC_PMR_OFFSET_LS 0x0000 #define ENETC_PMR 0x0000 #define ENETC_PMR_SI0_EN BIT(16) #define ENETC_PSIPMMR 0x0018 -#define ENETC_PSIPMAR0 0x0100 -#define ENETC_PSIPMAR1 0x0104 -#define ENETC_PCAPR0 0x0900 -#define ENETC_PCAPRO_MDIO BIT(11) -#define ENETC_PSICFGR(n) (0x0940 + (n) * 0x10) -#define ENETC_PSICFGR_SET_TXBDR(val) ((val) & 0xff) -#define ENETC_PSICFGR_SET_RXBDR(val) (((val) & 0xff) << 16) +#define ENETC_PSIPMARn_OFFSET_IMX 0x0000 +#define ENETC_PSIPMARn_OFFSET_LS 0x0080 +#define ENETC_PSIPMAR0 0x0080 +#define ENETC_PSIPMAR1 0x0084 +#define ENETC_PCAPR_OFFSET_IMX 0x4008 +#define ENETC_PCAPR_OFFSET_LS 0x0900 +#define ENETC_PCAPR0 0x0000 +#define ENETC_PCAPRO_MDIO BIT(11) /* LS only */ +#define ENETC_PCS_PROT GENMASK(15, 0) /* IMX only */ +/* ENETC base registers */ +#define ENETC_PSICFGR_OFFSET_LS 0x0940 +#define ENETC_PSICFGR_SHIFT_LS 0x10 +#define ENETC_PSICFGR_OFFSET_IMX 0x2010 +#define ENETC_PSICFGR_SHIFT_IMX 0x80 +#define ENETC_PSICFGR(n, s) ((n) * (s)) +#define ENETC_PSICFGR_SET_BDR(rx, tx) (((rx) << 16) | (tx)) /* MAC configuration */ -#define ENETC_PM_CC 0x8008 +#define ENETC_PM_OFFSET_IMX 0x5000 +#define ENETC_PM_OFFSET_LS 0x8000 +#define ENETC_PM_CC 0x0008 #define ENETC_PM_CC_DEFAULT 0x0810 -#define ENETC_PM_CC_RX_TX_EN 0x8813 -#define ENETC_PM_MAXFRM 0x8014 +#define ENETC_PM_CC_TXP_IMX BIT(15) +#define ENETC_PM_CC_TXP_LS BIT(11) +#define ENETC_PM_CC_PROMIS BIT(4) +#define ENETC_PM_CC_TX BIT(1) +#define ENETC_PM_CC_RX BIT(0) +#define ENETC_PM_MAXFRM 0x0014 #define ENETC_RX_MAXFRM_SIZE PKTSIZE_ALIGN -#define ENETC_PM_IMDIO_BASE 0x8030 -#define ENETC_PM_IF_MODE 0x8300 +#define ENETC_PM_IMDIO_BASE 0x0030 +#define ENETC_PM_IF_MODE 0x0300 #define ENETC_PM_IF_MODE_RG BIT(2) #define ENETC_PM_IF_MODE_AN_ENA BIT(15) #define ENETC_PM_IFM_SSP_MASK GENMASK(14, 13) #define ENETC_PM_IFM_SSP_1000 (2 << 13) #define ENETC_PM_IFM_SSP_100 (0 << 13) #define ENETC_PM_IFM_SSP_10 (1 << 13) -#define ENETC_PM_IFM_FULL_DPX BIT(12) -#define ENETC_PM_IF_IFMODE_MASK GENMASK(1, 0) +#define ENETC_PM_IFM_FULL_DPX_IMX BIT(6) +#define ENETC_PM_IFM_FULL_DPX_LS BIT(12) +#define ENETC_PM_IF_IFMODE_MASK_IMX GENMASK(2, 0) +#define ENETC_PM_IF_IFMODE_MASK_LS GENMASK(1, 0) + +/* i.MX95 specific registers */ +#define IMX95_ENETC_SIPMAR0 0x80 +#define IMX95_ENETC_SIPMAR1 0x84 + +/* Port registers */ +#define IMX95_ENETC_PMAR0 0x4020 +#define IMX95_ENETC_PMAR1 0x4024 +#define ENETC_POR 0x4100 /* buffer descriptors count must be multiple of 8 and aligned to 128 bytes */ #define ENETC_BD_CNT CONFIG_SYS_RX_ETH_BUFFER @@ -163,25 +194,14 @@ struct enetc_priv { struct phy_device *phy; }; -/* register accessors */ -#define enetc_read_reg(x) readl((x)) -#define enetc_write_reg(x, val) writel((val), (x)) -#define enetc_read(priv, off) enetc_read_reg((priv)->regs_base + (off)) -#define enetc_write(priv, off, v) \ - enetc_write_reg((priv)->regs_base + (off), v) - -/* port register accessors */ -#define enetc_port_regs(priv, off) ((priv)->port_regs + (off)) -#define enetc_read_port(priv, off) \ - enetc_read_reg(enetc_port_regs((priv), (off))) -#define enetc_write_port(priv, off, v) \ - enetc_write_reg(enetc_port_regs((priv), (off)), v) - -/* BDR register accessors, see ENETC_BDR() */ -#define enetc_bdr_read(priv, t, n, off) \ - enetc_read(priv, ENETC_BDR(t, n, off)) -#define enetc_bdr_write(priv, t, n, off, val) \ - enetc_write(priv, ENETC_BDR(t, n, off), val) +struct enetc_data { + /* Register layout offsets */ + u16 reg_offset_pmr; + u16 reg_offset_psipmar; + u16 reg_offset_pcapr; + u16 reg_offset_psicfgr; + u16 reg_offset_mac; +}; /* PCS / internal SoC PHY ID, it defaults to 0 on all interfaces */ #define ENETC_PCS_PHY_ADDR 0 diff --git a/drivers/net/fsl_enetc_mdio.c b/drivers/net/fsl_enetc_mdio.c index 2d5fcbb6dbd..c1d491f2c5a 100644 --- a/drivers/net/fsl_enetc_mdio.c +++ b/drivers/net/fsl_enetc_mdio.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * ENETC ethernet controller driver - * Copyright 2019 NXP + * Copyright 2019-2025 NXP */ #include <dm.h> @@ -14,6 +14,16 @@ #include "fsl_enetc.h" +static u32 enetc_read(struct enetc_mdio_priv *priv, u32 off) +{ + return readl(priv->regs_base + off); +} + +static void enetc_write(struct enetc_mdio_priv *priv, u32 off, u32 val) +{ + writel(val, priv->regs_base + off); +} + static void enetc_mdio_wait_bsy(struct enetc_mdio_priv *priv) { int to = 10000; @@ -122,7 +132,9 @@ static int enetc_mdio_bind(struct udevice *dev) static int enetc_mdio_probe(struct udevice *dev) { + struct pci_child_plat *pplat = dev_get_parent_plat(dev); struct enetc_mdio_priv *priv = dev_get_priv(dev); + u16 cmd = PCI_COMMAND_MEMORY; priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { @@ -132,7 +144,10 @@ static int enetc_mdio_probe(struct udevice *dev) priv->regs_base += ENETC_MDIO_BASE; - dm_pci_clrset_config16(dev, PCI_COMMAND, 0, PCI_COMMAND_MEMORY); + if (pplat->vendor == PCI_VENDOR_ID_PHILIPS) /* i.MX95 */ + cmd |= PCI_COMMAND_MASTER; + + dm_pci_clrset_config16(dev, PCI_COMMAND, 0, cmd); return 0; } @@ -148,6 +163,7 @@ U_BOOT_DRIVER(enetc_mdio) = { static struct pci_device_id enetc_mdio_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, PCI_DEVICE_ID_ENETC_MDIO) }, + { PCI_DEVICE(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_ENETC4_EMDIO) }, { } }; diff --git a/drivers/net/fsl_enetc_netc_blk_ctrl.c b/drivers/net/fsl_enetc_netc_blk_ctrl.c new file mode 100644 index 00000000000..46b68d3d8a4 --- /dev/null +++ b/drivers/net/fsl_enetc_netc_blk_ctrl.c @@ -0,0 +1,346 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * NXP NETC Blocks Control Driver + * + * Copyright 2024 NXP + * + * This driver is used for pre-initialization of NETC, such as PCS and MII + * protocols, LDID, warm reset, etc. Therefore, all NETC device drivers can + * only be probed after the netc-blk-crtl driver has completed initialization. + * In addition, when the system enters suspend mode, IERB, PRB, and NETCMIX + * will be powered off, except for WOL. Therefore, when the system resumes, + * these blocks need to be reinitialized. + */ + +#include <asm/io.h> +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/errno.h> +#include <linux/iopoll.h> +#include <phy_interface.h> + +/* NETCMIX registers */ +#define IMX95_CFG_LINK_IO_VAR 0x0 +#define IO_VAR_16FF_16G_SERDES 0x1 +#define IO_VAR(port, var) (((var) & 0xf) << ((port) << 2)) + +#define IMX95_CFG_LINK_MII_PROT 0x4 +#define CFG_LINK_MII_PORT_0 GENMASK(3, 0) +#define CFG_LINK_MII_PORT_1 GENMASK(7, 4) +#define MII_PROT_MII 0x0 +#define MII_PROT_RMII 0x1 +#define MII_PROT_RGMII 0x2 +#define MII_PROT_SERIAL 0x3 +#define MII_PROT(port, prot) (((prot) & 0xf) << ((port) << 2)) + +#define IMX95_CFG_LINK_PCS_PROT(a) (0x8 + (a) * 4) +#define PCS_PROT_1G_SGMII BIT(0) +#define PCS_PROT_2500M_SGMII BIT(1) +#define PCS_PROT_XFI BIT(3) +#define PCS_PROT_SFI BIT(4) +#define PCS_PROT_10G_SXGMII BIT(6) + +/* NETC privileged register block register */ +#define PRB_NETCRR 0x100 +#define NETCRR_SR BIT(0) +#define NETCRR_LOCK BIT(1) + +#define PRB_NETCSR 0x104 +#define NETCSR_ERROR BIT(0) +#define NETCSR_STATE BIT(1) + +/* NETC integrated endpoint register block register */ +#define IERB_EMDIOFAUXR 0x344 +#define IERB_T0FAUXR 0x444 +#define IERB_EFAUXR(a) (0x3044 + 0x100 * (a)) +#define IERB_VFAUXR(a) (0x4004 + 0x40 * (a)) +#define FAUXR_LDID GENMASK(3, 0) + +/* Platform information */ +#define IMX95_ENETC0_BUS_DEVFN 0x0 +#define IMX95_ENETC1_BUS_DEVFN 0x40 +#define IMX95_ENETC2_BUS_DEVFN 0x80 + +/* Flags for different platforms */ +#define NETC_HAS_NETCMIX BIT(0) + +struct netc_blk_ctrl { + void __iomem *prb; + void __iomem *ierb; + void __iomem *netcmix; +}; + +static void netc_reg_write(void __iomem *base, u32 offset, u32 val) +{ + writel(val, base + offset); +} + +static u32 netc_reg_read(void __iomem *base, u32 offset) +{ + return readl(base + offset); +} + +static int netc_of_pci_get_bus_devfn(ofnode node) +{ + u32 reg[5]; + int error; + + error = ofnode_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg)); + if (error) + return error; + + return (reg[0] >> 8) & 0xffff; +} + +static int netc_get_link_mii_protocol(phy_interface_t interface) +{ + switch (interface) { + case PHY_INTERFACE_MODE_MII: + return MII_PROT_MII; + case PHY_INTERFACE_MODE_RMII: + return MII_PROT_RMII; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: + return MII_PROT_RGMII; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_10GBASER: + case PHY_INTERFACE_MODE_XGMII: + case PHY_INTERFACE_MODE_USXGMII: + return MII_PROT_SERIAL; + default: + return -EINVAL; + } +} + +static int imx95_netcmix_init(struct udevice *dev) +{ + struct netc_blk_ctrl *priv = dev_get_priv(dev); + ofnode child, gchild; + phy_interface_t interface; + int bus_devfn, mii_proto; + u32 val; + + /* Default setting of MII protocol */ + val = MII_PROT(0, MII_PROT_RGMII) | MII_PROT(1, MII_PROT_RGMII) | + MII_PROT(2, MII_PROT_SERIAL); + + /* Update the link MII protocol through parsing phy-mode */ + dev_for_each_subnode(child, dev) { + if (!ofnode_is_enabled(child)) + continue; + + ofnode_for_each_subnode(gchild, child) { + if (!ofnode_is_enabled(gchild)) + continue; + + if (!ofnode_device_is_compatible(gchild, "pci1131,e101")) + continue; + + bus_devfn = netc_of_pci_get_bus_devfn(gchild); + if (bus_devfn < 0) + return -EINVAL; + + if (bus_devfn == IMX95_ENETC2_BUS_DEVFN) + continue; + + interface = ofnode_read_phy_mode(gchild); + if (interface == -1) + continue; + + mii_proto = netc_get_link_mii_protocol(interface); + if (mii_proto < 0) + return -EINVAL; + + switch (bus_devfn) { + case IMX95_ENETC0_BUS_DEVFN: + val &= ~CFG_LINK_MII_PORT_0; + val |= FIELD_PREP(CFG_LINK_MII_PORT_0, mii_proto); + break; + case IMX95_ENETC1_BUS_DEVFN: + val &= ~CFG_LINK_MII_PORT_1; + val |= FIELD_PREP(CFG_LINK_MII_PORT_1, mii_proto); + break; + default: + return -EINVAL; + } + } + } + + /* Configure Link I/O variant */ + netc_reg_write(priv->netcmix, IMX95_CFG_LINK_IO_VAR, + IO_VAR(2, IO_VAR_16FF_16G_SERDES)); + /* Configure Link 2 PCS protocol */ + netc_reg_write(priv->netcmix, IMX95_CFG_LINK_PCS_PROT(2), + PCS_PROT_10G_SXGMII); + netc_reg_write(priv->netcmix, IMX95_CFG_LINK_MII_PROT, val); + + return 0; +} + +static bool netc_ierb_is_locked(struct netc_blk_ctrl *priv) +{ + return !!(netc_reg_read(priv->prb, PRB_NETCRR) & NETCRR_LOCK); +} + +static int netc_lock_ierb(struct netc_blk_ctrl *priv) +{ + u32 val; + + netc_reg_write(priv->prb, PRB_NETCRR, NETCRR_LOCK); + + return readl_poll_timeout(priv->prb + PRB_NETCSR, val, + !(val & NETCSR_STATE), 2000); +} + +static int netc_unlock_ierb_with_warm_reset(struct netc_blk_ctrl *priv) +{ + u32 val; + + netc_reg_write(priv->prb, PRB_NETCRR, 0); + + return readl_poll_timeout(priv->prb + PRB_NETCRR, val, + !(val & NETCRR_LOCK), 100000); +} + +static int imx95_ierb_init(struct udevice *dev) +{ + struct netc_blk_ctrl *priv = dev_get_priv(dev); + + /* EMDIO : No MSI-X intterupt */ + netc_reg_write(priv->ierb, IERB_EMDIOFAUXR, 0); + /* ENETC0 PF */ + netc_reg_write(priv->ierb, IERB_EFAUXR(0), 0); + /* ENETC0 VF0 */ + netc_reg_write(priv->ierb, IERB_VFAUXR(0), 1); + /* ENETC0 VF1 */ + netc_reg_write(priv->ierb, IERB_VFAUXR(1), 2); + /* ENETC1 PF */ + netc_reg_write(priv->ierb, IERB_EFAUXR(1), 3); + /* ENETC1 VF0 */ + netc_reg_write(priv->ierb, IERB_VFAUXR(2), 5); + /* ENETC1 VF1 */ + netc_reg_write(priv->ierb, IERB_VFAUXR(3), 6); + /* ENETC2 PF */ + netc_reg_write(priv->ierb, IERB_EFAUXR(2), 4); + /* ENETC2 VF0 */ + netc_reg_write(priv->ierb, IERB_VFAUXR(4), 5); + /* ENETC2 VF1 */ + netc_reg_write(priv->ierb, IERB_VFAUXR(5), 6); + /* NETC TIMER */ + netc_reg_write(priv->ierb, IERB_T0FAUXR, 7); + + return 0; +} + +static int netc_ierb_init(struct udevice *dev) +{ + struct netc_blk_ctrl *priv = dev_get_priv(dev); + int err; + + if (netc_ierb_is_locked(priv)) { + err = netc_unlock_ierb_with_warm_reset(priv); + if (err) { + dev_err(dev, "Unlock IERB failed.\n"); + return err; + } + } + + err = imx95_ierb_init(dev); + if (err) + return err; + + err = netc_lock_ierb(priv); + if (err) { + dev_err(dev, "Lock IERB failed.\n"); + return err; + } + + return 0; +} + +static int netc_prb_check_error(struct netc_blk_ctrl *priv) +{ + if (netc_reg_read(priv->prb, PRB_NETCSR) & NETCSR_ERROR) + return -1; + + return 0; +} + +static const struct udevice_id netc_blk_ctrl_match[] = { + { .compatible = "nxp,imx95-netc-blk-ctrl" }, + {}, +}; + +static int netc_blk_ctrl_probe(struct udevice *dev) +{ + struct netc_blk_ctrl *priv = dev_get_priv(dev); + struct clk *ipg_clk; + fdt_addr_t regs; + int err; + + ipg_clk = devm_clk_get_optional(dev, "ipg"); + if (IS_ERR(ipg_clk)) { + dev_err(dev, "Set ipg clock failed\n"); + return PTR_ERR(ipg_clk); + } + + err = clk_prepare_enable(ipg_clk); + if (err) { + dev_err(dev, "Enable ipg clock failed\n"); + return PTR_ERR(ipg_clk); + } + + regs = dev_read_addr_name(dev, "ierb"); + if (regs == FDT_ADDR_T_NONE) { + dev_err(dev, "Missing IERB resource\n"); + return -EINVAL; + } + + priv->ierb = (void __iomem *)regs; + regs = dev_read_addr_name(dev, "prb"); + if (regs == FDT_ADDR_T_NONE) { + dev_err(dev, "Missing PRB resource\n"); + return -EINVAL; + } + + priv->prb = (void __iomem *)regs; + regs = dev_read_addr_name(dev, "netcmix"); + if (regs == FDT_ADDR_T_NONE) { + dev_err(dev, "Missing NETCMIX resource\n"); + return -EINVAL; + } + + priv->netcmix = (void __iomem *)regs; + + err = imx95_netcmix_init(dev); + if (err) { + dev_err(dev, "Initializing NETCMIX failed\n"); + return err; + } + + err = netc_ierb_init(dev); + if (err) { + dev_err(dev, "Initializing IERB failed\n"); + return err; + } + + if (netc_prb_check_error(priv) < 0) + dev_warn(dev, "The current IERB configuration is invalid\n"); + + return 0; +} + +U_BOOT_DRIVER(netc_blk_ctrl_drv) = { + .name = "netc_blk_ctrl", + .id = UCLASS_SIMPLE_BUS, + .of_match = netc_blk_ctrl_match, + .probe = netc_blk_ctrl_probe, + .priv_auto = sizeof(struct netc_blk_ctrl), + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/nvme/Kconfig b/drivers/nvme/Kconfig index 73edb355160..d138867666b 100644 --- a/drivers/nvme/Kconfig +++ b/drivers/nvme/Kconfig @@ -4,6 +4,7 @@ config NVME bool "NVM Express device support" + select BLK help This option enables support for NVM Express devices. It supports basic functions of NVMe (read/write). diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 41901433e8c..4f876d39875 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -371,6 +371,14 @@ config PCIE_DW_MESON Say Y here if you want to enable DW PCIe controller support on Amlogic SoCs. +config PCIE_DW_QCOM + bool "Qualcomm DesignWare based PCIe controller" + depends on ARCH_SNAPDRAGON + select PCIE_DW_COMMON + help + Say Y here if you want to enable DW PCIe controller support on + Qualcomm SoCs. + config PCIE_ROCKCHIP bool "Enable Rockchip PCIe driver" depends on ARCH_ROCKCHIP diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index bf361cd0fba..ba53f594963 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_PCIE_MEDIATEK_GEN3) += pcie_mediatek_gen3.o obj-$(CONFIG_PCIE_ROCKCHIP) += pcie_rockchip.o obj-$(CONFIG_PCIE_DW_ROCKCHIP) += pcie_dw_rockchip.o obj-$(CONFIG_PCIE_DW_MESON) += pcie_dw_meson.o +obj-$(CONFIG_PCIE_DW_QCOM) += pcie_dw_qcom.o obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o obj-$(CONFIG_PCIE_OCTEON) += pcie_octeon.o diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 2753df275ca..3697ad00be2 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -347,6 +347,7 @@ int vesa_setup_video_priv(struct vesa_mode_info *vesa, u64 fb, case 32: case 24: uc_priv->bpix = VIDEO_BPP32; + uc_priv->format = VIDEO_X8B8G8R8; break; case 16: uc_priv->bpix = VIDEO_BPP16; @@ -392,6 +393,7 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void)) uc_priv->ysize = ho->ysize; uc_priv->line_length = ho->line_length; uc_priv->bpix = ho->bpix; + uc_priv->format = ho->format; } else { bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); ret = dm_pci_run_vga_bios(dev, int15_handler, @@ -438,6 +440,7 @@ int vesa_setup_video(struct udevice *dev, int (*int15_handler)(void)) ho->ysize = uc_priv->ysize; ho->line_length = uc_priv->line_length; ho->bpix = uc_priv->bpix; + ho->format = uc_priv->format; } return 0; diff --git a/drivers/pci/pcie_dw_common.c b/drivers/pci/pcie_dw_common.c index 0673e516c6f..78961271a8e 100644 --- a/drivers/pci/pcie_dw_common.c +++ b/drivers/pci/pcie_dw_common.c @@ -267,6 +267,48 @@ int pcie_dw_write_config(struct udevice *bus, pci_dev_t bdf, pcie->io.bus_start, pcie->io.size); } +/* + * These interfaces resemble the pci_find_*capability() interfaces, but these + * are for configuring host controllers, which are bridges *to* PCI devices but + * are not PCI devices themselves. + */ +static u8 pcie_dw_find_next_cap(struct pcie_dw *pci, u8 cap_ptr, u8 cap) +{ + u8 cap_id, next_cap_ptr; + u32 val; + u16 reg; + + if (!cap_ptr) + return 0; + + val = readl(pci->dbi_base + (cap_ptr & ~0x3)); + reg = pci_conv_32_to_size(val, cap_ptr, 2); + cap_id = (reg & 0x00ff); + + if (cap_id > PCI_CAP_ID_MAX) + return 0; + + if (cap_id == cap) + return cap_ptr; + + next_cap_ptr = (reg & 0xff00) >> 8; + return pcie_dw_find_next_cap(pci, next_cap_ptr, cap); +} + +u8 pcie_dw_find_capability(struct pcie_dw *pci, u8 cap) +{ + u8 next_cap_ptr; + u32 val; + u16 reg; + + val = readl(pci->dbi_base + (PCI_CAPABILITY_LIST & ~0x3)); + reg = pci_conv_32_to_size(val, PCI_CAPABILITY_LIST, 2); + + next_cap_ptr = (reg & 0x00ff); + + return pcie_dw_find_next_cap(pci, next_cap_ptr, cap); +} + /** * pcie_dw_setup_host() - Setup the PCIe controller for RC opertaion * diff --git a/drivers/pci/pcie_dw_common.h b/drivers/pci/pcie_dw_common.h index e0f7796f2a8..8cb99a12ea1 100644 --- a/drivers/pci/pcie_dw_common.h +++ b/drivers/pci/pcie_dw_common.h @@ -139,6 +139,8 @@ int pcie_dw_read_config(const struct udevice *bus, pci_dev_t bdf, uint offset, u int pcie_dw_write_config(struct udevice *bus, pci_dev_t bdf, uint offset, ulong value, enum pci_size_t size); +u8 pcie_dw_find_capability(struct pcie_dw *pci, u8 cap); + static inline void dw_pcie_dbi_write_enable(struct pcie_dw *pci, bool en) { u32 val; diff --git a/drivers/pci/pcie_dw_qcom.c b/drivers/pci/pcie_dw_qcom.c new file mode 100644 index 00000000000..39b4cd4efe2 --- /dev/null +++ b/drivers/pci/pcie_dw_qcom.c @@ -0,0 +1,571 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <clk.h> +#include <dm.h> +#include <generic-phy.h> +#include <pci.h> +#include <u-boot/crc.h> +#include <power-domain.h> +#include <reset.h> +#include <syscon.h> +#include <malloc.h> +#include <power/regulator.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm-generic/gpio.h> +#include <dm/device_compat.h> +#include <linux/iopoll.h> +#include <linux/delay.h> +#include <linux/log2.h> +#include <linux/bitfield.h> + +#include "pcie_dw_common.h" + +DECLARE_GLOBAL_DATA_PTR; + +struct qcom_pcie; + +struct qcom_pcie_ops { + int (*config_sid)(struct qcom_pcie *priv); +}; + +#define NUM_SUPPLIES 2 + +struct qcom_pcie { + /* Must be first member of the struct */ + struct pcie_dw dw; + void *parf; + struct phy phy; + struct reset_ctl_bulk rsts; + struct clk_bulk clks; + struct gpio_desc rst_gpio; + struct qcom_pcie_ops *ops; + struct udevice *vregs[NUM_SUPPLIES]; +}; + +/* PARF registers */ +#define PARF_SYS_CTRL 0x00 +#define PARF_PM_CTRL 0x20 +#define PARF_PCS_DEEMPH 0x34 +#define PARF_PCS_SWING 0x38 +#define PARF_PHY_CTRL 0x40 +#define PARF_PHY_REFCLK 0x4c +#define PARF_CONFIG_BITS 0x50 +#define PARF_DBI_BASE_ADDR 0x168 +#define PARF_MHI_CLOCK_RESET_CTRL 0x174 +#define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 +#define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 +#define PARF_Q2A_FLUSH 0x1ac +#define PARF_LTSSM 0x1b0 +#define PARF_SID_OFFSET 0x234 +#define PARF_BDF_TRANSLATE_CFG 0x24c +#define PARF_SLV_ADDR_SPACE_SIZE 0x358 +#define PARF_DEVICE_TYPE 0x1000 +#define PARF_BDF_TO_SID_TABLE_N 0x2000 + +/* ELBI registers */ +#define ELBI_SYS_CTRL 0x04 + +/* DBI registers */ +#define AXI_MSTR_RESP_COMP_CTRL0 0x818 +#define AXI_MSTR_RESP_COMP_CTRL1 0x81c +#define MISC_CONTROL_1_REG 0x8bc + +/* MHI registers */ +#define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04 +#define PARF_DEBUG_CNT_PM_LINKST_IN_L1 0xc0c +#define PARF_DEBUG_CNT_PM_LINKST_IN_L0S 0xc10 +#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1 0xc84 +#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2 0xc88 + +/* PARF_SYS_CTRL register fields */ +#define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN BIT(29) +#define MST_WAKEUP_EN BIT(13) +#define SLV_WAKEUP_EN BIT(12) +#define MSTR_ACLK_CGC_DIS BIT(10) +#define SLV_ACLK_CGC_DIS BIT(9) +#define CORE_CLK_CGC_DIS BIT(6) +#define AUX_PWR_DET BIT(4) +#define L23_CLK_RMV_DIS BIT(2) +#define L1_CLK_RMV_DIS BIT(1) + +/* PARF_PM_CTRL register fields */ +#define REQ_NOT_ENTR_L1 BIT(5) + +/* PARF_PCS_DEEMPH register fields */ +#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) FIELD_PREP(GENMASK(21, 16), x) +#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) FIELD_PREP(GENMASK(13, 8), x) +#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) FIELD_PREP(GENMASK(5, 0), x) + +/* PARF_PCS_SWING register fields */ +#define PCS_SWING_TX_SWING_FULL(x) FIELD_PREP(GENMASK(14, 8), x) +#define PCS_SWING_TX_SWING_LOW(x) FIELD_PREP(GENMASK(6, 0), x) + +/* PARF_PHY_CTRL register fields */ +#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK GENMASK(20, 16) +#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) FIELD_PREP(PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK, x) +#define PHY_TEST_PWR_DOWN BIT(0) + +/* PARF_PHY_REFCLK register fields */ +#define PHY_REFCLK_SSP_EN BIT(16) +#define PHY_REFCLK_USE_PAD BIT(12) + +/* PARF_CONFIG_BITS register fields */ +#define PHY_RX0_EQ(x) FIELD_PREP(GENMASK(26, 24), x) + +/* PARF_SLV_ADDR_SPACE_SIZE register value */ +#define SLV_ADDR_SPACE_SZ 0x10000000 + +/* PARF_MHI_CLOCK_RESET_CTRL register fields */ +#define AHB_CLK_EN BIT(0) +#define MSTR_AXI_CLK_EN BIT(1) +#define BYPASS BIT(4) + +/* PARF_AXI_MSTR_WR_ADDR_HALT register fields */ +#define EN BIT(31) + +/* PARF_LTSSM register fields */ +#define LTSSM_EN BIT(8) + +/* PARF_DEVICE_TYPE register fields */ +#define DEVICE_TYPE_RC 0x4 + +/* ELBI_SYS_CTRL register fields */ +#define ELBI_SYS_CTRL_LT_ENABLE BIT(0) + +/* AXI_MSTR_RESP_COMP_CTRL0 register fields */ +#define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K 0x4 +#define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_4K 0x5 + +/* AXI_MSTR_RESP_COMP_CTRL1 register fields */ +#define CFG_BRIDGE_SB_INIT BIT(0) + +/* MISC_CONTROL_1_REG register fields */ +#define DBI_RO_WR_EN 1 + +/* PCI_EXP_SLTCAP register fields */ +#define PCIE_CAP_SLOT_POWER_LIMIT_VAL FIELD_PREP(PCI_EXP_SLTCAP_SPLV, 250) +#define PCIE_CAP_SLOT_POWER_LIMIT_SCALE FIELD_PREP(PCI_EXP_SLTCAP_SPLS, 1) +#define PCIE_CAP_SLOT_VAL (PCI_EXP_SLTCAP_ABP | \ + PCI_EXP_SLTCAP_PCP | \ + PCI_EXP_SLTCAP_MRLSP | \ + PCI_EXP_SLTCAP_AIP | \ + PCI_EXP_SLTCAP_PIP | \ + PCI_EXP_SLTCAP_HPS | \ + PCI_EXP_SLTCAP_HPC | \ + PCI_EXP_SLTCAP_EIP | \ + PCIE_CAP_SLOT_POWER_LIMIT_VAL | \ + PCIE_CAP_SLOT_POWER_LIMIT_SCALE) + +#define PERST_DELAY_US 1000 + +#define LINK_WAIT_MAX_RETRIES 10 +#define LINK_WAIT_USLEEP 100000 + +#define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) + +#define CRC8_TABLE_SIZE 256 + +static bool qcom_pcie_wait_link_up(struct qcom_pcie *priv) +{ + u8 offset = pcie_dw_find_capability(&priv->dw, PCI_CAP_ID_EXP); + unsigned int cnt = 0; + u16 val; + + do { + val = readw(priv->dw.dbi_base + offset + PCI_EXP_LNKSTA); + + if ((val & PCI_EXP_LNKSTA_DLLLA)) + return true; + cnt++; + + udelay(LINK_WAIT_USLEEP); + } while (cnt < LINK_WAIT_MAX_RETRIES); + + return false; +} + +static void qcom_pcie_clear_aspm_l0s(struct qcom_pcie *priv) +{ + u8 offset = pcie_dw_find_capability(&priv->dw, PCI_CAP_ID_EXP); + u32 val; + + dw_pcie_dbi_write_enable(&priv->dw, true); + + val = readl(priv->dw.dbi_base + offset + PCI_EXP_LNKCAP); + val &= ~PCI_EXP_LNKCAP_ASPM_L0S; + writel(val, priv->dw.dbi_base + offset + PCI_EXP_LNKCAP); + + dw_pcie_dbi_write_enable(&priv->dw, false); +} + +static void qcom_pcie_clear_hpc(struct qcom_pcie *priv) +{ + u8 offset = pcie_dw_find_capability(&priv->dw, PCI_CAP_ID_EXP); + u32 val; + + dw_pcie_dbi_write_enable(&priv->dw, true); + + val = readl(priv->dw.dbi_base + offset + PCI_EXP_SLTCAP); + val &= ~PCI_EXP_SLTCAP_HPC; + writel(val, priv->dw.dbi_base + offset + PCI_EXP_SLTCAP); + + dw_pcie_dbi_write_enable(&priv->dw, false); +} + +static void qcom_pcie_set_lanes(struct qcom_pcie *priv, unsigned int lanes) +{ + u8 offset = pcie_dw_find_capability(&priv->dw, PCI_CAP_ID_EXP); + u32 val; + + val = readl(priv->dw.dbi_base + offset + PCI_EXP_LNKCAP); + val &= ~PCI_EXP_LNKCAP_MLW; + val |= FIELD_PREP(PCI_EXP_LNKCAP_MLW, lanes); + writel(val, priv->dw.dbi_base + offset + PCI_EXP_LNKCAP); +} + +static int qcom_pcie_config_sid_1_9_0(struct qcom_pcie *priv) +{ + /* iommu map structure */ + struct { + u32 bdf; + u32 phandle; + u32 smmu_sid; + u32 smmu_sid_len; + } *map; + void *bdf_to_sid_base = priv->parf + PARF_BDF_TO_SID_TABLE_N; + int i, nr_map, size = 0; + u32 smmu_sid_base; + + dev_read_prop(priv->dw.dev, "iommu-map", &size); + if (!size) + return 0; + + map = malloc(size); + if (!map) + return -ENOMEM; + + dev_read_u32_array(priv->dw.dev, "iommu-map", (u32 *)map, size / sizeof(u32)); + + nr_map = size / (sizeof(*map)); + + /* Registers need to be zero out first */ + memset_io(bdf_to_sid_base, 0, CRC8_TABLE_SIZE * sizeof(u32)); + + /* Extract the SMMU SID base from the first entry of iommu-map */ + smmu_sid_base = map[0].smmu_sid; + + /* Look for an available entry to hold the mapping */ + for (i = 0; i < nr_map; i++) { + __be16 bdf_be = cpu_to_be16(map[i].bdf); + u32 val; + u8 hash; + + hash = crc8(QCOM_PCIE_CRC8_POLYNOMIAL, (u8 *)&bdf_be, sizeof(bdf_be)); + + val = readl(bdf_to_sid_base + hash * sizeof(u32)); + + /* If the register is already populated, look for next available entry */ + while (val) { + u8 current_hash = hash++; + u8 next_mask = 0xff; + + /* If NEXT field is NULL then update it with next hash */ + if (!(val & next_mask)) { + val |= (u32)hash; + writel(val, bdf_to_sid_base + current_hash * sizeof(u32)); + } + + val = readl(bdf_to_sid_base + hash * sizeof(u32)); + } + + /* BDF [31:16] | SID [15:8] | NEXT [7:0] */ + val = map[i].bdf << 16 | (map[i].smmu_sid - smmu_sid_base) << 8 | 0; + writel(val, bdf_to_sid_base + hash * sizeof(u32)); + } + + free(map); + + return 0; +} + +static void qcom_pcie_configure(struct qcom_pcie *priv) +{ + u32 val; + + dw_pcie_dbi_write_enable(&priv->dw, true); + + val = readl(priv->dw.dbi_base + PCIE_PORT_LINK_CONTROL); + val &= ~PORT_LINK_FAST_LINK_MODE; + val |= PORT_LINK_DLL_LINK_EN; + val &= ~PORT_LINK_MODE_MASK; + val |= PORT_LINK_MODE_2_LANES; + writel(val, priv->dw.dbi_base + PCIE_PORT_LINK_CONTROL); + + val = readl(priv->dw.dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); + val &= ~PORT_LOGIC_LINK_WIDTH_MASK; + val |= PORT_LOGIC_LINK_WIDTH_2_LANES; + writel(val, priv->dw.dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); + + qcom_pcie_set_lanes(priv, 2); + + dw_pcie_dbi_write_enable(&priv->dw, false); +} + +static int qcom_pcie_init_port(struct udevice *dev) +{ + struct qcom_pcie *priv = dev_get_priv(dev); + int vreg, ret; + u32 val; + + dm_gpio_set_value(&priv->rst_gpio, 1); + udelay(PERST_DELAY_US); + + ret = generic_phy_init(&priv->phy); + if (ret) { + dev_err(dev, "failed to init phy (%d)\n", ret); + return ret; + } + + udelay(PERST_DELAY_US); + + for (vreg = 0; vreg < NUM_SUPPLIES; ++vreg) { + ret = regulator_set_enable(priv->vregs[vreg], true); + if (ret && ret != -ENOSYS) + dev_warn(dev, "failed to enable regulator %d (%d)\n", vreg, ret); + } + + ret = clk_enable_bulk(&priv->clks); + if (ret) { + dev_err(dev, "failed to enable clocks (%d)\n", ret); + goto err_power_off_phy; + } + + ret = reset_assert_bulk(&priv->rsts); + if (ret) { + dev_err(dev, "failed to assert resets (%d)\n", ret); + goto err_disable_clks; + } + + udelay(PERST_DELAY_US); + + ret = reset_deassert_bulk(&priv->rsts); + if (ret) { + dev_err(dev, "failed to deassert resets (%d)\n", ret); + goto err_power_off_phy; + } + + udelay(PERST_DELAY_US); + + /* configure PCIe to RC mode */ + writel(DEVICE_TYPE_RC, priv->parf + PARF_DEVICE_TYPE); + + /* enable PCIe clocks and resets */ + val = readl(priv->parf + PARF_PHY_CTRL); + val &= ~PHY_TEST_PWR_DOWN; + writel(val, priv->parf + PARF_PHY_CTRL); + + /* change DBI base address */ + writel(0, priv->parf + PARF_DBI_BASE_ADDR); + + /* MAC PHY_POWERDOWN MUX DISABLE */ + val = readl(priv->parf + PARF_SYS_CTRL); + val &= ~MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN; + writel(val, priv->parf + PARF_SYS_CTRL); + + val = readl(priv->parf + PARF_MHI_CLOCK_RESET_CTRL); + val |= BYPASS; + writel(val, priv->parf + PARF_MHI_CLOCK_RESET_CTRL); + + /* Enable L1 and L1SS */ + val = readl(priv->parf + PARF_PM_CTRL); + val &= ~REQ_NOT_ENTR_L1; + writel(val, priv->parf + PARF_PM_CTRL); + + val = readl(priv->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val |= EN; + writel(val, priv->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + dev_err(dev, "failed to power on phy (%d)\n", ret); + goto err_exit_phy; + } + + qcom_pcie_clear_aspm_l0s(priv); + qcom_pcie_clear_hpc(priv); + + mdelay(100); + dm_gpio_set_value(&priv->rst_gpio, 0); + udelay(PERST_DELAY_US); + + if (priv->ops && priv->ops->config_sid) { + ret = priv->ops->config_sid(priv); + if (ret) + goto err_deassert_bulk; + } + + qcom_pcie_configure(priv); + + pcie_dw_setup_host(&priv->dw); + + /* enable link training */ + val = readl(priv->parf + PARF_LTSSM); + val |= LTSSM_EN; + writel(val, priv->parf + PARF_LTSSM); + + return 0; +err_deassert_bulk: + reset_assert_bulk(&priv->rsts); +err_disable_clks: + clk_disable_bulk(&priv->clks); +err_power_off_phy: + generic_phy_power_off(&priv->phy); +err_exit_phy: + generic_phy_exit(&priv->phy); + + return ret; +} + +static const char *qcom_pcie_vregs[NUM_SUPPLIES] = { + "vdda-supply", + "vddpe-3v3-supply", +}; + +static int qcom_pcie_parse_dt(struct udevice *dev) +{ + struct qcom_pcie *priv = dev_get_priv(dev); + int vreg, ret; + + priv->dw.dbi_base = dev_read_addr_name_ptr(dev, "dbi"); + if (!priv->dw.dbi_base) + return -EINVAL; + + dev_dbg(dev, "DBI address is 0x%p\n", priv->dw.dbi_base); + + priv->dw.atu_base = dev_read_addr_name_ptr(dev, "atu"); + if (!priv->dw.atu_base) + return -EINVAL; + + dev_dbg(dev, "ATU address is 0x%p\n", priv->dw.atu_base); + + priv->parf = dev_read_addr_name_ptr(dev, "parf"); + if (!priv->parf) + return -EINVAL; + + dev_dbg(dev, "PARF address is 0x%p\n", priv->parf); + + ret = gpio_request_by_name(dev, "perst-gpios", 0, + &priv->rst_gpio, GPIOD_IS_OUT); + if (ret) { + dev_err(dev, "failed to find reset-gpios property\n"); + return ret; + } + + ret = reset_get_bulk(dev, &priv->rsts); + if (ret) { + dev_err(dev, "failed to get resets (%d)\n", ret); + return ret; + } + + ret = clk_get_bulk(dev, &priv->clks); + if (ret) { + dev_err(dev, "failed to get clocks (%d)\n", ret); + return ret; + } + + ret = generic_phy_get_by_index(dev, 0, &priv->phy); + if (ret) { + dev_err(dev, "failed to get pcie phy (%d)\n", ret); + return ret; + } + + for (vreg = 0; vreg < NUM_SUPPLIES; ++vreg) { + ret = device_get_supply_regulator(dev, qcom_pcie_vregs[vreg], &priv->vregs[vreg]); + if (ret) + dev_warn(dev, "failed to get regulator %d (%d)\n", vreg, ret); + } + + return 0; +} + +/** + * qcom_pcie_probe() - Probe the PCIe bus for active link + * + * @dev: A pointer to the device being operated on + * + * Probe for an active link on the PCIe bus and configure the controller + * to enable this port. + * + * Return: 0 on success, else -ENODEV + */ +static int qcom_pcie_probe(struct udevice *dev) +{ + struct qcom_pcie *priv = dev_get_priv(dev); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + int ret = 0; + + priv->dw.first_busno = dev_seq(dev); + priv->dw.dev = dev; + + ret = qcom_pcie_parse_dt(dev); + if (ret) + return ret; + + ret = qcom_pcie_init_port(dev); + if (ret) { + dm_gpio_free(dev, &priv->rst_gpio); + return ret; + } + + if (qcom_pcie_wait_link_up(priv)) + printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", + dev_seq(dev), pcie_dw_get_link_speed(&priv->dw), + pcie_dw_get_link_width(&priv->dw), + hose->first_busno); + else + printf("PCIE-%d: Link up timeout\n", dev_seq(dev)); + + return pcie_dw_prog_outbound_atu_unroll(&priv->dw, + PCIE_ATU_REGION_INDEX0, + PCIE_ATU_TYPE_MEM, + priv->dw.mem.phys_start, + priv->dw.mem.bus_start, + priv->dw.mem.size); +} + +static const struct dm_pci_ops qcom_pcie_ops = { + .read_config = pcie_dw_read_config, + .write_config = pcie_dw_write_config, +}; + +static const struct qcom_pcie_ops ops_1_9_0 = { + .config_sid = qcom_pcie_config_sid_1_9_0, +}; + +static const struct udevice_id qcom_pcie_ids[] = { + { .compatible = "qcom,pcie-sa8540p", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sc7280", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sc8180x", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sc8280xp", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sdm845" }, + { .compatible = "qcom,pcie-sdx55", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sm8150", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sm8250", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sm8350", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sm8450-pcie0", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sm8450-pcie1", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-sm8550", .data = (ulong)&ops_1_9_0 }, + { .compatible = "qcom,pcie-x1e80100", .data = (ulong)&ops_1_9_0 }, + { } +}; + +U_BOOT_DRIVER(qcom_dw_pcie) = { + .name = "pcie_dw_qcom", + .id = UCLASS_PCI, + .of_match = qcom_pcie_ids, + .ops = &qcom_pcie_ops, + .probe = qcom_pcie_probe, + .priv_auto = sizeof(struct qcom_pcie), +}; diff --git a/drivers/pci/pcie_mediatek_gen3.c b/drivers/pci/pcie_mediatek_gen3.c index 0149edae0bf..1818d4c1e30 100644 --- a/drivers/pci/pcie_mediatek_gen3.c +++ b/drivers/pci/pcie_mediatek_gen3.c @@ -83,6 +83,28 @@ struct mtk_pcie { struct phy phy; }; +static pci_dev_t convert_bdf(const struct udevice *controller, pci_dev_t bdf) +{ + int bdfs[3]; + + bdfs[0] = PCI_BUS(bdf); + bdfs[1] = PCI_DEV(bdf); + bdfs[2] = PCI_FUNC(bdf); + + /* + * One MediaTek PCIe Gen3 controller has only one port, where PCI bus 0 on + * this port represents the controller itself and bus 1 represents the + * external PCIe device. If multiple PCIe controllers are probed in U-Boot, + * U-Boot will use bus numbers greater than 2 as input parameters. Therefore, + * we should convert the BDF bus number to either 0 or 1 by subtracting the + * offset by controller->seq_ + */ + + bdfs[0] = bdfs[0] - controller->seq_; + + return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]); +} + static void mtk_pcie_config_tlp_header(const struct udevice *bus, pci_dev_t devfn, int where, int size) @@ -91,6 +113,8 @@ static void mtk_pcie_config_tlp_header(const struct udevice *bus, int bytes; u32 val; + devfn = convert_bdf(bus, devfn); + size = 1 << size; bytes = (GENMASK(size - 1, 0) & 0xf) << (where & 0x3); diff --git a/drivers/phy/qcom/Kconfig b/drivers/phy/qcom/Kconfig index 5c77203d606..61e5e2fca41 100644 --- a/drivers/phy/qcom/Kconfig +++ b/drivers/phy/qcom/Kconfig @@ -12,6 +12,12 @@ config PHY_QCOM_IPQ4019_USB help Support for the USB PHY-s on Qualcomm IPQ40xx SoC-s. +config PHY_QCOM_QMP_PCIE + tristate "Qualcomm QMP PCIe PHY driver" + depends on PHY && ARCH_SNAPDRAGON + help + Enable this to support the PCIe QMP PHY on various Qualcomm chipsets. + config PHY_QCOM_QMP_UFS tristate "Qualcomm QMP UFS PHY driver" depends on PHY && ARCH_SNAPDRAGON diff --git a/drivers/phy/qcom/Makefile b/drivers/phy/qcom/Makefile index dc3ed492696..1c4e7d8d391 100644 --- a/drivers/phy/qcom/Makefile +++ b/drivers/phy/qcom/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_MSM8916_USB_PHY) += msm8916-usbh-phy.o +obj-$(CONFIG_PHY_QCOM_QMP_PCIE) += phy-qcom-qmp-pcie.o obj-$(CONFIG_PHY_QCOM_QMP_UFS) += phy-qcom-qmp-ufs.o obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o obj-$(CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2) += phy-qcom-snps-femto-v2.o diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcie-qhp.h b/drivers/phy/qcom/phy-qcom-qmp-pcie-qhp.h new file mode 100644 index 00000000000..e4a4d2cd85e --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcie-qhp.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_PCIE_QHP_H_ +#define QCOM_PHY_QMP_PCIE_QHP_H_ + +/* PCIE GEN3 COM registers */ +#define PCIE_GEN3_QHP_COM_SSC_EN_CENTER 0x14 +#define PCIE_GEN3_QHP_COM_SSC_PER1 0x20 +#define PCIE_GEN3_QHP_COM_SSC_PER2 0x24 +#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1 0x28 +#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2 0x2c +#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE1_MODE1 0x34 +#define PCIE_GEN3_QHP_COM_SSC_STEP_SIZE2_MODE1 0x38 +#define PCIE_GEN3_QHP_COM_BIAS_EN_CKBUFLR_EN 0x54 +#define PCIE_GEN3_QHP_COM_CLK_ENABLE1 0x58 +#define PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE0 0x6c +#define PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE0 0x70 +#define PCIE_GEN3_QHP_COM_LOCK_CMP1_MODE1 0x78 +#define PCIE_GEN3_QHP_COM_LOCK_CMP2_MODE1 0x7c +#define PCIE_GEN3_QHP_COM_BGV_TRIM 0x98 +#define PCIE_GEN3_QHP_COM_CP_CTRL_MODE0 0xb4 +#define PCIE_GEN3_QHP_COM_CP_CTRL_MODE1 0xb8 +#define PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE0 0xc0 +#define PCIE_GEN3_QHP_COM_PLL_RCTRL_MODE1 0xc4 +#define PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE0 0xcc +#define PCIE_GEN3_QHP_COM_PLL_CCTRL_MODE1 0xd0 +#define PCIE_GEN3_QHP_COM_SYSCLK_EN_SEL 0xdc +#define PCIE_GEN3_QHP_COM_RESTRIM_CTRL2 0xf0 +#define PCIE_GEN3_QHP_COM_LOCK_CMP_EN 0xf8 +#define PCIE_GEN3_QHP_COM_DEC_START_MODE0 0x100 +#define PCIE_GEN3_QHP_COM_DEC_START_MODE1 0x108 +#define PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE0 0x11c +#define PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE0 0x120 +#define PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE0 0x124 +#define PCIE_GEN3_QHP_COM_DIV_FRAC_START1_MODE1 0x128 +#define PCIE_GEN3_QHP_COM_DIV_FRAC_START2_MODE1 0x12c +#define PCIE_GEN3_QHP_COM_DIV_FRAC_START3_MODE1 0x130 +#define PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE0 0x150 +#define PCIE_GEN3_QHP_COM_INTEGLOOP_GAIN0_MODE1 0x158 +#define PCIE_GEN3_QHP_COM_VCO_TUNE_MAP 0x178 +#define PCIE_GEN3_QHP_COM_BG_CTRL 0x1c8 +#define PCIE_GEN3_QHP_COM_CLK_SELECT 0x1cc +#define PCIE_GEN3_QHP_COM_HSCLK_SEL1 0x1d0 +#define PCIE_GEN3_QHP_COM_CORECLK_DIV 0x1e0 +#define PCIE_GEN3_QHP_COM_CORE_CLK_EN 0x1e8 +#define PCIE_GEN3_QHP_COM_CMN_CONFIG 0x1f0 +#define PCIE_GEN3_QHP_COM_SVS_MODE_CLK_SEL 0x1fc +#define PCIE_GEN3_QHP_COM_CORECLK_DIV_MODE1 0x21c +#define PCIE_GEN3_QHP_COM_CMN_MODE 0x224 +#define PCIE_GEN3_QHP_COM_VREGCLK_DIV1 0x228 +#define PCIE_GEN3_QHP_COM_VREGCLK_DIV2 0x22c + +/* PCIE GEN3 QHP Lane registers */ +#define PCIE_GEN3_QHP_L0_DRVR_CTRL0 0xc +#define PCIE_GEN3_QHP_L0_DRVR_CTRL1 0x10 +#define PCIE_GEN3_QHP_L0_DRVR_CTRL2 0x14 +#define PCIE_GEN3_QHP_L0_DRVR_TAP_EN 0x18 +#define PCIE_GEN3_QHP_L0_TX_BAND_MODE 0x60 +#define PCIE_GEN3_QHP_L0_LANE_MODE 0x64 +#define PCIE_GEN3_QHP_L0_PARALLEL_RATE 0x7c +#define PCIE_GEN3_QHP_L0_CML_CTRL_MODE0 0xc0 +#define PCIE_GEN3_QHP_L0_CML_CTRL_MODE1 0xc4 +#define PCIE_GEN3_QHP_L0_CML_CTRL_MODE2 0xc8 +#define PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE1 0xd0 +#define PCIE_GEN3_QHP_L0_PREAMP_CTRL_MODE2 0xd4 +#define PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE0 0xd8 +#define PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE1 0xdc +#define PCIE_GEN3_QHP_L0_MIXER_CTRL_MODE2 0xe0 +#define PCIE_GEN3_QHP_L0_CTLE_THRESH_DFE 0xfc +#define PCIE_GEN3_QHP_L0_CGA_THRESH_DFE 0x100 +#define PCIE_GEN3_QHP_L0_RXENGINE_EN0 0x108 +#define PCIE_GEN3_QHP_L0_CTLE_TRAIN_TIME 0x114 +#define PCIE_GEN3_QHP_L0_CTLE_DFE_OVRLP_TIME 0x118 +#define PCIE_GEN3_QHP_L0_DFE_REFRESH_TIME 0x11c +#define PCIE_GEN3_QHP_L0_DFE_ENABLE_TIME 0x120 +#define PCIE_GEN3_QHP_L0_VGA_GAIN 0x124 +#define PCIE_GEN3_QHP_L0_DFE_GAIN 0x128 +#define PCIE_GEN3_QHP_L0_EQ_GAIN 0x130 +#define PCIE_GEN3_QHP_L0_OFFSET_GAIN 0x134 +#define PCIE_GEN3_QHP_L0_PRE_GAIN 0x138 +#define PCIE_GEN3_QHP_L0_VGA_INITVAL 0x13c +#define PCIE_GEN3_QHP_L0_EQ_INTVAL 0x154 +#define PCIE_GEN3_QHP_L0_EDAC_INITVAL 0x160 +#define PCIE_GEN3_QHP_L0_RXEQ_INITB0 0x168 +#define PCIE_GEN3_QHP_L0_RXEQ_INITB1 0x16c +#define PCIE_GEN3_QHP_L0_RCVRDONE_THRESH1 0x178 +#define PCIE_GEN3_QHP_L0_RXEQ_CTRL 0x180 +#define PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE0 0x184 +#define PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE1 0x188 +#define PCIE_GEN3_QHP_L0_UCDR_FO_GAIN_MODE2 0x18c +#define PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE0 0x190 +#define PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE1 0x194 +#define PCIE_GEN3_QHP_L0_UCDR_SO_GAIN_MODE2 0x198 +#define PCIE_GEN3_QHP_L0_UCDR_SO_CONFIG 0x19c +#define PCIE_GEN3_QHP_L0_RX_BAND 0x1a4 +#define PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE0 0x1c0 +#define PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE1 0x1c4 +#define PCIE_GEN3_QHP_L0_RX_RCVR_PATH1_MODE2 0x1c8 +#define PCIE_GEN3_QHP_L0_SIGDET_ENABLES 0x230 +#define PCIE_GEN3_QHP_L0_SIGDET_CNTRL 0x234 +#define PCIE_GEN3_QHP_L0_SIGDET_DEGLITCH_CNTRL 0x238 +#define PCIE_GEN3_QHP_L0_DCC_GAIN 0x2a4 +#define PCIE_GEN3_QHP_L0_RSM_START 0x2a8 +#define PCIE_GEN3_QHP_L0_RX_EN_SIGNAL 0x2ac +#define PCIE_GEN3_QHP_L0_PSM_RX_EN_CAL 0x2b0 +#define PCIE_GEN3_QHP_L0_RX_MISC_CNTRL0 0x2b8 +#define PCIE_GEN3_QHP_L0_TS0_TIMER 0x2c0 +#define PCIE_GEN3_QHP_L0_DLL_HIGHDATARATE 0x2c4 +#define PCIE_GEN3_QHP_L0_RX_RESETCODE_OFFSET 0x2cc + +/* PCIE GEN3 PCS registers */ +#define PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M3P5DB 0x2c +#define PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M3P5DB 0x40 +#define PCIE_GEN3_QHP_PHY_TXMGN_MAIN_V0_M6DB 0x54 +#define PCIE_GEN3_QHP_PHY_TXMGN_POST_V0_M6DB 0x68 +#define PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG 0x15c +#define PCIE_GEN3_QHP_PHY_POWER_STATE_CONFIG5 0x16c +#define PCIE_GEN3_QHP_PHY_PCS_TX_RX_CONFIG 0x174 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcie.c b/drivers/phy/qcom/phy-qcom-qmp-pcie.c new file mode 100644 index 00000000000..2f6ff259b35 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcie.c @@ -0,0 +1,1131 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Bhupesh Sharma <bhupesh.sharma@linaro.org> + * + * Based on Linux driver + */ + +#include <clk.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/devres.h> +#include <generic-phy.h> +#include <malloc.h> +#include <reset.h> +#include <power/regulator.h> + +#include <asm/io.h> +#include <linux/bitops.h> +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <linux/ioport.h> + +#include "phy-qcom-qmp.h" +#include "phy-qcom-qmp-pcs-misc-v3.h" +#include "phy-qcom-qmp-pcs-v5.h" +#include "phy-qcom-qmp-pcs-v6.h" +#include "phy-qcom-qmp-pcs-v6_20.h" +#include "phy-qcom-qmp-pcs-pcie-v6.h" +#include "phy-qcom-qmp-pcs-pcie-v6_20.h" +#include "phy-qcom-qmp-pcie-qhp.h" +#include "phy-qcom-qmp-qserdes-com-v6.h" +#include "phy-qcom-qmp-qserdes-txrx-v6.h" +#include "phy-qcom-qmp-qserdes-txrx-v6_20.h" +#include "phy-qcom-qmp-qserdes-ln-shrd-v6.h" + +/* QPHY_SW_RESET bit */ +#define SW_RESET BIT(0) +/* QPHY_POWER_DOWN_CONTROL */ +#define SW_PWRDN BIT(0) +#define REFCLK_DRV_DSBL BIT(1) +/* QPHY_START_CONTROL bits */ +#define SERDES_START BIT(0) +#define PCS_START BIT(1) +/* QPHY_PCS_READY_STATUS bit */ +#define PCS_READY BIT(0) + +/* QPHY_PCS_STATUS bit */ +#define PHYSTATUS BIT(6) +#define PHYSTATUS_4_20 BIT(7) + +#define PHY_INIT_COMPLETE_TIMEOUT (200 * 10000) + +#define NUM_SUPPLIES 3 + +struct qmp_pcie_init_tbl { + unsigned int offset; + unsigned int val; + /* + * mask of lanes for which this register is written + * for cases when second lane needs different values + */ + u8 lane_mask; +}; + +#define QMP_PHY_INIT_CFG(o, v) \ + { \ + .offset = o, \ + .val = v, \ + .lane_mask = 0xff, \ + } + +#define QMP_PHY_INIT_CFG_LANE(o, v, l) \ + { \ + .offset = o, \ + .val = v, \ + .lane_mask = l, \ + } + +/* set of registers with offsets different per-PHY */ +enum qphy_reg_layout { + /* PCS registers */ + QPHY_SW_RESET, + QPHY_START_CTRL, + QPHY_PCS_STATUS, + QPHY_PCS_POWER_DOWN_CONTROL, + /* Keep last to ensure regs_layout arrays are properly initialized */ + QPHY_LAYOUT_SIZE +}; + +static const unsigned int pciephy_v5_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_SW_RESET] = QPHY_V5_PCS_SW_RESET, + [QPHY_START_CTRL] = QPHY_V5_PCS_START_CONTROL, + [QPHY_PCS_STATUS] = QPHY_V5_PCS_PCS_STATUS1, + [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V5_PCS_POWER_DOWN_CONTROL, +}; + +static const unsigned int pciephy_v6_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_SW_RESET] = QPHY_V6_PCS_SW_RESET, + [QPHY_START_CTRL] = QPHY_V6_PCS_START_CONTROL, + [QPHY_PCS_STATUS] = QPHY_V6_PCS_PCS_STATUS1, + [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V6_PCS_POWER_DOWN_CONTROL, +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen3x2_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x93), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x42), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0x55), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_ADDITIONAL_MISC_3, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen3x2_pcie_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_1, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_LANE_MODE_4, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_PI_QEC_CTRL, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_RX, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_TX_RES_CODE_LANE_OFFSET_TX, 0x18), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen3x2_pcie_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_GM_CAL, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH2, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH3, 0xb7), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_HIGH4, 0xea), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_00_LOW, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH, 0x5c), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH2, 0x9c), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH3, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_HIGH4, 0x89), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_01_LOW, 0xdc), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH, 0x94), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH2, 0x5b), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH3, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_MODE_10_HIGH4, 0x89), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_TX_ADAPT_POST_THRESH, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_FO_GAIN, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SO_GAIN, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH1, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_UCDR_SB2_THRESH2, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_VGA_CAL_CNTRL2, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIDGET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_RX_IDAC_TSETTLE_LOW, 0x07), + QMP_PHY_INIT_CFG(QSERDES_V6_RX_SIGDET_CAL_TRIM, 0x08), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen3x2_pcie_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V6_PCS_REFGEN_REQ_CONFIG1, 0x05), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_RX_SIGDET_LVL, 0x77), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_RATE_SLEW_CNTRL1, 0x0b), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_EQ_CONFIG2, 0x0f), + QMP_PHY_INIT_CFG(QPHY_V6_PCS_PCS_TX_RX_CONFIG, 0x8c), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen3x2_pcie_pcs_misc_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_EQ_CONFIG1, 0x1e), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_RXEQEVAL_TIME, 0x27), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2, 0x1d), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4, 0x07), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE, 0xc1), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS, 0x00), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen4x2_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x26), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_POST_DIV_MUX, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x46), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MISC_1, 0x88), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen4x2_pcie_ln_shrd_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3, 0x9a), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5, 0xb6), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6, 0x64), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen4x2_pcie_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1d), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_3, 0x51), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN, 0x34), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen4x2_pcie_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x7c), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x30), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0xb3), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x58), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x26), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x78), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen4x2_pcie_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_G12S1_TXDEEMPH_M6DB, 0x17), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_G3S2_PRE_GAIN, 0x2e), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_RX_SIGDET_LVL, 0xcc), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG4, 0x00), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG5, 0x22), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG1, 0x04), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG2, 0x02), +}; + +static const struct qmp_pcie_init_tbl sm8550_qmp_gen4x2_pcie_pcs_misc_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_OSC_DTCT_ATCIONS, 0x00), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG1, 0x16), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_RXEQEVAL_TIME, 0x27), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_RXEQEVAL_TIME, 0x27), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG5, 0x02), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN, 0x2e), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1, 0x03), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG3, 0x28), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_TX_RX_CONFIG, 0xc0), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_POWER_STATE_CONFIG2, 0x1d), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG5, 0x0f), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_FOM_EQ_CONFIG5, 0xf2), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0xf2), +}; + +static const struct qmp_pcie_init_tbl sm8650_qmp_gen4x2_pcie_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x05), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0xd3), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0xd3), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0x23), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0x9b), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0x60), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x43), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff), +}; + +static const struct qmp_pcie_init_tbl x1e80100_qmp_gen4x2_pcie_serdes_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE1, 0x26), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE1, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE1, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORECLK_DIV_MODE1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE1, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE1, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE1, 0x68), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE1, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE1, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_SEL_1, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE1_MODE0, 0xf8), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_STEP_SIZE2_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CP_CTRL_MODE0, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_RCTRL_MODE0, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CCTRL_MODE0, 0x36), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_CORE_CLK_DIV_MODE0, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP1_MODE0, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP2_MODE0, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DEC_START_MODE0, 0x41), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START1_MODE0, 0xab), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START2_MODE0, 0xaa), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_DIV_FRAC_START3_MODE0, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_HSCLK_HS_SWITCH_SEL_1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_BG_TIMER, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_EN_CENTER, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER1, 0x62), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SSC_PER2, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_POST_DIV_MUX, 0x40), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_BIAS_EN_CLK_BUFLR_EN, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_ENABLE1, 0x90), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYS_CLK_CTRL, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_SYSCLK_EN_SEL, 0x08), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_EN, 0x46), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_LOCK_CMP_CFG, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_VCO_TUNE_MAP, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CLK_SELECT, 0x34), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CORE_CLK_EN, 0xa0), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_CONFIG_1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MISC_1, 0x88), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_CMN_MODE, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_COM_PLL_VCO_DC_LEVEL_CTRL, 0x0f), +}; + +static const struct qmp_pcie_init_tbl x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1, 0x88), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0, 0xd4), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1, 0x12), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2, 0xdb), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3, 0x9a), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4, 0x32), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5, 0xb6), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6, 0x64), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3, 0x1f), + QMP_PHY_INIT_CFG(QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE, 0x5b), +}; + +static const struct qmp_pcie_init_tbl x1e80100_qmp_gen4x2_pcie_tx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX, 0x1d), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_2, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_LANE_MODE_3, 0x51), + QMP_PHY_INIT_CFG(QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN, 0x34), +}; + +static const struct qmp_pcie_init_tbl x1e80100_qmp_gen4x2_pcie_rx_tbl[] = { + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2, 0x0c), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_PI_CONTROLS, 0x16), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_CAL_CTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_BKUP_CTRL1, 0x15), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_2, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_DFE_3, 0x45), + QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0a, 1), + QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_VGA_CAL_MAN_VAL, 0x0b, 2), + QMP_PHY_INIT_CFG(QSERDES_V6_20_VGA_CAL_CNTRL1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_GM_CAL, 0x0d), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4, 0x0b), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_SIGDET_ENABLES, 0x1c), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_PHPRE_CTRL, 0x20), + QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x3a, 1), + QMP_PHY_INIT_CFG_LANE(QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET, 0x38, 2), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32, 0x39), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B1, 0xb3), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B2, 0x58), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B3, 0x9a), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B4, 0x26), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B5, 0xb6), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE2_B6, 0xee), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B0, 0xe4), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B1, 0xa4), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B2, 0x60), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B3, 0xdf), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B4, 0x4b), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B5, 0x76), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_MODE_RATE3_B6, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V6_20_RX_TX_ADPT_CTRL, 0x10), +}; + +static const struct qmp_pcie_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_G3S2_PRE_GAIN, 0x2e), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_RX_SIGDET_LVL, 0xcc), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG4, 0x00), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_EQ_CONFIG5, 0x22), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG1, 0x04), + QMP_PHY_INIT_CFG(QPHY_V6_20_PCS_TX_RX_CONFIG2, 0x02), +}; + +static const struct qmp_pcie_init_tbl x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl[] = { + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_ENDPOINT_REFCLK_DRIVE, 0xc1), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_OSC_DTCT_ATCIONS, 0x00), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG1, 0x16), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_EQ_CONFIG5, 0x02), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN, 0x2e), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1, 0x03), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG3, 0x28), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_RXEQEVAL_TIME, 0x27), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_RXEQEVAL_TIME, 0x27), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_TX_RX_CONFIG, 0xc0), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_POWER_STATE_CONFIG2, 0x1d), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG5, 0x18), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G3_FOM_EQ_CONFIG5, 0x7a), + QMP_PHY_INIT_CFG(QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5, 0x8a), +}; + +struct qmp_pcie_offsets { + u16 serdes; + u16 pcs; + u16 pcs_misc; + u16 tx; + u16 rx; + u16 tx2; + u16 rx2; + u16 ln_shrd; +}; + +struct qmp_pcie_cfg_tbls { + /* Init sequence for PHY blocks - serdes, tx, rx, pcs */ + const struct qmp_pcie_init_tbl *serdes; + int serdes_num; + const struct qmp_pcie_init_tbl *tx; + int tx_num; + const struct qmp_pcie_init_tbl *rx; + int rx_num; + const struct qmp_pcie_init_tbl *pcs; + int pcs_num; + const struct qmp_pcie_init_tbl *pcs_misc; + int pcs_misc_num; + const struct qmp_pcie_init_tbl *ln_shrd; + int ln_shrd_num; +}; + +/* struct qmp_pcie_cfg - per-PHY initialization config */ +struct qmp_pcie_cfg { + int lanes; + + const struct qmp_pcie_offsets *offsets; + + /* Main init sequence for PHY blocks - serdes, tx, rx, pcs */ + const struct qmp_pcie_cfg_tbls tbls; + + /* regulators to be requested */ + const char * const *vreg_list; + int num_vregs; + /* resets to be requested */ + const char * const *reset_list; + int num_resets; + + /* array of registers with different offsets */ + const unsigned int *regs; + + unsigned int pwrdn_ctrl; + /* bit offset of PHYSTATUS in QPHY_PCS_STATUS register */ + unsigned int phy_status; + + bool has_nocsr_reset; +}; + +struct qmp_pcie_priv { + struct phy *phy; + + void __iomem *serdes; + void __iomem *pcs; + void __iomem *pcs_misc; + void __iomem *tx; + void __iomem *rx; + void __iomem *tx2; + void __iomem *rx2; + void __iomem *ln_shrd; + + struct clk *clks; + unsigned int clk_count; + + struct clk pipe_clk; + + struct reset_ctl *resets; + unsigned int reset_count; + + struct reset_ctl nocsr_reset; + + struct udevice *vregs[NUM_SUPPLIES]; + unsigned int vreg_count; + + const struct qmp_pcie_cfg *cfg; + struct udevice *dev; +}; + +static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) +{ + u32 reg; + + reg = readl(base + offset); + reg |= val; + writel(reg, base + offset); + + /* ensure that above write is through */ + readl(base + offset); +} + +static inline void qphy_clrbits(void __iomem *base, u32 offset, u32 val) +{ + u32 reg; + + reg = readl(base + offset); + reg &= ~val; + writel(reg, base + offset); + + /* ensure that above write is through */ + readl(base + offset); +} + +/* list of clocks required by phy */ +static const char * const qmp_pciephy_clk_l[] = { + "aux", "cfg_ahb", "ref", "rchng", +}; + +/* list of regulators */ +static const char * const qmp_phy_vreg_l[] = { + "vdda-phy-supply", "vdda-pll-supply", +}; + +static const char * const sm8550_qmp_phy_vreg_l[] = { + "vdda-phy-supply", "vdda-pll-supply", "vdda-qref-supply", +}; + +/* list of resets */ +static const char * const sdm845_pciephy_reset_l[] = { + "phy", +}; + +static const struct qmp_pcie_offsets qmp_pcie_offsets_v5 = { + .serdes = 0, + .pcs = 0x0200, + .pcs_misc = 0x0600, + .tx = 0x0e00, + .rx = 0x1000, + .tx2 = 0x1600, + .rx2 = 0x1800, +}; + +static const struct qmp_pcie_offsets qmp_pcie_offsets_v6_20 = { + .serdes = 0x1000, + .pcs = 0x1200, + .pcs_misc = 0x1400, + .tx = 0x0000, + .rx = 0x0200, + .tx2 = 0x0800, + .rx2 = 0x0a00, + .ln_shrd = 0x0e00, +}; + +static const struct qmp_pcie_cfg sm8550_qmp_gen3x2_pciephy_cfg = { + .lanes = 2, + + .offsets = &qmp_pcie_offsets_v5, + + .tbls = { + .serdes = sm8550_qmp_gen3x2_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_serdes_tbl), + .tx = sm8550_qmp_gen3x2_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_tx_tbl), + .rx = sm8550_qmp_gen3x2_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_rx_tbl), + .pcs = sm8550_qmp_gen3x2_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_tbl), + .pcs_misc = sm8550_qmp_gen3x2_pcie_pcs_misc_tbl, + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen3x2_pcie_pcs_misc_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = pciephy_v5_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS, +}; + +static const struct qmp_pcie_cfg sm8550_qmp_gen4x2_pciephy_cfg = { + .lanes = 2, + + .offsets = &qmp_pcie_offsets_v6_20, + + .tbls = { + .serdes = sm8550_qmp_gen4x2_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_tbl), + .tx = sm8550_qmp_gen4x2_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_tx_tbl), + .rx = sm8550_qmp_gen4x2_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_rx_tbl), + .pcs = sm8550_qmp_gen4x2_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_tbl), + .pcs_misc = sm8550_qmp_gen4x2_pcie_pcs_misc_tbl, + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_misc_tbl), + .ln_shrd = sm8550_qmp_gen4x2_pcie_ln_shrd_tbl, + .ln_shrd_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_ln_shrd_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), + .regs = pciephy_v6_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS_4_20, + .has_nocsr_reset = true, +}; + +static const struct qmp_pcie_cfg sm8650_qmp_gen4x2_pciephy_cfg = { + .lanes = 2, + + .offsets = &qmp_pcie_offsets_v6_20, + + .tbls = { + .serdes = sm8550_qmp_gen4x2_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_serdes_tbl), + .tx = sm8550_qmp_gen4x2_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_tx_tbl), + .rx = sm8650_qmp_gen4x2_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(sm8650_qmp_gen4x2_pcie_rx_tbl), + .pcs = sm8550_qmp_gen4x2_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_tbl), + .pcs_misc = sm8550_qmp_gen4x2_pcie_pcs_misc_tbl, + .pcs_misc_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_pcs_misc_tbl), + .ln_shrd = sm8550_qmp_gen4x2_pcie_ln_shrd_tbl, + .ln_shrd_num = ARRAY_SIZE(sm8550_qmp_gen4x2_pcie_ln_shrd_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = sm8550_qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(sm8550_qmp_phy_vreg_l), + .regs = pciephy_v6_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS_4_20, + .has_nocsr_reset = true, +}; + +static const struct qmp_pcie_cfg x1e80100_qmp_gen4x2_pciephy_cfg = { + .lanes = 2, + + .offsets = &qmp_pcie_offsets_v6_20, + + .tbls = { + .serdes = x1e80100_qmp_gen4x2_pcie_serdes_tbl, + .serdes_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_serdes_tbl), + .tx = x1e80100_qmp_gen4x2_pcie_tx_tbl, + .tx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_tx_tbl), + .rx = x1e80100_qmp_gen4x2_pcie_rx_tbl, + .rx_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_rx_tbl), + .pcs = x1e80100_qmp_gen4x2_pcie_pcs_tbl, + .pcs_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_tbl), + .pcs_misc = x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl, + .pcs_misc_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_pcs_misc_tbl), + .ln_shrd = x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl, + .ln_shrd_num = ARRAY_SIZE(x1e80100_qmp_gen4x2_pcie_ln_shrd_tbl), + }, + .reset_list = sdm845_pciephy_reset_l, + .num_resets = ARRAY_SIZE(sdm845_pciephy_reset_l), + .vreg_list = qmp_phy_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_phy_vreg_l), + .regs = pciephy_v6_regs_layout, + + .pwrdn_ctrl = SW_PWRDN | REFCLK_DRV_DSBL, + .phy_status = PHYSTATUS_4_20, + .has_nocsr_reset = true, +}; + +static void qmp_pcie_configure_lane(void __iomem *base, + const struct qmp_pcie_init_tbl tbl[], + int num, u8 lane_mask) +{ + int i; + const struct qmp_pcie_init_tbl *t = tbl; + + if (!t) + return; + + for (i = 0; i < num; i++, t++) { + if (!(t->lane_mask & lane_mask)) + continue; + + writel(t->val, base + t->offset); + } +} + +static void qmp_pcie_configure(void __iomem *base, + const struct qmp_pcie_init_tbl tbl[], + int num) +{ + qmp_pcie_configure_lane(base, tbl, num, 0xff); +} + +static void qmp_pcie_init_registers(struct qmp_pcie_priv *qmp, const struct qmp_pcie_cfg *cfg) +{ + const struct qmp_pcie_cfg_tbls *tbls = &cfg->tbls; + void __iomem *serdes = qmp->serdes; + void __iomem *tx = qmp->tx; + void __iomem *rx = qmp->rx; + void __iomem *tx2 = qmp->tx2; + void __iomem *rx2 = qmp->rx2; + void __iomem *pcs = qmp->pcs; + void __iomem *pcs_misc = qmp->pcs_misc; + void __iomem *ln_shrd = qmp->ln_shrd; + + qmp_pcie_configure(serdes, tbls->serdes, tbls->serdes_num); + + qmp_pcie_configure_lane(tx, tbls->tx, tbls->tx_num, 1); + qmp_pcie_configure_lane(rx, tbls->rx, tbls->rx_num, 1); + + if (cfg->lanes >= 2) { + qmp_pcie_configure_lane(tx2, tbls->tx, tbls->tx_num, 2); + qmp_pcie_configure_lane(rx2, tbls->rx, tbls->rx_num, 2); + } + + qmp_pcie_configure(pcs, tbls->pcs, tbls->pcs_num); + qmp_pcie_configure(pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num); + + qmp_pcie_configure(ln_shrd, tbls->ln_shrd, tbls->ln_shrd_num); +} + +static int qmp_pcie_do_reset(struct qmp_pcie_priv *qmp) +{ + const struct qmp_pcie_cfg *cfg = qmp->cfg; + int i, ret; + + for (i = 0; i < qmp->reset_count; i++) { + ret = reset_assert(&qmp->resets[i]); + if (ret) + return ret; + } + + if (cfg->has_nocsr_reset) + reset_assert(&qmp->nocsr_reset); + + udelay(10); + + for (i = 0; i < qmp->reset_count; i++) { + ret = reset_deassert(&qmp->resets[i]); + if (ret) + return ret; + } + + udelay(50); + + return 0; +} + +static int qmp_pcie_power_on(struct phy *phy) +{ + struct qmp_pcie_priv *qmp = dev_get_priv(phy->dev); + const struct qmp_pcie_cfg *cfg = qmp->cfg; + void __iomem *pcs = qmp->pcs; + void __iomem *status; + unsigned int mask, val; + int ret, i; + + for (i = 0; i < qmp->vreg_count; i++) { + ret = regulator_set_enable(qmp->vregs[i], true); + if (ret && ret != -ENOSYS) + dev_err(phy->dev, "failed to enable regulator %d (%d)\n", i, ret); + } + + ret = qmp_pcie_do_reset(qmp); + if (ret) + return ret; + + for (i = 0; i < qmp->clk_count; i++) { + ret = clk_enable(&qmp->clks[i]); + if (ret && ret != -ENOSYS) { + dev_err(phy->dev, "failed to enable clock %d\n", i); + return ret; + } + } + + /* Power down PHY */ + qphy_setbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], cfg->pwrdn_ctrl); + + qmp_pcie_init_registers(qmp, cfg); + + clk_enable(&qmp->pipe_clk); + + if (cfg->has_nocsr_reset) + reset_deassert(&qmp->nocsr_reset); + + /* Pull PHY out of reset state */ + qphy_clrbits(pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + + /* start SerDes */ + qphy_setbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START); + + status = pcs + cfg->regs[QPHY_PCS_STATUS]; + mask = cfg->phy_status; + ret = readl_poll_timeout(status, val, !(val & mask), PHY_INIT_COMPLETE_TIMEOUT); + if (ret) { + dev_err(phy->dev, "phy initialization timed-out\n"); + return ret; + } + + return 0; +} + +static int qmp_pcie_power_off(struct phy *phy) +{ + struct qmp_pcie_priv *qmp = dev_get_priv(phy->dev); + const struct qmp_pcie_cfg *cfg = qmp->cfg; + + clk_disable(&qmp->pipe_clk); + + /* PHY reset */ + qphy_setbits(qmp->pcs, cfg->regs[QPHY_SW_RESET], SW_RESET); + + /* stop SerDes and Phy-Coding-Sublayer */ + qphy_clrbits(qmp->pcs, cfg->regs[QPHY_START_CTRL], + SERDES_START | PCS_START); + + /* Put PHY into POWER DOWN state: active low */ + qphy_clrbits(qmp->pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], + cfg->pwrdn_ctrl); + + return 0; +} + +static int qmp_pcie_vreg_init(struct udevice *dev, struct qmp_pcie_priv *qmp) +{ + const struct qmp_pcie_cfg *cfg = qmp->cfg; + unsigned int vreg; + int ret; + + qmp->vreg_count = cfg->num_vregs; + + for (vreg = 0; vreg < NUM_SUPPLIES && vreg < qmp->vreg_count; ++vreg) { + ret = device_get_supply_regulator(dev, cfg->vreg_list[vreg], &qmp->vregs[vreg]); + if (ret) + dev_warn(dev, "failed to get regulator %d (%d)\n", vreg, ret); + + regulator_set_enable(qmp->vregs[vreg], true); + } + + return 0; +} + +static int qmp_pcie_reset_init(struct udevice *dev, struct qmp_pcie_priv *qmp) +{ + const struct qmp_pcie_cfg *cfg = qmp->cfg; + int num = cfg->num_resets; + int i, ret; + + qmp->reset_count = 0; + qmp->resets = devm_kcalloc(dev, num, sizeof(*qmp->resets), GFP_KERNEL); + if (!qmp->resets) + return -ENOMEM; + + for (i = 0; i < num; i++) { + ret = reset_get_by_name(dev, cfg->reset_list[i], &qmp->resets[i]); + if (ret) { + dev_err(dev, "failed to get reset %d\n", i); + goto reset_get_err; + } + + ++qmp->reset_count; + } + + if (cfg->has_nocsr_reset) { + ret = reset_get_by_name(dev, "phy_nocsr", &qmp->nocsr_reset); + if (ret) + dev_warn(dev, "failed to get nocsr reset\n"); + } + + return 0; + +reset_get_err: + reset_release_all(qmp->resets, qmp->reset_count); + + return ret; +} + +static int qmp_pcie_clk_init(struct udevice *dev, struct qmp_pcie_priv *qmp) +{ + int num = ARRAY_SIZE(qmp_pciephy_clk_l); + int i, ret; + + qmp->clk_count = 0; + qmp->clks = devm_kcalloc(dev, num, sizeof(*qmp->clks), GFP_KERNEL); + if (!qmp->clks) + return -ENOMEM; + + for (i = 0; i < num; i++) { + ret = clk_get_by_name(dev, qmp_pciephy_clk_l[i], &qmp->clks[i]); + /* Ignore failure to get ref clock */ + if (ret && strcmp(qmp_pciephy_clk_l[i], "ref") != 0) { + dev_err(dev, "failed to get clock %d\n", i); + goto clk_get_err; + } + + ++qmp->clk_count; + } + + ret = clk_get_by_name(dev, "pipe", &qmp->pipe_clk); + if (ret) + dev_warn(dev, "failed to get pipe clock\n"); + + return 0; + +clk_get_err: + clk_release_all(qmp->clks, qmp->clk_count); + + return ret; +} + +static int qmp_pcie_parse_dt(struct udevice *dev, struct qmp_pcie_priv *qmp) +{ + const struct qmp_pcie_offsets *offs = qmp->cfg->offsets; + const struct qmp_pcie_cfg *cfg = qmp->cfg; + struct resource res; + int ret; + + if (!qmp->cfg->offsets) { + dev_err(dev, "missing PCIE offsets\n"); + return -EINVAL; + } + + ret = ofnode_read_resource(dev_ofnode(dev), 0, &res); + if (ret) { + dev_err(dev, "can't get reg property\n"); + return ret; + } + + qmp->serdes = (void __iomem *)res.start + offs->serdes; + qmp->pcs = (void __iomem *)res.start + offs->pcs; + qmp->pcs_misc = (void __iomem *)res.start + offs->pcs_misc; + qmp->tx = (void __iomem *)res.start + offs->tx; + qmp->rx = (void __iomem *)res.start + offs->rx; + + if (qmp->cfg->lanes >= 2) { + qmp->tx2 = (void __iomem *)res.start + offs->tx2; + qmp->rx2 = (void __iomem *)res.start + offs->rx2; + } + + if (cfg->tbls.ln_shrd) + qmp->ln_shrd = (void __iomem *)res.start + offs->ln_shrd; + + return 0; +} + +static int qmp_pcie_probe(struct udevice *dev) +{ + struct qmp_pcie_priv *qmp = dev_get_priv(dev); + int ret; + + qmp->serdes = (void __iomem *)dev_read_addr(dev); + if (IS_ERR(qmp->serdes)) + return PTR_ERR(qmp->serdes); + + qmp->cfg = (const struct qmp_pcie_cfg *)dev_get_driver_data(dev); + if (!qmp->cfg) + return -EINVAL; + + ret = qmp_pcie_clk_init(dev, qmp); + if (ret) { + dev_err(dev, "failed to get PCIE clks\n"); + return ret; + } + + ret = qmp_pcie_vreg_init(dev, qmp); + if (ret) { + dev_err(dev, "failed to get PCIE voltage regulators\n"); + return ret; + } + + ret = qmp_pcie_reset_init(dev, qmp); + if (ret) { + dev_err(dev, "failed to get PCIE resets\n"); + return ret; + } + + qmp->dev = dev; + + return qmp_pcie_parse_dt(dev, qmp); +} + +static struct phy_ops qmp_pcie_ops = { + .power_on = qmp_pcie_power_on, + .power_off = qmp_pcie_power_off, +}; + +static const struct udevice_id qmp_pcie_ids[] = { + { + .compatible = "qcom,sm8550-qmp-gen3x2-pcie-phy", + .data = (ulong)&sm8550_qmp_gen3x2_pciephy_cfg, + }, { + .compatible = "qcom,sm8550-qmp-gen4x2-pcie-phy", + .data = (ulong)&sm8550_qmp_gen4x2_pciephy_cfg + }, { + .compatible = "qcom,sm8650-qmp-gen3x2-pcie-phy", + .data = (ulong)&sm8550_qmp_gen3x2_pciephy_cfg, + }, { + .compatible = "qcom,sm8650-qmp-gen4x2-pcie-phy", + .data = (ulong)&sm8650_qmp_gen4x2_pciephy_cfg + }, { + .compatible = "qcom,x1e80100-qmp-gen3x2-pcie-phy", + .data = (ulong)&sm8550_qmp_gen3x2_pciephy_cfg + }, { + .compatible = "qcom,x1e80100-qmp-gen4x2-pcie-phy", + .data = (ulong)&x1e80100_qmp_gen4x2_pciephy_cfg + }, { + .compatible = "qcom,x1e80100-qmp-gen4x4-pcie-phy", + .data = (ulong)&x1e80100_qmp_gen4x2_pciephy_cfg + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(qcom_qmp_pcie) = { + .name = "qcom-qmp-pcie", + .id = UCLASS_PHY, + .of_match = qmp_pcie_ids, + .ops = &qmp_pcie_ops, + .probe = qmp_pcie_probe, + .priv_auto = sizeof(struct qmp_pcie_priv), +}; diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-misc-v3.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-misc-v3.h new file mode 100644 index 00000000000..a45bd301bc9 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-misc-v3.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_PCS_MISC_V3_H_ +#define QCOM_PHY_QMP_PCS_MISC_V3_H_ + +/* Only for QMP V3 PHY - PCS_MISC registers */ +#define QPHY_V3_PCS_MISC_CLAMP_ENABLE 0x0c +#define QPHY_V3_PCS_MISC_OSC_DTCT_CONFIG2 0x2c +#define QPHY_V3_PCS_MISC_PCIE_INT_AUX_CLK_CONFIG1 0x44 +#define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG2 0x54 +#define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG4 0x5c +#define QPHY_V3_PCS_MISC_OSC_DTCT_MODE2_CONFIG5 0x60 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v4.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v4.h new file mode 100644 index 00000000000..4cc02288d41 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v4.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_PCS_PCIE_V4_H_ +#define QCOM_PHY_QMP_PCS_PCIE_V4_H_ + +/* Only for QMP V4 PHY - PCS_PCIE registers (same as PCS_MISC?) */ +#define QPHY_V4_PCS_PCIE_INT_AUX_CLK_STATUS 0x00 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_STATUS 0x04 +#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG1 0x08 +#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG2 0x0c +#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG3 0x10 +#define QPHY_V4_PCS_PCIE_POWER_STATE_CONFIG4 0x14 +#define QPHY_V4_PCS_PCIE_PCS_TX_RX_CONFIG 0x18 +#define QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x1c +#define QPHY_V4_PCS_PCIE_ENDPOINT_REFCLK_CNTRL 0x20 +#define QPHY_V4_PCS_PCIE_EPCLK_PRE_PLL_LOCK_DLY_AUXCLK 0x24 +#define QPHY_V4_PCS_PCIE_EPCLK_DLY_COUNT_VAL_L 0x28 +#define QPHY_V4_PCS_PCIE_EPCLK_DLY_COUNT_VAL_H 0x2c +#define QPHY_V4_PCS_PCIE_RX_IDLE_DTCT_CNTRL1 0x30 +#define QPHY_V4_PCS_PCIE_RX_IDLE_DTCT_CNTRL2 0x34 +#define QPHY_V4_PCS_PCIE_SIGDET_CNTRL 0x38 +#define QPHY_V4_PCS_PCIE_SIGDET_LOW_2_IDLE_TIME 0x3c +#define QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_L 0x40 +#define QPHY_V4_PCS_PCIE_L1P1_WAKEUP_DLY_TIME_AUXCLK_H 0x44 +#define QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_L 0x48 +#define QPHY_V4_PCS_PCIE_L1P2_WAKEUP_DLY_TIME_AUXCLK_H 0x4c +#define QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x50 +#define QPHY_V4_PCS_PCIE_INT_AUX_CLK_CONFIG2 0x54 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG1 0x58 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG2 0x5c +#define QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG3 0x60 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG4 0x64 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG5 0x68 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG6 0x6c +#define QPHY_V4_PCS_PCIE_OSC_DTCT_CONFIG7 0x70 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG1 0x74 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG2 0x78 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG3 0x7c +#define QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG4 0x80 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x84 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG6 0x88 +#define QPHY_V4_PCS_PCIE_OSC_DTCT_MODE2_CONFIG7 0x8c +#define QPHY_V4_PCS_PCIE_OSC_DTCT_ACTIONS 0x90 +#define QPHY_V4_PCS_PCIE_LOCAL_FS 0x94 +#define QPHY_V4_PCS_PCIE_LOCAL_LF 0x98 +#define QPHY_V4_PCS_PCIE_LOCAL_FS_RS 0x9c +#define QPHY_V4_PCS_PCIE_EQ_CONFIG1 0xa0 +#define QPHY_V4_PCS_PCIE_EQ_CONFIG2 0xa4 +#define QPHY_V4_PCS_PCIE_PRESET_P0_P1_PRE 0xa8 +#define QPHY_V4_PCS_PCIE_PRESET_P2_P3_PRE 0xac +#define QPHY_V4_PCS_PCIE_PRESET_P4_P5_PRE 0xb0 +#define QPHY_V4_PCS_PCIE_PRESET_P6_P7_PRE 0xb4 +#define QPHY_V4_PCS_PCIE_PRESET_P8_P9_PRE 0xb8 +#define QPHY_V4_PCS_PCIE_PRESET_P10_PRE 0xbc +#define QPHY_V4_PCS_PCIE_PRESET_P1_P3_PRE_RS 0xc0 +#define QPHY_V4_PCS_PCIE_PRESET_P4_P5_PRE_RS 0xc4 +#define QPHY_V4_PCS_PCIE_PRESET_P6_P9_PRE_RS 0xc8 +#define QPHY_V4_PCS_PCIE_PRESET_P0_P1_POST 0xcc +#define QPHY_V4_PCS_PCIE_PRESET_P2_P3_POST 0xd0 +#define QPHY_V4_PCS_PCIE_PRESET_P4_P5_POST 0xd4 +#define QPHY_V4_PCS_PCIE_PRESET_P6_P7_POST 0xd8 +#define QPHY_V4_PCS_PCIE_PRESET_P8_P9_POST 0xdc +#define QPHY_V4_PCS_PCIE_PRESET_P10_POST 0xe0 +#define QPHY_V4_PCS_PCIE_PRESET_P1_P3_POST_RS 0xe4 +#define QPHY_V4_PCS_PCIE_PRESET_P4_P5_POST_RS 0xe8 +#define QPHY_V4_PCS_PCIE_PRESET_P6_P9_POST_RS 0xec +#define QPHY_V4_PCS_PCIE_RXEQEVAL_TIME 0xf0 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v4_20.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v4_20.h new file mode 100644 index 00000000000..ac872a9eff9 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v4_20.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_PCS_PCIE_V4_20_H_ +#define QCOM_PHY_QMP_PCS_PCIE_V4_20_H_ + +#define QPHY_V4_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x01c +#define QPHY_V4_20_PCS_PCIE_OSC_DTCT_ACTIONS 0x090 +#define QPHY_V4_20_PCS_PCIE_EQ_CONFIG1 0x0a0 +#define QPHY_V4_20_PCS_PCIE_G3_RXEQEVAL_TIME 0x0f0 +#define QPHY_V4_20_PCS_PCIE_G4_RXEQEVAL_TIME 0x0f4 +#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG2 0x0fc +#define QPHY_V4_20_PCS_PCIE_G4_EQ_CONFIG5 0x108 +#define QPHY_V4_20_PCS_LANE1_INSIG_SW_CTRL2 0x824 +#define QPHY_V4_20_PCS_LANE1_INSIG_MX_CTRL2 0x828 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v5.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v5.h new file mode 100644 index 00000000000..2801bcf10f2 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v5.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_PCS_PCIE_V5_H_ +#define QCOM_PHY_QMP_PCS_PCIE_V5_H_ + +/* Only for QMP V5 PHY - PCS_PCIE registers */ +#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG2 0x0c +#define QPHY_V5_PCS_PCIE_POWER_STATE_CONFIG4 0x14 +#define QPHY_V5_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x20 +#define QPHY_V5_PCS_PCIE_INT_AUX_CLK_CONFIG1 0x54 +#define QPHY_V5_PCS_PCIE_OSC_DTCT_ACTIONS 0x94 +#define QPHY_V5_PCS_PCIE_EQ_CONFIG2 0xa8 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v5_20.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v5_20.h new file mode 100644 index 00000000000..cdf8c04ea07 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v5_20.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_PCS_PCIE_V5_20_H_ +#define QCOM_PHY_QMP_PCS_PCIE_V5_20_H_ + +/* Only for QMP V5_20 PHY - PCIe PCS registers */ +#define QPHY_V5_20_PCS_PCIE_POWER_STATE_CONFIG2 0x00c +#define QPHY_V5_20_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x01c +#define QPHY_V5_20_PCS_PCIE_OSC_DTCT_MODE2_CONFIG5 0x084 +#define QPHY_V5_20_PCS_PCIE_OSC_DTCT_ACTIONS 0x090 +#define QPHY_V5_20_PCS_PCIE_EQ_CONFIG1 0x0a0 +#define QPHY_V5_20_PCS_PCIE_PRESET_P10_POST 0x0e0 +#define QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG2 0x0fc +#define QPHY_V5_20_PCS_PCIE_G4_EQ_CONFIG5 0x108 +#define QPHY_V5_20_PCS_PCIE_G4_PRE_GAIN 0x15c +#define QPHY_V5_20_PCS_PCIE_RX_MARGINING_CONFIG3 0x184 +#define QPHY_V5_20_PCS_LANE1_INSIG_SW_CTRL2 0xa24 +#define QPHY_V5_20_PCS_LANE1_INSIG_MX_CTRL2 0xa28 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v6.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v6.h new file mode 100644 index 00000000000..0ca79333d94 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v6.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef QCOM_PHY_QMP_PCS_PCIE_V6_H_ +#define QCOM_PHY_QMP_PCS_PCIE_V6_H_ + +/* Only for QMP V6 PHY - PCIE have different offsets than V5 */ +#define QPHY_PCIE_V6_PCS_PCIE_EQ_CONFIG1 0xa4 +#define QPHY_PCIE_V6_PCS_PCIE_RXEQEVAL_TIME 0xf4 +#define QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG2 0x0c +#define QPHY_PCIE_V6_PCS_PCIE_POWER_STATE_CONFIG4 0x14 +#define QPHY_PCIE_V6_PCS_PCIE_ENDPOINT_REFCLK_DRIVE 0x20 +#define QPHY_PCIE_V6_PCS_PCIE_OSC_DTCT_ACTIONS 0x94 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v6_20.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v6_20.h new file mode 100644 index 00000000000..dfcecf31a60 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-pcie-v6_20.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef QCOM_PHY_QMP_PCS_PCIE_V6_20_H_ +#define QCOM_PHY_QMP_PCS_PCIE_V6_20_H_ + +/* Only for QMP V6_20 PHY - PCIE have different offsets than V5 */ +#define QPHY_PCIE_V6_20_PCS_POWER_STATE_CONFIG2 0x00c +#define QPHY_PCIE_V6_20_PCS_TX_RX_CONFIG 0x018 +#define QPHY_PCIE_V6_20_PCS_ENDPOINT_REFCLK_DRIVE 0x01c +#define QPHY_PCIE_V6_20_PCS_OSC_DTCT_ATCIONS 0x090 +#define QPHY_PCIE_V6_20_PCS_EQ_CONFIG1 0x0a0 +#define QPHY_PCIE_V6_20_PCS_G3_RXEQEVAL_TIME 0x0f0 +#define QPHY_PCIE_V6_20_PCS_G4_RXEQEVAL_TIME 0x0f4 +#define QPHY_PCIE_V6_20_PCS_EQ_CONFIG5 0x108 +#define QPHY_PCIE_V6_20_PCS_G4_PRE_GAIN 0x15c +#define QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG1 0x17c +#define QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG3 0x184 +#define QPHY_PCIE_V6_20_PCS_RX_MARGINING_CONFIG5 0x18c +#define QPHY_PCIE_V6_20_PCS_G3_FOM_EQ_CONFIG5 0x1ac +#define QPHY_PCIE_V6_20_PCS_G4_FOM_EQ_CONFIG5 0x1c0 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-v5.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-v5.h new file mode 100644 index 00000000000..36cc80bb905 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-v5.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_PCS_V5_H_ +#define QCOM_PHY_QMP_PCS_V5_H_ + +/* Only for QMP V5 PHY - USB/PCIe PCS registers */ +#define QPHY_V5_PCS_SW_RESET 0x000 +#define QPHY_V5_PCS_PCS_STATUS1 0x014 +#define QPHY_V5_PCS_POWER_DOWN_CONTROL 0x040 +#define QPHY_V5_PCS_START_CONTROL 0x044 +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG1 0x0c4 +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG2 0x0c8 +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG3 0x0cc +#define QPHY_V5_PCS_LOCK_DETECT_CONFIG6 0x0d8 +#define QPHY_V5_PCS_REFGEN_REQ_CONFIG1 0x0dc +#define QPHY_V5_PCS_G3S2_PRE_GAIN 0x170 +#define QPHY_V5_PCS_RX_SIGDET_LVL 0x188 +#define QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_L 0x190 +#define QPHY_V5_PCS_RCVR_DTCT_DLY_P1U2_H 0x194 +#define QPHY_V5_PCS_RATE_SLEW_CNTRL1 0x198 +#define QPHY_V5_PCS_CDR_RESET_TIME 0x1b0 +#define QPHY_V5_PCS_RX_CONFIG 0x1b0 +#define QPHY_V5_PCS_ALIGN_DETECT_CONFIG1 0x1c0 +#define QPHY_V5_PCS_ALIGN_DETECT_CONFIG2 0x1c4 +#define QPHY_V5_PCS_PCS_TX_RX_CONFIG 0x1d0 +#define QPHY_V5_PCS_EQ_CONFIG1 0x1dc +#define QPHY_V5_PCS_EQ_CONFIG2 0x1e0 +#define QPHY_V5_PCS_EQ_CONFIG3 0x1e4 +#define QPHY_V5_PCS_EQ_CONFIG5 0x1ec + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-v6.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-v6.h new file mode 100644 index 00000000000..08299d2b78f --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-v6.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef QCOM_PHY_QMP_PCS_V6_H_ +#define QCOM_PHY_QMP_PCS_V6_H_ + +/* Only for QMP V6 PHY - USB/PCIe PCS registers */ +#define QPHY_V6_PCS_SW_RESET 0x000 +#define QPHY_V6_PCS_PCS_STATUS1 0x014 +#define QPHY_V6_PCS_POWER_DOWN_CONTROL 0x040 +#define QPHY_V6_PCS_START_CONTROL 0x044 +#define QPHY_V6_PCS_POWER_STATE_CONFIG1 0x090 +#define QPHY_V6_PCS_LOCK_DETECT_CONFIG1 0x0c4 +#define QPHY_V6_PCS_LOCK_DETECT_CONFIG2 0x0c8 +#define QPHY_V6_PCS_LOCK_DETECT_CONFIG3 0x0cc +#define QPHY_V6_PCS_LOCK_DETECT_CONFIG6 0x0d8 +#define QPHY_V6_PCS_REFGEN_REQ_CONFIG1 0x0dc +#define QPHY_V6_PCS_RX_SIGDET_LVL 0x188 +#define QPHY_V6_PCS_RCVR_DTCT_DLY_P1U2_L 0x190 +#define QPHY_V6_PCS_RCVR_DTCT_DLY_P1U2_H 0x194 +#define QPHY_V6_PCS_RATE_SLEW_CNTRL1 0x198 +#define QPHY_V6_PCS_CDR_RESET_TIME 0x1b0 +#define QPHY_V6_PCS_ALIGN_DETECT_CONFIG1 0x1c0 +#define QPHY_V6_PCS_ALIGN_DETECT_CONFIG2 0x1c4 +#define QPHY_V6_PCS_PCS_TX_RX_CONFIG 0x1d0 +#define QPHY_V6_PCS_EQ_CONFIG1 0x1dc +#define QPHY_V6_PCS_EQ_CONFIG2 0x1e0 +#define QPHY_V6_PCS_EQ_CONFIG5 0x1ec + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-pcs-v6_20.h b/drivers/phy/qcom/phy-qcom-qmp-pcs-v6_20.h new file mode 100644 index 00000000000..4d9615cc038 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-pcs-v6_20.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef QCOM_PHY_QMP_PCS_V6_20_H_ +#define QCOM_PHY_QMP_PCS_V6_20_H_ + +/* Only for QMP V6_20 PHY - USB/PCIe PCS registers */ +#define QPHY_V6_20_PCS_G12S1_TXDEEMPH_M6DB 0x170 +#define QPHY_V6_20_PCS_G3S2_PRE_GAIN 0x178 +#define QPHY_V6_20_PCS_RX_SIGDET_LVL 0x190 +#define QPHY_V6_20_PCS_COM_ELECIDLE_DLY_SEL 0x1b8 +#define QPHY_V6_20_PCS_TX_RX_CONFIG1 0x1dc +#define QPHY_V6_20_PCS_TX_RX_CONFIG2 0x1e0 +#define QPHY_V6_20_PCS_EQ_CONFIG4 0x1f8 +#define QPHY_V6_20_PCS_EQ_CONFIG5 0x1fc + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v5.h b/drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v5.h new file mode 100644 index 00000000000..c8afdf7bc1e --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-qserdes-com-v5.h @@ -0,0 +1,124 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_QSERDES_COM_V5_H_ +#define QCOM_PHY_QMP_QSERDES_COM_V5_H_ + +/* Only for QMP V5 PHY - QSERDES COM registers */ +#define QSERDES_V5_COM_ATB_SEL1 0x000 +#define QSERDES_V5_COM_ATB_SEL2 0x004 +#define QSERDES_V5_COM_FREQ_UPDATE 0x008 +#define QSERDES_V5_COM_BG_TIMER 0x00c +#define QSERDES_V5_COM_SSC_EN_CENTER 0x010 +#define QSERDES_V5_COM_SSC_ADJ_PER1 0x014 +#define QSERDES_V5_COM_SSC_ADJ_PER2 0x018 +#define QSERDES_V5_COM_SSC_PER1 0x01c +#define QSERDES_V5_COM_SSC_PER2 0x020 +#define QSERDES_V5_COM_SSC_STEP_SIZE1_MODE0 0x024 +#define QSERDES_V5_COM_SSC_STEP_SIZE2_MODE0 0x028 +#define QSERDES_V5_COM_SSC_STEP_SIZE3_MODE0 0x02c +#define QSERDES_V5_COM_SSC_STEP_SIZE1_MODE1 0x030 +#define QSERDES_V5_COM_SSC_STEP_SIZE2_MODE1 0x034 +#define QSERDES_V5_COM_SSC_STEP_SIZE3_MODE1 0x038 +#define QSERDES_V5_COM_POST_DIV 0x03c +#define QSERDES_V5_COM_POST_DIV_MUX 0x040 +#define QSERDES_V5_COM_BIAS_EN_CLKBUFLR_EN 0x044 +#define QSERDES_V5_COM_CLK_ENABLE1 0x048 +#define QSERDES_V5_COM_SYS_CLK_CTRL 0x04c +#define QSERDES_V5_COM_SYSCLK_BUF_ENABLE 0x050 +#define QSERDES_V5_COM_PLL_EN 0x054 +#define QSERDES_V5_COM_PLL_IVCO 0x058 +#define QSERDES_V5_COM_CMN_IETRIM 0x05c +#define QSERDES_V5_COM_CMN_IPTRIM 0x060 +#define QSERDES_V5_COM_EP_CLOCK_DETECT_CTRL 0x064 +#define QSERDES_V5_COM_SYSCLK_DET_COMP_STATUS 0x068 +#define QSERDES_V5_COM_CLK_EP_DIV_MODE0 0x06c +#define QSERDES_V5_COM_CLK_EP_DIV_MODE1 0x070 +#define QSERDES_V5_COM_CP_CTRL_MODE0 0x074 +#define QSERDES_V5_COM_CP_CTRL_MODE1 0x078 +#define QSERDES_V5_COM_PLL_RCTRL_MODE0 0x07c +#define QSERDES_V5_COM_PLL_RCTRL_MODE1 0x080 +#define QSERDES_V5_COM_PLL_CCTRL_MODE0 0x084 +#define QSERDES_V5_COM_PLL_CCTRL_MODE1 0x088 +#define QSERDES_V5_COM_PLL_CNTRL 0x08c +#define QSERDES_V5_COM_BIAS_EN_CTRL_BY_PSM 0x090 +#define QSERDES_V5_COM_SYSCLK_EN_SEL 0x094 +#define QSERDES_V5_COM_CML_SYSCLK_SEL 0x098 +#define QSERDES_V5_COM_RESETSM_CNTRL 0x09c +#define QSERDES_V5_COM_RESETSM_CNTRL2 0x0a0 +#define QSERDES_V5_COM_LOCK_CMP_EN 0x0a4 +#define QSERDES_V5_COM_LOCK_CMP_CFG 0x0a8 +#define QSERDES_V5_COM_LOCK_CMP1_MODE0 0x0ac +#define QSERDES_V5_COM_LOCK_CMP2_MODE0 0x0b0 +#define QSERDES_V5_COM_LOCK_CMP1_MODE1 0x0b4 +#define QSERDES_V5_COM_LOCK_CMP2_MODE1 0x0b8 +#define QSERDES_V5_COM_DEC_START_MODE0 0x0bc +#define QSERDES_V5_COM_DEC_START_MSB_MODE0 0x0c0 +#define QSERDES_V5_COM_DEC_START_MODE1 0x0c4 +#define QSERDES_V5_COM_DEC_START_MSB_MODE1 0x0c8 +#define QSERDES_V5_COM_DIV_FRAC_START1_MODE0 0x0cc +#define QSERDES_V5_COM_DIV_FRAC_START2_MODE0 0x0d0 +#define QSERDES_V5_COM_DIV_FRAC_START3_MODE0 0x0d4 +#define QSERDES_V5_COM_DIV_FRAC_START1_MODE1 0x0d8 +#define QSERDES_V5_COM_DIV_FRAC_START2_MODE1 0x0dc +#define QSERDES_V5_COM_DIV_FRAC_START3_MODE1 0x0e0 +#define QSERDES_V5_COM_INTEGLOOP_INITVAL 0x0e4 +#define QSERDES_V5_COM_INTEGLOOP_EN 0x0e8 +#define QSERDES_V5_COM_INTEGLOOP_GAIN0_MODE0 0x0ec +#define QSERDES_V5_COM_INTEGLOOP_GAIN1_MODE0 0x0f0 +#define QSERDES_V5_COM_INTEGLOOP_GAIN0_MODE1 0x0f4 +#define QSERDES_V5_COM_INTEGLOOP_GAIN1_MODE1 0x0f8 +#define QSERDES_V5_COM_INTEGLOOP_P_PATH_GAIN0 0x0fc +#define QSERDES_V5_COM_INTEGLOOP_P_PATH_GAIN1 0x100 +#define QSERDES_V5_COM_VCOCAL_DEADMAN_CTRL 0x104 +#define QSERDES_V5_COM_VCO_TUNE_CTRL 0x108 +#define QSERDES_V5_COM_VCO_TUNE_MAP 0x10c +#define QSERDES_V5_COM_VCO_TUNE1_MODE0 0x110 +#define QSERDES_V5_COM_VCO_TUNE2_MODE0 0x114 +#define QSERDES_V5_COM_VCO_TUNE1_MODE1 0x118 +#define QSERDES_V5_COM_VCO_TUNE2_MODE1 0x11c +#define QSERDES_V5_COM_VCO_TUNE_INITVAL1 0x120 +#define QSERDES_V5_COM_VCO_TUNE_INITVAL2 0x124 +#define QSERDES_V5_COM_VCO_TUNE_MINVAL1 0x128 +#define QSERDES_V5_COM_VCO_TUNE_MINVAL2 0x12c +#define QSERDES_V5_COM_VCO_TUNE_MAXVAL1 0x130 +#define QSERDES_V5_COM_VCO_TUNE_MAXVAL2 0x134 +#define QSERDES_V5_COM_VCO_TUNE_TIMER1 0x138 +#define QSERDES_V5_COM_VCO_TUNE_TIMER2 0x13c +#define QSERDES_V5_COM_CMN_STATUS 0x140 +#define QSERDES_V5_COM_RESET_SM_STATUS 0x144 +#define QSERDES_V5_COM_RESTRIM_CODE_STATUS 0x148 +#define QSERDES_V5_COM_PLLCAL_CODE1_STATUS 0x14c +#define QSERDES_V5_COM_PLLCAL_CODE2_STATUS 0x150 +#define QSERDES_V5_COM_CLK_SELECT 0x154 +#define QSERDES_V5_COM_HSCLK_SEL 0x158 +#define QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL 0x15c +#define QSERDES_V5_COM_INTEGLOOP_BINCODE_STATUS 0x160 +#define QSERDES_V5_COM_PLL_ANALOG 0x164 +#define QSERDES_V5_COM_CORECLK_DIV_MODE0 0x168 +#define QSERDES_V5_COM_CORECLK_DIV_MODE1 0x16c +#define QSERDES_V5_COM_SW_RESET 0x170 +#define QSERDES_V5_COM_CORE_CLK_EN 0x174 +#define QSERDES_V5_COM_C_READY_STATUS 0x178 +#define QSERDES_V5_COM_CMN_CONFIG 0x17c +#define QSERDES_V5_COM_CMN_RATE_OVERRIDE 0x180 +#define QSERDES_V5_COM_SVS_MODE_CLK_SEL 0x184 +#define QSERDES_V5_COM_DEBUG_BUS0 0x188 +#define QSERDES_V5_COM_DEBUG_BUS1 0x18c +#define QSERDES_V5_COM_DEBUG_BUS2 0x190 +#define QSERDES_V5_COM_DEBUG_BUS3 0x194 +#define QSERDES_V5_COM_DEBUG_BUS_SEL 0x198 +#define QSERDES_V5_COM_CMN_MISC1 0x19c +#define QSERDES_V5_COM_CMN_MODE 0x1a0 +#define QSERDES_V5_COM_CMN_MODE_CONTD 0x1a4 +#define QSERDES_V5_COM_VCO_DC_LEVEL_CTRL 0x1a8 +#define QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0 0x1ac +#define QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0 0x1b0 +#define QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1 0x1b4 +#define QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1 0x1b8 +#define QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL 0x1bc +#define QSERDES_V5_COM_RESERVED_1 0x1c0 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-qserdes-ln-shrd-v6.h b/drivers/phy/qcom/phy-qcom-qmp-qserdes-ln-shrd-v6.h new file mode 100644 index 00000000000..86d7d796d5d --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-qserdes-ln-shrd-v6.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef QCOM_PHY_QMP_QSERDES_LN_SHRD_V6_H_ +#define QCOM_PHY_QMP_QSERDES_LN_SHRD_V6_H_ + +#define QSERDES_V6_LN_SHRD_RXCLK_DIV2_CTRL 0xa0 +#define QSERDES_V6_LN_SHRD_RX_Q_EN_RATES 0xb0 +#define QSERDES_V6_LN_SHRD_DFE_DAC_ENABLE1 0xb4 +#define QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH1 0xc4 +#define QSERDES_V6_LN_SHRD_TX_ADAPT_POST_THRESH2 0xc8 +#define QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B0 0xd4 +#define QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B1 0xd8 +#define QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B2 0xdc +#define QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B3 0xe0 +#define QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B4 0xe4 +#define QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B5 0xe8 +#define QSERDES_V6_LN_SHRD_RX_MODE_RATE_0_1_B6 0xec +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE210 0xf0 +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH1_RATE3 0xf4 +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE210 0xf8 +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH2_RATE3 0xfc +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE210 0x100 +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH3_RATE3 0x104 +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH4_RATE3 0x10c +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH5_RATE3 0x114 +#define QSERDES_V6_LN_SHRD_RX_MARG_COARSE_THRESH6_RATE3 0x11c +#define QSERDES_V6_LN_SHRD_RX_SUMMER_CAL_SPD_MODE 0x128 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v5.h b/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v5.h new file mode 100644 index 00000000000..fe8f3e330d0 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v5.h @@ -0,0 +1,231 @@ + +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + */ + +#ifndef QCOM_PHY_QMP_QSERDES_TXRX_V5_H_ +#define QCOM_PHY_QMP_QSERDES_TXRX_V5_H_ + +/* Only for QMP V5 PHY - TX registers */ +#define QSERDES_V5_TX_BIST_MODE_LANENO 0x000 +#define QSERDES_V5_TX_BIST_INVERT 0x004 +#define QSERDES_V5_TX_CLKBUF_ENABLE 0x008 +#define QSERDES_V5_TX_TX_EMP_POST1_LVL 0x00c +#define QSERDES_V5_TX_TX_IDLE_LVL_LARGE_AMP 0x010 +#define QSERDES_V5_TX_TX_DRV_LVL 0x014 +#define QSERDES_V5_TX_TX_DRV_LVL_OFFSET 0x018 +#define QSERDES_V5_TX_RESET_TSYNC_EN 0x01c +#define QSERDES_V5_TX_PRE_STALL_LDO_BOOST_EN 0x020 +#define QSERDES_V5_TX_TX_BAND 0x024 +#define QSERDES_V5_TX_SLEW_CNTL 0x028 +#define QSERDES_V5_TX_INTERFACE_SELECT 0x02c +#define QSERDES_V5_TX_LPB_EN 0x030 +#define QSERDES_V5_TX_RES_CODE_LANE_TX 0x034 +#define QSERDES_V5_TX_RES_CODE_LANE_RX 0x038 +#define QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX 0x03c +#define QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX 0x040 +#define QSERDES_V5_TX_PERL_LENGTH1 0x044 +#define QSERDES_V5_TX_PERL_LENGTH2 0x048 +#define QSERDES_V5_TX_SERDES_BYP_EN_OUT 0x04c +#define QSERDES_V5_TX_DEBUG_BUS_SEL 0x050 +#define QSERDES_V5_TX_TRANSCEIVER_BIAS_EN 0x054 +#define QSERDES_V5_TX_HIGHZ_DRVR_EN 0x058 +#define QSERDES_V5_TX_TX_POL_INV 0x05c +#define QSERDES_V5_TX_PARRATE_REC_DETECT_IDLE_EN 0x060 +#define QSERDES_V5_TX_BIST_PATTERN1 0x064 +#define QSERDES_V5_TX_BIST_PATTERN2 0x068 +#define QSERDES_V5_TX_BIST_PATTERN3 0x06c +#define QSERDES_V5_TX_BIST_PATTERN4 0x070 +#define QSERDES_V5_TX_BIST_PATTERN5 0x074 +#define QSERDES_V5_TX_BIST_PATTERN6 0x078 +#define QSERDES_V5_TX_BIST_PATTERN7 0x07c +#define QSERDES_V5_TX_BIST_PATTERN8 0x080 +#define QSERDES_V5_TX_LANE_MODE_1 0x084 +#define QSERDES_V5_TX_LANE_MODE_2 0x088 +#define QSERDES_V5_TX_LANE_MODE_3 0x08c +#define QSERDES_V5_TX_LANE_MODE_4 0x090 +#define QSERDES_V5_TX_LANE_MODE_5 0x094 +#define QSERDES_V5_TX_ATB_SEL1 0x098 +#define QSERDES_V5_TX_ATB_SEL2 0x09c +#define QSERDES_V5_TX_RCV_DETECT_LVL 0x0a0 +#define QSERDES_V5_TX_RCV_DETECT_LVL_2 0x0a4 +#define QSERDES_V5_TX_PRBS_SEED1 0x0a8 +#define QSERDES_V5_TX_PRBS_SEED2 0x0ac +#define QSERDES_V5_TX_PRBS_SEED3 0x0b0 +#define QSERDES_V5_TX_PRBS_SEED4 0x0b4 +#define QSERDES_V5_TX_RESET_GEN 0x0b8 +#define QSERDES_V5_TX_RESET_GEN_MUXES 0x0bc +#define QSERDES_V5_TX_TRAN_DRVR_EMP_EN 0x0c0 +#define QSERDES_V5_TX_TX_INTERFACE_MODE 0x0c4 +#define QSERDES_V5_TX_VMODE_CTRL1 0x0c8 +#define QSERDES_V5_TX_ALOG_OBSV_BUS_CTRL_1 0x0cc +#define QSERDES_V5_TX_BIST_STATUS 0x0d0 +#define QSERDES_V5_TX_BIST_ERROR_COUNT1 0x0d4 +#define QSERDES_V5_TX_BIST_ERROR_COUNT2 0x0d8 +#define QSERDES_V5_TX_ALOG_OBSV_BUS_STATUS_1 0x0dc +#define QSERDES_V5_TX_LANE_DIG_CONFIG 0x0e0 +#define QSERDES_V5_TX_PI_QEC_CTRL 0x0e4 +#define QSERDES_V5_TX_PRE_EMPH 0x0e8 +#define QSERDES_V5_TX_SW_RESET 0x0ec +#define QSERDES_V5_TX_DCC_OFFSET 0x0f0 +#define QSERDES_V5_TX_DCC_CMUX_POSTCAL_OFFSET 0x0f4 +#define QSERDES_V5_TX_DCC_CMUX_CAL_CTRL1 0x0f8 +#define QSERDES_V5_TX_DCC_CMUX_CAL_CTRL2 0x0fc +#define QSERDES_V5_TX_DIG_BKUP_CTRL 0x100 +#define QSERDES_V5_TX_DEBUG_BUS0 0x104 +#define QSERDES_V5_TX_DEBUG_BUS1 0x108 +#define QSERDES_V5_TX_DEBUG_BUS2 0x10c +#define QSERDES_V5_TX_DEBUG_BUS3 0x110 +#define QSERDES_V5_TX_READ_EQCODE 0x114 +#define QSERDES_V5_TX_READ_OFFSETCODE 0x118 +#define QSERDES_V5_TX_IA_ERROR_COUNTER_LOW 0x11c +#define QSERDES_V5_TX_IA_ERROR_COUNTER_HIGH 0x120 +#define QSERDES_V5_TX_VGA_READ_CODE 0x124 +#define QSERDES_V5_TX_VTH_READ_CODE 0x128 +#define QSERDES_V5_TX_DFE_TAP1_READ_CODE 0x12c +#define QSERDES_V5_TX_DFE_TAP2_READ_CODE 0x130 +#define QSERDES_V5_TX_IDAC_STATUS_I 0x134 +#define QSERDES_V5_TX_IDAC_STATUS_IBAR 0x138 +#define QSERDES_V5_TX_IDAC_STATUS_Q 0x13c +#define QSERDES_V5_TX_IDAC_STATUS_QBAR 0x140 +#define QSERDES_V5_TX_IDAC_STATUS_A 0x144 +#define QSERDES_V5_TX_IDAC_STATUS_ABAR 0x148 +#define QSERDES_V5_TX_IDAC_STATUS_SM_ON 0x14c +#define QSERDES_V5_TX_IDAC_STATUS_CAL_DONE 0x150 +#define QSERDES_V5_TX_IDAC_STATUS_SIGNERROR 0x154 +#define QSERDES_V5_TX_DCC_CAL_STATUS 0x158 +#define QSERDES_V5_TX_DCC_READ_CODE_STATUS 0x15c + +/* Only for QMP V5 PHY - RX registers */ +#define QSERDES_V5_RX_UCDR_FO_GAIN_HALF 0x000 +#define QSERDES_V5_RX_UCDR_FO_GAIN_QUARTER 0x004 +#define QSERDES_V5_RX_UCDR_FO_GAIN 0x008 +#define QSERDES_V5_RX_UCDR_SO_GAIN_HALF 0x00c +#define QSERDES_V5_RX_UCDR_SO_GAIN_QUARTER 0x010 +#define QSERDES_V5_RX_UCDR_SO_GAIN 0x014 +#define QSERDES_V5_RX_UCDR_SVS_FO_GAIN_HALF 0x018 +#define QSERDES_V5_RX_UCDR_SVS_FO_GAIN_QUARTER 0x01c +#define QSERDES_V5_RX_UCDR_SVS_FO_GAIN 0x020 +#define QSERDES_V5_RX_UCDR_SVS_SO_GAIN_HALF 0x024 +#define QSERDES_V5_RX_UCDR_SVS_SO_GAIN_QUARTER 0x028 +#define QSERDES_V5_RX_UCDR_SVS_SO_GAIN 0x02c +#define QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN 0x030 +#define QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE 0x034 +#define QSERDES_V5_RX_UCDR_FO_TO_SO_DELAY 0x038 +#define QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW 0x03c +#define QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH 0x040 +#define QSERDES_V5_RX_UCDR_PI_CONTROLS 0x044 +#define QSERDES_V5_RX_UCDR_PI_CTRL2 0x048 +#define QSERDES_V5_RX_UCDR_SB2_THRESH1 0x04c +#define QSERDES_V5_RX_UCDR_SB2_THRESH2 0x050 +#define QSERDES_V5_RX_UCDR_SB2_GAIN1 0x054 +#define QSERDES_V5_RX_UCDR_SB2_GAIN2 0x058 +#define QSERDES_V5_RX_AUX_CONTROL 0x05c +#define QSERDES_V5_RX_AUX_DATA_TCOARSE_TFINE 0x060 +#define QSERDES_V5_RX_RCLK_AUXDATA_SEL 0x064 +#define QSERDES_V5_RX_AC_JTAG_ENABLE 0x068 +#define QSERDES_V5_RX_AC_JTAG_INITP 0x06c +#define QSERDES_V5_RX_AC_JTAG_INITN 0x070 +#define QSERDES_V5_RX_AC_JTAG_LVL 0x074 +#define QSERDES_V5_RX_AC_JTAG_MODE 0x078 +#define QSERDES_V5_RX_AC_JTAG_RESET 0x07c +#define QSERDES_V5_RX_RX_TERM_BW 0x080 +#define QSERDES_V5_RX_RX_RCVR_IQ_EN 0x084 +#define QSERDES_V5_RX_RX_IDAC_I_DC_OFFSETS 0x088 +#define QSERDES_V5_RX_RX_IDAC_IBAR_DC_OFFSETS 0x08c +#define QSERDES_V5_RX_RX_IDAC_Q_DC_OFFSETS 0x090 +#define QSERDES_V5_RX_RX_IDAC_QBAR_DC_OFFSETS 0x094 +#define QSERDES_V5_RX_RX_IDAC_A_DC_OFFSETS 0x098 +#define QSERDES_V5_RX_RX_IDAC_ABAR_DC_OFFSETS 0x09c +#define QSERDES_V5_RX_RX_IDAC_EN 0x0a0 +#define QSERDES_V5_RX_RX_IDAC_ENABLES 0x0a4 +#define QSERDES_V5_RX_RX_IDAC_SIGN 0x0a8 +#define QSERDES_V5_RX_RX_HIGHZ_HIGHRATE 0x0ac +#define QSERDES_V5_RX_RX_TERM_AC_BYPASS_DC_COUPLE_OFFSET 0x0b0 +#define QSERDES_V5_RX_DFE_1 0x0b4 +#define QSERDES_V5_RX_DFE_2 0x0b8 +#define QSERDES_V5_RX_DFE_3 0x0bc +#define QSERDES_V5_RX_DFE_4 0x0c0 +#define QSERDES_V5_RX_TX_ADAPT_PRE_THRESH1 0x0c4 +#define QSERDES_V5_RX_TX_ADAPT_PRE_THRESH2 0x0c8 +#define QSERDES_V5_RX_TX_ADAPT_POST_THRESH 0x0cc +#define QSERDES_V5_RX_TX_ADAPT_MAIN_THRESH 0x0d0 +#define QSERDES_V5_RX_VGA_CAL_CNTRL1 0x0d4 +#define QSERDES_V5_RX_VGA_CAL_CNTRL2 0x0d8 +#define QSERDES_V5_RX_GM_CAL 0x0dc +#define QSERDES_V5_RX_RX_VGA_GAIN2_LSB 0x0e0 +#define QSERDES_V5_RX_RX_VGA_GAIN2_MSB 0x0e4 +#define QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1 0x0e8 +#define QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2 0x0ec +#define QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3 0x0f0 +#define QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4 0x0f4 +#define QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW 0x0f8 +#define QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH 0x0fc +#define QSERDES_V5_RX_RX_IDAC_MEASURE_TIME 0x100 +#define QSERDES_V5_RX_RX_IDAC_ACCUMULATOR 0x104 +#define QSERDES_V5_RX_RX_EQ_OFFSET_LSB 0x108 +#define QSERDES_V5_RX_RX_EQ_OFFSET_MSB 0x10c +#define QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110 +#define QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2 0x114 +#define QSERDES_V5_RX_SIGDET_ENABLES 0x118 +#define QSERDES_V5_RX_SIGDET_CNTRL 0x11c +#define QSERDES_V5_RX_SIGDET_LVL 0x120 +#define QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL 0x124 +#define QSERDES_V5_RX_RX_BAND 0x128 +#define QSERDES_V5_RX_CDR_FREEZE_UP_DN 0x12c +#define QSERDES_V5_RX_CDR_RESET_OVERRIDE 0x130 +#define QSERDES_V5_RX_RX_INTERFACE_MODE 0x134 +#define QSERDES_V5_RX_JITTER_GEN_MODE 0x138 +#define QSERDES_V5_RX_SJ_AMP1 0x13c +#define QSERDES_V5_RX_SJ_AMP2 0x140 +#define QSERDES_V5_RX_SJ_PER1 0x144 +#define QSERDES_V5_RX_SJ_PER2 0x148 +#define QSERDES_V5_RX_PPM_OFFSET1 0x14c +#define QSERDES_V5_RX_PPM_OFFSET2 0x150 +#define QSERDES_V5_RX_SIGN_PPM_PERIOD1 0x154 +#define QSERDES_V5_RX_SIGN_PPM_PERIOD2 0x158 +#define QSERDES_V5_RX_RX_MODE_00_LOW 0x15c +#define QSERDES_V5_RX_RX_MODE_00_HIGH 0x160 +#define QSERDES_V5_RX_RX_MODE_00_HIGH2 0x164 +#define QSERDES_V5_RX_RX_MODE_00_HIGH3 0x168 +#define QSERDES_V5_RX_RX_MODE_00_HIGH4 0x16c +#define QSERDES_V5_RX_RX_MODE_01_LOW 0x170 +#define QSERDES_V5_RX_RX_MODE_01_HIGH 0x174 +#define QSERDES_V5_RX_RX_MODE_01_HIGH2 0x178 +#define QSERDES_V5_RX_RX_MODE_01_HIGH3 0x17c +#define QSERDES_V5_RX_RX_MODE_01_HIGH4 0x180 +#define QSERDES_V5_RX_RX_MODE_10_LOW 0x184 +#define QSERDES_V5_RX_RX_MODE_10_HIGH 0x188 +#define QSERDES_V5_RX_RX_MODE_10_HIGH2 0x18c +#define QSERDES_V5_RX_RX_MODE_10_HIGH3 0x190 +#define QSERDES_V5_RX_RX_MODE_10_HIGH4 0x194 +#define QSERDES_V5_RX_PHPRE_CTRL 0x198 +#define QSERDES_V5_RX_PHPRE_INITVAL 0x19c +#define QSERDES_V5_RX_DFE_EN_TIMER 0x1a0 +#define QSERDES_V5_RX_DFE_CTLE_POST_CAL_OFFSET 0x1a4 +#define QSERDES_V5_RX_DCC_CTRL1 0x1a8 +#define QSERDES_V5_RX_DCC_CTRL2 0x1ac +#define QSERDES_V5_RX_VTH_CODE 0x1b0 +#define QSERDES_V5_RX_VTH_MIN_THRESH 0x1b4 +#define QSERDES_V5_RX_VTH_MAX_THRESH 0x1b8 +#define QSERDES_V5_RX_ALOG_OBSV_BUS_CTRL_1 0x1bc +#define QSERDES_V5_RX_PI_CTRL1 0x1c0 +#define QSERDES_V5_RX_PI_CTRL2 0x1c4 +#define QSERDES_V5_RX_PI_QUAD 0x1c8 +#define QSERDES_V5_RX_IDATA1 0x1cc +#define QSERDES_V5_RX_IDATA2 0x1d0 +#define QSERDES_V5_RX_AUX_DATA1 0x1d4 +#define QSERDES_V5_RX_AUX_DATA2 0x1d8 +#define QSERDES_V5_RX_AC_JTAG_OUTP 0x1dc +#define QSERDES_V5_RX_AC_JTAG_OUTN 0x1e0 +#define QSERDES_V5_RX_RX_SIGDET 0x1e4 +#define QSERDES_V5_RX_ALOG_OBSV_BUS_STATUS_1 0x1e8 + +/* Only for QMP V5 UFS ? */ +#define QSERDES_V5_TX_PWM_GEAR_1_DIVIDER_BAND0_1 0x178 +#define QSERDES_V5_TX_PWM_GEAR_2_DIVIDER_BAND0_1 0x17c +#define QSERDES_V5_TX_PWM_GEAR_3_DIVIDER_BAND0_1 0x180 +#define QSERDES_V5_TX_PWM_GEAR_4_DIVIDER_BAND0_1 0x184 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v6.h b/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v6.h new file mode 100644 index 00000000000..23ffcfae9ef --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v6.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef QCOM_PHY_QMP_QSERDES_TXRX_USB_V6_H_ +#define QCOM_PHY_QMP_QSERDES_TXRX_USB_V6_H_ + +#define QSERDES_V6_TX_CLKBUF_ENABLE 0x08 +#define QSERDES_V6_TX_TX_EMP_POST1_LVL 0x0c +#define QSERDES_V6_TX_TX_DRV_LVL 0x14 +#define QSERDES_V6_TX_RESET_TSYNC_EN 0x1c +#define QSERDES_V6_TX_PRE_STALL_LDO_BOOST_EN 0x20 +#define QSERDES_V6_TX_TX_BAND 0x24 +#define QSERDES_V6_TX_INTERFACE_SELECT 0x2c +#define QSERDES_V6_TX_RES_CODE_LANE_TX 0x34 +#define QSERDES_V6_TX_RES_CODE_LANE_RX 0x38 +#define QSERDES_V6_TX_RES_CODE_LANE_OFFSET_TX 0x3c +#define QSERDES_V6_TX_RES_CODE_LANE_OFFSET_RX 0x40 +#define QSERDES_V6_TX_TRANSCEIVER_BIAS_EN 0x54 +#define QSERDES_V6_TX_HIGHZ_DRVR_EN 0x58 +#define QSERDES_V6_TX_TX_POL_INV 0x5c +#define QSERDES_V6_TX_PARRATE_REC_DETECT_IDLE_EN 0x60 +#define QSERDES_V6_TX_BIST_PATTERN7 0x7c +#define QSERDES_V6_TX_LANE_MODE_1 0x84 +#define QSERDES_V6_TX_LANE_MODE_2 0x88 +#define QSERDES_V6_TX_LANE_MODE_3 0x8c +#define QSERDES_V6_TX_LANE_MODE_4 0x90 +#define QSERDES_V6_TX_LANE_MODE_5 0x94 +#define QSERDES_V6_TX_RCV_DETECT_LVL_2 0xa4 +#define QSERDES_V6_TX_TRAN_DRVR_EMP_EN 0xc0 +#define QSERDES_V6_TX_TX_INTERFACE_MODE 0xc4 +#define QSERDES_V6_TX_VMODE_CTRL1 0xc8 +#define QSERDES_V6_TX_PI_QEC_CTRL 0xe4 + +#define QSERDES_V6_RX_UCDR_FO_GAIN 0x08 +#define QSERDES_V6_RX_UCDR_SO_GAIN 0x14 +#define QSERDES_V6_RX_UCDR_FASTLOCK_FO_GAIN 0x30 +#define QSERDES_V6_RX_UCDR_SO_SATURATION_AND_ENABLE 0x34 +#define QSERDES_V6_RX_UCDR_FASTLOCK_COUNT_LOW 0x3c +#define QSERDES_V6_RX_UCDR_FASTLOCK_COUNT_HIGH 0x40 +#define QSERDES_V6_RX_UCDR_PI_CONTROLS 0x44 +#define QSERDES_V6_RX_UCDR_SB2_THRESH1 0x4c +#define QSERDES_V6_RX_UCDR_SB2_THRESH2 0x50 +#define QSERDES_V6_RX_UCDR_SB2_GAIN1 0x54 +#define QSERDES_V6_RX_UCDR_SB2_GAIN2 0x58 +#define QSERDES_V6_RX_AUX_DATA_TCOARSE_TFINE 0x60 +#define QSERDES_V6_RX_TX_ADAPT_POST_THRESH 0xcc +#define QSERDES_V6_RX_VGA_CAL_CNTRL1 0xd4 +#define QSERDES_V6_RX_VGA_CAL_CNTRL2 0xd8 +#define QSERDES_V6_RX_GM_CAL 0xdc +#define QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL2 0xec +#define QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL3 0xf0 +#define QSERDES_V6_RX_RX_EQU_ADAPTOR_CNTRL4 0xf4 +#define QSERDES_V6_RX_RX_IDAC_TSETTLE_LOW 0xf8 +#define QSERDES_V6_RX_RX_IDAC_TSETTLE_HIGH 0xfc +#define QSERDES_V6_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1 0x110 +#define QSERDES_V6_RX_SIDGET_ENABLES 0x118 +#define QSERDES_V6_RX_SIGDET_CNTRL 0x11c +#define QSERDES_V6_RX_SIGDET_DEGLITCH_CNTRL 0x124 +#define QSERDES_V6_RX_RX_MODE_00_LOW 0x15c +#define QSERDES_V6_RX_RX_MODE_00_HIGH 0x160 +#define QSERDES_V6_RX_RX_MODE_00_HIGH2 0x164 +#define QSERDES_V6_RX_RX_MODE_00_HIGH3 0x168 +#define QSERDES_V6_RX_RX_MODE_00_HIGH4 0x16c +#define QSERDES_V6_RX_RX_MODE_01_LOW 0x170 +#define QSERDES_V6_RX_RX_MODE_01_HIGH 0x174 +#define QSERDES_V6_RX_RX_MODE_01_HIGH2 0x178 +#define QSERDES_V6_RX_RX_MODE_01_HIGH3 0x17c +#define QSERDES_V6_RX_RX_MODE_01_HIGH4 0x180 +#define QSERDES_V6_RX_RX_MODE_10_LOW 0x184 +#define QSERDES_V6_RX_RX_MODE_10_HIGH 0x188 +#define QSERDES_V6_RX_RX_MODE_10_HIGH2 0x18c +#define QSERDES_V6_RX_RX_MODE_10_HIGH3 0x190 +#define QSERDES_V6_RX_RX_MODE_10_HIGH4 0x194 +#define QSERDES_V6_RX_DFE_EN_TIMER 0x1a0 +#define QSERDES_V6_RX_DFE_CTLE_POST_CAL_OFFSET 0x1a4 +#define QSERDES_V6_RX_DCC_CTRL1 0x1a8 +#define QSERDES_V6_RX_VTH_CODE 0x1b0 +#define QSERDES_V6_RX_SIGDET_CAL_CTRL1 0x1e4 +#define QSERDES_V6_RX_SIGDET_CAL_TRIM 0x1f8 + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v6_20.h b/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v6_20.h new file mode 100644 index 00000000000..7bac5d5c6c3 --- /dev/null +++ b/drivers/phy/qcom/phy-qcom-qmp-qserdes-txrx-v6_20.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2023, Linaro Limited + */ + +#ifndef QCOM_PHY_QMP_QSERDES_TXRX_PCIE_V6_20_H_ +#define QCOM_PHY_QMP_QSERDES_TXRX_PCIE_V6_20_H_ + +#define QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_TX 0x30 +#define QSERDES_V6_20_TX_RES_CODE_LANE_OFFSET_RX 0x34 +#define QSERDES_V6_20_TX_TRAN_DRVR_EMP_EN 0xac +#define QSERDES_V6_20_TX_LANE_MODE_1 0x78 +#define QSERDES_V6_20_TX_LANE_MODE_2 0x7c +#define QSERDES_V6_20_TX_LANE_MODE_3 0x80 + +#define QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_2 0x08 +#define QSERDES_V6_20_RX_UCDR_FO_GAIN_RATE_3 0x0c +#define QSERDES_V6_20_RX_UCDR_SO_GAIN_RATE_2 0x18 +#define QSERDES_V6_20_RX_UCDR_PI_CONTROLS 0x20 +#define QSERDES_V6_20_RX_UCDR_SO_ACC_DEFAULT_VAL_RATE3 0x34 +#define QSERDES_V6_20_RX_IVCM_CAL_CTRL2 0x9c +#define QSERDES_V6_20_RX_IVCM_POSTCAL_OFFSET 0xa0 +#define QSERDES_V6_20_RX_DFE_1 0xac +#define QSERDES_V6_20_RX_DFE_2 0xb0 +#define QSERDES_V6_20_RX_DFE_3 0xb4 +#define QSERDES_V6_20_RX_TX_ADPT_CTRL 0xd4 +#define QSERDES_V6_20_VGA_CAL_CNTRL1 0xe0 +#define QSERDES_V6_20_RX_VGA_CAL_MAN_VAL 0xe8 +#define QSERDES_V6_20_RX_GM_CAL 0x10c +#define QSERDES_V6_20_RX_EQU_ADAPTOR_CNTRL4 0x120 +#define QSERDES_V6_20_RX_SIGDET_ENABLES 0x148 +#define QSERDES_V6_20_RX_PHPRE_CTRL 0x188 +#define QSERDES_V6_20_RX_DFE_CTLE_POST_CAL_OFFSET 0x194 +#define QSERDES_V6_20_RX_Q_PI_INTRINSIC_BIAS_RATE32 0x1dc +#define QSERDES_V6_20_RX_MODE_RATE2_B0 0x1f4 +#define QSERDES_V6_20_RX_MODE_RATE2_B1 0x1f8 +#define QSERDES_V6_20_RX_MODE_RATE2_B2 0x1fc +#define QSERDES_V6_20_RX_MODE_RATE2_B3 0x200 +#define QSERDES_V6_20_RX_MODE_RATE2_B4 0x204 +#define QSERDES_V6_20_RX_MODE_RATE2_B5 0x208 +#define QSERDES_V6_20_RX_MODE_RATE2_B6 0x20c +#define QSERDES_V6_20_RX_MODE_RATE3_B0 0x210 +#define QSERDES_V6_20_RX_MODE_RATE3_B1 0x214 +#define QSERDES_V6_20_RX_MODE_RATE3_B2 0x218 +#define QSERDES_V6_20_RX_MODE_RATE3_B3 0x21c +#define QSERDES_V6_20_RX_MODE_RATE3_B4 0x220 +#define QSERDES_V6_20_RX_MODE_RATE3_B5 0x224 +#define QSERDES_V6_20_RX_MODE_RATE3_B6 0x228 +#define QSERDES_V6_20_RX_BKUP_CTRL1 0x22c + +#endif diff --git a/drivers/phy/qcom/phy-qcom-qmp-ufs.c b/drivers/phy/qcom/phy-qcom-qmp-ufs.c index 5c90d60e7d1..449b9767778 100644 --- a/drivers/phy/qcom/phy-qcom-qmp-ufs.c +++ b/drivers/phy/qcom/phy-qcom-qmp-ufs.c @@ -33,8 +33,10 @@ #include "phy-qcom-qmp-pcs-ufs-v6.h" #include "phy-qcom-qmp-qserdes-com-v4.h" +#include "phy-qcom-qmp-qserdes-com-v5.h" #include "phy-qcom-qmp-qserdes-com-v6.h" #include "phy-qcom-qmp-qserdes-txrx-v4.h" +#include "phy-qcom-qmp-qserdes-txrx-v5.h" #include "phy-qcom-qmp-qserdes-txrx-ufs-v6.h" /* QPHY_SW_RESET bit */ @@ -97,6 +99,13 @@ static const unsigned int ufsphy_v4_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V4_PCS_UFS_POWER_DOWN_CONTROL, }; +static const unsigned int ufsphy_v5_regs_layout[QPHY_LAYOUT_SIZE] = { + [QPHY_START_CTRL] = QPHY_V5_PCS_UFS_PHY_START, + [QPHY_PCS_READY_STATUS] = QPHY_V5_PCS_UFS_READY_STATUS, + [QPHY_SW_RESET] = QPHY_V5_PCS_UFS_SW_RESET, + [QPHY_PCS_POWER_DOWN_CONTROL] = QPHY_V5_PCS_UFS_POWER_DOWN_CONTROL, +}; + static const unsigned int ufsphy_v6_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_START_CTRL] = QPHY_V6_PCS_UFS_PHY_START, [QPHY_PCS_READY_STATUS] = QPHY_V6_PCS_UFS_READY_STATUS, @@ -458,6 +467,128 @@ static const struct qmp_ufs_init_tbl sm8650_ufsphy_rx[] = { QMP_PHY_INIT_CFG(QSERDES_UFS_V6_RX_DLL0_FTUNE_CTRL, 0x30), }; +static const struct qmp_ufs_init_tbl sm8350_ufsphy_serdes[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_COM_SYSCLK_EN_SEL, 0xd9), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_SEL, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_HSCLK_HS_SWITCH_SEL, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP_EN, 0x42), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x02), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_IVCO, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_INITVAL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_HSCLK_SEL, 0x11), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE0, 0x82), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE0, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE0, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE0, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE0, 0xff), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE0, 0x19), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE0, 0xac), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE0, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_DEC_START_MODE1, 0x98), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_CP_CTRL_MODE1, 0x14), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_RCTRL_MODE1, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_PLL_CCTRL_MODE1, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP1_MODE1, 0x65), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_LOCK_CMP2_MODE1, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE1_MODE1, 0xdd), + QMP_PHY_INIT_CFG(QSERDES_V5_COM_BIN_VCOCAL_CMP_CODE2_MODE1, 0x23), +}; + +static const struct qmp_ufs_init_tbl sm8350_ufsphy_hs_b_serdes[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_COM_VCO_TUNE_MAP, 0x06), +}; + +static const struct qmp_ufs_init_tbl sm8350_ufsphy_tx[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_1_DIVIDER_BAND0_1, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_2_DIVIDER_BAND0_1, 0x03), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_3_DIVIDER_BAND0_1, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_PWM_GEAR_4_DIVIDER_BAND0_1, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xf5), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_3, 0x3f), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_TX, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_RES_CODE_LANE_OFFSET_RX, 0x09), + QMP_PHY_INIT_CFG(QSERDES_V5_TX_TRAN_DRVR_EMP_EN, 0x0c), +}; + +static const struct qmp_ufs_init_tbl sm8350_ufsphy_rx[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_LVL, 0x24), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_CNTRL, 0x0f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_SIGDET_DEGLITCH_CNTRL, 0x1e), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_BAND, 0x18), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_SATURATION_AND_ENABLE, 0x5a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CONTROLS, 0xf1), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CTRL2, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0e), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_TERM_BW, 0x1b), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL1, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x06), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x04), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x1a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x17), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_OFFSET_ADAPTOR_CNTRL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x10), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0xc0), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0x6d), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0x6d), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0xed), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x3b), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0x3c), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0xe0), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0xc8), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xc8), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH3, 0x3b), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0xb7), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_LOW, 0xe0), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH, 0xc8), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH2, 0xc8), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH3, 0x3b), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_10_HIGH4, 0xb7), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_DCC_CTRL1, 0x0c), +}; + +static const struct qmp_ufs_init_tbl sm8350_ufsphy_pcs[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL2, 0x6d), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_LARGE_AMP_DRV_LVL, 0x0a), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_SMALL_AMP_DRV_LVL, 0x02), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_DEBUG_BUS_CLKSEL, 0x1f), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_MIN_HIBERN8_TIME, 0xff), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_RX_SIGDET_CTRL1, 0x0e), + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_MULTI_LANE_CTRL1, 0x02), +}; + +static const struct qmp_ufs_init_tbl sm8350_ufsphy_g4_tx[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_TX_LANE_MODE_1, 0xe5), +}; + +static const struct qmp_ufs_init_tbl sm8350_ufsphy_g4_rx[] = { + QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_PI_CTRL2, 0x81), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_TERM_BW, 0x6f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x00), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL3, 0x4a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL4, 0x0a), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_MEASURE_TIME, 0x20), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_LOW, 0x80), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_IDAC_TSETTLE_HIGH, 0x01), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_LOW, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH, 0xbf), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH2, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH3, 0x7f), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_00_HIGH4, 0x2d), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_LOW, 0x6d), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH, 0x6d), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH2, 0xed), + QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_MODE_01_HIGH4, 0x3c), +}; + +static const struct qmp_ufs_init_tbl sm8350_ufsphy_g4_pcs[] = { + QMP_PHY_INIT_CFG(QPHY_V5_PCS_UFS_BIST_FIXED_PAT_CTRL, 0x0a), +}; + static const struct qmp_ufs_init_tbl sm8650_ufsphy_pcs[] = { QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_MULTI_LANE_CTRL1, 0x02), QMP_PHY_INIT_CFG(QPHY_V6_PCS_UFS_TX_MID_TERM_CTRL1, 0x43), @@ -690,6 +821,11 @@ static const char * const sdm845_ufs_phy_clk_l[] = { "ref", "ref_aux", }; +/* the primary usb3 phy on sm8250 doesn't have a ref clock */ +static const char * const sm8450_ufs_phy_clk_l[] = { + "qref", "ref", "ref_aux", +}; + /* list of regulators */ static const char * const qmp_ufs_vreg_l[] = { "vdda-phy", "vdda-pll", @@ -909,6 +1045,40 @@ static const struct qmp_ufs_cfg sc7280_ufsphy_cfg = { .regs = ufsphy_v4_regs_layout, }; +static const struct qmp_ufs_cfg sa8775p_ufsphy_cfg = { + .lanes = 2, + + .offsets = &qmp_ufs_offsets, + + .tbls = { + .serdes = sm8350_ufsphy_serdes, + .serdes_num = ARRAY_SIZE(sm8350_ufsphy_serdes), + .tx = sm8350_ufsphy_tx, + .tx_num = ARRAY_SIZE(sm8350_ufsphy_tx), + .rx = sm8350_ufsphy_rx, + .rx_num = ARRAY_SIZE(sm8350_ufsphy_rx), + .pcs = sm8350_ufsphy_pcs, + .pcs_num = ARRAY_SIZE(sm8350_ufsphy_pcs), + }, + .tbls_hs_b = { + .serdes = sm8350_ufsphy_hs_b_serdes, + .serdes_num = ARRAY_SIZE(sm8350_ufsphy_hs_b_serdes), + }, + .tbls_hs_g4 = { + .tx = sm8350_ufsphy_g4_tx, + .tx_num = ARRAY_SIZE(sm8350_ufsphy_g4_tx), + .rx = sm8350_ufsphy_g4_rx, + .rx_num = ARRAY_SIZE(sm8350_ufsphy_g4_rx), + .pcs = sm8350_ufsphy_g4_pcs, + .pcs_num = ARRAY_SIZE(sm8350_ufsphy_g4_pcs), + }, + .clk_list = sm8450_ufs_phy_clk_l, + .num_clks = ARRAY_SIZE(sm8450_ufs_phy_clk_l), + .vreg_list = qmp_ufs_vreg_l, + .num_vregs = ARRAY_SIZE(qmp_ufs_vreg_l), + .regs = ufsphy_v5_regs_layout, +}; + static void qmp_ufs_configure_lane(void __iomem *base, const struct qmp_ufs_init_tbl tbl[], int num, @@ -1295,6 +1465,7 @@ static struct phy_ops qmp_ufs_ops = { }; static const struct udevice_id qmp_ufs_ids[] = { + { .compatible = "qcom,sa8775p-qmp-ufs-phy", .data = (ulong)&sa8775p_ufsphy_cfg, }, { .compatible = "qcom,sdm845-qmp-ufs-phy", .data = (ulong)&sdm845_ufsphy_cfg }, { .compatible = "qcom,sm8150-qmp-ufs-phy", .data = (ulong)&sm8150_ufsphy_cfg }, { .compatible = "qcom,sm8250-qmp-ufs-phy", .data = (ulong)&sm8250_ufsphy_cfg }, diff --git a/drivers/pinctrl/nxp/pinctrl-imx.c b/drivers/pinctrl/nxp/pinctrl-imx.c index b1960c56b51..54cec37327c 100644 --- a/drivers/pinctrl/nxp/pinctrl-imx.c +++ b/drivers/pinctrl/nxp/pinctrl-imx.c @@ -219,7 +219,7 @@ int imx_pinctrl_probe(struct udevice *dev, if (info->flags & IMX8_USE_SCU) return 0; - addr = ofnode_get_addr_size_index(dev_ofnode(dev), 0, &size); + addr = ofnode_get_addr_size_index(node, 0, &size); if (addr == FDT_ADDR_T_NONE) return -EINVAL; @@ -228,7 +228,7 @@ int imx_pinctrl_probe(struct udevice *dev, return -ENOMEM; priv->info = info; - info->mux_mask = ofnode_read_u32(node, "fsl,mux_mask", 0); + info->mux_mask = ofnode_read_u32_default(node, "fsl,mux_mask", 0); /* * Refer to linux documentation for details: * Documentation/devicetree/bindings/pinctrl/fsl,imx7d-pinctrl.txt diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 4f93a34281d..d3eb6998551 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -83,6 +83,13 @@ config PINCTRL_QCOM_SM8650 Say Y here to enable support for pinctrl on the Snapdragon SM8650 SoC, as well as the associated GPIO driver. +config PINCTRL_QCOM_X1E80100 + bool "Qualcomm X1E80100 GCC" + select PINCTRL_QCOM + help + Say Y here to enable support for pinctrl on the Snapdragon X1E80100 SoC, + as well as the associated GPIO driver. + endmenu endif diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 43d0dd29222..06d3c95f93a 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_PINCTRL_QCOM_SM8150) += pinctrl-sm8150.o obj-$(CONFIG_PINCTRL_QCOM_SM8250) += pinctrl-sm8250.o obj-$(CONFIG_PINCTRL_QCOM_SM8550) += pinctrl-sm8550.o obj-$(CONFIG_PINCTRL_QCOM_SM8650) += pinctrl-sm8650.o +obj-$(CONFIG_PINCTRL_QCOM_X1E80100) += pinctrl-x1e80100.o diff --git a/drivers/pinctrl/qcom/pinctrl-sm8550.c b/drivers/pinctrl/qcom/pinctrl-sm8550.c index c65dfe0435e..25b972a6d82 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8550.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8550.c @@ -16,6 +16,7 @@ static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); static const struct pinctrl_function msm_pinctrl_functions[] = { {"qup1_se7", 1}, {"gpio", 0}, + {"pcie1_clk_req_n", 1}, }; #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ diff --git a/drivers/pinctrl/qcom/pinctrl-sm8650.c b/drivers/pinctrl/qcom/pinctrl-sm8650.c index 58fc94e71ac..9146d6abd9a 100644 --- a/drivers/pinctrl/qcom/pinctrl-sm8650.c +++ b/drivers/pinctrl/qcom/pinctrl-sm8650.c @@ -16,6 +16,8 @@ static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); static const struct pinctrl_function msm_pinctrl_functions[] = { {"qup2_se7", 1}, {"gpio", 0}, + {"pcie0_clk_req_n", 1}, + {"pcie1_clk_req_n", 1}, }; #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ diff --git a/drivers/pinctrl/qcom/pinctrl-x1e80100.c b/drivers/pinctrl/qcom/pinctrl-x1e80100.c new file mode 100644 index 00000000000..f39dc426d68 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-x1e80100.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm x1e80100 pinctrl + * + * (C) Copyright 2024 Linaro Ltd. + * + */ + +#include <dm.h> + +#include "pinctrl-qcom.h" + +#define MAX_PIN_NAME_LEN 32 +static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); + +static const struct pinctrl_function msm_pinctrl_functions[] = { + {"qup2_se5", 1}, + {"pcie3_clk", 1}, + {"pcie4_clk", 1}, + {"pcie5_clk", 1}, + {"pcie6a_clk", 1}, + {"pcie6b_clk", 1}, + {"gpio", 0}, +}; + +#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = pg_name, \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + } + +#define UFS_RESET(pg_name, ctl) \ + { \ + .name = pg_name, \ + .ctl_reg = ctl, \ + .io_reg = ctl + 0x4, \ + .pull_bit = 3, \ + .drv_bit = 0, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = 0, \ + } + +static const struct msm_special_pin_data msm_special_pins_data[] = { + [0] = UFS_RESET("ufs_reset", 0xf9000), + [1] = SDC_QDSD_PINGROUP("sdc2_clk", 0xf2000, 14, 6), + [2] = SDC_QDSD_PINGROUP("sdc2_cmd", 0xf2000, 11, 3), + [3] = SDC_QDSD_PINGROUP("sdc2_data", 0xf2000, 9, 0), +}; + +static const char *x1e80100_get_function_name(struct udevice *dev, + unsigned int selector) +{ + return msm_pinctrl_functions[selector].name; +} + +static const char *x1e80100_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + if (selector >= 238 && selector <= 241) + snprintf(pin_name, MAX_PIN_NAME_LEN, + msm_special_pins_data[selector - 238].name); + else + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); + + return pin_name; +} + +static unsigned int x1e80100_get_function_mux(__maybe_unused unsigned int pin, + unsigned int selector) +{ + return msm_pinctrl_functions[selector].val; +} + +static struct msm_pinctrl_data x1e80100_data = { + .pin_data = { + .pin_count = 242, + .special_pins_start = 238, + .special_pins_data = msm_special_pins_data, + }, + .functions_count = ARRAY_SIZE(msm_pinctrl_functions), + .get_function_name = x1e80100_get_function_name, + .get_function_mux = x1e80100_get_function_mux, + .get_pin_name = x1e80100_get_pin_name, +}; + +static const struct udevice_id msm_pinctrl_ids[] = { + { .compatible = "qcom,x1e80100-tlmm", .data = (ulong)&x1e80100_data }, + { /* Sentinel */ } +}; + +U_BOOT_DRIVER(pinctrl_x1e80100) = { + .name = "pinctrl_x1e80100", + .id = UCLASS_NOP, + .of_match = msm_pinctrl_ids, + .ops = &msm_pinctrl_ops, + .bind = msm_pinctrl_bind, +}; + diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c b/drivers/power/regulator/qcom-rpmh-regulator.c index 2dc261d83e3..70df51b5fa4 100644 --- a/drivers/power/regulator/qcom-rpmh-regulator.c +++ b/drivers/power/regulator/qcom-rpmh-regulator.c @@ -536,6 +536,21 @@ static const struct rpmh_vreg_init_data pm8550ve_vreg_data[] = { {} }; +static const struct rpmh_vreg_init_data pmc8380_vreg_data[] = { + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"), + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"), + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"), + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"), + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"), + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"), + RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"), + RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"), + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"), + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2"), + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"), + {} +}; + /* probe an individual regulator */ static int rpmh_regulator_probe(struct udevice *dev) { @@ -662,6 +677,10 @@ static const struct udevice_id rpmh_regulator_ids[] = { .compatible = "qcom,pm8550vs-rpmh-regulators", .data = (ulong)pm8550vs_vreg_data, }, + { + .compatible = "qcom,pmc8380-rpmh-regulators", + .data = (ulong)pmc8380_vreg_data, + }, { /* sentinal */ }, }; diff --git a/drivers/pwm/pwm-mtk.c b/drivers/pwm/pwm-mtk.c index 9776a41ff48..5cf2eba2ba0 100644 --- a/drivers/pwm/pwm-mtk.c +++ b/drivers/pwm/pwm-mtk.c @@ -192,7 +192,7 @@ static const struct mtk_pwm_soc mt7629_data = { }; static const struct mtk_pwm_soc mt7981_data = { - .num_pwms = 2, + .num_pwms = 3, .pwm45_fixup = false, .reg_ver = PWM_REG_V2, }; diff --git a/drivers/rng/msm_rng.c b/drivers/rng/msm_rng.c index 658c153d3ed..f790d3b60f9 100644 --- a/drivers/rng/msm_rng.c +++ b/drivers/rng/msm_rng.c @@ -34,6 +34,7 @@ struct msm_rng_priv { phys_addr_t base; struct clk clk; + bool skip_init; }; static int msm_rng_read(struct udevice *dev, void *data, size_t len) @@ -100,10 +101,15 @@ static int msm_rng_probe(struct udevice *dev) int ret; + priv->skip_init = (bool)dev_get_driver_data(dev); + priv->base = dev_read_addr(dev); if (priv->base == FDT_ADDR_T_NONE) return -EINVAL; + if (priv->skip_init) + return 0; + ret = clk_get_by_index(dev, 0, &priv->clk); if (ret) return ret; @@ -119,6 +125,9 @@ static int msm_rng_remove(struct udevice *dev) { struct msm_rng_priv *priv = dev_get_priv(dev); + if (priv->skip_init) + return 0; + return msm_rng_enable(priv, 0); } @@ -127,7 +136,9 @@ static const struct dm_rng_ops msm_rng_ops = { }; static const struct udevice_id msm_rng_match[] = { - { .compatible = "qcom,prng", }, + { .compatible = "qcom,prng", .data = (ulong)false }, + { .compatible = "qcom,prng-ee", .data = (ulong)true }, + { .compatible = "qcom,trng", .data = (ulong)true }, {}, }; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7e21c4ae2bb..fc87d34cca3 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1,5 +1,6 @@ config SCSI bool "Support SCSI controllers with driver model" + select BLK help This enables support for SCSI (Small Computer System Interface), a parallel interface widely used with storage peripherals such as diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index c3b884b6d00..039da835f5f 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -464,7 +464,7 @@ int ns16550_serial_getinfo(struct udevice *dev, struct serial_device_info *info) struct ns16550_plat *plat = com_port->plat; /* save code size */ - if (!not_xpl()) + if (!not_xpl() && !CONFIG_IS_ENABLED(UPL_OUT)) return -ENOSYS; info->type = SERIAL_CHIP_16550_COMPATIBLE; diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h deleted file mode 100644 index 9663cca5e66..00000000000 --- a/drivers/spi/atmel_spi.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Register definitions for the Atmel AT32/AT91 SPI Controller - */ - -/* Register offsets */ -#include <linux/bitops.h> -#define ATMEL_SPI_CR 0x0000 -#define ATMEL_SPI_MR 0x0004 -#define ATMEL_SPI_RDR 0x0008 -#define ATMEL_SPI_TDR 0x000c -#define ATMEL_SPI_SR 0x0010 -#define ATMEL_SPI_IER 0x0014 -#define ATMEL_SPI_IDR 0x0018 -#define ATMEL_SPI_IMR 0x001c -#define ATMEL_SPI_CSR(x) (0x0030 + 4 * (x)) -#define ATMEL_SPI_VERSION 0x00fc - -/* Bits in CR */ -#define ATMEL_SPI_CR_SPIEN BIT(0) -#define ATMEL_SPI_CR_SPIDIS BIT(1) -#define ATMEL_SPI_CR_SWRST BIT(7) -#define ATMEL_SPI_CR_LASTXFER BIT(24) - -/* Bits in MR */ -#define ATMEL_SPI_MR_MSTR BIT(0) -#define ATMEL_SPI_MR_PS BIT(1) -#define ATMEL_SPI_MR_PCSDEC BIT(2) -#define ATMEL_SPI_MR_FDIV BIT(3) -#define ATMEL_SPI_MR_MODFDIS BIT(4) -#define ATMEL_SPI_MR_WDRBT BIT(5) -#define ATMEL_SPI_MR_LLB BIT(7) -#define ATMEL_SPI_MR_PCS(x) (((x) & 15) << 16) -#define ATMEL_SPI_MR_DLYBCS(x) ((x) << 24) - -/* Bits in RDR */ -#define ATMEL_SPI_RDR_RD(x) (x) -#define ATMEL_SPI_RDR_PCS(x) ((x) << 16) - -/* Bits in TDR */ -#define ATMEL_SPI_TDR_TD(x) (x) -#define ATMEL_SPI_TDR_PCS(x) ((x) << 16) -#define ATMEL_SPI_TDR_LASTXFER BIT(24) - -/* Bits in SR/IER/IDR/IMR */ -#define ATMEL_SPI_SR_RDRF BIT(0) -#define ATMEL_SPI_SR_TDRE BIT(1) -#define ATMEL_SPI_SR_MODF BIT(2) -#define ATMEL_SPI_SR_OVRES BIT(3) -#define ATMEL_SPI_SR_ENDRX BIT(4) -#define ATMEL_SPI_SR_ENDTX BIT(5) -#define ATMEL_SPI_SR_RXBUFF BIT(6) -#define ATMEL_SPI_SR_TXBUFE BIT(7) -#define ATMEL_SPI_SR_NSSR BIT(8) -#define ATMEL_SPI_SR_TXEMPTY BIT(9) -#define ATMEL_SPI_SR_SPIENS BIT(16) - -/* Bits in CSRx */ -#define ATMEL_SPI_CSRx_CPOL BIT(0) -#define ATMEL_SPI_CSRx_NCPHA BIT(1) -#define ATMEL_SPI_CSRx_CSAAT BIT(3) -#define ATMEL_SPI_CSRx_BITS(x) ((x) << 4) -#define ATMEL_SPI_CSRx_SCBR(x) ((x) << 8) -#define ATMEL_SPI_CSRx_SCBR_MAX GENMASK(7, 0) -#define ATMEL_SPI_CSRx_DLYBS(x) ((x) << 16) -#define ATMEL_SPI_CSRx_DLYBCT(x) ((x) << 24) - -/* Bits in VERSION */ -#define ATMEL_SPI_VERSION_REV(x) ((x) & 0xfff) -#define ATMEL_SPI_VERSION_MFN(x) ((x) << 16) - -/* Constants for CSRx:BITS */ -#define ATMEL_SPI_BITS_8 0 -#define ATMEL_SPI_BITS_9 1 -#define ATMEL_SPI_BITS_10 2 -#define ATMEL_SPI_BITS_11 3 -#define ATMEL_SPI_BITS_12 4 -#define ATMEL_SPI_BITS_13 5 -#define ATMEL_SPI_BITS_14 6 -#define ATMEL_SPI_BITS_15 7 -#define ATMEL_SPI_BITS_16 8 - -/* Register access macros */ -#define spi_readl(as, reg) \ - readl(as->regs + ATMEL_SPI_##reg) -#define spi_writel(as, reg, value) \ - writel(value, as->regs + ATMEL_SPI_##reg) diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 93ab2b5635f..f2f69cf9f12 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -151,9 +151,9 @@ static int cadence_qspi_set_protocol(struct cadence_spi_priv *priv, /* Return 1 if idle, otherwise return 0 (busy). */ static unsigned int cadence_qspi_wait_idle(void *reg_base) { - unsigned int start, count = 0; + unsigned long start, count = 0; /* timeout in unit of ms */ - unsigned int timeout = 5000; + unsigned long timeout = 5000; start = get_timer(0); for ( ; get_timer(start) < timeout ; ) { @@ -170,7 +170,7 @@ static unsigned int cadence_qspi_wait_idle(void *reg_base) } /* Timeout, still in busy mode. */ - printf("QSPI: QSPI is still busy after poll for %d ms.\n", timeout); + printf("QSPI: QSPI is still busy after poll for %lu ms.\n", timeout); return 0; } diff --git a/drivers/spi/mtk_spim.c b/drivers/spi/mtk_spim.c index b66bcfc4233..2b2c31b4b3f 100644 --- a/drivers/spi/mtk_spim.c +++ b/drivers/spi/mtk_spim.c @@ -359,6 +359,9 @@ static bool mtk_spim_supports_op(struct spi_slave *slave, struct udevice *bus = dev_get_parent(slave->dev); struct mtk_spim_priv *priv = dev_get_priv(bus); + if (!spi_mem_default_supports_op(slave, op)) + return false; + if (op->cmd.buswidth == 0 || op->cmd.buswidth > 4 || op->addr.buswidth > 4 || op->dummy.buswidth > 4 || op->data.buswidth > 4) @@ -648,7 +651,7 @@ static int mtk_spim_probe(struct udevice *dev) struct mtk_spim_priv *priv = dev_get_priv(dev); int ret; - priv->base = devfdt_get_addr_ptr(dev); + priv->base = dev_read_addr_ptr(dev); if (!priv->base) return -EINVAL; diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 960b6a906ac..99c6649e417 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -1,5 +1,6 @@ menuconfig USB bool "USB support" + select BLK ---help--- Universal Serial Bus (USB) is a specification for a serial bus subsystem which offers higher speeds and more features than the diff --git a/drivers/video/bochs.c b/drivers/video/bochs.c index 00e673a4db0..c34bc23f274 100644 --- a/drivers/video/bochs.c +++ b/drivers/video/bochs.c @@ -64,6 +64,7 @@ static int bochs_init_fb(struct udevice *dev) uc_priv->xsize = xsize; uc_priv->ysize = ysize; uc_priv->bpix = VIDEO_BPP32; + uc_priv->format = VIDEO_X8B8G8R8; /* setup video mode */ bochs_write(mmio, INDEX_ENABLE, 0); diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index a5b3e898066..ff4f2199585 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -589,6 +589,7 @@ static int video_post_probe(struct udevice *dev) ho->ysize = priv->ysize; ho->line_length = priv->line_length; ho->bpix = priv->bpix; + ho->format = priv->format; } if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->copy_base) diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 1de68867d52..512ac376f18 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -64,6 +64,7 @@ config VIRTIO_NET config VIRTIO_BLK bool "virtio block driver" depends on VIRTIO + select BLK help This is the virtual block driver for virtio. It can be used with QEMU based targets. |