diff options
Diffstat (limited to 'drivers')
130 files changed, 5821 insertions, 2031 deletions
diff --git a/drivers/ata/dwc_ahsata_priv.h b/drivers/ata/dwc_ahsata_priv.h index 0c2cd5446b5..f2a118420f9 100644 --- a/drivers/ata/dwc_ahsata_priv.h +++ b/drivers/ata/dwc_ahsata_priv.h @@ -117,8 +117,8 @@ #define SATA_HOST_GPARAM1R_PHY_TYPE 0x00001000 #define SATA_HOST_GPARAM1R_RETURN_ERR 0x00000400 #define SATA_HOST_GPARAM1R_AHB_ENDIAN_MASK 0x00000300 -#define SATA_HOST_GPARAM1R_S_HADDR 0X00000080 -#define SATA_HOST_GPARAM1R_M_HADDR 0X00000040 +#define SATA_HOST_GPARAM1R_S_HADDR 0x00000080 +#define SATA_HOST_GPARAM1R_M_HADDR 0x00000040 /* Global Parameter 2 Register */ #define SATA_HOST_GPARAM2R_DEV_CP 0x00004000 diff --git a/drivers/button/button-qcom-pmic.c b/drivers/button/button-qcom-pmic.c index e3bb9bd758a..85addfe32a2 100644 --- a/drivers/button/button-qcom-pmic.c +++ b/drivers/button/button-qcom-pmic.c @@ -143,6 +143,21 @@ static int qcom_pwrkey_probe(struct udevice *dev) priv->base = base; + ret = dev_read_u32(dev, "linux,code", &priv->code); + if (ret == 0) { + /* convert key, if read OK */ + switch (priv->code) { + case KEY_VOLUMEDOWN: + priv->code = KEY_DOWN; + uc_plat->label = "Volume Down"; + break; + case KEY_VOLUMEUP: + priv->code = KEY_UP; + uc_plat->label = "Volume Up"; + break; + } + } + /* Do a sanity check */ ret = pmic_reg_read(priv->pmic, priv->base + REG_TYPE); if (ret != 0x1 && ret != 0xb) { diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 19aa2ffa539..ef1e5355be8 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -10,6 +10,16 @@ config CLK feed into other clocks in a tree structure, with multiplexers to choose the source for each clock. +config CLK_AUTO_ID + bool "Enable support of an unique clock id with several provider" + depends on CLK + help + Add the uclass sequence number of clock provider in the 8 higher bits + of the clk id to guaranty an unique clock identifier in clk uclass + when several clock providers are present on the device and when + default xlate are used. + This feature limit each identifier for each clock providers (24 bits). + config SPL_CLK bool "Enable clock support in SPL" depends on CLK && SPL && SPL_DM @@ -182,6 +192,7 @@ config CLK_SCMI bool "Enable SCMI clock driver" depends on CLK depends on SCMI_FIRMWARE + select CLK_AUTO_ID if CLK_CCF help Enable this option if you want to support clock devices exposed by a SCMI agent based on SCMI clock protocol communication diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 2167cd5ad0f..7262e89b512 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -34,6 +34,11 @@ struct clk *dev_get_clk_ptr(struct udevice *dev) return (struct clk *)dev_get_uclass_priv(dev); } +ulong clk_get_id(const struct clk *clk) +{ + return (ulong)(clk->id & CLK_ID_MSK); +} + #if CONFIG_IS_ENABLED(OF_PLATDATA) int clk_get_by_phandle(struct udevice *dev, const struct phandle_1_arg *cells, struct clk *clk) @@ -43,7 +48,7 @@ int clk_get_by_phandle(struct udevice *dev, const struct phandle_1_arg *cells, ret = device_get_by_ofplat_idx(cells->idx, &clk->dev); if (ret) return ret; - clk->id = cells->arg[0]; + clk->id = CLK_ID(dev, cells->arg[0]); return 0; } @@ -61,7 +66,7 @@ static int clk_of_xlate_default(struct clk *clk, } if (args->args_count) - clk->id = args->args[0]; + clk->id = CLK_ID(clk->dev, args->args[0]); else clk->id = 0; diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index d1da05cc18a..95a77d2e041 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -44,6 +44,7 @@ void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev, dev_set_uclass_priv(dev, clk); clk->dev = dev; + clk->id = CLK_ID(dev, 0); clk->enable_count = 0; } diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c index 8dd77f18d90..c8c5a88c52d 100644 --- a/drivers/clk/clk_sandbox.c +++ b/drivers/clk/clk_sandbox.c @@ -13,24 +13,26 @@ static ulong sandbox_clk_get_rate(struct clk *clk) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); + ulong id = clk_get_id(clk); if (!priv->probed) return -ENODEV; - if (clk->id >= SANDBOX_CLK_ID_COUNT) + if (id >= SANDBOX_CLK_ID_COUNT) return -EINVAL; - return priv->rate[clk->id]; + return priv->rate[id]; } static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); + ulong id = clk_get_id(clk); if (!priv->probed) return -ENODEV; - if (clk->id >= SANDBOX_CLK_ID_COUNT) + if (id >= SANDBOX_CLK_ID_COUNT) return -EINVAL; if (!rate) @@ -43,18 +45,19 @@ static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); ulong old_rate; + ulong id = clk_get_id(clk); if (!priv->probed) return -ENODEV; - if (clk->id >= SANDBOX_CLK_ID_COUNT) + if (id >= SANDBOX_CLK_ID_COUNT) return -EINVAL; if (!rate) return -EINVAL; - old_rate = priv->rate[clk->id]; - priv->rate[clk->id] = rate; + old_rate = priv->rate[id]; + priv->rate[id] = rate; return old_rate; } @@ -62,14 +65,15 @@ static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate) static int sandbox_clk_enable(struct clk *clk) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); + ulong id = clk_get_id(clk); if (!priv->probed) return -ENODEV; - if (clk->id >= SANDBOX_CLK_ID_COUNT) + if (id >= SANDBOX_CLK_ID_COUNT) return -EINVAL; - priv->enabled[clk->id] = true; + priv->enabled[id] = true; return 0; } @@ -77,14 +81,15 @@ static int sandbox_clk_enable(struct clk *clk) static int sandbox_clk_disable(struct clk *clk) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); + ulong id = clk_get_id(clk); if (!priv->probed) return -ENODEV; - if (clk->id >= SANDBOX_CLK_ID_COUNT) + if (id >= SANDBOX_CLK_ID_COUNT) return -EINVAL; - priv->enabled[clk->id] = false; + priv->enabled[id] = false; return 0; } @@ -92,11 +97,12 @@ static int sandbox_clk_disable(struct clk *clk) static int sandbox_clk_request(struct clk *clk) { struct sandbox_clk_priv *priv = dev_get_priv(clk->dev); + ulong id = clk_get_id(clk); - if (clk->id >= SANDBOX_CLK_ID_COUNT) + if (id >= SANDBOX_CLK_ID_COUNT) return -EINVAL; - priv->requested[clk->id] = true; + priv->requested[id] = true; return 0; } diff --git a/drivers/clk/clk_sandbox_ccf.c b/drivers/clk/clk_sandbox_ccf.c index f96a15c30b3..9b8036d41aa 100644 --- a/drivers/clk/clk_sandbox_ccf.c +++ b/drivers/clk/clk_sandbox_ccf.c @@ -235,47 +235,47 @@ static int sandbox_clk_ccf_probe(struct udevice *dev) void *base = NULL; u32 reg; - clk_dm(SANDBOX_CLK_PLL3, - sandbox_clk_pllv3(SANDBOX_PLLV3_USB, "pll3_usb_otg", "osc", - base + 0x10, 0x3)); + dev_clk_dm(dev, SANDBOX_CLK_PLL3, + sandbox_clk_pllv3(SANDBOX_PLLV3_USB, "pll3_usb_otg", "osc", + base + 0x10, 0x3)); - clk_dm(SANDBOX_CLK_PLL3_60M, - sandbox_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8)); + dev_clk_dm(dev, SANDBOX_CLK_PLL3_60M, + sandbox_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8)); - clk_dm(SANDBOX_CLK_PLL3_80M, - sandbox_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6)); + dev_clk_dm(dev, SANDBOX_CLK_PLL3_80M, + sandbox_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6)); /* The HW adds +1 to the divider value (2+1) is the divider */ reg = (2 << 19); - clk_dm(SANDBOX_CLK_ECSPI_ROOT, - sandbox_clk_divider("ecspi_root", "pll3_60m", ®, 19, 6)); + dev_clk_dm(dev, SANDBOX_CLK_ECSPI_ROOT, + sandbox_clk_divider("ecspi_root", "pll3_60m", ®, 19, 6)); reg = 0; - clk_dm(SANDBOX_CLK_ECSPI0, - sandbox_clk_gate("ecspi0", "ecspi_root", ®, 0, 0)); + dev_clk_dm(dev, SANDBOX_CLK_ECSPI0, + sandbox_clk_gate("ecspi0", "ecspi_root", ®, 0, 0)); - clk_dm(SANDBOX_CLK_ECSPI1, - sandbox_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0)); + dev_clk_dm(dev, SANDBOX_CLK_ECSPI1, + sandbox_clk_gate2("ecspi1", "ecspi_root", base + 0x6c, 0)); /* Select 'pll3_60m' */ reg = 0; - clk_dm(SANDBOX_CLK_USDHC1_SEL, - sandbox_clk_mux("usdhc1_sel", ®, 16, 1, usdhc_sels, - ARRAY_SIZE(usdhc_sels))); + dev_clk_dm(dev, SANDBOX_CLK_USDHC1_SEL, + sandbox_clk_mux("usdhc1_sel", ®, 16, 1, usdhc_sels, + ARRAY_SIZE(usdhc_sels))); /* Select 'pll3_80m' */ reg = BIT(17); - clk_dm(SANDBOX_CLK_USDHC2_SEL, - sandbox_clk_mux("usdhc2_sel", ®, 17, 1, usdhc_sels, - ARRAY_SIZE(usdhc_sels))); + dev_clk_dm(dev, SANDBOX_CLK_USDHC2_SEL, + sandbox_clk_mux("usdhc2_sel", ®, 17, 1, usdhc_sels, + ARRAY_SIZE(usdhc_sels))); reg = BIT(28) | BIT(24) | BIT(16); - clk_dm(SANDBOX_CLK_I2C, - sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels), - ®, CLK_SET_RATE_UNGATE)); + dev_clk_dm(dev, SANDBOX_CLK_I2C, + sandbox_clk_composite("i2c", i2c_sels, ARRAY_SIZE(i2c_sels), + ®, CLK_SET_RATE_UNGATE)); - clk_dm(SANDBOX_CLK_I2C_ROOT, - sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0)); + dev_clk_dm(dev, SANDBOX_CLK_I2C_ROOT, + sandbox_clk_gate2("i2c_root", "i2c", base + 0x7c, 0)); return 0; } diff --git a/drivers/clk/clk_scmi.c b/drivers/clk/clk_scmi.c index af69850cdd8..cfb372e6190 100644 --- a/drivers/clk/clk_scmi.c +++ b/drivers/clk/clk_scmi.c @@ -84,26 +84,47 @@ static int scmi_clk_get_num_clock(struct udevice *dev, size_t *num_clocks) static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name, u32 *attr) { + struct scmi_clock_priv *priv = dev_get_priv(dev); struct scmi_clk_attribute_in in = { .clock_id = clkid, }; - struct scmi_clk_attribute_out out; - struct scmi_msg msg = { - .protocol_id = SCMI_PROTOCOL_ID_CLOCK, - .message_id = SCMI_CLOCK_ATTRIBUTES, - .in_msg = (u8 *)&in, - .in_msg_sz = sizeof(in), - .out_msg = (u8 *)&out, - .out_msg_sz = sizeof(out), - }; int ret; - ret = devm_scmi_process_msg(dev, &msg); - if (ret) - return ret; - - *name = strdup(out.clock_name); - *attr = out.attributes; + if (priv->version >= 0x20000) { + struct scmi_clk_attribute_out_v2 out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_CLOCK, + .message_id = SCMI_CLOCK_ATTRIBUTES, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + *name = strdup(out.clock_name); + *attr = out.attributes; + } else { + struct scmi_clk_attribute_out out; + struct scmi_msg msg = { + .protocol_id = SCMI_PROTOCOL_ID_CLOCK, + .message_id = SCMI_CLOCK_ATTRIBUTES, + .in_msg = (u8 *)&in, + .in_msg_sz = sizeof(in), + .out_msg = (u8 *)&out, + .out_msg_sz = sizeof(out), + }; + + ret = devm_scmi_process_msg(dev, &msg); + if (ret) + return ret; + + *name = strdup(out.clock_name); + *attr = out.attributes; + } return 0; } @@ -111,7 +132,7 @@ static int scmi_clk_get_attibute(struct udevice *dev, int clkid, char **name, static int scmi_clk_gate(struct clk *clk, int enable) { struct scmi_clk_state_in in = { - .clock_id = clk->id, + .clock_id = clk_get_id(clk), .attributes = enable, }; struct scmi_clk_state_out out; @@ -176,7 +197,7 @@ static int scmi_clk_disable(struct clk *clk) static ulong scmi_clk_get_rate(struct clk *clk) { struct scmi_clk_rate_get_in in = { - .clock_id = clk->id, + .clock_id = clk_get_id(clk), }; struct scmi_clk_rate_get_out out; struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, @@ -198,7 +219,7 @@ static ulong scmi_clk_get_rate(struct clk *clk) static ulong __scmi_clk_set_rate(struct clk *clk, ulong rate) { struct scmi_clk_rate_set_in in = { - .clock_id = clk->id, + .clock_id = clk_get_id(clk), .flags = SCMI_CLK_RATE_ROUND_CLOSEST, .rate_lsb = (u32)rate, .rate_msb = (u32)((u64)rate >> 32), @@ -257,6 +278,9 @@ static int scmi_clk_probe(struct udevice *dev) if (!CONFIG_IS_ENABLED(CLK_CCF)) return 0; + ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_CLOCK, + &priv->version); + /* register CCF children: CLK UCLASS, no probed again */ if (device_get_uclass_id(dev->parent) == UCLASS_CLK) return 0; @@ -289,7 +313,7 @@ static int scmi_clk_probe(struct udevice *dev) return ret; } - clk_dm(i, &clk_scmi->clk); + dev_clk_dm(dev, i, &clk_scmi->clk); if (CLK_HAS_RESTRICTIONS(attributes)) { u32 perm; diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index d17a54fb9b3..74d5fe73f94 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -14,6 +14,14 @@ config CLK_IMX6Q help This enables DM/DTS support for clock driver in i.MX6Q platforms. +config CLK_IMX6UL + bool "Clock support for i.MX6UL" + depends on ARCH_MX6 + select CLK + select CLK_CCF + help + This enables DM/DTS support for clock driver in i.MX6UL platforms. + config CLK_IMX8 bool "Clock support for i.MX8" depends on ARCH_IMX8 diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index a89ee7acb12..b10221a195c 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_$(PHASE_)CLK_CCF) += clk-gate2.o clk-pllv3.o clk-pfd.o obj-$(CONFIG_$(PHASE_)CLK_IMX6Q) += clk-imx6q.o +obj-$(CONFIG_$(PHASE_)CLK_IMX6UL) += clk-imx6ul.o obj-$(CONFIG_CLK_IMX8) += clk-imx8.o ifdef CONFIG_CLK_IMX8 diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c index 81e19d393cf..b3926564a22 100644 --- a/drivers/clk/imx/clk-fracn-gppll.c +++ b/drivers/clk/imx/clk-fracn-gppll.c @@ -10,6 +10,7 @@ #include <dm/devres.h> #include <linux/bitfield.h> #include <linux/bitops.h> +#include <linux/bug.h> #include <linux/clk-provider.h> #include <linux/delay.h> #include <linux/err.h> diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c new file mode 100644 index 00000000000..32fb949ffbc --- /dev/null +++ b/drivers/clk/imx/clk-imx6ul.c @@ -0,0 +1,289 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2025 Amarula Solutions Software Engineering + * Michael Trimarchi, Amarula Solutions Software Engineering, michael@amarulasolutions.com + */ + +#include <clk-uclass.h> +#include <dm.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <dt-bindings/clock/imx6ul-clock.h> + +#include "clk.h" + +static int imx6ul_clk_request(struct clk *clk) +{ + debug("%s: request clk id %ld\n", __func__, clk->id); + + if (clk->id < IMX6UL_CLK_DUMMY || clk->id >= IMX6UL_CLK_END) { + printf("%s: Invalid clk ID #%lu\n", __func__, clk->id); + return -EINVAL; + } + + return 0; +} + +static struct clk_ops imx6ul_clk_ops = { + .request = imx6ul_clk_request, + .set_rate = ccf_clk_set_rate, + .get_rate = ccf_clk_get_rate, + .enable = ccf_clk_enable, + .disable = ccf_clk_disable, +}; + +static const char *const pll_bypass_src_sels[] = { "osc", "dummy", }; +static const char *const pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", }; +static const char *const bch_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *const gpmi_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; + +static const char *const enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", + "pll3_pfd3_454m", "dummy", "dummy", "dummy", }; +static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *const periph_sels[] = { "periph_pre", "periph_clk2", }; +static const char *const periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", + "pll4_audio_div", }; +static const char *const periph_clk2_sels[] = { "pll3_usb_otg", "osc", "pll2_bypass_src", }; +static const char *const periph2_clk2_sels[] = { "pll3_usb_otg", "osc", }; +static const char *const perclk_sels[] = { "ipg", "osc", }; + +static const char *const periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", + "pll2_198m", }; +static const char *const uart_sels[] = { "pll3_80m", "osc", }; +static const char *const ecspi_sels[] = { "pll3_60m", "osc", }; + +static int imx6ul_clk_probe(struct udevice *dev) +{ + struct clk osc_clk; + void *base; + int ret; + + /* Anatop clocks */ + base = (void *)ANATOP_BASE_ADDR; + + clk_dm(IMX6UL_CLK_DUMMY, clk_register_fixed_rate(NULL, "dummy", 0)); + + ret = clk_get_by_name(dev, "osc", &osc_clk); + if (ret) + return ret; + + clk_dm(IMX6UL_CLK_OSC, dev_get_clk_ptr(osc_clk.dev)); + + clk_dm(IMX6UL_CLK_PLL2, + imx_clk_pllv3(dev, IMX_PLLV3_GENERIC, "pll2_bus", "osc", + base + 0x30, 0x1)); + clk_dm(IMX6UL_CLK_PLL3, + imx_clk_pllv3(dev, IMX_PLLV3_USB, "pll3", "osc", + base + 0x10, 0x3)); + clk_dm(IMX6UL_PLL3_BYPASS_SRC, + imx_clk_mux(dev, "pll3_bypass_src", base + 0x10, 14, 1, + pll_bypass_src_sels, + ARRAY_SIZE(pll_bypass_src_sels))); + clk_dm(IMX6UL_PLL3_BYPASS, + imx_clk_mux_flags(dev, "pll3_bypass", base + 0x10, 16, 1, + pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMX6UL_CLK_PLL3_USB_OTG, + imx_clk_gate(dev, "pll3_usb_otg", "pll3_bypass", base + 0x10, + 13)); + clk_dm(IMX6UL_CLK_PLL3_80M, + imx_clk_fixed_factor(dev, "pll3_80m", "pll3_usb_otg", 1, 6)); + clk_dm(IMX6UL_CLK_PLL3_60M, + imx_clk_fixed_factor(dev, "pll3_60m", "pll3_usb_otg", 1, 8)); + clk_dm(IMX6UL_CLK_PLL2_PFD0, + imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0)); + clk_dm(IMX6UL_CLK_PLL2_PFD1, + imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1)); + clk_dm(IMX6UL_CLK_PLL2_PFD2, + imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2)); + clk_dm(IMX6UL_CLK_PLL2_PFD3, + imx_clk_pfd("pll2_pfd3_396m", "pll2_bus", base + 0x100, 3)); + clk_dm(IMX6UL_CLK_PLL6, + imx_clk_pllv3(dev, IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, + 0x3)); + clk_dm(IMX6UL_CLK_PLL6_ENET, + imx_clk_gate(dev, "pll6_enet", "pll6", base + 0xe0, 13)); + + /* CCM clocks */ + base = dev_read_addr_ptr(dev); + if (!base) + return -EINVAL; + + clk_dm(IMX6UL_CLK_GPMI_SEL, + imx_clk_mux(dev, "gpmi_sel", base + 0x1c, 19, 1, gpmi_sels, + ARRAY_SIZE(gpmi_sels))); + clk_dm(IMX6UL_CLK_BCH_SEL, + imx_clk_mux(dev, "bch_sel", base + 0x1c, 18, 1, bch_sels, + ARRAY_SIZE(bch_sels))); + clk_dm(IMX6UL_CLK_USDHC1_SEL, + imx_clk_mux(dev, "usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, + ARRAY_SIZE(usdhc_sels))); + clk_dm(IMX6UL_CLK_USDHC2_SEL, + imx_clk_mux(dev, "usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, + ARRAY_SIZE(usdhc_sels))); + clk_dm(IMX6UL_CLK_ECSPI_SEL, + imx_clk_mux(dev, "ecspi_sel", base + 0x38, 18, 1, ecspi_sels, + ARRAY_SIZE(ecspi_sels))); + clk_dm(IMX6UL_CLK_UART_SEL, + imx_clk_mux(dev, "uart_sel", base + 0x24, 6, 1, uart_sels, + ARRAY_SIZE(uart_sels))); + clk_dm(IMX6UL_CLK_ENFC_SEL, + imx_clk_mux(dev, "enfc_sel", base + 0x2c, 15, 3, enfc_sels, + ARRAY_SIZE(enfc_sels))); + clk_dm(IMX6UL_CLK_PERCLK_SEL, + imx_clk_mux(dev, "perclk_sel", base + 0x1c, 6, 1, perclk_sels, + ARRAY_SIZE(perclk_sels))); + clk_dm(IMX6UL_CLK_PERIPH_PRE, + imx_clk_mux(dev, "periph_pre", base + 0x18, 18, 2, + periph_pre_sels, ARRAY_SIZE(periph_pre_sels))); + clk_dm(IMX6UL_CLK_PERIPH2_PRE, + imx_clk_mux(dev, "periph2_pre", base + 0x18, 21, 2, + periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels))); + clk_dm(IMX6UL_CLK_PERIPH_CLK2_SEL, + imx_clk_mux(dev, "periph_clk2_sel", base + 0x18, 12, 2, + periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels))); + clk_dm(IMX6UL_CLK_PERIPH2_CLK2_SEL, + imx_clk_mux(dev, "periph2_clk2_sel", base + 0x18, 20, 1, + periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels))); + clk_dm(IMX6UL_CLK_PERIPH, + imx_clk_busy_mux(dev, "periph", base + 0x14, 25, 1, base + 0x48, + 5, periph_sels, ARRAY_SIZE(periph_sels))); + clk_dm(IMX6UL_CLK_AHB, + imx_clk_busy_divider(dev, "ahb", "periph", base + 0x14, 10, 3, + base + 0x48, 1)); + clk_dm(IMX6UL_CLK_PERIPH_CLK2, + imx_clk_divider(dev, "periph_clk2", "periph_clk2_sel", + base + 0x14, 27, 3)); + clk_dm(IMX6UL_CLK_PERIPH2_CLK2, + imx_clk_divider(dev, "periph2_clk2", "periph2_clk2_sel", + base + 0x14, 0, 3)); + clk_dm(IMX6UL_CLK_IPG, + imx_clk_divider(dev, "ipg", "ahb", base + 0x14, 8, 2)); + clk_dm(IMX6UL_CLK_ENFC_PRED, + imx_clk_divider(dev, "enfc_pred", "enfc_sel", base + 0x2c, 18, + 3)); + clk_dm(IMX6UL_CLK_ENFC_PODF, + imx_clk_divider(dev, "enfc_podf", "enfc_pred", base + 0x2c, 21, + 6)); + clk_dm(IMX6UL_CLK_GPMI_PODF, + imx_clk_divider(dev, "gpmi_podf", "gpmi_sel", base + 0x24, 22, + 3)); + clk_dm(IMX6UL_CLK_BCH_PODF, + imx_clk_divider(dev, "bch_podf", "bch_sel", base + 0x24, 19, 3)); + clk_dm(IMX6UL_CLK_PERCLK, + imx_clk_divider(dev, "perclk", "perclk_sel", base + 0x1c, 0, 6)); + clk_dm(IMX6UL_CLK_UART_PODF, + imx_clk_divider(dev, "uart_podf", "uart_sel", base + 0x24, 0, + 6)); + clk_dm(IMX6UL_CLK_USDHC1_PODF, + imx_clk_divider(dev, "usdhc1_podf", "usdhc1_sel", base + 0x24, + 11, 3)); + clk_dm(IMX6UL_CLK_USDHC2_PODF, + imx_clk_divider(dev, "usdhc2_podf", "usdhc2_sel", base + 0x24, + 16, 3)); + clk_dm(IMX6UL_CLK_ECSPI_PODF, + imx_clk_divider(dev, "ecspi_podf", "ecspi_sel", base + 0x38, 19, + 6)); + + clk_dm(IMX6UL_CLK_APBHDMA, + imx_clk_gate2(dev, "apbh_dma", "bch_podf", base + 0x68, 4)); + clk_dm(IMX6UL_CLK_ECSPI1, + imx_clk_gate2(dev, "ecspi1", "ecspi_podf", base + 0x6c, 0)); + clk_dm(IMX6UL_CLK_ECSPI2, + imx_clk_gate2(dev, "ecspi2", "ecspi_podf", base + 0x6c, 2)); + clk_dm(IMX6UL_CLK_ECSPI3, + imx_clk_gate2(dev, "ecspi3", "ecspi_podf", base + 0x6c, 4)); + clk_dm(IMX6UL_CLK_ECSPI4, + imx_clk_gate2(dev, "ecspi4", "ecspi_podf", base + 0x6c, 6)); + + clk_dm(IMX6UL_CLK_USBOH3, + imx_clk_gate2(dev, "usboh3", "ipg", base + 0x80, 0)); + clk_dm(IMX6UL_CLK_USDHC1, + imx_clk_gate2(dev, "usdhc1", "usdhc1_podf", base + 0x80, 2)); + clk_dm(IMX6UL_CLK_USDHC2, + imx_clk_gate2(dev, "usdhc2", "usdhc2_podf", base + 0x80, 4)); + + clk_dm(IMX6UL_CLK_UART1_IPG, + imx_clk_gate2(dev, "uart1_ipg", "ipg", base + 0x7c, 24)); + clk_dm(IMX6UL_CLK_UART1_SERIAL, + imx_clk_gate2(dev, "uart1_serial", "uart_podf", base + 0x7c, 24)); + clk_dm(IMX6UL_CLK_UART2_IPG, + imx_clk_gate2(dev, "uart2_ipg", "ipg", base + 0x68, 28)); + clk_dm(IMX6UL_CLK_UART2_SERIAL, + imx_clk_gate2(dev, "uart2_serial", "uart_podf", base + 0x68, 28)); + clk_dm(IMX6UL_CLK_UART3_IPG, + imx_clk_gate2(dev, "uart3_ipg", "ipg", base + 0x6c, 10)); + clk_dm(IMX6UL_CLK_UART3_SERIAL, + imx_clk_gate2(dev, "uart3_serial", "uart_podf", base + 0x6c, 10)); + clk_dm(IMX6UL_CLK_UART4_IPG, + imx_clk_gate2(dev, "uart4_ipg", "ipg", base + 0x6c, 24)); + clk_dm(IMX6UL_CLK_UART4_SERIAL, + imx_clk_gate2(dev, "uart4_serial", "uart_podf", base + 0x6c, 24)); + clk_dm(IMX6UL_CLK_UART5_IPG, + imx_clk_gate2(dev, "uart5_ipg", "ipg", base + 0x74, 2)); + clk_dm(IMX6UL_CLK_UART5_SERIAL, + imx_clk_gate2(dev, "uart5_serial", "uart_podf", base + 0x74, 2)); + clk_dm(IMX6UL_CLK_UART6_IPG, + imx_clk_gate2(dev, "uart6_ipg", "ipg", base + 0x74, 6)); + clk_dm(IMX6UL_CLK_UART6_SERIAL, + imx_clk_gate2(dev, "uart6_serial", "uart_podf", base + 0x74, 6)); + clk_dm(IMX6UL_CLK_UART7_IPG, + imx_clk_gate2(dev, "uart7_ipg", "ipg", base + 0x7c, 26)); + clk_dm(IMX6UL_CLK_UART7_SERIAL, + imx_clk_gate2(dev, "uart7_serial", "uart_podf", base + 0x7c, 26)); + clk_dm(IMX6UL_CLK_UART8_IPG, + imx_clk_gate2(dev, "uart8_ipg", "ipg", base + 0x80, 14)); + clk_dm(IMX6UL_CLK_UART8_SERIAL, + imx_clk_gate2(dev, "uart8_serial", "uart_podf", base + 0x80, 14)); + +#if CONFIG_IS_ENABLED(NAND_MXS) + clk_dm(IMX6UL_CLK_PER_BCH, + imx_clk_gate2(dev, "per_bch", "bch_podf", base + 0x78, 12)); + clk_dm(IMX6UL_CLK_GPMI_BCH_APB, + imx_clk_gate2(dev, "gpmi_bch_apb", "bch_podf", base + 0x78, 24)); + clk_dm(IMX6UL_CLK_GPMI_BCH, + imx_clk_gate2(dev, "gpmi_bch", "gpmi_podf", base + 0x78, 26)); + clk_dm(IMX6UL_CLK_GPMI_IO, + imx_clk_gate2(dev, "gpmi_io", "enfc_podf", base + 0x78, 28)); + clk_dm(IMX6UL_CLK_GPMI_APB, + imx_clk_gate2(dev, "gpmi_apb", "bch_podf", base + 0x78, 30)); +#endif + + clk_dm(IMX6UL_CLK_I2C1, + imx_clk_gate2(dev, "i2c1", "perclk", base + 0x70, 6)); + clk_dm(IMX6UL_CLK_I2C2, + imx_clk_gate2(dev, "i2c2", "perclk", base + 0x70, 8)); + clk_dm(IMX6UL_CLK_I2C3, + imx_clk_gate2(dev, "i2c3", "perclk", base + 0x70, 10)); + clk_dm(IMX6UL_CLK_PWM1, + imx_clk_gate2(dev, "pwm1", "perclk", base + 0x78, 16)); + + clk_dm(IMX6UL_CLK_ENET, + imx_clk_gate2(dev, "enet", "ipg", base + 0x6c, 10)); + clk_dm(IMX6UL_CLK_ENET_REF, + imx_clk_fixed_factor(dev, "enet_ref", "pll6_enet", 1, 1)); + + struct clk *clk, *clk1; + + clk_get_by_id(IMX6UL_CLK_ENFC_SEL, &clk); + clk_get_by_id(IMX6UL_CLK_PLL2_PFD2, &clk1); + + clk_set_parent(clk, clk1); + + return 0; +} + +static const struct udevice_id imx6ul_clk_ids[] = { + { .compatible = "fsl,imx6ul-ccm" }, + { }, +}; + +U_BOOT_DRIVER(imx6ul_clk) = { + .name = "clk_imx6ul", + .id = UCLASS_CLK, + .of_match = imx6ul_clk_ids, + .ops = &imx6ul_clk_ops, + .probe = imx6ul_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/mediatek/clk-mt7981.c b/drivers/clk/mediatek/clk-mt7981.c index 60814652322..6130c93d5e6 100644 --- a/drivers/clk/mediatek/clk-mt7981.c +++ b/drivers/clk/mediatek/clk-mt7981.c @@ -566,7 +566,7 @@ U_BOOT_DRIVER(mtk_clk_apmixedsys) = { .of_match = mt7981_fixed_pll_compat, .probe = mt7981_fixed_pll_probe, .priv_auto = sizeof(struct mtk_clk_priv), - .ops = &mtk_clk_topckgen_ops, + .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt7986.c b/drivers/clk/mediatek/clk-mt7986.c index f9d6f9c1749..cf298af644c 100644 --- a/drivers/clk/mediatek/clk-mt7986.c +++ b/drivers/clk/mediatek/clk-mt7986.c @@ -573,7 +573,7 @@ U_BOOT_DRIVER(mtk_clk_apmixedsys) = { .of_match = mt7986_fixed_pll_compat, .probe = mt7986_fixed_pll_probe, .priv_auto = sizeof(struct mtk_clk_priv), - .ops = &mtk_clk_topckgen_ops, + .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt7987.c b/drivers/clk/mediatek/clk-mt7987.c index 173686a38e8..b662d680b15 100644 --- a/drivers/clk/mediatek/clk-mt7987.c +++ b/drivers/clk/mediatek/clk-mt7987.c @@ -67,7 +67,7 @@ U_BOOT_DRIVER(mtk_clk_apmixedsys) = { .of_match = mt7987_fixed_pll_compat, .probe = mt7987_fixed_pll_probe, .priv_auto = sizeof(struct mtk_clk_priv), - .ops = &mtk_clk_topckgen_ops, + .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mt7988.c b/drivers/clk/mediatek/clk-mt7988.c index 73fd9c6bea6..c6da42f970b 100644 --- a/drivers/clk/mediatek/clk-mt7988.c +++ b/drivers/clk/mediatek/clk-mt7988.c @@ -830,7 +830,7 @@ U_BOOT_DRIVER(mtk_clk_apmixedsys) = { .of_match = mt7988_fixed_pll_compat, .probe = mt7988_fixed_pll_probe, .priv_auto = sizeof(struct mtk_clk_priv), - .ops = &mtk_clk_topckgen_ops, + .ops = &mtk_clk_fixed_pll_ops, .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 66683aeb2d7..f91777e968a 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -47,6 +47,11 @@ static int mtk_clk_get_id(struct clk *clk) return id; } +static int mtk_dummy_enable(struct clk *clk) +{ + return 0; +} + static int mtk_gate_enable(void __iomem *base, const struct mtk_gate *gate) { u32 bit = BIT(gate->shift); @@ -752,6 +757,12 @@ const struct clk_ops mtk_clk_apmixedsys_ops = { .get_rate = mtk_apmixedsys_get_rate, }; +const struct clk_ops mtk_clk_fixed_pll_ops = { + .enable = mtk_dummy_enable, + .disable = mtk_dummy_enable, + .get_rate = mtk_topckgen_get_rate, +}; + const struct clk_ops mtk_clk_topckgen_ops = { .enable = mtk_clk_mux_enable, .disable = mtk_clk_mux_disable, diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index c1d9901c10b..4ef1341aea6 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -283,6 +283,7 @@ struct mtk_cg_priv { }; extern const struct clk_ops mtk_clk_apmixedsys_ops; +extern const struct clk_ops mtk_clk_fixed_pll_ops; extern const struct clk_ops mtk_clk_topckgen_ops; extern const struct clk_ops mtk_clk_infrasys_ops; extern const struct clk_ops mtk_clk_gate_ops; diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index 6a53f900a9e..b7bd9c9a342 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -23,10 +23,7 @@ #define APCS_GPLL_ENA_VOTE (0x45000) #define APCS_CLOCK_BRANCH_ENA_VOTE (0x45004) -#define SDCC_BCR(n) ((n * 0x1000) + 0x41000) -#define SDCC_CMD_RCGR(n) (((n + 1) * 0x1000) + 0x41004) -#define SDCC_APPS_CBCR(n) ((n * 0x1000) + 0x41018) -#define SDCC_AHB_CBCR(n) ((n * 0x1000) + 0x4101C) +#define SDCC_CMD_RCGR(n) (((n) * 0x1000) + 0x42004) /* BLSP1 AHB clock (root clock for BLSP) */ #define BLSP1_AHB_CBCR 0x1008 @@ -54,9 +51,13 @@ static struct vote_clk gcc_blsp1_ahb_clk = { }; static const struct gate_clk apq8016_clks[] = { - GATE_CLK(GCC_PRNG_AHB_CLK, 0x45004, BIT(8)), - GATE_CLK(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0)), - GATE_CLK(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0)), + GATE_CLK_POLLED(GCC_PRNG_AHB_CLK, 0x45004, BIT(8), 0x13004), + GATE_CLK_POLLED(GCC_SDCC1_AHB_CLK, 0x4201c, BIT(0), 0x4201c), + GATE_CLK_POLLED(GCC_SDCC1_APPS_CLK, 0x42018, BIT(0), 0x42018), + GATE_CLK_POLLED(GCC_SDCC2_AHB_CLK, 0x4301c, BIT(0), 0x4301c), + GATE_CLK_POLLED(GCC_SDCC2_APPS_CLK, 0x43018, BIT(0), 0x43018), + GATE_CLK_POLLED(GCC_USB_HS_AHB_CLK, 0x41008, BIT(0), 0x41008), + GATE_CLK_POLLED(GCC_USB_HS_SYSTEM_CLK, 0x41004, BIT(0), 0x41004), }; /* SDHCI */ @@ -67,12 +68,10 @@ static int apq8016_clk_init_sdc(struct msm_clk_priv *priv, int slot, uint rate) if (rate == 200000000) div = 4; - clk_enable_cbc(priv->base + SDCC_AHB_CBCR(slot)); /* 800Mhz/div, gpll0 */ clk_rcg_set_rate_mnd(priv->base, SDCC_CMD_RCGR(slot), div, 0, 0, CFG_CLK_SRC_GPLL0, 8); clk_enable_gpll0(priv->base, &gpll0_vote_clk); - clk_enable_cbc(priv->base + SDCC_APPS_CBCR(slot)); return rate; } diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index 7687bbe6a23..6b46d9db744 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -74,6 +74,33 @@ void clk_enable_vote_clk(phys_addr_t base, const struct vote_clk *vclk) } while ((val != BRANCH_ON_VAL) && (val != BRANCH_NOC_FSM_ON_VAL)); } +int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) +{ + if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) { + log_err("gcc@%#08llx: unknown clock ID %lu!\n", + priv->base, id); + return -ENOENT; + } + + setbits_le32(priv->base + priv->data->clks[id].reg, priv->data->clks[id].en_val); + if (priv->data->clks[id].cbcr_reg) { + unsigned int count; + u32 val; + + for (count = 0; count < 200; count++) { + val = readl(priv->base + priv->data->clks[id].cbcr_reg); + val &= BRANCH_CHECK_MASK; + if (val == BRANCH_ON_VAL || val == BRANCH_NOC_FSM_ON_VAL) + break; + udelay(1); + } + if (WARN(count == 200, "WARNING: Clock @ %#lx [%#010x] stuck at off\n", + priv->data->clks[id].cbcr_reg, val)) + return -EBUSY; + } + return 0; +} + #define APPS_CMD_RCGR_UPDATE BIT(0) /* Update clock command via CMD_RCGR */ diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index f43edea2525..1b60882dae4 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -52,13 +52,20 @@ struct freq_tbl { struct gate_clk { uintptr_t reg; u32 en_val; + uintptr_t cbcr_reg; const char *name; }; +/* + * GATE_CLK() is deprecated: Use GATE_CLK_POLLED() instead to ensure the clock + * is running before we start making use of devices or registers. + */ #ifdef DEBUG -#define GATE_CLK(clk, reg, val) [clk] = { reg, val, #clk } +#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, #clk } +#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, #clk } #else -#define GATE_CLK(clk, reg, val) [clk] = { reg, val, NULL } +#define GATE_CLK(clk, reg, val) [clk] = { reg, val, 0, NULL } +#define GATE_CLK_POLLED(clk, en_reg, val, cbcr_reg) [clk] = { en_reg, val, cbcr_reg, NULL } #endif struct qcom_reset_map { @@ -107,19 +114,6 @@ 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 int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) -{ - u32 val; - if (id >= priv->data->num_clks || priv->data->clks[id].reg == 0) { - log_err("gcc@%#08llx: unknown clock ID %lu!\n", - priv->base, id); - return -ENOENT; - } - - val = readl(priv->base + priv->data->clks[id].reg); - writel(val | priv->data->clks[id].en_val, priv->base + priv->data->clks[id].reg); - - return 0; -} +int qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id); #endif diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c index d23041a8026..c8972106d90 100644 --- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c @@ -305,7 +305,7 @@ static const struct mstp_stop_table r8a774a1_mstp_table[] = { { 0xD00C7C1F, 0, 0xD00C7C1F, 0 }, { 0x80000004, 0, 0x80000004, 0 }, { 0x00DF0006, 0, 0x00DF0006, 0 }, - { 0XC5EACCCE, 0, 0XC5EACCCE, 0 }, + { 0xC5EACCCE, 0, 0xC5EACCCE, 0 }, { 0x29E1401C, 0, 0x29E1401C, 0 }, { 0x00009FF1, 0, 0x00009FF1, 0 }, { 0xFC4FDFE0, 0, 0xFC4FDFE0, 0 }, diff --git a/drivers/clk/stm32/Kconfig b/drivers/clk/stm32/Kconfig index c05015efe8b..ea856be1662 100644 --- a/drivers/clk/stm32/Kconfig +++ b/drivers/clk/stm32/Kconfig @@ -36,3 +36,12 @@ config CLK_STM32MP13 help Enable the STM32 clock (RCC) driver. Enable support for manipulating STM32MP13's on-SoC clocks. + +config CLK_STM32MP25 + bool "Enable RCC clock driver for STM32MP25" + depends on ARCH_STM32MP && CLK + default y if STM32MP25X + select CLK_STM32_CORE + help + Enable the STM32 clock (RCC) driver. Enable support for + manipulating STM32MP25's on-SoC clocks. diff --git a/drivers/clk/stm32/Makefile b/drivers/clk/stm32/Makefile index 20afbc3cfce..56adb8a4bbb 100644 --- a/drivers/clk/stm32/Makefile +++ b/drivers/clk/stm32/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_CLK_STM32F) += clk-stm32f.o obj-$(CONFIG_CLK_STM32H7) += clk-stm32h7.o obj-$(CONFIG_CLK_STM32MP1) += clk-stm32mp1.o obj-$(CONFIG_CLK_STM32MP13) += clk-stm32mp13.o +obj-$(CONFIG_CLK_STM32MP25) += clk-stm32mp25.o diff --git a/drivers/clk/stm32/clk-stm32-core.c b/drivers/clk/stm32/clk-stm32-core.c index cad07cc952e..a0ae89d0912 100644 --- a/drivers/clk/stm32/clk-stm32-core.c +++ b/drivers/clk/stm32/clk-stm32-core.c @@ -41,12 +41,13 @@ int stm32_rcc_init(struct udevice *dev, const struct clock_config *cfg = &data->tab_clocks[i]; struct clk *clk = ERR_PTR(-ENOENT); - if (data->check_security && data->check_security(priv->base, cfg)) + if (data->check_security && data->check_security(dev, priv->base, cfg)) continue; if (cfg->setup) { clk = cfg->setup(dev, cfg); - clk->id = cfg->id; + /* set identifier of clock provider*/ + dev_clk_dm(dev, cfg->id, clk); } else { dev_err(dev, "failed to register clock %s\n", cfg->name); return -ENOENT; @@ -69,11 +70,71 @@ ulong clk_stm32_get_rate_by_name(const char *name) return 0; } +static const struct clk_ops *clk_dev_ops(struct udevice *dev) +{ + return (const struct clk_ops *)dev->driver->ops; +} + +static int stm32_clk_endisable(struct clk *clk, bool enable) +{ + const struct clk_ops *ops; + struct clk *c = NULL; + + if (!clk->id || clk_get_by_id(clk->id, &c)) + return -ENOENT; + + ops = clk_dev_ops(c->dev); + if (!ops->enable || !ops->disable) + return 0; + + return enable ? ops->enable(c) : ops->disable(c); +} + +static int stm32_clk_enable(struct clk *clk) +{ + return stm32_clk_endisable(clk, true); +} + +static int stm32_clk_disable(struct clk *clk) +{ + return stm32_clk_endisable(clk, false); +} + +static ulong stm32_clk_get_rate(struct clk *clk) +{ + const struct clk_ops *ops; + struct clk *c = NULL; + + if (!clk->id || clk_get_by_id(clk->id, &c)) + return -ENOENT; + + ops = clk_dev_ops(c->dev); + if (!ops->get_rate) + return -ENOSYS; + + return ops->get_rate(c); +} + +static ulong stm32_clk_set_rate(struct clk *clk, unsigned long clk_rate) +{ + const struct clk_ops *ops; + struct clk *c = NULL; + + if (!clk->id || clk_get_by_id(clk->id, &c)) + return -ENOENT; + + ops = clk_dev_ops(c->dev); + if (!ops->set_rate) + return -ENOSYS; + + return ops->set_rate(c, clk_rate); +} + const struct clk_ops stm32_clk_ops = { - .enable = ccf_clk_enable, - .disable = ccf_clk_disable, - .get_rate = ccf_clk_get_rate, - .set_rate = ccf_clk_set_rate, + .enable = stm32_clk_enable, + .disable = stm32_clk_disable, + .get_rate = stm32_clk_get_rate, + .set_rate = stm32_clk_set_rate, }; #define RCC_MP_ENCLRR_OFFSET 4 diff --git a/drivers/clk/stm32/clk-stm32-core.h b/drivers/clk/stm32/clk-stm32-core.h index f9ef0702005..baf2a996ef3 100644 --- a/drivers/clk/stm32/clk-stm32-core.h +++ b/drivers/clk/stm32/clk-stm32-core.h @@ -127,7 +127,7 @@ struct stm32_clock_match_data { unsigned int num_clocks; const struct clock_config *tab_clocks; const struct clk_stm32_clock_data *clock_data; - int (*check_security)(void __iomem *base, + int (*check_security)(struct udevice *dev, void __iomem *base, const struct clock_config *cfg); }; @@ -144,6 +144,7 @@ struct stm32mp_rcc_priv { void __iomem *base; u8 *gate_cpt; const struct clk_stm32_clock_data *data; + struct clk osc_clk[6]; }; int stm32_rcc_init(struct udevice *dev, diff --git a/drivers/clk/stm32/clk-stm32h7.c b/drivers/clk/stm32/clk-stm32h7.c index 6acf2ff0a8f..aa3be414a29 100644 --- a/drivers/clk/stm32/clk-stm32h7.c +++ b/drivers/clk/stm32/clk-stm32h7.c @@ -114,6 +114,7 @@ #define QSPISRC_PER_CK 3 #define PWR_CR3 0x0c +#define PWR_CR3_LDOEN BIT(1) #define PWR_CR3_SCUEN BIT(2) #define PWR_D3CR 0x18 #define PWR_D3CR_VOS_MASK GENMASK(15, 14) @@ -375,7 +376,11 @@ int configure_clocks(struct udevice *dev) clrsetbits_le32(pwr_base + PWR_D3CR, PWR_D3CR_VOS_MASK, VOS_SCALE_1 << PWR_D3CR_VOS_SHIFT); /* Lock supply configuration update */ +#if IS_ENABLED(CONFIG_TARGET_STM32H747_DISCO) + clrbits_le32(pwr_base + PWR_CR3, PWR_CR3_LDOEN); +#else clrbits_le32(pwr_base + PWR_CR3, PWR_CR3_SCUEN); +#endif while (!(readl(pwr_base + PWR_D3CR) & PWR_D3CR_VOSREADY)) ; diff --git a/drivers/clk/stm32/clk-stm32mp1.c b/drivers/clk/stm32/clk-stm32mp1.c index 9cb69a01f7f..823ce132d0b 100644 --- a/drivers/clk/stm32/clk-stm32mp1.c +++ b/drivers/clk/stm32/clk-stm32mp1.c @@ -117,7 +117,7 @@ DECLARE_GLOBAL_DATA_PTR; #define RCC_DSICKSELR 0x924 #define RCC_ADCCKSELR 0x928 #define RCC_MP_APB1ENSETR 0xA00 -#define RCC_MP_APB2ENSETR 0XA08 +#define RCC_MP_APB2ENSETR 0xA08 #define RCC_MP_APB3ENSETR 0xA10 #define RCC_MP_AHB2ENSETR 0xA18 #define RCC_MP_AHB3ENSETR 0xA20 diff --git a/drivers/clk/stm32/clk-stm32mp13.c b/drivers/clk/stm32/clk-stm32mp13.c index 362dba10252..b4d0890f902 100644 --- a/drivers/clk/stm32/clk-stm32mp13.c +++ b/drivers/clk/stm32/clk-stm32mp13.c @@ -3,7 +3,6 @@ * Copyright (C) 2022, STMicroelectronics - All Rights Reserved * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics. */ - #define LOG_CATEGORY UCLASS_CLK #include <clk-uclass.h> @@ -12,6 +11,22 @@ #include <asm/io.h> #include <dt-bindings/clock/stm32mp13-clks.h> #include <linux/clk-provider.h> +#include <dt-bindings/clock/stm32mp13-clksrc.h> +#include <asm/arch/sys_proto.h> +#include <asm/global_data.h> +#include <clk-uclass.h> +#include <div64.h> +#include <dm/device_compat.h> +#include <init.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <regmap.h> +#include <spl.h> +#include <syscon.h> +#include <time.h> +#include <vsprintf.h> +#include <asm/arch/sys_proto.h> #include "clk-stm32-core.h" #include "stm32mp13_rcc.h" @@ -130,46 +145,6 @@ static const char * const usbphy_src[] = { "ck_hse", "pll4_r", "clk-hse-div2" }; -enum enum_mux_cfg { - MUX_I2C12, - MUX_LPTIM45, - MUX_SPI23, - MUX_UART35, - MUX_UART78, - MUX_ADC1, - MUX_ADC2, - MUX_DCMIPP, - MUX_ETH1, - MUX_ETH2, - MUX_FDCAN, - MUX_FMC, - MUX_I2C3, - MUX_I2C4, - MUX_I2C5, - MUX_LPTIM1, - MUX_LPTIM2, - MUX_LPTIM3, - MUX_QSPI, - MUX_RNG1, - MUX_SAES, - MUX_SAI1, - MUX_SAI2, - MUX_SDMMC1, - MUX_SDMMC2, - MUX_SPDIF, - MUX_SPI1, - MUX_SPI4, - MUX_SPI5, - MUX_STGEN, - MUX_UART1, - MUX_UART2, - MUX_UART4, - MUX_UART6, - MUX_USBO, - MUX_USBPHY, - MUX_MCO1, - MUX_MCO2 -}; #define MUX_CFG(id, src, _offset, _shift, _witdh) \ [id] = { \ @@ -471,15 +446,6 @@ static const struct clk_div_table ck_trace_div_table[] = { { 0 }, }; -enum enum_div_cfg { - DIV_MCO1, - DIV_MCO2, - DIV_TRACE, - DIV_ETH1PTP, - DIV_ETH2PTP, - LAST_DIV -}; - #define DIV_CFG(id, _offset, _shift, _width, _flags, _table) \ [id] = { \ .reg_off = _offset, \ @@ -489,7 +455,7 @@ enum enum_div_cfg { .table = _table, \ } -static const struct stm32_div_cfg stm32mp13_dividers[LAST_DIV] = { +static const struct stm32_div_cfg stm32mp13_dividers[] = { DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL), DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL), DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table), @@ -497,7 +463,7 @@ static const struct stm32_div_cfg stm32mp13_dividers[LAST_DIV] = { DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL), }; -struct clk_stm32_securiy { +struct clk_stm32_security { u16 offset; u8 bit_idx; }; @@ -566,7 +532,8 @@ enum securit_clk { .bit_idx = _bit_idx, \ } -static const struct clk_stm32_securiy stm32mp13_security[] = { +#ifdef CONFIG_TFABOOT +static const struct clk_stm32_security stm32mp13_security[] = { SECF(SECF_LPTIM2, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM2SECF), SECF(SECF_LPTIM3, RCC_APB3SECSR, RCC_APB3SECSR_LPTIM3SECF), SECF(SECF_VREF, RCC_APB3SECSR, RCC_APB3SECSR_VREFSECF), @@ -622,6 +589,7 @@ static const struct clk_stm32_securiy stm32mp13_security[] = { SECF(SECF_MCO1, RCC_SECCFGR, RCC_SECCFGR_MCO1SECF), SECF(SECF_MCO2, RCC_SECCFGR, RCC_SECCFGR_MCO2SECF), }; +#endif #define PCLK(_id, _name, _parent, _flags, _gate_id, _sec_id) \ STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id) @@ -635,6 +603,7 @@ static const struct clk_stm32_securiy stm32mp13_security[] = { _gate_id, _mux_id, NO_STM32_DIV) static const struct clock_config stm32mp13_clock_cfg[] = { +#ifndef CONFIG_XPL_BUILD TIMER(TIM2_K, "tim2_k", "timg1_ck", 0, GATE_TIM2, SECF_NONE), TIMER(TIM3_K, "tim3_k", "timg1_ck", 0, GATE_TIM3, SECF_NONE), TIMER(TIM4_K, "tim4_k", "timg1_ck", 0, GATE_TIM4, SECF_NONE), @@ -649,23 +618,28 @@ static const struct clock_config stm32mp13_clock_cfg[] = { TIMER(TIM15_K, "tim15_k", "timg3_ck", 0, GATE_TIM15, SECF_TIM15), TIMER(TIM16_K, "tim16_k", "timg3_ck", 0, GATE_TIM16, SECF_TIM16), TIMER(TIM17_K, "tim17_k", "timg3_ck", 0, GATE_TIM17, SECF_TIM17), +#endif /* Peripheral clocks */ PCLK(SYSCFG, "syscfg", "pclk3", 0, GATE_SYSCFG, SECF_NONE), PCLK(VREF, "vref", "pclk3", 0, GATE_VREF, SECF_VREF), +#ifndef CONFIG_XPL_BUILD PCLK(PMBCTRL, "pmbctrl", "pclk3", 0, GATE_PMBCTRL, SECF_NONE), PCLK(HDP, "hdp", "pclk3", 0, GATE_HDP, SECF_NONE), +#endif PCLK(IWDG2, "iwdg2", "pclk4", 0, GATE_IWDG2APB, SECF_NONE), PCLK(STGENRO, "stgenro", "pclk4", 0, GATE_STGENRO, SECF_STGENRO), PCLK(TZPC, "tzpc", "pclk5", 0, GATE_TZC, SECF_TZC), PCLK(IWDG1, "iwdg1", "pclk5", 0, GATE_IWDG1APB, SECF_IWDG1), PCLK(BSEC, "bsec", "pclk5", 0, GATE_BSEC, SECF_BSEC), +#ifndef CONFIG_XPL_BUILD PCLK(DMA1, "dma1", "ck_mlahb", 0, GATE_DMA1, SECF_NONE), PCLK(DMA2, "dma2", "ck_mlahb", 0, GATE_DMA2, SECF_NONE), PCLK(DMAMUX1, "dmamux1", "ck_mlahb", 0, GATE_DMAMUX1, SECF_NONE), PCLK(DMAMUX2, "dmamux2", "ck_mlahb", 0, GATE_DMAMUX2, SECF_DMAMUX2), PCLK(ADC1, "adc1", "ck_mlahb", 0, GATE_ADC1, SECF_ADC1), PCLK(ADC2, "adc2", "ck_mlahb", 0, GATE_ADC2, SECF_ADC2), +#endif PCLK(GPIOA, "gpioa", "pclk4", 0, GATE_GPIOA, SECF_NONE), PCLK(GPIOB, "gpiob", "pclk4", 0, GATE_GPIOB, SECF_NONE), PCLK(GPIOC, "gpioc", "pclk4", 0, GATE_GPIOC, SECF_NONE), @@ -681,17 +655,23 @@ static const struct clock_config stm32mp13_clock_cfg[] = { PCLK(HASH1, "hash1", "ck_axi", 0, GATE_HASH1, SECF_HASH1), PCLK(BKPSRAM, "bkpsram", "ck_axi", 0, GATE_BKPSRAM, SECF_BKPSRAM), PCLK(MDMA, "mdma", "ck_axi", 0, GATE_MDMA, SECF_NONE), +#ifndef CONFIG_XPL_BUILD PCLK(ETH1TX, "eth1tx", "ck_axi", 0, GATE_ETH1TX, SECF_ETH1TX), PCLK(ETH1RX, "eth1rx", "ck_axi", 0, GATE_ETH1RX, SECF_ETH1RX), PCLK(ETH1MAC, "eth1mac", "ck_axi", 0, GATE_ETH1MAC, SECF_ETH1MAC), PCLK(ETH2TX, "eth2tx", "ck_axi", 0, GATE_ETH2TX, SECF_ETH2TX), PCLK(ETH2RX, "eth2rx", "ck_axi", 0, GATE_ETH2RX, SECF_ETH2RX), PCLK(ETH2MAC, "eth2mac", "ck_axi", 0, GATE_ETH2MAC, SECF_ETH2MAC), +#endif PCLK(CRC1, "crc1", "ck_axi", 0, GATE_CRC1, SECF_NONE), +#ifndef CONFIG_XPL_BUILD PCLK(USBH, "usbh", "ck_axi", 0, GATE_USBH, SECF_NONE), +#endif PCLK(DDRPERFM, "ddrperfm", "pclk4", 0, GATE_DDRPERFM, SECF_NONE), +#ifndef CONFIG_XPL_BUILD PCLK(ETH1STP, "eth1stp", "ck_axi", 0, GATE_ETH1STP, SECF_ETH1STP), PCLK(ETH2STP, "eth2stp", "ck_axi", 0, GATE_ETH2STP, SECF_ETH2STP), +#endif /* Kernel clocks */ KCLK(SDMMC1_K, "sdmmc1_k", 0, GATE_SDMMC1, MUX_SDMMC1, SECF_SDMMC1), @@ -702,8 +682,10 @@ static const struct clock_config stm32mp13_clock_cfg[] = { KCLK(SPI3_K, "spi3_k", 0, GATE_SPI3, MUX_SPI23, SECF_NONE), KCLK(I2C1_K, "i2c1_k", 0, GATE_I2C1, MUX_I2C12, SECF_NONE), KCLK(I2C2_K, "i2c2_k", 0, GATE_I2C2, MUX_I2C12, SECF_NONE), +#ifndef CONFIG_XPL_BUILD KCLK(LPTIM4_K, "lptim4_k", 0, GATE_LPTIM4, MUX_LPTIM45, SECF_NONE), KCLK(LPTIM5_K, "lptim5_k", 0, GATE_LPTIM5, MUX_LPTIM45, SECF_NONE), +#endif KCLK(USART3_K, "usart3_k", 0, GATE_USART3, MUX_UART35, SECF_NONE), KCLK(UART5_K, "uart5_k", 0, GATE_UART5, MUX_UART35, SECF_NONE), KCLK(UART7_K, "uart7_k", 0, GATE_UART7, MUX_UART78, SECF_NONE), @@ -711,20 +693,29 @@ static const struct clock_config stm32mp13_clock_cfg[] = { KCLK(RNG1_K, "rng1_k", 0, GATE_RNG1, MUX_RNG1, SECF_RNG1), KCLK(USBPHY_K, "usbphy_k", 0, GATE_USBPHY, MUX_USBPHY, SECF_USBPHY), KCLK(STGEN_K, "stgen_k", 0, GATE_STGENC, MUX_STGEN, SECF_STGENC), +#ifndef CONFIG_XPL_BUILD KCLK(SPDIF_K, "spdif_k", 0, GATE_SPDIF, MUX_SPDIF, SECF_NONE), +#endif KCLK(SPI1_K, "spi1_k", 0, GATE_SPI1, MUX_SPI1, SECF_NONE), KCLK(SPI4_K, "spi4_k", 0, GATE_SPI4, MUX_SPI4, SECF_SPI4), KCLK(SPI5_K, "spi5_k", 0, GATE_SPI5, MUX_SPI5, SECF_SPI5), +#ifdef CONFIG_TFABOOT KCLK(I2C3_K, "i2c3_k", 0, GATE_I2C3, MUX_I2C3, SECF_I2C3), +#else + KCLK(I2C3_K, "i2c3_k", 0, GATE_I2C3, MUX_I2C3, SECF_NONE), +#endif KCLK(I2C4_K, "i2c4_k", 0, GATE_I2C4, MUX_I2C4, SECF_I2C4), KCLK(I2C5_K, "i2c5_k", 0, GATE_I2C5, MUX_I2C5, SECF_I2C5), +#ifndef CONFIG_XPL_BUILD KCLK(LPTIM1_K, "lptim1_k", 0, GATE_LPTIM1, MUX_LPTIM1, SECF_NONE), KCLK(LPTIM2_K, "lptim2_k", 0, GATE_LPTIM2, MUX_LPTIM2, SECF_LPTIM2), KCLK(LPTIM3_K, "lptim3_k", 0, GATE_LPTIM3, MUX_LPTIM3, SECF_LPTIM3), +#endif KCLK(USART1_K, "usart1_k", 0, GATE_USART1, MUX_UART1, SECF_USART1), KCLK(USART2_K, "usart2_k", 0, GATE_USART2, MUX_UART2, SECF_USART2), KCLK(UART4_K, "uart4_k", 0, GATE_UART4, MUX_UART4, SECF_NONE), KCLK(USART6_K, "uart6_k", 0, GATE_USART6, MUX_UART6, SECF_NONE), +#ifndef CONFIG_XPL_BUILD KCLK(FDCAN_K, "fdcan_k", 0, GATE_FDCAN, MUX_FDCAN, SECF_NONE), KCLK(SAI1_K, "sai1_k", 0, GATE_SAI1, MUX_SAI1, SECF_NONE), KCLK(SAI2_K, "sai2_k", 0, GATE_SAI2, MUX_SAI2, SECF_NONE), @@ -732,7 +723,9 @@ static const struct clock_config stm32mp13_clock_cfg[] = { KCLK(ADC2_K, "adc2_k", 0, GATE_ADC2, MUX_ADC2, SECF_ADC2), KCLK(DCMIPP_K, "dcmipp_k", 0, GATE_DCMIPP, MUX_DCMIPP, SECF_DCMIPP), KCLK(ADFSDM_K, "adfsdm_k", 0, GATE_ADFSDM, MUX_SAI1, SECF_NONE), +#endif KCLK(USBO_K, "usbo_k", 0, GATE_USBO, MUX_USBO, SECF_USBO), +#ifndef CONFIG_XPL_BUILD KCLK(ETH1CK_K, "eth1ck_k", 0, GATE_ETH1CK, MUX_ETH1, SECF_ETH1CK), KCLK(ETH2CK_K, "eth2ck_k", 0, GATE_ETH2CK, MUX_ETH2, SECF_ETH2CK), KCLK(SAES_K, "saes_k", 0, GATE_SAES, MUX_SAES, SECF_SAES), @@ -742,6 +735,7 @@ static const struct clock_config stm32mp13_clock_cfg[] = { GATE_LTDC, SECF_NONE), STM32_GATE(DTS_K, "dts_k", "ck_lse", 0, GATE_DTS, SECF_NONE), +#endif STM32_COMPOSITE(ETH1PTP_K, "eth1ptp_k", CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT, SECF_ETH1CK, @@ -767,16 +761,30 @@ static const struct clock_config stm32mp13_clock_cfg[] = { STM32_COMPOSITE_NOMUX(CK_TRACE, "ck_trace", "ck_axi", CLK_OPS_PARENT_ENABLE, SECF_NONE, GATE_TRACECK, DIV_TRACE), + +#ifdef CONFIG_XPL_BUILD + STM32_GATE(AXIDCG, "axidcg", "ck_axi", CLK_IGNORE_UNUSED, + GATE_AXIDCG, SECF_NONE), + STM32_GATE(DDRC1, "ddrc1", "ck_axi", CLK_IGNORE_UNUSED, + GATE_DDRC1, SECF_NONE), + STM32_GATE(DDRPHYC, "ddrphyc", "pll2_r", CLK_IGNORE_UNUSED, + GATE_DDRPHYC, SECF_NONE), + STM32_GATE(DDRCAPB, "ddrcapb", "pclk4", CLK_IGNORE_UNUSED, + GATE_DDRCAPB, SECF_NONE), + STM32_GATE(DDRPHYCAPB, "ddrphycapb", "pclk4", CLK_IGNORE_UNUSED, + GATE_DDRPHYCAPB, SECF_NONE), +#endif }; -static int stm32mp13_check_security(void __iomem *base, +#ifdef CONFIG_TFABOOT +static int stm32mp13_check_security(struct udevice *dev, void __iomem *base, const struct clock_config *cfg) { int sec_id = cfg->sec_id; int secured = 0; if (sec_id != SECF_NONE) { - const struct clk_stm32_securiy *secf; + const struct clk_stm32_security *secf; secf = &stm32mp13_security[sec_id]; secured = !!(readl(base + secf->offset) & BIT(secf->bit_idx)); @@ -784,6 +792,7 @@ static int stm32mp13_check_security(void __iomem *base, return secured; } +#endif static const struct stm32_clock_match_data stm32mp13_data = { .tab_clocks = stm32mp13_clock_cfg, @@ -794,16 +803,1204 @@ static const struct stm32_clock_match_data stm32mp13_data = { .muxes = stm32mp13_muxes, .dividers = stm32mp13_dividers, }, +#ifdef CONFIG_TFABOOT .check_security = stm32mp13_check_security, +#endif +}; + +#ifndef CONFIG_TFABOOT + +enum stm32mp1_parent_id { +/* + * _HSI, _HSE, _CSI, _LSI, _LSE should not be moved + * they are used as index in osc_clk[] as clock reference + */ + _HSI, + _HSE, + _CSI, + _LSI, + _LSE, + _I2S_CKIN, + NB_OSC, + +/* other parent source */ + _HSI_KER = NB_OSC, + _HSE_KER, + _HSE_KER_DIV2, + _CSI_KER, + _PLL1_P, + _PLL1_Q, + _PLL1_R, + _PLL2_P, + _PLL2_Q, + _PLL2_R, + _PLL3_P, + _PLL3_Q, + _PLL3_R, + _PLL4_P, + _PLL4_Q, + _PLL4_R, + _ACLK, + _PCLK1, + _PCLK2, + _PCLK3, + _PCLK4, + _PCLK5, + _HCLK6, + _HCLK2, + _CK_PER, + _CK_MPU, + _CK_MCU, + _DSI_PHY, + _USB_PHY_48, + _PARENT_NB, + _UNKNOWN_ID = 0xff, +}; + +#if defined(CONFIG_XPL_BUILD) + +#define MAX_HSI_HZ 64000000 + +/* TIMEOUT */ +#define TIMEOUT_200MS 200000 +#define TIMEOUT_1S 1000000 + +/* STGEN registers */ +#define STGENC_CNTCR 0x00 +#define STGENC_CNTSR 0x04 +#define STGENC_CNTCVL 0x08 +#define STGENC_CNTCVU 0x0C +#define STGENC_CNTFID0 0x20 + +#define STGENC_CNTCR_EN BIT(0) + +enum stm32mp1_clksrc_id { + CLKSRC_MPU, + CLKSRC_AXI, + CLKSRC_MLAHB, + CLKSRC_PLL12, + CLKSRC_PLL3, + CLKSRC_PLL4, + CLKSRC_RTC, + CLKSRC_MCO1, + CLKSRC_MCO2, + CLKSRC_NB +}; + +enum stm32mp1_clkdiv_id { + CLKDIV_AXI, + CLKDIV_MLAHB, + CLKDIV_APB1, + CLKDIV_APB2, + CLKDIV_APB3, + CLKDIV_APB4, + CLKDIV_APB5, + CLKDIV_APB6, + CLKDIV_RTC, + CLKDIV_NB +}; + +enum stm32mp1_pll_id { + _PLL1, + _PLL2, + _PLL3, + _PLL4, + _PLL_NB +}; + +enum stm32mp1_div_id { + _DIV_P, + _DIV_Q, + _DIV_R, + _DIV_NB, +}; + +/* define characteristic of PLL according type */ +#define DIVM_MIN 1 +#define DIVM_MAX 63 +#define DIVN_MIN 24 +#define DIVP_MIN 0 +#define DIVP_MAX 127 +#define FRAC_MAX 8192 + +#define PLL2000_VCO_MIN 992000000 +#define PLL2000_VCO_MAX 2000000000 + +enum stm32mp1_pllcfg { + PLLCFG_M, + PLLCFG_N, + PLLCFG_P, + PLLCFG_Q, + PLLCFG_R, + PLLCFG_O, + PLLCFG_NB +}; + +enum stm32mp1_pllcsg { + PLLCSG_MOD_PER, + PLLCSG_INC_STEP, + PLLCSG_SSCG_MODE, + PLLCSG_NB +}; + +enum stm32mp1_plltype { + PLL_800, + PLL_1600, + PLL_2000, + PLL_TYPE_NB +}; + +struct stm32mp1_pll { + u8 refclk_min; + u8 refclk_max; + u8 divn_max; +}; + +#define REFCLK_SIZE 4 +struct stm32mp1_clk_pll { + enum stm32mp1_plltype plltype; + u16 rckxselr; + u16 pllxcfgr1; + u16 pllxcfgr2; + u16 pllxfracr; + u16 pllxcr; + u16 pllxcsgr; + u8 refclk[REFCLK_SIZE]; +}; + +static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { + [PLL_800] = { + .refclk_min = 4, + .refclk_max = 16, + .divn_max = 99, + }, + [PLL_1600] = { + .refclk_min = 8, + .refclk_max = 16, + .divn_max = 199, + }, + [PLL_2000] = { + .refclk_min = 8, + .refclk_max = 16, + .divn_max = 99, + }, +}; + +#define STM32MP1_CLK_PLL(idx, type, off1, off2, off3, off4, off5, off6,\ + p1, p2, p3, p4) \ + [(idx)] = { \ + .plltype = (type), \ + .rckxselr = (off1), \ + .pllxcfgr1 = (off2), \ + .pllxcfgr2 = (off3), \ + .pllxfracr = (off4), \ + .pllxcr = (off5), \ + .pllxcsgr = (off6), \ + .refclk[0] = (p1), \ + .refclk[1] = (p2), \ + .refclk[2] = (p3), \ + .refclk[3] = (p4), \ + } + +static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { + STM32MP1_CLK_PLL(_PLL1, PLL_2000, + RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, + RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, + _HSI, _HSE, _UNKNOWN_ID, _UNKNOWN_ID), + STM32MP1_CLK_PLL(_PLL2, PLL_1600, + RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, + RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, + _HSI, _HSE, _UNKNOWN_ID, _UNKNOWN_ID), + STM32MP1_CLK_PLL(_PLL3, PLL_800, + RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, + RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, + _HSI, _HSE, _CSI, _UNKNOWN_ID), + STM32MP1_CLK_PLL(_PLL4, PLL_800, + RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, + RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, + _HSI, _HSE, _CSI, _I2S_CKIN), }; +static ulong stm32mp1_clk_get_fixed(struct stm32mp_rcc_priv *priv, int idx) +{ + if (idx >= NB_OSC) { + log_debug("clk id %d not found\n", idx); + return 0; + } + + return clk_get_rate(&priv->osc_clk[idx]); +} + +bool stm32mp1_supports_opp(u32 opp_id, u32 cpu_type) +{ + /* 650 MHz is always supported */ + if (opp_id == 1) + return true; + + /* + * 1000 MHz is supported on STM32MP13xDxx and STM32MP13xFxx, + * which all have bit 11 i.e. 0x800 set in CPU ID. + */ + if (opp_id == 2) + return !!(cpu_type & BIT(11)); + + /* Any other OPP is invalid. */ + return false; +} + +__weak void board_vddcore_init(u32 voltage_mv) +{ +} + +/* + * gets OPP parameters (frequency in KHz and voltage in mV) from + * an OPP table subnode. Platform HW support capabilities are also checked. + * Returns 0 on success and a negative FDT error code on failure. + */ +static int stm32mp1_get_opp(u32 cpu_type, ofnode subnode, + u32 *freq_khz, u32 *voltage_mv) +{ + u32 opp_hw; + u64 read_freq_64; + u32 read_voltage_32; + + *freq_khz = 0; + *voltage_mv = 0; + + opp_hw = ofnode_read_u32_default(subnode, "opp-supported-hw", 0); + if (opp_hw) + if (!stm32mp1_supports_opp(opp_hw, cpu_type)) + return -FDT_ERR_BADVALUE; + + read_freq_64 = ofnode_read_u64_default(subnode, "opp-hz", 0) / + 1000ULL; + read_voltage_32 = ofnode_read_u32_default(subnode, "opp-microvolt", 0) / + 1000U; + + if (!read_voltage_32 || !read_freq_64) + return -FDT_ERR_NOTFOUND; + + /* Frequency value expressed in KHz must fit on 32 bits */ + if (read_freq_64 > U32_MAX) + return -FDT_ERR_BADVALUE; + + /* Millivolt value must fit on 16 bits */ + if (read_voltage_32 > U16_MAX) + return -FDT_ERR_BADVALUE; + + *freq_khz = (u32)read_freq_64; + *voltage_mv = read_voltage_32; + + return 0; +} + +/* + * parses OPP table in DT and finds the parameters for the + * highest frequency supported by the HW platform. + * Returns 0 on success and a negative FDT error code on failure. + */ +int stm32mp1_get_max_opp_freq(struct stm32mp_rcc_priv *priv, u64 *freq_hz) +{ + ofnode node, subnode; + int ret; + u32 freq = 0U, voltage = 0U; + u32 cpu_type = get_cpu_type(); + + node = ofnode_by_compatible(ofnode_null(), "operating-points-v2"); + if (!ofnode_valid(node)) + return -FDT_ERR_NOTFOUND; + + ofnode_for_each_subnode(subnode, node) { + unsigned int read_freq; + unsigned int read_voltage; + + ret = stm32mp1_get_opp(cpu_type, subnode, + &read_freq, &read_voltage); + if (ret) + continue; + + if (read_freq > freq) { + freq = read_freq; + voltage = read_voltage; + } + } + + if (!freq || !voltage) + return -FDT_ERR_NOTFOUND; + + *freq_hz = (u64)1000U * freq; + board_vddcore_init(voltage); + + return 0; +} + +static int stm32mp1_pll1_opp(struct stm32mp_rcc_priv *priv, int clksrc, + u32 *pllcfg, u32 *fracv) +{ + u32 post_divm; + u32 input_freq; + u64 output_freq; + u64 freq; + u64 vco; + u32 divm, divn, divp, frac; + int i, ret; + u32 diff; + u32 best_diff = U32_MAX; + + /* PLL1 is 2000 */ + const u32 DIVN_MAX = stm32mp1_pll[PLL_2000].divn_max; + const u32 POST_DIVM_MIN = stm32mp1_pll[PLL_2000].refclk_min * 1000000U; + const u32 POST_DIVM_MAX = stm32mp1_pll[PLL_2000].refclk_max * 1000000U; + + ret = stm32mp1_get_max_opp_freq(priv, &output_freq); + if (ret) { + log_debug("PLL1 OPP configuration not found (%d).\n", ret); + return ret; + } + + switch (clksrc) { + case CLK_PLL12_HSI: + input_freq = stm32mp1_clk_get_fixed(priv, _HSI); + break; + case CLK_PLL12_HSE: + input_freq = stm32mp1_clk_get_fixed(priv, _HSE); + break; + default: + return -EINTR; + } + + /* Following parameters have always the same value */ + pllcfg[PLLCFG_Q] = 0; + pllcfg[PLLCFG_R] = 0; + pllcfg[PLLCFG_O] = PQR(1, 1, 1); + + for (divm = DIVM_MAX; divm >= DIVM_MIN; divm--) { + post_divm = (u32)(input_freq / (divm + 1)); + if (post_divm < POST_DIVM_MIN || post_divm > POST_DIVM_MAX) + continue; + + for (divp = DIVP_MIN; divp <= DIVP_MAX; divp++) { + freq = output_freq * (divm + 1) * (divp + 1); + divn = (u32)((freq / input_freq) - 1); + if (divn < DIVN_MIN || divn > DIVN_MAX) + continue; + + frac = (u32)(((freq * FRAC_MAX) / input_freq) - + ((divn + 1) * FRAC_MAX)); + /* 2 loops to refine the fractional part */ + for (i = 2; i != 0; i--) { + if (frac > FRAC_MAX) + break; + + vco = (post_divm * (divn + 1)) + + ((post_divm * (u64)frac) / + FRAC_MAX); + if (vco < (PLL2000_VCO_MIN / 2) || + vco > (PLL2000_VCO_MAX / 2)) { + frac++; + continue; + } + freq = vco / (divp + 1); + if (output_freq < freq) + diff = (u32)(freq - output_freq); + else + diff = (u32)(output_freq - freq); + if (diff < best_diff) { + pllcfg[PLLCFG_M] = divm; + pllcfg[PLLCFG_N] = divn; + pllcfg[PLLCFG_P] = divp; + *fracv = frac; + + if (diff == 0) { + return 0; + } + + best_diff = diff; + } + frac++; + } + } + } + + if (best_diff == U32_MAX) + return -1; + + return 0; +} + +static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset, + u32 mask_on) +{ + u32 address = rcc + offset; + + if (enable) + setbits_le32(address, mask_on); + else + clrbits_le32(address, mask_on); +} + +static void stm32mp1_hs_ocs_set(int enable, fdt_addr_t rcc, u32 mask_on) +{ + writel(mask_on, rcc + (enable ? RCC_OCENSETR : RCC_OCENCLRR)); +} + +static int stm32mp1_osc_wait(int enable, fdt_addr_t rcc, u32 offset, + u32 mask_rdy) +{ + u32 mask_test = 0; + u32 address = rcc + offset; + u32 val; + int ret; + + if (enable) + mask_test = mask_rdy; + + ret = readl_poll_timeout(address, val, + (val & mask_rdy) == mask_test, + TIMEOUT_1S); + + if (ret) + log_err("OSC %x @ %x timeout for enable=%d : 0x%x\n", + mask_rdy, address, enable, readl(address)); + + return ret; +} + +static void stm32mp1_lse_enable(fdt_addr_t rcc, int bypass, int digbyp, + u32 lsedrv) +{ + u32 value; + + if (digbyp) + setbits_le32(rcc + RCC_BDCR, RCC_BDCR_DIGBYP); + + if (bypass || digbyp) + setbits_le32(rcc + RCC_BDCR, RCC_BDCR_LSEBYP); + + /* + * warning: not recommended to switch directly from "high drive" + * to "medium low drive", and vice-versa. + */ + value = (readl(rcc + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) + >> RCC_BDCR_LSEDRV_SHIFT; + + while (value != lsedrv) { + if (value > lsedrv) + value--; + else + value++; + + clrsetbits_le32(rcc + RCC_BDCR, + RCC_BDCR_LSEDRV_MASK, + value << RCC_BDCR_LSEDRV_SHIFT); + } + + stm32mp1_ls_osc_set(1, rcc, RCC_BDCR, RCC_BDCR_LSEON); +} + +static void stm32mp1_lse_wait(fdt_addr_t rcc) +{ + stm32mp1_osc_wait(1, rcc, RCC_BDCR, RCC_BDCR_LSERDY); +} + +static void stm32mp1_lsi_set(fdt_addr_t rcc, int enable) +{ + stm32mp1_ls_osc_set(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSION); + stm32mp1_osc_wait(enable, rcc, RCC_RDLSICR, RCC_RDLSICR_LSIRDY); +} + +static void stm32mp1_hse_enable(fdt_addr_t rcc, int bypass, int digbyp, int css) +{ + if (digbyp) + writel(RCC_OCENR_DIGBYP, rcc + RCC_OCENSETR); + if (bypass || digbyp) + writel(RCC_OCENR_HSEBYP, rcc + RCC_OCENSETR); + + stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON); + stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY); + + if (css) + writel(RCC_OCENR_HSECSSON, rcc + RCC_OCENSETR); +} + +static void stm32mp1_csi_set(fdt_addr_t rcc, int enable) +{ + stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_CSION); + stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY); +} + +static void stm32mp1_hsi_set(fdt_addr_t rcc, int enable) +{ + stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_HSION); + stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_HSIRDY); +} + +static int stm32mp1_set_hsidiv(fdt_addr_t rcc, u8 hsidiv) +{ + u32 address = rcc + RCC_OCRDYR; + u32 val; + int ret; + + clrsetbits_le32(rcc + RCC_HSICFGR, + RCC_HSICFGR_HSIDIV_MASK, + RCC_HSICFGR_HSIDIV_MASK & hsidiv); + + ret = readl_poll_timeout(address, val, + val & RCC_OCRDYR_HSIDIVRDY, + TIMEOUT_200MS); + if (ret) + log_err("HSIDIV failed @ 0x%x: 0x%x\n", + address, readl(address)); + + return ret; +} + +static int stm32mp1_hsidiv(fdt_addr_t rcc, ulong hsifreq) +{ + u8 hsidiv; + u32 hsidivfreq = MAX_HSI_HZ; + + for (hsidiv = 0; hsidiv < 4; hsidiv++, + hsidivfreq = hsidivfreq / 2) + if (hsidivfreq == hsifreq) + break; + + if (hsidiv == 4) { + log_err("hsi frequency invalid"); + return -1; + } + + if (hsidiv > 0) + return stm32mp1_set_hsidiv(rcc, hsidiv); + + return 0; +} + +static void pll_start(struct stm32mp_rcc_priv *priv, int pll_id) +{ + clrsetbits_le32((u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); +} + +static int pll_output(struct stm32mp_rcc_priv *priv, int pll_id, int output) +{ + u32 pllxcr = (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr; + u32 val; + int ret; + + ret = readl_poll_timeout(pllxcr, val, val & RCC_PLLNCR_PLLRDY, + TIMEOUT_200MS); + + if (ret) { + log_err("PLL%d start failed @ 0x%x: 0x%x\n", + pll_id, pllxcr, readl(pllxcr)); + return ret; + } + + /* start the requested output */ + setbits_le32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); + + return 0; +} + +static int pll_stop(struct stm32mp_rcc_priv *priv, int pll_id) +{ + u32 pllxcr = (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr; + u32 val; + + /* stop all output */ + clrbits_le32(pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); + + /* stop PLL */ + clrbits_le32(pllxcr, RCC_PLLNCR_PLLON); + + /* wait PLL stopped */ + return readl_poll_timeout(pllxcr, val, (val & RCC_PLLNCR_PLLRDY) == 0, + TIMEOUT_200MS); +} + +static void pll_config_output(struct stm32mp_rcc_priv *priv, + int pll_id, u32 *pllcfg) +{ + fdt_addr_t rcc = (u32)(priv->base); + u32 value; + + value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) + & RCC_PLLNCFGR2_DIVP_MASK; + value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) + & RCC_PLLNCFGR2_DIVQ_MASK; + value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) + & RCC_PLLNCFGR2_DIVR_MASK; + writel(value, rcc + stm32mp1_clk_pll[pll_id].pllxcfgr2); +} + +static int pll_config(struct stm32mp_rcc_priv *priv, int pll_id, + u32 *pllcfg, u32 fracv) +{ + fdt_addr_t rcc = (u32)(priv->base); + enum stm32mp1_plltype type = stm32mp1_clk_pll[pll_id].plltype; + int src; + ulong refclk; + u8 ifrge = 0; + u32 value; + + src = readl((u32)(priv->base) + stm32mp1_clk_pll[pll_id].rckxselr) & RCC_SELR_SRC_MASK; + refclk = stm32mp1_clk_get_fixed(priv, stm32mp1_clk_pll[pll_id].refclk[src]) / + (pllcfg[PLLCFG_M] + 1); + + if (refclk < (stm32mp1_pll[type].refclk_min * 1000000) || + refclk > (stm32mp1_pll[type].refclk_max * 1000000)) { + log_err("invalid refclk = %x\n", (u32)refclk); + return -EINVAL; + } + + + if (type == PLL_800 && refclk >= 8000000) + ifrge = 1; + + value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) + & RCC_PLLNCFGR1_DIVN_MASK; + value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) + & RCC_PLLNCFGR1_DIVM_MASK; + value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) + & RCC_PLLNCFGR1_IFRGE_MASK; + writel(value, rcc + stm32mp1_clk_pll[pll_id].pllxcfgr1); + + /* fractional configuration: load sigma-delta modulator (SDM) */ + + /* Write into FRACV the new fractional value , and FRACLE to 0 */ + writel(fracv << RCC_PLLNFRACR_FRACV_SHIFT, + rcc + stm32mp1_clk_pll[pll_id].pllxfracr); + + /* Write FRACLE to 1 : FRACV value is loaded into the SDM */ + setbits_le32(rcc + stm32mp1_clk_pll[pll_id].pllxfracr, + RCC_PLLNFRACR_FRACLE); + + pll_config_output(priv, pll_id, pllcfg); + + return 0; +} + +static void pll_csg(struct stm32mp_rcc_priv *priv, int pll_id, u32 *csg) +{ + u32 pllxcsg; + + pllxcsg = ((csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & + RCC_PLLNCSGR_MOD_PER_MASK) | + ((csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & + RCC_PLLNCSGR_INC_STEP_MASK) | + ((csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & + RCC_PLLNCSGR_SSCG_MODE_MASK); + + writel(pllxcsg, (u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcsgr); + + setbits_le32((u32)(priv->base) + stm32mp1_clk_pll[pll_id].pllxcr, RCC_PLLNCR_SSCG_CTRL); +} + +static ulong pll_get_fref_ck(struct stm32mp_rcc_priv *priv, + int pll_id) +{ + u32 selr; + int src; + + /* Get current refclk */ + selr = readl(priv->base + stm32mp1_clk_pll[pll_id].rckxselr); + src = selr & RCC_SELR_SRC_MASK; + + return stm32mp1_clk_get_fixed(priv, stm32mp1_clk_pll[pll_id].refclk[src]); +} + +static __maybe_unused int pll_set_rate(struct udevice *dev, + int pll_id, + int div_id, + unsigned long clk_rate) +{ + struct stm32mp_rcc_priv *priv = dev_get_priv(dev); + unsigned int pllcfg[PLLCFG_NB]; + ofnode plloff; + char name[12]; + enum stm32mp1_plltype type = stm32mp1_clk_pll[pll_id].plltype; + int divm, divn, divy; + int ret; + ulong fck_ref; + u32 fracv; + u64 value; + + if (div_id > _DIV_NB) + return -EINVAL; + + sprintf(name, "st,pll@%d", pll_id); + plloff = dev_read_subnode(dev, name); + if (!ofnode_valid(plloff)) + return -FDT_ERR_NOTFOUND; + + ret = ofnode_read_u32_array(plloff, "cfg", + pllcfg, PLLCFG_NB); + if (ret < 0) + return -FDT_ERR_NOTFOUND; + + fck_ref = pll_get_fref_ck(priv, pll_id); + + divm = pllcfg[PLLCFG_M]; + /* select output divider = 0: for _DIV_P, 1:_DIV_Q 2:_DIV_R */ + divy = pllcfg[PLLCFG_P + div_id]; + + /* For: PLL1 & PLL2 => VCO is * 2 but ck_pll_y is also / 2 + * So same final result than PLL2 et 4 + * with FRACV + * Fck_pll_y = Fck_ref * ((DIVN + 1) + FRACV / 2^13) + * / (DIVy + 1) * (DIVM + 1) + * value = (DIVN + 1) * 2^13 + FRACV / 2^13 + * = Fck_pll_y (DIVy + 1) * (DIVM + 1) * 2^13 / Fck_ref + */ + value = ((u64)clk_rate * (divy + 1) * (divm + 1)) << 13; + value = lldiv(value, fck_ref); + + divn = (value >> 13) - 1; + if (divn < DIVN_MIN || + divn > stm32mp1_pll[type].divn_max) { + dev_err(dev, "divn invalid = %d", divn); + return -EINVAL; + } + fracv = value - ((divn + 1) << 13); + pllcfg[PLLCFG_N] = divn; + + /* reconfigure PLL */ + pll_stop(priv, pll_id); + pll_config(priv, pll_id, pllcfg, fracv); + pll_start(priv, pll_id); + pll_output(priv, pll_id, pllcfg[PLLCFG_O]); + + return 0; +} + +static int set_clksrc(struct stm32mp_rcc_priv *priv, unsigned int clksrc) +{ + u32 address = (u32)(priv->base); + u32 mux = (clksrc & MUX_ID_MASK) >> MUX_ID_SHIFT; + u32 val; + int ret; + + /* List of relevant muxes to keep the size down */ + if (mux == MUX_PLL12) + address += RCC_RCK12SELR; + else if (mux == MUX_PLL3) + address += RCC_RCK3SELR; + else if (mux == MUX_PLL4) + address += RCC_RCK4SELR; + else if (mux == MUX_MPU) + address += RCC_MPCKSELR; + else if (mux == MUX_AXI) + address += RCC_ASSCKSELR; + else if (mux == MUX_MLAHB) + address += RCC_MSSCKSELR; + else if (mux == MUX_CKPER) + address += RCC_CPERCKSELR; + else + return -EINVAL; + + clrsetbits_le32(address, RCC_SELR_SRC_MASK, clksrc & RCC_SELR_SRC_MASK); + ret = readl_poll_timeout(address, val, val & RCC_SELR_SRCRDY, + TIMEOUT_200MS); + if (ret) + log_err("CLKSRC %x start failed @ 0x%x: 0x%x\n", + clksrc, address, readl(address)); + + return ret; +} + +static void stgen_config(struct stm32mp_rcc_priv *priv) +{ + u32 stgenc, cntfid0; + ulong rate = clk_get_rate(&priv->osc_clk[_HSI]); + stgenc = STM32_STGEN_BASE; + cntfid0 = readl(stgenc + STGENC_CNTFID0); + + if (cntfid0 != rate) { + u64 counter; + + log_debug("System Generic Counter (STGEN) update\n"); + clrbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN); + counter = (u64)readl(stgenc + STGENC_CNTCVL); + counter |= ((u64)(readl(stgenc + STGENC_CNTCVU))) << 32; + counter = lldiv(counter * (u64)rate, cntfid0); + writel((u32)counter, stgenc + STGENC_CNTCVL); + writel((u32)(counter >> 32), stgenc + STGENC_CNTCVU); + writel(rate, stgenc + STGENC_CNTFID0); + setbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN); + + __asm__ volatile("mcr p15, 0, %0, c14, c0, 0" : : "r" (rate)); + + /* need to update gd->arch.timer_rate_hz with new frequency */ + timer_init(); + } +} + +static int set_clkdiv(unsigned int clkdiv, u32 address) +{ + u32 val; + int ret; + + + clrsetbits_le32(address, RCC_DIVR_DIV_MASK, clkdiv & RCC_DIVR_DIV_MASK); + ret = readl_poll_timeout(address, val, val & RCC_DIVR_DIVRDY, + TIMEOUT_200MS); + if (ret) + log_err("CLKDIV %x start failed @ 0x%x: 0x%x\n", + clkdiv, address, readl(address)); + + return ret; +} + +static void set_rtcsrc(struct stm32mp_rcc_priv *priv, + unsigned int clksrc, + int lse_css) +{ + u32 address = (u32)(priv->base) + RCC_BDCR; + + if (readl(address) & RCC_BDCR_RTCCKEN) + goto skip_rtc; + + if (clksrc == CLK_RTC_DISABLED) + goto skip_rtc; + + clrsetbits_le32(address, + RCC_BDCR_RTCSRC_MASK, + clksrc << RCC_BDCR_RTCSRC_SHIFT); + + setbits_le32(address, RCC_BDCR_RTCCKEN); + +skip_rtc: + if (lse_css) + setbits_le32(address, RCC_BDCR_LSECSSON); +} + +static void pkcs_config(struct stm32mp_rcc_priv *priv, u32 pkcs) +{ + u32 mux = (pkcs & MUX_ID_MASK) >> MUX_ID_SHIFT; + u32 address = (u32)(priv->base) + stm32mp13_muxes[mux].reg_off; + u32 mask = (BIT(stm32mp13_muxes[mux].width) - 1) << stm32mp13_muxes[mux].shift; + u32 value = (pkcs << stm32mp13_muxes[mux].shift) & mask; + + clrsetbits_le32(address, mask, value); +} + +static int stm32mp1_clktree(struct udevice *dev) +{ + struct stm32mp_rcc_priv *priv = dev_get_priv(dev); + fdt_addr_t rcc = (u32)(priv->base); + unsigned int clksrc[CLKSRC_NB]; + unsigned int clkdiv[CLKDIV_NB]; + unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; + unsigned int pllfracv[_PLL_NB]; + unsigned int pllcsg[_PLL_NB][PLLCSG_NB]; + bool pllcfg_valid[_PLL_NB]; + bool pllcsg_set[_PLL_NB]; + int ret; + int i, len; + int lse_css = 0; + const u32 *pkcs_cell; + + /* check mandatory field */ + ret = dev_read_u32_array(dev, "st,clksrc", clksrc, CLKSRC_NB); + if (ret < 0) { + dev_dbg(dev, "field st,clksrc invalid: error %d\n", ret); + return -FDT_ERR_NOTFOUND; + } + + ret = dev_read_u32_array(dev, "st,clkdiv", clkdiv, CLKDIV_NB); + if (ret < 0) { + dev_dbg(dev, "field st,clkdiv invalid: error %d\n", ret); + return -FDT_ERR_NOTFOUND; + } + + /* check mandatory field in each pll */ + for (i = 0; i < _PLL_NB; i++) { + char name[12]; + ofnode node; + + sprintf(name, "st,pll@%d", i); + node = dev_read_subnode(dev, name); + pllcfg_valid[i] = ofnode_valid(node); + pllcsg_set[i] = false; + if (pllcfg_valid[i]) { + dev_dbg(dev, "DT for PLL %d @ %s\n", i, name); + ret = ofnode_read_u32_array(node, "cfg", + pllcfg[i], PLLCFG_NB); + if (ret < 0) { + dev_dbg(dev, "field cfg invalid: error %d\n", ret); + return -FDT_ERR_NOTFOUND; + } + pllfracv[i] = ofnode_read_u32_default(node, "frac", 0); + + ret = ofnode_read_u32_array(node, "csg", pllcsg[i], + PLLCSG_NB); + if (!ret) { + pllcsg_set[i] = true; + } else if (ret != -FDT_ERR_NOTFOUND) { + dev_dbg(dev, "invalid csg node for pll@%d res=%d\n", + i, ret); + return ret; + } + } else if (i == _PLL1) { + /* use OPP for PLL1 for A7 CPU */ + dev_dbg(dev, "DT for PLL %d with OPP\n", i); + ret = stm32mp1_pll1_opp(priv, + clksrc[CLKSRC_PLL12], + pllcfg[i], + &pllfracv[i]); + if (ret) { + dev_dbg(dev, "PLL %d with OPP error = %d\n", i, ret); + return ret; + } + pllcfg_valid[i] = true; + } + } + + dev_dbg(dev, "switch ON osillator\n"); + /* + * switch ON oscillator found in device-tree, + * HSI already ON after bootrom + */ + if (clk_valid(&priv->osc_clk[_LSI])) + stm32mp1_lsi_set(rcc, 1); + + if (clk_valid(&priv->osc_clk[_LSE])) { + int bypass, digbyp; + u32 lsedrv; + struct udevice *dev = priv->osc_clk[_LSE].dev; + + bypass = dev_read_bool(dev, "st,bypass"); + digbyp = dev_read_bool(dev, "st,digbypass"); + lse_css = dev_read_bool(dev, "st,css"); + lsedrv = dev_read_u32_default(dev, "st,drive", + LSEDRV_MEDIUM_HIGH); + + stm32mp1_lse_enable(rcc, bypass, digbyp, lsedrv); + } + + + if (clk_valid(&priv->osc_clk[_HSE])) { + int bypass, digbyp, css; + struct udevice *dev = priv->osc_clk[_HSE].dev; + + bypass = dev_read_bool(dev, "st,bypass"); + digbyp = dev_read_bool(dev, "st,digbypass"); + css = dev_read_bool(dev, "st,css"); + + stm32mp1_hse_enable(rcc, bypass, digbyp, css); + } + + /* CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) + * => switch on CSI even if node is not present in device tree + */ + stm32mp1_csi_set(rcc, 1); + + /* come back to HSI */ + dev_dbg(dev, "come back to HSI\n"); + set_clksrc(priv, CLK_MPU_HSI); + set_clksrc(priv, CLK_AXI_HSI); + set_clksrc(priv, CLK_MLAHBS_HSI); + + dev_dbg(dev, "pll stop\n"); + for (i = 0; i < _PLL_NB; i++) + pll_stop(priv, i); + + /* configure HSIDIV */ + dev_dbg(dev, "configure HSIDIV\n"); + if (clk_valid(&priv->osc_clk[_HSI])) { + stm32mp1_hsidiv(rcc, clk_get_rate(&priv->osc_clk[_HSI])); + stgen_config(priv); + } + + /* select DIV */ + dev_dbg(dev, "select DIV\n"); + /* no ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ + set_clkdiv(clkdiv[CLKDIV_AXI], rcc + RCC_AXIDIVR); + set_clkdiv(clkdiv[CLKDIV_APB4], rcc + RCC_APB4DIVR); + set_clkdiv(clkdiv[CLKDIV_APB5], rcc + RCC_APB5DIVR); + set_clkdiv(clkdiv[CLKDIV_APB6], rcc + RCC_APB6DIVR); + set_clkdiv(clkdiv[CLKDIV_APB1], rcc + RCC_APB1DIVR); + set_clkdiv(clkdiv[CLKDIV_APB2], rcc + RCC_APB2DIVR); + set_clkdiv(clkdiv[CLKDIV_APB3], rcc + RCC_APB3DIVR); + + /* no ready bit for RTC */ + writel(clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK, rcc + RCC_RTCDIVR); + + /* configure PLLs source */ + dev_dbg(dev, "configure PLLs source\n"); + set_clksrc(priv, clksrc[CLKSRC_PLL12]); + set_clksrc(priv, clksrc[CLKSRC_PLL3]); + set_clksrc(priv, clksrc[CLKSRC_PLL4]); + + /* configure and start PLLs */ + dev_dbg(dev, "configure PLLs\n"); + for (i = 0; i < _PLL_NB; i++) { + if (!pllcfg_valid[i]) + continue; + dev_dbg(dev, "configure PLL %d\n", i); + pll_config(priv, i, pllcfg[i], pllfracv[i]); + if (pllcsg_set[i]) + pll_csg(priv, i, pllcsg[i]); + pll_start(priv, i); + } + + /* wait and start PLLs ouptut when ready */ + for (i = 0; i < _PLL_NB; i++) { + if (!pllcfg_valid[i]) + continue; + dev_dbg(dev, "output PLL %d\n", i); + pll_output(priv, i, pllcfg[i][PLLCFG_O]); + } + + /* wait LSE ready before to use it */ + if (clk_valid(&priv->osc_clk[_LSE])) + stm32mp1_lse_wait(rcc); + + /* configure with expected clock source */ + dev_dbg(dev, "CLKSRC\n"); + set_clksrc(priv, clksrc[CLKSRC_MPU]); + set_clksrc(priv, clksrc[CLKSRC_AXI]); + set_clksrc(priv, clksrc[CLKSRC_MLAHB]); + set_rtcsrc(priv, clksrc[CLKSRC_RTC], lse_css); + + /* configure PKCK */ + dev_dbg(dev, "PKCK\n"); + pkcs_cell = dev_read_prop(dev, "st,pkcs", &len); + if (pkcs_cell) { + bool ckper_disabled = false; + + for (i = 0; i < len / sizeof(u32); i++) { + u32 pkcs = (u32)fdt32_to_cpu(pkcs_cell[i]); + + if (pkcs == CLK_CKPER_DISABLED) { + ckper_disabled = true; + continue; + } + pkcs_config(priv, pkcs); + } + /* CKPER is source for some peripheral clock + * (FMC-NAND / QPSI-NOR) and switching source is allowed + * only if previous clock is still ON + * => deactivated CKPER only after switching clock + */ + if (ckper_disabled) + pkcs_config(priv, CLK_CKPER_DISABLED); + } + + /* STGEN clock source can change with CLK_STGEN_XXX */ + stgen_config(priv); + + dev_dbg(dev, "oscillator off\n"); + /* switch OFF HSI if not found in device-tree */ + if (!clk_valid(&priv->osc_clk[_HSI])) + stm32mp1_hsi_set(rcc, 0); + + /* Software Self-Refresh mode (SSR) during DDR initilialization */ + clrsetbits_le32((u32)(priv->base) + RCC_DDRITFCR, + RCC_DDRITFCR_DDRCKMOD_MASK, + RCC_DDRITFCR_DDRCKMOD_SSR << + RCC_DDRITFCR_DDRCKMOD_SHIFT); + + return 0; +} +#endif + +static int stm32mp1_osc_init(struct udevice *dev) +{ + struct stm32mp_rcc_priv *priv = dev_get_priv(dev); + fdt_addr_t base = dev_read_addr(dev->parent); + struct clk *ck; + int i; + + const char *name[NB_OSC] = { + [_LSI] = "lsi", + [_LSE] = "lse", + [_HSI] = "hsi", + [_HSE] = "hse", + [_CSI] = "csi", + [_I2S_CKIN] = "i2s_ckin", + }; + + const struct { + const char *name; + const int rate; + } fixed_clk[] = { + { "bsec", 66625000 }, + { "ck_axi", 266500000 }, + { "ck_mlahb", 200000000 }, + { "ck_mpu", 1000000000 }, + { "ck_per", 24000000 }, + { "ck_rtc", 32768 }, + { "clk-hse-div2", 12000000 }, + { "pclk1", 100000000 }, + { "pclk2", 100000000 }, + { "pclk3", 100000000 }, + { "pclk4", 133250000 }, + { "pclk5", 66625000 }, + { "pclk6", 100000000 }, + { "pll2_q", 266500000 }, + { "pll2_r", 533000000 }, + { "pll3_p", 200000000 }, + { "pll3_q", 150000000 }, + { "pll3_r", 200000000 }, + { "pll4_p", 125000000 }, + { "pll4_q", 83333333 }, + { "pll4_r", 75000000 }, + { "rtcapb", 66625000 }, + { "timg1_ck", 200000000 }, + { "timg2_ck", 200000000 }, + { "timg3_ck", 200000000 }, + }; + + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = (void __iomem *)base; + + for (i = 0; i < NB_OSC; i++) { + if (clk_get_by_name(dev, name[i], &priv->osc_clk[i])) + dev_dbg(dev, "No source clock \"%s\"\n", name[i]); + else + dev_dbg(dev, "%s clock rate: %luHz\n", + name[i], clk_get_rate(&priv->osc_clk[i])); + } + + for (i = 0; i < ARRAY_SIZE(fixed_clk); i++) { + ck = clk_register_fixed_rate(NULL, fixed_clk[i].name, fixed_clk[i].rate); + if (!ck) + dev_dbg(dev, "Cannot register fixed clock \"%s\"\n", fixed_clk[i].name); + } + + return 0; +} +#endif + static int stm32mp1_clk_probe(struct udevice *dev) { - struct udevice *scmi; int err; +#ifdef CONFIG_TFABOOT + struct udevice *scmi; + /* force SCMI probe to register all SCMI clocks */ uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(scmi_clock), &scmi); +#else + err = stm32mp1_osc_init(dev); + if (err) + return err; + +#if defined(CONFIG_XPL_BUILD) + /* clock tree init is done only one time, before relocation */ + if (!(gd->flags & GD_FLG_RELOC)) + err = stm32mp1_clktree(dev); + if (err) + dev_err(dev, "clock tree initialization failed (%d)\n", err); +#endif +#endif err = stm32_rcc_init(dev, &stm32mp13_data); if (err) @@ -815,6 +2012,7 @@ static int stm32mp1_clk_probe(struct udevice *dev) /* DDRPHYC father */ gd->mem_clk = clk_stm32_get_rate_by_name("pll2_r"); +#ifndef CONFIG_XPL_BUILD if (IS_ENABLED(CONFIG_DISPLAY_CPUINFO)) { if (gd->flags & GD_FLG_RELOC) { char buf[32]; @@ -827,6 +2025,7 @@ static int stm32mp1_clk_probe(struct udevice *dev) log_info("- DDR : %s MHz\n", strmhz(buf, gd->mem_clk)); } } +#endif return 0; } diff --git a/drivers/clk/stm32/clk-stm32mp25.c b/drivers/clk/stm32/clk-stm32mp25.c new file mode 100644 index 00000000000..18c0b1cb867 --- /dev/null +++ b/drivers/clk/stm32/clk-stm32mp25.c @@ -0,0 +1,782 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ + +#include <clk-uclass.h> +#include <dm.h> +#include <dt-bindings/clock/st,stm32mp25-rcc.h> +#include <linux/bitfield.h> +#include <linux/clk-provider.h> +#include <linux/io.h> +#include <mach/rif.h> + +#include "clk-stm32-core.h" +#include "stm32mp25_rcc.h" + +/* Clock security definition */ +#define SECF_NONE -1 + +#define RCC_REG_SIZE 32 +#define RCC_SECCFGR(x) (((x) / RCC_REG_SIZE) * 0x4 + RCC_SECCFGR0) +#define RCC_CIDCFGR(x) ((x) * 0x8 + RCC_R0CIDCFGR) +#define RCC_SEMCR(x) ((x) * 0x8 + RCC_R0SEMCR) +#define RCC_CID1 1 + +/* Register: RIFSC_CIDCFGR */ +#define RCC_CIDCFGR_CFEN BIT(0) +#define RCC_CIDCFGR_SEM_EN BIT(1) +#define RCC_CIDCFGR_SEMWLC1_EN BIT(17) +#define RCC_CIDCFGR_SCID_MASK GENMASK(6, 4) + +/* Register: RIFSC_SEMCR */ +#define RCC_SEMCR_SEMCID_MASK GENMASK(6, 4) + +#define STM32MP25_RIFRCC_DBG_ID 73 +#define STM32MP25_RIFRCC_IS2M_ID 107 +#define STM32MP25_RIFRCC_MCO1_ID 108 +#define STM32MP25_RIFRCC_MCO2_ID 109 +#define STM32MP25_RIFRCC_OSPI1_ID 110 +#define STM32MP25_RIFRCC_OSPI2_ID 111 + +#define SEC_RIFSC_FLAG BIT(31) +#define SEC_RIFRCC(_id) (STM32MP25_RIFRCC_##_id##_ID) +#define SEC_RIFSC(_id) ((_id) | SEC_RIFSC_FLAG) + +static const char * const adc12_src[] = { + "ck_flexgen_46", "ck_icn_ls_mcu" +}; + +static const char * const adc3_src[] = { + "ck_flexgen_47", "ck_icn_ls_mcu", "ck_flexgen_46" +}; + +static const char * const usb2phy1_src[] = { + "ck_flexgen_57", "hse_div2_ck" +}; + +static const char * const usb2phy2_src[] = { + "ck_flexgen_58", "hse_div2_ck" +}; + +static const char * const usb3pciphy_src[] = { + "ck_flexgen_34", "hse_div2_ck" +}; + +static const char * const dsiblane_src[] = { + "txbyteclk", "ck_ker_ltdc" +}; + +static const char * const dsiphy_src[] = { + "ck_flexgen_28", "hse_ck" +}; + +static const char * const lvdsphy_src[] = { + "ck_flexgen_32", "hse_ck" +}; + +static const char * const dts_src[] = { + "hsi_ck", "hse_ck", "msi_ck" +}; + +static const char * const mco1_src[] = { + "ck_flexgen_61", "ck_obs0" +}; + +static const char * const mco2_src[] = { + "ck_flexgen_62", "ck_obs1" +}; + +enum enum_mux_cfg { + MUX_MCO1, + MUX_MCO2, + MUX_ADC12, + MUX_ADC3, + MUX_USB2PHY1, + MUX_USB2PHY2, + MUX_USB3PCIEPHY, + MUX_DSIBLANE, + MUX_DSIPHY, + MUX_LVDSPHY, + MUX_DTS, + MUX_NB +}; + +#define MUX_CFG(id, src, _offset, _shift, _witdh)[id] = {\ + .num_parents = ARRAY_SIZE(src),\ + .parent_names = src,\ + .reg_off = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ +} + +static const struct stm32_mux_cfg stm32mp25_muxes[MUX_NB] = { + MUX_CFG(MUX_ADC12, adc12_src, RCC_ADC12CFGR, 12, 1), + MUX_CFG(MUX_ADC3, adc3_src, RCC_ADC3CFGR, 12, 2), + MUX_CFG(MUX_DSIBLANE, dsiblane_src, RCC_DSICFGR, 12, 1), + MUX_CFG(MUX_DSIPHY, dsiphy_src, RCC_DSICFGR, 15, 1), + MUX_CFG(MUX_DTS, dts_src, RCC_DTSCFGR, 12, 2), + MUX_CFG(MUX_MCO1, mco1_src, RCC_MCO1CFGR, 0, 1), + MUX_CFG(MUX_MCO2, mco2_src, RCC_MCO2CFGR, 0, 1), + MUX_CFG(MUX_LVDSPHY, lvdsphy_src, RCC_LVDSCFGR, 15, 1), + MUX_CFG(MUX_USB2PHY1, usb2phy1_src, RCC_USB2PHY1CFGR, 15, 1), + MUX_CFG(MUX_USB2PHY2, usb2phy2_src, RCC_USB2PHY2CFGR, 15, 1), + MUX_CFG(MUX_USB3PCIEPHY, usb3pciphy_src, RCC_USB3PCIEPHYCFGR, 15, 1), +}; + +enum enum_gate_cfg { + GATE_ADC12, + GATE_ADC3, + GATE_ADF1, + GATE_CCI, + GATE_CRC, + GATE_CRYP1, + GATE_CRYP2, + GATE_CSI, + GATE_DBG, + GATE_DCMIPP, + GATE_DSI, + GATE_DTS, + GATE_ETH1, + GATE_ETH1MAC, + GATE_ETH1RX, + GATE_ETH1STP, + GATE_ETH1TX, + GATE_ETH2, + GATE_ETH2MAC, + GATE_ETH2RX, + GATE_ETH2STP, + GATE_ETH2TX, + GATE_ETHSW, + GATE_ETHSWMAC, + GATE_ETHSWREF, + GATE_ETR, + GATE_FDCAN, + GATE_GPU, + GATE_HASH, + GATE_HDP, + GATE_I2C1, + GATE_I2C2, + GATE_I2C3, + GATE_I2C4, + GATE_I2C5, + GATE_I2C6, + GATE_I2C7, + GATE_I2C8, + GATE_I3C1, + GATE_I3C2, + GATE_I3C3, + GATE_I3C4, + GATE_IS2M, + GATE_IWDG1, + GATE_IWDG2, + GATE_IWDG3, + GATE_IWDG4, + GATE_IWDG5, + GATE_LPTIM1, + GATE_LPTIM2, + GATE_LPTIM3, + GATE_LPTIM4, + GATE_LPTIM5, + GATE_LPUART1, + GATE_LTDC, + GATE_LVDS, + GATE_MCO1, + GATE_MCO2, + GATE_MDF1, + GATE_OSPI1, + GATE_OSPI2, + GATE_OSPIIOM, + GATE_PCIE, + GATE_PKA, + GATE_RNG, + GATE_SAES, + GATE_SAI1, + GATE_SAI2, + GATE_SAI3, + GATE_SAI4, + GATE_SDMMC1, + GATE_SDMMC2, + GATE_SDMMC3, + GATE_SERC, + GATE_SPDIFRX, + GATE_SPI1, + GATE_SPI2, + GATE_SPI3, + GATE_SPI4, + GATE_SPI5, + GATE_SPI6, + GATE_SPI7, + GATE_SPI8, + GATE_STGEN, + GATE_STM500, + GATE_TIM1, + GATE_TIM2, + GATE_TIM3, + GATE_TIM4, + GATE_TIM5, + GATE_TIM6, + GATE_TIM7, + GATE_TIM8, + GATE_TIM10, + GATE_TIM11, + GATE_TIM12, + GATE_TIM13, + GATE_TIM14, + GATE_TIM15, + GATE_TIM16, + GATE_TIM17, + GATE_TIM20, + GATE_TRACE, + GATE_UART4, + GATE_UART5, + GATE_UART7, + GATE_UART8, + GATE_UART9, + GATE_USART1, + GATE_USART2, + GATE_USART3, + GATE_USART6, + GATE_USBH, + GATE_USB2PHY1, + GATE_USB2PHY2, + GATE_USB3DR, + GATE_USB3PCIEPHY, + GATE_USBTC, + GATE_VDEC, + GATE_VENC, + GATE_VREF, + GATE_WWDG1, + GATE_WWDG2, + GATE_NB +}; + +#define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\ + .reg_off = (_offset),\ + .bit_idx = (_bit_idx),\ + .set_clr = (_offset_clr),\ +} + +static const struct stm32_gate_cfg stm32mp25_gates[GATE_NB] = { + GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 8, 0), + GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 8, 0), + GATE_CFG(GATE_OSPI1, RCC_OSPI1CFGR, 1, 0), + GATE_CFG(GATE_OSPI2, RCC_OSPI2CFGR, 1, 0), + GATE_CFG(GATE_DBG, RCC_DBGCFGR, 8, 0), + GATE_CFG(GATE_TRACE, RCC_DBGCFGR, 9, 0), + GATE_CFG(GATE_STM500, RCC_STM500CFGR, 1, 0), + GATE_CFG(GATE_ETR, RCC_ETRCFGR, 1, 0), + GATE_CFG(GATE_IS2M, RCC_IS2MCFGR, 1, 0), + GATE_CFG(GATE_TIM1, RCC_TIM1CFGR, 1, 0), + GATE_CFG(GATE_TIM2, RCC_TIM2CFGR, 1, 0), + GATE_CFG(GATE_TIM3, RCC_TIM3CFGR, 1, 0), + GATE_CFG(GATE_TIM4, RCC_TIM4CFGR, 1, 0), + GATE_CFG(GATE_TIM5, RCC_TIM5CFGR, 1, 0), + GATE_CFG(GATE_TIM6, RCC_TIM6CFGR, 1, 0), + GATE_CFG(GATE_TIM7, RCC_TIM7CFGR, 1, 0), + GATE_CFG(GATE_TIM8, RCC_TIM8CFGR, 1, 0), + GATE_CFG(GATE_TIM10, RCC_TIM10CFGR, 1, 0), + GATE_CFG(GATE_TIM11, RCC_TIM11CFGR, 1, 0), + GATE_CFG(GATE_TIM12, RCC_TIM12CFGR, 1, 0), + GATE_CFG(GATE_TIM13, RCC_TIM13CFGR, 1, 0), + GATE_CFG(GATE_TIM14, RCC_TIM14CFGR, 1, 0), + GATE_CFG(GATE_TIM15, RCC_TIM15CFGR, 1, 0), + GATE_CFG(GATE_TIM16, RCC_TIM16CFGR, 1, 0), + GATE_CFG(GATE_TIM17, RCC_TIM17CFGR, 1, 0), + GATE_CFG(GATE_TIM20, RCC_TIM20CFGR, 1, 0), + GATE_CFG(GATE_LPTIM1, RCC_LPTIM1CFGR, 1, 0), + GATE_CFG(GATE_LPTIM2, RCC_LPTIM2CFGR, 1, 0), + GATE_CFG(GATE_LPTIM3, RCC_LPTIM3CFGR, 1, 0), + GATE_CFG(GATE_LPTIM4, RCC_LPTIM4CFGR, 1, 0), + GATE_CFG(GATE_LPTIM5, RCC_LPTIM5CFGR, 1, 0), + GATE_CFG(GATE_SPI1, RCC_SPI1CFGR, 1, 0), + GATE_CFG(GATE_SPI2, RCC_SPI2CFGR, 1, 0), + GATE_CFG(GATE_SPI3, RCC_SPI3CFGR, 1, 0), + GATE_CFG(GATE_SPI4, RCC_SPI4CFGR, 1, 0), + GATE_CFG(GATE_SPI5, RCC_SPI5CFGR, 1, 0), + GATE_CFG(GATE_SPI6, RCC_SPI6CFGR, 1, 0), + GATE_CFG(GATE_SPI7, RCC_SPI7CFGR, 1, 0), + GATE_CFG(GATE_SPI8, RCC_SPI8CFGR, 1, 0), + GATE_CFG(GATE_SPDIFRX, RCC_SPDIFRXCFGR, 1, 0), + GATE_CFG(GATE_USART1, RCC_USART1CFGR, 1, 0), + GATE_CFG(GATE_USART2, RCC_USART2CFGR, 1, 0), + GATE_CFG(GATE_USART3, RCC_USART3CFGR, 1, 0), + GATE_CFG(GATE_UART4, RCC_UART4CFGR, 1, 0), + GATE_CFG(GATE_UART5, RCC_UART5CFGR, 1, 0), + GATE_CFG(GATE_USART6, RCC_USART6CFGR, 1, 0), + GATE_CFG(GATE_UART7, RCC_UART7CFGR, 1, 0), + GATE_CFG(GATE_UART8, RCC_UART8CFGR, 1, 0), + GATE_CFG(GATE_UART9, RCC_UART9CFGR, 1, 0), + GATE_CFG(GATE_LPUART1, RCC_LPUART1CFGR, 1, 0), + GATE_CFG(GATE_I2C1, RCC_I2C1CFGR, 1, 0), + GATE_CFG(GATE_I2C2, RCC_I2C2CFGR, 1, 0), + GATE_CFG(GATE_I2C3, RCC_I2C3CFGR, 1, 0), + GATE_CFG(GATE_I2C4, RCC_I2C4CFGR, 1, 0), + GATE_CFG(GATE_I2C5, RCC_I2C5CFGR, 1, 0), + GATE_CFG(GATE_I2C6, RCC_I2C6CFGR, 1, 0), + GATE_CFG(GATE_I2C7, RCC_I2C7CFGR, 1, 0), + GATE_CFG(GATE_I2C8, RCC_I2C8CFGR, 1, 0), + GATE_CFG(GATE_SAI1, RCC_SAI1CFGR, 1, 0), + GATE_CFG(GATE_SAI2, RCC_SAI2CFGR, 1, 0), + GATE_CFG(GATE_SAI3, RCC_SAI3CFGR, 1, 0), + GATE_CFG(GATE_SAI4, RCC_SAI4CFGR, 1, 0), + GATE_CFG(GATE_MDF1, RCC_MDF1CFGR, 1, 0), + GATE_CFG(GATE_ADF1, RCC_ADF1CFGR, 1, 0), + GATE_CFG(GATE_FDCAN, RCC_FDCANCFGR, 1, 0), + GATE_CFG(GATE_HDP, RCC_HDPCFGR, 1, 0), + GATE_CFG(GATE_ADC12, RCC_ADC12CFGR, 1, 0), + GATE_CFG(GATE_ADC3, RCC_ADC3CFGR, 1, 0), + GATE_CFG(GATE_ETH1MAC, RCC_ETH1CFGR, 1, 0), + GATE_CFG(GATE_ETH1STP, RCC_ETH1CFGR, 4, 0), + GATE_CFG(GATE_ETH1, RCC_ETH1CFGR, 5, 0), + GATE_CFG(GATE_ETH1TX, RCC_ETH1CFGR, 8, 0), + GATE_CFG(GATE_ETH1RX, RCC_ETH1CFGR, 10, 0), + GATE_CFG(GATE_ETH2MAC, RCC_ETH2CFGR, 1, 0), + GATE_CFG(GATE_ETH2STP, RCC_ETH2CFGR, 4, 0), + GATE_CFG(GATE_ETH2, RCC_ETH2CFGR, 5, 0), + GATE_CFG(GATE_ETH2TX, RCC_ETH2CFGR, 8, 0), + GATE_CFG(GATE_ETH2RX, RCC_ETH2CFGR, 10, 0), + GATE_CFG(GATE_USBH, RCC_USBHCFGR, 1, 0), + GATE_CFG(GATE_USB2PHY1, RCC_USB2PHY1CFGR, 1, 0), + GATE_CFG(GATE_USB2PHY2, RCC_USB2PHY2CFGR, 1, 0), + GATE_CFG(GATE_USB3DR, RCC_USB3DRCFGR, 1, 0), + GATE_CFG(GATE_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 1, 0), + GATE_CFG(GATE_PCIE, RCC_PCIECFGR, 1, 0), + GATE_CFG(GATE_USBTC, RCC_UCPDCFGR, 1, 0), + GATE_CFG(GATE_ETHSWMAC, RCC_ETHSWCFGR, 1, 0), + GATE_CFG(GATE_ETHSW, RCC_ETHSWCFGR, 5, 0), + GATE_CFG(GATE_ETHSWREF, RCC_ETHSWCFGR, 21, 0), + GATE_CFG(GATE_STGEN, RCC_STGENCFGR, 1, 0), + GATE_CFG(GATE_SDMMC1, RCC_SDMMC1CFGR, 1, 0), + GATE_CFG(GATE_SDMMC2, RCC_SDMMC2CFGR, 1, 0), + GATE_CFG(GATE_SDMMC3, RCC_SDMMC3CFGR, 1, 0), + GATE_CFG(GATE_GPU, RCC_GPUCFGR, 1, 0), + GATE_CFG(GATE_LTDC, RCC_LTDCCFGR, 1, 0), + GATE_CFG(GATE_DSI, RCC_DSICFGR, 1, 0), + GATE_CFG(GATE_LVDS, RCC_LVDSCFGR, 1, 0), + GATE_CFG(GATE_CSI, RCC_CSICFGR, 1, 0), + GATE_CFG(GATE_DCMIPP, RCC_DCMIPPCFGR, 1, 0), + GATE_CFG(GATE_CCI, RCC_CCICFGR, 1, 0), + GATE_CFG(GATE_VDEC, RCC_VDECCFGR, 1, 0), + GATE_CFG(GATE_VENC, RCC_VENCCFGR, 1, 0), + GATE_CFG(GATE_RNG, RCC_RNGCFGR, 1, 0), + GATE_CFG(GATE_PKA, RCC_PKACFGR, 1, 0), + GATE_CFG(GATE_SAES, RCC_SAESCFGR, 1, 0), + GATE_CFG(GATE_HASH, RCC_HASHCFGR, 1, 0), + GATE_CFG(GATE_CRYP1, RCC_CRYP1CFGR, 1, 0), + GATE_CFG(GATE_CRYP2, RCC_CRYP2CFGR, 1, 0), + GATE_CFG(GATE_IWDG1, RCC_IWDG1CFGR, 1, 0), + GATE_CFG(GATE_IWDG2, RCC_IWDG2CFGR, 1, 0), + GATE_CFG(GATE_IWDG3, RCC_IWDG3CFGR, 1, 0), + GATE_CFG(GATE_IWDG4, RCC_IWDG4CFGR, 1, 0), + GATE_CFG(GATE_IWDG5, RCC_IWDG5CFGR, 1, 0), + GATE_CFG(GATE_WWDG1, RCC_WWDG1CFGR, 1, 0), + GATE_CFG(GATE_WWDG2, RCC_WWDG2CFGR, 1, 0), + GATE_CFG(GATE_VREF, RCC_VREFCFGR, 1, 0), + GATE_CFG(GATE_DTS, RCC_DTSCFGR, 1, 0), + GATE_CFG(GATE_CRC, RCC_CRCCFGR, 1, 0), + GATE_CFG(GATE_SERC, RCC_SERCCFGR, 1, 0), + GATE_CFG(GATE_OSPIIOM, RCC_OSPIIOMCFGR, 1, 0), + GATE_CFG(GATE_I3C1, RCC_I3C1CFGR, 1, 0), + GATE_CFG(GATE_I3C2, RCC_I3C2CFGR, 1, 0), + GATE_CFG(GATE_I3C3, RCC_I3C3CFGR, 1, 0), + GATE_CFG(GATE_I3C4, RCC_I3C4CFGR, 1, 0), +}; + +static int stm32_rcc_get_access(struct udevice *dev, u32 index) +{ + fdt_addr_t rcc_base = dev_read_addr(dev->parent); + u32 seccfgr, cidcfgr, semcr; + int bit, cid; + + bit = index % RCC_REG_SIZE; + + seccfgr = readl(rcc_base + RCC_SECCFGR(index)); + if (seccfgr & BIT(bit)) + return -EACCES; + + cidcfgr = readl(rcc_base + RCC_CIDCFGR(index)); + if (!(cidcfgr & RCC_CIDCFGR_CFEN)) + /* CID filtering is turned off: access granted */ + return 0; + + if (!(cidcfgr & RCC_CIDCFGR_SEM_EN)) { + /* Static CID mode */ + cid = FIELD_GET(RCC_CIDCFGR_SCID_MASK, cidcfgr); + if (cid != RCC_CID1) + return -EACCES; + return 0; + } + + /* Pass-list with semaphore mode */ + if (!(cidcfgr & RCC_CIDCFGR_SEMWLC1_EN)) + return -EACCES; + + semcr = readl(rcc_base + RCC_SEMCR(index)); + + cid = FIELD_GET(RCC_SEMCR_SEMCID_MASK, semcr); + if (cid != RCC_CID1) + return -EACCES; + + return 0; +} + +static int stm32mp25_check_security(struct udevice *dev, void __iomem *base, + const struct clock_config *cfg) +{ + int ret = 0; + + if (cfg->sec_id != SECF_NONE) { + u32 index = (u32)cfg->sec_id; + + if (index & SEC_RIFSC_FLAG) + ret = stm32_rifsc_check_access_by_id(dev_ofnode(dev), + index & ~SEC_RIFSC_FLAG); + else + ret = stm32_rcc_get_access(dev, index); + } + + return ret; +} +#define STM32_COMPOSITE_NODIV(_id, _name, _flags, _sec_id, _gate_id, _mux_id)\ + STM32_COMPOSITE(_id, _name, _flags, _sec_id, _gate_id, _mux_id, NO_STM32_DIV) + +static const struct clock_config stm32mp25_clock_cfg[] = { + /* ADC */ + STM32_GATE(CK_BUS_ADC12, "ck_icn_p_adc12", "ck_icn_ls_mcu", 0, GATE_ADC12, + SEC_RIFSC(58)), + STM32_COMPOSITE_NODIV(CK_KER_ADC12, "ck_ker_adc12", 0, SEC_RIFSC(58), + GATE_ADC12, MUX_ADC12), + STM32_GATE(CK_BUS_ADC3, "ck_icn_p_adc3", "ck_icn_ls_mcu", 0, GATE_ADC3, SEC_RIFSC(59)), + STM32_COMPOSITE_NODIV(CK_KER_ADC3, "ck_ker_adc3", 0, SEC_RIFSC(59), GATE_ADC3, MUX_ADC3), + + /* ADF */ + STM32_GATE(CK_BUS_ADF1, "ck_icn_p_adf1", "ck_icn_ls_mcu", 0, GATE_ADF1, SEC_RIFSC(55)), + STM32_GATE(CK_KER_ADF1, "ck_ker_adf1", "ck_flexgen_42", 0, GATE_ADF1, SEC_RIFSC(55)), + + /* Camera */ + /* DCMI */ + STM32_GATE(CK_BUS_CCI, "ck_icn_p_cci", "ck_icn_ls_mcu", 0, GATE_CCI, SEC_RIFSC(88)), + + /* CSI-HOST */ + STM32_GATE(CK_BUS_CSI, "ck_icn_p_csi", "ck_icn_apb4", 0, GATE_CSI, SEC_RIFSC(86)), + STM32_GATE(CK_KER_CSI, "ck_ker_csi", "ck_flexgen_29", 0, GATE_CSI, SEC_RIFSC(86)), + STM32_GATE(CK_KER_CSITXESC, "ck_ker_csitxesc", "ck_flexgen_30", 0, GATE_CSI, + SEC_RIFSC(86)), + + /* CSI-PHY */ + STM32_GATE(CK_KER_CSIPHY, "ck_ker_csiphy", "ck_flexgen_31", 0, GATE_CSI, + SEC_RIFSC(86)), + + /* DCMIPP */ + STM32_GATE(CK_BUS_DCMIPP, "ck_icn_p_dcmipp", "ck_icn_apb4", 0, GATE_DCMIPP, + SEC_RIFSC(87)), + + /* CRC */ + STM32_GATE(CK_BUS_CRC, "ck_icn_p_crc", "ck_icn_ls_mcu", 0, GATE_CRC, SEC_RIFSC(109)), + + /* CRYP */ + STM32_GATE(CK_BUS_CRYP1, "ck_icn_p_cryp1", "ck_icn_ls_mcu", 0, GATE_CRYP1, + SEC_RIFSC(96)), + STM32_GATE(CK_BUS_CRYP2, "ck_icn_p_cryp2", "ck_icn_ls_mcu", 0, GATE_CRYP2, + SEC_RIFSC(97)), + + /* DBG & TRACE*/ + /* Trace and debug clocks are managed by SCMI */ + + /* Display subsystem */ + /* LTDC */ + STM32_GATE(CK_BUS_LTDC, "ck_icn_p_ltdc", "ck_icn_apb4", 0, GATE_LTDC, SEC_RIFSC(80)), + STM32_GATE(CK_KER_LTDC, "ck_ker_ltdc", "ck_flexgen_27", CLK_SET_RATE_PARENT, GATE_LTDC, + SEC_RIFSC(80)), + + /* DSI */ + STM32_GATE(CK_BUS_DSI, "ck_icn_p_dsi", "ck_icn_apb4", 0, GATE_DSI, SEC_RIFSC(81)), + STM32_COMPOSITE_NODIV(CK_KER_DSIBLANE, "clk_lanebyte", 0, SEC_RIFSC(81), + GATE_DSI, MUX_DSIBLANE), + + /* LVDS */ + STM32_GATE(CK_BUS_LVDS, "ck_icn_p_lvds", "ck_icn_apb4", 0, GATE_LVDS, SEC_RIFSC(84)), + + /* DSI PHY */ + STM32_COMPOSITE_NODIV(CK_KER_DSIPHY, "ck_ker_dsiphy", 0, SEC_RIFSC(81), + GATE_DSI, MUX_DSIPHY), + + /* LVDS PHY */ + STM32_COMPOSITE_NODIV(CK_KER_LVDSPHY, "ck_ker_lvdsphy", 0, SEC_RIFSC(84), + GATE_LVDS, MUX_LVDSPHY), + + /* DTS */ + STM32_COMPOSITE_NODIV(CK_KER_DTS, "ck_ker_dts", 0, SEC_RIFSC(107), GATE_DTS, MUX_DTS), + + /* ETHERNET */ + STM32_GATE(CK_BUS_ETH1, "ck_icn_p_eth1", "ck_icn_ls_mcu", 0, GATE_ETH1, SEC_RIFSC(60)), + STM32_GATE(CK_ETH1_STP, "ck_ker_eth1stp", "ck_icn_ls_mcu", 0, GATE_ETH1STP, + SEC_RIFSC(60)), + STM32_GATE(CK_KER_ETH1, "ck_ker_eth1", "ck_flexgen_54", 0, GATE_ETH1, SEC_RIFSC(60)), + STM32_GATE(CK_KER_ETH1, "ck_ker_eth1ptp", "ck_flexgen_56", 0, GATE_ETH1, SEC_RIFSC(60)), + STM32_GATE(CK_ETH1_MAC, "ck_ker_eth1mac", "ck_icn_ls_mcu", 0, GATE_ETH1MAC, + SEC_RIFSC(60)), + STM32_GATE(CK_ETH1_TX, "ck_ker_eth1tx", "ck_icn_ls_mcu", 0, GATE_ETH1TX, SEC_RIFSC(60)), + STM32_GATE(CK_ETH1_RX, "ck_ker_eth1rx", "ck_icn_ls_mcu", 0, GATE_ETH1RX, SEC_RIFSC(60)), + + STM32_GATE(CK_BUS_ETH2, "ck_icn_p_eth2", "ck_icn_ls_mcu", 0, GATE_ETH2, SEC_RIFSC(61)), + STM32_GATE(CK_ETH2_STP, "ck_ker_eth2stp", "ck_icn_ls_mcu", 0, GATE_ETH2STP, + SEC_RIFSC(61)), + STM32_GATE(CK_KER_ETH2, "ck_ker_eth2", "ck_flexgen_54", 0, GATE_ETH2, SEC_RIFSC(61)), + STM32_GATE(CK_KER_ETH2, "ck_ker_eth2ptp", "ck_flexgen_56", 0, GATE_ETH2, SEC_RIFSC(61)), + STM32_GATE(CK_ETH2_MAC, "ck_ker_eth2mac", "ck_icn_ls_mcu", 0, GATE_ETH2MAC, + SEC_RIFSC(61)), + STM32_GATE(CK_ETH2_TX, "ck_ker_eth2tx", "ck_icn_ls_mcu", 0, GATE_ETH2TX, SEC_RIFSC(61)), + STM32_GATE(CK_ETH2_RX, "ck_ker_eth2rx", "ck_icn_ls_mcu", 0, GATE_ETH2RX, SEC_RIFSC(61)), + + STM32_GATE(CK_BUS_ETHSW, "ck_icn_p_ethsw", "ck_icn_ls_mcu", 0, GATE_ETHSWMAC, + SEC_RIFSC(70)), + STM32_GATE(CK_KER_ETHSW, "ck_ker_ethsw", "ck_flexgen_54", 0, GATE_ETHSW, + SEC_RIFSC(70)), + STM32_GATE(CK_KER_ETHSWREF, "ck_ker_ethswref", "ck_flexgen_60", 0, GATE_ETHSWREF, + SEC_RIFSC(70)), + + /* FDCAN */ + STM32_GATE(CK_BUS_FDCAN, "ck_icn_p_fdcan", "ck_icn_apb2", 0, GATE_FDCAN, SEC_RIFSC(56)), + STM32_GATE(CK_KER_FDCAN, "ck_ker_fdcan", "ck_flexgen_26", 0, GATE_FDCAN, SEC_RIFSC(56)), + + /* GPU */ + STM32_GATE(CK_BUS_GPU, "ck_icn_m_gpu", "ck_flexgen_59", 0, GATE_GPU, SEC_RIFSC(79)), + STM32_GATE(CK_KER_GPU, "ck_ker_gpu", "ck_pll3", 0, GATE_GPU, SEC_RIFSC(79)), + + /* HASH */ + STM32_GATE(CK_BUS_HASH, "ck_icn_p_hash", "ck_icn_ls_mcu", 0, GATE_HASH, SEC_RIFSC(95)), + + /* HDP */ + STM32_GATE(CK_BUS_HDP, "ck_icn_p_hdp", "ck_icn_apb3", 0, GATE_HDP, SEC_RIFSC(57)), + + /* I2C */ + STM32_GATE(CK_KER_I2C1, "ck_ker_i2c1", "ck_flexgen_12", 0, GATE_I2C1, SEC_RIFSC(41)), + STM32_GATE(CK_KER_I2C2, "ck_ker_i2c2", "ck_flexgen_12", 0, GATE_I2C2, SEC_RIFSC(42)), + STM32_GATE(CK_KER_I2C3, "ck_ker_i2c3", "ck_flexgen_13", 0, GATE_I2C3, SEC_RIFSC(43)), + STM32_GATE(CK_KER_I2C5, "ck_ker_i2c5", "ck_flexgen_13", 0, GATE_I2C5, SEC_RIFSC(45)), + STM32_GATE(CK_KER_I2C4, "ck_ker_i2c4", "ck_flexgen_14", 0, GATE_I2C4, SEC_RIFSC(44)), + STM32_GATE(CK_KER_I2C6, "ck_ker_i2c6", "ck_flexgen_14", 0, GATE_I2C6, SEC_RIFSC(46)), + STM32_GATE(CK_KER_I2C7, "ck_ker_i2c7", "ck_flexgen_15", 0, GATE_I2C7, SEC_RIFSC(47)), + STM32_GATE(CK_KER_I2C8, "ck_ker_i2c8", "ck_flexgen_38", 0, GATE_I2C8, SEC_RIFSC(48)), + + /* I3C */ + STM32_GATE(CK_KER_I3C1, "ck_ker_i3c1", "ck_flexgen_12", 0, GATE_I3C1, SEC_RIFSC(114)), + STM32_GATE(CK_KER_I3C2, "ck_ker_i3c2", "ck_flexgen_12", 0, GATE_I3C2, SEC_RIFSC(115)), + STM32_GATE(CK_KER_I3C3, "ck_ker_i3c3", "ck_flexgen_13", 0, GATE_I3C3, SEC_RIFSC(116)), + STM32_GATE(CK_KER_I3C4, "ck_ker_i3c4", "ck_flexgen_36", 0, GATE_I3C4, SEC_RIFSC(117)), + + /* I2S */ + STM32_GATE(CK_BUS_IS2M, "ck_icn_p_is2m", "ck_icn_apb3", 0, GATE_IS2M, SEC_RIFRCC(IS2M)), + + /* IWDG */ + STM32_GATE(CK_BUS_IWDG1, "ck_icn_p_iwdg1", "ck_icn_apb3", 0, GATE_IWDG1, SEC_RIFSC(98)), + STM32_GATE(CK_BUS_IWDG2, "ck_icn_p_iwdg2", "ck_icn_apb3", 0, GATE_IWDG2, SEC_RIFSC(99)), + STM32_GATE(CK_BUS_IWDG3, "ck_icn_p_iwdg3", "ck_icn_apb3", 0, GATE_IWDG3, SEC_RIFSC(100)), + STM32_GATE(CK_BUS_IWDG4, "ck_icn_p_iwdg4", "ck_icn_apb3", 0, GATE_IWDG4, SEC_RIFSC(101)), + STM32_GATE(CK_BUS_IWDG5, "ck_icn_p_iwdg5", "ck_icn_ls_mcu", 0, GATE_IWDG5, + SEC_RIFSC(102)), + + /* LPTIM */ + STM32_GATE(CK_KER_LPTIM1, "ck_ker_lptim1", "ck_flexgen_07", 0, GATE_LPTIM1, + SEC_RIFSC(17)), + STM32_GATE(CK_KER_LPTIM2, "ck_ker_lptim2", "ck_flexgen_07", 0, GATE_LPTIM2, + SEC_RIFSC(18)), + STM32_GATE(CK_KER_LPTIM3, "ck_ker_lptim3", "ck_flexgen_40", 0, GATE_LPTIM3, + SEC_RIFSC(19)), + STM32_GATE(CK_KER_LPTIM4, "ck_ker_lptim4", "ck_flexgen_41", 0, GATE_LPTIM4, + SEC_RIFSC(20)), + STM32_GATE(CK_KER_LPTIM5, "ck_ker_lptim5", "ck_flexgen_41", 0, GATE_LPTIM5, + SEC_RIFSC(21)), + + /* LPUART */ + STM32_GATE(CK_KER_LPUART1, "ck_ker_lpuart1", "ck_flexgen_39", 0, GATE_LPUART1, + SEC_RIFSC(40)), + + /* MCO1 & MCO2 */ + STM32_COMPOSITE_NODIV(CK_MCO1, "ck_mco1", 0, SEC_RIFRCC(MCO1), GATE_MCO1, MUX_MCO1), + STM32_COMPOSITE_NODIV(CK_MCO2, "ck_mco2", 0, SEC_RIFRCC(MCO2), GATE_MCO2, MUX_MCO2), + + /* MDF */ + STM32_GATE(CK_KER_MDF1, "ck_ker_mdf1", "ck_flexgen_23", 0, GATE_MDF1, SEC_RIFSC(54)), + + /* OCTOSPI */ + STM32_GATE(CK_BUS_OSPIIOM, "ck_icn_p_ospiiom", "ck_icn_ls_mcu", 0, GATE_OSPIIOM, + SEC_RIFSC(111)), + + /* PCIE */ + STM32_GATE(CK_BUS_PCIE, "ck_icn_p_pcie", "ck_icn_ls_mcu", 0, GATE_PCIE, SEC_RIFSC(68)), + + /* PKA */ + STM32_GATE(CK_BUS_PKA, "ck_icn_p_pka", "ck_icn_ls_mcu", 0, GATE_PKA, SEC_RIFSC(93)), + + /* RNG */ + STM32_GATE(CK_BUS_RNG, "ck_icn_p_rng", "ck_icn_ls_mcu", CLK_IGNORE_UNUSED, GATE_RNG, + SEC_RIFSC(92)), + + /* SAES */ + STM32_GATE(CK_BUS_SAES, "ck_icn_p_saes", "ck_icn_ls_mcu", 0, GATE_SAES, SEC_RIFSC(94)), + + /* SAI [1..4] */ + STM32_GATE(CK_BUS_SAI1, "ck_icn_p_sai1", "ck_icn_apb2", 0, GATE_SAI1, SEC_RIFSC(49)), + STM32_GATE(CK_BUS_SAI2, "ck_icn_p_sai2", "ck_icn_apb2", 0, GATE_SAI2, SEC_RIFSC(50)), + STM32_GATE(CK_BUS_SAI3, "ck_icn_p_sai3", "ck_icn_apb2", 0, GATE_SAI3, SEC_RIFSC(51)), + STM32_GATE(CK_BUS_SAI4, "ck_icn_p_sai4", "ck_icn_apb2", 0, GATE_SAI4, SEC_RIFSC(52)), + STM32_GATE(CK_KER_SAI1, "ck_ker_sai1", "ck_flexgen_23", 0, GATE_SAI1, SEC_RIFSC(49)), + STM32_GATE(CK_KER_SAI2, "ck_ker_sai2", "ck_flexgen_24", 0, GATE_SAI2, SEC_RIFSC(50)), + STM32_GATE(CK_KER_SAI3, "ck_ker_sai3", "ck_flexgen_25", 0, GATE_SAI3, SEC_RIFSC(51)), + STM32_GATE(CK_KER_SAI4, "ck_ker_sai4", "ck_flexgen_25", 0, GATE_SAI4, SEC_RIFSC(52)), + + /* SDMMC */ + STM32_GATE(CK_KER_SDMMC1, "ck_ker_sdmmc1", "ck_flexgen_51", 0, GATE_SDMMC1, + SEC_RIFSC(76)), + STM32_GATE(CK_KER_SDMMC2, "ck_ker_sdmmc2", "ck_flexgen_52", 0, GATE_SDMMC2, + SEC_RIFSC(77)), + STM32_GATE(CK_KER_SDMMC3, "ck_ker_sdmmc3", "ck_flexgen_53", 0, GATE_SDMMC3, + SEC_RIFSC(78)), + + /* SERC */ + STM32_GATE(CK_BUS_SERC, "ck_icn_p_serc", "ck_icn_apb3", 0, GATE_SERC, SEC_RIFSC(110)), + + /* SPDIF */ + STM32_GATE(CK_KER_SPDIFRX, "ck_ker_spdifrx", "ck_flexgen_11", 0, GATE_SPDIFRX, + SEC_RIFSC(30)), + + /* SPI */ + STM32_GATE(CK_KER_SPI1, "ck_ker_spi1", "ck_flexgen_16", 0, GATE_SPI1, SEC_RIFSC(22)), + STM32_GATE(CK_KER_SPI2, "ck_ker_spi2", "ck_flexgen_10", 0, GATE_SPI2, SEC_RIFSC(23)), + STM32_GATE(CK_KER_SPI3, "ck_ker_spi3", "ck_flexgen_10", 0, GATE_SPI3, SEC_RIFSC(24)), + STM32_GATE(CK_KER_SPI4, "ck_ker_spi4", "ck_flexgen_17", 0, GATE_SPI4, SEC_RIFSC(25)), + STM32_GATE(CK_KER_SPI5, "ck_ker_spi5", "ck_flexgen_17", 0, GATE_SPI5, SEC_RIFSC(26)), + STM32_GATE(CK_KER_SPI6, "ck_ker_spi6", "ck_flexgen_18", 0, GATE_SPI6, SEC_RIFSC(27)), + STM32_GATE(CK_KER_SPI7, "ck_ker_spi7", "ck_flexgen_18", 0, GATE_SPI7, SEC_RIFSC(28)), + STM32_GATE(CK_KER_SPI8, "ck_ker_spi8", "ck_flexgen_37", 0, GATE_SPI8, SEC_RIFSC(29)), + + /* STGEN */ + STM32_GATE(CK_KER_STGEN, "ck_ker_stgen", "ck_flexgen_33", CLK_IGNORE_UNUSED, GATE_STGEN, + SEC_RIFSC(73)), + + /* Timers */ + STM32_GATE(CK_KER_TIM2, "ck_ker_tim2", "timg1_ck", 0, GATE_TIM2, SEC_RIFSC(1)), + STM32_GATE(CK_KER_TIM3, "ck_ker_tim3", "timg1_ck", 0, GATE_TIM3, SEC_RIFSC(2)), + STM32_GATE(CK_KER_TIM4, "ck_ker_tim4", "timg1_ck", 0, GATE_TIM4, SEC_RIFSC(3)), + STM32_GATE(CK_KER_TIM5, "ck_ker_tim5", "timg1_ck", 0, GATE_TIM5, SEC_RIFSC(4)), + STM32_GATE(CK_KER_TIM6, "ck_ker_tim6", "timg1_ck", 0, GATE_TIM6, SEC_RIFSC(5)), + STM32_GATE(CK_KER_TIM7, "ck_ker_tim7", "timg1_ck", 0, GATE_TIM7, SEC_RIFSC(6)), + STM32_GATE(CK_KER_TIM10, "ck_ker_tim10", "timg1_ck", 0, GATE_TIM10, SEC_RIFSC(8)), + STM32_GATE(CK_KER_TIM11, "ck_ker_tim11", "timg1_ck", 0, GATE_TIM11, SEC_RIFSC(9)), + STM32_GATE(CK_KER_TIM12, "ck_ker_tim12", "timg1_ck", 0, GATE_TIM12, SEC_RIFSC(10)), + STM32_GATE(CK_KER_TIM13, "ck_ker_tim13", "timg1_ck", 0, GATE_TIM13, SEC_RIFSC(11)), + STM32_GATE(CK_KER_TIM14, "ck_ker_tim14", "timg1_ck", 0, GATE_TIM14, SEC_RIFSC(12)), + + STM32_GATE(CK_KER_TIM1, "ck_ker_tim1", "timg2_ck", 0, GATE_TIM1, SEC_RIFSC(0)), + STM32_GATE(CK_KER_TIM8, "ck_ker_tim8", "timg2_ck", 0, GATE_TIM8, SEC_RIFSC(7)), + STM32_GATE(CK_KER_TIM15, "ck_ker_tim15", "timg2_ck", 0, GATE_TIM15, SEC_RIFSC(13)), + STM32_GATE(CK_KER_TIM16, "ck_ker_tim16", "timg2_ck", 0, GATE_TIM16, SEC_RIFSC(14)), + STM32_GATE(CK_KER_TIM17, "ck_ker_tim17", "timg2_ck", 0, GATE_TIM17, SEC_RIFSC(15)), + STM32_GATE(CK_KER_TIM20, "ck_ker_tim20", "timg2_ck", 0, GATE_TIM20, SEC_RIFSC(20)), + + /* UART/USART */ + STM32_GATE(CK_KER_USART2, "ck_ker_usart2", "ck_flexgen_08", 0, GATE_USART2, + SEC_RIFSC(32)), + STM32_GATE(CK_KER_UART4, "ck_ker_uart4", "ck_flexgen_08", 0, GATE_UART4, + SEC_RIFSC(34)), + STM32_GATE(CK_KER_USART3, "ck_ker_usart3", "ck_flexgen_09", 0, GATE_USART3, + SEC_RIFSC(33)), + STM32_GATE(CK_KER_UART5, "ck_ker_uart5", "ck_flexgen_09", 0, GATE_UART5, + SEC_RIFSC(35)), + STM32_GATE(CK_KER_USART1, "ck_ker_usart1", "ck_flexgen_19", 0, GATE_USART1, + SEC_RIFSC(31)), + STM32_GATE(CK_KER_USART6, "ck_ker_usart6", "ck_flexgen_20", 0, GATE_USART6, + SEC_RIFSC(36)), + STM32_GATE(CK_KER_UART7, "ck_ker_uart7", "ck_flexgen_21", 0, GATE_UART7, + SEC_RIFSC(37)), + STM32_GATE(CK_KER_UART8, "ck_ker_uart8", "ck_flexgen_21", 0, GATE_UART8, + SEC_RIFSC(38)), + STM32_GATE(CK_KER_UART9, "ck_ker_uart9", "ck_flexgen_22", 0, GATE_UART9, + SEC_RIFSC(39)), + + /* USB2PHY1 */ + STM32_COMPOSITE_NODIV(CK_KER_USB2PHY1, "ck_ker_usb2phy1", 0, SEC_RIFSC(63), + GATE_USB2PHY1, MUX_USB2PHY1), + + /* USBH */ + STM32_GATE(CK_BUS_USB2OHCI, "ck_icn_m_usb2ohci", "ck_icn_hsl", 0, GATE_USBH, + SEC_RIFSC(63)), + STM32_GATE(CK_BUS_USB2EHCI, "ck_icn_m_usb2ehci", "ck_icn_hsl", 0, GATE_USBH, + SEC_RIFSC(63)), + + /* USB2PHY2 */ + STM32_COMPOSITE_NODIV(CK_KER_USB2PHY2EN, "ck_ker_usb2phy2_en", 0, SEC_RIFSC(66), + GATE_USB2PHY2, MUX_USB2PHY2), + + /* USB3 PCIe COMBOPHY */ + STM32_GATE(CK_BUS_USB3PCIEPHY, "ck_icn_p_usb3pciephy", "ck_icn_apb4", 0, GATE_USB3PCIEPHY, + SEC_RIFSC(67)), + + STM32_COMPOSITE_NODIV(CK_KER_USB3PCIEPHY, "ck_ker_usb3pciephy", 0, SEC_RIFSC(67), + GATE_USB3PCIEPHY, MUX_USB3PCIEPHY), + + /* USB3 DRD */ + STM32_GATE(CK_BUS_USB3DR, "ck_icn_m_usb3dr", "ck_icn_hsl", 0, GATE_USB3DR, + SEC_RIFSC(66)), + STM32_GATE(CK_KER_USB2PHY2, "ck_ker_usb2phy2", "ck_flexgen_58", 0, GATE_USB3DR, + SEC_RIFSC(66)), + + /* UCPD */ + STM32_GATE(CK_BUS_USBTC, "ck_icn_p_usbtc", "ck_flexgen_35", 0, GATE_USBTC, + SEC_RIFSC(69)), + STM32_GATE(CK_KER_USBTC, "ck_ker_usbtc", "ck_flexgen_35", 0, GATE_USBTC, + SEC_RIFSC(69)), + + /* VDEC / VENC */ + STM32_GATE(CK_BUS_VDEC, "ck_icn_p_vdec", "ck_icn_apb4", 0, GATE_VDEC, SEC_RIFSC(89)), + STM32_GATE(CK_BUS_VENC, "ck_icn_p_venc", "ck_icn_apb4", 0, GATE_VENC, SEC_RIFSC(90)), + + /* VREF */ + STM32_GATE(CK_BUS_VREF, "ck_icn_p_vref", "ck_icn_apb3", 0, RCC_VREFCFGR, + SEC_RIFSC(106)), + + /* WWDG */ + STM32_GATE(CK_BUS_WWDG1, "ck_icn_p_wwdg1", "ck_icn_apb3", 0, GATE_WWDG1, + SEC_RIFSC(103)), + STM32_GATE(CK_BUS_WWDG2, "ck_icn_p_wwdg2", "ck_icn_ls_mcu", 0, GATE_WWDG2, + SEC_RIFSC(104)), +}; + +static const struct stm32_clock_match_data stm32mp25_data = { + .tab_clocks = stm32mp25_clock_cfg, + .num_clocks = ARRAY_SIZE(stm32mp25_clock_cfg), + .clock_data = &(const struct clk_stm32_clock_data) { + .num_gates = ARRAY_SIZE(stm32mp25_gates), + .gates = stm32mp25_gates, + .muxes = stm32mp25_muxes, + }, + .check_security = stm32mp25_check_security, + +}; + +static int stm32mp25_clk_probe(struct udevice *dev) +{ + fdt_addr_t base = dev_read_addr(dev->parent); + struct udevice *scmi; + + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* force SCMI probe to register all SCMI clocks */ + uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(scmi_clock), &scmi); + + stm32_rcc_init(dev, &stm32mp25_data); + + return 0; +} + +U_BOOT_DRIVER(stm32mp25_clock) = { + .name = "stm32mp25_clk", + .id = UCLASS_CLK, + .ops = &stm32_clk_ops, + .priv_auto = sizeof(struct stm32mp_rcc_priv), + .probe = stm32mp25_clk_probe, +}; diff --git a/drivers/clk/stm32/stm32mp13_rcc.h b/drivers/clk/stm32/stm32mp13_rcc.h index e7191b428af..b9b44b213c3 100644 --- a/drivers/clk/stm32/stm32mp13_rcc.h +++ b/drivers/clk/stm32/stm32mp13_rcc.h @@ -285,4 +285,97 @@ #define RCC_AHB6SECSR_ETH2MACSECF 30 #define RCC_AHB6SECSR_ETH2STPSECF 31 +/* Fields of RCC_BDCR register */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +#define RCC_BDCR_RTCSRC_SHIFT 16 + +/* Fields of RCC_RDLSICR register */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) + +/* used for ALL PLLNCR registers */ +#define RCC_PLLNCR_PLLON BIT(0) +#define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) +#define RCC_PLLNCR_DIVPEN BIT(4) +#define RCC_PLLNCR_DIVQEN BIT(5) +#define RCC_PLLNCR_DIVREN BIT(6) +#define RCC_PLLNCR_DIVEN_SHIFT 4 + +/* used for ALL PLLNCFGR1 registers */ +#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) +#define RCC_PLLNCFGR1_DIVN_SHIFT 0 +#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) +/* only for PLL3 and PLL4 */ +#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 +#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) + +/* used for ALL PLLNCFGR2 registers , using stm32mp1_div_id */ +#define RCC_PLLNCFGR2_SHIFT(div_id) ((div_id) * 8) +#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVP_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_P) +#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVQ_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_Q) +#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLLNCFGR2_DIVR_SHIFT RCC_PLLNCFGR2_SHIFT(_DIV_R) +#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) + +/* used for ALL PLLNFRACR registers */ +#define RCC_PLLNFRACR_FRACV_SHIFT 3 +#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLLNFRACR_FRACLE BIT(16) + +/* used for ALL PLLNCSGR registers */ +#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) + +/* used for RCC_OCENSETR and RCC_OCENCLRR registers */ +#define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_DIGBYP BIT(7) +#define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEBYP BIT(10) +#define RCC_OCENR_HSECSSON BIT(11) + +/* Fields of RCC_OCRDYR register */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) + +/* Fields of DDRITFCR register */ +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_DDRCKMOD_SSR 0 + +/* Fields of RCC_HSICFGR register */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) + +/* used for MCO related operations */ +#define RCC_MCOCFG_MCOON BIT(12) +#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) +#define RCC_MCOCFG_MCODIV_SHIFT 4 +#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) + +/* used for most of SELR register */ +#define RCC_SELR_SRC_MASK GENMASK(2, 0) +#define RCC_SELR_SRCRDY BIT(31) + +/* used for most of DIVR register : max div for RTC */ +#define RCC_DIVR_DIV_MASK GENMASK(5, 0) +#define RCC_DIVR_DIVRDY BIT(31) + #endif /* STM32MP13_RCC_H */ diff --git a/drivers/core/read.c b/drivers/core/read.c index 55c19f335ae..c0d7a969db2 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -38,8 +38,8 @@ int dev_read_u32(const struct udevice *dev, const char *propname, u32 *outp) return ofnode_read_u32(dev_ofnode(dev), propname, outp); } -int dev_read_u32_default(const struct udevice *dev, const char *propname, - int def) +u32 dev_read_u32_default(const struct udevice *dev, const char *propname, + u32 def) { return ofnode_read_u32_default(dev_ofnode(dev), propname, def); } @@ -62,8 +62,8 @@ int dev_read_s32(const struct udevice *dev, const char *propname, s32 *outp) return ofnode_read_u32(dev_ofnode(dev), propname, (u32 *)outp); } -int dev_read_s32_default(const struct udevice *dev, const char *propname, - int def) +s32 dev_read_s32_default(const struct udevice *dev, const char *propname, + s32 def) { return ofnode_read_u32_default(dev_ofnode(dev), propname, def); } diff --git a/drivers/crypto/fsl/jr.c b/drivers/crypto/fsl/jr.c index 1d95d2bff27..8f7a821ebf3 100644 --- a/drivers/crypto/fsl/jr.c +++ b/drivers/crypto/fsl/jr.c @@ -217,6 +217,13 @@ static int jr_enqueue(uint32_t *desc_addr, jr->head = (head + 1) & (jr->size - 1); + /* Invalidate output ring */ + start = (unsigned long)jr->output_ring & + ~(ARCH_DMA_MINALIGN - 1); + end = ALIGN((unsigned long)jr->output_ring + jr->op_size, + ARCH_DMA_MINALIGN); + invalidate_dcache_range(start, end); + sec_out32(®s->irja, 1); return 0; @@ -236,7 +243,6 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) #else uint32_t *addr; #endif - unsigned long start, end; while (sec_in32(®s->orsf) && CIRC_CNT(jr->head, jr->tail, jr->size)) { @@ -244,11 +250,6 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) found = 0; caam_dma_addr_t op_desc; - - /* Invalidate output ring */ - start = (unsigned long)jr->output_ring & ~(ARCH_DMA_MINALIGN - 1); - end = ALIGN((unsigned long)jr->output_ring + jr->op_size, ARCH_DMA_MINALIGN); - invalidate_dcache_range(start, end); #ifdef CONFIG_CAAM_64BIT /* Read the 64 bit Descriptor address from Output Ring. * The 32 bit hign and low part of the address will @@ -282,13 +283,8 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) } /* Error condition if match not found */ - if (!found) { - int slots_full = sec_in32(®s->orsf); - - jr->tail = (jr->tail + slots_full) & (jr->size - 1); - sec_out32(®s->orjr, slots_full); + if (!found) return -1; - } jr->info[idx].op_done = 1; callback = (void *)jr->info[idx].callback; @@ -300,14 +296,14 @@ static int jr_dequeue(int sec_idx, struct caam_regs *caam) */ if (idx == tail) do { - jr->info[tail].op_done = 0; tail = (tail + 1) & (jr->size - 1); } while (jr->info[tail].op_done); jr->tail = tail; - + jr->read_idx = (jr->read_idx + 1) & (jr->size - 1); sec_out32(®s->orjr, 1); + jr->info[idx].op_done = 0; callback(status, arg); } @@ -382,6 +378,7 @@ static int jr_sw_cleanup(uint8_t sec_idx, struct caam_regs *caam) jr->head = 0; jr->tail = 0; + jr->read_idx = 0; jr->write_idx = 0; memset(jr->info, 0, sizeof(jr->info)); memset(jr->input_ring, 0, jr->size * sizeof(caam_dma_addr_t)); diff --git a/drivers/crypto/fsl/jr.h b/drivers/crypto/fsl/jr.h index 8d5ca03e501..b136cd8d05a 100644 --- a/drivers/crypto/fsl/jr.h +++ b/drivers/crypto/fsl/jr.h @@ -83,6 +83,10 @@ struct jobring { * in-order job completion */ int tail; + /* Read index of the output ring. It may not match with tail in case + * of out of order completetion + */ + int read_idx; /* Write index to input ring. Would be always equal to head */ int write_idx; /* Size of the rings. */ diff --git a/drivers/ddr/altera/iossm_mailbox.c b/drivers/ddr/altera/iossm_mailbox.c index fc09dde3f9e..21f94959a04 100644 --- a/drivers/ddr/altera/iossm_mailbox.c +++ b/drivers/ddr/altera/iossm_mailbox.c @@ -41,7 +41,7 @@ /* Offset of Mailbox Read-only Registers */ #define IOSSM_MAILBOX_HEADER_OFFSET 0x0 -#define IOSSM_MEM_INTF_INFO_0_OFFSET 0X200 +#define IOSSM_MEM_INTF_INFO_0_OFFSET 0x200 #define IOSSM_MEM_INTF_INFO_1_OFFSET 0x280 #define IOSSM_MEM_TECHNOLOGY_INTF0_OFFSET 0x210 #define IOSSM_MEM_TECHNOLOGY_INTF1_OFFSET 0x290 diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index c19eb919388..a91671755e1 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -117,7 +117,7 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu, return -1; } - snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d", + snprintf(dev_part_str, sizeof(dev_part_str), "%d:%x", dfu->data.mmc.dev, dfu->data.mmc.part); ret = fs_set_blk_dev("mmc", dev_part_str, fstype); diff --git a/drivers/dfu/dfu_scsi.c b/drivers/dfu/dfu_scsi.c index 9f95194784c..7ec34a8f7e3 100644 --- a/drivers/dfu/dfu_scsi.c +++ b/drivers/dfu/dfu_scsi.c @@ -96,7 +96,7 @@ static int scsi_file_op(enum dfu_op op, struct dfu_entity *dfu, u64 offset, void return -1; } - snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d", dfu->data.scsi.dev, + snprintf(dev_part_str, sizeof(dev_part_str), "%d:%x", dfu->data.scsi.dev, dfu->data.scsi.part); ret = fs_set_blk_dev("scsi", dev_part_str, fstype); diff --git a/drivers/fpga/intel_sdm_mb.c b/drivers/fpga/intel_sdm_mb.c index 5fe4dbdfd32..a2f3b160a73 100644 --- a/drivers/fpga/intel_sdm_mb.c +++ b/drivers/fpga/intel_sdm_mb.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2018 Intel Corporation <www.intel.com> + * Copyright (C) 2025 Altera Corporation <www.altera.com> */ #include <altera.h> @@ -9,6 +10,8 @@ #include <watchdog.h> #include <asm/arch/mailbox_s10.h> #include <asm/arch/smc_api.h> +#include <asm/cache.h> +#include <cpu_func.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/intel-smc.h> @@ -738,6 +741,8 @@ int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) debug("Invoking FPGA_CONFIG_START...\n"); + flush_dcache_range((unsigned long)rbf_data, (unsigned long)(rbf_data + rbf_size)); + ret = invoke_smc(INTEL_SIP_SMC_FPGA_CONFIG_START, &arg, 1, NULL, 0); if (ret) { @@ -1023,6 +1028,8 @@ int intel_sdm_mb_load(Altera_desc *desc, const void *rbf_data, size_t rbf_size) u32 resp_len = 2; u32 resp_buf[2]; + flush_dcache_range((unsigned long)rbf_data, (unsigned long)(rbf_data + rbf_size)); + debug("Sending MBOX_RECONFIG...\n"); ret = mbox_send_cmd(MBOX_ID_UBOOT, MBOX_RECONFIG, MBOX_CMD_DIRECT, 0, NULL, 0, &resp_len, resp_buf); diff --git a/drivers/fwu-mdata/raw_mtd.c b/drivers/fwu-mdata/raw_mtd.c index 78a709f766c..41c153038ab 100644 --- a/drivers/fwu-mdata/raw_mtd.c +++ b/drivers/fwu-mdata/raw_mtd.c @@ -8,6 +8,7 @@ #include <fwu.h> #include <fwu_mdata.h> #include <memalign.h> +#include <mtd.h> #include <linux/errno.h> #include <linux/types.h> diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 2fb14590c0f..f0a79b92b02 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -13,6 +13,7 @@ #include <i2c.h> #include <pca953x.h> #include <vsprintf.h> +#include <asm/byteorder.h> /* Default to an address that hopefully won't corrupt other i2c devices */ #ifndef CFG_SYS_I2C_PCA953X_ADDR diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index e8c1623d41f..a54976e7889 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -404,7 +404,7 @@ static int i2c_wait_for_bb(struct i2c_regs *i2c_base) /* Evaluate timeout */ if (get_timer(start_time_bb) > (unsigned long)(I2C_BYTE_TO_BB)) - return 1; + return -ETIMEDOUT; } return 0; @@ -413,8 +413,10 @@ static int i2c_wait_for_bb(struct i2c_regs *i2c_base) static int i2c_xfer_init(struct i2c_regs *i2c_base, uchar chip, uint addr, int alen) { - if (i2c_wait_for_bb(i2c_base)) - return 1; + int ret = i2c_wait_for_bb(i2c_base); + + if (ret) + return ret; i2c_setaddress(i2c_base, chip); while (alen) { @@ -429,6 +431,7 @@ static int i2c_xfer_init(struct i2c_regs *i2c_base, uchar chip, uint addr, static int i2c_xfer_finish(struct i2c_regs *i2c_base) { ulong start_stop_det = get_timer(0); + int ret; while (1) { if ((readl(&i2c_base->ic_raw_intr_stat) & IC_STOP_DET)) { @@ -439,9 +442,10 @@ static int i2c_xfer_finish(struct i2c_regs *i2c_base) } } - if (i2c_wait_for_bb(i2c_base)) { + ret = i2c_wait_for_bb(i2c_base); + if (ret) { printf("Timed out waiting for bus\n"); - return 1; + return ret; } i2c_flush_rxfifo(i2c_base); @@ -464,6 +468,7 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr, { unsigned long start_time_rx; unsigned int active = 0; + int ret; #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW /* @@ -484,8 +489,9 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr, addr); #endif - if (i2c_xfer_init(i2c_base, dev, addr, alen)) - return 1; + ret = i2c_xfer_init(i2c_base, dev, addr, alen); + if (ret) + return ret; start_time_rx = get_timer(0); while (len) { @@ -510,7 +516,7 @@ static int __dw_i2c_read(struct i2c_regs *i2c_base, u8 dev, uint addr, start_time_rx = get_timer(0); active = 0; } else if (get_timer(start_time_rx) > I2C_BYTE_TO) { - return 1; + return -ETIMEDOUT; } } @@ -532,6 +538,7 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr, { int nb = len; unsigned long start_time_tx; + int ret; #ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW /* @@ -552,8 +559,9 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr, addr); #endif - if (i2c_xfer_init(i2c_base, dev, addr, alen)) - return 1; + ret = i2c_xfer_init(i2c_base, dev, addr, alen); + if (ret) + return ret; start_time_tx = get_timer(0); while (len) { @@ -569,7 +577,7 @@ static int __dw_i2c_write(struct i2c_regs *i2c_base, u8 dev, uint addr, } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) { printf("Timed out. i2c write Failed\n"); - return 1; + return -ETIMEDOUT; } } diff --git a/drivers/iommu/qcom-hyp-smmu.c b/drivers/iommu/qcom-hyp-smmu.c index c1b95bc8b8c..2e51ce4f242 100644 --- a/drivers/iommu/qcom-hyp-smmu.c +++ b/drivers/iommu/qcom-hyp-smmu.c @@ -11,6 +11,7 @@ #include <dm.h> #include <iommu.h> #include <linux/bitfield.h> +#include <linux/bug.h> #include <linux/list.h> #include <linux/err.h> #include <lmb.h> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index ffc5868c0dd..8b8f6309ada 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -114,6 +114,14 @@ config ROCKCHIP_IODOMAIN for the IO-domain setting of the SoC to match the voltage supplied by the regulators. +config SPL_ROCKCHIP_IODOMAIN + bool "Rockchip IO-domain driver support in SPL" + depends on SPL_MISC && SPL_DM_REGULATOR && ARCH_ROCKCHIP + help + Enable support for IO-domains in Rockchip SoCs in SPL. It is necessary + for the IO-domain setting of the SoC to match the voltage supplied + by the regulators. + config SIFIVE_OTP bool "SiFive eMemory OTP driver" depends on MISC diff --git a/drivers/misc/rockchip-io-domain.c b/drivers/misc/rockchip-io-domain.c index 025b6049a9f..a0573c52193 100644 --- a/drivers/misc/rockchip-io-domain.c +++ b/drivers/misc/rockchip-io-domain.c @@ -344,8 +344,10 @@ static int rockchip_iodomain_probe(struct udevice *dev) continue; ret = device_get_supply_regulator(dev, supply_name, ®); - if (ret) + if (ret) { + dev_dbg(dev, "%s: Regulator not found\n", supply_name); continue; + } ret = regulator_autoset(reg); if (ret && ret != -EALREADY && ret != -EMEDIUMTYPE && @@ -353,6 +355,7 @@ static int rockchip_iodomain_probe(struct udevice *dev) continue; uV = regulator_get_value(reg); + dev_dbg(dev, "%s: Regulator %s at %d uV\n", supply_name, reg->name, uV); if (uV <= 0) continue; diff --git a/drivers/misc/stm32_rcc.c b/drivers/misc/stm32_rcc.c index 5a6f979f91b..15bf69f7d57 100644 --- a/drivers/misc/stm32_rcc.c +++ b/drivers/misc/stm32_rcc.c @@ -14,47 +14,56 @@ #include <dm/device_compat.h> #include <dm/lists.h> -struct stm32_rcc_clk stm32_rcc_clk_f42x = { - .drv_name = "stm32fx_rcc_clock", +static const struct stm32_rcc stm32_rcc_f42x = { + .drv_name_clk = "stm32fx_rcc_clock", + .drv_name_rst = "stm32_rcc_reset", .soc = STM32F42X, }; -struct stm32_rcc_clk stm32_rcc_clk_f469 = { - .drv_name = "stm32fx_rcc_clock", +static const struct stm32_rcc stm32_rcc_f469 = { + .drv_name_clk = "stm32fx_rcc_clock", + .drv_name_rst = "stm32_rcc_reset", .soc = STM32F469, }; -struct stm32_rcc_clk stm32_rcc_clk_f7 = { - .drv_name = "stm32fx_rcc_clock", +static const struct stm32_rcc stm32_rcc_f7 = { + .drv_name_clk = "stm32fx_rcc_clock", + .drv_name_rst = "stm32_rcc_reset", .soc = STM32F7, }; -struct stm32_rcc_clk stm32_rcc_clk_h7 = { - .drv_name = "stm32h7_rcc_clock", +static const struct stm32_rcc stm32_rcc_h7 = { + .drv_name_clk = "stm32h7_rcc_clock", + .drv_name_rst = "stm32_rcc_reset", }; -struct stm32_rcc_clk stm32_rcc_clk_mp1 = { - .drv_name = "stm32mp1_clk", - .soc = STM32MP1, +static const struct stm32_rcc stm32_rcc_mp15 = { + .drv_name_clk = "stm32mp1_clk", + .drv_name_rst = "stm32mp1_reset", }; -struct stm32_rcc_clk stm32_rcc_clk_mp13 = { - .drv_name = "stm32mp13_clk", - .soc = STM32MP1, +static const struct stm32_rcc stm32_rcc_mp13 = { + .drv_name_clk = "stm32mp13_clk", + .drv_name_rst = "stm32mp1_reset", +}; + +static const struct stm32_rcc stm32_rcc_mp25 = { + .drv_name_clk = "stm32mp25_clk", + .drv_name_rst = "stm32mp25_reset", }; static int stm32_rcc_bind(struct udevice *dev) { struct udevice *child; struct driver *drv; - struct stm32_rcc_clk *rcc_clk = - (struct stm32_rcc_clk *)dev_get_driver_data(dev); + struct stm32_rcc *rcc_clk = + (struct stm32_rcc *)dev_get_driver_data(dev); int ret; dev_dbg(dev, "RCC bind\n"); - drv = lists_driver_lookup_name(rcc_clk->drv_name); + drv = lists_driver_lookup_name(rcc_clk->drv_name_clk); if (!drv) { - dev_err(dev, "Cannot find driver '%s'\n", rcc_clk->drv_name); + dev_err(dev, "Cannot find driver '%s'\n", rcc_clk->drv_name_clk); return -ENOENT; } @@ -65,25 +74,24 @@ static int stm32_rcc_bind(struct udevice *dev) if (ret) return ret; - drv = lists_driver_lookup_name("stm32_rcc_reset"); + drv = lists_driver_lookup_name(rcc_clk->drv_name_rst); if (!drv) { dev_err(dev, "Cannot find driver stm32_rcc_reset'\n"); return -ENOENT; } - return device_bind_with_driver_data(dev, drv, dev->name, - rcc_clk->soc, - dev_ofnode(dev), &child); + return device_bind(dev, drv, dev->name, NULL, dev_ofnode(dev), &child); } static const struct udevice_id stm32_rcc_ids[] = { - {.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_clk_f42x }, - {.compatible = "st,stm32f469-rcc", .data = (ulong)&stm32_rcc_clk_f469 }, - {.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_clk_f7 }, - {.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_clk_h7 }, - {.compatible = "st,stm32mp1-rcc", .data = (ulong)&stm32_rcc_clk_mp1 }, - {.compatible = "st,stm32mp1-rcc-secure", .data = (ulong)&stm32_rcc_clk_mp1 }, - {.compatible = "st,stm32mp13-rcc", .data = (ulong)&stm32_rcc_clk_mp13 }, + {.compatible = "st,stm32f42xx-rcc", .data = (ulong)&stm32_rcc_f42x }, + {.compatible = "st,stm32f469-rcc", .data = (ulong)&stm32_rcc_f469 }, + {.compatible = "st,stm32f746-rcc", .data = (ulong)&stm32_rcc_f7 }, + {.compatible = "st,stm32h743-rcc", .data = (ulong)&stm32_rcc_h7 }, + {.compatible = "st,stm32mp1-rcc", .data = (ulong)&stm32_rcc_mp15 }, + {.compatible = "st,stm32mp1-rcc-secure", .data = (ulong)&stm32_rcc_mp15 }, + {.compatible = "st,stm32mp13-rcc", .data = (ulong)&stm32_rcc_mp13 }, + {.compatible = "st,stm32mp25-rcc", .data = (ulong)&stm32_rcc_mp25 }, { } }; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 38867f30a7e..1c9b6898bff 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -528,7 +528,7 @@ config SPL_MMC_SDHCI_ADMA config MMC_SDHCI_ADMA_FORCE_32BIT bool "Force 32 bit mode for ADMA on 64 bit platforms" - depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA + depends on MMC_SDHCI_ADMA_HELPERS help This forces SDHCI ADMA to be built for 32 bit descriptors, even on a 64 bit platform where they would otherwise be assumed to @@ -538,7 +538,7 @@ config MMC_SDHCI_ADMA_FORCE_32BIT config MMC_SDHCI_ADMA_64BIT bool "Use SHDCI ADMA with 64 bit descriptors" - depends on MMC_SDHCI_ADMA || SPL_MMC_SDHCI_ADMA + depends on MMC_SDHCI_ADMA_HELPERS depends on !MMC_SDHCI_ADMA_FORCE_32BIT default y if DMA_ADDR_T_64BIT help diff --git a/drivers/mmc/am654_sdhci.c b/drivers/mmc/am654_sdhci.c index 0df3568f073..d3c8f94dd0c 100644 --- a/drivers/mmc/am654_sdhci.c +++ b/drivers/mmc/am654_sdhci.c @@ -527,11 +527,16 @@ static int am654_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) void am654_sdhci_set_control_reg(struct sdhci_host *host) { struct mmc *mmc = host->mmc; + u32 reg; + reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); + reg &= ~SDHCI_CTRL_UHS_MASK; sdhci_set_voltage(host); if (mmc->selected_mode > MMC_HS_52) sdhci_set_uhs_timing(host); + else + sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); } const struct sdhci_ops am654_sdhci_ops = { diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index cdcf2e0c8fe..9421a846e45 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -20,6 +20,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/printk.h> +#include <linux/sizes.h> #include <power/regulator.h> #include <malloc.h> #include <memalign.h> diff --git a/drivers/mmc/sdhci-cadence6.c b/drivers/mmc/sdhci-cadence6.c index a5ed87321ab..9a92b8437a6 100644 --- a/drivers/mmc/sdhci-cadence6.c +++ b/drivers/mmc/sdhci-cadence6.c @@ -19,7 +19,7 @@ #include "sdhci-cadence.h" /* IO Delay Information */ -#define SDHCI_CDNS_HRS07 0X1C +#define SDHCI_CDNS_HRS07 0x1C #define SDHCI_CDNS_HRS07_RW_COMPENSATE GENMASK(20, 16) #define SDHCI_CDNS_HRS07_IDELAY_VAL GENMASK(4, 0) diff --git a/drivers/mmc/snps_sdhci.c b/drivers/mmc/snps_sdhci.c index f5ede38c3c1..fe834ec2969 100644 --- a/drivers/mmc/snps_sdhci.c +++ b/drivers/mmc/snps_sdhci.c @@ -6,6 +6,7 @@ #include <clk.h> #include <dm.h> #include <linux/bitfield.h> +#include <linux/sizes.h> #include <sdhci.h> /* DWCMSHC specific Mode Select value */ diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 0e2bdab4e7e..2375b15539b 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -83,7 +83,7 @@ #define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLY_CHAIN 39 #define VERSAL_NET_EMMC_ICLK_PHASE_DDR52_DLL 146 -#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0X77 +#define VERSAL_NET_PHY_CTRL_STRB90_STRB180_VAL 0x77 struct arasan_sdhci_clk_data { int clk_phase_in[MMC_TIMING_MMC_HS400 + 1]; diff --git a/drivers/mtd/altera_qspi.c b/drivers/mtd/altera_qspi.c index e5c8df750b7..46174aab349 100644 --- a/drivers/mtd/altera_qspi.c +++ b/drivers/mtd/altera_qspi.c @@ -9,10 +9,10 @@ #include <fdt_support.h> #include <flash.h> #include <log.h> -#include <mtd.h> #include <asm/global_data.h> #include <asm/io.h> #include <linux/bitops.h> +#include <linux/mtd/mtd.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c index 4430c4e93ee..7779e63fa5d 100644 --- a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c @@ -165,9 +165,9 @@ static void lpc32xx_cmd_ctrl(struct mtd_info *mtd, int cmd, return; if (ctrl & NAND_CLE) - writeb(cmd & 0Xff, &lpc32xx_nand_mlc_registers->cmd); + writeb(cmd & 0xff, &lpc32xx_nand_mlc_registers->cmd); else if (ctrl & NAND_ALE) - writeb(cmd & 0Xff, &lpc32xx_nand_mlc_registers->addr); + writeb(cmd & 0xff, &lpc32xx_nand_mlc_registers->addr); } /** diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c index 80d9307cdd1..ba67466069b 100644 --- a/drivers/mtd/nand/raw/mxs_nand.c +++ b/drivers/mtd/nand/raw/mxs_nand.c @@ -1507,8 +1507,18 @@ static void mxs_compute_timings(struct nand_chip *chip, writel(GPMI_CTRL1_CLEAR_MASK, &nand_info->gpmi_regs->hw_gpmi_ctrl1_clr); writel(ctrl1n, &nand_info->gpmi_regs->hw_gpmi_ctrl1_set); + /* Clock dividers do NOT guarantee a clean clock signal on its output + * during the change of the divide factor on i.MX6Q/UL/SX. On i.MX7/8, + * all clock dividers provide these guarantee. + */ + if (IS_ENABLED(CONFIG_MX6ULL)) + clk_disable(nand_info->gpmi_clk); + clk_set_rate(nand_info->gpmi_clk, clk_rate); + if (IS_ENABLED(CONFIG_MX6ULL)) + clk_enable(nand_info->gpmi_clk); + /* Wait 64 clock cycles before using the GPMI after enabling the DLL */ dll_wait_time_us = USEC_PER_SEC / clk_rate * 64; if (!dll_wait_time_us) diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c index 11dbcbbf442..90eefa2558d 100644 --- a/drivers/mtd/nand/raw/mxs_nand_dt.c +++ b/drivers/mtd/nand/raw/mxs_nand_dt.c @@ -99,10 +99,8 @@ static int mxs_nand_dt_probe(struct udevice *dev) info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc"); if (IS_ENABLED(CONFIG_CLK) && - (IS_ENABLED(CONFIG_IMX8) || IS_ENABLED(CONFIG_IMX8M))) { - /* Assigned clock already set clock */ - struct clk gpmi_clk; - + (IS_ENABLED(CONFIG_IMX8) || IS_ENABLED(CONFIG_IMX8M) || IS_ENABLED(CONFIG_MX6ULL))) { + struct clk_bulk clk_bulk; info->gpmi_clk = devm_clk_get(dev, "gpmi_io"); if (IS_ERR(info->gpmi_clk)) { @@ -111,47 +109,11 @@ static int mxs_nand_dt_probe(struct udevice *dev) return ret; } - ret = clk_enable(info->gpmi_clk); - if (ret < 0) { - debug("Can't enable gpmi io clk: %d\n", ret); - return ret; - } - - if (IS_ENABLED(CONFIG_IMX8)) { - ret = clk_get_by_name(dev, "gpmi_apb", &gpmi_clk); - if (ret < 0) { - debug("Can't get gpmi_apb clk: %d\n", ret); - return ret; - } - - ret = clk_enable(&gpmi_clk); - if (ret < 0) { - debug("Can't enable gpmi_apb clk: %d\n", ret); - return ret; - } - - ret = clk_get_by_name(dev, "gpmi_bch", &gpmi_clk); - if (ret < 0) { - debug("Can't get gpmi_bch clk: %d\n", ret); - return ret; - } - - ret = clk_enable(&gpmi_clk); - if (ret < 0) { - debug("Can't enable gpmi_bch clk: %d\n", ret); - return ret; - } - } - - ret = clk_get_by_name(dev, "gpmi_bch_apb", &gpmi_clk); - if (ret < 0) { - debug("Can't get gpmi_bch_apb clk: %d\n", ret); - return ret; - } - - ret = clk_enable(&gpmi_clk); + ret = clk_get_bulk(dev, &clk_bulk); + if (!ret) + ret = clk_enable_bulk(&clk_bulk); if (ret < 0) { - debug("Can't enable gpmi_bch_apb clk: %d\n", ret); + debug("Can't enable gpmi clks: %d\n", ret); return ret; } } diff --git a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c index dd4ed257a83..16abf89dbbf 100644 --- a/drivers/mtd/nand/spi/winbond.c +++ b/drivers/mtd/nand/spi/winbond.c @@ -11,6 +11,7 @@ #include <linux/device.h> #include <linux/kernel.h> #endif +#include <linux/bitfield.h> #include <linux/bug.h> #include <linux/mtd/spinand.h> @@ -18,6 +19,8 @@ #define WINBOND_CFG_BUF_READ BIT(3) +#define W25N04KV_STATUS_ECC_5_8_BITFLIPS FIELD_PREP_CONST(STATUS_ECC_MASK, 0x3) + static SPINAND_OP_VARIANTS(read_cache_variants, SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0), SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), @@ -121,6 +124,7 @@ static int w25n02kv_ecc_get_status(struct spinand_device *spinand, return -EBADMSG; case STATUS_ECC_HAS_BITFLIPS: + case W25N04KV_STATUS_ECC_5_8_BITFLIPS: /* * Let's try to retrieve the real maximum number of bitflips * in order to avoid forcing the wear-leveling layer to move @@ -172,6 +176,15 @@ static const struct spinand_info winbond_spinand_table[] = { &update_cache_variants), 0, SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), + SPINAND_INFO("W25N04KV", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa, 0x23), + NAND_MEMORG(1, 2048, 128, 64, 4096, 40, 2, 1, 1), + NAND_ECCREQ(8, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&w25n02kv_ooblayout, w25n02kv_ecc_get_status)), }; static int winbond_spinand_init(struct spinand_device *spinand) diff --git a/drivers/mtd/renesas_rpc_hf.c b/drivers/mtd/renesas_rpc_hf.c index 50a6191d9c2..9390c9e9ab3 100644 --- a/drivers/mtd/renesas_rpc_hf.c +++ b/drivers/mtd/renesas_rpc_hf.c @@ -16,7 +16,6 @@ #include <errno.h> #include <fdt_support.h> #include <flash.h> -#include <mtd.h> #include <wait_bit.h> #include <linux/bitops.h> #include <mtd/cfi_flash.h> diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index 7c0665faa8e..8fa549280aa 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -3,6 +3,7 @@ #include <asm/io.h> #include <cpu_func.h> #include <dm.h> +#include <env.h> #include <malloc.h> #include <net.h> #include <netdev.h> diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index c2869ce4010..86daf0fb2bb 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -45,7 +45,7 @@ #define MC_BUFFER_SIZE (1024 * 1024 * 16) #define MAGIC_MC 0x4d430100 #define MC_FW_ADDR_MASK_LOW 0xE0000000 -#define MC_FW_ADDR_MASK_HIGH 0X1FFFF +#define MC_FW_ADDR_MASK_HIGH 0x1FFFF #define MC_STRUCT_BUFFER_OFFSET 0x01000000 #define MC_OFFSET_DELTA MC_STRUCT_BUFFER_OFFSET diff --git a/drivers/net/mscc_eswitch/jr2_switch.c b/drivers/net/mscc_eswitch/jr2_switch.c index 925888e0765..f0404209116 100644 --- a/drivers/net/mscc_eswitch/jr2_switch.c +++ b/drivers/net/mscc_eswitch/jr2_switch.c @@ -222,7 +222,6 @@ #define CPU_PORT 53 #define IFH_LEN 7 #define JR2_BUF_CELL_SZ 60 -#define ETH_ALEN 6 #define PGID_BROADCAST 510 #define PGID_UNICAST 511 diff --git a/drivers/net/mscc_eswitch/luton_switch.c b/drivers/net/mscc_eswitch/luton_switch.c index 1c584373b8b..be78afc3f79 100644 --- a/drivers/net/mscc_eswitch/luton_switch.c +++ b/drivers/net/mscc_eswitch/luton_switch.c @@ -132,7 +132,6 @@ #define CPU_PORT 26 #define INTERNAL_PORT_MSK 0xFFFFFF #define IFH_LEN 2 -#define ETH_ALEN 6 #define PGID_BROADCAST 28 #define PGID_UNICAST 29 #define PGID_SRC 80 diff --git a/drivers/net/mscc_eswitch/ocelot_switch.c b/drivers/net/mscc_eswitch/ocelot_switch.c index 30bb4b5bad8..b7a8b60587d 100644 --- a/drivers/net/mscc_eswitch/ocelot_switch.c +++ b/drivers/net/mscc_eswitch/ocelot_switch.c @@ -126,7 +126,6 @@ #define CPU_PORT 11 #define INTERNAL_PORT_MSK 0x2FF #define IFH_LEN 4 -#define ETH_ALEN 6 #define PGID_BROADCAST 13 #define PGID_UNICAST 14 #define PGID_SRC 80 diff --git a/drivers/net/mscc_eswitch/serval_switch.c b/drivers/net/mscc_eswitch/serval_switch.c index 8eab41df99a..02f197aa339 100644 --- a/drivers/net/mscc_eswitch/serval_switch.c +++ b/drivers/net/mscc_eswitch/serval_switch.c @@ -111,7 +111,6 @@ #define CPU_PORT 11 #define INTERNAL_PORT_MSK 0xFF #define IFH_LEN 4 -#define ETH_ALEN 6 #define PGID_BROADCAST 13 #define PGID_UNICAST 14 diff --git a/drivers/net/mscc_eswitch/servalt_switch.c b/drivers/net/mscc_eswitch/servalt_switch.c index 61547d7933e..4b073c0781e 100644 --- a/drivers/net/mscc_eswitch/servalt_switch.c +++ b/drivers/net/mscc_eswitch/servalt_switch.c @@ -88,7 +88,6 @@ #define MAC_VID 0 #define CPU_PORT 11 #define IFH_LEN 7 -#define ETH_ALEN 6 #define PGID_BROADCAST 50 #define PGID_UNICAST 51 diff --git a/drivers/net/mvpp2.c b/drivers/net/mvpp2.c index ae545fe229c..184c1f9a46a 100644 --- a/drivers/net/mvpp2.c +++ b/drivers/net/mvpp2.c @@ -3876,7 +3876,6 @@ mvpp2_rxq_next_desc_get(struct mvpp2_rx_queue *rxq) int rx_desc = rxq->next_desc_to_proc; rxq->next_desc_to_proc = MVPP2_QUEUE_NEXT_DESC(rxq, rx_desc); - prefetch(rxq->descs + rxq->next_desc_to_proc); return rxq->descs + rx_desc; } diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 1943de8ba73..c2ce4a80d12 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -61,8 +61,8 @@ static int is_broadcast(struct in_addr ip) /* update only when the environment has changed */ if (env_changed_id != env_id) { - netmask = env_get_ip("netmask"); - our_ip = env_get_ip("ipaddr"); + netmask = string_to_ip(env_get("netmask")); + our_ip = string_to_ip(env_get("ipaddr")); env_changed_id = env_id; } @@ -81,11 +81,12 @@ static int refresh_settings_from_env(void) /* update only when the environment has changed */ if (env_changed_id != env_id) { - if (env_get("ncip")) { - nc_ip = env_get_ip("ncip"); + char *tmp = env_get("ncip"); + if (tmp) { + nc_ip = string_to_ip(tmp); if (!nc_ip.s_addr) return -1; /* ncip is 0.0.0.0 */ - p = strchr(env_get("ncip"), ':'); + p = strchr(tmp, ':'); if (p != NULL) { nc_out_port = dectoul(p + 1, NULL); nc_in_port = nc_out_port; diff --git a/drivers/net/octeontx/nicvf_main.c b/drivers/net/octeontx/nicvf_main.c index 6e4d0a05121..27d0327c88a 100644 --- a/drivers/net/octeontx/nicvf_main.c +++ b/drivers/net/octeontx/nicvf_main.c @@ -279,8 +279,6 @@ int nicvf_cq_handler(struct nicvf *nic, void **ppkt, int *pkt_len) cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head); cqe_head++; cqe_head &= (cq->dmem.q_len - 1); - /* Initiate prefetch for next descriptor */ - prefetch((struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head)); switch (cq_desc->cqe_type) { case CQE_TYPE_RX: diff --git a/drivers/net/pfe_eth/pfe_firmware.c b/drivers/net/pfe_eth/pfe_firmware.c index da4f2ca42a5..b821fb17a1d 100644 --- a/drivers/net/pfe_eth/pfe_firmware.c +++ b/drivers/net/pfe_eth/pfe_firmware.c @@ -12,6 +12,7 @@ #include <dm.h> #include <dm/device-internal.h> +#include <env.h> #include <image.h> #include <log.h> #include <malloc.h> diff --git a/drivers/net/phy/ca_phy.c b/drivers/net/phy/ca_phy.c index 5b2c67d2fda..72d370274a1 100644 --- a/drivers/net/phy/ca_phy.c +++ b/drivers/net/phy/ca_phy.c @@ -73,7 +73,7 @@ static void __external_phy_init(struct phy_device *phydev, int reset_phy) val &= ~(1 << 2); phy_write(phydev, MDIO_DEVAD_NONE, 27, val); - /* REG31 write 0X0000, back to page0 */ + /* REG31 write 0x0000, back to page0 */ phy_write(phydev, MDIO_DEVAD_NONE, 31, 0x0000); } diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 716a1d46111..e6fed8c41d7 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -839,8 +839,6 @@ struct phy_device *phy_find_by_mask(struct mii_dev *bus, uint phy_mask) static void phy_connect_dev(struct phy_device *phydev, struct udevice *dev, phy_interface_t interface) { - /* Soft Reset the PHY */ - phy_reset(phydev); if (phydev->dev && phydev->dev != dev) { printf("%s:%d is connected to %s. Reconnecting to %s\n", phydev->bus->name, phydev->addr, diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 461805ae53f..703e22479d2 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -567,12 +567,14 @@ static int zynq_gem_init(struct udevice *dev) } #endif - ret = clk_get_rate(&priv->tx_clk); - if (ret != clk_rate) { - ret = clk_set_rate(&priv->tx_clk, clk_rate); - if (IS_ERR_VALUE(ret)) { - dev_err(dev, "failed to set tx clock rate %ld\n", clk_rate); - return ret; + if (priv->interface != PHY_INTERFACE_MODE_MII) { + ret = clk_get_rate(&priv->tx_clk); + if (ret != clk_rate) { + ret = clk_set_rate(&priv->tx_clk, clk_rate); + if (IS_ERR_VALUE(ret)) { + dev_err(dev, "failed to set tx clock rate %ld\n", clk_rate); + return ret; + } } } diff --git a/drivers/pci/pcie-xilinx-nwl.c b/drivers/pci/pcie-xilinx-nwl.c index 7ef2bdf57b5..e03ab3be912 100644 --- a/drivers/pci/pcie-xilinx-nwl.c +++ b/drivers/pci/pcie-xilinx-nwl.c @@ -303,6 +303,13 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie) return PTR_ERR(pcie->breg_base); pcie->phys_breg_base = res.start; + ret = dev_read_resource_byname(dev, "pcireg", &res); + if (ret) + return ret; + pcie->pcireg_base = devm_ioremap(dev, res.start, resource_size(&res)); + if (IS_ERR(pcie->pcireg_base)) + return PTR_ERR(pcie->pcireg_base); + ret = dev_read_resource_byname(dev, "cfg", &res); if (ret) return ret; diff --git a/drivers/phy/phy-stm32-usbphyc.c b/drivers/phy/phy-stm32-usbphyc.c index 8d643b762f9..fcf8617ee9b 100644 --- a/drivers/phy/phy-stm32-usbphyc.c +++ b/drivers/phy/phy-stm32-usbphyc.c @@ -16,7 +16,9 @@ #include <syscon.h> #include <usb.h> #include <asm/io.h> +#include <dm/device.h> #include <dm/device_compat.h> +#include <dm/device-internal.h> #include <dm/lists.h> #include <dm/of_access.h> #include <linux/bitfield.h> @@ -633,6 +635,7 @@ U_BOOT_DRIVER(stm32_usb_phyc) = { struct stm32_usbphyc_clk { bool enable; + struct clk clkp; }; static ulong stm32_usbphyc_clk48_get_rate(struct clk *clk) @@ -687,9 +690,25 @@ const struct clk_ops usbphyc_clk48_ops = { .disable = stm32_usbphyc_clk48_disable, }; +int usbphyc_clk48_probe(struct udevice *dev) +{ + struct stm32_usbphyc_clk *priv = dev_get_priv(dev); + + /* prepare clkp to correctly register clock with CCF */ + priv->clkp.dev = dev; + priv->clkp.id = CLK_ID(dev, 0); + + /* Store back pointer to clk from udevice */ + /* FIXME: This is not allowed...should be allocated by driver model */ + dev_set_uclass_priv(dev, &priv->clkp); + + return 0; +} + U_BOOT_DRIVER(stm32_usb_phyc_clk) = { .name = "stm32-usbphyc-clk", .id = UCLASS_CLK, .ops = &usbphyc_clk48_ops, + .probe = &usbphyc_clk48_probe, .priv_auto = sizeof(struct stm32_usbphyc_clk), }; diff --git a/drivers/phy/phy-zynqmp.c b/drivers/phy/phy-zynqmp.c index 7049e740d56..9649e660220 100644 --- a/drivers/phy/phy-zynqmp.c +++ b/drivers/phy/phy-zynqmp.c @@ -138,6 +138,7 @@ #define PROT_BUS_WIDTH_40 0x2 #define PROT_BUS_WIDTH_MASK 0x3 #define PROT_BUS_WIDTH_SHIFT 2 +#define GEM_CLK_CTRL_WIDTH_SHIFT 5 /* Number of GT lanes */ #define NUM_LANES 4 @@ -400,6 +401,7 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy) { struct xpsgtr_dev *gtr_dev = gtr_phy->dev; u32 shift = gtr_phy->lane * PROT_BUS_WIDTH_SHIFT; + u32 clk_ctrl_shift = gtr_phy->lane * GEM_CLK_CTRL_WIDTH_SHIFT; /* Set SGMII protocol TX and RX bus width to 10 bits. */ xpsgtr_clr_set(gtr_dev, TX_PROT_BUS_WIDTH, PROT_BUS_WIDTH_MASK << shift, @@ -417,9 +419,9 @@ static void xpsgtr_phy_init_sgmii(struct xpsgtr_phy *gtr_phy) */ /* GEM I/O Clock Control */ clrsetbits_le32(ZYNQMP_IOU_SLCR_BASEADDR + IOU_SLCR_GEM_CLK_CTRL, - 0xf << shift, + 0xf << clk_ctrl_shift, (GEM_CTRL_GEM_SGMII_MODE | GEM_CTRL_GEM_REF_SRC_SEL) << - shift); + clk_ctrl_shift); /* Setup signal detect */ clrsetbits_le32(ZYNQMP_IOU_SLCR_BASEADDR + IOU_SLCR_GEM_CTRL, diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c index c7459dbc5fc..c48a5cd5267 100644 --- a/drivers/phy/rockchip/phy-rockchip-typec.c +++ b/drivers/phy/rockchip/phy-rockchip-typec.c @@ -284,7 +284,7 @@ DECLARE_GLOBAL_DATA_PTR; * clock 0: PLL 0 div 1 * clock 1: PLL 1 div 2 */ -#define CLK_PLL_CONFIG 0X30 +#define CLK_PLL_CONFIG 0x30 #define CLK_PLL_MASK 0x33 #define CMN_READY BIT(0) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 687fb339ea0..8d47fa0cfd5 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -263,6 +263,24 @@ config PINCTRL_ROCKCHIP_RV1108 both the GPIO definitions and pin control functions for each available multiplex function. +config PINCTRL_SX150X + bool "Semtech SX150x I2C GPIO expander pinctrl driver" + depends on DM && PINCTRL_FULL + help + Say yes here to provide support for Semtech SX150x-series I2C + GPIO expanders as pinctrl module. + Compatible models include: + - 8 bits: sx1508q, sx1502q + - 16 bits: sx1509q, sx1506q + +config SPL_PINCTRL_SX150X + bool "Semtech SX150x I2C GPIO expander pinctrl driver in SPL" + depends on DM && SPL_PINCTRL_FULL + help + This option is an SPL-variant of the PINCTRL_SX150X option. + See the help of PINCTRL_SX150X for details. + + config PINCTRL_SANDBOX bool "Sandbox pinctrl driver" depends on SANDBOX diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index a8eba656843..fc9c604c485 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_PINCTRL_QE) += pinctrl-qe-io.o obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o obj-$(CONFIG_PINCTRL_STI) += pinctrl-sti.o obj-$(CONFIG_PINCTRL_STM32) += pinctrl_stm32.o +obj-$(CONFIG_$(PHASE_)PINCTRL_SX150X) += pinctrl-sx150x.o obj-$(CONFIG_$(PHASE_)PINCTRL_STMFX) += pinctrl-stmfx.o obj-y += broadcom/ obj-$(CONFIG_PINCTRL_ZYNQMP) += pinctrl-zynqmp.o diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c new file mode 100644 index 00000000000..324d7af8fcd --- /dev/null +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -0,0 +1,902 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2024, Exfo Inc - All Rights Reserved + * + * Author: Anis CHALI <anis.chali@exfo.com> + * inspired and adapted from linux driver of sx150x written by Gregory Bean + * <gbean@codeaurora.org> + */ + +#include <asm/gpio.h> +#include <dm.h> +#include <dm/device-internal.h> +#include <dm/device.h> +#include <dm/device_compat.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> +#include <dt-bindings/gpio/gpio.h> +#include <i2c.h> +#include <linux/bitfield.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <log.h> +#include <power/regulator.h> +#include <regmap.h> + +#define err(format, arg...) printf("ERR:" format "\n", ##arg) +#define dbg(format, arg...) printf("DBG:" format "\n", ##arg) + +#define SX150X_PIN(_pin, _name) { .pin = _pin, .name = _name } + +/* The chip models of sx150x */ +enum { + SX150X_123 = 0, + SX150X_456, + SX150X_789, +}; + +enum { + SX150X_789_REG_MISC_AUTOCLEAR_OFF = 1 << 0, + SX150X_MAX_REGISTER = 0xad, + SX150X_IRQ_TYPE_EDGE_RISING = 0x1, + SX150X_IRQ_TYPE_EDGE_FALLING = 0x2, + SX150X_789_RESET_KEY1 = 0x12, + SX150X_789_RESET_KEY2 = 0x34, +}; + +struct sx150x_123_pri { + u8 reg_pld_mode; + u8 reg_pld_table0; + u8 reg_pld_table1; + u8 reg_pld_table2; + u8 reg_pld_table3; + u8 reg_pld_table4; + u8 reg_advanced; +}; + +struct sx150x_456_pri { + u8 reg_pld_mode; + u8 reg_pld_table0; + u8 reg_pld_table1; + u8 reg_pld_table2; + u8 reg_pld_table3; + u8 reg_pld_table4; + u8 reg_advanced; +}; + +struct sx150x_789_pri { + u8 reg_drain; + u8 reg_polarity; + u8 reg_clock; + u8 reg_misc; + u8 reg_reset; + u8 ngpios; +}; + +struct sx150x_pin_desc { + u32 pin; + u8 *name; +}; + +struct sx150x_device_data { + u8 model; + u8 reg_pullup; + u8 reg_pulldn; + u8 reg_dir; + u8 reg_data; + u8 reg_irq_mask; + u8 reg_irq_src; + u8 reg_sense; + u8 ngpios; + union { + struct sx150x_123_pri x123; + struct sx150x_456_pri x456; + struct sx150x_789_pri x789; + } pri; + const struct sx150x_pin_desc *pins; + unsigned int npins; +}; + +struct sx150x_pinctrl_priv { + char name[32]; + struct udevice *gpio; + struct udevice *i2c; + const struct sx150x_device_data *data; +}; + +static const struct sx150x_pin_desc sx150x_4_pins[] = { + SX150X_PIN(0, "gpio0"), SX150X_PIN(1, "gpio1"), SX150X_PIN(2, "gpio2"), + SX150X_PIN(3, "gpio3"), SX150X_PIN(4, "oscio"), +}; + +static const struct sx150x_pin_desc sx150x_8_pins[] = { + SX150X_PIN(0, "gpio0"), SX150X_PIN(1, "gpio1"), SX150X_PIN(2, "gpio2"), + SX150X_PIN(3, "gpio3"), SX150X_PIN(4, "gpio4"), SX150X_PIN(5, "gpio5"), + SX150X_PIN(6, "gpio6"), SX150X_PIN(7, "gpio7"), SX150X_PIN(8, "oscio"), +}; + +static const struct sx150x_pin_desc sx150x_16_pins[] = { + SX150X_PIN(0, "gpio0"), SX150X_PIN(1, "gpio1"), + SX150X_PIN(2, "gpio2"), SX150X_PIN(3, "gpio3"), + SX150X_PIN(4, "gpio4"), SX150X_PIN(5, "gpio5"), + SX150X_PIN(6, "gpio6"), SX150X_PIN(7, "gpio7"), + SX150X_PIN(8, "gpio8"), SX150X_PIN(9, "gpio9"), + SX150X_PIN(10, "gpio10"), SX150X_PIN(11, "gpio11"), + SX150X_PIN(12, "gpio12"), SX150X_PIN(13, "gpio13"), + SX150X_PIN(14, "gpio14"), SX150X_PIN(15, "gpio15"), + SX150X_PIN(16, "oscio"), +}; + +static const struct sx150x_device_data sx1501q_device_data = { + .model = SX150X_123, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x07, + .pri.x123 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table2 = 0x13, + .reg_advanced = 0xad, + }, + .ngpios = 4, + .pins = sx150x_4_pins, + .npins = 4, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1502q_device_data = { + .model = SX150X_123, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x06, + .pri.x123 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table1 = 0x12, + .reg_pld_table2 = 0x13, + .reg_pld_table3 = 0x14, + .reg_pld_table4 = 0x15, + .reg_advanced = 0xad, + }, + .ngpios = 8, + .pins = sx150x_8_pins, + .npins = 8, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1503q_device_data = { + .model = SX150X_123, + .reg_pullup = 0x04, + .reg_pulldn = 0x06, + .reg_dir = 0x02, + .reg_data = 0x00, + .reg_irq_mask = 0x08, + .reg_irq_src = 0x0e, + .reg_sense = 0x0a, + .pri.x123 = { + .reg_pld_mode = 0x20, + .reg_pld_table0 = 0x22, + .reg_pld_table1 = 0x24, + .reg_pld_table2 = 0x26, + .reg_pld_table3 = 0x28, + .reg_pld_table4 = 0x2a, + .reg_advanced = 0xad, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = 16, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1504q_device_data = { + .model = SX150X_456, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x07, + .pri.x456 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table2 = 0x13, + }, + .ngpios = 4, + .pins = sx150x_4_pins, + .npins = 4, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1505q_device_data = { + .model = SX150X_456, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x06, + .pri.x456 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table1 = 0x12, + .reg_pld_table2 = 0x13, + .reg_pld_table3 = 0x14, + .reg_pld_table4 = 0x15, + }, + .ngpios = 8, + .pins = sx150x_8_pins, + .npins = 8, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1506q_device_data = { + .model = SX150X_456, + .reg_pullup = 0x04, + .reg_pulldn = 0x06, + .reg_dir = 0x02, + .reg_data = 0x00, + .reg_irq_mask = 0x08, + .reg_irq_src = 0x0e, + .reg_sense = 0x0a, + .pri.x456 = { + .reg_pld_mode = 0x20, + .reg_pld_table0 = 0x22, + .reg_pld_table1 = 0x24, + .reg_pld_table2 = 0x26, + .reg_pld_table3 = 0x28, + .reg_pld_table4 = 0x2a, + .reg_advanced = 0xad, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = 16, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1507q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x03, + .reg_pulldn = 0x04, + .reg_dir = 0x07, + .reg_data = 0x08, + .reg_irq_mask = 0x09, + .reg_irq_src = 0x0b, + .reg_sense = 0x0a, + .pri.x789 = { + .reg_drain = 0x05, + .reg_polarity = 0x06, + .reg_clock = 0x0d, + .reg_misc = 0x0e, + .reg_reset = 0x7d, + }, + .ngpios = 4, + .pins = sx150x_4_pins, + .npins = ARRAY_SIZE(sx150x_4_pins), +}; + +static const struct sx150x_device_data sx1508q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x03, + .reg_pulldn = 0x04, + .reg_dir = 0x07, + .reg_data = 0x08, + .reg_irq_mask = 0x09, + .reg_irq_src = 0x0c, + .reg_sense = 0x0a, + .pri.x789 = { + .reg_drain = 0x05, + .reg_polarity = 0x06, + .reg_clock = 0x0f, + .reg_misc = 0x10, + .reg_reset = 0x7d, + }, + .ngpios = 8, + .pins = sx150x_8_pins, + .npins = ARRAY_SIZE(sx150x_8_pins), +}; + +static const struct sx150x_device_data sx1509q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x06, + .reg_pulldn = 0x08, + .reg_dir = 0x0e, + .reg_data = 0x10, + .reg_irq_mask = 0x12, + .reg_irq_src = 0x18, + .reg_sense = 0x14, + .pri.x789 = { + .reg_drain = 0x0a, + .reg_polarity = 0x0c, + .reg_clock = 0x1e, + .reg_misc = 0x1f, + .reg_reset = 0x7d, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = ARRAY_SIZE(sx150x_16_pins), +}; + +static bool sx150x_pin_is_oscio(struct sx150x_pinctrl_priv *pctl, + unsigned int pin) +{ + if (pin >= pctl->data->npins) + return false; + + /* OSCIO pin is only present in 789 devices */ + if (pctl->data->model != SX150X_789) + return false; + + return !strcmp(pctl->data->pins[pin].name, "oscio"); +} + +static int sx150x_reg_width(struct sx150x_pinctrl_priv *pctl, unsigned int reg) +{ + const struct sx150x_device_data *data = pctl->data; + + if (reg == data->reg_sense) { + /* + * RegSense packs two bits of configuration per GPIO, + * so we'd need to read twice as many bits as there + * are GPIO in our chip + */ + return 2 * data->ngpios; + } else if ((data->model == SX150X_789 && + (reg == data->pri.x789.reg_misc || + reg == data->pri.x789.reg_clock || + reg == data->pri.x789.reg_reset)) || + (data->model == SX150X_123 && + reg == data->pri.x123.reg_advanced) || + (data->model == SX150X_456 && data->pri.x456.reg_advanced && + reg == data->pri.x456.reg_advanced)) { + return 8; + } else { + return data->ngpios; + } +} + +static unsigned int sx150x_maybe_swizzle(struct sx150x_pinctrl_priv *pctl, + unsigned int reg, unsigned int val) +{ + unsigned int a, b; + const struct sx150x_device_data *data = pctl->data; + + /* + * Whereas SX1509 presents RegSense in a simple layout as such: + * reg [ f f e e d d c c ] + * reg 1 [ b b a a 9 9 8 8 ] + * reg 2 [ 7 7 6 6 5 5 4 4 ] + * reg 3 [ 3 3 2 2 1 1 0 0 ] + * + * SX1503 and SX1506 deviate from that data layout, instead storing + * their contents as follows: + * + * reg [ f f e e d d c c ] + * reg 1 [ 7 7 6 6 5 5 4 4 ] + * reg 2 [ b b a a 9 9 8 8 ] + * reg 3 [ 3 3 2 2 1 1 0 0 ] + * + * so, taking that into account, we swap two + * inner bytes of a 4-byte result + */ + + if (reg == data->reg_sense && data->ngpios == 16 && + (data->model == SX150X_123 || data->model == SX150X_456)) { + a = val & 0x00ff0000; + b = val & 0x0000ff00; + + val &= 0xff0000ff; + val |= b << 8; + val |= a >> 8; + } + + return val; +} + +/* + * In order to mask the differences between 16 and 8 bit expander + * devices we set up a sligthly ficticious regmap that pretends to be + * a set of 32-bit (to accommodate RegSenseLow/RegSenseHigh + * pair/quartet) registers and transparently reconstructs those + * registers via multiple I2C/SMBus reads + * + * This way the rest of the driver code, interfacing with the chip via + * regmap API, can work assuming that each GPIO pin is represented by + * a group of bits at an offset proportional to GPIO number within a + * given register. + */ +static int sx150x_reg_read(struct sx150x_pinctrl_priv *pctl, unsigned int reg, + unsigned int *result) +{ + int ret, n; + const int width = sx150x_reg_width(pctl, reg); + unsigned int idx, val; + + /* + * There are four potential cases covered by this function: + * + * 1) 8-pin chip, single configuration bit register + * + * This is trivial the code below just needs to read: + * reg [ 7 6 5 4 3 2 1 0 ] + * + * 2) 8-pin chip, double configuration bit register (RegSense) + * + * The read will be done as follows: + * reg [ 7 7 6 6 5 5 4 4 ] + * reg 1 [ 3 3 2 2 1 1 0 0 ] + * + * 3) 16-pin chip, single configuration bit register + * + * The read will be done as follows: + * reg [ f e d c b a 9 8 ] + * reg 1 [ 7 6 5 4 3 2 1 0 ] + * + * 4) 16-pin chip, double configuration bit register (RegSense) + * + * The read will be done as follows: + * reg [ f f e e d d c c ] + * reg 1 [ b b a a 9 9 8 8 ] + * reg 2 [ 7 7 6 6 5 5 4 4 ] + * reg 3 [ 3 3 2 2 1 1 0 0 ] + */ + + for (n = width, val = 0, idx = reg; n > 0; n -= 8, idx) { + val <<= 8; + + ret = dm_i2c_reg_read(pctl->i2c, idx); + if (ret < 0) + return ret; + + val |= ret; + } + + *result = sx150x_maybe_swizzle(pctl, reg, val); + + return 0; +} + +static int sx150x_reg_write(struct sx150x_pinctrl_priv *pctl, unsigned int reg, + unsigned int val) +{ + int ret, n; + const int width = sx150x_reg_width(pctl, reg); + + val = sx150x_maybe_swizzle(pctl, reg, val); + + n = (width - 1) & ~7; + do { + const u8 byte = (val >> n) & 0xff; + + ret = dm_i2c_reg_write(pctl->i2c, reg, byte); + if (ret < 0) + return ret; + + reg; + n -= 8; + } while (n >= 0); + + return 0; +} + +static unsigned int sx150x_read(struct sx150x_pinctrl_priv *pctl, uint reg) +{ + int ret; + unsigned int res; + + ret = sx150x_reg_read(pctl, reg, &res); + if (ret) { + err("%s: failed to read reg(%x) with %d", pctl->name, reg, ret); + return ret; + } + + return res; +} + +static int sx150x_write(struct sx150x_pinctrl_priv *pctl, uint reg, uint val) +{ + return sx150x_reg_write(pctl, reg, val); +} + +static int sx150x_write_bits(struct sx150x_pinctrl_priv *pctl, uint reg, + uint mask, uint val) +{ + int orig, tmp; + + orig = sx150x_read(pctl, reg); + if (orig < 0) + return orig; + + tmp = orig & ~mask; + tmp |= val & mask; + + return sx150x_write(pctl, reg, tmp); +} + +static int sx150x_reset(struct udevice *dev) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev); + int err; + + err = sx150x_write(pctl, pctl->data->pri.x789.reg_reset, + SX150X_789_RESET_KEY1); + if (err < 0) + return err; + + err = sx150x_write(pctl, pctl->data->pri.x789.reg_reset, + SX150X_789_RESET_KEY2); + return err; +} + +static int sx150x_init_misc(struct udevice *dev) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev); + u8 reg, value; + + switch (pctl->data->model) { + case SX150X_789: + reg = pctl->data->pri.x789.reg_misc; + value = 0x0; + break; + case SX150X_456: + reg = pctl->data->pri.x456.reg_advanced; + value = 0x00; + + /* + * Only SX1506 has RegAdvanced, SX1504/5 are expected + * to initialize this offset to zero + */ + if (!reg) + return 0; + break; + case SX150X_123: + reg = pctl->data->pri.x123.reg_advanced; + value = 0x00; + break; + default: + WARN(1, "Unknown chip model %d\n", pctl->data->model); + return -EINVAL; + } + + return sx150x_write(pctl, reg, value); +} + +static int sx150x_init_hw(struct udevice *dev) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev); + const u8 reg[] = { + [SX150X_789] = pctl->data->pri.x789.reg_polarity, + [SX150X_456] = pctl->data->pri.x456.reg_pld_mode, + [SX150X_123] = pctl->data->pri.x123.reg_pld_mode, + }; + int err; + + if (pctl->data->model == SX150X_789 && + dev_read_bool(dev, "semtech,probe-reset")) { + err = sx150x_reset(dev); + if (err < 0) + return err; + } + + err = sx150x_init_misc(dev); + if (err < 0) + return err; + + /* Set all pins to work in normal mode */ + return sx150x_write(pctl, reg[pctl->data->model], 0); +} + +static int sx150x_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + + if (sx150x_pin_is_oscio(pctl, offset)) + return -EINVAL; + + int val = sx150x_read(pctl, pctl->data->reg_data); + + return !!(val & BIT(offset)); +} + +static int sx150x_gpio_set(struct udevice *dev, unsigned int offset, int value) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + + return sx150x_write_bits(pctl, pctl->data->reg_data, BIT(offset), + value ? BIT(offset) : 0); +} + +static int sx150x_gpio_oscio_set(struct udevice *dev, int value) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + + return sx150x_write(pctl, pctl->data->pri.x789.reg_clock, + (value ? 0x1f : 0x10)); +} + +static int sx150x_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + + if (sx150x_pin_is_oscio(pctl, offset)) + sx150x_gpio_oscio_set(dev->parent, value); + else + sx150x_gpio_set(dev->parent, offset, value); + + return 0; +} + +static int sx150x_gpio_get_direction(struct udevice *dev, unsigned int offset) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + int val; + + if (sx150x_pin_is_oscio(pctl, offset)) + return GPIOF_OUTPUT; + + val = sx150x_read(pctl, pctl->data->reg_data); + if (val < 0) + return val; + + if (val & BIT(offset)) + return GPIOF_INPUT; + + return GPIOF_OUTPUT; +} + +static int sx150x_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + + if (sx150x_pin_is_oscio(pctl, offset)) + return -EINVAL; + + return sx150x_write_bits(pctl, pctl->data->reg_dir, BIT(offset), + BIT(offset)); +} + +static int sx150x_gpio_direction_output(struct udevice *dev, + unsigned int offset, int value) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + int ret; + + if (sx150x_pin_is_oscio(pctl, offset)) + return sx150x_gpio_oscio_set(dev, value); + + ret = sx150x_write_bits(pctl, pctl->data->reg_dir, BIT(offset), 0); + if (ret < 0) + return ret; + + return sx150x_gpio_set(dev, offset, value); +} + +static int sx150x_gpio_probe(struct udevice *dev) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev->parent); + struct gpio_dev_priv *uc_priv; + + uc_priv = dev_get_uclass_priv(dev); + uc_priv->bank_name = pctl->name; + uc_priv->gpio_count = pctl->data->ngpios; + + return 0; +} + +static struct dm_gpio_ops sx150x_gpio_ops = { + .get_value = sx150x_gpio_get_value, + .set_value = sx150x_gpio_set_value, + .get_function = sx150x_gpio_get_direction, + .direction_input = sx150x_gpio_direction_input, + .direction_output = sx150x_gpio_direction_output, +}; + +static struct driver sx150x_gpio_driver = { + .name = "sx150x-gpio", + .id = UCLASS_GPIO, + .probe = sx150x_gpio_probe, + .ops = &sx150x_gpio_ops, +}; + +static const struct udevice_id sx150x_pinctrl_of_match[] = { + { .compatible = "semtech,sx1501q", + .data = (ulong)&sx1501q_device_data }, + { .compatible = "semtech,sx1502q", + .data = (ulong)&sx1502q_device_data }, + { .compatible = "semtech,sx1503q", + .data = (ulong)&sx1503q_device_data }, + { .compatible = "semtech,sx1504q", + .data = (ulong)&sx1504q_device_data }, + { .compatible = "semtech,sx1505q", + .data = (ulong)&sx1505q_device_data }, + { .compatible = "semtech,sx1506q", + .data = (ulong)&sx1506q_device_data }, + { .compatible = "semtech,sx1507q", + .data = (ulong)&sx1507q_device_data }, + { .compatible = "semtech,sx1508q", + .data = (ulong)&sx1508q_device_data }, + { .compatible = "semtech,sx1509q", + .data = (ulong)&sx1509q_device_data }, + {}, +}; + +static const struct pinconf_param sx150x_conf_params[] = { + { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 }, + { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 }, + { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 }, + { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 }, + { "drive-push-pull", PIN_CONFIG_DRIVE_PUSH_PULL, 0 }, + { "output", PIN_CONFIG_OUTPUT, 0 }, +}; + +static int sx150x_pinctrl_get_pins_count(struct udevice *dev) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev); + + return pctl->data->ngpios; +} + +static const char *sx150x_pinctrl_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev); + static char pin_name[PINNAME_SIZE]; + + snprintf(pin_name, PINNAME_SIZE, "%s", pctl->data->pins[selector].name); + return pin_name; +} + +static int sx150x_pinctrl_conf_set(struct udevice *dev, unsigned int pin, + unsigned int param, unsigned int arg) +{ + int ret; + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev); + + if (sx150x_pin_is_oscio(pctl, pin)) { + if (param == PIN_CONFIG_OUTPUT) { + ret = sx150x_gpio_direction_output(pctl->gpio, pin, + arg); + if (ret < 0) + return ret; + } else { + return -EOPNOTSUPP; + } + } + + switch (param) { + case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: + case PIN_CONFIG_BIAS_DISABLE: + ret = sx150x_write_bits(pctl, pctl->data->reg_pulldn, BIT(pin), + 0); + if (ret < 0) + return ret; + + ret = sx150x_write_bits(pctl, pctl->data->reg_pullup, BIT(pin), + 0); + if (ret < 0) + return ret; + break; + + case PIN_CONFIG_BIAS_PULL_UP: + ret = sx150x_write_bits(pctl, pctl->data->reg_pullup, BIT(pin), + BIT(pin)); + if (ret < 0) + return ret; + + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + ret = sx150x_write_bits(pctl, pctl->data->reg_pulldn, BIT(pin), + BIT(pin)); + if (ret < 0) + return ret; + break; + + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (pctl->data->model != SX150X_789 || + sx150x_pin_is_oscio(pctl, pin)) + return -EOPNOTSUPP; + + ret = sx150x_write_bits(pctl, pctl->data->pri.x789.reg_drain, + BIT(pin), BIT(pin)); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (pctl->data->model != SX150X_789 || + sx150x_pin_is_oscio(pctl, pin)) + return 0; + + ret = sx150x_write_bits(pctl, pctl->data->pri.x789.reg_drain, + BIT(pin), 0); + if (ret < 0) + return ret; + + break; + + case PIN_CONFIG_OUTPUT: + ret = sx150x_gpio_direction_output(pctl->gpio, pin, arg); + if (ret < 0) + return ret; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int sx150x_pinctrl_bind(struct udevice *dev) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_plat(dev); + int ret, reg; + + if (!dev_read_bool(dev, "gpio-controller")) + return 0; + + reg = (int)dev_read_addr_ptr(dev); + + ret = device_bind(dev, &sx150x_gpio_driver, dev_read_name(dev), NULL, + dev_ofnode(dev), &pctl->gpio); + if (ret) + return ret; + + return 0; +} + +static int sx150x_pinctrl_probe(struct udevice *dev) +{ + struct sx150x_pinctrl_priv *pctl = dev_get_priv(dev); + const struct sx150x_device_data *drv_data = + (const struct sx150x_device_data *)dev_get_driver_data(dev); + int ret, reg; + + if (!drv_data) + return -ENOENT; + + pctl->data = drv_data; + + reg = (int)dev_read_addr_ptr(dev); + ret = dm_i2c_probe(dev->parent, reg, 0, &pctl->i2c); + if (ret) { + err("Cannot find I2C chip %02x (%d)", reg, ret); + return ret; + } + + ret = sx150x_init_hw(dev); + if (ret) { + err("Cannot initialize GPIO expander at %02x with %d", reg, + ret); + return ret; + } + + snprintf(pctl->name, 32, "gpio-ext@%x_", reg); + + return 0; +} + +static struct pinctrl_ops sx150x_pinctrl_ops = { + .set_state = pinctrl_generic_set_state, + .get_pins_count = sx150x_pinctrl_get_pins_count, + .get_pin_name = sx150x_pinctrl_get_pin_name, +#if CONFIG_IS_ENABLED(PINCONF) + .pinconf_set = sx150x_pinctrl_conf_set, + .pinconf_num_params = ARRAY_SIZE(sx150x_conf_params), + .pinconf_params = sx150x_conf_params, +#endif +}; + +U_BOOT_DRIVER(sx150x_pinctrl) = { + .name = "sx150x-pinctrl", + .id = UCLASS_PINCTRL, + .of_match = sx150x_pinctrl_of_match, + .priv_auto = sizeof(struct sx150x_pinctrl_priv), + .ops = &sx150x_pinctrl_ops, + .probe = sx150x_pinctrl_probe, + .bind = sx150x_pinctrl_bind, +}; diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c index c22ca03f469..f5daa243082 100644 --- a/drivers/power/axp221.c +++ b/drivers/power/axp221.c @@ -10,6 +10,7 @@ */ #include <command.h> +#include <env.h> #include <errno.h> #include <asm/arch/pmic_bus.h> #include <axp_pmic.h> diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index a14555cf472..3bc696d4caa 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -91,7 +91,7 @@ void rk8xx_off_for_plugin(struct udevice *dev) static struct reg_data rk806_init_reg[] = { /* RST_FUN */ - { RK806_REG_SYS_CFG3, GENMASK(7, 6), BIT(7)}, + { RK806_REG_SYS_CFG3, BIT(7), GENMASK(7, 6)}, }; static struct reg_data rk817_init_reg[] = { diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig index 7ed435f0202..65b99e89656 100644 --- a/drivers/power/regulator/Kconfig +++ b/drivers/power/regulator/Kconfig @@ -264,6 +264,15 @@ config REGULATOR_RK8XX by the PMIC device. This driver is controlled by a device tree node which includes voltage limits. +config SPL_REGULATOR_RK8XX + bool "Enable driver for RK8XX regulators in SPL" + depends on SPL_DM_REGULATOR && SPL_PMIC_RK8XX + help + Enable support for the regulator functions of the RK8XX PMIC in SPL. The + driver implements get/set api for the various BUCKS and LDOs supported + by the PMIC device. This driver is controlled by a device tree node + which includes voltage limits. + config DM_REGULATOR_S2MPS11 bool "Enable driver for S2MPS11 regulator" depends on DM_REGULATOR && PMIC_S2MPS11 diff --git a/drivers/power/regulator/act8846.c b/drivers/power/regulator/act8846.c index d3e72da0d35..144032692f6 100644 --- a/drivers/power/regulator/act8846.c +++ b/drivers/power/regulator/act8846.c @@ -29,7 +29,7 @@ enum { REG_SYS0, REG_SYS1, REG1_VOL = 0x10, - REG1_CTL = 0X11, + REG1_CTL = 0x11, REG2_VOL0 = 0x20, REG2_VOL1, REG2_CTL, @@ -41,7 +41,7 @@ enum { REG4_CTL, REG5_VOL = 0x50, REG5_CTL, - REG6_VOL = 0X58, + REG6_VOL = 0x58, REG6_CTL, REG7_VOL = 0x60, REG7_CTL, diff --git a/drivers/power/regulator/qcom_usb_vbus_regulator.c b/drivers/power/regulator/qcom_usb_vbus_regulator.c index 2d58ef5e111..07f118d4797 100644 --- a/drivers/power/regulator/qcom_usb_vbus_regulator.c +++ b/drivers/power/regulator/qcom_usb_vbus_regulator.c @@ -15,14 +15,33 @@ #include <power/pmic.h> #include <power/regulator.h> -#define CMD_OTG 0x50 +enum pm8x50b_vbus { + PM8150B, + PM8550B, +}; + #define OTG_EN BIT(0) -// The 0 bit in this register's bit field is undocumented -#define OTG_CFG 0x56 + #define OTG_EN_SRC_CFG BIT(1) +struct qcom_otg_regs { + u32 otg_cmd; + u32 otg_cfg; +}; struct qcom_usb_vbus_priv { phys_addr_t base; + struct qcom_otg_regs *regs; +}; + +static const struct qcom_otg_regs qcom_otg[] = { + [PM8150B] = { + .otg_cmd = 0x40, + .otg_cfg = 0x53, + }, + [PM8550B] = { + .otg_cmd = 0x50, + .otg_cfg = 0x56, + }, }; static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev) @@ -38,8 +57,9 @@ static int qcom_usb_vbus_regulator_of_to_plat(struct udevice *dev) static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev) { + const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)]; struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); - int otg_en_reg = priv->base + CMD_OTG; + int otg_en_reg = priv->base + regs->otg_cmd; int ret; ret = pmic_reg_read(dev->parent, otg_en_reg); @@ -53,8 +73,9 @@ static int qcom_usb_vbus_regulator_get_enable(struct udevice *dev) static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable) { + const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)]; struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); - int otg_en_reg = priv->base + CMD_OTG; + int otg_en_reg = priv->base + regs->otg_cmd; int ret; if (enable) { @@ -76,8 +97,9 @@ static int qcom_usb_vbus_regulator_set_enable(struct udevice *dev, bool enable) static int qcom_usb_vbus_regulator_probe(struct udevice *dev) { + const struct qcom_otg_regs *regs = &qcom_otg[dev_get_driver_data(dev)]; struct qcom_usb_vbus_priv *priv = dev_get_priv(dev); - int otg_cfg_reg = priv->base + OTG_CFG; + int otg_cfg_reg = priv->base + regs->otg_cfg; int ret; /* Disable HW logic for VBUS enable */ @@ -96,7 +118,8 @@ static const struct dm_regulator_ops qcom_usb_vbus_regulator_ops = { }; static const struct udevice_id qcom_usb_vbus_regulator_ids[] = { - { .compatible = "qcom,pm8150b-vbus-reg"}, + { .compatible = "qcom,pm8150b-vbus-reg", .data = PM8150B }, + { .compatible = "qcom,pm8550b-vbus-reg", .data = PM8550B }, { }, }; diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c index 368675ebb9f..88453bb7bdb 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -16,10 +16,6 @@ #include <power/pmic.h> #include <power/regulator.h> -#ifndef CONFIG_XPL_BUILD -#define ENABLE_DRIVER -#endif - /* Not used or exisit register and configure */ #define NA 0xff @@ -202,7 +198,7 @@ static const struct rk8xx_reg_info rk818_buck[] = { { 1800000, 100000, REG_BUCK4_ON_VSEL, REG_BUCK4_SLP_VSEL, REG_BUCK4_CONFIG, RK818_BUCK4_VSEL_MASK, 0x00, 0x1f }, }; -#ifdef ENABLE_DRIVER +#if CONFIG_IS_ENABLED(REGULATOR_RK8XX) static const struct rk8xx_reg_info rk806_nldo[] = { /* nldo 1 */ { 500000, 12500, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7}, @@ -454,7 +450,7 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) return ret; } -#ifdef ENABLE_DRIVER +#if CONFIG_IS_ENABLED(REGULATOR_RK8XX) static int _buck_set_suspend_value(struct udevice *pmic, int buck, int uvolt) { const struct rk8xx_reg_info *info = get_buck_reg(pmic, buck, uvolt); diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index de312656746..e4c676d75c2 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -126,3 +126,9 @@ config PWM_TI_EHRPWM default y help PWM driver support for the EHRPWM controller found on TI SOCs. + +config PWM_TI_ECAP + bool "Enable support for ECAP PWM" + depends on DM_PWM && ARCH_OMAP2PLUS + help + PWM driver support for the ECAP controller found on TI SOCs. diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 76305b93bc9..2682c536c6f 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_PWM_TEGRA) += tegra_pwm.o obj-$(CONFIG_PWM_STM32) += pwm-stm32.o obj-$(CONFIG_PWM_SUNXI) += sunxi_pwm.o obj-$(CONFIG_PWM_TI_EHRPWM) += pwm-ti-ehrpwm.o +obj-$(CONFIG_PWM_TI_ECAP) += pwm-tiecap.o diff --git a/drivers/pwm/pwm-ti-ehrpwm.c b/drivers/pwm/pwm-ti-ehrpwm.c index 563109ef0f8..135ea3b4321 100644 --- a/drivers/pwm/pwm-ti-ehrpwm.c +++ b/drivers/pwm/pwm-ti-ehrpwm.c @@ -399,7 +399,7 @@ static int ti_ehrpwm_of_to_plat(struct udevice *dev) return -EINVAL; } - dev_dbg(dev, "regs=0x%08lx\n", priv->regs); + dev_dbg(dev, "regs=0x%08x\n", priv->regs); return 0; } diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c new file mode 100644 index 00000000000..cfd6c871b57 --- /dev/null +++ b/drivers/pwm/pwm-tiecap.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * ECAP PWM driver + * + * Copyright (C) 2025 BayLibre, SAS + * Author: Sukrut Bellary <sbellary@baylibre.com> + */ + +#include <clk.h> +#include <div64.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <pwm.h> +#include <asm/io.h> + +/* eCAP module registers */ +#define ECAP_PWM_CAP1 0x08 +#define ECAP_PWM_CAP2 0x0C +#define ECAP_PWM_CAP3 0x10 +#define ECAP_PWM_CAP4 0x14 + +#define ECAP_PWM_ECCTL2 0x2A +#define ECAP_PWM_ECCTL2_APWM_POL_LOW BIT(10) +#define ECAP_PWM_ECCTL2_APWM_MODE BIT(9) +#define ECAP_PWM_ECCTL2_TSCTR_FREERUN BIT(4) +#define ECAP_PWM_ECCTL2_SYNC_SEL_DISA (BIT(7) | BIT(6)) + +#define NSEC_PER_SEC 1000000000L + +enum tiecap_pwm_polarity { + TIECAP_PWM_POLARITY_NORMAL, + TIECAP_PWM_POLARITY_INVERSED +}; + +enum tiecap_pwm_state { + TIECAP_APWM_DISABLED, + TIECAP_APWM_ENABLED +}; + +struct tiecap_pwm_priv { + fdt_addr_t regs; + u32 clk_rate; + enum tiecap_pwm_state pwm_state; +}; + +static int tiecap_pwm_set_config(struct udevice *dev, uint channel, + uint period_ns, uint duty_ns) +{ + struct tiecap_pwm_priv *priv = dev_get_priv(dev); + u32 period_cycles, duty_cycles; + unsigned long long c; + u16 value; + + c = priv->clk_rate; + c = c * period_ns; + do_div(c, NSEC_PER_SEC); + period_cycles = (u32)c; + + if (period_cycles < 1) { + period_cycles = 1; + duty_cycles = 1; + } else { + c = priv->clk_rate; + c = c * duty_ns; + do_div(c, NSEC_PER_SEC); + duty_cycles = (u32)c; + } + + value = readw(priv->regs + ECAP_PWM_ECCTL2); + + /* Configure APWM mode & disable sync option */ + value |= ECAP_PWM_ECCTL2_APWM_MODE | ECAP_PWM_ECCTL2_SYNC_SEL_DISA; + + writew(value, priv->regs + ECAP_PWM_ECCTL2); + + if (priv->pwm_state == TIECAP_APWM_DISABLED) { + /* Update active registers */ + writel(duty_cycles, priv->regs + ECAP_PWM_CAP2); + writel(period_cycles, priv->regs + ECAP_PWM_CAP1); + } else { + /* Update shadow registers to configure period and + * compare values. This helps current pwm period to + * complete on reconfiguring. + */ + writel(duty_cycles, priv->regs + ECAP_PWM_CAP4); + writel(period_cycles, priv->regs + ECAP_PWM_CAP3); + } + + return 0; +} + +static int tiecap_pwm_set_enable(struct udevice *dev, uint channel, bool enable) +{ + struct tiecap_pwm_priv *priv = dev_get_priv(dev); + u16 value; + + value = readw(priv->regs + ECAP_PWM_ECCTL2); + + if (enable) { + /* + * Enable 'Free run Time stamp counter mode' to start counter + * and 'APWM mode' to enable APWM output + */ + value |= ECAP_PWM_ECCTL2_TSCTR_FREERUN | ECAP_PWM_ECCTL2_APWM_MODE; + priv->pwm_state = TIECAP_APWM_ENABLED; + } else { + /* Disable 'Free run Time stamp counter mode' to stop counter + * and 'APWM mode' to put APWM output to low + */ + value &= ~(ECAP_PWM_ECCTL2_TSCTR_FREERUN | ECAP_PWM_ECCTL2_APWM_MODE); + priv->pwm_state = TIECAP_APWM_DISABLED; + } + + writew(value, priv->regs + ECAP_PWM_ECCTL2); + + return 0; +} + +static int tiecap_pwm_set_invert(struct udevice *dev, uint channel, + bool polarity) +{ + struct tiecap_pwm_priv *priv = dev_get_priv(dev); + u16 value; + + value = readw(priv->regs + ECAP_PWM_ECCTL2); + + if (polarity == TIECAP_PWM_POLARITY_INVERSED) + /* Duty cycle defines LOW period of PWM */ + value |= ECAP_PWM_ECCTL2_APWM_POL_LOW; + else + /* Duty cycle defines HIGH period of PWM */ + value &= ~ECAP_PWM_ECCTL2_APWM_POL_LOW; + + writew(value, priv->regs + ECAP_PWM_ECCTL2); + + return 0; +} + +static int tiecap_pwm_of_to_plat(struct udevice *dev) +{ + struct tiecap_pwm_priv *priv = dev_get_priv(dev); + + priv->regs = dev_read_addr(dev); + if (priv->regs == FDT_ADDR_T_NONE) { + dev_err(dev, "invalid address\n"); + return -EINVAL; + } + + dev_dbg(dev, "regs=0x%08x\n", priv->regs); + + return 0; +} + +static int tiecap_pwm_probe(struct udevice *dev) +{ + struct tiecap_pwm_priv *priv = dev_get_priv(dev); + struct clk clk; + int err; + + err = clk_get_by_name(dev, "fck", &clk); + if (err) { + dev_err(dev, "failed to get clock\n"); + return err; + } + + priv->clk_rate = clk_get_rate(&clk); + if (IS_ERR_VALUE(priv->clk_rate) || !priv->clk_rate) { + dev_err(dev, "failed to get clock rate\n"); + if (IS_ERR_VALUE(priv->clk_rate)) + return priv->clk_rate; + + return -EINVAL; + } + + return 0; +} + +static const struct pwm_ops tiecap_pwm_ops = { + .set_config = tiecap_pwm_set_config, + .set_enable = tiecap_pwm_set_enable, + .set_invert = tiecap_pwm_set_invert, +}; + +static const struct udevice_id tiecap_pwm_ids[] = { + { .compatible = "ti,am3352-ecap" }, + { .compatible = "ti,am33xx-ecap" }, + { } +}; + +U_BOOT_DRIVER(tiecap_pwm) = { + .name = "tiecap_pwm", + .id = UCLASS_PWM, + .of_match = tiecap_pwm_ids, + .ops = &tiecap_pwm_ops, + .probe = tiecap_pwm_probe, + .of_to_plat = tiecap_pwm_of_to_plat, + .priv_auto = sizeof(struct tiecap_pwm_priv), +}; diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index 39d03e8d3d3..edb8e254d5b 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -1,3 +1,5 @@ +menu "RAM drivers using Driver Model" + config RAM bool "Enable RAM drivers using Driver Model" depends on DM @@ -136,3 +138,5 @@ source "drivers/ram/stm32mp1/Kconfig" source "drivers/ram/starfive/Kconfig" source "drivers/ram/sunxi/Kconfig" source "drivers/ram/thead/Kconfig" + +endmenu diff --git a/drivers/ram/k3-ddrss/k3-ddrss.c b/drivers/ram/k3-ddrss/k3-ddrss.c index ff87faf6a22..6590d57ad84 100644 --- a/drivers/ram/k3-ddrss/k3-ddrss.c +++ b/drivers/ram/k3-ddrss/k3-ddrss.c @@ -35,7 +35,7 @@ #define DDRSS_V2A_CTL_REG_SDRAM_IDX_CALC(x) ((ilog2(x) - 16) << 5) #define DDRSS_V2A_CTL_REG_SDRAM_IDX_MASK (~(0x1F << 0x5)) -#define DDRSS_V2A_CTL_REG_REGION_IDX_MASK (~(0X1F)) +#define DDRSS_V2A_CTL_REG_REGION_IDX_MASK (~(0x1F)) #define DDRSS_V2A_CTL_REG_REGION_IDX_DEFAULT 0xF #define DDRSS_ECC_CTRL_REG_DEFAULT 0x0 diff --git a/drivers/ram/octeon/octeon3_lmc.c b/drivers/ram/octeon/octeon3_lmc.c index eaef0fa5c12..dc4b8f8cf23 100644 --- a/drivers/ram/octeon/octeon3_lmc.c +++ b/drivers/ram/octeon/octeon3_lmc.c @@ -8692,7 +8692,7 @@ int init_octeon3_ddr3_interface(struct ddr_priv *priv, bank_bits = min((int)bank_bits, 4); spd_package = - 0XFF & read_spd(&dimm_config_table[0], 0, + 0xFF & read_spd(&dimm_config_table[0], 0, DDR4_SPD_PACKAGE_TYPE); if (spd_package & 0x80) { // non-monolithic device is_stacked_die = ((spd_package & 0x73) == 0x11); diff --git a/drivers/ram/rockchip/Kconfig b/drivers/ram/rockchip/Kconfig index 67c63ecba04..d707d09c1c8 100644 --- a/drivers/ram/rockchip/Kconfig +++ b/drivers/ram/rockchip/Kconfig @@ -15,6 +15,7 @@ if RAM_ROCKCHIP config RAM_ROCKCHIP_DEBUG bool "Rockchip ram drivers debugging" + depends on DEBUG_UART default y help This enables debugging ram driver API's for the platforms diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.c b/drivers/ram/stm32mp1/stm32mp1_ddr.c index 0e37ea93fbc..b275407d4ac 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.c +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.c @@ -12,6 +12,7 @@ #include <timer.h> #include <asm/io.h> #include <asm/arch/ddr.h> +#include <dm/device.h> #include <linux/bitops.h> #include <linux/delay.h> #include <linux/iopoll.h> @@ -19,7 +20,8 @@ #include "stm32mp1_ddr.h" #include "stm32mp1_ddr_regs.h" -#define RCC_DDRITFCR 0xD8 +#define RCC_DDRITFCR_STM32MP13xx 0x5c0 +#define RCC_DDRITFCR_STM32MP15xx 0xd8 #define RCC_DDRITFCR_DDRCAPBRST (BIT(14)) #define RCC_DDRITFCR_DDRCAXIRST (BIT(15)) @@ -66,9 +68,19 @@ struct reg_desc { #define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */ #define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */ #define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */ -#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */ -#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ +#define DDRCTL_REG_PERF_SIZE_STM32MP13xx 11 /* st,ctl-perf */ +#define DDRCTL_REG_PERF_SIZE_STM32MP15xx 17 /* st,ctl-perf */ +#define DDRCTL_REG_PERF_SIZE \ + (IS_ENABLED(CONFIG_STM32MP15X) ? DDRCTL_REG_PERF_SIZE_STM32MP15xx : \ + DDRCTL_REG_PERF_SIZE_STM32MP13xx) + +#define DDRPHY_REG_REG_SIZE_STM32MP13xx 9 /* st,phy-reg */ +#define DDRPHY_REG_REG_SIZE_STM32MP15xx 11 /* st,phy-reg */ +#define DDRPHY_REG_REG_SIZE \ + (IS_ENABLED(CONFIG_STM32MP15X) ? DDRPHY_REG_REG_SIZE_STM32MP15xx : \ + DDRPHY_REG_REG_SIZE_STM32MP13xx) + #define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ #define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) @@ -142,12 +154,14 @@ static const struct reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = { DDRCTL_REG_PERF(pcfgqos1_0), DDRCTL_REG_PERF(pcfgwqos0_0), DDRCTL_REG_PERF(pcfgwqos1_0), +#if IS_ENABLED(CONFIG_STM32MP15X) DDRCTL_REG_PERF(pcfgr_1), DDRCTL_REG_PERF(pcfgw_1), DDRCTL_REG_PERF(pcfgqos0_1), DDRCTL_REG_PERF(pcfgqos1_1), DDRCTL_REG_PERF(pcfgwqos0_1), DDRCTL_REG_PERF(pcfgwqos1_1), +#endif }; #define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg) @@ -161,8 +175,10 @@ static const struct reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = { DDRPHY_REG_REG(zq0cr1), DDRPHY_REG_REG(dx0gcr), DDRPHY_REG_REG(dx1gcr), +#if IS_ENABLED(CONFIG_STM32MP15X) DDRPHY_REG_REG(dx2gcr), DDRPHY_REG_REG(dx3gcr), +#endif }; #define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing) @@ -211,6 +227,7 @@ static const struct reg_desc ddrphy_dyn[] = { DDRPHY_REG_DYN(dx1dllcr), DDRPHY_REG_DYN(dx1dqtr), DDRPHY_REG_DYN(dx1dqstr), +#if IS_ENABLED(CONFIG_STM32MP15X) DDRPHY_REG_DYN(dx2gsr0), DDRPHY_REG_DYN(dx2gsr1), DDRPHY_REG_DYN(dx2dllcr), @@ -221,6 +238,7 @@ static const struct reg_desc ddrphy_dyn[] = { DDRPHY_REG_DYN(dx3dllcr), DDRPHY_REG_DYN(dx3dqtr), DDRPHY_REG_DYN(dx3dqstr), +#endif }; #define DDRPHY_REG_DYN_SIZE ARRAY_SIZE(ddrphy_dyn) @@ -287,6 +305,24 @@ const char *base_name[] = { [DDRPHY_BASE] = "phy", }; +bool is_stm32mp13_ddrc(const struct ddr_info *priv) +{ + if (IS_ENABLED(CONFIG_STM32MP13X) && !IS_ENABLED(CONFIG_STM32MP15X)) + return true; /* STM32MP13xx only build */ + else if (!IS_ENABLED(CONFIG_STM32MP13X) && IS_ENABLED(CONFIG_STM32MP15X)) + return false; /* STM32MP15xx only build */ + + /* Combined STM32MP13xx and STM32MP15xx build */ + return device_is_compatible(priv->dev, "st,stm32mp13-ddr"); +} + +static u32 get_rcc_ddritfcr(const struct ddr_info *priv) +{ + return priv->rcc + (is_stm32mp13_ddrc(priv) ? + RCC_DDRITFCR_STM32MP13xx : + RCC_DDRITFCR_STM32MP15xx); +} + static u32 get_base_addr(const struct ddr_info *priv, enum base_type base) { if (base == DDRPHY_BASE) @@ -295,6 +331,21 @@ static u32 get_base_addr(const struct ddr_info *priv, enum base_type base) return (u32)priv->ctl; } +static u32 get_type_size(const struct ddr_info *priv, enum reg_type type) +{ + bool is_mp13 = is_stm32mp13_ddrc(priv); + + if (type == REG_PERF) + return is_mp13 ? DDRCTL_REG_PERF_SIZE_STM32MP13xx : + DDRCTL_REG_PERF_SIZE_STM32MP15xx; + else if (type == REGPHY_REG) + return is_mp13 ? DDRPHY_REG_REG_SIZE_STM32MP13xx : + DDRPHY_REG_REG_SIZE_STM32MP15xx; + + /* Everything else is the default size */ + return ddr_registers[type].size; +} + static void set_reg(const struct ddr_info *priv, enum reg_type type, const void *param) @@ -304,9 +355,10 @@ static void set_reg(const struct ddr_info *priv, enum base_type base = ddr_registers[type].base; u32 base_addr = get_base_addr(priv, base); const struct reg_desc *desc = ddr_registers[type].desc; + u32 size = get_type_size(priv, type); log_debug("init %s\n", ddr_registers[type].name); - for (i = 0; i < ddr_registers[type].size; i++) { + for (i = 0; i < size; i++) { ptr = (unsigned int *)(base_addr + desc[i].offset); if (desc[i].par_offset == INVALID_OFFSET) { log_err("invalid parameter offset for %s", desc[i].name); @@ -656,12 +708,13 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, static void stm32mp1_asr_enable(struct ddr_info *priv, const u32 pwrctl) { struct stm32mp1_ddrctl *ctl = priv->ctl; + u32 rcc_ddritfcr = get_rcc_ddritfcr(priv); /* SSR is the best we can do. */ if (!(pwrctl & DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE)) return; - clrsetbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCKMOD_MASK, + clrsetbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCKMOD_MASK, RCC_DDRITFCR_DDRCKMOD_ASR); start_sw_done(ctl); @@ -691,6 +744,7 @@ __maybe_unused void stm32mp1_ddr_init(struct ddr_info *priv, const struct stm32mp1_ddr_config *config) { + u32 rcc_ddritfcr = get_rcc_ddritfcr(priv); u32 pir; int ret = -EINVAL; char bus_width; @@ -732,12 +786,12 @@ start: * 1.1 RESETS: presetn, core_ddrc_rstn, aresetn */ /* Assert All DDR part */ - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); - setbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAXIRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCORERST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYAPBRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYRST); + setbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYCTLRST); /* 1.2. start CLOCK */ if (stm32mp1_ddr_clk_enable(priv, config->info.speed)) @@ -746,12 +800,12 @@ start: /* 1.3. deassert reset */ /* de-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST */ - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYCTLRST); /* De-assert presetn once the clocks are active * and stable via DDRCAPBRST bit */ - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAPBRST); /* 1.4. wait 128 cycles to permit initialization of end logic */ udelay(2); @@ -781,9 +835,9 @@ start: goto start; /* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */ - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); - clrbits_le32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCORERST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DDRCAXIRST); + clrbits_le32(rcc_ddritfcr, RCC_DDRITFCR_DPHYAPBRST); /* 3. start PHY init by accessing relevant PUBL registers * (DXGCR, DCR, PTR*, MR*, DTPR*) @@ -854,9 +908,12 @@ start: /* Enable auto-self-refresh, which saves a bit of power at runtime. */ stm32mp1_asr_enable(priv, config->c_reg.pwrctl); - /* enable uMCTL2 AXI port 0 and 1 */ + /* enable uMCTL2 AXI port 0 */ setbits_le32(&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); - setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); + + /* enable uMCTL2 AXI port 1 only on STM32MP15xx with 32bit DRAM bus */ + if (!is_stm32mp13_ddrc(priv)) + setbits_le32(&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); if (INTERACTIVE(STEP_DDR_READY)) goto start; diff --git a/drivers/ram/stm32mp1/stm32mp1_ddr.h b/drivers/ram/stm32mp1/stm32mp1_ddr.h index 861efff92be..3621e6c9a1b 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ddr.h +++ b/drivers/ram/stm32mp1/stm32mp1_ddr.h @@ -105,12 +105,14 @@ struct stm32mp1_ddrctrl_perf { u32 pcfgqos1_0; u32 pcfgwqos0_0; u32 pcfgwqos1_0; +#if IS_ENABLED(CONFIG_STM32MP15X) u32 pcfgr_1; u32 pcfgw_1; u32 pcfgqos0_1; u32 pcfgqos1_1; u32 pcfgwqos0_1; u32 pcfgwqos1_1; +#endif }; struct stm32mp1_ddrphy_reg { @@ -123,8 +125,10 @@ struct stm32mp1_ddrphy_reg { u32 zq0cr1; u32 dx0gcr; u32 dx1gcr; +#if IS_ENABLED(CONFIG_STM32MP15X) u32 dx2gcr; u32 dx3gcr; +#endif }; struct stm32mp1_ddrphy_timing { @@ -181,4 +185,6 @@ bool stm32mp1_ddr_interactive( enum stm32mp1_ddr_interact_step step, const struct stm32mp1_ddr_config *config); +bool is_stm32mp13_ddrc(const struct ddr_info *priv); + #endif diff --git a/drivers/ram/stm32mp1/stm32mp1_ram.c b/drivers/ram/stm32mp1/stm32mp1_ram.c index e9cd6229ec4..5f9b91d50e4 100644 --- a/drivers/ram/stm32mp1/stm32mp1_ram.c +++ b/drivers/ram/stm32mp1/stm32mp1_ram.c @@ -33,6 +33,7 @@ static const char *const clkname[] = { int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) { + bool is_mp13 = is_stm32mp13_ddrc(priv); unsigned long ddrphy_clk; unsigned long ddr_clk; struct clk clk; @@ -40,6 +41,10 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) unsigned int idx; for (idx = 0; idx < ARRAY_SIZE(clkname); idx++) { + /* DDRC2 clock are available only on STM32MP15xx */ + if (is_mp13 && !strcmp(clkname[idx], "ddrc2")) + continue; + ret = clk_get_by_name(priv->dev, clkname[idx], &clk); if (!ret) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index a0d079c4555..e92bb8a7c39 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -28,13 +28,6 @@ config STI_RESET Say Y if you want to control reset signals provided by system config block. -config STM32_RESET - bool "Enable the STM32 reset" - depends on ARCH_STM32 || ARCH_STM32MP - help - Support for reset controllers on STMicroelectronics STM32 family SoCs. - This reset driver is compatible with STM32 F4/F7 and H7 SoCs. - config TEGRA_CAR_RESET bool "Enable Tegra CAR-based reset driver" depends on TEGRA_CAR @@ -258,4 +251,6 @@ config RESET_SPACEMIT_K1 help Support for SPACEMIT's K1 Reset system. Basic Assert/Deassert is supported. + +source "drivers/reset/stm32/Kconfig" endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 1dd3cd99a14..ee5b009d134 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_DM_RESET) += reset-uclass.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o obj-$(CONFIG_STI_RESET) += sti-reset.o -obj-$(CONFIG_STM32_RESET) += stm32-reset.o obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o obj-$(CONFIG_RESET_AIROHA) += reset-airoha.o @@ -36,3 +35,6 @@ obj-$(CONFIG_RESET_AT91) += reset-at91.o obj-$(CONFIG_$(PHASE_)RESET_JH7110) += reset-jh7110.o obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o obj-$(CONFIG_RESET_SPACEMIT_K1) += reset-spacemit-k1.o + +obj-$(CONFIG_ARCH_STM32) += stm32/ +obj-$(CONFIG_ARCH_STM32MP) += stm32/ diff --git a/drivers/reset/stm32-reset.c b/drivers/reset/stm32-reset.c deleted file mode 100644 index 9d4f361b251..00000000000 --- a/drivers/reset/stm32-reset.c +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2017, STMicroelectronics - All Rights Reserved - * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics. - */ - -#define LOG_CATEGORY UCLASS_RESET - -#include <dm.h> -#include <errno.h> -#include <log.h> -#include <malloc.h> -#include <reset-uclass.h> -#include <stm32_rcc.h> -#include <asm/io.h> -#include <dm/device_compat.h> -#include <linux/bitops.h> - -/* offset of register without set/clear management */ -#define RCC_MP_GCR_OFFSET 0x10C - -/* reset clear offset for STM32MP RCC */ -#define RCC_CL 0x4 - -struct stm32_reset_priv { - fdt_addr_t base; -}; - -static int stm32_reset_assert(struct reset_ctl *reset_ctl) -{ - struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev); - int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4; - int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE); - - dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n", - reset_ctl->id, bank, offset); - - if (dev_get_driver_data(reset_ctl->dev) == STM32MP1) - if (bank != RCC_MP_GCR_OFFSET) - /* reset assert is done in rcc set register */ - writel(BIT(offset), priv->base + bank); - else - clrbits_le32(priv->base + bank, BIT(offset)); - else - setbits_le32(priv->base + bank, BIT(offset)); - - return 0; -} - -static int stm32_reset_deassert(struct reset_ctl *reset_ctl) -{ - struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev); - int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4; - int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE); - - dev_dbg(reset_ctl->dev, "reset id = %ld bank = %d offset = %d)\n", - reset_ctl->id, bank, offset); - - if (dev_get_driver_data(reset_ctl->dev) == STM32MP1) - if (bank != RCC_MP_GCR_OFFSET) - /* reset deassert is done in rcc clr register */ - writel(BIT(offset), priv->base + bank + RCC_CL); - else - setbits_le32(priv->base + bank, BIT(offset)); - else - clrbits_le32(priv->base + bank, BIT(offset)); - - return 0; -} - -static const struct reset_ops stm32_reset_ops = { - .rst_assert = stm32_reset_assert, - .rst_deassert = stm32_reset_deassert, -}; - -static int stm32_reset_probe(struct udevice *dev) -{ - struct stm32_reset_priv *priv = dev_get_priv(dev); - - priv->base = dev_read_addr(dev); - if (priv->base == FDT_ADDR_T_NONE) { - /* for MFD, get address of parent */ - priv->base = dev_read_addr(dev->parent); - if (priv->base == FDT_ADDR_T_NONE) - return -EINVAL; - } - - return 0; -} - -U_BOOT_DRIVER(stm32_rcc_reset) = { - .name = "stm32_rcc_reset", - .id = UCLASS_RESET, - .probe = stm32_reset_probe, - .priv_auto = sizeof(struct stm32_reset_priv), - .ops = &stm32_reset_ops, -}; diff --git a/drivers/reset/stm32/Kconfig b/drivers/reset/stm32/Kconfig new file mode 100644 index 00000000000..39dcfa0a9ca --- /dev/null +++ b/drivers/reset/stm32/Kconfig @@ -0,0 +1,23 @@ +config RESET_STM32 + bool "Enable the STM32 reset" + depends on ARCH_STM32 + default y + help + Support for reset controllers on STMicroelectronics STM32 family SoCs. + This reset driver is compatible with STM32 F4/F7 and H7 SoCs. + +config RESET_STM32MP1 + bool "Enable the STM32MP1 reset" + depends on STM32MP13X || STM32MP15X + default y + help + Support for reset controllers on STMicroelectronics STM32MP1 family SoCs. + This reset driver is compatible with STM32MP13 and STM32MP15 SoCs. + +config RESET_STM32MP25 + bool "Enable the STM32MP25 reset" + depends on STM32MP25X + default y + help + Support for reset controllers on STMicroelectronics STM32MP2 family SoCs. + This reset driver is compatible with STM32MP25 SoCs. diff --git a/drivers/reset/stm32/Makefile b/drivers/reset/stm32/Makefile new file mode 100644 index 00000000000..c31ae524ba1 --- /dev/null +++ b/drivers/reset/stm32/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Copyright (C) 2024, STMicroelectronics - All Rights Reserved + +obj-y += stm32-reset-core.o + +obj-$(CONFIG_RESET_STM32) += stm32-reset.o +obj-$(CONFIG_RESET_STM32MP1) += stm32-reset-mp1.o +obj-$(CONFIG_RESET_STM32MP25) += stm32-reset-mp25.o diff --git a/drivers/reset/stm32/stm32-reset-core.c b/drivers/reset/stm32/stm32-reset-core.c new file mode 100644 index 00000000000..7dd92e07e1a --- /dev/null +++ b/drivers/reset/stm32/stm32-reset-core.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2024, STMicroelectronics - All Rights Reserved + * Author(s): Gabriel Fernandez, <gabriel.fernandez@foss.st.com> for STMicroelectronics. + */ + +#include <dm.h> +#include <reset-uclass.h> +#include <stm32-reset-core.h> +#include <stm32_rcc.h> +#include <dm/device_compat.h> +#include <linux/iopoll.h> + +static int stm32_reset_update(struct reset_ctl *reset_ctl, bool status) +{ + struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev); + const struct stm32_reset_data *data = priv->data; + const struct stm32_reset_cfg *ptr_line; + fdt_addr_t addr; + + assert(priv->data->get_reset_line); + + ptr_line = priv->data->get_reset_line(reset_ctl); + if (!ptr_line) + return -EPERM; + + addr = priv->base + ptr_line->offset; + + dev_dbg(reset_ctl->dev, "reset id=%ld offset=0x%x bit=%d status=%d\n", + reset_ctl->id, ptr_line->offset, ptr_line->bit_idx, status); + + status = ptr_line->inverted ^ status; + + if (ptr_line->set_clr) { + if (!status) + addr += data->clear_offset; + + writel(BIT(ptr_line->bit_idx), addr); + + } else { + if (status) + setbits_le32(addr, BIT(ptr_line->bit_idx)); + else + clrbits_le32(addr, BIT(ptr_line->bit_idx)); + } + + /* Check deassert */ + if (!status) { + u32 reg; + + return readl_poll_timeout(addr, reg, + !(reg & BIT(ptr_line->bit_idx)), + data->reset_us); + } + + return 0; +} + +static int stm32_reset_assert(struct reset_ctl *reset_ctl) +{ + return stm32_reset_update(reset_ctl, true); +} + +static int stm32_reset_deassert(struct reset_ctl *reset_ctl) +{ + return stm32_reset_update(reset_ctl, false); +} + +const struct reset_ops stm32_reset_ops = { + .rst_assert = stm32_reset_assert, + .rst_deassert = stm32_reset_deassert, +}; + +int stm32_reset_core_probe(struct udevice *dev, + const struct stm32_reset_data *data) +{ + struct stm32_reset_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) { + /* for MFD, get address of parent */ + priv->base = dev_read_addr(dev->parent); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + } + + priv->data = data; + + assert(priv->data); + + return 0; +} diff --git a/drivers/reset/stm32/stm32-reset-core.h b/drivers/reset/stm32/stm32-reset-core.h new file mode 100644 index 00000000000..25a1aa152cb --- /dev/null +++ b/drivers/reset/stm32/stm32-reset-core.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/* + * Copyright (C) 2025, STMicroelectronics - All Rights Reserved + * Author(s): Gabriel Fernandez, <gabriel.fernandez@foss.st.com> for STMicroelectronics. + */ + +#include <reset-uclass.h> + +struct stm32_reset_cfg { + u16 offset; + u8 bit_idx; + bool set_clr; + bool inverted; +}; + +struct stm32_reset_data { + const struct stm32_reset_cfg * (*get_reset_line)(struct reset_ctl *reset_ctl); + u32 clear_offset; + u32 reset_us; +}; + +struct stm32_reset_priv { + fdt_addr_t base; + struct stm32_reset_cfg reset_line; + const struct stm32_reset_data *data; +}; + +extern const struct reset_ops stm32_reset_ops; + +int stm32_reset_core_probe(struct udevice *dev, + const struct stm32_reset_data *data); diff --git a/drivers/reset/stm32/stm32-reset-mp1.c b/drivers/reset/stm32/stm32-reset-mp1.c new file mode 100644 index 00000000000..6863f6e64b7 --- /dev/null +++ b/drivers/reset/stm32/stm32-reset-mp1.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics. + */ + +#include <dm.h> +#include <stm32-reset-core.h> + +/* Reset clear offset for STM32MP RCC */ +#define RCC_CLR_OFFSET 0x4 + +/* Offset of register without set/clear management */ +#define RCC_MP_GCR_OFFSET 0x10C + +/* Timeout for deassert */ +#define STM32_DEASSERT_TIMEOUT_US 10000 + +static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_ctl *reset_ctl) +{ + struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev); + struct stm32_reset_cfg *ptr_line = &priv->reset_line; + int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4; + int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE); + + ptr_line->offset = bank; + ptr_line->bit_idx = offset; + ptr_line->set_clr = true; + + if (ptr_line->offset == RCC_MP_GCR_OFFSET) { + ptr_line->set_clr = false; + ptr_line->inverted = true; + } + + return ptr_line; +} + +static const struct stm32_reset_data stm32mp1_reset_data = { + .get_reset_line = stm32_get_reset_line, + .clear_offset = RCC_CLR_OFFSET, + .reset_us = STM32_DEASSERT_TIMEOUT_US, +}; + +static int stm32_reset_probe(struct udevice *dev) +{ + return stm32_reset_core_probe(dev, &stm32mp1_reset_data); +} + +U_BOOT_DRIVER(stm32mp25_rcc_reset) = { + .name = "stm32mp1_reset", + .id = UCLASS_RESET, + .probe = stm32_reset_probe, + .priv_auto = sizeof(struct stm32_reset_priv), + .ops = &stm32_reset_ops, +}; diff --git a/drivers/reset/stm32/stm32-reset-mp25.c b/drivers/reset/stm32/stm32-reset-mp25.c new file mode 100644 index 00000000000..91c0336bc58 --- /dev/null +++ b/drivers/reset/stm32/stm32-reset-mp25.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2024, STMicroelectronics - All Rights Reserved + * Author(s): Gabriel Fernandez, <gabriel.fernandez@foss.st.com> for STMicroelectronics. + */ + +#include <dm.h> +#include <stm32-reset-core.h> +#include <stm32mp25_rcc.h> +#include <dt-bindings/reset/st,stm32mp25-rcc.h> + +/* Reset clear offset for STM32MP RCC */ +#define RCC_CLR_OFFSET 0x4 + +/* Timeout for deassert */ +#define STM32_DEASSERT_TIMEOUT_US 10000 + +#define RESET(id, _offset, _bit_idx, _set_clr) \ + [id] = &(struct stm32_reset_cfg){ \ + .offset = (_offset), \ + .bit_idx = (_bit_idx), \ + .set_clr = (_set_clr), \ + } + +static const struct stm32_reset_cfg *stm32mp25_reset[STM32MP25_LAST_RESET] = { + RESET(TIM1_R, RCC_TIM1CFGR, 0, 0), + RESET(TIM2_R, RCC_TIM2CFGR, 0, 0), + RESET(TIM3_R, RCC_TIM3CFGR, 0, 0), + RESET(TIM4_R, RCC_TIM4CFGR, 0, 0), + RESET(TIM5_R, RCC_TIM5CFGR, 0, 0), + RESET(TIM6_R, RCC_TIM6CFGR, 0, 0), + RESET(TIM7_R, RCC_TIM7CFGR, 0, 0), + RESET(TIM8_R, RCC_TIM8CFGR, 0, 0), + RESET(TIM10_R, RCC_TIM10CFGR, 0, 0), + RESET(TIM11_R, RCC_TIM11CFGR, 0, 0), + RESET(TIM12_R, RCC_TIM12CFGR, 0, 0), + RESET(TIM13_R, RCC_TIM13CFGR, 0, 0), + RESET(TIM14_R, RCC_TIM14CFGR, 0, 0), + RESET(TIM15_R, RCC_TIM15CFGR, 0, 0), + RESET(TIM16_R, RCC_TIM16CFGR, 0, 0), + RESET(TIM17_R, RCC_TIM17CFGR, 0, 0), + RESET(TIM20_R, RCC_TIM20CFGR, 0, 0), + RESET(LPTIM1_R, RCC_LPTIM1CFGR, 0, 0), + RESET(LPTIM2_R, RCC_LPTIM2CFGR, 0, 0), + RESET(LPTIM3_R, RCC_LPTIM3CFGR, 0, 0), + RESET(LPTIM4_R, RCC_LPTIM4CFGR, 0, 0), + RESET(LPTIM5_R, RCC_LPTIM5CFGR, 0, 0), + RESET(SPI1_R, RCC_SPI1CFGR, 0, 0), + RESET(SPI2_R, RCC_SPI2CFGR, 0, 0), + RESET(SPI3_R, RCC_SPI3CFGR, 0, 0), + RESET(SPI4_R, RCC_SPI4CFGR, 0, 0), + RESET(SPI5_R, RCC_SPI5CFGR, 0, 0), + RESET(SPI6_R, RCC_SPI6CFGR, 0, 0), + RESET(SPI7_R, RCC_SPI7CFGR, 0, 0), + RESET(SPI8_R, RCC_SPI8CFGR, 0, 0), + RESET(SPDIFRX_R, RCC_SPDIFRXCFGR, 0, 0), + RESET(USART1_R, RCC_USART1CFGR, 0, 0), + RESET(USART2_R, RCC_USART2CFGR, 0, 0), + RESET(USART3_R, RCC_USART3CFGR, 0, 0), + RESET(UART4_R, RCC_UART4CFGR, 0, 0), + RESET(UART5_R, RCC_UART5CFGR, 0, 0), + RESET(USART6_R, RCC_USART6CFGR, 0, 0), + RESET(UART7_R, RCC_UART7CFGR, 0, 0), + RESET(UART8_R, RCC_UART8CFGR, 0, 0), + RESET(UART9_R, RCC_UART9CFGR, 0, 0), + RESET(LPUART1_R, RCC_LPUART1CFGR, 0, 0), + RESET(IS2M_R, RCC_IS2MCFGR, 0, 0), + RESET(I2C1_R, RCC_I2C1CFGR, 0, 0), + RESET(I2C2_R, RCC_I2C2CFGR, 0, 0), + RESET(I2C3_R, RCC_I2C3CFGR, 0, 0), + RESET(I2C4_R, RCC_I2C4CFGR, 0, 0), + RESET(I2C5_R, RCC_I2C5CFGR, 0, 0), + RESET(I2C6_R, RCC_I2C6CFGR, 0, 0), + RESET(I2C7_R, RCC_I2C7CFGR, 0, 0), + RESET(I2C8_R, RCC_I2C8CFGR, 0, 0), + RESET(SAI1_R, RCC_SAI1CFGR, 0, 0), + RESET(SAI2_R, RCC_SAI2CFGR, 0, 0), + RESET(SAI3_R, RCC_SAI3CFGR, 0, 0), + RESET(SAI4_R, RCC_SAI4CFGR, 0, 0), + RESET(MDF1_R, RCC_MDF1CFGR, 0, 0), + RESET(MDF2_R, RCC_ADF1CFGR, 0, 0), + RESET(FDCAN_R, RCC_FDCANCFGR, 0, 0), + RESET(HDP_R, RCC_HDPCFGR, 0, 0), + RESET(ADC12_R, RCC_ADC12CFGR, 0, 0), + RESET(ADC3_R, RCC_ADC3CFGR, 0, 0), + RESET(ETH1_R, RCC_ETH1CFGR, 0, 0), + RESET(ETH2_R, RCC_ETH2CFGR, 0, 0), + RESET(USBH_R, RCC_USBHCFGR, 0, 0), + RESET(USB2PHY1_R, RCC_USB2PHY1CFGR, 0, 0), + RESET(USB2PHY2_R, RCC_USB2PHY2CFGR, 0, 0), + RESET(USB3DR_R, RCC_USB3DRCFGR, 0, 0), + RESET(USB3PCIEPHY_R, RCC_USB3PCIEPHYCFGR, 0, 0), + RESET(USBTC_R, RCC_UCPDCFGR, 0, 0), + RESET(ETHSW_R, RCC_ETHSWCFGR, 0, 0), + RESET(SDMMC1_R, RCC_SDMMC1CFGR, 0, 0), + RESET(SDMMC1DLL_R, RCC_SDMMC1CFGR, 16, 0), + RESET(SDMMC2_R, RCC_SDMMC2CFGR, 0, 0), + RESET(SDMMC2DLL_R, RCC_SDMMC2CFGR, 16, 0), + RESET(SDMMC3_R, RCC_SDMMC3CFGR, 0, 0), + RESET(SDMMC3DLL_R, RCC_SDMMC3CFGR, 16, 0), + RESET(GPU_R, RCC_GPUCFGR, 0, 0), + RESET(LTDC_R, RCC_LTDCCFGR, 0, 0), + RESET(DSI_R, RCC_DSICFGR, 0, 0), + RESET(LVDS_R, RCC_LVDSCFGR, 0, 0), + RESET(CSI_R, RCC_CSICFGR, 0, 0), + RESET(DCMIPP_R, RCC_DCMIPPCFGR, 0, 0), + RESET(CCI_R, RCC_CCICFGR, 0, 0), + RESET(VDEC_R, RCC_VDECCFGR, 0, 0), + RESET(VENC_R, RCC_VENCCFGR, 0, 0), + RESET(WWDG1_R, RCC_WWDG1CFGR, 0, 0), + RESET(WWDG2_R, RCC_WWDG2CFGR, 0, 0), + RESET(VREF_R, RCC_VREFCFGR, 0, 0), + RESET(DTS_R, RCC_DTSCFGR, 0, 0), + RESET(CRC_R, RCC_CRCCFGR, 0, 0), + RESET(SERC_R, RCC_SERCCFGR, 0, 0), + RESET(OSPIIOM_R, RCC_OSPIIOMCFGR, 0, 0), + RESET(I3C1_R, RCC_I3C1CFGR, 0, 0), + RESET(I3C2_R, RCC_I3C2CFGR, 0, 0), + RESET(I3C3_R, RCC_I3C3CFGR, 0, 0), + RESET(I3C4_R, RCC_I3C4CFGR, 0, 0), + RESET(IWDG2_KER_R, RCC_IWDGC1CFGSETR, 18, 1), + RESET(IWDG4_KER_R, RCC_IWDGC2CFGSETR, 18, 1), + RESET(RNG_R, RCC_RNGCFGR, 0, 0), + RESET(PKA_R, RCC_PKACFGR, 0, 0), + RESET(SAES_R, RCC_SAESCFGR, 0, 0), + RESET(HASH_R, RCC_HASHCFGR, 0, 0), + RESET(CRYP1_R, RCC_CRYP1CFGR, 0, 0), + RESET(CRYP2_R, RCC_CRYP2CFGR, 0, 0), + RESET(PCIE_R, RCC_PCIECFGR, 0, 0), +}; + +static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_ctl *reset_ctl) +{ + unsigned long id = reset_ctl->id; + + if (id < STM32MP25_LAST_RESET) + return stm32mp25_reset[id]; + + return NULL; +} + +static const struct stm32_reset_data stm32mp25_reset_data = { + .get_reset_line = stm32_get_reset_line, + .clear_offset = RCC_CLR_OFFSET, + .reset_us = STM32_DEASSERT_TIMEOUT_US, +}; + +static int stm32_reset_probe(struct udevice *dev) +{ + return stm32_reset_core_probe(dev, &stm32mp25_reset_data); +} + +U_BOOT_DRIVER(stm32mp25_rcc_reset) = { + .name = "stm32mp25_reset", + .id = UCLASS_RESET, + .probe = stm32_reset_probe, + .priv_auto = sizeof(struct stm32_reset_priv), + .ops = &stm32_reset_ops, +}; diff --git a/drivers/reset/stm32/stm32-reset.c b/drivers/reset/stm32/stm32-reset.c new file mode 100644 index 00000000000..975f67f712a --- /dev/null +++ b/drivers/reset/stm32/stm32-reset.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause +/* + * Copyright (C) 2017, STMicroelectronics - All Rights Reserved + * Author(s): Patrice Chotard, <patrice.chotard@foss.st.com> for STMicroelectronics. + */ + +#include <dm.h> +#include <stm32-reset-core.h> + +/* Timeout for deassert */ +#define STM32_DEASSERT_TIMEOUT_US 10000 + +static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_ctl *reset_ctl) +{ + struct stm32_reset_priv *priv = dev_get_priv(reset_ctl->dev); + struct stm32_reset_cfg *ptr_line = &priv->reset_line; + int bank = (reset_ctl->id / (sizeof(u32) * BITS_PER_BYTE)) * 4; + int offset = reset_ctl->id % (sizeof(u32) * BITS_PER_BYTE); + + ptr_line->offset = bank; + ptr_line->bit_idx = offset; + ptr_line->set_clr = true; + + return ptr_line; +} + +static const struct stm32_reset_data stm32_reset_data = { + .get_reset_line = stm32_get_reset_line, + .reset_us = STM32_DEASSERT_TIMEOUT_US, +}; + +static int stm32_reset_probe(struct udevice *dev) +{ + return stm32_reset_core_probe(dev, &stm32_reset_data); +} + +U_BOOT_DRIVER(stm32_rcc_reset) = { + .name = "stm32_rcc_reset", + .id = UCLASS_RESET, + .probe = stm32_reset_probe, + .priv_auto = sizeof(struct stm32_reset_priv), + .ops = &stm32_reset_ops, +}; diff --git a/drivers/scsi/scsi-uclass.c b/drivers/scsi/scsi-uclass.c index 1ee8236c05c..3eb6069649f 100644 --- a/drivers/scsi/scsi-uclass.c +++ b/drivers/scsi/scsi-uclass.c @@ -10,7 +10,9 @@ #define LOG_CATEGORY UCLASS_SCSI +#include <blk.h> #include <dm.h> +#include <part.h> #include <scsi.h> int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) @@ -23,6 +25,34 @@ int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) return ops->exec(dev, pccb); } +int scsi_get_blk_by_uuid(const char *uuid, + struct blk_desc **blk_desc_ptr, + struct disk_partition *part_info_ptr) +{ + static int is_scsi_scanned; + struct blk_desc *blk; + int i, ret; + + if (!is_scsi_scanned) { + scsi_scan(false /* no verbose */); + is_scsi_scanned = 1; + } + + for (i = 0; i < blk_find_max_devnum(UCLASS_SCSI) + 1; i++) { + ret = blk_get_desc(UCLASS_SCSI, i, &blk); + if (ret) + continue; + + ret = part_get_info_by_uuid(blk, uuid, part_info_ptr); + if (ret > 0) { + *blk_desc_ptr = blk; + return 0; + } + } + + return -1; +} + int scsi_bus_reset(struct udevice *dev) { struct scsi_ops *ops = scsi_get_ops(dev); diff --git a/drivers/serial/serial_mtk.c b/drivers/serial/serial_mtk.c index becf9317076..01cc415efdd 100644 --- a/drivers/serial/serial_mtk.c +++ b/drivers/serial/serial_mtk.c @@ -30,16 +30,23 @@ struct mtk_serial_regs { u32 mcr; u32 lsr; u32 msr; - u32 spr; - u32 mdr1; + u32 scr; + u32 autobaud_en; u32 highspeed; u32 sample_count; u32 sample_point; + u32 autobaud_reg; + u32 ratefix_ad; + u32 autobaud_sample; + u32 guard; + u32 escape_dat; + u32 escape_en; + u32 sleep_en; + u32 dma_en; + u32 rxtri_ad; u32 fracdiv_l; u32 fracdiv_m; - u32 escape_en; - u32 guard; - u32 rx_sel; + u32 fcr_rd; }; #define thr rbr @@ -92,10 +99,18 @@ struct mtk_serial_priv { bool upstream_highspeed_logic; }; +static const unsigned short fraction_l_mapping[] = { + 0, 1, 0x5, 0x15, 0x55, 0x57, 0x57, 0x77, 0x7F, 0xFF, 0xFF +}; + +static const unsigned short fraction_m_mapping[] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3 +}; + static void _mtk_serial_setbrg(struct mtk_serial_priv *priv, int baud, uint clk_rate) { - u32 quot, realbaud, samplecount = 1; + u32 quot, realbaud, samplecount = 1, fraction, frac_l = 0, frac_m = 0; /* Special case for low baud clock */ if (baud <= 115200 && clk_rate == 12000000) { @@ -140,7 +155,13 @@ use_hs3: writel(3, &priv->regs->highspeed); quot = DIV_ROUND_UP(clk_rate, 256 * baud); - samplecount = DIV_ROUND_CLOSEST(clk_rate, quot * baud); + samplecount = clk_rate / (quot * baud); + + fraction = ((clk_rate * 100) / quot / baud) % 100; + fraction = DIV_ROUND_CLOSEST(fraction, 10); + + frac_l = fraction_l_mapping[fraction]; + frac_m = fraction_m_mapping[fraction]; } set_baud: @@ -152,7 +173,11 @@ set_baud: /* set highspeed mode sample count & point */ writel(samplecount - 1, &priv->regs->sample_count); - writel((samplecount - 2) >> 1, &priv->regs->sample_point); + writel((samplecount >> 1) - 1, &priv->regs->sample_point); + + /* set baudrate fraction compensation */ + writel(frac_l, &priv->regs->fracdiv_l); + writel(frac_m, &priv->regs->fracdiv_m); } static int _mtk_serial_putc(struct mtk_serial_priv *priv, const char ch) diff --git a/drivers/sound/max98088.h b/drivers/sound/max98088.h index b1307a73623..2ca6ca1f734 100644 --- a/drivers/sound/max98088.h +++ b/drivers/sound/max98088.h @@ -15,14 +15,14 @@ #define M98088_REG_JACK_STAUS 0x02 #define M98088_REG_BATTERY_VOLTAGE 0x03 #define M98088_REG_IRQ_ENABLE 0x0f -#define M98088_REG_SYS_CLK 0X10 +#define M98088_REG_SYS_CLK 0x10 #define M98088_REG_DAI1_CLKMODE 0x11 #define M98088_REG_DAI1_CLKCFG_HI 0x12 #define M98088_REG_DAI1_CLKCFG_LO 0x13 #define M98088_REG_DAI1_FORMAT 0x14 #define M98088_REG_DAI1_CLOCK 0x15 #define M98088_REG_DAI1_IOCFG 0x16 -#define M98088_REG_DAI1_TDM 0X17 +#define M98088_REG_DAI1_TDM 0x17 #define M98088_REG_DAI1_FILTERS 0x18 #define M98088_REG_DAI2_CLKMODE 0x19 #define M98088_REG_DAI2_CLKCFG_HI 0x1a @@ -30,10 +30,10 @@ #define M98088_REG_DAI2_FORMAT 0x1c #define M98088_REG_DAI2_CLOCK 0x1d #define M98088_REG_DAI2_IOCFG 0x1e -#define M98088_REG_DAI2_TDM 0X1f +#define M98088_REG_DAI2_TDM 0x1f #define M98088_REG_DAI2_FILTERS 0x20 -#define M98088_REG_SRC 0X21 -#define M98088_REG_MIX_DAC 0X22 +#define M98088_REG_SRC 0x21 +#define M98088_REG_MIX_DAC 0x22 #define M98088_REG_MIX_ADC_LEFT 0x23 #define M98088_REG_MIX_ADC_RIGHT 0x24 #define M98088_REG_MIX_HP_LEFT 0x25 @@ -50,37 +50,37 @@ #define M98088_REG_LVL_DAI1_PLAY_EQ 0x30 #define M98088_REG_LVL_DAI2_PLAY 0x31 #define M98088_REG_LVL_DAI2_PLAY_EQ 0x32 -#define M98088_REG_LVL_ADC_L 0X33 -#define M98088_REG_LVL_ADC_R 0X34 -#define M98088_REG_LVL_MIC1 0X35 -#define M98088_REG_LVL_MIC2 0X36 -#define M98088_REG_LVL_INA 0X37 -#define M98088_REG_LVL_INB 0X38 -#define M98088_REG_LVL_HP_L 0X39 -#define M98088_REG_LVL_HP_R 0X3a -#define M98088_REG_LVL_REC_L 0X3b -#define M98088_REG_LVL_REC_R 0X3c -#define M98088_REG_LVL_SPK_L 0X3d -#define M98088_REG_LVL_SPK_R 0X3e +#define M98088_REG_LVL_ADC_L 0x33 +#define M98088_REG_LVL_ADC_R 0x34 +#define M98088_REG_LVL_MIC1 0x35 +#define M98088_REG_LVL_MIC2 0x36 +#define M98088_REG_LVL_INA 0x37 +#define M98088_REG_LVL_INB 0x38 +#define M98088_REG_LVL_HP_L 0x39 +#define M98088_REG_LVL_HP_R 0x3a +#define M98088_REG_LVL_REC_L 0x3b +#define M98088_REG_LVL_REC_R 0x3c +#define M98088_REG_LVL_SPK_L 0x3d +#define M98088_REG_LVL_SPK_R 0x3e #define M98088_REG_MICAGC_CFG 0x3f #define M98088_REG_MICAGC_THRESH 0x40 -#define M98088_REG_SPKDHP 0X41 +#define M98088_REG_SPKDHP 0x41 #define M98088_REG_SPKDHP_THRESH 0x42 #define M98088_REG_SPKALC_COMP 0x43 #define M98088_REG_PWRLMT_CFG 0x44 #define M98088_REG_PWRLMT_TIME 0x45 #define M98088_REG_THDLMT_CFG 0x46 #define M98088_REG_CFG_AUDIO_IN 0x47 -#define M98088_REG_CFG_MIC 0X48 -#define M98088_REG_CFG_LEVEL 0X49 +#define M98088_REG_CFG_MIC 0x48 +#define M98088_REG_CFG_LEVEL 0x49 #define M98088_REG_CFG_BYPASS 0x4a #define M98088_REG_CFG_JACKDET 0x4b -#define M98088_REG_PWR_EN_IN 0X4c +#define M98088_REG_PWR_EN_IN 0x4c #define M98088_REG_PWR_EN_OUT 0x4d -#define M98088_REG_BIAS_CNTL 0X4e -#define M98088_REG_DAC_BIAS1 0X4f -#define M98088_REG_DAC_BIAS2 0X50 -#define M98088_REG_PWR_SYS 0X51 +#define M98088_REG_BIAS_CNTL 0x4e +#define M98088_REG_DAC_BIAS1 0x4f +#define M98088_REG_DAC_BIAS2 0x50 +#define M98088_REG_PWR_SYS 0x51 #define M98088_REG_DAI1_EQ_BASE 0x52 #define M98088_REG_DAI2_EQ_BASE 0x84 #define M98088_REG_DAI1_BIQUAD_BASE 0xb6 diff --git a/drivers/sound/max98095.h b/drivers/sound/max98095.h index 1521f3f02f9..009164d85d2 100644 --- a/drivers/sound/max98095.h +++ b/drivers/sound/max98095.h @@ -176,7 +176,7 @@ enum en_max_audio_interface { #define M98095_0FF_REV_ID 0xFF #define M98095_REG_CNT (0xFF+1) -#define M98095_REG_MAX_CACHED 0X97 +#define M98095_REG_MAX_CACHED 0x97 /* MAX98095 Registers Bit Fields */ diff --git a/drivers/tpm/sandbox_common.c b/drivers/tpm/sandbox_common.c index 596e0156389..9d386fc32e5 100644 --- a/drivers/tpm/sandbox_common.c +++ b/drivers/tpm/sandbox_common.c @@ -9,6 +9,7 @@ #include <tpm-v1.h> #include <tpm-v2.h> +#include <linux/string.h> #include <asm/unaligned.h> #include "sandbox_common.h" diff --git a/drivers/tpm/tpm_tis_sandbox.c b/drivers/tpm/tpm_tis_sandbox.c index 2bc7dc87ed3..d7341062b31 100644 --- a/drivers/tpm/tpm_tis_sandbox.c +++ b/drivers/tpm/tpm_tis_sandbox.c @@ -221,6 +221,7 @@ static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, case 0x72: /* physical set deactivated */ case 0x99: /* startup */ case 0x50: /* self test full */ + case 0x53: /* self test continue */ case 0x4000000a: /* assert physical presence */ *recv_len = 12; memset(recvbuf, '\0', *recv_len); diff --git a/drivers/usb/common/Makefile b/drivers/usb/common/Makefile index 4c597c166c6..db8f35c10c4 100644 --- a/drivers/usb/common/Makefile +++ b/drivers/usb/common/Makefile @@ -4,6 +4,8 @@ # obj-$(CONFIG_$(PHASE_)DM_USB) += common.o +obj-$(CONFIG_USB_DWC2) += dwc2_core.o +obj-$(CONFIG_USB_GADGET_DWC2_OTG) += dwc2_core.o obj-$(CONFIG_USB_ISP1760) += usb_urb.o obj-$(CONFIG_USB_MUSB_HOST) += usb_urb.o obj-$(CONFIG_USB_MUSB_GADGET) += usb_urb.o diff --git a/drivers/usb/common/dwc2_core.c b/drivers/usb/common/dwc2_core.c new file mode 100644 index 00000000000..63062d5cc94 --- /dev/null +++ b/drivers/usb/common/dwc2_core.c @@ -0,0 +1,131 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2024-2025, Kongyang Liu <seashell11234455@gmail.com> + */ + +#include <linux/bitfield.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <wait_bit.h> + +#include "dwc2_core.h" + +int dwc2_core_reset(struct dwc2_core_regs *regs) +{ + u32 snpsid; + int ret; + bool host_mode = false; + + if (!(readl(®s->global_regs.gotgctl) & GOTGCTL_CONID_B) || + (readl(®s->global_regs.gusbcfg) & GUSBCFG_FORCEDEVMODE)) + host_mode = true; + + /* Core Soft Reset */ + snpsid = readl(®s->global_regs.gsnpsid); + writel(GRSTCTL_CSFTRST, ®s->global_regs.grstctl); + if (FIELD_GET(GSNPSID_VER_MASK, snpsid) < 0x420a) { + ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_CSFTRST, + false, 1000, false); + if (ret) { + log_warning("%s: Waiting for GRSTCTL_CSFTRST timeout\n", __func__); + return ret; + } + } else { + ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_CSFTRST_DONE, + true, 1000, false); + if (ret) { + log_warning("%s: Waiting for GRSTCTL_CSFTRST_DONE timeout\n", __func__); + return ret; + } + clrsetbits_le32(®s->global_regs.grstctl, GRSTCTL_CSFTRST, GRSTCTL_CSFTRST_DONE); + } + + /* Wait for AHB master IDLE state. */ + ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_AHBIDLE, + true, 1000, false); + if (ret) { + log_warning("%s: Waiting for GRSTCTL_AHBIDLE timeout\n", __func__); + return ret; + } + + if (host_mode) { + ret = wait_for_bit_le32(®s->global_regs.gintsts, GINTSTS_CURMODE_HOST, + host_mode, 1000, false); + if (ret) { + log_warning("%s: Waiting for GINTSTS_CURMODE_HOST timeout\n", __func__); + return ret; + } + } + + return 0; +} + +int dwc2_flush_tx_fifo(struct dwc2_core_regs *regs, const int num) +{ + int ret; + + log_debug("Flush Tx FIFO %d\n", num); + + /* Wait for AHB master IDLE state */ + ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_AHBIDLE, true, 1000, false); + if (ret) { + log_warning("%s: Waiting for GRSTCTL_AHBIDLE timeout\n", __func__); + return ret; + } + + writel(GRSTCTL_TXFFLSH | FIELD_PREP(GRSTCTL_TXFNUM_MASK, num), ®s->global_regs.grstctl); + + ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_TXFFLSH, false, 1000, false); + if (ret) { + log_warning("%s: Waiting for GRSTCTL_TXFFLSH timeout\n", __func__); + return ret; + } + + /* + * Wait for at least 3 PHY clocks. + * + * The PHY clock frequency can be configured to 6/30/48/60 MHz + * based on the speed mode. A fixed delay of 1us ensures that the + * wait time is sufficient even at the lowest PHY clock frequency + * (6 MHz), where 1us corresponds to twice the duration of 3 PHY + * clocks. + */ + udelay(1); + + return 0; +} + +int dwc2_flush_rx_fifo(struct dwc2_core_regs *regs) +{ + int ret; + + log_debug("Flush Rx FIFO\n"); + + /* Wait for AHB master IDLE state */ + ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_AHBIDLE, true, 1000, false); + if (ret) { + log_warning("%s: Waiting for GRSTCTL_AHBIDLE timeout\n", __func__); + return ret; + } + + writel(GRSTCTL_RXFFLSH, ®s->global_regs.grstctl); + + ret = wait_for_bit_le32(®s->global_regs.grstctl, GRSTCTL_RXFFLSH, false, 1000, false); + if (ret) { + log_warning("%s: Waiting for GRSTCTL_RXFFLSH timeout\n", __func__); + return ret; + } + + /* + * Wait for at least 3 PHY clocks. + * + * The PHY clock frequency can be configured to 6/30/48/60 MHz + * based on the speed mode. A fixed delay of 1us ensures that the + * wait time is sufficient even at the lowest PHY clock frequency + * (6 MHz), where 1us corresponds to twice the duration of 3 PHY + * clocks. + */ + udelay(1); + + return 0; +} diff --git a/drivers/usb/common/dwc2_core.h b/drivers/usb/common/dwc2_core.h new file mode 100644 index 00000000000..1897ad7cb54 --- /dev/null +++ b/drivers/usb/common/dwc2_core.h @@ -0,0 +1,560 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> + * + */ + +#ifndef __DWC2_CORE_H_ +#define __DWC2_CORE_H_ + +#include <linux/bitops.h> + +struct dwc2_global_regs { + u32 gotgctl; /* 0x000 */ + u32 gotgint; + u32 gahbcfg; + u32 gusbcfg; + u32 grstctl; /* 0x010 */ + u32 gintsts; + u32 gintmsk; + u32 grxstsr; + u32 grxstsp; /* 0x020 */ + u32 grxfsiz; + u32 gnptxfsiz; + u32 gnptxsts; + u32 gi2cctl; /* 0x030 */ + u32 gpvndctl; + u32 ggpio; + u32 guid; + u32 gsnpsid; /* 0x040 */ + u32 ghwcfg1; + u32 ghwcfg2; + u32 ghwcfg3; + u32 ghwcfg4; /* 0x050 */ + u32 glpmcfg; + u32 gpwrdn; + u32 gdfifocfg; + u32 gadpctl; /* 0x060 */ + u32 grefclk; + u32 gintmsk2; + u32 gintsts2; + u8 _pad_from_0x70_to_0x100[0x100 - 0x70]; + u32 hptxfsiz; /* 0x100 */ + u32 dptxfsizn[15]; + u8 _pad_from_0x140_to_0x400[0x400 - 0x140]; +}; + +struct dwc2_hc_regs { + u32 hcchar; /* 0x500 + 0x20 * ch */ + u32 hcsplt; + u32 hcint; + u32 hcintmsk; + u32 hctsiz; + u32 hcdma; + u32 reserved; + u32 hcdmab; +}; + +struct dwc2_host_regs { + u32 hcfg; /* 0x400 */ + u32 hfir; + u32 hfnum; + u32 _pad_0x40c; + u32 hptxsts; /* 0x410 */ + u32 haint; + u32 haintmsk; + u32 hflbaddr; + u8 _pad_from_0x420_to_0x440[0x440 - 0x420]; + u32 hprt0; /* 0x440 */ + u8 _pad_from_0x444_to_0x500[0x500 - 0x444]; + struct dwc2_hc_regs hc[16]; /* 0x500 */ + u8 _pad_from_0x700_to_0x800[0x800 - 0x700]; +}; + +/* Device Logical IN Endpoint-Specific Registers */ +struct dwc2_dev_in_endp { + u32 diepctl; /* 0x900 + 0x20 * ep */ + u32 reserved0; + u32 diepint; + u32 reserved1; + u32 dieptsiz; + u32 diepdma; + u32 reserved2; + u32 diepdmab; +}; + +/* Device Logical OUT Endpoint-Specific Registers */ +struct dwc2_dev_out_endp { + u32 doepctl; /* 0xB00 + 0x20 * ep */ + u32 reserved0; + u32 doepint; + u32 reserved1; + u32 doeptsiz; + u32 doepdma; + u32 reserved2; + u32 doepdmab; +}; + +struct dwc2_device_regs { + u32 dcfg; /* 0x800 */ + u32 dctl; + u32 dsts; + u32 _pad_0x80c; + u32 diepmsk; /* 0x810 */ + u32 doepmsk; + u32 daint; + u32 daintmsk; + u32 dtknqr1; /* 0x820 */ + u32 dtknqr2; + u32 dvbusdis; + u32 dvbuspulse; + u32 dtknqr3; /* 0x830 */ + u32 dtknqr4; + u8 _pad_from_0x838_to_0x900[0x900 - 0x838]; + struct dwc2_dev_in_endp in_endp[16]; /* 0x900 */ + struct dwc2_dev_out_endp out_endp[16]; /* 0xB00 */ +}; + +struct dwc2_core_regs { + struct dwc2_global_regs global_regs; /* 0x000 */ + struct dwc2_host_regs host_regs; /* 0x400 */ + struct dwc2_device_regs device_regs; /* 0x800 */ + u8 _pad_from_0xd00_to_0xe00[0xe00 - 0xd00]; + u32 pcgcctl; /* 0xe00 */ + u8 _pad_from_0xe04_to_0x1000[0x1000 - 0xe04]; + u8 ep_fifo[16][0x1000]; /* 0x1000 */ +}; + +int dwc2_core_reset(struct dwc2_core_regs *regs); +int dwc2_flush_tx_fifo(struct dwc2_core_regs *regs, const int num); +int dwc2_flush_rx_fifo(struct dwc2_core_regs *regs); + +/* Core Global Register */ +#define GOTGCTL_CHIRPEN BIT(27) +#define GOTGCTL_MULT_VALID_BC_MASK GENMASK(26, 22) +#define GOTGCTL_CURMODE_HOST BIT(21) +#define GOTGCTL_OTGVER BIT(20) +#define GOTGCTL_BSESVLD BIT(19) +#define GOTGCTL_ASESVLD BIT(18) +#define GOTGCTL_DBNC_SHORT BIT(17) +#define GOTGCTL_CONID_B BIT(16) +#define GOTGCTL_DBNCE_FLTR_BYPASS BIT(15) +#define GOTGCTL_DEVHNPEN BIT(11) +#define GOTGCTL_HSTSETHNPEN BIT(10) +#define GOTGCTL_HNPREQ BIT(9) +#define GOTGCTL_HSTNEGSCS BIT(8) +#define GOTGCTL_BVALOVAL BIT(7) +#define GOTGCTL_BVALOEN BIT(6) +#define GOTGCTL_AVALOVAL BIT(5) +#define GOTGCTL_AVALOEN BIT(4) +#define GOTGCTL_VBVALOVAL BIT(3) +#define GOTGCTL_VBVALOEN BIT(2) +#define GOTGCTL_SESREQ BIT(1) +#define GOTGCTL_SESREQSCS BIT(0) + +#define GOTGINT_DBNCE_DONE BIT(19) +#define GOTGINT_A_DEV_TOUT_CHG BIT(18) +#define GOTGINT_HST_NEG_DET BIT(17) +#define GOTGINT_HST_NEG_SUC_STS_CHNG BIT(9) +#define GOTGINT_SES_REQ_SUC_STS_CHNG BIT(8) +#define GOTGINT_SES_END_DET BIT(2) + +#define GAHBCFG_AHB_SINGLE BIT(23) +#define GAHBCFG_NOTI_ALL_DMA_WRIT BIT(22) +#define GAHBCFG_REM_MEM_SUPP BIT(21) +#define GAHBCFG_P_TXF_EMP_LVL BIT(8) +#define GAHBCFG_NP_TXF_EMP_LVL BIT(7) +#define GAHBCFG_DMA_EN BIT(5) +#define GAHBCFG_HBSTLEN_MASK GENMASK(4, 1) +#define GAHBCFG_HBSTLEN_SINGLE 0 +#define GAHBCFG_HBSTLEN_INCR 1 +#define GAHBCFG_HBSTLEN_INCR4 3 +#define GAHBCFG_HBSTLEN_INCR8 5 +#define GAHBCFG_HBSTLEN_INCR16 7 +#define GAHBCFG_GLBL_INTR_EN BIT(0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ + GAHBCFG_NP_TXF_EMP_LVL | \ + GAHBCFG_DMA_EN | \ + GAHBCFG_GLBL_INTR_EN) + +#define GUSBCFG_FORCEDEVMODE BIT(30) +#define GUSBCFG_FORCEHOSTMODE BIT(29) +#define GUSBCFG_TXENDDELAY BIT(28) +#define GUSBCFG_ICTRAFFICPULLREMOVE BIT(27) +#define GUSBCFG_ICUSBCAP BIT(26) +#define GUSBCFG_ULPI_INT_PROT_DIS BIT(25) +#define GUSBCFG_INDICATORPASSTHROUGH BIT(24) +#define GUSBCFG_INDICATORCOMPLEMENT BIT(23) +#define GUSBCFG_TERMSELDLPULSE BIT(22) +#define GUSBCFG_ULPI_INT_VBUS_IND BIT(21) +#define GUSBCFG_ULPI_EXT_VBUS_DRV BIT(20) +#define GUSBCFG_ULPI_CLK_SUSP_M BIT(19) +#define GUSBCFG_ULPI_AUTO_RES BIT(18) +#define GUSBCFG_ULPI_FS_LS BIT(17) +#define GUSBCFG_OTG_UTMI_FS_SEL BIT(16) +#define GUSBCFG_PHY_LP_CLK_SEL BIT(15) +#define GUSBCFG_USBTRDTIM_MASK GENMASK(14, 10) +#define GUSBCFG_HNPCAP BIT(9) +#define GUSBCFG_SRPCAP BIT(8) +#define GUSBCFG_DDRSEL BIT(7) +#define GUSBCFG_PHYSEL BIT(6) +#define GUSBCFG_FSINTF BIT(5) +#define GUSBCFG_ULPI_UTMI_SEL BIT(4) +#define GUSBCFG_PHYIF16 BIT(3) +#define GUSBCFG_TOUTCAL_MASK GENMASK(2, 0) + +#define GRSTCTL_AHBIDLE BIT(31) +#define GRSTCTL_DMAREQ BIT(30) +#define GRSTCTL_CSFTRST_DONE BIT(29) +#define GRSTCTL_TXFNUM_MASK GENMASK(10, 6) +#define GRSTCTL_TXFFLSH BIT(5) +#define GRSTCTL_RXFFLSH BIT(4) +#define GRSTCTL_IN_TKNQ_FLSH BIT(3) +#define GRSTCTL_FRMCNTRRST BIT(2) +#define GRSTCTL_HSFTRST BIT(1) +#define GRSTCTL_CSFTRST BIT(0) +#define GRSTCTL_TXFNUM_ALL 0x10 + +#define GINTSTS_WKUPINT BIT(31) +#define GINTSTS_SESSREQINT BIT(30) +#define GINTSTS_DISCONNINT BIT(29) +#define GINTSTS_CONIDSTSCHNG BIT(28) +#define GINTSTS_LPMTRANRCVD BIT(27) +#define GINTSTS_PTXFEMP BIT(26) +#define GINTSTS_HCHINT BIT(25) +#define GINTSTS_PRTINT BIT(24) +#define GINTSTS_RESETDET BIT(23) +#define GINTSTS_FET_SUSP BIT(22) +#define GINTSTS_INCOMPL_IP BIT(21) +#define GINTSTS_INCOMPL_SOOUT BIT(21) +#define GINTSTS_INCOMPL_SOIN BIT(20) +#define GINTSTS_OEPINT BIT(19) +#define GINTSTS_IEPINT BIT(18) +#define GINTSTS_EPMIS BIT(17) +#define GINTSTS_RESTOREDONE BIT(16) +#define GINTSTS_EOPF BIT(15) +#define GINTSTS_ISOUTDROP BIT(14) +#define GINTSTS_ENUMDONE BIT(13) +#define GINTSTS_USBRST BIT(12) +#define GINTSTS_USBSUSP BIT(11) +#define GINTSTS_ERLYSUSP BIT(10) +#define GINTSTS_I2CINT BIT(9) +#define GINTSTS_ULPI_CK_INT BIT(8) +#define GINTSTS_GOUTNAKEFF BIT(7) +#define GINTSTS_GINNAKEFF BIT(6) +#define GINTSTS_NPTXFEMP BIT(5) +#define GINTSTS_RXFLVL BIT(4) +#define GINTSTS_SOF BIT(3) +#define GINTSTS_OTGINT BIT(2) +#define GINTSTS_MODEMIS BIT(1) +#define GINTSTS_CURMODE_HOST BIT(0) + +#define GRXSTS_FN_MASK GENMASK(31, 25) +#define GRXSTS_PKTSTS_MASK GENMASK(20, 17) +#define GRXSTS_PKTSTS_GLOBALOUTNAK 1 +#define GRXSTS_PKTSTS_OUTRX 2 +#define GRXSTS_PKTSTS_HCHIN 2 +#define GRXSTS_PKTSTS_OUTDONE 3 +#define GRXSTS_PKTSTS_HCHIN_XFER_COMP 3 +#define GRXSTS_PKTSTS_SETUPDONE 4 +#define GRXSTS_PKTSTS_DATATOGGLEERR 5 +#define GRXSTS_PKTSTS_SETUPRX 6 +#define GRXSTS_PKTSTS_HCHHALTED 7 +#define GRXSTS_DPID_MASK GENMASK(16, 15) +#define GRXSTS_BYTECNT_MASK GENMASK(14, 4) +#define GRXSTS_HCHNUM_MASK GENMASK(3, 0) + +#define GRXFSIZ_DEPTH_MASK GENMASK(15, 0) + +#define GI2CCTL_BSYDNE BIT(31) +#define GI2CCTL_RW BIT(30) +#define GI2CCTL_I2CDATSE0 BIT(28) +#define GI2CCTL_I2CDEVADDR_MASK GENMASK(27, 26) +#define GI2CCTL_I2CSUSPCTL BIT(25) +#define GI2CCTL_ACK BIT(24) +#define GI2CCTL_I2CEN BIT(23) +#define GI2CCTL_ADDR_MASK GENMASK(22, 16) +#define GI2CCTL_REGADDR_MASK GENMASK(15, 8) +#define GI2CCTL_RWDATA_MASK GENMASK(7, 0) + +#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22) +#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21) +#define GGPIO_STM32_OTG_GCCFG_PWRDWN BIT(16) + +#define GSNPSID_ID_MASK GENMASK(31, 16) +#define GSNPSID_OTG_ID 0x4f54 +#define GSNPSID_VER_MASK GENMASK(15, 0) + +#define GHWCFG2_OTG_ENABLE_IC_USB BIT(31) +#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK GENMASK(30, 26) +#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK GENMASK(25, 24) +#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK GENMASK(23, 22) +#define GHWCFG2_MULTI_PROC_INT BIT(20) +#define GHWCFG2_DYNAMIC_FIFO BIT(19) +#define GHWCFG2_PERIO_EP_SUPPORTED BIT(18) +#define GHWCFG2_NUM_HOST_CHAN_MASK GENMASK(17, 14) +#define GHWCFG2_NUM_DEV_EP_MASK GENMASK(13, 10) +#define GHWCFG2_FS_PHY_TYPE_MASK GENMASK(9, 8) +#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0 +#define GHWCFG2_FS_PHY_TYPE_DEDICATED 1 +#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI 2 +#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI 3 +#define GHWCFG2_HS_PHY_TYPE_MASK GENMASK(7, 6) +#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0 +#define GHWCFG2_HS_PHY_TYPE_UTMI 1 +#define GHWCFG2_HS_PHY_TYPE_ULPI 2 +#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI 3 +#define GHWCFG2_POINT2POINT BIT(5) +#define GHWCFG2_ARCHITECTURE_MASK GENMASK(4, 3) +#define GHWCFG2_SLAVE_ONLY_ARCH 0 +#define GHWCFG2_EXT_DMA_ARCH 1 +#define GHWCFG2_INT_DMA_ARCH 2 +#define GHWCFG2_OP_MODE_MASK GENMASK(2, 0) +#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE 0 +#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE 1 +#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE 2 +#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3 +#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4 +#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST 5 +#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6 +#define GHWCFG2_OP_MODE_UNDEFINED 7 + +#define GHWCFG4_DESC_DMA_DYN BIT(31) +#define GHWCFG4_DESC_DMA BIT(30) +#define GHWCFG4_NUM_IN_EPS_MASK GENMASK(29, 26) +#define GHWCFG4_DED_FIFO_EN BIT(25) +#define GHWCFG4_SESSION_END_FILT_EN BIT(24) +#define GHWCFG4_B_VALID_FILT_EN BIT(23) +#define GHWCFG4_A_VALID_FILT_EN BIT(22) +#define GHWCFG4_VBUS_VALID_FILT_EN BIT(21) +#define GHWCFG4_IDDIG_FILT_EN BIT(20) +#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK GENMASK(19, 16) +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK GENMASK(15, 14) +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8 0 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16 1 +#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16 2 +#define GHWCFG4_ACG_SUPPORTED BIT(12) +#define GHWCFG4_IPG_ISOC_SUPPORTED BIT(11) +#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10) +#define GHWCFG4_XHIBER BIT(7) +#define GHWCFG4_HIBER BIT(6) +#define GHWCFG4_MIN_AHB_FREQ BIT(5) +#define GHWCFG4_POWER_OPTIMIZ BIT(4) +#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK GENMASK(3, 0) + +#define FIFOSIZE_DEPTH_MASK GENMASK(31, 16) +#define FIFOSIZE_STARTADDR_MASK GENMASK(15, 0) + +/* Host Register */ +#define HCFG_MODECHTIMEN BIT(31) +#define HCFG_PERSCHEDENA BIT(26) +#define HCFG_FRLISTEN_MASK GENMASK(25, 24) +#define HCFG_FRLISTEN_8 0 +#define HCFG_FRLISTEN_16 1 +#define HCFG_FRLISTEN_32 2 +#define HCFG_FRLISTEN_64 3 +#define HCFG_DESCDMA BIT(23) +#define HCFG_RESVALID_MASK GENMASK(15, 8) +#define HCFG_ENA32KHZ BIT(7) +#define HCFG_FSLSSUPP BIT(2) +#define HCFG_FSLSPCLKSEL_MASK GENMASK(2, 0) +#define HCFG_FSLSPCLKSEL_30_60_MHZ 0 +#define HCFG_FSLSPCLKSEL_48_MHZ 1 +#define HCFG_FSLSPCLKSEL_6_MHZ 2 + +#define HFNUM_FRREM_MASK GENMASK(31, 16) +#define HFNUM_FRNUM_MASK GENMASK(15, 0) + +#define HPRT0_SPD_MASK GENMASK(18, 17) +#define HPRT0_SPD_HIGH_SPEED 0 +#define HPRT0_SPD_FULL_SPEED 1 +#define HPRT0_SPD_LOW_SPEED 2 +#define HPRT0_TSTCTL_MASK GENMASK(16, 13) +#define HPRT0_PWR BIT(12) +#define HPRT0_LNSTS_MASK GENMASK(11, 10) +#define HPRT0_RST BIT(8) +#define HPRT0_SUSP BIT(7) +#define HPRT0_RES BIT(6) +#define HPRT0_OVRCURRCHG BIT(5) +#define HPRT0_OVRCURRACT BIT(4) +#define HPRT0_ENACHG BIT(3) +#define HPRT0_ENA BIT(2) +#define HPRT0_CONNDET BIT(1) +#define HPRT0_CONNSTS BIT(0) +#define HPRT0_W1C_MASK (HPRT0_CONNDET | \ + HPRT0_ENA | \ + HPRT0_ENACHG | \ + HPRT0_OVRCURRCHG) + +#define HCCHAR_CHENA BIT(31) +#define HCCHAR_CHDIS BIT(30) +#define HCCHAR_ODDFRM BIT(29) +#define HCCHAR_DEVADDR_MASK GENMASK(28, 22) +#define HCCHAR_MULTICNT_MASK GENMASK(21, 20) +#define HCCHAR_EPTYPE_MASK GENMASK(19, 18) +#define HCCHAR_EPTYPE_CONTROL 0 +#define HCCHAR_EPTYPE_ISOC 1 +#define HCCHAR_EPTYPE_BULK 2 +#define HCCHAR_EPTYPE_INTR 3 +#define HCCHAR_LSPDDEV BIT(17) +#define HCCHAR_EPDIR BIT(15) +#define HCCHAR_EPNUM_MASK GENMASK(14, 11) +#define HCCHAR_MPS_MASK GENMASK(10, 0) + +#define HCSPLT_SPLTENA BIT(31) +#define HCSPLT_COMPSPLT BIT(16) +#define HCSPLT_XACTPOS_MASK GENMASK(15, 14) +#define HCSPLT_XACTPOS_MID 0 +#define HCSPLT_XACTPOS_END 1 +#define HCSPLT_XACTPOS_BEGIN 2 +#define HCSPLT_XACTPOS_ALL 3 +#define HCSPLT_HUBADDR_MASK GENMASK(13, 7) +#define HCSPLT_PRTADDR_MASK GENMASK(6, 0) + +#define HCINTMSK_FRM_LIST_ROLL BIT(13) +#define HCINTMSK_XCS_XACT BIT(12) +#define HCINTMSK_BNA BIT(11) +#define HCINTMSK_DATATGLERR BIT(10) +#define HCINTMSK_FRMOVRUN BIT(9) +#define HCINTMSK_BBLERR BIT(8) +#define HCINTMSK_XACTERR BIT(7) +#define HCINTMSK_NYET BIT(6) +#define HCINTMSK_ACK BIT(5) +#define HCINTMSK_NAK BIT(4) +#define HCINTMSK_STALL BIT(3) +#define HCINTMSK_AHBERR BIT(2) +#define HCINTMSK_CHHLTD BIT(1) +#define HCINTMSK_XFERCOMPL BIT(0) + +#define TSIZ_DOPNG BIT(31) +#define TSIZ_SC_MC_PID_MASK GENMASK(30, 29) +#define TSIZ_SC_MC_PID_DATA0 0 +#define TSIZ_SC_MC_PID_DATA2 1 +#define TSIZ_SC_MC_PID_DATA1 2 +#define TSIZ_SC_MC_PID_MDATA 3 +#define TSIZ_SC_MC_PID_SETUP 3 +#define TSIZ_PKTCNT_MASK GENMASK(28, 19) +#define TSIZ_NTD_MASK GENMASK(15, 8) +#define TSIZ_SCHINFO_MASK GENMASK(7, 0) +#define TSIZ_XFERSIZE_MASK GENMASK(18, 0) + +/* Device Mode Register */ +#define DCFG_DESCDMA_EN BIT(23) +#define DCFG_EPMISCNT_MASK GENMASK(22, 18) +#define DCFG_IPG_ISOC_SUPPORDED BIT(17) +#define DCFG_PERFRINT_MASK GENMASK(12, 11) +#define DCFG_DEVADDR_MASK GENMASK(10, 4) +#define DCFG_NZ_STS_OUT_HSHK BIT(2) +#define DCFG_DEVSPD_MASK GENMASK(1, 0) +#define DCFG_DEVSPD_HS 0 +#define DCFG_DEVSPD_FS 1 +#define DCFG_DEVSPD_LS 2 +#define DCFG_DEVSPD_FS48 3 + +#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19) +#define DCTL_PWRONPRGDONE BIT(11) +#define DCTL_CGOUTNAK BIT(10) +#define DCTL_SGOUTNAK BIT(9) +#define DCTL_CGNPINNAK BIT(8) +#define DCTL_SGNPINNAK BIT(7) +#define DCTL_TSTCTL_MASK GENMASK(6, 4) +#define DCTL_GOUTNAKSTS BIT(3) +#define DCTL_GNPINNAKSTS BIT(2) +#define DCTL_SFTDISCON BIT(1) +#define DCTL_RMTWKUPSIG BIT(0) + +#define DSTS_SOFFN_MASK GENMASK(21, 8) +#define DSTS_ERRATICERR BIT(3) +#define DSTS_ENUMSPD_MASK GENMASK(2, 1) +#define DSTS_ENUMSPD_HS 0 +#define DSTS_ENUMSPD_FS 1 +#define DSTS_ENUMSPD_LS 2 +#define DSTS_ENUMSPD_FS48 3 +#define DSTS_SUSPSTS BIT(0) + +#define DIEPMSK_NAKMSK BIT(13) +#define DIEPMSK_BNAININTRMSK BIT(9) +#define DIEPMSK_TXFIFOUNDRNMSK BIT(8) +#define DIEPMSK_TXFIFOEMPTY BIT(7) +#define DIEPMSK_INEPNAKEFFMSK BIT(6) +#define DIEPMSK_INTKNEPMISMSK BIT(5) +#define DIEPMSK_INTKNTXFEMPMSK BIT(4) +#define DIEPMSK_TIMEOUTMSK BIT(3) +#define DIEPMSK_AHBERRMSK BIT(2) +#define DIEPMSK_EPDISBLDMSK BIT(1) +#define DIEPMSK_XFERCOMPLMSK BIT(0) + +#define DOEPMSK_BNAMSK BIT(9) +#define DOEPMSK_BACK2BACKSETUP BIT(6) +#define DOEPMSK_STSPHSERCVDMSK BIT(5) +#define DOEPMSK_OUTTKNEPDISMSK BIT(4) +#define DOEPMSK_SETUPMSK BIT(3) +#define DOEPMSK_AHBERRMSK BIT(2) +#define DOEPMSK_EPDISBLDMSK BIT(1) +#define DOEPMSK_XFERCOMPLMSK BIT(0) + +#define DAINT_OUTEP_MASK GENMASK(31, 16) +#define DAINT_INEP_MASK GENMASK(15, 0) + +#define D0EPCTL_MPS_MASK GENMASK(1, 0) +#define D0EPCTL_MPS_64 0 +#define D0EPCTL_MPS_32 1 +#define D0EPCTL_MPS_16 2 +#define D0EPCTL_MPS_8 3 + +#define DXEPCTL_EPENA BIT(31) +#define DXEPCTL_EPDIS BIT(30) +#define DXEPCTL_SETD1PID BIT(29) +#define DXEPCTL_SETODDFR BIT(29) +#define DXEPCTL_SETD0PID BIT(28) +#define DXEPCTL_SETEVENFR BIT(28) +#define DXEPCTL_SNAK BIT(27) +#define DXEPCTL_CNAK BIT(26) +#define DXEPCTL_TXFNUM_MASK GENMASK(25, 22) +#define DXEPCTL_STALL BIT(21) +#define DXEPCTL_SNP BIT(20) +#define DXEPCTL_EPTYPE_MASK GENMASK(19, 18) +#define DXEPCTL_EPTYPE_CONTROL 0 +#define DXEPCTL_EPTYPE_ISO 1 +#define DXEPCTL_EPTYPE_BULK 2 +#define DXEPCTL_EPTYPE_INTERRUPT 3 +#define DXEPCTL_NAKSTS BIT(17) +#define DXEPCTL_DPID BIT(16) +#define DXEPCTL_EOFRNUM BIT(16) +#define DXEPCTL_USBACTEP BIT(15) +#define DXEPCTL_NEXTEP_MASK GENMASK(14, 11) +#define DXEPCTL_MPS_MASK GENMASK(10, 0) + +#define DXEPINT_SETUP_RCVD BIT(15) +#define DXEPINT_NYETINTRPT BIT(14) +#define DXEPINT_NAKINTRPT BIT(13) +#define DXEPINT_BBLEERRINTRPT BIT(12) +#define DXEPINT_PKTDRPSTS BIT(11) +#define DXEPINT_BNAINTR BIT(9) +#define DXEPINT_TXFIFOUNDRN BIT(8) +#define DXEPINT_OUTPKTERR BIT(8) +#define DXEPINT_TXFEMP BIT(7) +#define DXEPINT_INEPNAKEFF BIT(6) +#define DXEPINT_BACK2BACKSETUP BIT(6) +#define DXEPINT_INTKNEPMIS BIT(5) +#define DXEPINT_STSPHSERCVD BIT(5) +#define DXEPINT_INTKNTXFEMP BIT(4) +#define DXEPINT_OUTTKNEPDIS BIT(4) +#define DXEPINT_TIMEOUT BIT(3) +#define DXEPINT_SETUP BIT(3) +#define DXEPINT_AHBERR BIT(2) +#define DXEPINT_EPDISBLD BIT(1) +#define DXEPINT_XFERCOMPL BIT(0) + +#define DIEPTSIZ0_PKTCNT_MASK GENMASK(20, 19) +#define DIEPTSIZ0_XFERSIZE_MASK GENMASK(6, 0) + +#define DOEPTSIZ0_SUPCNT_MASK GENMASK(30, 29) +#define DOEPTSIZ0_PKTCNT BIT(19) +#define DOEPTSIZ0_XFERSIZE_MASK GENMASK(6, 0) + +#define DXEPTSIZ_MC_MASK GENMASK(30, 29) +#define DXEPTSIZ_PKTCNT_MASK GENMASK(28, 19) +#define DXEPTSIZ_XFERSIZE_MASK GENMASK(18, 0) + +#endif /* __DWC2_CORE_H_ */ diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 86b2cbf3f6a..b3c780a4e35 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -228,7 +228,6 @@ static int write_fifo(struct at91_ep *ep, struct at91_request *req) } buf = req->req.buf + req->req.actual; - prefetch(buf); total = req->req.length - req->req.actual; if (ep->ep.maxpacket < total) { count = ep->ep.maxpacket; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index f9326f0a7e7..72f68dba3a7 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -521,16 +521,16 @@ usba_udc_set_selfpowered(struct usb_gadget *gadget, int is_selfpowered) static int usba_udc_pullup(struct usb_gadget *gadget, int is_on) { struct usba_udc *udc = to_usba_udc(gadget); - u32 ctrl; - - ctrl = usba_readl(udc, CTRL); + /* + * Some chips don't reliably drive DP/DM lines to high impedance when + * using the DETACH/PULLD_DIS bits. + * To ensure a reliable disconnect, power cycle the controller instead + */ if (is_on) - ctrl &= ~USBA_DETACH; + usba_writel(udc, CTRL, USBA_ENABLE_MASK); else - ctrl |= USBA_DETACH; - - usba_writel(udc, CTRL, ctrl); + usba_writel(udc, CTRL, USBA_DISABLE_MASK); return 0; } diff --git a/drivers/usb/gadget/dwc2_udc_otg.c b/drivers/usb/gadget/dwc2_udc_otg.c index 7e9dd6f4268..40393141ca9 100644 --- a/drivers/usb/gadget/dwc2_udc_otg.c +++ b/drivers/usb/gadget/dwc2_udc_otg.c @@ -29,6 +29,7 @@ #include <linux/delay.h> #include <linux/printk.h> +#include <linux/bitfield.h> #include <linux/errno.h> #include <linux/list.h> @@ -45,6 +46,7 @@ #include <power/regulator.h> +#include "../common/dwc2_core.h" #include "dwc2_udc_otg_regs.h" #include "dwc2_udc_otg_priv.h" @@ -154,11 +156,11 @@ static struct usb_ep_ops dwc2_ep_ops = { /***********************************************************/ -struct dwc2_usbotg_reg *reg; +struct dwc2_core_regs *reg; bool dfu_usb_get_reset(void) { - return !!(readl(®->gintsts) & INT_RESET); + return !!(readl(®->global_regs.gintsts) & GINTSTS_USBRST); } __weak void otg_phy_init(struct dwc2_udc *dev) {} @@ -229,7 +231,7 @@ static int udc_enable(struct dwc2_udc *dev) debug_cond(DEBUG_SETUP != 0, "DWC2 USB 2.0 OTG Controller Core Initialized : 0x%x\n", - readl(®->gintmsk)); + readl(®->global_regs.gintmsk)); dev->gadget.speed = USB_SPEED_UNKNOWN; @@ -238,8 +240,8 @@ static int udc_enable(struct dwc2_udc *dev) static int dwc2_gadget_pullup(struct usb_gadget *g, int is_on) { - clrsetbits_le32(®->dctl, SOFT_DISCONNECT, - is_on ? 0 : SOFT_DISCONNECT); + clrsetbits_le32(®->device_regs.dctl, DCTL_SFTDISCON, + is_on ? 0 : DCTL_SFTDISCON); return 0; } @@ -463,12 +465,13 @@ static void reconfig_usbd(struct dwc2_udc *dev) { /* 2. Soft-reset OTG Core and then unreset again. */ int i; - unsigned int uTemp = writel(CORE_SOFT_RESET, ®->grstctl); - uint32_t dflt_gusbcfg; - uint32_t rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; + u32 dflt_gusbcfg; + u32 rx_fifo_sz, tx_fifo_sz, np_tx_fifo_sz; u32 max_hw_ep; int pdata_hw_ep; + dwc2_core_reset(reg); + debug("Resetting OTG controller\n"); dflt_gusbcfg = @@ -490,47 +493,44 @@ static void reconfig_usbd(struct dwc2_udc *dev) if (dev->pdata->usb_gusbcfg) dflt_gusbcfg = dev->pdata->usb_gusbcfg; - writel(dflt_gusbcfg, ®->gusbcfg); + writel(dflt_gusbcfg, ®->global_regs.gusbcfg); /* 3. Put the OTG device core in the disconnected state.*/ - uTemp = readl(®->dctl); - uTemp |= SOFT_DISCONNECT; - writel(uTemp, ®->dctl); + setbits_le32(®->device_regs.dctl, DCTL_SFTDISCON); udelay(20); /* 4. Make the OTG device core exit from the disconnected state.*/ - uTemp = readl(®->dctl); - uTemp = uTemp & ~SOFT_DISCONNECT; - writel(uTemp, ®->dctl); + clrbits_le32(®->device_regs.dctl, DCTL_SFTDISCON); /* 5. Configure OTG Core to initial settings of device mode.*/ /* [][1: full speed(30Mhz) 0:high speed]*/ - writel(EP_MISS_CNT(1) | DEV_SPEED_HIGH_SPEED_20, ®->dcfg); + writel(FIELD_PREP(DCFG_EPMISCNT_MASK, 1) | + FIELD_PREP(DCFG_DEVSPD_MASK, DCFG_DEVSPD_HS), ®->device_regs.dcfg); mdelay(1); /* 6. Unmask the core interrupts*/ - writel(GINTMSK_INIT, ®->gintmsk); + writel(GINTMSK_INIT, ®->global_regs.gintmsk); /* 7. Set NAK bit of EP0, EP1, EP2*/ - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->out_endp[EP0_CON].doepctl); - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->in_endp[EP0_CON].diepctl); + writel(DXEPCTL_EPDIS | DXEPCTL_SNAK, ®->device_regs.out_endp[EP0_CON].doepctl); + writel(DXEPCTL_EPDIS | DXEPCTL_SNAK, ®->device_regs.in_endp[EP0_CON].diepctl); for (i = 1; i < DWC2_MAX_ENDPOINTS; i++) { - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->out_endp[i].doepctl); - writel(DEPCTL_EPDIS|DEPCTL_SNAK, ®->in_endp[i].diepctl); + writel(DXEPCTL_EPDIS | DXEPCTL_SNAK, ®->device_regs.out_endp[i].doepctl); + writel(DXEPCTL_EPDIS | DXEPCTL_SNAK, ®->device_regs.in_endp[i].diepctl); } /* 8. Unmask EPO interrupts*/ - writel(((1 << EP0_CON) << DAINT_OUT_BIT) - | (1 << EP0_CON), ®->daintmsk); + writel(FIELD_PREP(DAINT_OUTEP_MASK, BIT(EP0_CON)) | + FIELD_PREP(DAINT_INEP_MASK, BIT(EP0_CON)), ®->device_regs.daintmsk); /* 9. Unmask device OUT EP common interrupts*/ - writel(DOEPMSK_INIT, ®->doepmsk); + writel(DOEPMSK_INIT, ®->device_regs.doepmsk); /* 10. Unmask device IN EP common interrupts*/ - writel(DIEPMSK_INIT, ®->diepmsk); + writel(DIEPMSK_INIT, ®->device_regs.diepmsk); rx_fifo_sz = RX_FIFO_SIZE; np_tx_fifo_sz = NPTX_FIFO_SIZE; @@ -544,15 +544,15 @@ static void reconfig_usbd(struct dwc2_udc *dev) tx_fifo_sz = dev->pdata->tx_fifo_sz; /* 11. Set Rx FIFO Size (in 32-bit words) */ - writel(rx_fifo_sz, ®->grxfsiz); + writel(rx_fifo_sz, ®->global_regs.grxfsiz); /* 12. Set Non Periodic Tx FIFO Size */ - writel((np_tx_fifo_sz << 16) | rx_fifo_sz, - ®->gnptxfsiz); + writel(FIELD_PREP(FIFOSIZE_DEPTH_MASK, np_tx_fifo_sz) | + FIELD_PREP(FIFOSIZE_STARTADDR_MASK, rx_fifo_sz), + ®->global_regs.gnptxfsiz); /* retrieve the number of IN Endpoints (excluding ep0) */ - max_hw_ep = (readl(®->ghwcfg4) & GHWCFG4_NUM_IN_EPS_MASK) >> - GHWCFG4_NUM_IN_EPS_SHIFT; + max_hw_ep = FIELD_GET(GHWCFG4_NUM_IN_EPS_MASK, readl(®->global_regs.ghwcfg4)); pdata_hw_ep = dev->pdata->tx_fifo_sz_nb; /* tx_fifo_sz_nb should equal to number of IN Endpoint */ @@ -564,33 +564,29 @@ static void reconfig_usbd(struct dwc2_udc *dev) if (pdata_hw_ep) tx_fifo_sz = dev->pdata->tx_fifo_sz_array[i]; - writel((rx_fifo_sz + np_tx_fifo_sz + (tx_fifo_sz * i)) | - tx_fifo_sz << 16, ®->dieptxf[i]); + writel(FIELD_PREP(FIFOSIZE_DEPTH_MASK, tx_fifo_sz) | + FIELD_PREP(FIFOSIZE_STARTADDR_MASK, + rx_fifo_sz + np_tx_fifo_sz + tx_fifo_sz * i), + ®->global_regs.dptxfsizn[i]); } /* Flush the RX FIFO */ - writel(RX_FIFO_FLUSH, ®->grstctl); - while (readl(®->grstctl) & RX_FIFO_FLUSH) - debug("%s: waiting for DWC2_UDC_OTG_GRSTCTL\n", __func__); + dwc2_flush_rx_fifo(reg); /* Flush all the Tx FIFO's */ - writel(TX_FIFO_FLUSH_ALL, ®->grstctl); - writel(TX_FIFO_FLUSH_ALL | TX_FIFO_FLUSH, ®->grstctl); - while (readl(®->grstctl) & TX_FIFO_FLUSH) - debug("%s: waiting for DWC2_UDC_OTG_GRSTCTL\n", __func__); + dwc2_flush_tx_fifo(reg, GRSTCTL_TXFNUM_ALL); /* 13. Clear NAK bit of EP0, EP1, EP2*/ /* For Slave mode*/ /* EP0: Control OUT */ - writel(DEPCTL_EPDIS | DEPCTL_CNAK, - ®->out_endp[EP0_CON].doepctl); + writel(DXEPCTL_EPDIS | DXEPCTL_CNAK, + ®->device_regs.out_endp[EP0_CON].doepctl); /* 14. Initialize OTG Link Core.*/ - writel(GAHBCFG_INIT, ®->gahbcfg); + writel(GAHBCFG_INIT, ®->global_regs.gahbcfg); } static void set_max_pktsize(struct dwc2_udc *dev, enum usb_device_speed speed) { - unsigned int ep_ctrl; int i; if (speed == USB_SPEED_HIGH) { @@ -610,12 +606,10 @@ static void set_max_pktsize(struct dwc2_udc *dev, enum usb_device_speed speed) dev->ep[i].ep.maxpacket = ep_fifo_size; /* EP0 - Control IN (64 bytes)*/ - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); - writel(ep_ctrl|(0<<0), ®->in_endp[EP0_CON].diepctl); + setbits_le32(®->device_regs.in_endp[EP0_CON].diepctl, (0 << 0)); /* EP0 - Control OUT (64 bytes)*/ - ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); - writel(ep_ctrl|(0<<0), ®->out_endp[EP0_CON].doepctl); + setbits_le32(®->device_regs.out_endp[EP0_CON].doepctl, (0 << 0)); } static int dwc2_ep_enable(struct usb_ep *_ep, @@ -904,7 +898,7 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata) dev->pdata = pdata; - reg = (struct dwc2_usbotg_reg *)pdata->regs_otg; + reg = (struct dwc2_core_regs *)pdata->regs_otg; dev->gadget.is_dualspeed = 1; /* Hack only*/ dev->gadget.is_otg = 0; @@ -932,8 +926,8 @@ int dwc2_udc_probe(struct dwc2_plat_otg_data *pdata) int dwc2_udc_handle_interrupt(void) { - u32 intr_status = readl(®->gintsts); - u32 gintmsk = readl(®->gintmsk); + u32 intr_status = readl(®->global_regs.gintsts); + u32 gintmsk = readl(®->global_regs.gintmsk); if (intr_status & gintmsk) return dwc2_udc_irq(1, (void *)the_controller); @@ -1087,8 +1081,8 @@ static int dwc2_udc_otg_probe(struct udevice *dev) { struct dwc2_plat_otg_data *plat = dev_get_plat(dev); struct dwc2_priv_data *priv = dev_get_priv(dev); - struct dwc2_usbotg_reg *usbotg_reg = - (struct dwc2_usbotg_reg *)plat->regs_otg; + struct dwc2_core_regs *usbotg_reg = + (struct dwc2_core_regs *)plat->regs_otg; int ret; ret = dwc2_udc_otg_clk_init(dev, &priv->clks); @@ -1123,21 +1117,22 @@ static int dwc2_udc_otg_probe(struct udevice *dev) if (plat->force_b_session_valid && !plat->force_vbus_detection) { /* Override VBUS detection: enable then value*/ - setbits_le32(&usbotg_reg->gotgctl, VB_VALOEN); - setbits_le32(&usbotg_reg->gotgctl, VB_VALOVAL); + setbits_le32(&usbotg_reg->global_regs.gotgctl, GOTGCTL_VBVALOEN); + setbits_le32(&usbotg_reg->global_regs.gotgctl, GOTGCTL_VBVALOVAL); } else { /* Enable VBUS sensing */ - setbits_le32(&usbotg_reg->ggpio, + setbits_le32(&usbotg_reg->global_regs.ggpio, GGPIO_STM32_OTG_GCCFG_VBDEN); } if (plat->force_b_session_valid) { /* Override B session bits: enable then value */ - setbits_le32(&usbotg_reg->gotgctl, A_VALOEN | B_VALOEN); - setbits_le32(&usbotg_reg->gotgctl, - A_VALOVAL | B_VALOVAL); + setbits_le32(&usbotg_reg->global_regs.gotgctl, + GOTGCTL_AVALOEN | GOTGCTL_BVALOEN); + setbits_le32(&usbotg_reg->global_regs.gotgctl, + GOTGCTL_AVALOVAL | GOTGCTL_BVALOVAL); } else { /* Enable ID detection */ - setbits_le32(&usbotg_reg->ggpio, + setbits_le32(&usbotg_reg->global_regs.ggpio, GGPIO_STM32_OTG_GCCFG_IDEN); } } @@ -1200,10 +1195,10 @@ U_BOOT_DRIVER(dwc2_udc_otg) = { int dwc2_udc_B_session_valid(struct udevice *dev) { struct dwc2_plat_otg_data *plat = dev_get_plat(dev); - struct dwc2_usbotg_reg *usbotg_reg = - (struct dwc2_usbotg_reg *)plat->regs_otg; + struct dwc2_core_regs *usbotg_reg = + (struct dwc2_core_regs *)plat->regs_otg; - return readl(&usbotg_reg->gotgctl) & B_SESSION_VALID; + return readl(&usbotg_reg->global_regs.gotgctl) & GOTGCTL_BSESVLD; } #else int dm_usb_gadget_handle_interrupts(struct udevice *dev) diff --git a/drivers/usb/gadget/dwc2_udc_otg_phy.c b/drivers/usb/gadget/dwc2_udc_otg_phy.c index c7eea7b3442..e0ac5d142b0 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_phy.c +++ b/drivers/usb/gadget/dwc2_udc_otg_phy.c @@ -48,29 +48,24 @@ void otg_phy_init(struct dwc2_udc *dev) printf("USB PHY0 Enable\n"); /* Enable PHY */ - writel(readl(usb_phy_ctrl) | USB_PHY_CTRL_EN0, usb_phy_ctrl); + setbits_le32(usb_phy_ctrl, USB_PHY_CTRL_EN0); if (dev->pdata->usb_flags == PHY0_SLEEP) /* C210 Universal */ - writel((readl(&phy->phypwr) - &~(PHY_0_SLEEP | OTG_DISABLE_0 | ANALOG_PWRDOWN) - &~FORCE_SUSPEND_0), &phy->phypwr); + clrbits_le32(&phy->phypwr, PHY_0_SLEEP | OTG_DISABLE_0 | + ANALOG_PWRDOWN | FORCE_SUSPEND_0); else /* C110 GONI */ - writel((readl(&phy->phypwr) &~(OTG_DISABLE_0 | ANALOG_PWRDOWN) - &~FORCE_SUSPEND_0), &phy->phypwr); + clrbits_le32(&phy->phypwr, OTG_DISABLE_0 | ANALOG_PWRDOWN | FORCE_SUSPEND_0); if (s5p_cpu_id == 0x4412) - writel((readl(&phy->phyclk) & ~(EXYNOS4X12_ID_PULLUP0 | - EXYNOS4X12_COMMON_ON_N0)) | EXYNOS4X12_CLK_SEL_24MHZ, - &phy->phyclk); /* PLL 24Mhz */ + clrsetbits_le32(&phy->phyclk, EXYNOS4X12_ID_PULLUP0 | EXYNOS4X12_COMMON_ON_N0, + EXYNOS4X12_CLK_SEL_24MHZ); /* PLL 24Mhz */ else - writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)) | - CLK_SEL_24MHZ, &phy->phyclk); /* PLL 24Mhz */ + clrsetbits_le32(&phy->phyclk, ID_PULLUP0 | COMMON_ON_N0, + CLK_SEL_24MHZ); /* PLL 24Mhz */ - writel((readl(&phy->rstcon) &~(LINK_SW_RST | PHYLNK_SW_RST)) - | PHY_SW_RST0, &phy->rstcon); + clrsetbits_le32(&phy->rstcon, LINK_SW_RST | PHYLNK_SW_RST, PHY_SW_RST0); udelay(10); - writel(readl(&phy->rstcon) - &~(PHY_SW_RST0 | LINK_SW_RST | PHYLNK_SW_RST), &phy->rstcon); + clrbits_le32(&phy->rstcon, PHY_SW_RST0 | LINK_SW_RST | PHYLNK_SW_RST); udelay(10); } @@ -86,13 +81,11 @@ void otg_phy_off(struct dwc2_udc *dev) writel(readl(&phy->phypwr) &~PHY_SW_RST0, &phy->rstcon); udelay(20); - writel(readl(&phy->phypwr) | OTG_DISABLE_0 | ANALOG_PWRDOWN - | FORCE_SUSPEND_0, &phy->phypwr); + setbits_le32(&phy->phypwr, OTG_DISABLE_0 | ANALOG_PWRDOWN | FORCE_SUSPEND_0); - writel(readl(usb_phy_ctrl) &~USB_PHY_CTRL_EN0, usb_phy_ctrl); + clrbits_le32(usb_phy_ctrl, USB_PHY_CTRL_EN0); - writel((readl(&phy->phyclk) & ~(ID_PULLUP0 | COMMON_ON_N0)), - &phy->phyclk); + clrbits_le32(&phy->phyclk, ID_PULLUP0 | COMMON_ON_N0); udelay(10000); diff --git a/drivers/usb/gadget/dwc2_udc_otg_regs.h b/drivers/usb/gadget/dwc2_udc_otg_regs.h index 01056fab1c2..5dd2d3a45bf 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_regs.h +++ b/drivers/usb/gadget/dwc2_udc_otg_regs.h @@ -10,286 +10,59 @@ #ifndef __ASM_ARCH_REGS_USB_OTG_HS_H #define __ASM_ARCH_REGS_USB_OTG_HS_H -/* USB2.0 OTG Controller register */ -#include <linux/bitops.h> +#include "../common/dwc2_core.h" + struct dwc2_usbotg_phy { u32 phypwr; u32 phyclk; u32 rstcon; }; -/* Device Logical IN Endpoint-Specific Registers */ -struct dwc2_dev_in_endp { - u32 diepctl; - u8 res1[4]; - u32 diepint; - u8 res2[4]; - u32 dieptsiz; - u32 diepdma; - u8 res3[4]; - u32 diepdmab; -}; - -/* Device Logical OUT Endpoint-Specific Registers */ -struct dwc2_dev_out_endp { - u32 doepctl; - u8 res1[4]; - u32 doepint; - u8 res2[4]; - u32 doeptsiz; - u32 doepdma; - u8 res3[4]; - u32 doepdmab; -}; - -struct ep_fifo { - u32 fifo; - u8 res[4092]; -}; - -/* USB2.0 OTG Controller register */ -struct dwc2_usbotg_reg { - /* Core Global Registers */ - u32 gotgctl; /* OTG Control & Status */ - u32 gotgint; /* OTG Interrupt */ - u32 gahbcfg; /* Core AHB Configuration */ - u32 gusbcfg; /* Core USB Configuration */ - u32 grstctl; /* Core Reset */ - u32 gintsts; /* Core Interrupt */ - u32 gintmsk; /* Core Interrupt Mask */ - u32 grxstsr; /* Receive Status Debug Read/Status Read */ - u32 grxstsp; /* Receive Status Debug Pop/Status Pop */ - u32 grxfsiz; /* Receive FIFO Size */ - u32 gnptxfsiz; /* Non-Periodic Transmit FIFO Size */ - u8 res0[12]; - u32 ggpio; /* 0x038 */ - u8 res1[20]; - u32 ghwcfg4; /* User HW Config4 */ - u8 res2[176]; - u32 dieptxf[15]; /* Device Periodic Transmit FIFO size register */ - u8 res3[1728]; - /* Device Configuration */ - u32 dcfg; /* Device Configuration Register */ - u32 dctl; /* Device Control */ - u32 dsts; /* Device Status */ - u8 res4[4]; - u32 diepmsk; /* Device IN Endpoint Common Interrupt Mask */ - u32 doepmsk; /* Device OUT Endpoint Common Interrupt Mask */ - u32 daint; /* Device All Endpoints Interrupt */ - u32 daintmsk; /* Device All Endpoints Interrupt Mask */ - u8 res5[224]; - struct dwc2_dev_in_endp in_endp[16]; - struct dwc2_dev_out_endp out_endp[16]; - u8 res6[768]; - struct ep_fifo ep[16]; -}; - -/*===================================================================== */ -/*definitions related to CSR setting */ - -/* DWC2_UDC_OTG_GOTGCTL */ -#define B_SESSION_VALID BIT(19) -#define A_SESSION_VALID BIT(18) -#define B_VALOVAL BIT(7) -#define B_VALOEN BIT(6) -#define A_VALOVAL BIT(5) -#define A_VALOEN BIT(4) -#define VB_VALOVAL BIT(3) -#define VB_VALOEN BIT(2) - -/* DWC2_UDC_OTG_GOTINT */ -#define GOTGINT_SES_END_DET (1<<2) - -/* DWC2_UDC_OTG_GAHBCFG */ -#define PTXFE_HALF (0<<8) -#define PTXFE_ZERO (1<<8) -#define NPTXFE_HALF (0<<7) -#define NPTXFE_ZERO (1<<7) -#define MODE_SLAVE (0<<5) -#define MODE_DMA (1<<5) -#define BURST_SINGLE (0<<1) -#define BURST_INCR (1<<1) -#define BURST_INCR4 (3<<1) -#define BURST_INCR8 (5<<1) -#define BURST_INCR16 (7<<1) -#define GBL_INT_UNMASK (1<<0) -#define GBL_INT_MASK (0<<0) - -/* DWC2_UDC_OTG_GRSTCTL */ -#define AHB_MASTER_IDLE (1u<<31) -#define CORE_SOFT_RESET (0x1<<0) - -/* DWC2_UDC_OTG_GINTSTS/DWC2_UDC_OTG_GINTMSK core interrupt register */ -#define INT_RESUME (1u<<31) -#define INT_DISCONN (0x1<<29) -#define INT_CONN_ID_STS_CNG (0x1<<28) -#define INT_OUT_EP (0x1<<19) -#define INT_IN_EP (0x1<<18) -#define INT_ENUMDONE (0x1<<13) -#define INT_RESET (0x1<<12) -#define INT_SUSPEND (0x1<<11) -#define INT_EARLY_SUSPEND (0x1<<10) -#define INT_NP_TX_FIFO_EMPTY (0x1<<5) -#define INT_RX_FIFO_NOT_EMPTY (0x1<<4) -#define INT_SOF (0x1<<3) -#define INT_OTG (0x1<<2) -#define INT_DEV_MODE (0x0<<0) -#define INT_HOST_MODE (0x1<<1) -#define INT_GOUTNakEff (0x01<<7) -#define INT_GINNakEff (0x01<<6) - #define FULL_SPEED_CONTROL_PKT_SIZE 8 #define FULL_SPEED_BULK_PKT_SIZE 64 #define HIGH_SPEED_CONTROL_PKT_SIZE 64 #define HIGH_SPEED_BULK_PKT_SIZE 512 -#define RX_FIFO_SIZE (1024) -#define NPTX_FIFO_SIZE (1024) -#define PTX_FIFO_SIZE (384) - -#define DEPCTL_TXFNUM_0 (0x0<<22) -#define DEPCTL_TXFNUM_1 (0x1<<22) -#define DEPCTL_TXFNUM_2 (0x2<<22) -#define DEPCTL_TXFNUM_3 (0x3<<22) -#define DEPCTL_TXFNUM_4 (0x4<<22) - -/* Enumeration speed */ -#define USB_HIGH_30_60MHZ (0x0<<1) -#define USB_FULL_30_60MHZ (0x1<<1) -#define USB_LOW_6MHZ (0x2<<1) -#define USB_FULL_48MHZ (0x3<<1) +#define RX_FIFO_SIZE 1024 +#define NPTX_FIFO_SIZE 1024 +#define PTX_FIFO_SIZE 384 -/* DWC2_UDC_OTG_GRXSTSP STATUS */ -#define OUT_PKT_RECEIVED (0x2<<17) -#define OUT_TRANSFER_COMPLELTED (0x3<<17) -#define SETUP_TRANSACTION_COMPLETED (0x4<<17) -#define SETUP_PKT_RECEIVED (0x6<<17) -#define GLOBAL_OUT_NAK (0x1<<17) - -/* DWC2_UDC_OTG_DCTL device control register */ -#define NORMAL_OPERATION (0x1<<0) -#define SOFT_DISCONNECT (0x1<<1) - -/* DWC2_UDC_OTG_DAINT device all endpoint interrupt register */ -#define DAINT_OUT_BIT (16) -#define DAINT_MASK (0xFFFF) - -/* DWC2_UDC_OTG_DIEPCTL0/DOEPCTL0 device - control IN/OUT endpoint 0 control register */ -#define DEPCTL_EPENA (0x1<<31) -#define DEPCTL_EPDIS (0x1<<30) -#define DEPCTL_SETD1PID (0x1<<29) -#define DEPCTL_SETD0PID (0x1<<28) -#define DEPCTL_SNAK (0x1<<27) -#define DEPCTL_CNAK (0x1<<26) -#define DEPCTL_STALL (0x1<<21) -#define DEPCTL_TYPE_BIT (18) -#define DEPCTL_TYPE_MASK (0x3<<18) -#define DEPCTL_CTRL_TYPE (0x0<<18) -#define DEPCTL_ISO_TYPE (0x1<<18) -#define DEPCTL_BULK_TYPE (0x2<<18) -#define DEPCTL_INTR_TYPE (0x3<<18) -#define DEPCTL_USBACTEP (0x1<<15) -#define DEPCTL_NEXT_EP_BIT (11) -#define DEPCTL_MPS_BIT (0) -#define DEPCTL_MPS_MASK (0x7FF) - -#define DEPCTL0_MPS_64 (0x0<<0) -#define DEPCTL0_MPS_32 (0x1<<0) -#define DEPCTL0_MPS_16 (0x2<<0) -#define DEPCTL0_MPS_8 (0x3<<0) -#define DEPCTL_MPS_BULK_512 (512<<0) -#define DEPCTL_MPS_INT_MPS_16 (16<<0) - -#define DIEPCTL0_NEXT_EP_BIT (11) - -/* DWC2_UDC_OTG_DIEPMSK/DOEPMSK device IN/OUT endpoint - common interrupt mask register */ -/* DWC2_UDC_OTG_DIEPINTn/DOEPINTn device IN/OUT endpoint interrupt register */ -#define BACK2BACK_SETUP_RECEIVED (0x1<<6) -#define INTKNEPMIS (0x1<<5) -#define INTKN_TXFEMP (0x1<<4) -#define NON_ISO_IN_EP_TIMEOUT (0x1<<3) -#define CTRL_OUT_EP_SETUP_PHASE_DONE (0x1<<3) -#define AHB_ERROR (0x1<<2) -#define EPDISBLD (0x1<<1) -#define TRANSFER_DONE (0x1<<0) - -#define USB_PHY_CTRL_EN0 (0x1 << 0) +#define USB_PHY_CTRL_EN0 BIT(0) /* OPHYPWR */ -#define PHY_0_SLEEP (0x1 << 5) -#define OTG_DISABLE_0 (0x1 << 4) -#define ANALOG_PWRDOWN (0x1 << 3) -#define FORCE_SUSPEND_0 (0x1 << 0) +#define PHY_0_SLEEP BIT(5) +#define OTG_DISABLE_0 BIT(4) +#define ANALOG_PWRDOWN BIT(3) +#define FORCE_SUSPEND_0 BIT(0) /* URSTCON */ -#define HOST_SW_RST (0x1 << 4) -#define PHY_SW_RST1 (0x1 << 3) -#define PHYLNK_SW_RST (0x1 << 2) -#define LINK_SW_RST (0x1 << 1) -#define PHY_SW_RST0 (0x1 << 0) +#define HOST_SW_RST BIT(4) +#define PHY_SW_RST1 BIT(3) +#define PHYLNK_SW_RST BIT(2) +#define LINK_SW_RST BIT(1) +#define PHY_SW_RST0 BIT(0) /* OPHYCLK */ -#define COMMON_ON_N1 (0x1 << 7) -#define COMMON_ON_N0 (0x1 << 4) -#define ID_PULLUP0 (0x1 << 2) -#define CLK_SEL_24MHZ (0x3 << 0) -#define CLK_SEL_12MHZ (0x2 << 0) -#define CLK_SEL_48MHZ (0x0 << 0) - -#define EXYNOS4X12_ID_PULLUP0 (0x01 << 3) -#define EXYNOS4X12_COMMON_ON_N0 (0x01 << 4) +#define COMMON_ON_N1 BIT(7) +#define COMMON_ON_N0 BIT(4) +#define ID_PULLUP0 BIT(2) +#define CLK_SEL_24MHZ (0x3 << 0) +#define CLK_SEL_12MHZ (0x2 << 0) +#define CLK_SEL_48MHZ (0x0 << 0) + +#define EXYNOS4X12_ID_PULLUP0 BIT(3) +#define EXYNOS4X12_COMMON_ON_N0 BIT(4) #define EXYNOS4X12_CLK_SEL_12MHZ (0x02 << 0) #define EXYNOS4X12_CLK_SEL_24MHZ (0x05 << 0) -/* Device Configuration Register DCFG */ -#define DEV_SPEED_HIGH_SPEED_20 (0x0 << 0) -#define DEV_SPEED_FULL_SPEED_20 (0x1 << 0) -#define DEV_SPEED_LOW_SPEED_11 (0x2 << 0) -#define DEV_SPEED_FULL_SPEED_11 (0x3 << 0) -#define EP_MISS_CNT(x) (x << 18) -#define DEVICE_ADDRESS(x) (x << 4) - -/* Core Reset Register (GRSTCTL) */ -#define TX_FIFO_FLUSH (0x1 << 5) -#define RX_FIFO_FLUSH (0x1 << 4) -#define TX_FIFO_NUMBER(x) (x << 6) -#define TX_FIFO_FLUSH_ALL TX_FIFO_NUMBER(0x10) - /* Masks definitions */ -#define GINTMSK_INIT (INT_OUT_EP | INT_IN_EP | INT_RESUME | INT_ENUMDONE\ - | INT_RESET | INT_SUSPEND | INT_OTG) -#define DOEPMSK_INIT (CTRL_OUT_EP_SETUP_PHASE_DONE | AHB_ERROR|TRANSFER_DONE) -#define DIEPMSK_INIT (NON_ISO_IN_EP_TIMEOUT|AHB_ERROR|TRANSFER_DONE) -#define GAHBCFG_INIT (PTXFE_HALF | NPTXFE_HALF | MODE_DMA | BURST_INCR4\ - | GBL_INT_UNMASK) - -/* Device Endpoint X Transfer Size Register (DIEPTSIZX) */ -#define DIEPT_SIZ_PKT_CNT(x) (x << 19) -#define DIEPT_SIZ_XFER_SIZE(x) (x << 0) - -/* Device OUT Endpoint X Transfer Size Register (DOEPTSIZX) */ -#define DOEPT_SIZ_PKT_CNT(x) (x << 19) -#define DOEPT_SIZ_XFER_SIZE(x) (x << 0) -#define DOEPT_SIZ_XFER_SIZE_MAX_EP0 (0x7F << 0) -#define DOEPT_SIZ_XFER_SIZE_MAX_EP (0x7FFF << 0) - -/* Device Endpoint-N Control Register (DIEPCTLn/DOEPCTLn) */ -#define DIEPCTL_TX_FIFO_NUM(x) (x << 22) -#define DIEPCTL_TX_FIFO_NUM_MASK (~DIEPCTL_TX_FIFO_NUM(0xF)) - -/* Device ALL Endpoints Interrupt Register (DAINT) */ -#define DAINT_IN_EP_INT(x) (x << 0) -#define DAINT_OUT_EP_INT(x) (x << 16) - -/* User HW Config4 */ -#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26) -#define GHWCFG4_NUM_IN_EPS_SHIFT 26 - -/* OTG general core configuration register (OTG_GCCFG:0x38) for STM32MP1 */ -#define GGPIO_STM32_OTG_GCCFG_VBDEN BIT(21) -#define GGPIO_STM32_OTG_GCCFG_IDEN BIT(22) +#define GINTMSK_INIT (GINTSTS_WKUPINT | GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | \ + GINTSTS_USBRST | GINTSTS_USBSUSP | GINTSTS_OTGINT) +#define DOEPMSK_INIT (DOEPMSK_SETUPMSK | DOEPMSK_AHBERRMSK | DOEPMSK_XFERCOMPLMSK) +#define DIEPMSK_INIT (DIEPMSK_TIMEOUTMSK | DIEPMSK_AHBERRMSK | DIEPMSK_XFERCOMPLMSK) +#define GAHBCFG_INIT (GAHBCFG_DMA_EN | \ + FIELD_PREP(GAHBCFG_HBSTLEN_MASK, GAHBCFG_HBSTLEN_INCR4) | \ + GAHBCFG_GLBL_INTR_EN) #endif diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c index c0408bae076..fca052b4556 100644 --- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c @@ -19,6 +19,7 @@ #include <cpu_func.h> #include <log.h> +#include <linux/bitfield.h> #include <linux/bug.h> static u8 clear_feature_num; @@ -30,66 +31,56 @@ int clear_feature_flag; static inline void dwc2_udc_ep0_zlp(struct dwc2_udc *dev) { - u32 ep_ctrl; + writel(phys_to_bus((unsigned long)usb_ctrl_dma_addr), + ®->device_regs.in_endp[EP0_CON].diepdma); + writel(FIELD_PREP(DXEPTSIZ_PKTCNT_MASK, 1), ®->device_regs.in_endp[EP0_CON].dieptsiz); - writel(phys_to_bus((unsigned long)usb_ctrl_dma_addr), ®->in_endp[EP0_CON].diepdma); - writel(DIEPT_SIZ_PKT_CNT(1), ®->in_endp[EP0_CON].dieptsiz); - - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); - writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, - ®->in_endp[EP0_CON].diepctl); + setbits_le32(®->device_regs.in_endp[EP0_CON].diepctl, DXEPCTL_EPENA | DXEPCTL_CNAK); debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); + __func__, readl(®->device_regs.in_endp[EP0_CON].diepctl)); dev->ep0state = WAIT_FOR_IN_COMPLETE; } static void dwc2_udc_pre_setup(void) { - u32 ep_ctrl; - debug_cond(DEBUG_IN_EP, "%s : Prepare Setup packets.\n", __func__); - writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest), - ®->out_endp[EP0_CON].doeptsiz); - writel(phys_to_bus((unsigned long)usb_ctrl_dma_addr), ®->out_endp[EP0_CON].doepdma); + writel(FIELD_PREP(DXEPTSIZ_PKTCNT_MASK, 1) | sizeof(struct usb_ctrlrequest), + ®->device_regs.out_endp[EP0_CON].doeptsiz); + writel(phys_to_bus((unsigned long)usb_ctrl_dma_addr), + ®->device_regs.out_endp[EP0_CON].doepdma); - ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); - writel(ep_ctrl|DEPCTL_EPENA, ®->out_endp[EP0_CON].doepctl); + setbits_le32(®->device_regs.out_endp[EP0_CON].doepctl, DXEPCTL_EPENA); debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); + __func__, readl(®->device_regs.in_endp[EP0_CON].diepctl)); debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n", - __func__, readl(®->out_endp[EP0_CON].doepctl)); - + __func__, readl(®->device_regs.out_endp[EP0_CON].doepctl)); } static inline void dwc2_ep0_complete_out(void) { - u32 ep_ctrl; - debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); + __func__, readl(®->device_regs.in_endp[EP0_CON].diepctl)); debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n", - __func__, readl(®->out_endp[EP0_CON].doepctl)); + __func__, readl(®->device_regs.out_endp[EP0_CON].doepctl)); debug_cond(DEBUG_IN_EP, "%s : Prepare Complete Out packet.\n", __func__); - writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest), - ®->out_endp[EP0_CON].doeptsiz); - writel(phys_to_bus((unsigned long)usb_ctrl_dma_addr), ®->out_endp[EP0_CON].doepdma); + writel(FIELD_PREP(DXEPTSIZ_PKTCNT_MASK, 1) | sizeof(struct usb_ctrlrequest), + ®->device_regs.out_endp[EP0_CON].doeptsiz); + writel(phys_to_bus((unsigned long)usb_ctrl_dma_addr), + ®->device_regs.out_endp[EP0_CON].doepdma); - ep_ctrl = readl(®->out_endp[EP0_CON].doepctl); - writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, - ®->out_endp[EP0_CON].doepctl); + setbits_le32(®->device_regs.out_endp[EP0_CON].doepctl, DXEPCTL_EPENA | DXEPCTL_CNAK); debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DIEPCTL0 = 0x%x\n", - __func__, readl(®->in_endp[EP0_CON].diepctl)); + __func__, readl(®->device_regs.in_endp[EP0_CON].diepctl)); debug_cond(DEBUG_EP0 != 0, "%s:EP0 ZLP DOEPCTL0 = 0x%x\n", - __func__, readl(®->out_endp[EP0_CON].doepctl)); - + __func__, readl(®->device_regs.out_endp[EP0_CON].doepctl)); } static int setdma_rx(struct dwc2_ep *ep, struct dwc2_request *req) @@ -110,33 +101,33 @@ static int setdma_rx(struct dwc2_ep *ep, struct dwc2_request *req) else pktcnt = (length - 1)/(ep->ep.maxpacket) + 1; - ctrl = readl(®->out_endp[ep_num].doepctl); + ctrl = readl(®->device_regs.out_endp[ep_num].doepctl); invalidate_dcache_range((unsigned long) ep->dma_buf, (unsigned long) ep->dma_buf + ROUND(ep->len, CONFIG_SYS_CACHELINE_SIZE)); - writel(phys_to_bus((unsigned long)ep->dma_buf), ®->out_endp[ep_num].doepdma); - writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length), - ®->out_endp[ep_num].doeptsiz); - writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, ®->out_endp[ep_num].doepctl); + writel(phys_to_bus((unsigned long)ep->dma_buf), ®->device_regs.out_endp[ep_num].doepdma); + writel(FIELD_PREP(DXEPTSIZ_PKTCNT_MASK, pktcnt) | + FIELD_PREP(DXEPTSIZ_XFERSIZE_MASK, length), + ®->device_regs.out_endp[ep_num].doeptsiz); + writel(DXEPCTL_EPENA | DXEPCTL_CNAK | ctrl, ®->device_regs.out_endp[ep_num].doepctl); debug_cond(DEBUG_OUT_EP != 0, "%s: EP%d RX DMA start : DOEPDMA = 0x%x," "DOEPTSIZ = 0x%x, DOEPCTL = 0x%x\n" "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n", __func__, ep_num, - readl(®->out_endp[ep_num].doepdma), - readl(®->out_endp[ep_num].doeptsiz), - readl(®->out_endp[ep_num].doepctl), + readl(®->device_regs.out_endp[ep_num].doepdma), + readl(®->device_regs.out_endp[ep_num].doeptsiz), + readl(®->device_regs.out_endp[ep_num].doepctl), buf, pktcnt, length); return 0; - } static int setdma_tx(struct dwc2_ep *ep, struct dwc2_request *req) { - u32 *buf, ctrl = 0; + u32 *buf; u32 length, pktcnt; u32 ep_num = ep_index(ep); @@ -159,34 +150,26 @@ static int setdma_tx(struct dwc2_ep *ep, struct dwc2_request *req) pktcnt = (length - 1)/(ep->ep.maxpacket) + 1; /* Flush the endpoint's Tx FIFO */ - writel(TX_FIFO_NUMBER(ep->fifo_num), ®->grstctl); - writel(TX_FIFO_NUMBER(ep->fifo_num) | TX_FIFO_FLUSH, ®->grstctl); - while (readl(®->grstctl) & TX_FIFO_FLUSH) - ; - - writel(phys_to_bus((unsigned long)ep->dma_buf), ®->in_endp[ep_num].diepdma); - writel(DIEPT_SIZ_PKT_CNT(pktcnt) | DIEPT_SIZ_XFER_SIZE(length), - ®->in_endp[ep_num].dieptsiz); + dwc2_flush_tx_fifo(reg, ep->fifo_num); - ctrl = readl(®->in_endp[ep_num].diepctl); + writel(phys_to_bus((unsigned long)ep->dma_buf), ®->device_regs.in_endp[ep_num].diepdma); + writel(FIELD_PREP(DXEPTSIZ_PKTCNT_MASK, pktcnt) | + FIELD_PREP(DXEPTSIZ_XFERSIZE_MASK, length), + ®->device_regs.in_endp[ep_num].dieptsiz); - /* Write the FIFO number to be used for this endpoint */ - ctrl &= DIEPCTL_TX_FIFO_NUM_MASK; - ctrl |= DIEPCTL_TX_FIFO_NUM(ep->fifo_num); - - /* Clear reserved (Next EP) bits */ - ctrl = (ctrl&~(EP_MASK<<DEPCTL_NEXT_EP_BIT)); - - writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, ®->in_endp[ep_num].diepctl); + clrsetbits_le32(®->device_regs.in_endp[ep_num].diepctl, + DXEPCTL_TXFNUM_MASK | DXEPCTL_NEXTEP_MASK, + FIELD_PREP(DXEPCTL_TXFNUM_MASK, ep->fifo_num) | + DXEPCTL_EPENA | DXEPCTL_CNAK); debug_cond(DEBUG_IN_EP, "%s:EP%d TX DMA start : DIEPDMA0 = 0x%x," "DIEPTSIZ0 = 0x%x, DIEPCTL0 = 0x%x\n" "\tbuf = 0x%p, pktcnt = %d, xfersize = %d\n", __func__, ep_num, - readl(®->in_endp[ep_num].diepdma), - readl(®->in_endp[ep_num].dieptsiz), - readl(®->in_endp[ep_num].diepctl), + readl(®->device_regs.in_endp[ep_num].diepdma), + readl(®->device_regs.in_endp[ep_num].dieptsiz), + readl(®->device_regs.in_endp[ep_num].diepctl), buf, pktcnt, length); return length; @@ -207,12 +190,12 @@ static void complete_rx(struct dwc2_udc *dev, u8 ep_num) } req = list_entry(ep->queue.next, struct dwc2_request, queue); - ep_tsr = readl(®->out_endp[ep_num].doeptsiz); + ep_tsr = readl(®->device_regs.out_endp[ep_num].doeptsiz); if (ep_num == EP0_CON) - xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP0); + xfer_size = FIELD_PREP(DIEPTSIZ0_XFERSIZE_MASK, ep_tsr); else - xfer_size = (ep_tsr & DOEPT_SIZ_XFER_SIZE_MAX_EP); + xfer_size = FIELD_PREP(DXEPTSIZ_XFERSIZE_MASK, ep_tsr); xfer_size = ep->len - xfer_size; @@ -288,7 +271,7 @@ static void complete_tx(struct dwc2_udc *dev, u8 ep_num) req = list_entry(ep->queue.next, struct dwc2_request, queue); - ep_tsr = readl(®->in_endp[ep_num].dieptsiz); + ep_tsr = readl(®->device_regs.in_endp[ep_num].dieptsiz); xfer_size = ep->len; is_short = (xfer_size < ep->ep.maxpacket); @@ -373,23 +356,23 @@ static void process_ep_in_intr(struct dwc2_udc *dev) u32 ep_intr, ep_intr_status; u8 ep_num = 0; - ep_intr = readl(®->daint); + ep_intr = readl(®->device_regs.daint); debug_cond(DEBUG_IN_EP, "*** %s: EP In interrupt : DAINT = 0x%x\n", __func__, ep_intr); - ep_intr &= DAINT_MASK; + ep_intr = FIELD_GET(DAINT_INEP_MASK, ep_intr); while (ep_intr) { - if (ep_intr & DAINT_IN_EP_INT(1)) { - ep_intr_status = readl(®->in_endp[ep_num].diepint); + if (ep_intr & BIT(EP0_CON)) { + ep_intr_status = readl(®->device_regs.in_endp[ep_num].diepint); debug_cond(DEBUG_IN_EP, "\tEP%d-IN : DIEPINT = 0x%x\n", ep_num, ep_intr_status); /* Interrupt Clear */ - writel(ep_intr_status, ®->in_endp[ep_num].diepint); + writel(ep_intr_status, ®->device_regs.in_endp[ep_num].diepint); - if (ep_intr_status & TRANSFER_DONE) { + if (ep_intr_status & DIEPMSK_XFERCOMPLMSK) { complete_tx(dev, ep_num); if (ep_num == 0) { @@ -420,31 +403,30 @@ static void process_ep_out_intr(struct dwc2_udc *dev) u32 ep_intr, ep_intr_status; u8 ep_num = 0; u32 ep_tsr = 0, xfer_size = 0; - u32 epsiz_reg = reg->out_endp[ep_num].doeptsiz; + u32 epsiz_reg = reg->device_regs.out_endp[ep_num].doeptsiz; u32 req_size = sizeof(struct usb_ctrlrequest); - ep_intr = readl(®->daint); + ep_intr = readl(®->device_regs.daint); debug_cond(DEBUG_OUT_EP != 0, "*** %s: EP OUT interrupt : DAINT = 0x%x\n", __func__, ep_intr); - ep_intr = (ep_intr >> DAINT_OUT_BIT) & DAINT_MASK; + ep_intr = FIELD_GET(DAINT_OUTEP_MASK, ep_intr); while (ep_intr) { - if (ep_intr & 0x1) { - ep_intr_status = readl(®->out_endp[ep_num].doepint); + if (ep_intr & BIT(EP0_CON)) { + ep_intr_status = readl(®->device_regs.out_endp[ep_num].doepint); debug_cond(DEBUG_OUT_EP != 0, "\tEP%d-OUT : DOEPINT = 0x%x\n", ep_num, ep_intr_status); /* Interrupt Clear */ - writel(ep_intr_status, ®->out_endp[ep_num].doepint); + writel(ep_intr_status, ®->device_regs.out_endp[ep_num].doepint); if (ep_num == 0) { - if (ep_intr_status & TRANSFER_DONE) { + if (ep_intr_status & DOEPMSK_XFERCOMPLMSK) { ep_tsr = readl(&epsiz_reg); - xfer_size = ep_tsr & - DOEPT_SIZ_XFER_SIZE_MAX_EP0; + xfer_size = ep_tsr & DOEPTSIZ0_XFERSIZE_MASK; if (xfer_size == req_size && dev->ep0state == WAIT_FOR_SETUP) { @@ -458,14 +440,13 @@ static void process_ep_out_intr(struct dwc2_udc *dev) } } - if (ep_intr_status & - CTRL_OUT_EP_SETUP_PHASE_DONE) { + if (ep_intr_status & DOEPMSK_SETUPMSK) { debug_cond(DEBUG_OUT_EP != 0, "SETUP packet arrived\n"); dwc2_handle_ep0(dev); } } else { - if (ep_intr_status & TRANSFER_DONE) + if (ep_intr_status & DOEPMSK_XFERCOMPLMSK) complete_rx(dev, ep_num); } } @@ -486,27 +467,27 @@ static int dwc2_udc_irq(int irq, void *_dev) spin_lock_irqsave(&dev->lock, flags); - intr_status = readl(®->gintsts); - gintmsk = readl(®->gintmsk); + intr_status = readl(®->global_regs.gintsts); + gintmsk = readl(®->global_regs.gintmsk); debug_cond(DEBUG_ISR, "\n*** %s : GINTSTS=0x%x(on state %s), GINTMSK : 0x%x," "DAINT : 0x%x, DAINTMSK : 0x%x\n", __func__, intr_status, state_names[dev->ep0state], gintmsk, - readl(®->daint), readl(®->daintmsk)); + readl(®->device_regs.daint), readl(®->device_regs.daintmsk)); if (!intr_status) { spin_unlock_irqrestore(&dev->lock, flags); return IRQ_HANDLED; } - if (intr_status & INT_ENUMDONE) { + if (intr_status & GINTSTS_ENUMDONE) { debug_cond(DEBUG_ISR, "\tSpeed Detection interrupt\n"); - writel(INT_ENUMDONE, ®->gintsts); - usb_status = (readl(®->dsts) & 0x6); + writel(GINTSTS_ENUMDONE, ®->global_regs.gintsts); + usb_status = FIELD_GET(DSTS_ENUMSPD_MASK, readl(®->device_regs.dsts)); - if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ)) { + if (usb_status != DSTS_ENUMSPD_HS) { debug_cond(DEBUG_ISR, "\t\tFull Speed Detection\n"); set_max_pktsize(dev, USB_SPEED_FULL); @@ -519,16 +500,16 @@ static int dwc2_udc_irq(int irq, void *_dev) } } - if (intr_status & INT_EARLY_SUSPEND) { + if (intr_status & GINTSTS_ERLYSUSP) { debug_cond(DEBUG_ISR, "\tEarly suspend interrupt\n"); - writel(INT_EARLY_SUSPEND, ®->gintsts); + writel(GINTSTS_ERLYSUSP, ®->global_regs.gintsts); } - if (intr_status & INT_SUSPEND) { - usb_status = readl(®->dsts); + if (intr_status & GINTSTS_USBSUSP) { + usb_status = readl(®->device_regs.dsts); debug_cond(DEBUG_ISR, "\tSuspend interrupt :(DSTS):0x%x\n", usb_status); - writel(INT_SUSPEND, ®->gintsts); + writel(GINTSTS_USBSUSP, ®->global_regs.gintsts); if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver) { @@ -537,8 +518,8 @@ static int dwc2_udc_irq(int irq, void *_dev) } } - if (intr_status & INT_OTG) { - gotgint = readl(®->gotgint); + if (intr_status & GINTSTS_OTGINT) { + gotgint = readl(®->global_regs.gotgint); debug_cond(DEBUG_ISR, "\tOTG interrupt: (GOTGINT):0x%x\n", gotgint); @@ -551,12 +532,12 @@ static int dwc2_udc_irq(int irq, void *_dev) spin_lock_irqsave(&dev->lock, flags); } } - writel(gotgint, ®->gotgint); + writel(gotgint, ®->global_regs.gotgint); } - if (intr_status & INT_RESUME) { + if (intr_status & GINTSTS_WKUPINT) { debug_cond(DEBUG_ISR, "\tResume interrupt\n"); - writel(INT_RESUME, ®->gintsts); + writel(GINTSTS_WKUPINT, ®->global_regs.gintsts); if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver @@ -566,13 +547,13 @@ static int dwc2_udc_irq(int irq, void *_dev) } } - if (intr_status & INT_RESET) { - usb_status = readl(®->gotgctl); + if (intr_status & GINTSTS_USBRST) { + usb_status = readl(®->global_regs.gotgctl); debug_cond(DEBUG_ISR, "\tReset interrupt - (GOTGCTL):0x%x\n", usb_status); - writel(INT_RESET, ®->gintsts); + writel(GINTSTS_USBRST, ®->global_regs.gintsts); - if ((usb_status & 0xc0000) == (0x3 << 18)) { + if (usb_status & (GOTGCTL_ASESVLD | GOTGCTL_BSESVLD)) { if (reset_available) { debug_cond(DEBUG_ISR, "\t\tOTG core got reset (%d)!!\n", @@ -591,10 +572,10 @@ static int dwc2_udc_irq(int irq, void *_dev) } } - if (intr_status & INT_IN_EP) + if (intr_status & GINTSTS_IEPINT) process_ep_in_intr(dev); - if (intr_status & INT_OUT_EP) + if (intr_status & GINTSTS_OEPINT) process_ep_out_intr(dev); spin_unlock_irqrestore(&dev->lock, flags); @@ -676,14 +657,14 @@ static int dwc2_queue(struct usb_ep *_ep, struct usb_request *_req, req = 0; } else if (ep_is_in(ep)) { - gintsts = readl(®->gintsts); + gintsts = readl(®->global_regs.gintsts); debug_cond(DEBUG_IN_EP, "%s: ep_is_in, DWC2_UDC_OTG_GINTSTS=0x%x\n", __func__, gintsts); setdma_tx(ep, req); } else { - gintsts = readl(®->gintsts); + gintsts = readl(®->global_regs.gintsts); debug_cond(DEBUG_OUT_EP != 0, "%s:ep_is_out, DWC2_UDC_OTG_GINTSTS=0x%x\n", __func__, gintsts); @@ -765,14 +746,13 @@ static int dwc2_fifo_read(struct dwc2_ep *ep, void *cp, int max) */ static void udc_set_address(struct dwc2_udc *dev, unsigned char address) { - u32 ctrl = readl(®->dcfg); - writel(DEVICE_ADDRESS(address) | ctrl, ®->dcfg); + setbits_le32(®->device_regs.dcfg, FIELD_PREP(DCFG_DEVADDR_MASK, address)); dwc2_udc_ep0_zlp(dev); debug_cond(DEBUG_EP0 != 0, "%s: USB OTG 2.0 Device address=%d, DCFG=0x%x\n", - __func__, address, readl(®->dcfg)); + __func__, address, readl(®->device_regs.dcfg)); dev->usb_address = address; } @@ -783,19 +763,19 @@ static inline void dwc2_udc_ep0_set_stall(struct dwc2_ep *ep) u32 ep_ctrl = 0; dev = ep->dev; - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); + ep_ctrl = readl(®->device_regs.in_endp[EP0_CON].diepctl); /* set the disable and stall bits */ - if (ep_ctrl & DEPCTL_EPENA) - ep_ctrl |= DEPCTL_EPDIS; + if (ep_ctrl & DXEPCTL_EPENA) + ep_ctrl |= DXEPCTL_EPDIS; - ep_ctrl |= DEPCTL_STALL; + ep_ctrl |= DXEPCTL_STALL; - writel(ep_ctrl, ®->in_endp[EP0_CON].diepctl); + writel(ep_ctrl, ®->device_regs.in_endp[EP0_CON].diepctl); debug_cond(DEBUG_EP0 != 0, "%s: set ep%d stall, DIEPCTL0 = 0x%p\n", - __func__, ep_index(ep), ®->in_endp[EP0_CON].diepctl); + __func__, ep_index(ep), ®->device_regs.in_endp[EP0_CON].diepctl); /* * The application can only set this bit, and the core clears it, * when a SETUP token is received for this endpoint @@ -890,7 +870,6 @@ static int dwc2_udc_get_status(struct dwc2_udc *dev, { u8 ep_num = crq->wIndex & 0x3; u16 g_status = 0; - u32 ep_ctrl; debug_cond(DEBUG_SETUP != 0, "%s: *** USB_REQ_GET_STATUS\n", __func__); @@ -934,13 +913,11 @@ static int dwc2_udc_get_status(struct dwc2_udc *dev, (unsigned long) usb_ctrl + ROUND(sizeof(g_status), CONFIG_SYS_CACHELINE_SIZE)); - writel(phys_to_bus(usb_ctrl_dma_addr), ®->in_endp[EP0_CON].diepdma); - writel(DIEPT_SIZ_PKT_CNT(1) | DIEPT_SIZ_XFER_SIZE(2), - ®->in_endp[EP0_CON].dieptsiz); + writel(phys_to_bus(usb_ctrl_dma_addr), ®->device_regs.in_endp[EP0_CON].diepdma); + writel(FIELD_PREP(DXEPTSIZ_PKTCNT_MASK, 1) | FIELD_PREP(DXEPTSIZ_XFERSIZE_MASK, 2), + ®->device_regs.in_endp[EP0_CON].dieptsiz); - ep_ctrl = readl(®->in_endp[EP0_CON].diepctl); - writel(ep_ctrl|DEPCTL_EPENA|DEPCTL_CNAK, - ®->in_endp[EP0_CON].diepctl); + setbits_le32(®->device_regs.in_endp[EP0_CON].diepctl, DXEPCTL_EPENA | DXEPCTL_CNAK); dev->ep0state = WAIT_FOR_NULL_COMPLETE; return 0; @@ -949,23 +926,18 @@ static int dwc2_udc_get_status(struct dwc2_udc *dev, static void dwc2_udc_set_nak(struct dwc2_ep *ep) { u8 ep_num; - u32 ep_ctrl = 0; ep_num = ep_index(ep); debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type); if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); - ep_ctrl |= DEPCTL_SNAK; - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); + setbits_le32(®->device_regs.in_endp[ep_num].diepctl, DXEPCTL_SNAK); debug("%s: set NAK, DIEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->in_endp[ep_num].diepctl)); + __func__, ep_num, readl(®->device_regs.in_endp[ep_num].diepctl)); } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); - ep_ctrl |= DEPCTL_SNAK; - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); + setbits_le32(®->device_regs.out_endp[ep_num].doepctl, DXEPCTL_SNAK); debug("%s: set NAK, DOEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->out_endp[ep_num].doepctl)); + __func__, ep_num, readl(®->device_regs.out_endp[ep_num].doepctl)); } return; @@ -980,27 +952,23 @@ static void dwc2_udc_ep_set_stall(struct dwc2_ep *ep) debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type); if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); + ep_ctrl = readl(®->device_regs.in_endp[ep_num].diepctl); /* set the disable and stall bits */ - if (ep_ctrl & DEPCTL_EPENA) - ep_ctrl |= DEPCTL_EPDIS; + if (ep_ctrl & DXEPCTL_EPENA) + ep_ctrl |= DXEPCTL_EPDIS; - ep_ctrl |= DEPCTL_STALL; + ep_ctrl |= DXEPCTL_STALL; - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); + writel(ep_ctrl, ®->device_regs.in_endp[ep_num].diepctl); debug("%s: set stall, DIEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->in_endp[ep_num].diepctl)); + __func__, ep_num, readl(®->device_regs.in_endp[ep_num].diepctl)); } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); - /* set the stall bit */ - ep_ctrl |= DEPCTL_STALL; - - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); + setbits_le32(®->device_regs.out_endp[ep_num].doepctl, DXEPCTL_STALL); debug("%s: set stall, DOEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->out_endp[ep_num].doepctl)); + __func__, ep_num, readl(®->device_regs.out_endp[ep_num].doepctl)); } return; @@ -1015,10 +983,10 @@ static void dwc2_udc_ep_clear_stall(struct dwc2_ep *ep) debug("%s: ep_num = %d, ep_type = %d\n", __func__, ep_num, ep->ep_type); if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); + ep_ctrl = readl(®->device_regs.in_endp[ep_num].diepctl); /* clear stall bit */ - ep_ctrl &= ~DEPCTL_STALL; + ep_ctrl &= ~DXEPCTL_STALL; /* * USB Spec 9.4.5: For endpoints using data toggle, regardless @@ -1028,27 +996,27 @@ static void dwc2_udc_ep_clear_stall(struct dwc2_ep *ep) */ if (ep->bmAttributes == USB_ENDPOINT_XFER_INT || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) { - ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */ + ep_ctrl |= DXEPCTL_SETD0PID; /* DATA0 */ } - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); + writel(ep_ctrl, ®->device_regs.in_endp[ep_num].diepctl); debug("%s: cleared stall, DIEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->in_endp[ep_num].diepctl)); + __func__, ep_num, readl(®->device_regs.in_endp[ep_num].diepctl)); } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); + ep_ctrl = readl(®->device_regs.out_endp[ep_num].doepctl); /* clear stall bit */ - ep_ctrl &= ~DEPCTL_STALL; + ep_ctrl &= ~DXEPCTL_STALL; if (ep->bmAttributes == USB_ENDPOINT_XFER_INT || ep->bmAttributes == USB_ENDPOINT_XFER_BULK) { - ep_ctrl |= DEPCTL_SETD0PID; /* DATA0 */ + ep_ctrl |= DXEPCTL_SETD0PID; /* DATA0 */ } - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); + writel(ep_ctrl, ®->device_regs.out_endp[ep_num].doepctl); debug("%s: cleared stall, DOEPCTL%d = 0x%x\n", - __func__, ep_num, readl(®->out_endp[ep_num].doepctl)); + __func__, ep_num, readl(®->device_regs.out_endp[ep_num].doepctl)); } return; @@ -1110,11 +1078,11 @@ static void dwc2_udc_ep_activate(struct dwc2_ep *ep) /* Read DEPCTLn register */ if (ep_is_in(ep)) { - ep_ctrl = readl(®->in_endp[ep_num].diepctl); - daintmsk = 1 << ep_num; + ep_ctrl = readl(®->device_regs.in_endp[ep_num].diepctl); + daintmsk = FIELD_PREP(DAINT_INEP_MASK, BIT(ep_num)); } else { - ep_ctrl = readl(®->out_endp[ep_num].doepctl); - daintmsk = (1 << ep_num) << DAINT_OUT_BIT; + ep_ctrl = readl(®->device_regs.out_endp[ep_num].doepctl); + daintmsk = FIELD_PREP(DAINT_OUTEP_MASK, BIT(ep_num)); } debug("%s: EPCTRL%d = 0x%x, ep_is_in = %d\n", @@ -1122,30 +1090,29 @@ static void dwc2_udc_ep_activate(struct dwc2_ep *ep) /* If the EP is already active don't change the EP Control * register. */ - if (!(ep_ctrl & DEPCTL_USBACTEP)) { - ep_ctrl = (ep_ctrl & ~DEPCTL_TYPE_MASK) | - (ep->bmAttributes << DEPCTL_TYPE_BIT); - ep_ctrl = (ep_ctrl & ~DEPCTL_MPS_MASK) | - (ep->ep.maxpacket << DEPCTL_MPS_BIT); - ep_ctrl |= (DEPCTL_SETD0PID | DEPCTL_USBACTEP | DEPCTL_SNAK); + if (!(ep_ctrl & DXEPCTL_USBACTEP)) { + ep_ctrl = (ep_ctrl & ~DXEPCTL_EPTYPE_MASK) | + FIELD_PREP(DXEPCTL_EPTYPE_MASK, ep->bmAttributes); + ep_ctrl = (ep_ctrl & ~DXEPCTL_MPS_MASK) | + FIELD_PREP(DXEPCTL_MPS_MASK, ep->ep.maxpacket); + ep_ctrl |= (DXEPCTL_SETD0PID | DXEPCTL_USBACTEP | DXEPCTL_SNAK); if (ep_is_in(ep)) { - writel(ep_ctrl, ®->in_endp[ep_num].diepctl); + writel(ep_ctrl, ®->device_regs.in_endp[ep_num].diepctl); debug("%s: USB Ative EP%d, DIEPCTRL%d = 0x%x\n", __func__, ep_num, ep_num, - readl(®->in_endp[ep_num].diepctl)); + readl(®->device_regs.in_endp[ep_num].diepctl)); } else { - writel(ep_ctrl, ®->out_endp[ep_num].doepctl); + writel(ep_ctrl, ®->device_regs.out_endp[ep_num].doepctl); debug("%s: USB Ative EP%d, DOEPCTRL%d = 0x%x\n", __func__, ep_num, ep_num, - readl(®->out_endp[ep_num].doepctl)); + readl(®->device_regs.out_endp[ep_num].doepctl)); } } /* Unmask EP Interrtupt */ - writel(readl(®->daintmsk)|daintmsk, ®->daintmsk); - debug("%s: DAINTMSK = 0x%x\n", __func__, readl(®->daintmsk)); - + setbits_le32(®->device_regs.daintmsk, daintmsk); + debug("%s: DAINTMSK = 0x%x\n", __func__, readl(®->device_regs.daintmsk)); } static int dwc2_udc_clear_feature(struct usb_ep *_ep) diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 36934b1bcf7..647001d8dd0 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -863,7 +863,7 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, struct spl_boot_device bootdev = {}; spl_parse_image_header(&spl_image, &bootdev, header); spl_board_prepare_for_boot(); - jump_to_image_no_args(&spl_image); + jump_to_image(&spl_image); #else /* In U-Boot, allow jumps to scripts */ cmd_source_script(sdp_func->jmp_address, NULL, NULL); diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index a9dbb85f4e6..16f21fa9083 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -19,11 +19,13 @@ #include <asm/cache.h> #include <asm/io.h> #include <dm/device_compat.h> +#include <linux/bitfield.h> #include <linux/delay.h> #include <linux/usb/otg.h> #include <power/regulator.h> #include <reset.h> +#include "../common/dwc2_core.h" #include "dwc2.h" /* Use only HC channel 0. */ @@ -37,16 +39,16 @@ struct dwc2_priv { #if CONFIG_IS_ENABLED(DM_USB) - uint8_t aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); - uint8_t status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); + u8 aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); + u8 status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); #ifdef CONFIG_DM_REGULATOR struct udevice *vbus_supply; #endif struct phy phy; struct clk_bulk clks; #else - uint8_t *aligned_buffer; - uint8_t *status_buffer; + u8 *aligned_buffer; + u8 *status_buffer; #endif u8 in_data_toggle[MAX_DEVICE][MAX_ENDPOINT]; u8 out_data_toggle[MAX_DEVICE][MAX_ENDPOINT]; @@ -65,10 +67,10 @@ struct dwc2_priv { #if !CONFIG_IS_ENABLED(DM_USB) /* We need cacheline-aligned buffers for DMA transfers and dcache support */ -DEFINE_ALIGN_BUFFER(uint8_t, aligned_buffer_addr, DWC2_DATA_BUF_SIZE, - ARCH_DMA_MINALIGN); -DEFINE_ALIGN_BUFFER(uint8_t, status_buffer_addr, DWC2_STATUS_BUF_SIZE, - ARCH_DMA_MINALIGN); +DEFINE_ALIGN_BUFFER(u8, aligned_buffer_addr, DWC2_DATA_BUF_SIZE, + ARCH_DMA_MINALIGN); +DEFINE_ALIGN_BUFFER(u8, status_buffer_addr, DWC2_STATUS_BUF_SIZE, + ARCH_DMA_MINALIGN); static struct dwc2_priv local; #endif @@ -83,101 +85,27 @@ static struct dwc2_priv local; */ static void init_fslspclksel(struct dwc2_core_regs *regs) { - uint32_t phyclk; + u32 phyclk; #if (DWC2_PHY_TYPE == DWC2_PHY_TYPE_FS) - phyclk = DWC2_HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */ + phyclk = HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */ #else /* High speed PHY running at full speed or high speed */ - phyclk = DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ; + phyclk = HCFG_FSLSPCLKSEL_30_60_MHZ; #endif #ifdef DWC2_ULPI_FS_LS - uint32_t hwcfg2 = readl(®s->ghwcfg2); - uint32_t hval = (ghwcfg2 & DWC2_HWCFG2_HS_PHY_TYPE_MASK) >> - DWC2_HWCFG2_HS_PHY_TYPE_OFFSET; - uint32_t fval = (ghwcfg2 & DWC2_HWCFG2_FS_PHY_TYPE_MASK) >> - DWC2_HWCFG2_FS_PHY_TYPE_OFFSET; - - if (hval == 2 && fval == 1) - phyclk = DWC2_HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */ + u32 hwcfg2 = readl(®s->global_regs.ghwcfg2); + u32 hval = FIELD_GET(GHWCFG2_HS_PHY_TYPE_MASK, ghwcfg2); + u32 fval = FIELD_GET(GHWCFG2_FS_PHY_TYPE_MASK, ghwcfg2); + + if (hval == GHWCFG2_FS_PHY_TYPE_SHARED_UTMI && fval == GHWCFG2_HS_PHY_TYPE_UTMI) + phyclk = HCFG_FSLSPCLKSEL_48_MHZ; /* Full speed PHY */ #endif clrsetbits_le32(®s->host_regs.hcfg, - DWC2_HCFG_FSLSPCLKSEL_MASK, - phyclk << DWC2_HCFG_FSLSPCLKSEL_OFFSET); -} - -/* - * Flush a Tx FIFO. - * - * @param regs Programming view of DWC_otg controller. - * @param num Tx FIFO to flush. - */ -static void dwc_otg_flush_tx_fifo(struct udevice *dev, - struct dwc2_core_regs *regs, const int num) -{ - int ret; - - writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET), - ®s->grstctl); - ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_TXFFLSH, - false, 1000, false); - if (ret) - dev_info(dev, "%s: Timeout!\n", __func__); - - /* Wait for 3 PHY Clocks */ - udelay(1); -} - -/* - * Flush Rx FIFO. - * - * @param regs Programming view of DWC_otg controller. - */ -static void dwc_otg_flush_rx_fifo(struct udevice *dev, - struct dwc2_core_regs *regs) -{ - int ret; - - writel(DWC2_GRSTCTL_RXFFLSH, ®s->grstctl); - ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_RXFFLSH, - false, 1000, false); - if (ret) - dev_info(dev, "%s: Timeout!\n", __func__); - - /* Wait for 3 PHY Clocks */ - udelay(1); -} - -/* - * Do core a soft reset of the core. Be careful with this because it - * resets all the internal state machines of the core. - */ -static void dwc_otg_core_reset(struct udevice *dev, - struct dwc2_core_regs *regs) -{ - int ret; - - /* Wait for AHB master IDLE state. */ - ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_AHBIDLE, - true, 1000, false); - if (ret) - dev_info(dev, "%s: Timeout!\n", __func__); - - /* Core Soft Reset */ - writel(DWC2_GRSTCTL_CSFTRST, ®s->grstctl); - ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_CSFTRST, - false, 1000, false); - if (ret) - dev_info(dev, "%s: Timeout!\n", __func__); - - /* - * Wait for core to come out of reset. - * NOTE: This long sleep is _very_ important, otherwise the core will - * not stay in host mode after a connector ID change! - */ - mdelay(100); + HCFG_FSLSPCLKSEL_MASK, + FIELD_PREP(HCFG_FSLSPCLKSEL_MASK, phyclk)); } #if CONFIG_IS_ENABLED(DM_USB) && defined(CONFIG_DM_REGULATOR) @@ -244,9 +172,9 @@ static int dwc_vbus_supply_exit(struct udevice *dev) static void dwc_otg_core_host_init(struct udevice *dev, struct dwc2_core_regs *regs) { - uint32_t nptxfifosize = 0; - uint32_t ptxfifosize = 0; - uint32_t hprt0 = 0; + u32 nptxfifosize = 0; + u32 ptxfifosize = 0; + u32 hprt0 = 0; int i, ret, num_channels; /* Restart the Phy Clock */ @@ -255,67 +183,59 @@ static void dwc_otg_core_host_init(struct udevice *dev, /* Initialize Host Configuration Register */ init_fslspclksel(regs); #ifdef DWC2_DFLT_SPEED_FULL - setbits_le32(®s->host_regs.hcfg, DWC2_HCFG_FSLSSUPP); + setbits_le32(®s->host_regs.hcfg, HCFG_FSLSSUPP); #endif /* Configure data FIFO sizes */ #ifdef DWC2_ENABLE_DYNAMIC_FIFO - if (readl(®s->ghwcfg2) & DWC2_HWCFG2_DYNAMIC_FIFO) { + if (readl(®s->global_regs.ghwcfg2) & GHWCFG2_DYNAMIC_FIFO) { /* Rx FIFO */ - writel(DWC2_HOST_RX_FIFO_SIZE, ®s->grxfsiz); + writel(DWC2_HOST_RX_FIFO_SIZE, ®s->global_regs.grxfsiz); /* Non-periodic Tx FIFO */ - nptxfifosize |= DWC2_HOST_NPERIO_TX_FIFO_SIZE << - DWC2_FIFOSIZE_DEPTH_OFFSET; - nptxfifosize |= DWC2_HOST_RX_FIFO_SIZE << - DWC2_FIFOSIZE_STARTADDR_OFFSET; - writel(nptxfifosize, ®s->gnptxfsiz); + nptxfifosize |= FIELD_PREP(FIFOSIZE_DEPTH_MASK, DWC2_HOST_NPERIO_TX_FIFO_SIZE); + nptxfifosize |= FIELD_PREP(FIFOSIZE_STARTADDR_MASK, DWC2_HOST_RX_FIFO_SIZE); + writel(nptxfifosize, ®s->global_regs.gnptxfsiz); /* Periodic Tx FIFO */ - ptxfifosize |= DWC2_HOST_PERIO_TX_FIFO_SIZE << - DWC2_FIFOSIZE_DEPTH_OFFSET; - ptxfifosize |= (DWC2_HOST_RX_FIFO_SIZE + - DWC2_HOST_NPERIO_TX_FIFO_SIZE) << - DWC2_FIFOSIZE_STARTADDR_OFFSET; - writel(ptxfifosize, ®s->hptxfsiz); + ptxfifosize |= FIELD_PREP(FIFOSIZE_DEPTH_MASK, DWC2_HOST_PERIO_TX_FIFO_SIZE); + ptxfifosize |= FIELD_PREP(FIFOSIZE_STARTADDR_MASK, DWC2_HOST_RX_FIFO_SIZE + + DWC2_HOST_NPERIO_TX_FIFO_SIZE); + writel(ptxfifosize, ®s->global_regs.hptxfsiz); } #endif /* Clear Host Set HNP Enable in the OTG Control Register */ - clrbits_le32(®s->gotgctl, DWC2_GOTGCTL_HSTSETHNPEN); + clrbits_le32(®s->global_regs.gotgctl, GOTGCTL_HSTSETHNPEN); /* Make sure the FIFOs are flushed. */ - dwc_otg_flush_tx_fifo(dev, regs, 0x10); /* All Tx FIFOs */ - dwc_otg_flush_rx_fifo(dev, regs); + dwc2_flush_tx_fifo(regs, GRSTCTL_TXFNUM_ALL); /* All Tx FIFOs */ + dwc2_flush_rx_fifo(regs); /* Flush out any leftover queued requests. */ - num_channels = readl(®s->ghwcfg2); - num_channels &= DWC2_HWCFG2_NUM_HOST_CHAN_MASK; - num_channels >>= DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET; - num_channels += 1; + num_channels = FIELD_GET(GHWCFG2_NUM_HOST_CHAN_MASK, readl(®s->global_regs.ghwcfg2)) + 1; for (i = 0; i < num_channels; i++) - clrsetbits_le32(®s->hc_regs[i].hcchar, - DWC2_HCCHAR_CHEN | DWC2_HCCHAR_EPDIR, - DWC2_HCCHAR_CHDIS); + clrsetbits_le32(®s->host_regs.hc[i].hcchar, HCCHAR_CHENA | HCCHAR_EPDIR, + HCCHAR_CHDIS); /* Halt all channels to put them into a known state. */ for (i = 0; i < num_channels; i++) { - clrsetbits_le32(®s->hc_regs[i].hcchar, - DWC2_HCCHAR_EPDIR, - DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS); - ret = wait_for_bit_le32(®s->hc_regs[i].hcchar, - DWC2_HCCHAR_CHEN, false, 1000, false); + clrsetbits_le32(®s->host_regs.hc[i].hcchar, + HCCHAR_EPDIR, + HCCHAR_CHENA | HCCHAR_CHDIS); + ret = wait_for_bit_le32(®s->host_regs.hc[i].hcchar, + HCCHAR_CHENA, false, 1000, false); if (ret) dev_info(dev, "%s: Timeout!\n", __func__); } /* Turn on the vbus power. */ - if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST) { - hprt0 = readl(®s->hprt0) & ~DWC2_HPRT0_W1C_MASK; - if (!(hprt0 & DWC2_HPRT0_PRTPWR)) { - hprt0 |= DWC2_HPRT0_PRTPWR; - writel(hprt0, ®s->hprt0); + if (readl(®s->global_regs.gintsts) & GINTSTS_CURMODE_HOST) { + hprt0 = readl(®s->host_regs.hprt0) & ~HPRT0_W1C_MASK; + if (!(hprt0 & HPRT0_PWR)) { + hprt0 |= HPRT0_PWR; + writel(hprt0, ®s->host_regs.hprt0); } } @@ -333,34 +253,34 @@ static void dwc_otg_core_init(struct udevice *dev) { struct dwc2_priv *priv = dev_get_priv(dev); struct dwc2_core_regs *regs = priv->regs; - uint32_t ahbcfg = 0; - uint32_t usbcfg = 0; - uint8_t brst_sz = DWC2_DMA_BURST_SIZE; + u32 ahbcfg = 0; + u32 usbcfg = 0; + u8 brst_sz = DWC2_DMA_BURST_SIZE; /* Common Initialization */ - usbcfg = readl(®s->gusbcfg); + usbcfg = readl(®s->global_regs.gusbcfg); /* Program the ULPI External VBUS bit if needed */ if (priv->ext_vbus) { - usbcfg |= DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV; + usbcfg |= GUSBCFG_ULPI_EXT_VBUS_DRV; if (!priv->oc_disable) { - usbcfg |= DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR | - DWC2_GUSBCFG_INDICATOR_PASSTHROUGH; + usbcfg |= GUSBCFG_ULPI_INT_VBUS_IND | + GUSBCFG_INDICATORPASSTHROUGH; } } else { - usbcfg &= ~DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV; + usbcfg &= ~GUSBCFG_ULPI_EXT_VBUS_DRV; } /* Set external TS Dline pulsing */ #ifdef DWC2_TS_DLINE - usbcfg |= DWC2_GUSBCFG_TERM_SEL_DL_PULSE; + usbcfg |= GUSBCFG_TERMSELDLPULSE; #else - usbcfg &= ~DWC2_GUSBCFG_TERM_SEL_DL_PULSE; + usbcfg &= ~GUSBCFG_TERMSELDLPULSE; #endif - writel(usbcfg, ®s->gusbcfg); + writel(usbcfg, ®s->global_regs.gusbcfg); /* Reset the Controller */ - dwc_otg_core_reset(dev, regs); + dwc2_core_reset(regs); /* * This programming sequence needs to happen in FS mode before @@ -369,28 +289,28 @@ static void dwc_otg_core_init(struct udevice *dev) #if defined(DWC2_DFLT_SPEED_FULL) && \ (DWC2_PHY_TYPE == DWC2_PHY_TYPE_FS) /* If FS mode with FS PHY */ - setbits_le32(®s->gusbcfg, DWC2_GUSBCFG_PHYSEL); + setbits_le32(®s->global_regs.gusbcfg, GUSBCFG_PHYSEL); /* Reset after a PHY select */ - dwc_otg_core_reset(dev, regs); + dwc2_core_reset(regs); /* * Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. * Also do this on HNP Dev/Host mode switches (done in dev_init * and host_init). */ - if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST) + if (readl(®s->global_regs.gintsts) & GINTSTS_CURMODE_HOST) init_fslspclksel(regs); #ifdef DWC2_I2C_ENABLE /* Program GUSBCFG.OtgUtmifsSel to I2C */ - setbits_le32(®s->gusbcfg, DWC2_GUSBCFG_OTGUTMIFSSEL); + setbits_le32(®s->global_regs.gusbcfg, GUSBCFG_OTG_UTMI_FS_SEL); /* Program GI2CCTL.I2CEn */ - clrsetbits_le32(®s->gi2cctl, DWC2_GI2CCTL_I2CEN | - DWC2_GI2CCTL_I2CDEVADDR_MASK, - 1 << DWC2_GI2CCTL_I2CDEVADDR_OFFSET); - setbits_le32(®s->gi2cctl, DWC2_GI2CCTL_I2CEN); + clrsetbits_le32(®s->global_regs.gi2cctl, GI2CCTL_I2CEN | + GI2CCTL_I2CDEVADDR_MASK, + FIELD_PREP(GI2CCTL_I2CDEVADDR_MASK, 1)); + setbits_le32(®s->global_regs.gi2cctl, GI2CCTL_I2CEN); #endif #else @@ -401,81 +321,76 @@ static void dwc_otg_core_init(struct udevice *dev) * soft reset so only program the first time. Do a soft reset * immediately after setting phyif. */ - usbcfg &= ~(DWC2_GUSBCFG_ULPI_UTMI_SEL | DWC2_GUSBCFG_PHYIF); - usbcfg |= DWC2_PHY_TYPE << DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET; - - if (usbcfg & DWC2_GUSBCFG_ULPI_UTMI_SEL) { /* ULPI interface */ +#if (DWC2_PHY_TYPE == DWC2_PHY_TYPE_ULPI) + usbcfg |= GUSBCFG_ULPI_UTMI_SEL; + usbcfg &= ~GUSBCFG_PHYIF16; #ifdef DWC2_PHY_ULPI_DDR - usbcfg |= DWC2_GUSBCFG_DDRSEL; + usbcfg |= GUSBCFG_DDRSEL; #else - usbcfg &= ~DWC2_GUSBCFG_DDRSEL; -#endif - } else { /* UTMI+ interface */ + usbcfg &= ~GUSBCFG_DDRSEL; +#endif /* DWC2_PHY_ULPI_DDR */ +#elif (DWC2_PHY_TYPE == DWC2_PHY_TYPE_UTMI) + usbcfg &= ~GUSBCFG_ULPI_UTMI_SEL; #if (DWC2_UTMI_WIDTH == 16) - usbcfg |= DWC2_GUSBCFG_PHYIF; -#endif - } + usbcfg |= GUSBCFG_PHYIF16; +#else + usbcfg &= ~GUSBCFG_PHYIF16; +#endif /* DWC2_UTMI_WIDTH */ +#endif /* DWC2_PHY_TYPE */ - writel(usbcfg, ®s->gusbcfg); + writel(usbcfg, ®s->global_regs.gusbcfg); /* Reset after setting the PHY parameters */ - dwc_otg_core_reset(dev, regs); + dwc2_core_reset(regs); #endif - usbcfg = readl(®s->gusbcfg); - usbcfg &= ~(DWC2_GUSBCFG_ULPI_FSLS | DWC2_GUSBCFG_ULPI_CLK_SUS_M); + usbcfg = readl(®s->global_regs.gusbcfg); + usbcfg &= ~(GUSBCFG_ULPI_FS_LS | GUSBCFG_ULPI_CLK_SUSP_M); #ifdef DWC2_ULPI_FS_LS - uint32_t hwcfg2 = readl(®s->ghwcfg2); - uint32_t hval = (ghwcfg2 & DWC2_HWCFG2_HS_PHY_TYPE_MASK) >> - DWC2_HWCFG2_HS_PHY_TYPE_OFFSET; - uint32_t fval = (ghwcfg2 & DWC2_HWCFG2_FS_PHY_TYPE_MASK) >> - DWC2_HWCFG2_FS_PHY_TYPE_OFFSET; - if (hval == 2 && fval == 1) { - usbcfg |= DWC2_GUSBCFG_ULPI_FSLS; - usbcfg |= DWC2_GUSBCFG_ULPI_CLK_SUS_M; + u32 hwcfg2 = readl(®s->global_regs.ghwcfg2); + u32 hval = FIELD_GET(GHWCFG2_HS_PHY_TYPE_MASK, ghwcfg2); + u32 fval = FIELD_GET(GHWCFG2_FS_PHY_TYPE_MASK, ghwcfg2); + + if (hval == GHWCFG2_FS_PHY_TYPE_SHARED_UTMI && fval == GHWCFG2_HS_PHY_TYPE_UTMI) { + usbcfg |= GUSBCFG_ULPI_FS_LS; + usbcfg |= GUSBCFG_ULPI_CLK_SUSP_M; } #endif if (priv->hnp_srp_disable) - usbcfg |= DWC2_GUSBCFG_FORCEHOSTMODE; + usbcfg |= GUSBCFG_FORCEHOSTMODE; - writel(usbcfg, ®s->gusbcfg); + writel(usbcfg, ®s->global_regs.gusbcfg); /* Program the GAHBCFG Register. */ - switch (readl(®s->ghwcfg2) & DWC2_HWCFG2_ARCHITECTURE_MASK) { - case DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY: + switch (FIELD_GET(GHWCFG2_ARCHITECTURE_MASK, readl(®s->global_regs.ghwcfg2))) { + case GHWCFG2_SLAVE_ONLY_ARCH: break; - case DWC2_HWCFG2_ARCHITECTURE_EXT_DMA: - while (brst_sz > 1) { - ahbcfg |= ahbcfg + (1 << DWC2_GAHBCFG_HBURSTLEN_OFFSET); - ahbcfg &= DWC2_GAHBCFG_HBURSTLEN_MASK; - brst_sz >>= 1; - } - + case GHWCFG2_EXT_DMA_ARCH: + ahbcfg |= FIELD_PREP(GAHBCFG_HBSTLEN_MASK, LOG2(brst_sz >> 1)); #ifdef DWC2_DMA_ENABLE - ahbcfg |= DWC2_GAHBCFG_DMAENABLE; + ahbcfg |= GAHBCFG_DMA_EN; #endif break; - - case DWC2_HWCFG2_ARCHITECTURE_INT_DMA: - ahbcfg |= DWC2_GAHBCFG_HBURSTLEN_INCR4; + case GHWCFG2_INT_DMA_ARCH: + ahbcfg |= FIELD_PREP(GAHBCFG_HBSTLEN_MASK, GAHBCFG_HBSTLEN_INCR4); #ifdef DWC2_DMA_ENABLE - ahbcfg |= DWC2_GAHBCFG_DMAENABLE; + ahbcfg |= GAHBCFG_DMA_EN; #endif break; } - writel(ahbcfg, ®s->gahbcfg); + writel(ahbcfg, ®s->global_regs.gahbcfg); /* Program the capabilities in GUSBCFG Register */ usbcfg = 0; if (!priv->hnp_srp_disable) - usbcfg |= DWC2_GUSBCFG_HNPCAP | DWC2_GUSBCFG_SRPCAP; + usbcfg |= GUSBCFG_HNPCAP | GUSBCFG_SRPCAP; #ifdef DWC2_IC_USB_CAP - usbcfg |= DWC2_GUSBCFG_IC_USB_CAP; + usbcfg |= GUSBCFG_ICUSBCAP; #endif - setbits_le32(®s->gusbcfg, usbcfg); + setbits_le32(®s->global_regs.gusbcfg, usbcfg); } /* @@ -487,19 +402,19 @@ static void dwc_otg_core_init(struct udevice *dev) * @param regs Programming view of DWC_otg controller * @param hc Information needed to initialize the host channel */ -static void dwc_otg_hc_init(struct dwc2_core_regs *regs, uint8_t hc_num, - struct usb_device *dev, uint8_t dev_addr, uint8_t ep_num, - uint8_t ep_is_in, uint8_t ep_type, uint16_t max_packet) +static void dwc_otg_hc_init(struct dwc2_core_regs *regs, u8 hc_num, + struct usb_device *dev, u8 dev_addr, u8 ep_num, + u8 ep_is_in, u8 ep_type, u16 max_packet) { - struct dwc2_hc_regs *hc_regs = ®s->hc_regs[hc_num]; - uint32_t hcchar = (dev_addr << DWC2_HCCHAR_DEVADDR_OFFSET) | - (ep_num << DWC2_HCCHAR_EPNUM_OFFSET) | - (ep_is_in << DWC2_HCCHAR_EPDIR_OFFSET) | - (ep_type << DWC2_HCCHAR_EPTYPE_OFFSET) | - (max_packet << DWC2_HCCHAR_MPS_OFFSET); + struct dwc2_hc_regs *hc_regs = ®s->host_regs.hc[hc_num]; + u32 hcchar = FIELD_PREP(HCCHAR_DEVADDR_MASK, dev_addr) | + FIELD_PREP(HCCHAR_EPNUM_MASK, ep_num) | + FIELD_PREP(HCCHAR_EPDIR, ep_is_in) | + FIELD_PREP(HCCHAR_EPTYPE_MASK, ep_type) | + FIELD_PREP(HCCHAR_MPS_MASK, max_packet); if (dev->speed == USB_SPEED_LOW) - hcchar |= DWC2_HCCHAR_LSPDDEV; + hcchar |= HCCHAR_LSPDDEV; /* * Program the HCCHARn register with the endpoint characteristics @@ -512,13 +427,13 @@ static void dwc_otg_hc_init(struct dwc2_core_regs *regs, uint8_t hc_num, } static void dwc_otg_hc_init_split(struct dwc2_hc_regs *hc_regs, - uint8_t hub_devnum, uint8_t hub_port) + u8 hub_devnum, u8 hub_port) { - uint32_t hcsplt = 0; + u32 hcsplt = 0; - hcsplt = DWC2_HCSPLT_SPLTENA; - hcsplt |= hub_devnum << DWC2_HCSPLT_HUBADDR_OFFSET; - hcsplt |= hub_port << DWC2_HCSPLT_PRTADDR_OFFSET; + hcsplt = HCSPLT_SPLTENA; + hcsplt |= FIELD_PREP(HCSPLT_HUBADDR_MASK, hub_devnum); + hcsplt |= FIELD_PREP(HCSPLT_PRTADDR_MASK, hub_port); /* Program the HCSPLIT register for SPLITs */ writel(hcsplt, &hc_regs->hcsplt); @@ -532,55 +447,58 @@ static int dwc_otg_submit_rh_msg_in_status(struct dwc2_core_regs *regs, struct usb_device *dev, void *buffer, int txlen, struct devrequest *cmd) { - uint32_t hprt0 = 0; - uint32_t port_status = 0; - uint32_t port_change = 0; + u32 hprt0 = 0; + u32 port_status = 0; + u32 port_change = 0; int len = 0; int stat = 0; switch (cmd->requesttype & ~USB_DIR_IN) { case 0: - *(uint16_t *)buffer = cpu_to_le16(1); + *(u16 *)buffer = cpu_to_le16(1); len = 2; break; case USB_RECIP_INTERFACE: case USB_RECIP_ENDPOINT: - *(uint16_t *)buffer = cpu_to_le16(0); + *(u16 *)buffer = cpu_to_le16(0); len = 2; break; case USB_TYPE_CLASS: - *(uint32_t *)buffer = cpu_to_le32(0); + *(u32 *)buffer = cpu_to_le32(0); len = 4; break; case USB_RECIP_OTHER | USB_TYPE_CLASS: - hprt0 = readl(®s->hprt0); - if (hprt0 & DWC2_HPRT0_PRTCONNSTS) + hprt0 = readl(®s->host_regs.hprt0); + if (hprt0 & HPRT0_CONNSTS) port_status |= USB_PORT_STAT_CONNECTION; - if (hprt0 & DWC2_HPRT0_PRTENA) + if (hprt0 & HPRT0_ENA) port_status |= USB_PORT_STAT_ENABLE; - if (hprt0 & DWC2_HPRT0_PRTSUSP) + if (hprt0 & HPRT0_SUSP) port_status |= USB_PORT_STAT_SUSPEND; - if (hprt0 & DWC2_HPRT0_PRTOVRCURRACT) + if (hprt0 & HPRT0_OVRCURRACT) port_status |= USB_PORT_STAT_OVERCURRENT; - if (hprt0 & DWC2_HPRT0_PRTRST) + if (hprt0 & HPRT0_RST) port_status |= USB_PORT_STAT_RESET; - if (hprt0 & DWC2_HPRT0_PRTPWR) + if (hprt0 & HPRT0_PWR) port_status |= USB_PORT_STAT_POWER; - if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == DWC2_HPRT0_PRTSPD_LOW) + switch (FIELD_GET(HPRT0_SPD_MASK, hprt0)) { + case HPRT0_SPD_LOW_SPEED: port_status |= USB_PORT_STAT_LOW_SPEED; - else if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == - DWC2_HPRT0_PRTSPD_HIGH) + break; + case HPRT0_SPD_HIGH_SPEED: port_status |= USB_PORT_STAT_HIGH_SPEED; + break; + } - if (hprt0 & DWC2_HPRT0_PRTENCHNG) + if (hprt0 & HPRT0_ENACHG) port_change |= USB_PORT_STAT_C_ENABLE; - if (hprt0 & DWC2_HPRT0_PRTCONNDET) + if (hprt0 & HPRT0_CONNDET) port_change |= USB_PORT_STAT_C_CONNECTION; - if (hprt0 & DWC2_HPRT0_PRTOVRCURRCHNG) + if (hprt0 & HPRT0_OVRCURRCHG) port_change |= USB_PORT_STAT_C_OVERCURRENT; - *(uint32_t *)buffer = cpu_to_le32(port_status | + *(u32 *)buffer = cpu_to_le32(port_status | (port_change << 16)); len = 4; break; @@ -601,11 +519,11 @@ static int dwc_otg_submit_rh_msg_in_descriptor(struct usb_device *dev, struct devrequest *cmd) { unsigned char data[32]; - uint32_t dsc; + u32 dsc; int len = 0; int stat = 0; - uint16_t wValue = cpu_to_le16(cmd->value); - uint16_t wLength = cpu_to_le16(cmd->length); + u16 wValue = cpu_to_le16(cmd->value); + u16 wLength = cpu_to_le16(cmd->length); switch (cmd->requesttype & ~USB_DIR_IN) { case 0: @@ -688,7 +606,7 @@ static int dwc_otg_submit_rh_msg_in_configuration(struct usb_device *dev, switch (cmd->requesttype & ~USB_DIR_IN) { case 0: - *(uint8_t *)buffer = 0x01; + *(u8 *)buffer = 0x01; len = 1; break; default: @@ -732,8 +650,8 @@ static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv, struct dwc2_core_regs *regs = priv->regs; int len = 0; int stat = 0; - uint16_t bmrtype_breq = cmd->requesttype | (cmd->request << 8); - uint16_t wValue = cpu_to_le16(cmd->value); + u16 bmrtype_breq = cmd->requesttype | (cmd->request << 8); + u16 wValue = cpu_to_le16(cmd->value); switch (bmrtype_breq & ~USB_DIR_IN) { case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_ENDPOINT: @@ -743,7 +661,7 @@ static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv, case (USB_REQ_CLEAR_FEATURE << 8) | USB_RECIP_OTHER | USB_TYPE_CLASS: switch (wValue) { case USB_PORT_FEAT_C_CONNECTION: - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTCONNDET); + clrsetbits_le32(®s->host_regs.hprt0, HPRT0_W1C_MASK, HPRT0_CONNDET); break; } break; @@ -754,13 +672,13 @@ static int dwc_otg_submit_rh_msg_out(struct dwc2_priv *priv, break; case USB_PORT_FEAT_RESET: - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST); + clrsetbits_le32(®s->host_regs.hprt0, HPRT0_W1C_MASK, HPRT0_RST); mdelay(50); - clrbits_le32(®s->hprt0, DWC2_HPRT0_W1C_MASK | DWC2_HPRT0_PRTRST); + clrbits_le32(®s->host_regs.hprt0, HPRT0_W1C_MASK | HPRT0_RST); break; case USB_PORT_FEAT_POWER: - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST); + clrsetbits_le32(®s->host_regs.hprt0, HPRT0_W1C_MASK, HPRT0_RST); break; case USB_PORT_FEAT_ENABLE: @@ -806,29 +724,28 @@ static int dwc_otg_submit_rh_msg(struct dwc2_priv *priv, struct usb_device *dev, return stat; } -int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle) +int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, u32 *sub, u8 *toggle) { int ret; - uint32_t hcint, hctsiz; + u32 hcint, hctsiz; - ret = wait_for_bit_le32(&hc_regs->hcint, DWC2_HCINT_CHHLTD, true, + ret = wait_for_bit_le32(&hc_regs->hcint, HCINTMSK_CHHLTD, true, 2000, false); if (ret) return ret; hcint = readl(&hc_regs->hcint); hctsiz = readl(&hc_regs->hctsiz); - *sub = (hctsiz & DWC2_HCTSIZ_XFERSIZE_MASK) >> - DWC2_HCTSIZ_XFERSIZE_OFFSET; - *toggle = (hctsiz & DWC2_HCTSIZ_PID_MASK) >> DWC2_HCTSIZ_PID_OFFSET; + *sub = FIELD_GET(TSIZ_XFERSIZE_MASK, hctsiz); + *toggle = FIELD_GET(TSIZ_SC_MC_PID_MASK, hctsiz); debug("%s: HCINT=%08x sub=%u toggle=%d\n", __func__, hcint, *sub, *toggle); - if (hcint & DWC2_HCINT_XFERCOMP) + if (hcint & HCINTMSK_XFERCOMPL) return 0; - if (hcint & (DWC2_HCINT_NAK | DWC2_HCINT_FRMOVRUN)) + if (hcint & (HCINTMSK_NAK | HCINTMSK_FRMOVRUN)) return -EAGAIN; debug("%s: Error (HCINT=%08x)\n", __func__, hcint); @@ -836,10 +753,10 @@ int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle) } static int dwc2_eptype[] = { - DWC2_HCCHAR_EPTYPE_ISOC, - DWC2_HCCHAR_EPTYPE_INTR, - DWC2_HCCHAR_EPTYPE_CONTROL, - DWC2_HCCHAR_EPTYPE_BULK, + HCCHAR_EPTYPE_ISOC, + HCCHAR_EPTYPE_INTR, + HCCHAR_EPTYPE_CONTROL, + HCCHAR_EPTYPE_BULK, }; static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer, @@ -847,14 +764,14 @@ static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer, int xfer_len, int *actual_len, int odd_frame) { int ret = 0; - uint32_t sub; + u32 sub; debug("%s: chunk: pid %d xfer_len %u pkts %u\n", __func__, *pid, xfer_len, num_packets); - writel((xfer_len << DWC2_HCTSIZ_XFERSIZE_OFFSET) | - (num_packets << DWC2_HCTSIZ_PKTCNT_OFFSET) | - (*pid << DWC2_HCTSIZ_PID_OFFSET), + writel(FIELD_PREP(TSIZ_XFERSIZE_MASK, xfer_len) | + FIELD_PREP(TSIZ_PKTCNT_MASK, num_packets) | + FIELD_PREP(TSIZ_SC_MC_PID_MASK, *pid), &hc_regs->hctsiz); if (xfer_len) { @@ -878,12 +795,12 @@ static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer, writel(0x3fff, &hc_regs->hcint); /* Set host channel enable after all other setup is complete. */ - clrsetbits_le32(&hc_regs->hcchar, DWC2_HCCHAR_MULTICNT_MASK | - DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS | - DWC2_HCCHAR_ODDFRM, - (1 << DWC2_HCCHAR_MULTICNT_OFFSET) | - (odd_frame << DWC2_HCCHAR_ODDFRM_OFFSET) | - DWC2_HCCHAR_CHEN); + clrsetbits_le32(&hc_regs->hcchar, HCCHAR_MULTICNT_MASK | + HCCHAR_CHENA | HCCHAR_CHDIS | + HCCHAR_ODDFRM, + FIELD_PREP(HCCHAR_MULTICNT_MASK, 1) | + FIELD_PREP(HCCHAR_ODDFRM, odd_frame) | + HCCHAR_CHENA); ret = wait_for_chhltd(hc_regs, &sub, pid); if (ret < 0) @@ -907,7 +824,7 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, unsigned long pipe, u8 *pid, int in, void *buffer, int len) { struct dwc2_core_regs *regs = priv->regs; - struct dwc2_hc_regs *hc_regs = ®s->hc_regs[DWC2_HC_CHANNEL]; + struct dwc2_hc_regs *hc_regs = ®s->host_regs.hc[DWC2_HC_CHANNEL]; struct dwc2_host_regs *host_regs = ®s->host_regs; int devnum = usb_pipedevice(pipe); int ep = usb_pipeendpoint(pipe); @@ -917,10 +834,10 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, int ret = 0; int do_split = 0; int complete_split = 0; - uint32_t xfer_len; - uint32_t num_packets; + u32 xfer_len; + u32 num_packets; int stop_transfer = 0; - uint32_t max_xfer_len; + u32 max_xfer_len; int ssplit_frame_num = 0; debug("%s: msg: pipe %lx pid %d in %d len %d\n", __func__, pipe, *pid, @@ -942,11 +859,11 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, /* Check if the target is a FS/LS device behind a HS hub */ if (dev->speed != USB_SPEED_HIGH) { - uint8_t hub_addr; - uint8_t hub_port; - uint32_t hprt0 = readl(®s->hprt0); - if ((hprt0 & DWC2_HPRT0_PRTSPD_MASK) == - DWC2_HPRT0_PRTSPD_HIGH) { + u8 hub_addr; + u8 hub_port; + u32 hprt0 = readl(®s->host_regs.hprt0); + + if (FIELD_GET(HPRT0_SPD_MASK, hprt0) == HPRT0_SPD_HIGH_SPEED) { usb_find_usb2_hub_address_port(dev, &hub_addr, &hub_port); dwc_otg_hc_init_split(hc_regs, hub_addr, hub_port); @@ -959,7 +876,7 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, do { int actual_len = 0; - uint32_t hcint; + u32 hcint; int odd_frame = 0; xfer_len = len - done; @@ -971,11 +888,11 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, num_packets = 1; if (complete_split) - setbits_le32(&hc_regs->hcsplt, DWC2_HCSPLT_COMPSPLT); + setbits_le32(&hc_regs->hcsplt, HCSPLT_COMPSPLT); else if (do_split) - clrbits_le32(&hc_regs->hcsplt, DWC2_HCSPLT_COMPSPLT); + clrbits_le32(&hc_regs->hcsplt, HCSPLT_COMPSPLT); - if (eptype == DWC2_HCCHAR_EPTYPE_INTR) { + if (eptype == HCCHAR_EPTYPE_INTR) { int uframe_num = readl(&host_regs->hfnum); if (!(uframe_num & 0x1)) odd_frame = 1; @@ -988,19 +905,19 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev, hcint = readl(&hc_regs->hcint); if (complete_split) { stop_transfer = 0; - if (hcint & DWC2_HCINT_NYET) { + if (hcint & HCINTMSK_NYET) { ret = 0; - int frame_num = DWC2_HFNUM_MAX_FRNUM & - readl(&host_regs->hfnum); - if (((frame_num - ssplit_frame_num) & - DWC2_HFNUM_MAX_FRNUM) > 4) + int frame_num = FIELD_GET(HFNUM_FRNUM_MASK, + readl(&host_regs->hfnum)); + + if (((frame_num - ssplit_frame_num) & HFNUM_FRNUM_MASK) > 4) ret = -EAGAIN; } else complete_split = 0; } else if (do_split) { - if (hcint & DWC2_HCINT_ACK) { - ssplit_frame_num = DWC2_HFNUM_MAX_FRNUM & - readl(&host_regs->hfnum); + if (hcint & HCINTMSK_ACK) { + ssplit_frame_num = FIELD_GET(HFNUM_FRNUM_MASK, + readl(&host_regs->hfnum)); ret = 0; complete_split = 1; } @@ -1166,7 +1083,7 @@ static int dwc2_reset(struct udevice *dev) static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) { struct dwc2_core_regs *regs = priv->regs; - uint32_t snpsid; + u32 snpsid; int i, j; int ret; @@ -1174,12 +1091,11 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) if (ret) return ret; - snpsid = readl(®s->gsnpsid); + snpsid = readl(®s->global_regs.gsnpsid); dev_info(dev, "Core Release: %x.%03x\n", snpsid >> 12 & 0xf, snpsid & 0xfff); - if ((snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_2xx && - (snpsid & DWC2_SNPSID_DEVID_MASK) != DWC2_SNPSID_DEVID_VER_3xx) { + if (FIELD_GET(GSNPSID_ID_MASK, snpsid) != GSNPSID_OTG_ID) { dev_info(dev, "SNPSID invalid (not DWC2 OTG device): %08x\n", snpsid); return -ENODEV; @@ -1200,9 +1116,9 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) dwc_otg_core_host_init(dev, regs); } - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST); + clrsetbits_le32(®s->host_regs.hprt0, HPRT0_W1C_MASK, HPRT0_RST); mdelay(50); - clrbits_le32(®s->hprt0, DWC2_HPRT0_W1C_MASK | DWC2_HPRT0_PRTRST); + clrbits_le32(®s->host_regs.hprt0, HPRT0_W1C_MASK | HPRT0_RST); for (i = 0; i < MAX_DEVICE; i++) { for (j = 0; j < MAX_ENDPOINT; j++) { @@ -1217,7 +1133,7 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) * is started (the bus is scanned) and fixes the USB detection * problems with some problematic USB keys. */ - if (readl(®s->gintsts) & DWC2_GINTSTS_CURMODE_HOST) + if (readl(®s->global_regs.gintsts) & GINTSTS_CURMODE_HOST) mdelay(1000); printf("USB DWC2\n"); @@ -1228,7 +1144,7 @@ static int dwc2_init_common(struct udevice *dev, struct dwc2_priv *priv) static void dwc2_uninit_common(struct dwc2_core_regs *regs) { /* Put everything in reset. */ - clrsetbits_le32(®s->hprt0, DWC2_HPRT0_W1C_MASK, DWC2_HPRT0_PRTRST); + clrsetbits_le32(®s->host_regs.hprt0, HPRT0_W1C_MASK, HPRT0_RST); } #if !CONFIG_IS_ENABLED(DM_USB) diff --git a/drivers/usb/host/dwc2.h b/drivers/usb/host/dwc2.h index 6f022e33a19..f0bb2949649 100644 --- a/drivers/usb/host/dwc2.h +++ b/drivers/usb/host/dwc2.h @@ -6,742 +6,6 @@ #ifndef __DWC2_H__ #define __DWC2_H__ -struct dwc2_hc_regs { - u32 hcchar; /* 0x00 */ - u32 hcsplt; - u32 hcint; - u32 hcintmsk; - u32 hctsiz; /* 0x10 */ - u32 hcdma; - u32 reserved; - u32 hcdmab; -}; - -struct dwc2_host_regs { - u32 hcfg; /* 0x00 */ - u32 hfir; - u32 hfnum; - u32 _pad_0x40c; - u32 hptxsts; /* 0x10 */ - u32 haint; - u32 haintmsk; - u32 hflbaddr; -}; - -struct dwc2_core_regs { - u32 gotgctl; /* 0x000 */ - u32 gotgint; - u32 gahbcfg; - u32 gusbcfg; - u32 grstctl; /* 0x010 */ - u32 gintsts; - u32 gintmsk; - u32 grxstsr; - u32 grxstsp; /* 0x020 */ - u32 grxfsiz; - u32 gnptxfsiz; - u32 gnptxsts; - u32 gi2cctl; /* 0x030 */ - u32 gpvndctl; - u32 ggpio; - u32 guid; - u32 gsnpsid; /* 0x040 */ - u32 ghwcfg1; - u32 ghwcfg2; - u32 ghwcfg3; - u32 ghwcfg4; /* 0x050 */ - u32 glpmcfg; - u32 _pad_0x58_0x9c[42]; - u32 hptxfsiz; /* 0x100 */ - u32 dptxfsiz_dieptxf[15]; - u32 _pad_0x140_0x3fc[176]; - struct dwc2_host_regs host_regs; /* 0x400 */ - u32 _pad_0x420_0x43c[8]; - u32 hprt0; /* 0x440 */ - u32 _pad_0x444_0x4fc[47]; - struct dwc2_hc_regs hc_regs[16]; /* 0x500 */ - u32 _pad_0x700_0xe00[448]; - u32 pcgcctl; /* 0xe00 */ -}; - -#define DWC2_GOTGCTL_SESREQSCS (1 << 0) -#define DWC2_GOTGCTL_SESREQSCS_OFFSET 0 -#define DWC2_GOTGCTL_SESREQ (1 << 1) -#define DWC2_GOTGCTL_SESREQ_OFFSET 1 -#define DWC2_GOTGCTL_HSTNEGSCS (1 << 8) -#define DWC2_GOTGCTL_HSTNEGSCS_OFFSET 8 -#define DWC2_GOTGCTL_HNPREQ (1 << 9) -#define DWC2_GOTGCTL_HNPREQ_OFFSET 9 -#define DWC2_GOTGCTL_HSTSETHNPEN (1 << 10) -#define DWC2_GOTGCTL_HSTSETHNPEN_OFFSET 10 -#define DWC2_GOTGCTL_DEVHNPEN (1 << 11) -#define DWC2_GOTGCTL_DEVHNPEN_OFFSET 11 -#define DWC2_GOTGCTL_CONIDSTS (1 << 16) -#define DWC2_GOTGCTL_CONIDSTS_OFFSET 16 -#define DWC2_GOTGCTL_DBNCTIME (1 << 17) -#define DWC2_GOTGCTL_DBNCTIME_OFFSET 17 -#define DWC2_GOTGCTL_ASESVLD (1 << 18) -#define DWC2_GOTGCTL_ASESVLD_OFFSET 18 -#define DWC2_GOTGCTL_BSESVLD (1 << 19) -#define DWC2_GOTGCTL_BSESVLD_OFFSET 19 -#define DWC2_GOTGCTL_OTGVER (1 << 20) -#define DWC2_GOTGCTL_OTGVER_OFFSET 20 -#define DWC2_GOTGINT_SESENDDET (1 << 2) -#define DWC2_GOTGINT_SESENDDET_OFFSET 2 -#define DWC2_GOTGINT_SESREQSUCSTSCHNG (1 << 8) -#define DWC2_GOTGINT_SESREQSUCSTSCHNG_OFFSET 8 -#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG (1 << 9) -#define DWC2_GOTGINT_HSTNEGSUCSTSCHNG_OFFSET 9 -#define DWC2_GOTGINT_RESERVER10_16_MASK (0x7F << 10) -#define DWC2_GOTGINT_RESERVER10_16_OFFSET 10 -#define DWC2_GOTGINT_HSTNEGDET (1 << 17) -#define DWC2_GOTGINT_HSTNEGDET_OFFSET 17 -#define DWC2_GOTGINT_ADEVTOUTCHNG (1 << 18) -#define DWC2_GOTGINT_ADEVTOUTCHNG_OFFSET 18 -#define DWC2_GOTGINT_DEBDONE (1 << 19) -#define DWC2_GOTGINT_DEBDONE_OFFSET 19 -#define DWC2_GAHBCFG_GLBLINTRMSK (1 << 0) -#define DWC2_GAHBCFG_GLBLINTRMSK_OFFSET 0 -#define DWC2_GAHBCFG_HBURSTLEN_SINGLE (0 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR (1 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR4 (3 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR8 (5 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_INCR16 (7 << 1) -#define DWC2_GAHBCFG_HBURSTLEN_MASK (0xF << 1) -#define DWC2_GAHBCFG_HBURSTLEN_OFFSET 1 -#define DWC2_GAHBCFG_DMAENABLE (1 << 5) -#define DWC2_GAHBCFG_DMAENABLE_OFFSET 5 -#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL (1 << 7) -#define DWC2_GAHBCFG_NPTXFEMPLVL_TXFEMPLVL_OFFSET 7 -#define DWC2_GAHBCFG_PTXFEMPLVL (1 << 8) -#define DWC2_GAHBCFG_PTXFEMPLVL_OFFSET 8 -#define DWC2_GUSBCFG_TOUTCAL_MASK (0x7 << 0) -#define DWC2_GUSBCFG_TOUTCAL_OFFSET 0 -#define DWC2_GUSBCFG_PHYIF (1 << 3) -#define DWC2_GUSBCFG_PHYIF_OFFSET 3 -#define DWC2_GUSBCFG_ULPI_UTMI_SEL (1 << 4) -#define DWC2_GUSBCFG_ULPI_UTMI_SEL_OFFSET 4 -#define DWC2_GUSBCFG_FSINTF (1 << 5) -#define DWC2_GUSBCFG_FSINTF_OFFSET 5 -#define DWC2_GUSBCFG_PHYSEL (1 << 6) -#define DWC2_GUSBCFG_PHYSEL_OFFSET 6 -#define DWC2_GUSBCFG_DDRSEL (1 << 7) -#define DWC2_GUSBCFG_DDRSEL_OFFSET 7 -#define DWC2_GUSBCFG_SRPCAP (1 << 8) -#define DWC2_GUSBCFG_SRPCAP_OFFSET 8 -#define DWC2_GUSBCFG_HNPCAP (1 << 9) -#define DWC2_GUSBCFG_HNPCAP_OFFSET 9 -#define DWC2_GUSBCFG_USBTRDTIM_MASK (0xF << 10) -#define DWC2_GUSBCFG_USBTRDTIM_OFFSET 10 -#define DWC2_GUSBCFG_NPTXFRWNDEN (1 << 14) -#define DWC2_GUSBCFG_NPTXFRWNDEN_OFFSET 14 -#define DWC2_GUSBCFG_PHYLPWRCLKSEL (1 << 15) -#define DWC2_GUSBCFG_PHYLPWRCLKSEL_OFFSET 15 -#define DWC2_GUSBCFG_OTGUTMIFSSEL (1 << 16) -#define DWC2_GUSBCFG_OTGUTMIFSSEL_OFFSET 16 -#define DWC2_GUSBCFG_ULPI_FSLS (1 << 17) -#define DWC2_GUSBCFG_ULPI_FSLS_OFFSET 17 -#define DWC2_GUSBCFG_ULPI_AUTO_RES (1 << 18) -#define DWC2_GUSBCFG_ULPI_AUTO_RES_OFFSET 18 -#define DWC2_GUSBCFG_ULPI_CLK_SUS_M (1 << 19) -#define DWC2_GUSBCFG_ULPI_CLK_SUS_M_OFFSET 19 -#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV (1 << 20) -#define DWC2_GUSBCFG_ULPI_EXT_VBUS_DRV_OFFSET 20 -#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR (1 << 21) -#define DWC2_GUSBCFG_ULPI_INT_VBUS_INDICATOR_OFFSET 21 -#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE (1 << 22) -#define DWC2_GUSBCFG_TERM_SEL_DL_PULSE_OFFSET 22 -#define DWC2_GUSBCFG_INDICATOR_PASSTHROUGH (1 << 24) -#define DWC2_GUSBCFG_INDICATOR_PASSTHROUGH_OFFSET 24 -#define DWC2_GUSBCFG_IC_USB_CAP (1 << 26) -#define DWC2_GUSBCFG_IC_USB_CAP_OFFSET 26 -#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE (1 << 27) -#define DWC2_GUSBCFG_IC_TRAFFIC_PULL_REMOVE_OFFSET 27 -#define DWC2_GUSBCFG_TX_END_DELAY (1 << 28) -#define DWC2_GUSBCFG_TX_END_DELAY_OFFSET 28 -#define DWC2_GUSBCFG_FORCEHOSTMODE (1 << 29) -#define DWC2_GUSBCFG_FORCEHOSTMODE_OFFSET 29 -#define DWC2_GUSBCFG_FORCEDEVMODE (1 << 30) -#define DWC2_GUSBCFG_FORCEDEVMODE_OFFSET 30 -#define DWC2_GLPMCTL_LPM_CAP_EN (1 << 0) -#define DWC2_GLPMCTL_LPM_CAP_EN_OFFSET 0 -#define DWC2_GLPMCTL_APPL_RESP (1 << 1) -#define DWC2_GLPMCTL_APPL_RESP_OFFSET 1 -#define DWC2_GLPMCTL_HIRD_MASK (0xF << 2) -#define DWC2_GLPMCTL_HIRD_OFFSET 2 -#define DWC2_GLPMCTL_REM_WKUP_EN (1 << 6) -#define DWC2_GLPMCTL_REM_WKUP_EN_OFFSET 6 -#define DWC2_GLPMCTL_EN_UTMI_SLEEP (1 << 7) -#define DWC2_GLPMCTL_EN_UTMI_SLEEP_OFFSET 7 -#define DWC2_GLPMCTL_HIRD_THRES_MASK (0x1F << 8) -#define DWC2_GLPMCTL_HIRD_THRES_OFFSET 8 -#define DWC2_GLPMCTL_LPM_RESP_MASK (0x3 << 13) -#define DWC2_GLPMCTL_LPM_RESP_OFFSET 13 -#define DWC2_GLPMCTL_PRT_SLEEP_STS (1 << 15) -#define DWC2_GLPMCTL_PRT_SLEEP_STS_OFFSET 15 -#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK (1 << 16) -#define DWC2_GLPMCTL_SLEEP_STATE_RESUMEOK_OFFSET 16 -#define DWC2_GLPMCTL_LPM_CHAN_INDEX_MASK (0xF << 17) -#define DWC2_GLPMCTL_LPM_CHAN_INDEX_OFFSET 17 -#define DWC2_GLPMCTL_RETRY_COUNT_MASK (0x7 << 21) -#define DWC2_GLPMCTL_RETRY_COUNT_OFFSET 21 -#define DWC2_GLPMCTL_SEND_LPM (1 << 24) -#define DWC2_GLPMCTL_SEND_LPM_OFFSET 24 -#define DWC2_GLPMCTL_RETRY_COUNT_STS_MASK (0x7 << 25) -#define DWC2_GLPMCTL_RETRY_COUNT_STS_OFFSET 25 -#define DWC2_GLPMCTL_HSIC_CONNECT (1 << 30) -#define DWC2_GLPMCTL_HSIC_CONNECT_OFFSET 30 -#define DWC2_GLPMCTL_INV_SEL_HSIC (1 << 31) -#define DWC2_GLPMCTL_INV_SEL_HSIC_OFFSET 31 -#define DWC2_GRSTCTL_CSFTRST (1 << 0) -#define DWC2_GRSTCTL_CSFTRST_OFFSET 0 -#define DWC2_GRSTCTL_HSFTRST (1 << 1) -#define DWC2_GRSTCTL_HSFTRST_OFFSET 1 -#define DWC2_GRSTCTL_HSTFRM (1 << 2) -#define DWC2_GRSTCTL_HSTFRM_OFFSET 2 -#define DWC2_GRSTCTL_INTKNQFLSH (1 << 3) -#define DWC2_GRSTCTL_INTKNQFLSH_OFFSET 3 -#define DWC2_GRSTCTL_RXFFLSH (1 << 4) -#define DWC2_GRSTCTL_RXFFLSH_OFFSET 4 -#define DWC2_GRSTCTL_TXFFLSH (1 << 5) -#define DWC2_GRSTCTL_TXFFLSH_OFFSET 5 -#define DWC2_GRSTCTL_TXFNUM_MASK (0x1F << 6) -#define DWC2_GRSTCTL_TXFNUM_OFFSET 6 -#define DWC2_GRSTCTL_DMAREQ (1 << 30) -#define DWC2_GRSTCTL_DMAREQ_OFFSET 30 -#define DWC2_GRSTCTL_AHBIDLE (1 << 31) -#define DWC2_GRSTCTL_AHBIDLE_OFFSET 31 -#define DWC2_GINTMSK_MODEMISMATCH (1 << 1) -#define DWC2_GINTMSK_MODEMISMATCH_OFFSET 1 -#define DWC2_GINTMSK_OTGINTR (1 << 2) -#define DWC2_GINTMSK_OTGINTR_OFFSET 2 -#define DWC2_GINTMSK_SOFINTR (1 << 3) -#define DWC2_GINTMSK_SOFINTR_OFFSET 3 -#define DWC2_GINTMSK_RXSTSQLVL (1 << 4) -#define DWC2_GINTMSK_RXSTSQLVL_OFFSET 4 -#define DWC2_GINTMSK_NPTXFEMPTY (1 << 5) -#define DWC2_GINTMSK_NPTXFEMPTY_OFFSET 5 -#define DWC2_GINTMSK_GINNAKEFF (1 << 6) -#define DWC2_GINTMSK_GINNAKEFF_OFFSET 6 -#define DWC2_GINTMSK_GOUTNAKEFF (1 << 7) -#define DWC2_GINTMSK_GOUTNAKEFF_OFFSET 7 -#define DWC2_GINTMSK_I2CINTR (1 << 9) -#define DWC2_GINTMSK_I2CINTR_OFFSET 9 -#define DWC2_GINTMSK_ERLYSUSPEND (1 << 10) -#define DWC2_GINTMSK_ERLYSUSPEND_OFFSET 10 -#define DWC2_GINTMSK_USBSUSPEND (1 << 11) -#define DWC2_GINTMSK_USBSUSPEND_OFFSET 11 -#define DWC2_GINTMSK_USBRESET (1 << 12) -#define DWC2_GINTMSK_USBRESET_OFFSET 12 -#define DWC2_GINTMSK_ENUMDONE (1 << 13) -#define DWC2_GINTMSK_ENUMDONE_OFFSET 13 -#define DWC2_GINTMSK_ISOOUTDROP (1 << 14) -#define DWC2_GINTMSK_ISOOUTDROP_OFFSET 14 -#define DWC2_GINTMSK_EOPFRAME (1 << 15) -#define DWC2_GINTMSK_EOPFRAME_OFFSET 15 -#define DWC2_GINTMSK_EPMISMATCH (1 << 17) -#define DWC2_GINTMSK_EPMISMATCH_OFFSET 17 -#define DWC2_GINTMSK_INEPINTR (1 << 18) -#define DWC2_GINTMSK_INEPINTR_OFFSET 18 -#define DWC2_GINTMSK_OUTEPINTR (1 << 19) -#define DWC2_GINTMSK_OUTEPINTR_OFFSET 19 -#define DWC2_GINTMSK_INCOMPLISOIN (1 << 20) -#define DWC2_GINTMSK_INCOMPLISOIN_OFFSET 20 -#define DWC2_GINTMSK_INCOMPLISOOUT (1 << 21) -#define DWC2_GINTMSK_INCOMPLISOOUT_OFFSET 21 -#define DWC2_GINTMSK_PORTINTR (1 << 24) -#define DWC2_GINTMSK_PORTINTR_OFFSET 24 -#define DWC2_GINTMSK_HCINTR (1 << 25) -#define DWC2_GINTMSK_HCINTR_OFFSET 25 -#define DWC2_GINTMSK_PTXFEMPTY (1 << 26) -#define DWC2_GINTMSK_PTXFEMPTY_OFFSET 26 -#define DWC2_GINTMSK_LPMTRANRCVD (1 << 27) -#define DWC2_GINTMSK_LPMTRANRCVD_OFFSET 27 -#define DWC2_GINTMSK_CONIDSTSCHNG (1 << 28) -#define DWC2_GINTMSK_CONIDSTSCHNG_OFFSET 28 -#define DWC2_GINTMSK_DISCONNECT (1 << 29) -#define DWC2_GINTMSK_DISCONNECT_OFFSET 29 -#define DWC2_GINTMSK_SESSREQINTR (1 << 30) -#define DWC2_GINTMSK_SESSREQINTR_OFFSET 30 -#define DWC2_GINTMSK_WKUPINTR (1 << 31) -#define DWC2_GINTMSK_WKUPINTR_OFFSET 31 -#define DWC2_GINTSTS_CURMODE_DEVICE (0 << 0) -#define DWC2_GINTSTS_CURMODE_HOST (1 << 0) -#define DWC2_GINTSTS_CURMODE (1 << 0) -#define DWC2_GINTSTS_CURMODE_OFFSET 0 -#define DWC2_GINTSTS_MODEMISMATCH (1 << 1) -#define DWC2_GINTSTS_MODEMISMATCH_OFFSET 1 -#define DWC2_GINTSTS_OTGINTR (1 << 2) -#define DWC2_GINTSTS_OTGINTR_OFFSET 2 -#define DWC2_GINTSTS_SOFINTR (1 << 3) -#define DWC2_GINTSTS_SOFINTR_OFFSET 3 -#define DWC2_GINTSTS_RXSTSQLVL (1 << 4) -#define DWC2_GINTSTS_RXSTSQLVL_OFFSET 4 -#define DWC2_GINTSTS_NPTXFEMPTY (1 << 5) -#define DWC2_GINTSTS_NPTXFEMPTY_OFFSET 5 -#define DWC2_GINTSTS_GINNAKEFF (1 << 6) -#define DWC2_GINTSTS_GINNAKEFF_OFFSET 6 -#define DWC2_GINTSTS_GOUTNAKEFF (1 << 7) -#define DWC2_GINTSTS_GOUTNAKEFF_OFFSET 7 -#define DWC2_GINTSTS_I2CINTR (1 << 9) -#define DWC2_GINTSTS_I2CINTR_OFFSET 9 -#define DWC2_GINTSTS_ERLYSUSPEND (1 << 10) -#define DWC2_GINTSTS_ERLYSUSPEND_OFFSET 10 -#define DWC2_GINTSTS_USBSUSPEND (1 << 11) -#define DWC2_GINTSTS_USBSUSPEND_OFFSET 11 -#define DWC2_GINTSTS_USBRESET (1 << 12) -#define DWC2_GINTSTS_USBRESET_OFFSET 12 -#define DWC2_GINTSTS_ENUMDONE (1 << 13) -#define DWC2_GINTSTS_ENUMDONE_OFFSET 13 -#define DWC2_GINTSTS_ISOOUTDROP (1 << 14) -#define DWC2_GINTSTS_ISOOUTDROP_OFFSET 14 -#define DWC2_GINTSTS_EOPFRAME (1 << 15) -#define DWC2_GINTSTS_EOPFRAME_OFFSET 15 -#define DWC2_GINTSTS_INTOKENRX (1 << 16) -#define DWC2_GINTSTS_INTOKENRX_OFFSET 16 -#define DWC2_GINTSTS_EPMISMATCH (1 << 17) -#define DWC2_GINTSTS_EPMISMATCH_OFFSET 17 -#define DWC2_GINTSTS_INEPINT (1 << 18) -#define DWC2_GINTSTS_INEPINT_OFFSET 18 -#define DWC2_GINTSTS_OUTEPINTR (1 << 19) -#define DWC2_GINTSTS_OUTEPINTR_OFFSET 19 -#define DWC2_GINTSTS_INCOMPLISOIN (1 << 20) -#define DWC2_GINTSTS_INCOMPLISOIN_OFFSET 20 -#define DWC2_GINTSTS_INCOMPLISOOUT (1 << 21) -#define DWC2_GINTSTS_INCOMPLISOOUT_OFFSET 21 -#define DWC2_GINTSTS_PORTINTR (1 << 24) -#define DWC2_GINTSTS_PORTINTR_OFFSET 24 -#define DWC2_GINTSTS_HCINTR (1 << 25) -#define DWC2_GINTSTS_HCINTR_OFFSET 25 -#define DWC2_GINTSTS_PTXFEMPTY (1 << 26) -#define DWC2_GINTSTS_PTXFEMPTY_OFFSET 26 -#define DWC2_GINTSTS_LPMTRANRCVD (1 << 27) -#define DWC2_GINTSTS_LPMTRANRCVD_OFFSET 27 -#define DWC2_GINTSTS_CONIDSTSCHNG (1 << 28) -#define DWC2_GINTSTS_CONIDSTSCHNG_OFFSET 28 -#define DWC2_GINTSTS_DISCONNECT (1 << 29) -#define DWC2_GINTSTS_DISCONNECT_OFFSET 29 -#define DWC2_GINTSTS_SESSREQINTR (1 << 30) -#define DWC2_GINTSTS_SESSREQINTR_OFFSET 30 -#define DWC2_GINTSTS_WKUPINTR (1 << 31) -#define DWC2_GINTSTS_WKUPINTR_OFFSET 31 -#define DWC2_GRXSTS_EPNUM_MASK (0xF << 0) -#define DWC2_GRXSTS_EPNUM_OFFSET 0 -#define DWC2_GRXSTS_BCNT_MASK (0x7FF << 4) -#define DWC2_GRXSTS_BCNT_OFFSET 4 -#define DWC2_GRXSTS_DPID_MASK (0x3 << 15) -#define DWC2_GRXSTS_DPID_OFFSET 15 -#define DWC2_GRXSTS_PKTSTS_MASK (0xF << 17) -#define DWC2_GRXSTS_PKTSTS_OFFSET 17 -#define DWC2_GRXSTS_FN_MASK (0xF << 21) -#define DWC2_GRXSTS_FN_OFFSET 21 -#define DWC2_FIFOSIZE_STARTADDR_MASK (0xFFFF << 0) -#define DWC2_FIFOSIZE_STARTADDR_OFFSET 0 -#define DWC2_FIFOSIZE_DEPTH_MASK (0xFFFF << 16) -#define DWC2_FIFOSIZE_DEPTH_OFFSET 16 -#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_MASK (0xFFFF << 0) -#define DWC2_GNPTXSTS_NPTXFSPCAVAIL_OFFSET 0 -#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_MASK (0xFF << 16) -#define DWC2_GNPTXSTS_NPTXQSPCAVAIL_OFFSET 16 -#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE (1 << 24) -#define DWC2_GNPTXSTS_NPTXQTOP_TERMINATE_OFFSET 24 -#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_MASK (0x3 << 25) -#define DWC2_GNPTXSTS_NPTXQTOP_TOKEN_OFFSET 25 -#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_MASK (0xF << 27) -#define DWC2_GNPTXSTS_NPTXQTOP_CHNEP_OFFSET 27 -#define DWC2_DTXFSTS_TXFSPCAVAIL_MASK (0xFFFF << 0) -#define DWC2_DTXFSTS_TXFSPCAVAIL_OFFSET 0 -#define DWC2_GI2CCTL_RWDATA_MASK (0xFF << 0) -#define DWC2_GI2CCTL_RWDATA_OFFSET 0 -#define DWC2_GI2CCTL_REGADDR_MASK (0xFF << 8) -#define DWC2_GI2CCTL_REGADDR_OFFSET 8 -#define DWC2_GI2CCTL_ADDR_MASK (0x7F << 16) -#define DWC2_GI2CCTL_ADDR_OFFSET 16 -#define DWC2_GI2CCTL_I2CEN (1 << 23) -#define DWC2_GI2CCTL_I2CEN_OFFSET 23 -#define DWC2_GI2CCTL_ACK (1 << 24) -#define DWC2_GI2CCTL_ACK_OFFSET 24 -#define DWC2_GI2CCTL_I2CSUSPCTL (1 << 25) -#define DWC2_GI2CCTL_I2CSUSPCTL_OFFSET 25 -#define DWC2_GI2CCTL_I2CDEVADDR_MASK (0x3 << 26) -#define DWC2_GI2CCTL_I2CDEVADDR_OFFSET 26 -#define DWC2_GI2CCTL_RW (1 << 30) -#define DWC2_GI2CCTL_RW_OFFSET 30 -#define DWC2_GI2CCTL_BSYDNE (1 << 31) -#define DWC2_GI2CCTL_BSYDNE_OFFSET 31 -#define DWC2_HWCFG1_EP_DIR0_MASK (0x3 << 0) -#define DWC2_HWCFG1_EP_DIR0_OFFSET 0 -#define DWC2_HWCFG1_EP_DIR1_MASK (0x3 << 2) -#define DWC2_HWCFG1_EP_DIR1_OFFSET 2 -#define DWC2_HWCFG1_EP_DIR2_MASK (0x3 << 4) -#define DWC2_HWCFG1_EP_DIR2_OFFSET 4 -#define DWC2_HWCFG1_EP_DIR3_MASK (0x3 << 6) -#define DWC2_HWCFG1_EP_DIR3_OFFSET 6 -#define DWC2_HWCFG1_EP_DIR4_MASK (0x3 << 8) -#define DWC2_HWCFG1_EP_DIR4_OFFSET 8 -#define DWC2_HWCFG1_EP_DIR5_MASK (0x3 << 10) -#define DWC2_HWCFG1_EP_DIR5_OFFSET 10 -#define DWC2_HWCFG1_EP_DIR6_MASK (0x3 << 12) -#define DWC2_HWCFG1_EP_DIR6_OFFSET 12 -#define DWC2_HWCFG1_EP_DIR7_MASK (0x3 << 14) -#define DWC2_HWCFG1_EP_DIR7_OFFSET 14 -#define DWC2_HWCFG1_EP_DIR8_MASK (0x3 << 16) -#define DWC2_HWCFG1_EP_DIR8_OFFSET 16 -#define DWC2_HWCFG1_EP_DIR9_MASK (0x3 << 18) -#define DWC2_HWCFG1_EP_DIR9_OFFSET 18 -#define DWC2_HWCFG1_EP_DIR10_MASK (0x3 << 20) -#define DWC2_HWCFG1_EP_DIR10_OFFSET 20 -#define DWC2_HWCFG1_EP_DIR11_MASK (0x3 << 22) -#define DWC2_HWCFG1_EP_DIR11_OFFSET 22 -#define DWC2_HWCFG1_EP_DIR12_MASK (0x3 << 24) -#define DWC2_HWCFG1_EP_DIR12_OFFSET 24 -#define DWC2_HWCFG1_EP_DIR13_MASK (0x3 << 26) -#define DWC2_HWCFG1_EP_DIR13_OFFSET 26 -#define DWC2_HWCFG1_EP_DIR14_MASK (0x3 << 28) -#define DWC2_HWCFG1_EP_DIR14_OFFSET 28 -#define DWC2_HWCFG1_EP_DIR15_MASK (0x3 << 30) -#define DWC2_HWCFG1_EP_DIR15_OFFSET 30 -#define DWC2_HWCFG2_OP_MODE_MASK (0x7 << 0) -#define DWC2_HWCFG2_OP_MODE_OFFSET 0 -#define DWC2_HWCFG2_ARCHITECTURE_SLAVE_ONLY (0x0 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_EXT_DMA (0x1 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_INT_DMA (0x2 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_MASK (0x3 << 3) -#define DWC2_HWCFG2_ARCHITECTURE_OFFSET 3 -#define DWC2_HWCFG2_POINT2POINT (1 << 5) -#define DWC2_HWCFG2_POINT2POINT_OFFSET 5 -#define DWC2_HWCFG2_HS_PHY_TYPE_MASK (0x3 << 6) -#define DWC2_HWCFG2_HS_PHY_TYPE_OFFSET 6 -#define DWC2_HWCFG2_FS_PHY_TYPE_MASK (0x3 << 8) -#define DWC2_HWCFG2_FS_PHY_TYPE_OFFSET 8 -#define DWC2_HWCFG2_NUM_DEV_EP_MASK (0xF << 10) -#define DWC2_HWCFG2_NUM_DEV_EP_OFFSET 10 -#define DWC2_HWCFG2_NUM_HOST_CHAN_MASK (0xF << 14) -#define DWC2_HWCFG2_NUM_HOST_CHAN_OFFSET 14 -#define DWC2_HWCFG2_PERIO_EP_SUPPORTED (1 << 18) -#define DWC2_HWCFG2_PERIO_EP_SUPPORTED_OFFSET 18 -#define DWC2_HWCFG2_DYNAMIC_FIFO (1 << 19) -#define DWC2_HWCFG2_DYNAMIC_FIFO_OFFSET 19 -#define DWC2_HWCFG2_MULTI_PROC_INT (1 << 20) -#define DWC2_HWCFG2_MULTI_PROC_INT_OFFSET 20 -#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_MASK (0x3 << 22) -#define DWC2_HWCFG2_NONPERIO_TX_Q_DEPTH_OFFSET 22 -#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK (0x3 << 24) -#define DWC2_HWCFG2_HOST_PERIO_TX_Q_DEPTH_OFFSET 24 -#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_MASK (0x1F << 26) -#define DWC2_HWCFG2_DEV_TOKEN_Q_DEPTH_OFFSET 26 -#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_MASK (0xF << 0) -#define DWC2_HWCFG3_XFER_SIZE_CNTR_WIDTH_OFFSET 0 -#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK (0x7 << 4) -#define DWC2_HWCFG3_PACKET_SIZE_CNTR_WIDTH_OFFSET 4 -#define DWC2_HWCFG3_OTG_FUNC (1 << 7) -#define DWC2_HWCFG3_OTG_FUNC_OFFSET 7 -#define DWC2_HWCFG3_I2C (1 << 8) -#define DWC2_HWCFG3_I2C_OFFSET 8 -#define DWC2_HWCFG3_VENDOR_CTRL_IF (1 << 9) -#define DWC2_HWCFG3_VENDOR_CTRL_IF_OFFSET 9 -#define DWC2_HWCFG3_OPTIONAL_FEATURES (1 << 10) -#define DWC2_HWCFG3_OPTIONAL_FEATURES_OFFSET 10 -#define DWC2_HWCFG3_SYNCH_RESET_TYPE (1 << 11) -#define DWC2_HWCFG3_SYNCH_RESET_TYPE_OFFSET 11 -#define DWC2_HWCFG3_OTG_ENABLE_IC_USB (1 << 12) -#define DWC2_HWCFG3_OTG_ENABLE_IC_USB_OFFSET 12 -#define DWC2_HWCFG3_OTG_ENABLE_HSIC (1 << 13) -#define DWC2_HWCFG3_OTG_ENABLE_HSIC_OFFSET 13 -#define DWC2_HWCFG3_OTG_LPM_EN (1 << 15) -#define DWC2_HWCFG3_OTG_LPM_EN_OFFSET 15 -#define DWC2_HWCFG3_DFIFO_DEPTH_MASK (0xFFFF << 16) -#define DWC2_HWCFG3_DFIFO_DEPTH_OFFSET 16 -#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_MASK (0xF << 0) -#define DWC2_HWCFG4_NUM_DEV_PERIO_IN_EP_OFFSET 0 -#define DWC2_HWCFG4_POWER_OPTIMIZ (1 << 4) -#define DWC2_HWCFG4_POWER_OPTIMIZ_OFFSET 4 -#define DWC2_HWCFG4_MIN_AHB_FREQ_MASK (0x1FF << 5) -#define DWC2_HWCFG4_MIN_AHB_FREQ_OFFSET 5 -#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_MASK (0x3 << 14) -#define DWC2_HWCFG4_UTMI_PHY_DATA_WIDTH_OFFSET 14 -#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_MASK (0xF << 16) -#define DWC2_HWCFG4_NUM_DEV_MODE_CTRL_EP_OFFSET 16 -#define DWC2_HWCFG4_IDDIG_FILT_EN (1 << 20) -#define DWC2_HWCFG4_IDDIG_FILT_EN_OFFSET 20 -#define DWC2_HWCFG4_VBUS_VALID_FILT_EN (1 << 21) -#define DWC2_HWCFG4_VBUS_VALID_FILT_EN_OFFSET 21 -#define DWC2_HWCFG4_A_VALID_FILT_EN (1 << 22) -#define DWC2_HWCFG4_A_VALID_FILT_EN_OFFSET 22 -#define DWC2_HWCFG4_B_VALID_FILT_EN (1 << 23) -#define DWC2_HWCFG4_B_VALID_FILT_EN_OFFSET 23 -#define DWC2_HWCFG4_SESSION_END_FILT_EN (1 << 24) -#define DWC2_HWCFG4_SESSION_END_FILT_EN_OFFSET 24 -#define DWC2_HWCFG4_DED_FIFO_EN (1 << 25) -#define DWC2_HWCFG4_DED_FIFO_EN_OFFSET 25 -#define DWC2_HWCFG4_NUM_IN_EPS_MASK (0xF << 26) -#define DWC2_HWCFG4_NUM_IN_EPS_OFFSET 26 -#define DWC2_HWCFG4_DESC_DMA (1 << 30) -#define DWC2_HWCFG4_DESC_DMA_OFFSET 30 -#define DWC2_HWCFG4_DESC_DMA_DYN (1 << 31) -#define DWC2_HWCFG4_DESC_DMA_DYN_OFFSET 31 -#define DWC2_HCFG_FSLSPCLKSEL_30_60_MHZ 0 -#define DWC2_HCFG_FSLSPCLKSEL_48_MHZ 1 -#define DWC2_HCFG_FSLSPCLKSEL_6_MHZ 2 -#define DWC2_HCFG_FSLSPCLKSEL_MASK (0x3 << 0) -#define DWC2_HCFG_FSLSPCLKSEL_OFFSET 0 -#define DWC2_HCFG_FSLSSUPP (1 << 2) -#define DWC2_HCFG_FSLSSUPP_OFFSET 2 -#define DWC2_HCFG_DESCDMA (1 << 23) -#define DWC2_HCFG_DESCDMA_OFFSET 23 -#define DWC2_HCFG_FRLISTEN_MASK (0x3 << 24) -#define DWC2_HCFG_FRLISTEN_OFFSET 24 -#define DWC2_HCFG_PERSCHEDENA (1 << 26) -#define DWC2_HCFG_PERSCHEDENA_OFFSET 26 -#define DWC2_HCFG_PERSCHEDSTAT (1 << 27) -#define DWC2_HCFG_PERSCHEDSTAT_OFFSET 27 -#define DWC2_HFIR_FRINT_MASK (0xFFFF << 0) -#define DWC2_HFIR_FRINT_OFFSET 0 -#define DWC2_HFNUM_FRNUM_MASK (0xFFFF << 0) -#define DWC2_HFNUM_FRNUM_OFFSET 0 -#define DWC2_HFNUM_FRREM_MASK (0xFFFF << 16) -#define DWC2_HFNUM_FRREM_OFFSET 16 -#define DWC2_HFNUM_MAX_FRNUM 0x3FFF -#define DWC2_HPTXSTS_PTXFSPCAVAIL_MASK (0xFFFF << 0) -#define DWC2_HPTXSTS_PTXFSPCAVAIL_OFFSET 0 -#define DWC2_HPTXSTS_PTXQSPCAVAIL_MASK (0xFF << 16) -#define DWC2_HPTXSTS_PTXQSPCAVAIL_OFFSET 16 -#define DWC2_HPTXSTS_PTXQTOP_TERMINATE (1 << 24) -#define DWC2_HPTXSTS_PTXQTOP_TERMINATE_OFFSET 24 -#define DWC2_HPTXSTS_PTXQTOP_TOKEN_MASK (0x3 << 25) -#define DWC2_HPTXSTS_PTXQTOP_TOKEN_OFFSET 25 -#define DWC2_HPTXSTS_PTXQTOP_CHNUM_MASK (0xF << 27) -#define DWC2_HPTXSTS_PTXQTOP_CHNUM_OFFSET 27 -#define DWC2_HPTXSTS_PTXQTOP_ODD (1 << 31) -#define DWC2_HPTXSTS_PTXQTOP_ODD_OFFSET 31 -#define DWC2_HPRT0_PRTCONNSTS (1 << 0) -#define DWC2_HPRT0_PRTCONNSTS_OFFSET 0 -#define DWC2_HPRT0_PRTCONNDET (1 << 1) -#define DWC2_HPRT0_PRTCONNDET_OFFSET 1 -#define DWC2_HPRT0_PRTENA (1 << 2) -#define DWC2_HPRT0_PRTENA_OFFSET 2 -#define DWC2_HPRT0_PRTENCHNG (1 << 3) -#define DWC2_HPRT0_PRTENCHNG_OFFSET 3 -#define DWC2_HPRT0_PRTOVRCURRACT (1 << 4) -#define DWC2_HPRT0_PRTOVRCURRACT_OFFSET 4 -#define DWC2_HPRT0_PRTOVRCURRCHNG (1 << 5) -#define DWC2_HPRT0_PRTOVRCURRCHNG_OFFSET 5 -#define DWC2_HPRT0_PRTRES (1 << 6) -#define DWC2_HPRT0_PRTRES_OFFSET 6 -#define DWC2_HPRT0_PRTSUSP (1 << 7) -#define DWC2_HPRT0_PRTSUSP_OFFSET 7 -#define DWC2_HPRT0_PRTRST (1 << 8) -#define DWC2_HPRT0_PRTRST_OFFSET 8 -#define DWC2_HPRT0_PRTLNSTS_MASK (0x3 << 10) -#define DWC2_HPRT0_PRTLNSTS_OFFSET 10 -#define DWC2_HPRT0_PRTPWR (1 << 12) -#define DWC2_HPRT0_PRTPWR_OFFSET 12 -#define DWC2_HPRT0_PRTTSTCTL_MASK (0xF << 13) -#define DWC2_HPRT0_PRTTSTCTL_OFFSET 13 -#define DWC2_HPRT0_PRTSPD_HIGH (0 << 17) -#define DWC2_HPRT0_PRTSPD_FULL (1 << 17) -#define DWC2_HPRT0_PRTSPD_LOW (2 << 17) -#define DWC2_HPRT0_PRTSPD_MASK (0x3 << 17) -#define DWC2_HPRT0_PRTSPD_OFFSET 17 -#define DWC2_HPRT0_W1C_MASK (DWC2_HPRT0_PRTCONNDET | \ - DWC2_HPRT0_PRTENA | \ - DWC2_HPRT0_PRTENCHNG | \ - DWC2_HPRT0_PRTOVRCURRCHNG) -#define DWC2_HAINT_CH0 (1 << 0) -#define DWC2_HAINT_CH0_OFFSET 0 -#define DWC2_HAINT_CH1 (1 << 1) -#define DWC2_HAINT_CH1_OFFSET 1 -#define DWC2_HAINT_CH2 (1 << 2) -#define DWC2_HAINT_CH2_OFFSET 2 -#define DWC2_HAINT_CH3 (1 << 3) -#define DWC2_HAINT_CH3_OFFSET 3 -#define DWC2_HAINT_CH4 (1 << 4) -#define DWC2_HAINT_CH4_OFFSET 4 -#define DWC2_HAINT_CH5 (1 << 5) -#define DWC2_HAINT_CH5_OFFSET 5 -#define DWC2_HAINT_CH6 (1 << 6) -#define DWC2_HAINT_CH6_OFFSET 6 -#define DWC2_HAINT_CH7 (1 << 7) -#define DWC2_HAINT_CH7_OFFSET 7 -#define DWC2_HAINT_CH8 (1 << 8) -#define DWC2_HAINT_CH8_OFFSET 8 -#define DWC2_HAINT_CH9 (1 << 9) -#define DWC2_HAINT_CH9_OFFSET 9 -#define DWC2_HAINT_CH10 (1 << 10) -#define DWC2_HAINT_CH10_OFFSET 10 -#define DWC2_HAINT_CH11 (1 << 11) -#define DWC2_HAINT_CH11_OFFSET 11 -#define DWC2_HAINT_CH12 (1 << 12) -#define DWC2_HAINT_CH12_OFFSET 12 -#define DWC2_HAINT_CH13 (1 << 13) -#define DWC2_HAINT_CH13_OFFSET 13 -#define DWC2_HAINT_CH14 (1 << 14) -#define DWC2_HAINT_CH14_OFFSET 14 -#define DWC2_HAINT_CH15 (1 << 15) -#define DWC2_HAINT_CH15_OFFSET 15 -#define DWC2_HAINT_CHINT_MASK 0xffff -#define DWC2_HAINT_CHINT_OFFSET 0 -#define DWC2_HAINTMSK_CH0 (1 << 0) -#define DWC2_HAINTMSK_CH0_OFFSET 0 -#define DWC2_HAINTMSK_CH1 (1 << 1) -#define DWC2_HAINTMSK_CH1_OFFSET 1 -#define DWC2_HAINTMSK_CH2 (1 << 2) -#define DWC2_HAINTMSK_CH2_OFFSET 2 -#define DWC2_HAINTMSK_CH3 (1 << 3) -#define DWC2_HAINTMSK_CH3_OFFSET 3 -#define DWC2_HAINTMSK_CH4 (1 << 4) -#define DWC2_HAINTMSK_CH4_OFFSET 4 -#define DWC2_HAINTMSK_CH5 (1 << 5) -#define DWC2_HAINTMSK_CH5_OFFSET 5 -#define DWC2_HAINTMSK_CH6 (1 << 6) -#define DWC2_HAINTMSK_CH6_OFFSET 6 -#define DWC2_HAINTMSK_CH7 (1 << 7) -#define DWC2_HAINTMSK_CH7_OFFSET 7 -#define DWC2_HAINTMSK_CH8 (1 << 8) -#define DWC2_HAINTMSK_CH8_OFFSET 8 -#define DWC2_HAINTMSK_CH9 (1 << 9) -#define DWC2_HAINTMSK_CH9_OFFSET 9 -#define DWC2_HAINTMSK_CH10 (1 << 10) -#define DWC2_HAINTMSK_CH10_OFFSET 10 -#define DWC2_HAINTMSK_CH11 (1 << 11) -#define DWC2_HAINTMSK_CH11_OFFSET 11 -#define DWC2_HAINTMSK_CH12 (1 << 12) -#define DWC2_HAINTMSK_CH12_OFFSET 12 -#define DWC2_HAINTMSK_CH13 (1 << 13) -#define DWC2_HAINTMSK_CH13_OFFSET 13 -#define DWC2_HAINTMSK_CH14 (1 << 14) -#define DWC2_HAINTMSK_CH14_OFFSET 14 -#define DWC2_HAINTMSK_CH15 (1 << 15) -#define DWC2_HAINTMSK_CH15_OFFSET 15 -#define DWC2_HAINTMSK_CHINT_MASK 0xffff -#define DWC2_HAINTMSK_CHINT_OFFSET 0 -#define DWC2_HCCHAR_MPS_MASK (0x7FF << 0) -#define DWC2_HCCHAR_MPS_OFFSET 0 -#define DWC2_HCCHAR_EPNUM_MASK (0xF << 11) -#define DWC2_HCCHAR_EPNUM_OFFSET 11 -#define DWC2_HCCHAR_EPDIR (1 << 15) -#define DWC2_HCCHAR_EPDIR_OFFSET 15 -#define DWC2_HCCHAR_LSPDDEV (1 << 17) -#define DWC2_HCCHAR_LSPDDEV_OFFSET 17 -#define DWC2_HCCHAR_EPTYPE_CONTROL 0 -#define DWC2_HCCHAR_EPTYPE_ISOC 1 -#define DWC2_HCCHAR_EPTYPE_BULK 2 -#define DWC2_HCCHAR_EPTYPE_INTR 3 -#define DWC2_HCCHAR_EPTYPE_MASK (0x3 << 18) -#define DWC2_HCCHAR_EPTYPE_OFFSET 18 -#define DWC2_HCCHAR_MULTICNT_MASK (0x3 << 20) -#define DWC2_HCCHAR_MULTICNT_OFFSET 20 -#define DWC2_HCCHAR_DEVADDR_MASK (0x7F << 22) -#define DWC2_HCCHAR_DEVADDR_OFFSET 22 -#define DWC2_HCCHAR_ODDFRM (1 << 29) -#define DWC2_HCCHAR_ODDFRM_OFFSET 29 -#define DWC2_HCCHAR_CHDIS (1 << 30) -#define DWC2_HCCHAR_CHDIS_OFFSET 30 -#define DWC2_HCCHAR_CHEN (1 << 31) -#define DWC2_HCCHAR_CHEN_OFFSET 31 -#define DWC2_HCSPLT_PRTADDR_MASK (0x7F << 0) -#define DWC2_HCSPLT_PRTADDR_OFFSET 0 -#define DWC2_HCSPLT_HUBADDR_MASK (0x7F << 7) -#define DWC2_HCSPLT_HUBADDR_OFFSET 7 -#define DWC2_HCSPLT_XACTPOS_MASK (0x3 << 14) -#define DWC2_HCSPLT_XACTPOS_OFFSET 14 -#define DWC2_HCSPLT_COMPSPLT (1 << 16) -#define DWC2_HCSPLT_COMPSPLT_OFFSET 16 -#define DWC2_HCSPLT_SPLTENA (1 << 31) -#define DWC2_HCSPLT_SPLTENA_OFFSET 31 -#define DWC2_HCINT_XFERCOMP (1 << 0) -#define DWC2_HCINT_XFERCOMP_OFFSET 0 -#define DWC2_HCINT_CHHLTD (1 << 1) -#define DWC2_HCINT_CHHLTD_OFFSET 1 -#define DWC2_HCINT_AHBERR (1 << 2) -#define DWC2_HCINT_AHBERR_OFFSET 2 -#define DWC2_HCINT_STALL (1 << 3) -#define DWC2_HCINT_STALL_OFFSET 3 -#define DWC2_HCINT_NAK (1 << 4) -#define DWC2_HCINT_NAK_OFFSET 4 -#define DWC2_HCINT_ACK (1 << 5) -#define DWC2_HCINT_ACK_OFFSET 5 -#define DWC2_HCINT_NYET (1 << 6) -#define DWC2_HCINT_NYET_OFFSET 6 -#define DWC2_HCINT_XACTERR (1 << 7) -#define DWC2_HCINT_XACTERR_OFFSET 7 -#define DWC2_HCINT_BBLERR (1 << 8) -#define DWC2_HCINT_BBLERR_OFFSET 8 -#define DWC2_HCINT_FRMOVRUN (1 << 9) -#define DWC2_HCINT_FRMOVRUN_OFFSET 9 -#define DWC2_HCINT_DATATGLERR (1 << 10) -#define DWC2_HCINT_DATATGLERR_OFFSET 10 -#define DWC2_HCINT_BNA (1 << 11) -#define DWC2_HCINT_BNA_OFFSET 11 -#define DWC2_HCINT_XCS_XACT (1 << 12) -#define DWC2_HCINT_XCS_XACT_OFFSET 12 -#define DWC2_HCINT_FRM_LIST_ROLL (1 << 13) -#define DWC2_HCINT_FRM_LIST_ROLL_OFFSET 13 -#define DWC2_HCINTMSK_XFERCOMPL (1 << 0) -#define DWC2_HCINTMSK_XFERCOMPL_OFFSET 0 -#define DWC2_HCINTMSK_CHHLTD (1 << 1) -#define DWC2_HCINTMSK_CHHLTD_OFFSET 1 -#define DWC2_HCINTMSK_AHBERR (1 << 2) -#define DWC2_HCINTMSK_AHBERR_OFFSET 2 -#define DWC2_HCINTMSK_STALL (1 << 3) -#define DWC2_HCINTMSK_STALL_OFFSET 3 -#define DWC2_HCINTMSK_NAK (1 << 4) -#define DWC2_HCINTMSK_NAK_OFFSET 4 -#define DWC2_HCINTMSK_ACK (1 << 5) -#define DWC2_HCINTMSK_ACK_OFFSET 5 -#define DWC2_HCINTMSK_NYET (1 << 6) -#define DWC2_HCINTMSK_NYET_OFFSET 6 -#define DWC2_HCINTMSK_XACTERR (1 << 7) -#define DWC2_HCINTMSK_XACTERR_OFFSET 7 -#define DWC2_HCINTMSK_BBLERR (1 << 8) -#define DWC2_HCINTMSK_BBLERR_OFFSET 8 -#define DWC2_HCINTMSK_FRMOVRUN (1 << 9) -#define DWC2_HCINTMSK_FRMOVRUN_OFFSET 9 -#define DWC2_HCINTMSK_DATATGLERR (1 << 10) -#define DWC2_HCINTMSK_DATATGLERR_OFFSET 10 -#define DWC2_HCINTMSK_BNA (1 << 11) -#define DWC2_HCINTMSK_BNA_OFFSET 11 -#define DWC2_HCINTMSK_XCS_XACT (1 << 12) -#define DWC2_HCINTMSK_XCS_XACT_OFFSET 12 -#define DWC2_HCINTMSK_FRM_LIST_ROLL (1 << 13) -#define DWC2_HCINTMSK_FRM_LIST_ROLL_OFFSET 13 -#define DWC2_HCTSIZ_XFERSIZE_MASK 0x7ffff -#define DWC2_HCTSIZ_XFERSIZE_OFFSET 0 -#define DWC2_HCTSIZ_SCHINFO_MASK 0xff -#define DWC2_HCTSIZ_SCHINFO_OFFSET 0 -#define DWC2_HCTSIZ_NTD_MASK (0xff << 8) -#define DWC2_HCTSIZ_NTD_OFFSET 8 -#define DWC2_HCTSIZ_PKTCNT_MASK (0x3ff << 19) -#define DWC2_HCTSIZ_PKTCNT_OFFSET 19 -#define DWC2_HCTSIZ_PID_MASK (0x3 << 29) -#define DWC2_HCTSIZ_PID_OFFSET 29 -#define DWC2_HCTSIZ_DOPNG (1 << 31) -#define DWC2_HCTSIZ_DOPNG_OFFSET 31 -#define DWC2_HCDMA_CTD_MASK (0xFF << 3) -#define DWC2_HCDMA_CTD_OFFSET 3 -#define DWC2_HCDMA_DMA_ADDR_MASK (0x1FFFFF << 11) -#define DWC2_HCDMA_DMA_ADDR_OFFSET 11 -#define DWC2_PCGCCTL_STOPPCLK (1 << 0) -#define DWC2_PCGCCTL_STOPPCLK_OFFSET 0 -#define DWC2_PCGCCTL_GATEHCLK (1 << 1) -#define DWC2_PCGCCTL_GATEHCLK_OFFSET 1 -#define DWC2_PCGCCTL_PWRCLMP (1 << 2) -#define DWC2_PCGCCTL_PWRCLMP_OFFSET 2 -#define DWC2_PCGCCTL_RSTPDWNMODULE (1 << 3) -#define DWC2_PCGCCTL_RSTPDWNMODULE_OFFSET 3 -#define DWC2_PCGCCTL_PHYSUSPENDED (1 << 4) -#define DWC2_PCGCCTL_PHYSUSPENDED_OFFSET 4 -#define DWC2_PCGCCTL_ENBL_SLEEP_GATING (1 << 5) -#define DWC2_PCGCCTL_ENBL_SLEEP_GATING_OFFSET 5 -#define DWC2_PCGCCTL_PHY_IN_SLEEP (1 << 6) -#define DWC2_PCGCCTL_PHY_IN_SLEEP_OFFSET 6 -#define DWC2_PCGCCTL_DEEP_SLEEP (1 << 7) -#define DWC2_PCGCCTL_DEEP_SLEEP_OFFSET 7 -#define DWC2_SNPSID_DEVID_VER_2xx (0x4f542 << 12) -#define DWC2_SNPSID_DEVID_VER_3xx (0x4f543 << 12) -#define DWC2_SNPSID_DEVID_MASK (0xfffff << 12) -#define DWC2_SNPSID_DEVID_OFFSET 12 - /* Host controller specific */ #define DWC2_HC_PID_DATA0 0 #define DWC2_HC_PID_DATA2 1 @@ -750,13 +14,13 @@ struct dwc2_core_regs { #define DWC2_HC_PID_SETUP 3 /* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ +#define RH_A_NDP GENMASK(7, 0) /* number of downstream ports */ +#define RH_A_PSM BIT(8) /* power switching mode */ +#define RH_A_NPS BIT(9) /* no power switching */ +#define RH_A_DT BIT(10) /* device type (mbz) */ +#define RH_A_OCPM BIT(11) /* over current protection mode */ +#define RH_A_NOCP BIT(12) /* no over current protection */ +#define RH_A_POTPGT GENMASK(31, 24) /* power on to power good time */ /* roothub.b masks */ #define RH_B_DR 0x0000ffff /* device removable flags */ diff --git a/drivers/usb/musb-new/musb_core.c b/drivers/usb/musb-new/musb_core.c index 6375be741ae..a14b127dc37 100644 --- a/drivers/usb/musb-new/musb_core.c +++ b/drivers/usb/musb-new/musb_core.c @@ -223,8 +223,6 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) struct musb *musb = hw_ep->musb; void __iomem *fifo = hw_ep->fifo; - prefetch((u8 *)src); - dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", 'T', hw_ep->epnum, fifo, len, src); diff --git a/drivers/usb/musb-new/ti-musb.c b/drivers/usb/musb-new/ti-musb.c index ec1baa9337d..967d0953875 100644 --- a/drivers/usb/musb-new/ti-musb.c +++ b/drivers/usb/musb-new/ti-musb.c @@ -282,7 +282,6 @@ U_BOOT_DRIVER(ti_musb_peripheral) = { .ops = &ti_musb_gadget_ops, .probe = ti_musb_peripheral_probe, .remove = ti_musb_peripheral_remove, - .ops = &musb_usb_ops, .plat_auto = sizeof(struct ti_musb_plat), .priv_auto = sizeof(struct ti_musb_peripheral), .flags = DM_FLAG_PRE_RELOC, diff --git a/drivers/video/bridge/dp501.c b/drivers/video/bridge/dp501.c index 9937cfe095b..0ad589304aa 100644 --- a/drivers/video/bridge/dp501.c +++ b/drivers/video/bridge/dp501.c @@ -99,7 +99,7 @@ #define SD_DB15 0x4F /* Aux Channel and PCS */ -#define DPCD_REV 0X50 +#define DPCD_REV 0x50 #define MAX_LINK_RATE 0x51 #define MAX_LANE_COUNT 0x52 #define MAX_DOWNSPREAD 0x53 diff --git a/drivers/video/hx8238d.c b/drivers/video/hx8238d.c index 2491a32810e..f0220e4cc07 100644 --- a/drivers/video/hx8238d.c +++ b/drivers/video/hx8238d.c @@ -22,7 +22,7 @@ DECLARE_GLOBAL_DATA_PTR; #define HX8238D_OUTPUT_CTRL_ADDR 0x01 #define HX8238D_LCD_AC_CTRL_ADDR 0x02 #define HX8238D_POWER_CTRL_1_ADDR 0x03 -#define HX8238D_DATA_CLR_CTRL_ADDR 0X04 +#define HX8238D_DATA_CLR_CTRL_ADDR 0x04 #define HX8238D_FUNCTION_CTRL_ADDR 0x05 #define HX8238D_LED_CTRL_ADDR 0x08 #define HX8238D_CONT_BRIGHT_CTRL_ADDR 0x0A diff --git a/drivers/video/nexell_display.c b/drivers/video/nexell_display.c index 7bda33fb16e..ea3776258a0 100644 --- a/drivers/video/nexell_display.c +++ b/drivers/video/nexell_display.c @@ -10,6 +10,7 @@ #include <config.h> #include <command.h> #include <dm.h> +#include <env.h> #include <mapmem.h> #include <malloc.h> #include <linux/compat.h> diff --git a/drivers/video/zynqmp/zynqmp_dpsub.h b/drivers/video/zynqmp/zynqmp_dpsub.h index 7d2737e31aa..dc549559cae 100644 --- a/drivers/video/zynqmp/zynqmp_dpsub.h +++ b/drivers/video/zynqmp/zynqmp_dpsub.h @@ -553,7 +553,7 @@ struct zynqmp_dpsub_priv { #define DPDMA_DESCRIPTOR_LINE_SIZE_STRIDE_SHIFT 18 #define DPDMA_DESCRIPTOR_SRC_ADDR_WIDTH 32U #define DPDMA_DESCRIPTOR_ADDR_EXT_SRC_ADDR_EXT_SHIFT 16U -#define DPDMA_CH0_DSCR_STRT_ADDR 0X0204U +#define DPDMA_CH0_DSCR_STRT_ADDR 0x0204U #define DPDMA_CH_OFFSET 0x100U #define DPDMA_CH0_CNTL 0x0218U #define DPDMA_CH3_CNTL 0x0518U diff --git a/drivers/virtio/virtio_net.h b/drivers/virtio/virtio_net.h index c92bae52690..3adcb19aead 100644 --- a/drivers/virtio/virtio_net.h +++ b/drivers/virtio/virtio_net.h @@ -9,8 +9,7 @@ #ifndef _LINUX_VIRTIO_NET_H #define _LINUX_VIRTIO_NET_H -/* TODO: needs to be removed! */ -#define ETH_ALEN 6 +#include <linux/if_ether.h> /* The feature bitmap for virtio net */ |