diff options
Diffstat (limited to 'drivers')
133 files changed, 5006 insertions, 870 deletions
diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index a01d738..c9cdbe6 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -13,6 +13,7 @@ config ADC config ADC_EXYNOS bool "Enable Exynos 54xx ADC driver" + depends on ADC help This enables basic driver for Exynos ADC compatible with Exynos54xx. It provides: @@ -22,6 +23,7 @@ config ADC_EXYNOS config ADC_SANDBOX bool "Enable Sandbox ADC test driver" + depends on ADC help This enables driver for Sandbox ADC device emulation. It provides: @@ -31,6 +33,7 @@ config ADC_SANDBOX config SARADC_MESON bool "Enable Amlogic Meson SARADC driver" + depends on ADC imply REGMAP help This enables driver for Amlogic Meson SARADC. @@ -41,6 +44,7 @@ config SARADC_MESON config SARADC_ROCKCHIP bool "Enable Rockchip SARADC driver" + depends on ADC help This enables driver for Rockchip SARADC. It provides: diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c index 03caca7..10ded1b 100644 --- a/drivers/adc/rockchip-saradc.c +++ b/drivers/adc/rockchip-saradc.c @@ -10,12 +10,17 @@ #include <clk.h> #include <dm.h> #include <errno.h> -#include <asm/io.h> +#include <reset.h> +#include <asm/arch-rockchip/hardware.h> +#include <linux/bitfield.h> #include <linux/bitops.h> +#include <linux/delay.h> #include <linux/err.h> #include <linux/printk.h> #include <power/regulator.h> +#define usleep_range(a, b) udelay((b)) + #define SARADC_CTRL_CHN_MASK GENMASK(2, 0) #define SARADC_CTRL_POWER_CTRL BIT(3) #define SARADC_CTRL_IRQ_ENABLE BIT(5) @@ -23,46 +28,163 @@ #define SARADC_TIMEOUT (100 * 1000) -struct rockchip_saradc_regs { +struct rockchip_saradc_regs_v1 { unsigned int data; unsigned int stas; unsigned int ctrl; unsigned int dly_pu_soc; }; +struct rockchip_saradc_regs_v2 { + unsigned int conv_con; +#define SARADC2_SINGLE_MODE BIT(5) +#define SARADC2_START BIT(4) +#define SARADC2_CONV_CHANNELS GENMASK(3, 0) + unsigned int t_pd_soc; + unsigned int t_as_soc; + unsigned int t_das_soc; + unsigned int t_sel_soc; + unsigned int high_comp[16]; + unsigned int low_comp[16]; + unsigned int debounce; + unsigned int ht_int_en; + unsigned int lt_int_en; + unsigned int reserved[24]; + unsigned int mt_int_en; + unsigned int end_int_en; +#define SARADC2_EN_END_INT BIT(0) + unsigned int st_con; + unsigned int status; + unsigned int end_int_st; + unsigned int ht_int_st; + unsigned int lt_int_st; + unsigned int mt_int_st; + unsigned int data[16]; + unsigned int auto_ch_en; +}; + +union rockchip_saradc_regs { + struct rockchip_saradc_regs_v1 *v1; + struct rockchip_saradc_regs_v2 *v2; +}; struct rockchip_saradc_data { int num_bits; int num_channels; unsigned long clk_rate; + int (*channel_data)(struct udevice *dev, int channel, unsigned int *data); + int (*start_channel)(struct udevice *dev, int channel); + int (*stop)(struct udevice *dev); }; struct rockchip_saradc_priv { - struct rockchip_saradc_regs *regs; + union rockchip_saradc_regs regs; int active_channel; const struct rockchip_saradc_data *data; + struct reset_ctl *reset; }; +int rockchip_saradc_channel_data_v1(struct udevice *dev, int channel, + unsigned int *data) +{ + struct rockchip_saradc_priv *priv = dev_get_priv(dev); + + if ((readl(&priv->regs.v1->ctrl) & SARADC_CTRL_IRQ_STATUS) != + SARADC_CTRL_IRQ_STATUS) + return -EBUSY; + + /* Read value */ + *data = readl(&priv->regs.v1->data); + + /* Power down adc */ + writel(0, &priv->regs.v1->ctrl); + + return 0; +} + +int rockchip_saradc_channel_data_v2(struct udevice *dev, int channel, + unsigned int *data) +{ + struct rockchip_saradc_priv *priv = dev_get_priv(dev); + + if (!(readl(&priv->regs.v2->end_int_st) & SARADC2_EN_END_INT)) + return -EBUSY; + + /* Read value */ + *data = readl(&priv->regs.v2->data[channel]); + + /* Acknowledge the interrupt */ + writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st); + + return 0; +} int rockchip_saradc_channel_data(struct udevice *dev, int channel, unsigned int *data) { struct rockchip_saradc_priv *priv = dev_get_priv(dev); struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); + int ret; if (channel != priv->active_channel) { pr_err("Requested channel is not active!"); return -EINVAL; } - if ((readl(&priv->regs->ctrl) & SARADC_CTRL_IRQ_STATUS) != - SARADC_CTRL_IRQ_STATUS) - return -EBUSY; + ret = priv->data->channel_data(dev, channel, data); + if (ret) { + if (ret != -EBUSY) + pr_err("Error reading channel data, %d!", ret); + return ret; + } - /* Read value */ - *data = readl(&priv->regs->data); *data &= uc_pdata->data_mask; - /* Power down adc */ - writel(0, &priv->regs->ctrl); + return 0; +} + +int rockchip_saradc_start_channel_v1(struct udevice *dev, int channel) +{ + struct rockchip_saradc_priv *priv = dev_get_priv(dev); + + /* 8 clock periods as delay between power up and start cmd */ + writel(8, &priv->regs.v1->dly_pu_soc); + + /* Select the channel to be used and trigger conversion */ + writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) | + SARADC_CTRL_IRQ_ENABLE, &priv->regs.v1->ctrl); + + return 0; +} + +static void rockchip_saradc_reset_controller(struct reset_ctl *reset) +{ + reset_assert(reset); + usleep_range(10, 20); + reset_deassert(reset); +} + +int rockchip_saradc_start_channel_v2(struct udevice *dev, int channel) +{ + struct rockchip_saradc_priv *priv = dev_get_priv(dev); + + /* + * Downstream says + * """If read other chn at anytime, then chn1 will error, assert + * controller as a workaround.""" + */ + if (priv->reset) + rockchip_saradc_reset_controller(priv->reset); + + writel(0xc, &priv->regs.v2->t_das_soc); + writel(0x20, &priv->regs.v2->t_pd_soc); + + /* Acknowledge any previous interrupt */ + writel(SARADC2_EN_END_INT, &priv->regs.v2->end_int_st); + + rk_clrsetreg(&priv->regs.v2->conv_con, + SARADC2_CONV_CHANNELS | SARADC2_START | SARADC2_SINGLE_MODE, + FIELD_PREP(SARADC2_CONV_CHANNELS, channel) | + FIELD_PREP(SARADC2_START, 1) | + FIELD_PREP(SARADC2_SINGLE_MODE, 1)); return 0; } @@ -70,30 +192,46 @@ int rockchip_saradc_channel_data(struct udevice *dev, int channel, int rockchip_saradc_start_channel(struct udevice *dev, int channel) { struct rockchip_saradc_priv *priv = dev_get_priv(dev); + int ret; if (channel < 0 || channel >= priv->data->num_channels) { pr_err("Requested channel is invalid!"); return -EINVAL; } - /* 8 clock periods as delay between power up and start cmd */ - writel(8, &priv->regs->dly_pu_soc); - - /* Select the channel to be used and trigger conversion */ - writel(SARADC_CTRL_POWER_CTRL | (channel & SARADC_CTRL_CHN_MASK) | - SARADC_CTRL_IRQ_ENABLE, &priv->regs->ctrl); + ret = priv->data->start_channel(dev, channel); + if (ret) { + pr_err("Error starting channel, %d!", ret); + return ret; + } priv->active_channel = channel; return 0; } -int rockchip_saradc_stop(struct udevice *dev) +int rockchip_saradc_stop_v1(struct udevice *dev) { struct rockchip_saradc_priv *priv = dev_get_priv(dev); /* Power down adc */ - writel(0, &priv->regs->ctrl); + writel(0, &priv->regs.v1->ctrl); + + return 0; +} + +int rockchip_saradc_stop(struct udevice *dev) +{ + struct rockchip_saradc_priv *priv = dev_get_priv(dev); + + if (priv->data->stop) { + int ret = priv->data->stop(dev); + + if (ret) { + pr_err("Error stopping channel, %d!", ret); + return ret; + } + } priv->active_channel = -1; @@ -109,6 +247,8 @@ int rockchip_saradc_probe(struct udevice *dev) int vref_uv; int ret; + priv->reset = devm_reset_control_get_optional(dev, "saradc-apb"); + ret = clk_get_by_index(dev, 0, &clk); if (ret) return ret; @@ -125,6 +265,9 @@ int rockchip_saradc_probe(struct udevice *dev) return ret; } + if (priv->reset) + rockchip_saradc_reset_controller(priv->reset); + vref_uv = regulator_get_value(vref); if (vref_uv < 0) { printf("can't get vref-supply value: %d\n", vref_uv); @@ -146,8 +289,8 @@ int rockchip_saradc_of_to_plat(struct udevice *dev) struct rockchip_saradc_data *data; data = (struct rockchip_saradc_data *)dev_get_driver_data(dev); - priv->regs = dev_read_addr_ptr(dev); - if (!priv->regs) { + priv->regs.v1 = dev_read_addr_ptr(dev); + if (!priv->regs.v1) { pr_err("Dev: %s - can't get address!", dev->name); return -EINVAL; } @@ -171,18 +314,35 @@ static const struct rockchip_saradc_data saradc_data = { .num_bits = 10, .num_channels = 3, .clk_rate = 1000000, + .channel_data = rockchip_saradc_channel_data_v1, + .start_channel = rockchip_saradc_start_channel_v1, + .stop = rockchip_saradc_stop_v1, }; static const struct rockchip_saradc_data rk3066_tsadc_data = { .num_bits = 12, .num_channels = 2, .clk_rate = 50000, + .channel_data = rockchip_saradc_channel_data_v1, + .start_channel = rockchip_saradc_start_channel_v1, + .stop = rockchip_saradc_stop_v1, }; static const struct rockchip_saradc_data rk3399_saradc_data = { .num_bits = 10, .num_channels = 6, .clk_rate = 1000000, + .channel_data = rockchip_saradc_channel_data_v1, + .start_channel = rockchip_saradc_start_channel_v1, + .stop = rockchip_saradc_stop_v1, +}; + +static const struct rockchip_saradc_data rk3588_saradc_data = { + .num_bits = 12, + .num_channels = 8, + .clk_rate = 1000000, + .channel_data = rockchip_saradc_channel_data_v2, + .start_channel = rockchip_saradc_start_channel_v2, }; static const struct udevice_id rockchip_saradc_ids[] = { @@ -192,6 +352,8 @@ static const struct udevice_id rockchip_saradc_ids[] = { .data = (ulong)&rk3066_tsadc_data }, { .compatible = "rockchip,rk3399-saradc", .data = (ulong)&rk3399_saradc_data }, + { .compatible = "rockchip,rk3588-saradc", + .data = (ulong)&rk3588_saradc_data }, { } }; diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 097b05f..3918b05 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -12,6 +12,7 @@ config BUTTON config BUTTON_ADC bool "Button adc" depends on BUTTON + depends on ADC help Enable support for buttons which are connected to Analog to Digital Converter device. The ADC driver must use driver model. Buttons are diff --git a/drivers/clk/altera/Makefile b/drivers/clk/altera/Makefile index 33db092..61ffa41 100644 --- a/drivers/clk/altera/Makefile +++ b/drivers/clk/altera/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_TARGET_SOCFPGA_AGILEX) += clk-agilex.o obj-$(CONFIG_TARGET_SOCFPGA_ARRIA10) += clk-arria10.o obj-$(CONFIG_TARGET_SOCFPGA_N5X) += clk-n5x.o obj-$(CONFIG_TARGET_SOCFPGA_N5X) += clk-mem-n5x.o +obj-$(CONFIG_TARGET_SOCFPGA_AGILEX5) += clk-agilex5.o diff --git a/drivers/clk/altera/clk-agilex5.c b/drivers/clk/altera/clk-agilex5.c new file mode 100644 index 0000000..92f2abd --- /dev/null +++ b/drivers/clk/altera/clk-agilex5.c @@ -0,0 +1,745 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Intel Corporation <www.intel.com> + */ + +#include <clk-uclass.h> +#include <config.h> +#include <errno.h> +#include <dm.h> +#include <log.h> +#include <stdarg.h> +#include <stdio.h> +#include <time.h> +#include <vsprintf.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/u-boot.h> +#include <dm/lists.h> +#include <dm/util.h> +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/types.h> +#include <asm/arch/clock_manager.h> +#include <dt-bindings/clock/agilex5-clock.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct socfpga_clk_plat { + void __iomem *regs; +}; + +/* + * function to write the bypass register which requires a poll of the + * busy bit + */ +static void clk_write_bypass_mainpll(struct socfpga_clk_plat *plat, u32 val) +{ + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_BYPASS); + cm_wait_for_fsm(); +} + +static void clk_write_bypass_perpll(struct socfpga_clk_plat *plat, u32 val) +{ + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_BYPASS); + cm_wait_for_fsm(); +} + +/* function to write the ctrl register which requires a poll of the busy bit */ +static void clk_write_ctrl(struct socfpga_clk_plat *plat, u32 val) +{ + CM_REG_WRITEL(plat, val, CLKMGR_CTRL); + cm_wait_for_fsm(); +} + +static const struct { + u32 reg; + u32 val; + u32 mask; +} membus_pll[] = { + { + MEMBUS_CLKSLICE_REG, + /* + * BIT[7:7] + * Enable source synchronous mode + */ + BIT(7), + BIT(7) + }, + { + MEMBUS_SYNTHCALFOSC_INIT_CENTERFREQ_REG, + /* + * BIT[0:0] + * Sets synthcalfosc_init_centerfreq=1 to limit overshoot + * frequency during lock + */ + BIT(0), + BIT(0) + }, + { + MEMBUS_SYNTHPPM_WATCHDOGTMR_VF01_REG, + /* + * BIT[0:0] + * Sets synthppm_watchdogtmr_vf0=1 to give the pll more time + * to settle before lock is asserted. + */ + BIT(0), + BIT(0) + }, + { + MEMBUS_CALCLKSLICE0_DUTY_LOCOVR_REG, + /* + * BIT[6:0] + * Centering duty cycle for clkslice0 output + */ + 0x4a, + GENMASK(6, 0) + }, + { + MEMBUS_CALCLKSLICE1_DUTY_LOCOVR_REG, + /* + * BIT[6:0] + * Centering duty cycle for clkslice1 output + */ + 0x4a, + GENMASK(6, 0) + }, +}; + +static int membus_wait_for_req(struct socfpga_clk_plat *plat, u32 pll, + int timeout) +{ + int cnt = 0; + u32 req_status; + + if (pll == MEMBUS_MAINPLL) + req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM); + else + req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM); + + while ((cnt < timeout) && (req_status & CLKMGR_MEM_REQ_SET_MSK)) { + if (pll == MEMBUS_MAINPLL) + req_status = CM_REG_READL(plat, CLKMGR_MAINPLL_MEM); + else + req_status = CM_REG_READL(plat, CLKMGR_PERPLL_MEM); + cnt++; + } + + if (cnt >= timeout) + return -ETIMEDOUT; + + return 0; +} + +static int membus_write_pll(struct socfpga_clk_plat *plat, u32 pll, + u32 addr_offset, u32 wdat, int timeout) +{ + u32 addr; + u32 val; + + addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK); + + val = (CLKMGR_MEM_REQ_SET_MSK | CLKMGR_MEM_WR_SET_MSK | + (wdat << CLKMGR_MEM_WDAT_LSB_OFFSET) | addr); + + if (pll == MEMBUS_MAINPLL) + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM); + else + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM); + + debug("MEMBUS: Write 0x%08x to addr = 0x%08x\n", wdat, addr); + + return membus_wait_for_req(plat, pll, timeout); +} + +static int membus_read_pll(struct socfpga_clk_plat *plat, u32 pll, + u32 addr_offset, u32 *rdata, int timeout) +{ + u32 addr; + u32 val; + + addr = ((addr_offset | CLKMGR_MEM_ADDR_START) & CLKMGR_MEM_ADDR_MASK); + + val = ((CLKMGR_MEM_REQ_SET_MSK & ~CLKMGR_MEM_WR_SET_MSK) | addr); + + if (pll == MEMBUS_MAINPLL) + CM_REG_WRITEL(plat, val, CLKMGR_MAINPLL_MEM); + else + CM_REG_WRITEL(plat, val, CLKMGR_PERPLL_MEM); + + *rdata = 0; + + if (membus_wait_for_req(plat, pll, timeout)) + return -ETIMEDOUT; + + if (pll == MEMBUS_MAINPLL) + *rdata = CM_REG_READL(plat, CLKMGR_MAINPLL_MEMSTAT); + else + *rdata = CM_REG_READL(plat, CLKMGR_PERPLL_MEMSTAT); + + debug("MEMBUS: Read 0x%08x from addr = 0x%08x\n", *rdata, addr); + + return 0; +} + +static void membus_pll_configs(struct socfpga_clk_plat *plat, u32 pll) +{ + int i; + u32 rdata; + + for (i = 0; i < ARRAY_SIZE(membus_pll); i++) { + membus_read_pll(plat, pll, membus_pll[i].reg, + &rdata, MEMBUS_TIMEOUT); + membus_write_pll(plat, pll, membus_pll[i].reg, + ((rdata & ~membus_pll[i].mask) | + membus_pll[i].val), + MEMBUS_TIMEOUT); + } +} + +static u32 calc_vocalib_pll(u32 pllm, u32 pllglob) +{ + u32 mdiv, refclkdiv, arefclkdiv, drefclkdiv, mscnt, hscnt, vcocalib; + + mdiv = pllm & CLKMGR_PLLM_MDIV_MASK; + arefclkdiv = (pllglob & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET; + drefclkdiv = (pllglob & CLKMGR_PLLGLOB_DREFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET; + refclkdiv = (pllglob & CLKMGR_PLLGLOB_REFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_REFCLKDIV_OFFSET; + mscnt = CLKMGR_VCOCALIB_MSCNT_CONST / (mdiv * BIT(drefclkdiv)); + if (!mscnt) + mscnt = 1; + hscnt = (mdiv * mscnt * BIT(drefclkdiv) / refclkdiv) - + CLKMGR_VCOCALIB_HSCNT_CONST; + vcocalib = (hscnt & CLKMGR_VCOCALIB_HSCNT_MASK) | + ((mscnt << CLKMGR_VCOCALIB_MSCNT_OFFSET) & + CLKMGR_VCOCALIB_MSCNT_MASK); + + /* Dump all the pll calibration settings for debug purposes */ + debug("mdiv : %d\n", mdiv); + debug("arefclkdiv : %d\n", arefclkdiv); + debug("drefclkdiv : %d\n", drefclkdiv); + debug("refclkdiv : %d\n", refclkdiv); + debug("mscnt : %d\n", mscnt); + debug("hscnt : %d\n", hscnt); + debug("vcocalib : 0x%08x\n", vcocalib); + + return vcocalib; +} + +/* + * Setup clocks while making no assumptions about previous state of the clocks. + */ +static void clk_basic_init(struct udevice *dev, + const struct cm_config * const cfg) +{ + struct socfpga_clk_plat *plat = dev_get_plat(dev); + u32 vcocalib; + + if (!cfg) + return; + + if (IS_ENABLED(CONFIG_TARGET_SOCFPGA_AGILEX5_EMU)) { + /* Take both PLL out of reset and power up */ + CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + + cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK); + + /* Put both PLLs in bypass */ + clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL); + clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL); + + /* Take all PLLs out of bypass */ + clk_write_bypass_mainpll(plat, 0); + clk_write_bypass_perpll(plat, 0); + + /* Out of boot mode */ + clk_write_ctrl(plat, + CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE); + } else { +#ifdef CONFIG_SPL_BUILD + /* Always force clock manager into boot mode before any configuration */ + clk_write_ctrl(plat, + CM_REG_READL(plat, CLKMGR_CTRL) | CLKMGR_CTRL_BOOTMODE); +#else + /* Skip clock configuration in SSBL if it's not in boot mode */ + if (!(CM_REG_READL(plat, CLKMGR_CTRL) & CLKMGR_CTRL_BOOTMODE)) + return; +#endif + + /* Put both PLLs in bypass */ + clk_write_bypass_mainpll(plat, CLKMGR_BYPASS_MAINPLL_ALL); + clk_write_bypass_perpll(plat, CLKMGR_BYPASS_PERPLL_ALL); + + /* Put both PLLs in Reset and Power Down */ + CM_REG_CLRBITS(plat, CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + CM_REG_CLRBITS(plat, CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + + /* setup main PLL dividers where calculate the vcocalib value */ + vcocalib = calc_vocalib_pll(cfg->main_pll_pllm, cfg->main_pll_pllglob); + CM_REG_WRITEL(plat, cfg->main_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK, + CLKMGR_MAINPLL_PLLGLOB); + CM_REG_WRITEL(plat, cfg->main_pll_fdbck, CLKMGR_MAINPLL_FDBCK); + CM_REG_WRITEL(plat, vcocalib, CLKMGR_MAINPLL_VCOCALIB); + CM_REG_WRITEL(plat, cfg->main_pll_pllc0, CLKMGR_MAINPLL_PLLC0); + CM_REG_WRITEL(plat, cfg->main_pll_pllc1, CLKMGR_MAINPLL_PLLC1); + CM_REG_WRITEL(plat, cfg->main_pll_pllc2, CLKMGR_MAINPLL_PLLC2); + CM_REG_WRITEL(plat, cfg->main_pll_pllc3, CLKMGR_MAINPLL_PLLC3); + CM_REG_WRITEL(plat, cfg->main_pll_pllm, CLKMGR_MAINPLL_PLLM); + CM_REG_WRITEL(plat, cfg->main_pll_nocclk, CLKMGR_MAINPLL_NOCCLK); + CM_REG_WRITEL(plat, cfg->main_pll_nocdiv, CLKMGR_MAINPLL_NOCDIV); + + /* setup peripheral PLL dividers where calculate the vcocalib value */ + vcocalib = calc_vocalib_pll(cfg->per_pll_pllm, cfg->per_pll_pllglob); + CM_REG_WRITEL(plat, cfg->per_pll_pllglob & ~CLKMGR_PLLGLOB_RST_MASK, + CLKMGR_PERPLL_PLLGLOB); + CM_REG_WRITEL(plat, cfg->per_pll_fdbck, CLKMGR_PERPLL_FDBCK); + CM_REG_WRITEL(plat, vcocalib, CLKMGR_PERPLL_VCOCALIB); + CM_REG_WRITEL(plat, cfg->per_pll_pllc0, CLKMGR_PERPLL_PLLC0); + CM_REG_WRITEL(plat, cfg->per_pll_pllc1, CLKMGR_PERPLL_PLLC1); + CM_REG_WRITEL(plat, cfg->per_pll_pllc2, CLKMGR_PERPLL_PLLC2); + CM_REG_WRITEL(plat, cfg->per_pll_pllc3, CLKMGR_PERPLL_PLLC3); + CM_REG_WRITEL(plat, cfg->per_pll_pllm, CLKMGR_PERPLL_PLLM); + CM_REG_WRITEL(plat, cfg->per_pll_emacctl, CLKMGR_PERPLL_EMACCTL); + CM_REG_WRITEL(plat, cfg->per_pll_gpiodiv, CLKMGR_PERPLL_GPIODIV); + + /* Configure ping pong counters in control group */ + CM_REG_WRITEL(plat, cfg->ctl_emacactr, CLKMGR_CTL_EMACACTR); + CM_REG_WRITEL(plat, cfg->ctl_emacbctr, CLKMGR_CTL_EMACBCTR); + CM_REG_WRITEL(plat, cfg->ctl_emacptpctr, CLKMGR_CTL_EMACPTPCTR); + CM_REG_WRITEL(plat, cfg->ctl_gpiodbctr, CLKMGR_CTL_GPIODBCTR); + CM_REG_WRITEL(plat, cfg->ctl_s2fuser0ctr, CLKMGR_CTL_S2FUSER0CTR); + CM_REG_WRITEL(plat, cfg->ctl_s2fuser1ctr, CLKMGR_CTL_S2FUSER1CTR); + CM_REG_WRITEL(plat, cfg->ctl_psirefctr, CLKMGR_CTL_PSIREFCTR); + CM_REG_WRITEL(plat, cfg->ctl_usb31ctr, CLKMGR_CTL_USB31CTR); + CM_REG_WRITEL(plat, cfg->ctl_dsuctr, CLKMGR_CTL_DSUCTR); + CM_REG_WRITEL(plat, cfg->ctl_core01ctr, CLKMGR_CTL_CORE01CTR); + CM_REG_WRITEL(plat, cfg->ctl_core23ctr, CLKMGR_CTL_CORE23CTR); + CM_REG_WRITEL(plat, cfg->ctl_core2ctr, CLKMGR_CTL_CORE2CTR); + CM_REG_WRITEL(plat, cfg->ctl_core3ctr, CLKMGR_CTL_CORE3CTR); + + /* Take both PLL out of reset and power up */ + CM_REG_SETBITS(plat, CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + CM_REG_SETBITS(plat, CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PLLGLOB_PD_MASK | CLKMGR_PLLGLOB_RST_MASK); + + /* Membus programming for mainpll */ + membus_pll_configs(plat, MEMBUS_MAINPLL); + /* Membus programming for peripll */ + membus_pll_configs(plat, MEMBUS_PERPLL); + + /* Enable Main pll clkslices */ + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC0) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_MAINPLL_PLLC0); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC1) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_MAINPLL_PLLC1); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC2) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_MAINPLL_PLLC2); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC3) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_MAINPLL_PLLC3); + + /* Enable Periph pll clkslices */ + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC0) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_PERPLL_PLLC0); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC1) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_PERPLL_PLLC1); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC2) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_PERPLL_PLLC2); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLC3) | + CLKMGR_PLLCX_EN_SET_MSK, + CLKMGR_PERPLL_PLLC3); + + cm_wait_for_lock(CLKMGR_STAT_ALLPLL_LOCKED_MASK); + + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_MAINPLL_LOSTLOCK); + CM_REG_WRITEL(plat, CLKMGR_LOSTLOCK_SET_MASK, CLKMGR_PERPLL_LOSTLOCK); + + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_MAINPLL_PLLGLOB) | + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK, + CLKMGR_MAINPLL_PLLGLOB); + CM_REG_WRITEL(plat, CM_REG_READL(plat, CLKMGR_PERPLL_PLLGLOB) | + CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK, + CLKMGR_PERPLL_PLLGLOB); + + /* Take all PLLs out of bypass */ + clk_write_bypass_mainpll(plat, 0); + clk_write_bypass_perpll(plat, 0); + + /* Clear the loss of lock bits (write 1 to clear) */ + CM_REG_CLRBITS(plat, CLKMGR_INTRCLR, + CLKMGR_INTER_PERPLLLOST_MASK | + CLKMGR_INTER_MAINPLLLOST_MASK); + + /* Take all ping pong counters out of reset */ + CM_REG_CLRBITS(plat, CLKMGR_CTL_EXTCNTRST, + CLKMGR_CTL_EXTCNTRST_ALLCNTRST); + +#ifdef COUNTER_FREQUENCY_REAL + u32 cntfrq = COUNTER_FREQUENCY_REAL; + u32 counter_freq = 0; + + /* Update with accurate clock frequency */ + if (current_el() == 3) { + asm volatile("msr cntfrq_el0, %0" : : "r" (cntfrq) : "memory"); + asm volatile("mrs %0, cntfrq_el0" : "=r" (counter_freq)); + debug("Counter freq = 0x%x\n", counter_freq); + } +#endif + + /* Out of boot mode */ + clk_write_ctrl(plat, + CM_REG_READL(plat, CLKMGR_CTRL) & ~CLKMGR_CTRL_BOOTMODE); + } +} + +static u64 clk_get_vco_clk_hz(struct socfpga_clk_plat *plat, + u32 pllglob_reg, u32 pllm_reg) +{ + u64 fref, arefdiv, mdiv, reg, vco; + + reg = CM_REG_READL(plat, pllglob_reg); + + fref = (reg & CLKMGR_PLLGLOB_VCO_PSRC_MASK) >> + CLKMGR_PLLGLOB_VCO_PSRC_OFFSET; + + switch (fref) { + case CLKMGR_VCO_PSRC_EOSC1: + fref = cm_get_osc_clk_hz(); + break; + case CLKMGR_VCO_PSRC_INTOSC: + fref = cm_get_intosc_clk_hz(); + break; + case CLKMGR_VCO_PSRC_F2S: + fref = cm_get_fpga_clk_hz(); + break; + } + + arefdiv = (reg & CLKMGR_PLLGLOB_AREFCLKDIV_MASK) >> + CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET; + + mdiv = CM_REG_READL(plat, pllm_reg) & CLKMGR_PLLM_MDIV_MASK; + + vco = fref / arefdiv; + vco = vco * mdiv; + + return vco; +} + +static u64 clk_get_main_vco_clk_hz(struct socfpga_clk_plat *plat) +{ + return clk_get_vco_clk_hz(plat, CLKMGR_MAINPLL_PLLGLOB, + CLKMGR_MAINPLL_PLLM); +} + +static u64 clk_get_per_vco_clk_hz(struct socfpga_clk_plat *plat) +{ + return clk_get_vco_clk_hz(plat, CLKMGR_PERPLL_PLLGLOB, + CLKMGR_PERPLL_PLLM); +} + +static u32 clk_get_5_1_clk_src(struct socfpga_clk_plat *plat, u64 reg) +{ + u32 clksrc = CM_REG_READL(plat, reg); + + return (clksrc & CLKMGR_CLKSRC_MASK) >> CLKMGR_CLKSRC_OFFSET; +} + +static u64 clk_get_clksrc_hz(struct socfpga_clk_plat *plat, u32 clksrc_reg, + u32 main_reg, u32 per_reg) +{ + u64 clock; + u32 clklsrc = clk_get_5_1_clk_src(plat, clksrc_reg); + + switch (clklsrc) { + case CLKMGR_CLKSRC_MAIN: + clock = clk_get_main_vco_clk_hz(plat); + clock /= (CM_REG_READL(plat, main_reg) & + CLKMGR_CLKCNT_MSK); + break; + + case CLKMGR_CLKSRC_PER: + clock = clk_get_per_vco_clk_hz(plat); + clock /= (CM_REG_READL(plat, per_reg) & + CLKMGR_CLKCNT_MSK); + break; + + case CLKMGR_CLKSRC_OSC1: + clock = cm_get_osc_clk_hz(); + break; + + case CLKMGR_CLKSRC_INTOSC: + clock = cm_get_intosc_clk_hz(); + break; + + case CLKMGR_CLKSRC_FPGA: + clock = cm_get_fpga_clk_hz(); + break; + default: + return 0; + } + + return clock; +} + +static u64 clk_get_mpu_clk_hz(struct socfpga_clk_plat *plat) +{ + u64 clock; + u32 ctr_reg; + u32 cpu = ((read_mpidr() >> MPIDR_AFF1_OFFSET) & MPIDR_AFF1_OFFSET); + + if (cpu > CORE1) { + ctr_reg = CLKMGR_CTL_CORE23CTR; + + clock = clk_get_clksrc_hz(plat, ctr_reg, + CLKMGR_MAINPLL_PLLC0, + CLKMGR_PERPLL_PLLC0); + } else { + ctr_reg = CLKMGR_CTL_CORE01CTR; + + clock = clk_get_clksrc_hz(plat, ctr_reg, + CLKMGR_MAINPLL_PLLC1, + CLKMGR_PERPLL_PLLC0); + } + + if (cpu == CORE3) + ctr_reg = CLKMGR_CTL_CORE3CTR; + else if (cpu == CORE2) + ctr_reg = CLKMGR_CTL_CORE2CTR; + else + ctr_reg = CLKMGR_CTL_CORE01CTR; + + clock /= 1 + (CM_REG_READL(plat, ctr_reg) & + CLKMGR_CLKCNT_MSK); + + return clock; +} + +static u32 clk_get_l3_main_clk_hz(struct socfpga_clk_plat *plat) +{ + return clk_get_clksrc_hz(plat, CLKMGR_MAINPLL_NOCCLK, + CLKMGR_MAINPLL_PLLC3, + CLKMGR_PERPLL_PLLC1); +} + +static u32 clk_get_l4_main_clk_hz(struct socfpga_clk_plat *plat) +{ + u64 clock = clk_get_l3_main_clk_hz(plat); + + return clock; +} + +static u32 clk_get_l4_sp_clk_hz(struct socfpga_clk_plat *plat) +{ + u64 clock = clk_get_l3_main_clk_hz(plat); + + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> + CLKMGR_NOCDIV_L4SPCLK_OFFSET) & + CLKMGR_NOCDIV_DIVIDER_MASK); + + return clock; +} + +static u32 clk_get_l4_mp_clk_hz(struct socfpga_clk_plat *plat) +{ + u64 clock = clk_get_l3_main_clk_hz(plat); + + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> + CLKMGR_NOCDIV_L4MPCLK_OFFSET) & + CLKMGR_NOCDIV_DIVIDER_MASK); + + return clock; +} + +static u32 clk_get_sdmmc_clk_hz(struct socfpga_clk_plat *plat) +{ + u64 clock = clk_get_l4_mp_clk_hz(plat); + + clock /= BIT((CM_REG_READL(plat, CLKMGR_MAINPLL_NOCDIV) >> + CLKMGR_NOCDIV_SOFTPHY_OFFSET) & + CLKMGR_NOCDIV_DIVIDER_MASK); + + return clock; +} + +static u32 clk_get_l4_sys_free_clk_hz(struct socfpga_clk_plat *plat) +{ + if (CM_REG_READL(plat, CLKMGR_STAT) & CLKMGR_STAT_BOOTMODE) + return clk_get_l3_main_clk_hz(plat) / 2; + + return clk_get_l3_main_clk_hz(plat) / 4; +} + +static u32 clk_get_emac_clk_hz(struct socfpga_clk_plat *plat, u32 emac_id) +{ + u32 ctl; + u32 ctr_reg; + u32 clock; + u32 div; + u32 reg; + + if (emac_id == AGILEX5_EMAC_PTP_CLK) { + reg = CM_REG_READL(plat, CLKMGR_CTL_EMACPTPCTR); + ctr_reg = CLKMGR_CTL_EMACPTPCTR; + } else { + reg = CM_REG_READL(plat, CLKMGR_CTL_EMACACTR); + ctl = CM_REG_READL(plat, CLKMGR_PERPLL_EMACCTL); + if (emac_id == AGILEX5_EMAC0_CLK) + ctl = (ctl & CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK) >> + CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET; + else if (emac_id == AGILEX5_EMAC1_CLK) + ctl = (ctl & CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK) >> + CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET; + else if (emac_id == AGILEX5_EMAC2_CLK) + ctl = (ctl & CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK) >> + CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET; + else + return 0; + + if (ctl) { + /* EMAC B source */ + ctr_reg = CLKMGR_CTL_EMACBCTR; + } else { + /* EMAC A source */ + ctr_reg = CLKMGR_CTL_EMACACTR; + } + } + /* Get EMAC clock source */ + clock = (reg & CLKMGR_CTL_EMACCTR_SRC_MASK) + >> CLKMGR_CTL_EMACCTR_SRC_OFFSET; + + reg = CM_REG_READL(plat, ctr_reg); + div = (reg & CLKMGR_CTL_EMACCTR_CNT_MASK) + >> CLKMGR_CTL_EMACCTR_CNT_OFFSET; + + switch (clock) { + case CLKMGR_CLKSRC_MAIN: + clock = clk_get_main_vco_clk_hz(plat); + + if (emac_id == AGILEX5_EMAC_PTP_CLK) { + clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC3) & + CLKMGR_CLKCNT_MSK); + } else { + clock /= (CM_REG_READL(plat, CLKMGR_MAINPLL_PLLC1) & + CLKMGR_CLKCNT_MSK); + } + break; + + case CLKMGR_CLKSRC_PER: + clock = clk_get_per_vco_clk_hz(plat); + + clock /= (CM_REG_READL(plat, CLKMGR_PERPLL_PLLC3) & + CLKMGR_CLKCNT_MSK); + break; + + case CLKMGR_CLKSRC_OSC1: + clock = cm_get_osc_clk_hz(); + break; + + case CLKMGR_CLKSRC_INTOSC: + clock = cm_get_intosc_clk_hz(); + break; + + case CLKMGR_CLKSRC_FPGA: + clock = cm_get_fpga_clk_hz(); + break; + } + + clock /= 1 + div; + + return clock; +} + +static ulong socfpga_clk_get_rate(struct clk *clk) +{ + struct socfpga_clk_plat *plat = dev_get_plat(clk->dev); + + switch (clk->id) { + case AGILEX5_MPU_CLK: + return clk_get_mpu_clk_hz(plat); + case AGILEX5_L4_MAIN_CLK: + return clk_get_l4_main_clk_hz(plat); + case AGILEX5_L4_SYS_FREE_CLK: + return clk_get_l4_sys_free_clk_hz(plat); + case AGILEX5_L4_MP_CLK: + return clk_get_l4_mp_clk_hz(plat); + case AGILEX5_L4_SP_CLK: + return clk_get_l4_sp_clk_hz(plat); + case AGILEX5_SDMMC_CLK: + case AGILEX5_NAND_CLK: + return clk_get_sdmmc_clk_hz(plat); + case AGILEX5_EMAC0_CLK: + case AGILEX5_EMAC1_CLK: + case AGILEX5_EMAC2_CLK: + case AGILEX5_EMAC_PTP_CLK: + return clk_get_emac_clk_hz(plat, clk->id); + case AGILEX5_USB_CLK: + case AGILEX5_NAND_X_CLK: + return clk_get_l4_mp_clk_hz(plat); + default: + return -ENXIO; + } +} + +static int socfpga_clk_enable(struct clk *clk) +{ + return 0; +} + +static int socfpga_clk_probe(struct udevice *dev) +{ + const struct cm_config *cm_default_cfg = cm_get_default_config(); + + clk_basic_init(dev, cm_default_cfg); + + return 0; +} + +static int socfpga_clk_of_to_plat(struct udevice *dev) +{ + struct socfpga_clk_plat *plat = dev_get_plat(dev); + fdt_addr_t addr; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + plat->regs = (void __iomem *)addr; + + return 0; +} + +static struct clk_ops socfpga_clk_ops = { + .enable = socfpga_clk_enable, + .get_rate = socfpga_clk_get_rate, +}; + +static const struct udevice_id socfpga_clk_match[] = { + { .compatible = "intel,agilex5-clkmgr" }, + {} +}; + +U_BOOT_DRIVER(socfpga_agilex5_clk) = { + .name = "clk-agilex5", + .id = UCLASS_CLK, + .of_match = socfpga_clk_match, + .ops = &socfpga_clk_ops, + .probe = socfpga_clk_probe, + .of_to_plat = socfpga_clk_of_to_plat, + .plat_auto = sizeof(struct socfpga_clk_plat), +}; diff --git a/drivers/clk/altera/clk-agilex5.h b/drivers/clk/altera/clk-agilex5.h new file mode 100644 index 0000000..a4ddc1a --- /dev/null +++ b/drivers/clk/altera/clk-agilex5.h @@ -0,0 +1,284 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2024 Intel Corporation <www.intel.com> + */ + +#ifndef _CLK_AGILEX5_ +#define _CLK_AGILEX5_ + +#ifndef __ASSEMBLY__ +#include <linux/bitops.h> +#endif + +#define CORE0 1 +#define CORE1 2 +#define CORE2 3 +#define CORE3 4 + +/* Derived from l4_main_clk (PSS clock) */ +#define COUNTER_FREQUENCY_REAL 400000000 + +#define CM_REG_READL(plat, reg) \ + readl((plat)->regs + (reg)) + +#define CM_REG_WRITEL(plat, data, reg) \ + writel(data, (plat)->regs + (reg)) + +#define CM_REG_CLRBITS(plat, reg, clear) \ + clrbits_le32((plat)->regs + (reg), (clear)) + +#define CM_REG_SETBITS(plat, reg, set) \ + setbits_le32((plat)->regs + (reg), (set)) + +struct cm_config { + /* main group */ + u32 main_pll_nocclk; + u32 main_pll_nocdiv; + u32 main_pll_pllglob; + u32 main_pll_fdbck; + u32 main_pll_pllc0; + u32 main_pll_pllc1; + u32 main_pll_pllc2; + u32 main_pll_pllc3; + u32 main_pll_pllm; + + /* peripheral group */ + u32 per_pll_emacctl; + u32 per_pll_gpiodiv; + u32 per_pll_pllglob; + u32 per_pll_fdbck; + u32 per_pll_pllc0; + u32 per_pll_pllc1; + u32 per_pll_pllc2; + u32 per_pll_pllc3; + u32 per_pll_pllm; + + /* control group */ + u32 ctl_emacactr; + u32 ctl_emacbctr; + u32 ctl_emacptpctr; + u32 ctl_gpiodbctr; + u32 ctl_s2fuser0ctr; + u32 ctl_s2fuser1ctr; + u32 ctl_psirefctr; + u32 ctl_usb31ctr; + u32 ctl_dsuctr; + u32 ctl_core01ctr; + u32 ctl_core23ctr; + u32 ctl_core2ctr; + u32 ctl_core3ctr; + + /* incoming clock */ + u32 hps_osc_clk_hz; + u32 fpga_clk_hz; + u32 spare[3]; +}; + +/* Clock Manager registers */ +#define CLKMGR_CTRL 0 +#define CLKMGR_STAT 4 +#define CLKMGR_TESTIOCTRL 8 +#define CLKMGR_INTRGEN 0x0c +#define CLKMGR_INTRMSK 0x10 +#define CLKMGR_INTRCLR 0x14 +#define CLKMGR_INTRSTS 0x18 +#define CLKMGR_INTRSTK 0x1c +#define CLKMGR_INTRRAW 0x20 + +/* Clock Manager Main PPL group registers */ +#define CLKMGR_MAINPLL_EN 0x24 +#define CLKMGR_MAINPLL_ENS 0x28 +#define CLKMGR_MAINPLL_ENR 0x2c +#define CLKMGR_MAINPLL_BYPASS 0x30 +#define CLKMGR_MAINPLL_BYPASSS 0x34 +#define CLKMGR_MAINPLL_BYPASSR 0x38 +#define CLKMGR_MAINPLL_NOCCLK 0x40 +#define CLKMGR_MAINPLL_NOCDIV 0x44 +#define CLKMGR_MAINPLL_PLLGLOB 0x48 +#define CLKMGR_MAINPLL_FDBCK 0x4c +#define CLKMGR_MAINPLL_MEM 0x50 +#define CLKMGR_MAINPLL_MEMSTAT 0x54 +#define CLKMGR_MAINPLL_VCOCALIB 0x58 +#define CLKMGR_MAINPLL_PLLC0 0x5c +#define CLKMGR_MAINPLL_PLLC1 0x60 +#define CLKMGR_MAINPLL_PLLC2 0x64 +#define CLKMGR_MAINPLL_PLLC3 0x68 +#define CLKMGR_MAINPLL_PLLM 0x6c +#define CLKMGR_MAINPLL_FHOP 0x70 +#define CLKMGR_MAINPLL_SSC 0x74 +#define CLKMGR_MAINPLL_LOSTLOCK 0x78 + +/* Clock Manager Peripheral PPL group registers */ +#define CLKMGR_PERPLL_EN 0x7c +#define CLKMGR_PERPLL_ENS 0x80 +#define CLKMGR_PERPLL_ENR 0x84 +#define CLKMGR_PERPLL_BYPASS 0x88 +#define CLKMGR_PERPLL_BYPASSS 0x8c +#define CLKMGR_PERPLL_BYPASSR 0x90 +#define CLKMGR_PERPLL_EMACCTL 0x94 +#define CLKMGR_PERPLL_GPIODIV 0x98 +#define CLKMGR_PERPLL_PLLGLOB 0x9c +#define CLKMGR_PERPLL_FDBCK 0xa0 +#define CLKMGR_PERPLL_MEM 0xa4 +#define CLKMGR_PERPLL_MEMSTAT 0xa8 +#define CLKMGR_PERPLL_VCOCALIB 0xac +#define CLKMGR_PERPLL_PLLC0 0xb0 +#define CLKMGR_PERPLL_PLLC1 0xb4 +#define CLKMGR_PERPLL_PLLC2 0xb8 +#define CLKMGR_PERPLL_PLLC3 0xbc +#define CLKMGR_PERPLL_PLLM 0xc0 +#define CLKMGR_PERPLL_FHOP 0xc4 +#define CLKMGR_PERPLL_SSC 0xc8 +#define CLKMGR_PERPLL_LOSTLOCK 0xcc + +/* Clock Manager Control group registers */ +#define CLKMGR_CTL_JTAG 0xd0 +#define CLKMGR_CTL_EMACACTR 0xd4 +#define CLKMGR_CTL_EMACBCTR 0xd8 +#define CLKMGR_CTL_EMACPTPCTR 0xdc +#define CLKMGR_CTL_GPIODBCTR 0xe0 +#define CLKMGR_CTL_S2FUSER0CTR 0xe8 +#define CLKMGR_CTL_S2FUSER1CTR 0xec +#define CLKMGR_CTL_PSIREFCTR 0xf0 +#define CLKMGR_CTL_EXTCNTRST 0xf4 +#define CLKMGR_CTL_USB31CTR 0xf8 +#define CLKMGR_CTL_DSUCTR 0xfc +#define CLKMGR_CTL_CORE01CTR 0x100 +#define CLKMGR_CTL_CORE23CTR 0x104 +#define CLKMGR_CTL_CORE2CTR 0x108 +#define CLKMGR_CTL_CORE3CTR 0x10C + +#define CLKMGR_CTRL_BOOTMODE BIT(0) + +#define CLKMGR_STAT_BUSY BIT(0) +#define CLKMGR_STAT_MAINPLL_LOCKED BIT(8) +#define CLKMGR_STAT_MAIN_TRANS BIT(9) +#define CLKMGR_STAT_PERPLL_LOCKED BIT(16) +#define CLKMGR_STAT_PERF_TRANS BIT(17) +#define CLKMGR_STAT_BOOTMODE BIT(24) +#define CLKMGR_STAT_BOOTCLKSRC BIT(25) + +#define CLKMGR_STAT_ALLPLL_LOCKED_MASK \ + (CLKMGR_STAT_MAINPLL_LOCKED | CLKMGR_STAT_PERPLL_LOCKED) + +#define CLKMGR_INTER_MAINPLLLOCKED_MASK 0x00000001 +#define CLKMGR_INTER_PERPLLLOCKED_MASK 0x00000002 +#define CLKMGR_INTER_MAINPLLLOST_MASK 0x00000004 +#define CLKMGR_INTER_PERPLLLOST_MASK 0x00000008 + +#define CLKMGR_CLKSRC_MASK GENMASK(18, 16) +#define CLKMGR_CLKSRC_OFFSET 16 +#define CLKMGR_CLKSRC_MAIN 0 +#define CLKMGR_CLKSRC_PER 1 +#define CLKMGR_CLKSRC_OSC1 2 +#define CLKMGR_CLKSRC_INTOSC 3 +#define CLKMGR_CLKSRC_FPGA 4 +#define CLKMGR_CLKCNT_MSK GENMASK(10, 0) + +#define CLKMGR_BYPASS_MAINPLL_ALL 0xf6 +#define CLKMGR_BYPASS_PERPLL_ALL 0xef + +#define CLKMGR_NOCDIV_SOFTPHY_DIV_ONE 0 +#define CLKMGR_NOCDIV_SOFTPHY_DIV_TWO 1 +#define CLKMGR_NOCDIV_SOFTPHY_DIV_FOUR 2 +#define CLKMGR_NOCDIV_L4SYSFREECLK_OFFSET 0 +#define CLKMGR_NOCDIV_L4MPCLK_OFFSET 4 +#define CLKMGR_NOCDIV_L4SPCLK_OFFSET 6 +#define CLKMGR_NOCDIV_SOFTPHY_OFFSET 16 +#define CLKMGR_NOCDIV_CCU_OFFSET 18 +#define CLKMGR_NOCDIV_MPUPERIPH_OFFSET 20 +#define CLKMGR_NOCDIV_CSATCLK_OFFSET 24 +#define CLKMGR_NOCDIV_CSTRACECLK_OFFSET 26 +#define CLKMGR_NOCDIV_CSPDBGCLK_OFFSET 28 +#define CLKMGR_NOCDIV_DIVIDER_MASK 0x3 + +#define CLKMGR_PLLGLOB_PD_MASK BIT(0) +#define CLKMGR_PLLGLOB_RST_MASK BIT(1) +#define CLKMGR_PLLGLOB_AREFCLKDIV_MASK GENMASK(11, 8) +#define CLKMGR_PLLGLOB_DREFCLKDIV_MASK GENMASK(13, 12) +#define CLKMGR_PLLGLOB_REFCLKDIV_MASK GENMASK(13, 8) +#define CLKMGR_PLLGLOB_MODCLKDIV_MASK GENMASK(24, 27) +#define CLKMGR_PLLGLOB_AREFCLKDIV_OFFSET 8 +#define CLKMGR_PLLGLOB_DREFCLKDIV_OFFSET 12 +#define CLKMGR_PLLGLOB_REFCLKDIV_OFFSET 8 +#define CLKMGR_PLLGLOB_MODCLKDIV_OFFSET 24 +#define CLKMGR_PLLGLOB_VCO_PSRC_MASK GENMASK(17, 16) +#define CLKMGR_PLLGLOB_VCO_PSRC_OFFSET 16 +#define CLKMGR_PLLGLOB_CLR_LOSTLOCK_BYPASS_MASK BIT(29) + +#define CLKMGR_VCO_PSRC_EOSC1 0 +#define CLKMGR_VCO_PSRC_INTOSC 1 +#define CLKMGR_VCO_PSRC_F2S 2 + +#define CLKMGR_MEM_REQ_SET_MSK BIT(24) +#define CLKMGR_MEM_WR_SET_MSK BIT(25) +#define CLKMGR_MEM_ERR_MSK BIT(26) +#define CLKMGR_MEM_WDAT_LSB_OFFSET 16 +#define CLKMGR_MEM_ADDR_MASK GENMASK(15, 0) +#define CLKMGR_MEM_ADDR_START 0x00004000 + +#define CLKMGR_PLLCX_EN_SET_MSK BIT(27) +#define CLKMGR_PLLCX_MUTE_SET_MSK BIT(28) + +#define CLKMGR_VCOCALIB_MSCNT_MASK GENMASK(23, 16) +#define CLKMGR_VCOCALIB_MSCNT_OFFSET 16 +#define CLKMGR_VCOCALIB_HSCNT_MASK GENMASK(9, 0) +#define CLKMGR_VCOCALIB_MSCNT_CONST 100 +#define CLKMGR_VCOCALIB_HSCNT_CONST 4 + +#define CLKMGR_PLLM_MDIV_MASK GENMASK(9, 0) + +#define CLKMGR_LOSTLOCK_SET_MASK BIT(0) + +#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK BIT(5) +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_OFFSET 26 +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC0SELB_MASK BIT(26) +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_OFFSET 27 +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC1SELB_MASK BIT(27) +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_OFFSET 28 +#define CLKMGR_PERPLLGRP_EMACCTL_EMAC2SELB_MASK BIT(28) + +#define CLKMGR_CTL_EMACCTR_SRC_OFFSET 16 +#define CLKMGR_CTL_EMACCTR_SRC_MASK GENMASK(18, 16) +#define CLKMGR_CTL_EMACCTR_CNT_OFFSET 0 +#define CLKMGR_CTL_EMACCTR_CNT_MASK GENMASK(10, 0) + +#define CLKMGR_CTL_EXTCNTRST_EMACACNTRST BIT(0) +#define CLKMGR_CTL_EXTCNTRST_EMACBCNTRST BIT(1) +#define CLKMGR_CTL_EXTCNTRST_EMACPTPCNTRST BIT(2) +#define CLKMGR_CTL_EXTCNTRST_GPIODBCNTRST BIT(3) +#define CLKMGR_CTL_EXTCNTRST_S2FUSER0CNTRST BIT(5) +#define CLKMGR_CTL_EXTCNTRST_S2FUSER1CNTRST BIT(6) +#define CLKMGR_CTL_EXTCNTRST_PSIREFCNTRST BIT(7) +#define CLKMGR_CTL_EXTCNTRST_USB31REFCNTRST BIT(8) +#define CLKMGR_CTL_EXTCNTRST_DSUCNTRST BIT(10) +#define CLKMGR_CTL_EXTCNTRST_CORE01CNTRST BIT(11) +#define CLKMGR_CTL_EXTCNTRST_CORE2CNTRST BIT(12) +#define CLKMGR_CTL_EXTCNTRST_CORE3CNTRST BIT(13) +#define CLKMGR_CTL_EXTCNTRST_ALLCNTRST \ + (CLKMGR_CTL_EXTCNTRST_EMACACNTRST | \ + CLKMGR_CTL_EXTCNTRST_EMACBCNTRST | \ + CLKMGR_CTL_EXTCNTRST_EMACPTPCNTRST | \ + CLKMGR_CTL_EXTCNTRST_GPIODBCNTRST | \ + CLKMGR_CTL_EXTCNTRST_S2FUSER0CNTRST | \ + CLKMGR_CTL_EXTCNTRST_S2FUSER1CNTRST | \ + CLKMGR_CTL_EXTCNTRST_PSIREFCNTRST | \ + CLKMGR_CTL_EXTCNTRST_USB31REFCNTRST | \ + CLKMGR_CTL_EXTCNTRST_DSUCNTRST | \ + CLKMGR_CTL_EXTCNTRST_CORE01CNTRST | \ + CLKMGR_CTL_EXTCNTRST_CORE2CNTRST | \ + CLKMGR_CTL_EXTCNTRST_CORE3CNTRST) + +#define MEMBUS_MAINPLL 0 +#define MEMBUS_PERPLL 1 +#define MEMBUS_TIMEOUT 1000 + +#define MEMBUS_CLKSLICE_REG 0x27 +#define MEMBUS_SYNTHCALFOSC_INIT_CENTERFREQ_REG 0xb3 +#define MEMBUS_SYNTHPPM_WATCHDOGTMR_VF01_REG 0xe6 +#define MEMBUS_CALCLKSLICE0_DUTY_LOCOVR_REG 0x03 +#define MEMBUS_CALCLKSLICE1_DUTY_LOCOVR_REG 0x07 + +#define MPIDR_AFF1_OFFSET 8 +#define MPIDR_AFF1_MASK 0x3 +#endif /* _CLK_AGILEX5_ */ diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index a21a3ce..7dfc829 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -62,6 +62,10 @@ static const char *imx8mp_dram_apb_sels[] = {"clock-osc-24m", "sys_pll2_200m", " "sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", }; +static const char * const imx8mp_pcie_aux_sels[] = {"clock-osc-24m", "sys_pll2_200m", "sys_pll2_50m", + "sys_pll3_out", "sys_pll2_100m", "sys_pll1_80m", + "sys_pll1_160m", "sys_pll1_200m", }; + static const char *imx8mp_i2c5_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", }; @@ -272,6 +276,7 @@ static int imx8mp_clk_probe(struct udevice *dev) clk_dm(IMX8MP_CLK_DRAM_ALT, imx8m_clk_composite("dram_alt", imx8mp_dram_alt_sels, base + 0xa000)); clk_dm(IMX8MP_CLK_DRAM_APB, imx8m_clk_composite_critical("dram_apb", imx8mp_dram_apb_sels, base + 0xa080)); + clk_dm(IMX8MP_CLK_PCIE_AUX, imx8m_clk_composite("pcie_aux", imx8mp_pcie_aux_sels, base + 0xa400)); clk_dm(IMX8MP_CLK_I2C5, imx8m_clk_composite("i2c5", imx8mp_i2c5_sels, base + 0xa480)); clk_dm(IMX8MP_CLK_I2C6, imx8m_clk_composite("i2c6", imx8mp_i2c6_sels, base + 0xa500)); clk_dm(IMX8MP_CLK_ENET_QOS, imx8m_clk_composite("enet_qos", imx8mp_enet_qos_sels, base + 0xa880)); @@ -322,6 +327,7 @@ static int imx8mp_clk_probe(struct udevice *dev) clk_dm(IMX8MP_CLK_I2C2_ROOT, imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0)); clk_dm(IMX8MP_CLK_I2C3_ROOT, imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0)); clk_dm(IMX8MP_CLK_I2C4_ROOT, imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0)); + clk_dm(IMX8MP_CLK_PCIE_ROOT, imx_clk_gate4("pcie_root_clk", "pcie_aux", base + 0x4250, 0)); clk_dm(IMX8MP_CLK_PWM1_ROOT, imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0)); clk_dm(IMX8MP_CLK_PWM2_ROOT, imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0)); clk_dm(IMX8MP_CLK_PWM3_ROOT, imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0)); diff --git a/drivers/clk/qcom/clock-apq8016.c b/drivers/clk/qcom/clock-apq8016.c index c0ce570..e6647f7 100644 --- a/drivers/clk/qcom/clock-apq8016.c +++ b/drivers/clk/qcom/clock-apq8016.c @@ -13,6 +13,7 @@ #include <errno.h> #include <asm/io.h> #include <linux/bitops.h> +#include <dt-bindings/clock/qcom,gcc-msm8916.h> #include "clock-qcom.h" @@ -102,20 +103,20 @@ static const struct bcr_regs uart2_regs = { }; /* UART: 115200 */ -static int clk_init_uart(struct msm_clk_priv *priv) +int apq8016_clk_init_uart(phys_addr_t base) { /* Enable AHB clock */ - clk_enable_vote_clk(priv->base, &gcc_blsp1_ahb_clk); + clk_enable_vote_clk(base, &gcc_blsp1_ahb_clk); /* 7372800 uart block clock @ GPLL0 */ - clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 1, 144, 15625, + clk_rcg_set_rate_mnd(base, &uart2_regs, 1, 144, 15625, CFG_CLK_SRC_GPLL0, 16); /* Vote for gpll0 clock */ - clk_enable_gpll0(priv->base, &gpll0_vote_clk); + clk_enable_gpll0(base, &gpll0_vote_clk); /* Enable core clk */ - clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR); + clk_enable_cbc(base + BLSP1_UART2_APPS_CBCR); return 0; } @@ -125,14 +126,14 @@ static ulong apq8016_clk_set_rate(struct clk *clk, ulong rate) struct msm_clk_priv *priv = dev_get_priv(clk->dev); switch (clk->id) { - case 0: /* SDC1 */ + case GCC_SDCC1_APPS_CLK: /* SDC1 */ return clk_init_sdc(priv, 0, rate); break; - case 1: /* SDC2 */ + case GCC_SDCC2_APPS_CLK: /* SDC2 */ return clk_init_sdc(priv, 1, rate); break; - case 4: /* UART2 */ - return clk_init_uart(priv); + case GCC_BLSP1_UART2_APPS_CLK: /* UART2 */ + return apq8016_clk_init_uart(priv->base); break; default: return 0; @@ -145,7 +146,7 @@ static struct msm_clk_data apq8016_clk_data = { static const struct udevice_id gcc_apq8016_of_match[] = { { - .compatible = "qcom,gcc-apq8016", + .compatible = "qcom,gcc-msm8916", .data = (ulong)&apq8016_clk_data, }, { } diff --git a/drivers/clk/qcom/clock-apq8096.c b/drivers/clk/qcom/clock-apq8096.c index cf1a347..a473161 100644 --- a/drivers/clk/qcom/clock-apq8096.c +++ b/drivers/clk/qcom/clock-apq8096.c @@ -13,6 +13,7 @@ #include <errno.h> #include <asm/io.h> #include <linux/bitops.h> +#include <dt-bindings/clock/qcom,gcc-msm8996.h> #include "clock-qcom.h" @@ -107,10 +108,10 @@ static ulong apq8096_clk_set_rate(struct clk *clk, ulong rate) struct msm_clk_priv *priv = dev_get_priv(clk->dev); switch (clk->id) { - case 0: /* SDC1 */ + case GCC_SDCC1_APPS_CLK: /* SDC1 */ return clk_init_sdc(priv, rate); break; - case 4: /*UART2*/ + case GCC_BLSP2_UART2_APPS_CLK: /*UART2*/ return clk_init_uart(priv); default: return 0; @@ -123,7 +124,7 @@ static struct msm_clk_data apq8096_clk_data = { static const struct udevice_id gcc_apq8096_of_match[] = { { - .compatible = "qcom,gcc-apq8096", + .compatible = "qcom,gcc-msm8996", .data = (ulong)&apq8096_clk_data, }, { } diff --git a/drivers/clk/qcom/clock-qcs404.c b/drivers/clk/qcom/clock-qcs404.c index f5b3528..958312b 100644 --- a/drivers/clk/qcom/clock-qcs404.c +++ b/drivers/clk/qcom/clock-qcs404.c @@ -193,24 +193,18 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) switch (clk->id) { case GCC_BLSP1_UART2_APPS_CLK: - /* UART: 115200 */ + /* UART: 1843200Hz for a fixed 115200 baudrate (19200000 * (12/125)) */ clk_rcg_set_rate_mnd(priv->base, &uart2_regs, 0, 12, 125, CFG_CLK_SRC_CXO, 16); clk_enable_cbc(priv->base + BLSP1_UART2_APPS_CBCR); - break; - case GCC_BLSP1_AHB_CLK: - clk_enable_vote_clk(priv->base, &gcc_blsp1_ahb_clk); - break; + return 1843200; case GCC_SDCC1_APPS_CLK: /* SDCC1: 200MHz */ clk_rcg_set_rate_mnd(priv->base, &sdc_regs, 7, 0, 0, CFG_CLK_SRC_GPLL0, 8); clk_enable_gpll0(priv->base, &gpll0_vote_clk); clk_enable_cbc(priv->base + SDCC_APPS_CBCR(1)); - break; - case GCC_SDCC1_AHB_CLK: - clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1)); - break; + return rate; case GCC_ETH_RGMII_CLK: if (rate == 250000000) clk_rcg_set_rate_mnd(priv->base, &emac_regs, 3, 0, 0, @@ -224,11 +218,15 @@ static ulong qcs404_clk_set_rate(struct clk *clk, ulong rate) else if (rate == 5000000) clk_rcg_set_rate_mnd(priv->base, &emac_regs, 3, 1, 50, CFG_CLK_SRC_GPLL1, 8); - break; - default: - return 0; + return rate; } + /* There is a bug only seeming to affect this board where the MMC driver somehow calls + * clk_set_rate() on a clock with id 0 which is associated with the qcom_clk device. + * The only clock with ID 0 is the xo_board clock which should not be associated with + * this device... + */ + log_debug("Unknown clock id %ld\n", clk->id); return 0; } @@ -305,6 +303,9 @@ static int qcs404_clk_enable(struct clk *clk) clk_rcg_set_rate(priv->base, &blsp1_qup4_i2c_apps_regs, 0, CFG_CLK_SRC_CXO); break; + case GCC_SDCC1_AHB_CLK: + clk_enable_cbc(priv->base + SDCC_AHB_CBCR(1)); + break; default: return 0; } diff --git a/drivers/clk/rockchip/clk_pll.c b/drivers/clk/rockchip/clk_pll.c index 1bb31b3..66f8bb1 100644 --- a/drivers/clk/rockchip/clk_pll.c +++ b/drivers/clk/rockchip/clk_pll.c @@ -8,7 +8,6 @@ #include <dm.h> #include <errno.h> #include <log.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> #include <div64.h> diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c index 93b7653..2875c15 100644 --- a/drivers/clk/rockchip/clk_px30.c +++ b/drivers/clk/rockchip/clk_px30.c @@ -15,7 +15,6 @@ #include <asm/arch-rockchip/cru_px30.h> #include <asm/arch-rockchip/hardware.h> #include <asm/global_data.h> -#include <asm/io.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dt-bindings/clock/px30-cru.h> diff --git a/drivers/clk/rockchip/clk_rk3036.c b/drivers/clk/rockchip/clk_rk3036.c index 6bc6d41..6238b14 100644 --- a/drivers/clk/rockchip/clk_rk3036.c +++ b/drivers/clk/rockchip/clk_rk3036.c @@ -10,7 +10,6 @@ #include <log.h> #include <malloc.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3036.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/clk/rockchip/clk_rk3066.c b/drivers/clk/rockchip/clk_rk3066.c index 2c12f6e..f83335d 100644 --- a/drivers/clk/rockchip/clk_rk3066.c +++ b/drivers/clk/rockchip/clk_rk3066.c @@ -14,7 +14,6 @@ #include <malloc.h> #include <mapmem.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3066.h> #include <asm/arch-rockchip/grf_rk3066.h> diff --git a/drivers/clk/rockchip/clk_rk3128.c b/drivers/clk/rockchip/clk_rk3128.c index 13e176c..182754e 100644 --- a/drivers/clk/rockchip/clk_rk3128.c +++ b/drivers/clk/rockchip/clk_rk3128.c @@ -10,7 +10,6 @@ #include <log.h> #include <malloc.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3128.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/clk/rockchip/clk_rk3188.c b/drivers/clk/rockchip/clk_rk3188.c index ebdd1b3..f98b46a 100644 --- a/drivers/clk/rockchip/clk_rk3188.c +++ b/drivers/clk/rockchip/clk_rk3188.c @@ -13,7 +13,6 @@ #include <malloc.h> #include <mapmem.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3188.h> #include <asm/arch-rockchip/grf_rk3188.h> diff --git a/drivers/clk/rockchip/clk_rk322x.c b/drivers/clk/rockchip/clk_rk322x.c index 28cdba7..9371c4f 100644 --- a/drivers/clk/rockchip/clk_rk322x.c +++ b/drivers/clk/rockchip/clk_rk322x.c @@ -10,7 +10,6 @@ #include <log.h> #include <malloc.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk322x.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c index e24c32c..0b7eefa 100644 --- a/drivers/clk/rockchip/clk_rk3288.c +++ b/drivers/clk/rockchip/clk_rk3288.c @@ -15,7 +15,6 @@ #include <mapmem.h> #include <syscon.h> #include <asm/global_data.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru.h> #include <asm/arch-rockchip/grf_rk3288.h> diff --git a/drivers/clk/rockchip/clk_rk3308.c b/drivers/clk/rockchip/clk_rk3308.c index d0a3f65..7755b01 100644 --- a/drivers/clk/rockchip/clk_rk3308.c +++ b/drivers/clk/rockchip/clk_rk3308.c @@ -12,7 +12,6 @@ #include <malloc.h> #include <syscon.h> #include <asm/global_data.h> -#include <asm/io.h> #include <asm/arch/cru_rk3308.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c index ef97381..cfec1d9 100644 --- a/drivers/clk/rockchip/clk_rk3328.c +++ b/drivers/clk/rockchip/clk_rk3328.c @@ -15,7 +15,6 @@ #include <asm/arch-rockchip/cru_rk3328.h> #include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/grf_rk3328.h> -#include <asm/io.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dt-bindings/clock/rk3328-cru.h> diff --git a/drivers/clk/rockchip/clk_rk3368.c b/drivers/clk/rockchip/clk_rk3368.c index 3406ff5..1c5dfaa 100644 --- a/drivers/clk/rockchip/clk_rk3368.c +++ b/drivers/clk/rockchip/clk_rk3368.c @@ -18,7 +18,6 @@ #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3368.h> #include <asm/arch-rockchip/hardware.h> -#include <asm/io.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dt-bindings/clock/rk3368-cru.h> diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index c37e8a5..80f65a2 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/drivers/clk/rockchip/clk_rk3399.c @@ -14,7 +14,6 @@ #include <mapmem.h> #include <syscon.h> #include <bitfield.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c index 68f5bbb..57ef27d 100644 --- a/drivers/clk/rockchip/clk_rk3568.c +++ b/drivers/clk/rockchip/clk_rk3568.c @@ -13,7 +13,6 @@ #include <asm/arch-rockchip/cru_rk3568.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> -#include <asm/io.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dt-bindings/clock/rk3568-cru.h> diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c index a995dd5..8f33843 100644 --- a/drivers/clk/rockchip/clk_rk3588.c +++ b/drivers/clk/rockchip/clk_rk3588.c @@ -14,7 +14,6 @@ #include <asm/arch-rockchip/cru_rk3588.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> -#include <asm/io.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dt-bindings/clock/rockchip,rk3588-cru.h> diff --git a/drivers/clk/rockchip/clk_rv1108.c b/drivers/clk/rockchip/clk_rv1108.c index b0c889a..fc442f7 100644 --- a/drivers/clk/rockchip/clk_rv1108.c +++ b/drivers/clk/rockchip/clk_rv1108.c @@ -13,7 +13,6 @@ #include <malloc.h> #include <syscon.h> #include <asm/global_data.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rv1108.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/clk/rockchip/clk_rv1126.c b/drivers/clk/rockchip/clk_rv1126.c index 580c0b1..cfdfcbd 100644 --- a/drivers/clk/rockchip/clk_rv1126.c +++ b/drivers/clk/rockchip/clk_rv1126.c @@ -16,7 +16,6 @@ #include <asm/arch-rockchip/grf_rv1126.h> #include <asm/arch-rockchip/hardware.h> #include <dm/device-internal.h> -#include <asm/io.h> #include <dm/lists.h> #include <dt-bindings/clock/rockchip,rv1126-cru.h> diff --git a/drivers/clk/ti/clk-k3.c b/drivers/clk/ti/clk-k3.c index eb76195..7aa162c 100644 --- a/drivers/clk/ti/clk-k3.c +++ b/drivers/clk/ti/clk-k3.c @@ -87,6 +87,18 @@ static const struct soc_attr ti_k3_soc_clk_data[] = { .data = &am62ax_clk_platdata, }, #endif +#ifdef CONFIG_SOC_K3_J784S4 + { + .family = "J784S4", + .data = &j784s4_clk_platdata, + }, +#endif +#ifdef CONFIG_SOC_K3_AM62P5 + { + .family = "AM62PX", + .data = &am62px_clk_platdata, + }, +#endif { /* sentinel */ } }; diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index 8e774d4..5f27d25 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -23,7 +23,7 @@ fdt_addr_t devfdt_get_addr_index(const struct udevice *dev, int index) { #if CONFIG_IS_ENABLED(OF_REAL) int offset = dev_of_offset(dev); - int parent = dev_of_offset(dev->parent); + int parent = fdt_parent_offset(gd->fdt_blob, offset); fdt_addr_t addr; if (CONFIG_IS_ENABLED(OF_TRANSLATE)) { diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile index f4e0271..94ec13b 100644 --- a/drivers/dma/ti/Makefile +++ b/drivers/dma/ti/Makefile @@ -9,3 +9,6 @@ k3-psil-data-$(CONFIG_SOC_K3_J721S2) += k3-psil-j721s2.o k3-psil-data-$(CONFIG_SOC_K3_AM642) += k3-psil-am64.o k3-psil-data-$(CONFIG_SOC_K3_AM625) += k3-psil-am62.o k3-psil-data-$(CONFIG_SOC_K3_AM62A7) += k3-psil-am62a.o +k3-psil-data-$(CONFIG_SOC_K3_J784S4) += k3-psil-j784s4.o +k3-psil-data-$(CONFIG_SOC_K3_AM62P5) += k3-psil-am62p.o +k3-psil-data-$(CONFIG_SOC_K3_J722S) += k3-psil-am62p.o diff --git a/drivers/dma/ti/k3-psil-am62p.c b/drivers/dma/ti/k3-psil-am62p.c new file mode 100644 index 0000000..8739bf4 --- /dev/null +++ b/drivers/dma/ti/k3-psil-am62p.c @@ -0,0 +1,325 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com + */ + +#include <linux/kernel.h> + +#include "k3-psil-priv.h" + +#define PSIL_PDMA_XY_TR(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .mapped_channel_id = -1, \ + .default_flow_id = -1, \ + }, \ + } + +#define PSIL_PDMA_XY_PKT(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .mapped_channel_id = -1, \ + .default_flow_id = -1, \ + .pkt_mode = 1, \ + }, \ + } + +#define PSIL_ETHERNET(x, ch, flow_base, flow_cnt) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 16, \ + .mapped_channel_id = ch, \ + .flow_start = flow_base, \ + .flow_num = flow_cnt, \ + .default_flow_id = flow_base, \ + }, \ + } + +#define PSIL_SAUL(x, ch, flow_base, flow_cnt, default_flow, tx) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 64, \ + .mapped_channel_id = ch, \ + .flow_start = flow_base, \ + .flow_num = flow_cnt, \ + .default_flow_id = default_flow, \ + .notdpkt = tx, \ + }, \ + } + +#define PSIL_PDMA_MCASP(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .pdma_acc32 = 1, \ + .pdma_burst = 1, \ + }, \ + } + +#define PSIL_CSI2RX(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + }, \ + } + +/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ +static struct psil_ep am62p_src_ep_map[] = { + /* SAUL */ + PSIL_SAUL(0x7504, 20, 35, 8, 35, 0), + PSIL_SAUL(0x7505, 21, 35, 8, 36, 0), + PSIL_SAUL(0x7506, 22, 43, 8, 43, 0), + PSIL_SAUL(0x7507, 23, 43, 8, 44, 0), + /* PDMA_MAIN0 - SPI0-3 */ + PSIL_PDMA_XY_PKT(0x4302), + PSIL_PDMA_XY_PKT(0x4303), + PSIL_PDMA_XY_PKT(0x4304), + PSIL_PDMA_XY_PKT(0x4305), + PSIL_PDMA_XY_PKT(0x4306), + PSIL_PDMA_XY_PKT(0x4307), + PSIL_PDMA_XY_PKT(0x4308), + PSIL_PDMA_XY_PKT(0x4309), + PSIL_PDMA_XY_PKT(0x430a), + PSIL_PDMA_XY_PKT(0x430b), + PSIL_PDMA_XY_PKT(0x430c), + PSIL_PDMA_XY_PKT(0x430d), + /* PDMA_MAIN1 - UART0-6 */ + PSIL_PDMA_XY_PKT(0x4400), + PSIL_PDMA_XY_PKT(0x4401), + PSIL_PDMA_XY_PKT(0x4402), + PSIL_PDMA_XY_PKT(0x4403), + PSIL_PDMA_XY_PKT(0x4404), + PSIL_PDMA_XY_PKT(0x4405), + PSIL_PDMA_XY_PKT(0x4406), + /* PDMA_MAIN2 - MCASP0-2 */ + PSIL_PDMA_MCASP(0x4500), + PSIL_PDMA_MCASP(0x4501), + PSIL_PDMA_MCASP(0x4502), + /* CPSW3G */ + PSIL_ETHERNET(0x4600, 19, 19, 16), + /* CSI2RX */ + PSIL_CSI2RX(0x5000), + PSIL_CSI2RX(0x5001), + PSIL_CSI2RX(0x5002), + PSIL_CSI2RX(0x5003), + PSIL_CSI2RX(0x5004), + PSIL_CSI2RX(0x5005), + PSIL_CSI2RX(0x5006), + PSIL_CSI2RX(0x5007), + PSIL_CSI2RX(0x5008), + PSIL_CSI2RX(0x5009), + PSIL_CSI2RX(0x500a), + PSIL_CSI2RX(0x500b), + PSIL_CSI2RX(0x500c), + PSIL_CSI2RX(0x500d), + PSIL_CSI2RX(0x500e), + PSIL_CSI2RX(0x500f), + PSIL_CSI2RX(0x5010), + PSIL_CSI2RX(0x5011), + PSIL_CSI2RX(0x5012), + PSIL_CSI2RX(0x5013), + PSIL_CSI2RX(0x5014), + PSIL_CSI2RX(0x5015), + PSIL_CSI2RX(0x5016), + PSIL_CSI2RX(0x5017), + PSIL_CSI2RX(0x5018), + PSIL_CSI2RX(0x5019), + PSIL_CSI2RX(0x501a), + PSIL_CSI2RX(0x501b), + PSIL_CSI2RX(0x501c), + PSIL_CSI2RX(0x501d), + PSIL_CSI2RX(0x501e), + PSIL_CSI2RX(0x501f), + PSIL_CSI2RX(0x5000), + PSIL_CSI2RX(0x5001), + PSIL_CSI2RX(0x5002), + PSIL_CSI2RX(0x5003), + PSIL_CSI2RX(0x5004), + PSIL_CSI2RX(0x5005), + PSIL_CSI2RX(0x5006), + PSIL_CSI2RX(0x5007), + PSIL_CSI2RX(0x5008), + PSIL_CSI2RX(0x5009), + PSIL_CSI2RX(0x500a), + PSIL_CSI2RX(0x500b), + PSIL_CSI2RX(0x500c), + PSIL_CSI2RX(0x500d), + PSIL_CSI2RX(0x500e), + PSIL_CSI2RX(0x500f), + PSIL_CSI2RX(0x5010), + PSIL_CSI2RX(0x5011), + PSIL_CSI2RX(0x5012), + PSIL_CSI2RX(0x5013), + PSIL_CSI2RX(0x5014), + PSIL_CSI2RX(0x5015), + PSIL_CSI2RX(0x5016), + PSIL_CSI2RX(0x5017), + PSIL_CSI2RX(0x5018), + PSIL_CSI2RX(0x5019), + PSIL_CSI2RX(0x501a), + PSIL_CSI2RX(0x501b), + PSIL_CSI2RX(0x501c), + PSIL_CSI2RX(0x501d), + PSIL_CSI2RX(0x501e), + PSIL_CSI2RX(0x501f), + /* CSIRX 1-3 (only for J722S) */ + PSIL_CSI2RX(0x5100), + PSIL_CSI2RX(0x5101), + PSIL_CSI2RX(0x5102), + PSIL_CSI2RX(0x5103), + PSIL_CSI2RX(0x5104), + PSIL_CSI2RX(0x5105), + PSIL_CSI2RX(0x5106), + PSIL_CSI2RX(0x5107), + PSIL_CSI2RX(0x5108), + PSIL_CSI2RX(0x5109), + PSIL_CSI2RX(0x510a), + PSIL_CSI2RX(0x510b), + PSIL_CSI2RX(0x510c), + PSIL_CSI2RX(0x510d), + PSIL_CSI2RX(0x510e), + PSIL_CSI2RX(0x510f), + PSIL_CSI2RX(0x5110), + PSIL_CSI2RX(0x5111), + PSIL_CSI2RX(0x5112), + PSIL_CSI2RX(0x5113), + PSIL_CSI2RX(0x5114), + PSIL_CSI2RX(0x5115), + PSIL_CSI2RX(0x5116), + PSIL_CSI2RX(0x5117), + PSIL_CSI2RX(0x5118), + PSIL_CSI2RX(0x5119), + PSIL_CSI2RX(0x511a), + PSIL_CSI2RX(0x511b), + PSIL_CSI2RX(0x511c), + PSIL_CSI2RX(0x511d), + PSIL_CSI2RX(0x511e), + PSIL_CSI2RX(0x511f), + PSIL_CSI2RX(0x5200), + PSIL_CSI2RX(0x5201), + PSIL_CSI2RX(0x5202), + PSIL_CSI2RX(0x5203), + PSIL_CSI2RX(0x5204), + PSIL_CSI2RX(0x5205), + PSIL_CSI2RX(0x5206), + PSIL_CSI2RX(0x5207), + PSIL_CSI2RX(0x5208), + PSIL_CSI2RX(0x5209), + PSIL_CSI2RX(0x520a), + PSIL_CSI2RX(0x520b), + PSIL_CSI2RX(0x520c), + PSIL_CSI2RX(0x520d), + PSIL_CSI2RX(0x520e), + PSIL_CSI2RX(0x520f), + PSIL_CSI2RX(0x5210), + PSIL_CSI2RX(0x5211), + PSIL_CSI2RX(0x5212), + PSIL_CSI2RX(0x5213), + PSIL_CSI2RX(0x5214), + PSIL_CSI2RX(0x5215), + PSIL_CSI2RX(0x5216), + PSIL_CSI2RX(0x5217), + PSIL_CSI2RX(0x5218), + PSIL_CSI2RX(0x5219), + PSIL_CSI2RX(0x521a), + PSIL_CSI2RX(0x521b), + PSIL_CSI2RX(0x521c), + PSIL_CSI2RX(0x521d), + PSIL_CSI2RX(0x521e), + PSIL_CSI2RX(0x521f), + PSIL_CSI2RX(0x5300), + PSIL_CSI2RX(0x5301), + PSIL_CSI2RX(0x5302), + PSIL_CSI2RX(0x5303), + PSIL_CSI2RX(0x5304), + PSIL_CSI2RX(0x5305), + PSIL_CSI2RX(0x5306), + PSIL_CSI2RX(0x5307), + PSIL_CSI2RX(0x5308), + PSIL_CSI2RX(0x5309), + PSIL_CSI2RX(0x530a), + PSIL_CSI2RX(0x530b), + PSIL_CSI2RX(0x530c), + PSIL_CSI2RX(0x530d), + PSIL_CSI2RX(0x530e), + PSIL_CSI2RX(0x530f), + PSIL_CSI2RX(0x5310), + PSIL_CSI2RX(0x5311), + PSIL_CSI2RX(0x5312), + PSIL_CSI2RX(0x5313), + PSIL_CSI2RX(0x5314), + PSIL_CSI2RX(0x5315), + PSIL_CSI2RX(0x5316), + PSIL_CSI2RX(0x5317), + PSIL_CSI2RX(0x5318), + PSIL_CSI2RX(0x5319), + PSIL_CSI2RX(0x531a), + PSIL_CSI2RX(0x531b), + PSIL_CSI2RX(0x531c), + PSIL_CSI2RX(0x531d), + PSIL_CSI2RX(0x531e), + PSIL_CSI2RX(0x531f), +}; + +/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ +static struct psil_ep am62p_dst_ep_map[] = { + /* SAUL */ + PSIL_SAUL(0xf500, 27, 83, 8, 83, 1), + PSIL_SAUL(0xf501, 28, 91, 8, 91, 1), + /* PDMA_MAIN0 - SPI0-3 */ + PSIL_PDMA_XY_PKT(0xc302), + PSIL_PDMA_XY_PKT(0xc303), + PSIL_PDMA_XY_PKT(0xc304), + PSIL_PDMA_XY_PKT(0xc305), + PSIL_PDMA_XY_PKT(0xc306), + PSIL_PDMA_XY_PKT(0xc307), + PSIL_PDMA_XY_PKT(0xc308), + PSIL_PDMA_XY_PKT(0xc309), + PSIL_PDMA_XY_PKT(0xc30a), + PSIL_PDMA_XY_PKT(0xc30b), + PSIL_PDMA_XY_PKT(0xc30c), + PSIL_PDMA_XY_PKT(0xc30d), + /* PDMA_MAIN1 - UART0-6 */ + PSIL_PDMA_XY_PKT(0xc400), + PSIL_PDMA_XY_PKT(0xc401), + PSIL_PDMA_XY_PKT(0xc402), + PSIL_PDMA_XY_PKT(0xc403), + PSIL_PDMA_XY_PKT(0xc404), + PSIL_PDMA_XY_PKT(0xc405), + PSIL_PDMA_XY_PKT(0xc406), + /* PDMA_MAIN2 - MCASP0-2 */ + PSIL_PDMA_MCASP(0xc500), + PSIL_PDMA_MCASP(0xc501), + PSIL_PDMA_MCASP(0xc502), + /* CPSW3G */ + PSIL_ETHERNET(0xc600, 19, 19, 8), + PSIL_ETHERNET(0xc601, 20, 27, 8), + PSIL_ETHERNET(0xc602, 21, 35, 8), + PSIL_ETHERNET(0xc603, 22, 43, 8), + PSIL_ETHERNET(0xc604, 23, 51, 8), + PSIL_ETHERNET(0xc605, 24, 59, 8), + PSIL_ETHERNET(0xc606, 25, 67, 8), + PSIL_ETHERNET(0xc607, 26, 75, 8), +}; + +struct psil_ep_map am62p_ep_map = { + .name = "am62p", + .src = am62p_src_ep_map, + .src_count = ARRAY_SIZE(am62p_src_ep_map), + .dst = am62p_dst_ep_map, + .dst_count = ARRAY_SIZE(am62p_dst_ep_map), +}; diff --git a/drivers/dma/ti/k3-psil-j784s4.c b/drivers/dma/ti/k3-psil-j784s4.c new file mode 100644 index 0000000..7f06a1f --- /dev/null +++ b/drivers/dma/ti/k3-psil-j784s4.c @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com + */ +#include <linux/kernel.h> + +#include "k3-psil-priv.h" + +#define PSIL_PDMA_XY_TR(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + }, \ + } + +#define PSIL_PDMA_XY_PKT(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .pkt_mode = 1, \ + }, \ + } + +#define PSIL_PDMA_MCASP(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .pdma_acc32 = 1, \ + .pdma_burst = 1, \ + }, \ + } + +#define PSIL_ETHERNET(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 16, \ + }, \ + } + +#define PSIL_SA2UL(x, tx) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 64, \ + .notdpkt = tx, \ + }, \ + } + +/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ +static struct psil_ep j784s4_src_ep_map[] = { + /* PDMA_MCASP - McASP0-4 */ + PSIL_PDMA_MCASP(0x4400), + PSIL_PDMA_MCASP(0x4401), + PSIL_PDMA_MCASP(0x4402), + PSIL_PDMA_MCASP(0x4403), + PSIL_PDMA_MCASP(0x4404), + /* PDMA_SPI_G0 - SPI0-3 */ + PSIL_PDMA_XY_PKT(0x4600), + PSIL_PDMA_XY_PKT(0x4601), + PSIL_PDMA_XY_PKT(0x4602), + PSIL_PDMA_XY_PKT(0x4603), + PSIL_PDMA_XY_PKT(0x4604), + PSIL_PDMA_XY_PKT(0x4605), + PSIL_PDMA_XY_PKT(0x4606), + PSIL_PDMA_XY_PKT(0x4607), + PSIL_PDMA_XY_PKT(0x4608), + PSIL_PDMA_XY_PKT(0x4609), + PSIL_PDMA_XY_PKT(0x460a), + PSIL_PDMA_XY_PKT(0x460b), + PSIL_PDMA_XY_PKT(0x460c), + PSIL_PDMA_XY_PKT(0x460d), + PSIL_PDMA_XY_PKT(0x460e), + PSIL_PDMA_XY_PKT(0x460f), + /* PDMA_SPI_G1 - SPI4-7 */ + PSIL_PDMA_XY_PKT(0x4610), + PSIL_PDMA_XY_PKT(0x4611), + PSIL_PDMA_XY_PKT(0x4612), + PSIL_PDMA_XY_PKT(0x4613), + PSIL_PDMA_XY_PKT(0x4614), + PSIL_PDMA_XY_PKT(0x4615), + PSIL_PDMA_XY_PKT(0x4616), + PSIL_PDMA_XY_PKT(0x4617), + PSIL_PDMA_XY_PKT(0x4618), + PSIL_PDMA_XY_PKT(0x4619), + PSIL_PDMA_XY_PKT(0x461a), + PSIL_PDMA_XY_PKT(0x461b), + PSIL_PDMA_XY_PKT(0x461c), + PSIL_PDMA_XY_PKT(0x461d), + PSIL_PDMA_XY_PKT(0x461e), + PSIL_PDMA_XY_PKT(0x461f), + /* PDMA_USART_G0 - UART0-1 */ + PSIL_PDMA_XY_PKT(0x4700), + PSIL_PDMA_XY_PKT(0x4701), + /* PDMA_USART_G1 - UART2-3 */ + PSIL_PDMA_XY_PKT(0x4702), + PSIL_PDMA_XY_PKT(0x4703), + /* PDMA_USART_G2 - UART4-9 */ + PSIL_PDMA_XY_PKT(0x4704), + PSIL_PDMA_XY_PKT(0x4705), + PSIL_PDMA_XY_PKT(0x4706), + PSIL_PDMA_XY_PKT(0x4707), + PSIL_PDMA_XY_PKT(0x4708), + PSIL_PDMA_XY_PKT(0x4709), + /* CPSW0 */ + PSIL_ETHERNET(0x7000), + /* MCU_PDMA0 (MCU_PDMA_MISC_G0) - SPI0 */ + PSIL_PDMA_XY_PKT(0x7100), + PSIL_PDMA_XY_PKT(0x7101), + PSIL_PDMA_XY_PKT(0x7102), + PSIL_PDMA_XY_PKT(0x7103), + /* MCU_PDMA1 (MCU_PDMA_MISC_G1) - SPI1-2 */ + PSIL_PDMA_XY_PKT(0x7200), + PSIL_PDMA_XY_PKT(0x7201), + PSIL_PDMA_XY_PKT(0x7202), + PSIL_PDMA_XY_PKT(0x7203), + PSIL_PDMA_XY_PKT(0x7204), + PSIL_PDMA_XY_PKT(0x7205), + PSIL_PDMA_XY_PKT(0x7206), + PSIL_PDMA_XY_PKT(0x7207), + /* MCU_PDMA2 (MCU_PDMA_MISC_G2) - UART0 */ + PSIL_PDMA_XY_PKT(0x7300), + /* MCU_PDMA_ADC - ADC0-1 */ + PSIL_PDMA_XY_TR(0x7400), + PSIL_PDMA_XY_TR(0x7401), + PSIL_PDMA_XY_TR(0x7402), + PSIL_PDMA_XY_TR(0x7403), + /* SA2UL */ + PSIL_SA2UL(0x7500, 0), + PSIL_SA2UL(0x7501, 0), + PSIL_SA2UL(0x7502, 0), + PSIL_SA2UL(0x7503, 0), +}; + +/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ +static struct psil_ep j784s4_dst_ep_map[] = { + /* CPSW0 */ + PSIL_ETHERNET(0xf000), + PSIL_ETHERNET(0xf001), + PSIL_ETHERNET(0xf002), + PSIL_ETHERNET(0xf003), + PSIL_ETHERNET(0xf004), + PSIL_ETHERNET(0xf005), + PSIL_ETHERNET(0xf006), + PSIL_ETHERNET(0xf007), + /* SA2UL */ + PSIL_SA2UL(0xf500, 1), + PSIL_SA2UL(0xf501, 1), +}; + +struct psil_ep_map j784s4_ep_map = { + .name = "j784s4", + .src = j784s4_src_ep_map, + .src_count = ARRAY_SIZE(j784s4_src_ep_map), + .dst = j784s4_dst_ep_map, + .dst_count = ARRAY_SIZE(j784s4_dst_ep_map), +}; diff --git a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h index 83f873b..b80916a 100644 --- a/drivers/dma/ti/k3-psil-priv.h +++ b/drivers/dma/ti/k3-psil-priv.h @@ -43,5 +43,7 @@ extern struct psil_ep_map j721s2_ep_map; extern struct psil_ep_map am64_ep_map; extern struct psil_ep_map am62_ep_map; extern struct psil_ep_map am62a_ep_map; +extern struct psil_ep_map j784s4_ep_map; +extern struct psil_ep_map am62p_ep_map; #endif /* K3_PSIL_PRIV_H_ */ diff --git a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c index d4d4fed..369e679 100644 --- a/drivers/dma/ti/k3-psil.c +++ b/drivers/dma/ti/k3-psil.c @@ -28,6 +28,12 @@ struct psil_endpoint_config *psil_get_ep_config(u32 thread_id) soc_ep_map = &am62_ep_map; else if (IS_ENABLED(CONFIG_SOC_K3_AM62A7)) soc_ep_map = &am62a_ep_map; + else if (IS_ENABLED(CONFIG_SOC_K3_J784S4)) + soc_ep_map = &j784s4_ep_map; + else if (IS_ENABLED(CONFIG_SOC_K3_AM62P5)) + soc_ep_map = &am62p_ep_map; + else if (IS_ENABLED(CONFIG_SOC_K3_J722S)) + soc_ep_map = &am62p_ep_map; } if (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET && soc_ep_map->dst) { diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index eea9ec9..ef3074a 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -884,10 +884,10 @@ static int udma_alloc_tx_resources(struct udma_chan *uc) return ret; tchan = uc->tchan; - if (tchan->tflow_id >= 0) + if (tchan->tflow_id > 0) ring_idx = tchan->tflow_id; else - ring_idx = ud->bchan_cnt + tchan->id; + ring_idx = tchan->id; ret = k3_nav_ringacc_request_rings_pair(ud->ringacc, ring_idx, -1, &uc->tchan->t_ring, @@ -1770,9 +1770,11 @@ static int udma_probe(struct udevice *dev) return PTR_ERR(ud->ringacc); ud->dev = dev; - ud->ch_count = setup_resources(ud); - if (ud->ch_count <= 0) - return ud->ch_count; + ret = setup_resources(ud); + if (ret < 0) + return ret; + + ud->ch_count = ret; for (i = 0; i < ud->bchan_cnt; i++) { struct udma_bchan *bchan = &ud->bchans[i]; @@ -1831,7 +1833,7 @@ static int udma_probe(struct udevice *dev) uc_priv->supported = DMA_SUPPORTS_MEM_TO_MEM | DMA_SUPPORTS_MEM_TO_DEV; - return ret; + return 0; } static int udma_push_to_ring(struct k3_nav_ring *ring, void *elem) diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index c6b9efa..03544d7 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -135,10 +135,13 @@ static int bind_smccc_features(struct udevice *dev, int psci_method) PSCI_VERSION_MAJOR(psci_0_2_get_version()) == 0) return 0; - if (request_psci_features(ARM_SMCCC_ARCH_FEATURES) == + if (request_psci_features(ARM_SMCCC_VERSION) == PSCI_RET_NOT_SUPPORTED) return 0; + if (invoke_psci_fn(ARM_SMCCC_VERSION, 0, 0, 0) < ARM_SMCCC_VERSION_1_1) + return 0; + if (psci_method == PSCI_METHOD_HVC) pdata->invoke_fn = smccc_invoke_hvc; else diff --git a/drivers/firmware/ti_sci_static_data.h b/drivers/firmware/ti_sci_static_data.h index 567ce89..9662bd9 100644 --- a/drivers/firmware/ti_sci_static_data.h +++ b/drivers/firmware/ti_sci_static_data.h @@ -84,7 +84,8 @@ static struct ti_sci_resource_static_data rm_static_data[] = { }; #endif /* CONFIG_SOC_K3_J721S2 */ -#if IS_ENABLED(CONFIG_SOC_K3_AM625) || IS_ENABLED(CONFIG_SOC_K3_AM62A7) +#if IS_ENABLED(CONFIG_SOC_K3_AM625) || IS_ENABLED(CONFIG_SOC_K3_AM62A7) || \ + IS_ENABLED(CONFIG_SOC_K3_AM62P5) static struct ti_sci_resource_static_data rm_static_data[] = { /* BC channels */ { @@ -95,7 +96,41 @@ static struct ti_sci_resource_static_data rm_static_data[] = { }, { }, }; -#endif /* CONFIG_SOC_K3_AM625 || CONFIG_SOC_K3_AM62A7 */ +#endif /* CONFIG_SOC_K3_AM625 || CONFIG_SOC_K3_AM62A7 || CONFIG_SOC_K3_AM62P5 */ + +#if IS_ENABLED(CONFIG_SOC_K3_J784S4) +static struct ti_sci_resource_static_data rm_static_data[] = { + /* Free rings */ + { + .dev_id = 328, + .subtype = 1, + .range_start = 208, + .range_num = 32, + }, + /* TX channels */ + { + .dev_id = 329, + .subtype = 13, + .range_start = 40, + .range_num = 3, + }, + /* RX channels */ + { + .dev_id = 329, + .subtype = 10, + .range_start = 40, + .range_num = 3, + }, + /* RX Free flows */ + { + .dev_id = 329, + .subtype = 0, + .range_start = 84, + .range_num = 8, + }, + { }, +}; +#endif /* CONFIG_SOC_K3_J784S4 */ #else static struct ti_sci_resource_static_data rm_static_data[] = { diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 2df3dc4..a7fb1eb 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -256,6 +256,9 @@ config MCP230XX_GPIO - MCP23008 - MCP23017 - MCP23018 + - MCP23S08 + - MCP23S17 + - MCP23S18 config MSCC_SGPIO bool "Microsemi Serial GPIO driver" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index da3da5d..9071170 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o obj-$(CONFIG_INTEL_BROADWELL_GPIO) += intel_broadwell_gpio.o obj-$(CONFIG_IPROC_GPIO) += iproc_gpio.o obj-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o -obj-$(CONFIG_MCP230XX_GPIO) += mcp230xx_gpio.o +obj-$(CONFIG_$(SPL_TPL_)MCP230XX_GPIO) += mcp230xx_gpio.o obj-$(CONFIG_MXC_GPIO) += mxc_gpio.o obj-$(CONFIG_MXS_GPIO) += mxs_gpio.o obj-$(CONFIG_NPCM_GPIO) += npcm_gpio.o diff --git a/drivers/gpio/mcp230xx_gpio.c b/drivers/gpio/mcp230xx_gpio.c index 9f02fd4..df99fde 100644 --- a/drivers/gpio/mcp230xx_gpio.c +++ b/drivers/gpio/mcp230xx_gpio.c @@ -11,6 +11,7 @@ #include <errno.h> #include <dm.h> #include <i2c.h> +#include <spi.h> #include <asm/gpio.h> #include <dm/device_compat.h> #include <dt-bindings/gpio/gpio.h> @@ -20,6 +21,13 @@ enum mcp230xx_type { MCP23008, MCP23017, MCP23018, + MCP23S08, + MCP23S17, + MCP23S18, +}; + +struct mcp230xx_info { + uint dev_addr; }; #define MCP230XX_IODIR 0x00 @@ -29,29 +37,136 @@ enum mcp230xx_type { #define BANKSIZE 8 +#define MCP230XX_ADDR 0x20 + +static int mcp230xx_read_spi(struct udevice *dev, uint reg_addr) +{ + struct mcp230xx_info *info = dev_get_plat(dev); + uint dev_addr, value = 0; + int ret; + + /* set R/W bit for reading */ + dev_addr = (info->dev_addr << 1) | 1; + + ret = dm_spi_claim_bus(dev); + if (ret) + return ret; + + ret = dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_BEGIN); + if (ret < 0) + goto fail; + udelay(1); + + ret = dm_spi_xfer(dev, 8, &dev_addr, NULL, 0); + if (ret < 0) + goto fail; + + ret = dm_spi_xfer(dev, 8, ®_addr, NULL, 0); + if (ret < 0) + goto fail; + + ret = dm_spi_xfer(dev, 8, NULL, &value, 0); + +fail: + dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_END); + dm_spi_release_bus(dev); + if (ret < 0) + return ret; + return value; +} + static int mcp230xx_read(struct udevice *dev, uint reg, uint offset) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); int bank = offset / BANKSIZE; int mask = 1 << (offset % BANKSIZE); int shift = (uc_priv->gpio_count / BANKSIZE) - 1; - int ret; + int reg_addr = (reg << shift) | bank; + int ret = 0; + + switch (dev_get_driver_data(dev)) { + case MCP23008: + case MCP23017: + case MCP23018: + ret = dm_i2c_reg_read(dev, reg_addr); + break; + case MCP23S08: + case MCP23S17: + case MCP23S18: + ret = mcp230xx_read_spi(dev, reg_addr); + break; + default: + return -ENODEV; + } - ret = dm_i2c_reg_read(dev, (reg << shift) | bank); if (ret < 0) return ret; return !!(ret & mask); } +static int mcp230xx_clrset_spi(struct udevice *dev, uint reg_addr, uint clr, uint set) +{ + struct mcp230xx_info *info = dev_get_plat(dev); + int dev_addr, value; + int ret; + + /* R/W bit = 0 for writing */ + dev_addr = (info->dev_addr << 1); + + ret = mcp230xx_read_spi(dev, reg_addr); + if (ret < 0) + return ret; + + value = ret; + value &= ~clr; + value |= set; + + ret = dm_spi_claim_bus(dev); + if (ret) + return ret; + + ret = dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_BEGIN); + if (ret < 0) + goto fail; + udelay(1); + + ret = dm_spi_xfer(dev, 8, &dev_addr, NULL, 0); + if (ret < 0) + goto fail; + + ret = dm_spi_xfer(dev, 8, ®_addr, NULL, 0); + if (ret < 0) + goto fail; + + ret = dm_spi_xfer(dev, 8, &value, NULL, 0); + +fail: + dm_spi_xfer(dev, 0, NULL, NULL, SPI_XFER_END); + dm_spi_release_bus(dev); + return ret; +} + static int mcp230xx_write(struct udevice *dev, uint reg, uint offset, bool val) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); int bank = offset / BANKSIZE; int mask = 1 << (offset % BANKSIZE); int shift = (uc_priv->gpio_count / BANKSIZE) - 1; + int reg_addr = (reg << shift) | bank; - return dm_i2c_reg_clrset(dev, (reg << shift) | bank, mask, val ? mask : 0); + switch (dev_get_driver_data(dev)) { + case MCP23008: + case MCP23017: + case MCP23018: + return dm_i2c_reg_clrset(dev, reg_addr, mask, val ? mask : 0); + case MCP23S08: + case MCP23S17: + case MCP23S18: + return mcp230xx_clrset_spi(dev, reg_addr, mask, val ? mask : 0); + default: + return -ENODEV; + } } static int mcp230xx_get_value(struct udevice *dev, uint offset) @@ -181,22 +296,37 @@ static const struct dm_gpio_ops mcp230xx_ops = { static int mcp230xx_probe(struct udevice *dev) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); - char name[32], label[8], *str; + struct mcp230xx_info *info = dev_get_plat(dev); + char name[32], label[32], *str; int addr, gpio_count, size; const u8 *tmp; switch (dev_get_driver_data(dev)) { case MCP23008: + case MCP23S08: gpio_count = 8; break; case MCP23017: case MCP23018: + case MCP23S17: + case MCP23S18: gpio_count = 16; break; default: return -ENODEV; } + switch (dev_get_driver_data(dev)) { + case MCP23S08: + case MCP23S17: + case MCP23S18: + info->dev_addr = dev_read_u32_default(dev, "addr", MCP230XX_ADDR); + break; + default: + info->dev_addr = 0; + break; + } + addr = dev_read_addr(dev); tmp = dev_read_prop(dev, "label", &size); if (tmp) { @@ -220,9 +350,14 @@ static int mcp230xx_probe(struct udevice *dev) } static const struct udevice_id mcp230xx_ids[] = { + /* i2c interface */ { .compatible = "microchip,mcp23008", .data = MCP23008, }, { .compatible = "microchip,mcp23017", .data = MCP23017, }, { .compatible = "microchip,mcp23018", .data = MCP23018, }, + /* spi interface */ + { .compatible = "microchip,mcp23s08", .data = MCP23S08, }, + { .compatible = "microchip,mcp23s17", .data = MCP23S17, }, + { .compatible = "microchip,mcp23s18", .data = MCP23S18, }, { } }; @@ -231,5 +366,6 @@ U_BOOT_DRIVER(mcp230xx) = { .id = UCLASS_GPIO, .ops = &mcp230xx_ops, .probe = mcp230xx_probe, + .plat_auto = sizeof(struct mcp230xx_info), .of_match = mcp230xx_ids, }; diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index 80cd28b..5e57b0c 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -39,6 +39,10 @@ static int msm_gpio_direction_input(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); + /* Always NOP for special pins, assume they're in the correct state */ + if (qcom_is_special_pin(priv->pin_data, gpio)) + return 0; + /* Disable OE bit */ clrsetbits_le32(priv->base + GPIO_CONFIG_REG(dev, gpio), GPIO_OE_MASK, GPIO_OE_DISABLE); @@ -50,6 +54,10 @@ static int msm_gpio_set_value(struct udevice *dev, unsigned int gpio, int value) { struct msm_gpio_bank *priv = dev_get_priv(dev); + /* Always NOP for special pins, assume they're in the correct state */ + if (qcom_is_special_pin(priv->pin_data, gpio)) + return 0; + value = !!value; /* set value */ writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio)); @@ -62,6 +70,10 @@ static int msm_gpio_direction_output(struct udevice *dev, unsigned int gpio, { struct msm_gpio_bank *priv = dev_get_priv(dev); + /* Always NOP for special pins, assume they're in the correct state */ + if (qcom_is_special_pin(priv->pin_data, gpio)) + return 0; + value = !!value; /* set value */ writel(value << GPIO_OUT, priv->base + GPIO_IN_OUT_REG(dev, gpio)); @@ -76,6 +88,10 @@ static int msm_gpio_get_value(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); + /* Always NOP for special pins, assume they're in the correct state */ + if (qcom_is_special_pin(priv->pin_data, gpio)) + return 0; + return !!(readl(priv->base + GPIO_IN_OUT_REG(dev, gpio)) >> GPIO_IN); } @@ -83,6 +99,10 @@ static int msm_gpio_get_function(struct udevice *dev, unsigned int gpio) { struct msm_gpio_bank *priv = dev_get_priv(dev); + /* Always NOP for special pins, assume they're in the correct state */ + if (qcom_is_special_pin(priv->pin_data, gpio)) + return 0; + if (readl(priv->base + GPIO_CONFIG_REG(dev, gpio)) & GPIO_OE_ENABLE) return GPIOF_OUTPUT; diff --git a/drivers/gpio/qcom_pmic_gpio.c b/drivers/gpio/qcom_pmic_gpio.c index 6167c84..14a8210 100644 --- a/drivers/gpio/qcom_pmic_gpio.c +++ b/drivers/gpio/qcom_pmic_gpio.c @@ -7,10 +7,14 @@ #include <common.h> #include <dm.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <dm/pinctrl.h> #include <log.h> #include <power/pmic.h> #include <spmi/spmi.h> #include <asm/io.h> +#include <stdlib.h> #include <asm/gpio.h> #include <linux/bitops.h> @@ -64,27 +68,34 @@ #define REG_EN_CTL 0x46 #define REG_EN_CTL_ENABLE (1 << 7) -struct qcom_gpio_bank { +/** + * pmic_gpio_match_data - platform specific configuration + * + * @PMIC_MATCH_READONLY: treat all GPIOs as readonly, don't attempt to configure them. + * This is a workaround for an unknown bug on some platforms where trying to write the + * GPIO configuration registers causes the board to hang. + */ +enum pmic_gpio_quirks { + QCOM_PMIC_QUIRK_READONLY = (1 << 0), +}; + +struct qcom_pmic_gpio_data { uint32_t pid; /* Peripheral ID on SPMI bus */ bool lv_mv_type; /* If subtype is GPIO_LV(0x10) or GPIO_MV(0x11) */ + u32 pin_count; + struct udevice *pmic; /* Reference to pmic device for read/write */ }; -static int qcom_gpio_set_direction(struct udevice *dev, unsigned offset, - bool input, int value) +/* dev can be the GPIO or pinctrl device */ +static int _qcom_gpio_set_direction(struct udevice *dev, u32 offset, bool input, int value) { - struct qcom_gpio_bank *priv = dev_get_priv(dev); - uint32_t gpio_base = priv->pid + REG_OFFSET(offset); - uint32_t reg_ctl_val; - int ret; - - /* Disable the GPIO */ - ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, - REG_EN_CTL_ENABLE, 0); - if (ret < 0) - return ret; + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + u32 gpio_base = plat->pid + REG_OFFSET(offset); + u32 reg_ctl_val; + int ret = 0; /* Select the mode and output */ - if (priv->lv_mv_type) { + if (plat->lv_mv_type) { if (input) reg_ctl_val = REG_CTL_LV_MV_MODE_INPUT; else @@ -96,20 +107,43 @@ static int qcom_gpio_set_direction(struct udevice *dev, unsigned offset, reg_ctl_val = REG_CTL_MODE_INOUT | !!value; } - ret = pmic_reg_write(dev->parent, gpio_base + REG_CTL, reg_ctl_val); + ret = pmic_reg_write(plat->pmic, gpio_base + REG_CTL, reg_ctl_val); if (ret < 0) return ret; - if (priv->lv_mv_type && !input) { - ret = pmic_reg_write(dev->parent, + if (plat->lv_mv_type && !input) { + ret = pmic_reg_write(plat->pmic, gpio_base + REG_LV_MV_OUTPUT_CTL, !!value << REG_LV_MV_OUTPUT_CTL_SHIFT); if (ret < 0) return ret; } + return 0; +} + +static int qcom_gpio_set_direction(struct udevice *dev, unsigned int offset, + bool input, int value) +{ + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + uint32_t gpio_base = plat->pid + REG_OFFSET(offset); + ulong quirks = dev_get_driver_data(dev); + int ret = 0; + + /* Some PMICs don't like their GPIOs being configured */ + if (quirks & QCOM_PMIC_QUIRK_READONLY) + return 0; + + /* Disable the GPIO */ + ret = pmic_clrsetbits(dev->parent, gpio_base + REG_EN_CTL, + REG_EN_CTL_ENABLE, 0); + if (ret < 0) + return ret; + + _qcom_gpio_set_direction(dev, offset, input, value); + /* Set the right pull (no pull) */ - ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_PULL_CTL, + ret = pmic_reg_write(plat->pmic, gpio_base + REG_DIG_PULL_CTL, REG_DIG_PULL_NO_PU); if (ret < 0) return ret; @@ -117,13 +151,13 @@ static int qcom_gpio_set_direction(struct udevice *dev, unsigned offset, /* Configure output pin drivers if needed */ if (!input) { /* Select the VIN - VIN0, pin is input so it doesn't matter */ - ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_VIN_CTL, + ret = pmic_reg_write(plat->pmic, gpio_base + REG_DIG_VIN_CTL, REG_DIG_VIN_VIN0); if (ret < 0) return ret; /* Set the right dig out control */ - ret = pmic_reg_write(dev->parent, gpio_base + REG_DIG_OUT_CTL, + ret = pmic_reg_write(plat->pmic, gpio_base + REG_DIG_OUT_CTL, REG_DIG_OUT_CTL_CMOS | REG_DIG_OUT_CTL_DRIVE_L); if (ret < 0) @@ -148,15 +182,15 @@ static int qcom_gpio_direction_output(struct udevice *dev, unsigned offset, static int qcom_gpio_get_function(struct udevice *dev, unsigned offset) { - struct qcom_gpio_bank *priv = dev_get_priv(dev); - uint32_t gpio_base = priv->pid + REG_OFFSET(offset); + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + uint32_t gpio_base = plat->pid + REG_OFFSET(offset); int reg; - reg = pmic_reg_read(dev->parent, gpio_base + REG_CTL); + reg = pmic_reg_read(plat->pmic, gpio_base + REG_CTL); if (reg < 0) return reg; - if (priv->lv_mv_type) { + if (plat->lv_mv_type) { switch (reg & REG_CTL_LV_MV_MODE_MASK) { case REG_CTL_LV_MV_MODE_INPUT: return GPIOF_INPUT; @@ -181,11 +215,11 @@ static int qcom_gpio_get_function(struct udevice *dev, unsigned offset) static int qcom_gpio_get_value(struct udevice *dev, unsigned offset) { - struct qcom_gpio_bank *priv = dev_get_priv(dev); - uint32_t gpio_base = priv->pid + REG_OFFSET(offset); + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + uint32_t gpio_base = plat->pid + REG_OFFSET(offset); int reg; - reg = pmic_reg_read(dev->parent, gpio_base + REG_STATUS); + reg = pmic_reg_read(plat->pmic, gpio_base + REG_STATUS); if (reg < 0) return reg; @@ -195,11 +229,11 @@ static int qcom_gpio_get_value(struct udevice *dev, unsigned offset) static int qcom_gpio_set_value(struct udevice *dev, unsigned offset, int value) { - struct qcom_gpio_bank *priv = dev_get_priv(dev); - uint32_t gpio_base = priv->pid + REG_OFFSET(offset); + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + uint32_t gpio_base = plat->pid + REG_OFFSET(offset); /* Set the output value of the gpio */ - if (priv->lv_mv_type) + if (plat->lv_mv_type) return pmic_clrsetbits(dev->parent, gpio_base + REG_LV_MV_OUTPUT_CTL, REG_LV_MV_OUTPUT_CTL_MASK, @@ -209,71 +243,104 @@ static int qcom_gpio_set_value(struct udevice *dev, unsigned offset, REG_CTL_OUTPUT_MASK, !!value); } +static int qcom_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, + struct ofnode_phandle_args *args) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + if (args->args_count < 1) + return -EINVAL; + + /* GPIOs in DT are 1-based */ + desc->offset = args->args[0] - 1; + if (desc->offset >= uc_priv->gpio_count) + return -EINVAL; + + if (args->args_count < 2) + return 0; + + desc->flags = gpio_flags_xlate(args->args[1]); + + return 0; +} + static const struct dm_gpio_ops qcom_gpio_ops = { .direction_input = qcom_gpio_direction_input, .direction_output = qcom_gpio_direction_output, .get_value = qcom_gpio_get_value, .set_value = qcom_gpio_set_value, .get_function = qcom_gpio_get_function, + .xlate = qcom_gpio_xlate, }; +static int qcom_gpio_bind(struct udevice *dev) +{ + + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + ulong quirks = dev_get_driver_data(dev); + struct udevice *child; + struct driver *drv; + int ret; + + drv = lists_driver_lookup_name("qcom_pmic_pinctrl"); + if (!drv) { + log_warning("Cannot find driver '%s'\n", "qcom_pmic_pinctrl"); + return -ENOENT; + } + + /* Bind the GPIO driver as a child of the PMIC. */ + ret = device_bind_with_driver_data(dev, drv, + dev->name, + quirks, dev_ofnode(dev), &child); + if (ret) + return log_msg_ret("bind", ret); + + dev_set_plat(child, plat); + + return 0; +} + static int qcom_gpio_probe(struct udevice *dev) { - struct qcom_gpio_bank *priv = dev_get_priv(dev); - int reg; + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + struct ofnode_phandle_args args; + int val, ret; u64 pid; + plat->pmic = dev->parent; + pid = dev_read_addr(dev); if (pid == FDT_ADDR_T_NONE) return log_msg_ret("bad address", -EINVAL); - priv->pid = pid; + plat->pid = pid; /* Do a sanity check */ - reg = pmic_reg_read(dev->parent, priv->pid + REG_TYPE); - if (reg != REG_TYPE_VAL) + val = pmic_reg_read(plat->pmic, plat->pid + REG_TYPE); + if (val != REG_TYPE_VAL) return log_msg_ret("bad type", -ENXIO); - reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE); - if (reg != REG_SUBTYPE_GPIO_4CH && reg != REG_SUBTYPE_GPIOC_4CH && - reg != REG_SUBTYPE_GPIO_LV && reg != REG_SUBTYPE_GPIO_MV) + val = pmic_reg_read(plat->pmic, plat->pid + REG_SUBTYPE); + if (val != REG_SUBTYPE_GPIO_4CH && val != REG_SUBTYPE_GPIOC_4CH && + val != REG_SUBTYPE_GPIO_LV && val != REG_SUBTYPE_GPIO_MV) return log_msg_ret("bad subtype", -ENXIO); - priv->lv_mv_type = reg == REG_SUBTYPE_GPIO_LV || - reg == REG_SUBTYPE_GPIO_MV; - - return 0; -} - -/* - * Parse basic GPIO count specified via the gpio-ranges property - * as specified in Linux devicetrees - * Returns < 0 on error, otherwise gpio count - */ -static int qcom_gpio_of_parse_ranges(struct udevice *dev) -{ - int ret; - struct ofnode_phandle_args args; + plat->lv_mv_type = val == REG_SUBTYPE_GPIO_LV || + val == REG_SUBTYPE_GPIO_MV; + /* + * Parse basic GPIO count specified via the gpio-ranges property + * as specified in upstream devicetrees + */ ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "gpio-ranges", NULL, 3, 0, &args); if (ret) return log_msg_ret("gpio-ranges", ret); - return args.args[2]; -} - -static int qcom_gpio_of_to_plat(struct udevice *dev) -{ - struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); - int ret; - - ret = qcom_gpio_of_parse_ranges(dev); - if (ret > 0) - uc_priv->gpio_count = ret; - else - return ret; + plat->pin_count = args.args[2]; + uc_priv->gpio_count = plat->pin_count; uc_priv->bank_name = "pmic"; return 0; @@ -282,7 +349,7 @@ static int qcom_gpio_of_to_plat(struct udevice *dev) static const struct udevice_id qcom_gpio_ids[] = { { .compatible = "qcom,pm8916-gpio" }, { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */ - { .compatible = "qcom,pm8998-gpio" }, + { .compatible = "qcom,pm8998-gpio", .data = QCOM_PMIC_QUIRK_READONLY }, { .compatible = "qcom,pms405-gpio" }, { } }; @@ -291,9 +358,75 @@ U_BOOT_DRIVER(qcom_pmic_gpio) = { .name = "qcom_pmic_gpio", .id = UCLASS_GPIO, .of_match = qcom_gpio_ids, - .of_to_plat = qcom_gpio_of_to_plat, - .probe = qcom_gpio_probe, + .bind = qcom_gpio_bind, + .probe = qcom_gpio_probe, .ops = &qcom_gpio_ops, - .priv_auto = sizeof(struct qcom_gpio_bank), + .plat_auto = sizeof(struct qcom_pmic_gpio_data), + .flags = DM_FLAG_ALLOC_PDATA, +}; + +static const struct pinconf_param qcom_pmic_pinctrl_conf_params[] = { + { "output-high", PIN_CONFIG_OUTPUT_ENABLE, 1 }, + { "output-low", PIN_CONFIG_OUTPUT, 0 }, +}; + +static int qcom_pmic_pinctrl_get_pins_count(struct udevice *dev) +{ + struct qcom_pmic_gpio_data *plat = dev_get_plat(dev); + + return plat->pin_count; +} + +static const char *qcom_pmic_pinctrl_get_pin_name(struct udevice *dev, unsigned int selector) +{ + static char name[8]; + + /* DT indexes from 1 */ + snprintf(name, sizeof(name), "gpio%u", selector + 1); + + return name; +} + +static int qcom_pmic_pinctrl_pinconf_set(struct udevice *dev, unsigned int selector, + unsigned int param, unsigned int arg) +{ + /* We only support configuring the pin as an output, either low or high */ + return _qcom_gpio_set_direction(dev, selector, false, + param == PIN_CONFIG_OUTPUT_ENABLE); +} + +static const char *qcom_pmic_pinctrl_get_function_name(struct udevice *dev, unsigned int selector) +{ + if (!selector) + return "normal"; + return NULL; +} + +static int qcom_pmic_pinctrl_generic_get_functions_count(struct udevice *dev) +{ + return 1; +} + +static int qcom_pmic_pinctrl_generic_pinmux_set_mux(struct udevice *dev, unsigned int selector, + unsigned int func_selector) +{ + return 0; +} + +struct pinctrl_ops qcom_pmic_pinctrl_ops = { + .get_pins_count = qcom_pmic_pinctrl_get_pins_count, + .get_pin_name = qcom_pmic_pinctrl_get_pin_name, + .set_state = pinctrl_generic_set_state, + .pinconf_num_params = ARRAY_SIZE(qcom_pmic_pinctrl_conf_params), + .pinconf_params = qcom_pmic_pinctrl_conf_params, + .pinconf_set = qcom_pmic_pinctrl_pinconf_set, + .get_function_name = qcom_pmic_pinctrl_get_function_name, + .get_functions_count = qcom_pmic_pinctrl_generic_get_functions_count, + .pinmux_set = qcom_pmic_pinctrl_generic_pinmux_set_mux, }; +U_BOOT_DRIVER(qcom_pmic_pinctrl) = { + .name = "qcom_pmic_pinctrl", + .id = UCLASS_PINCTRL, + .ops = &qcom_pmic_pinctrl_ops, +}; diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c index 4a6ae55..2e901ac 100644 --- a/drivers/gpio/rk_gpio.c +++ b/drivers/gpio/rk_gpio.c @@ -11,7 +11,6 @@ #include <syscon.h> #include <linux/errno.h> #include <asm/gpio.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/gpio.h> @@ -201,8 +200,11 @@ static int rockchip_gpio_probe(struct udevice *dev) priv->bank = args.args[1] / ROCKCHIP_GPIOS_PER_BANK; } else { uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK; - end = strrchr(dev->name, '@'); - priv->bank = trailing_strtoln(dev->name, end); + ret = dev_read_alias_seq(dev, &priv->bank); + if (ret) { + end = strrchr(dev->name, '@'); + priv->bank = trailing_strtoln(dev->name, end); + } } priv->name[0] = 'A' + priv->bank; diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index f11ce72..98043fc 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -689,4 +689,11 @@ config SL28CPLD the base driver which provides common access methods for the sub-drivers. +config SPL_SOCFPGA_DT_REG + bool "Enable register setting from device tree in SPL" + depends on SPL + help + Enable register setting from device tree. This also + provides user a clean interface and all register settings are + centralized in one place, device tree. endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 0432db6..1522f6c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -90,3 +90,4 @@ obj-$(CONFIG_K3_AVS0) += k3_avs.o obj-$(CONFIG_ESM_K3) += k3_esm.o obj-$(CONFIG_ESM_PMIC) += esm_pmic.o obj-$(CONFIG_SL28CPLD) += sl28cpld.o +obj-$(CONFIG_SPL_SOCFPGA_SEC_REG) += socfpga_dtreg.o diff --git a/drivers/misc/atsha204a-i2c.c b/drivers/misc/atsha204a-i2c.c index d3c5158..707daa9 100644 --- a/drivers/misc/atsha204a-i2c.c +++ b/drivers/misc/atsha204a-i2c.c @@ -21,7 +21,6 @@ #include <linux/bitrev.h> #include <u-boot/crc.h> -#define ATSHA204A_TWLO_US 60 #define ATSHA204A_TWHI_US 2500 #define ATSHA204A_TRANSACTION_TIMEOUT 100000 #define ATSHA204A_TRANSACTION_RETRY 5 @@ -34,6 +33,48 @@ static inline u16 atsha204a_crc16(const u8 *buffer, size_t len) return bitrev16(crc16(0, buffer, len)); } +static int atsha204a_ping_bus(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct i2c_msg msg; + int speed; + int res; + u8 val = 0; + + speed = dm_i2c_get_bus_speed(bus); + if (speed != I2C_SPEED_STANDARD_RATE) { + int rv; + + rv = dm_i2c_set_bus_speed(bus, I2C_SPEED_STANDARD_RATE); + if (rv) + debug("Couldn't change the I2C bus speed\n"); + } + + /* + * The I2C drivers don't support sending messages when NAK is received. + * This chip requires wake up low signal on SDA for >= 60us. + * To achieve this, we slow the bus to 100kHz and send an empty + * message to address 0. This will hold the SDA line low for the + * required time to wake up the chip. + */ + msg.addr = 0; + msg.flags = I2C_M_STOP; + msg.len = sizeof(val); + msg.buf = &val; + + res = dm_i2c_xfer(dev, &msg, 1); + + if (speed != I2C_SPEED_STANDARD_RATE) { + int rv; + + rv = dm_i2c_set_bus_speed(bus, speed); + if (rv) + debug("Couldn't restore the I2C bus speed\n"); + } + + return res; +} + static int atsha204a_send(struct udevice *dev, const u8 *buf, u8 len) { fdt_addr_t *priv = dev_get_priv(dev); @@ -94,42 +135,33 @@ static int atsha204a_recv_resp(struct udevice *dev, int atsha204a_wakeup(struct udevice *dev) { - u8 req[4]; struct atsha204a_resp resp; - int try, res; + int res; debug("Waking up ATSHA204A\n"); - for (try = 1; try <= 10; ++try) { - debug("Try %i... ", try); + /* + * The device ignores any levels or transitions on the SCL pin + * when the device is idle, asleep or during waking up. + * Don't check for error when waking up the device. + */ + atsha204a_ping_bus(dev); - /* - * The device ignores any levels or transitions on the SCL pin - * when the device is idle, asleep or during waking up. - * Don't check for error when waking up the device. - */ - memset(req, 0, 4); - atsha204a_send(dev, req, 4); - - udelay(ATSHA204A_TWLO_US + ATSHA204A_TWHI_US); - - res = atsha204a_recv_resp(dev, &resp); - if (res) { - debug("failed on receiving response, ending\n"); - return res; - } + udelay(ATSHA204A_TWHI_US); - if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) { - debug ("failed (responce code = %02x), ending\n", - resp.code); - return -EBADMSG; - } + res = atsha204a_recv_resp(dev, &resp); + if (res) { + debug("failed on receiving response, ending\n"); + return res; + } - debug("success\n"); - return 0; + if (resp.code != ATSHA204A_STATUS_AFTER_WAKE) { + debug("failed (response code = %02x), ending\n", resp.code); + return -EBADMSG; } - return -ETIMEDOUT; + debug("success\n"); + return 0; } int atsha204a_idle(struct udevice *dev) @@ -146,7 +178,7 @@ int atsha204a_idle(struct udevice *dev) int atsha204a_sleep(struct udevice *dev) { int res; - u8 req = ATSHA204A_FUNC_IDLE; + u8 req = ATSHA204A_FUNC_SLEEP; res = atsha204a_send(dev, &req, 1); if (res) diff --git a/drivers/misc/imx_ele/ele_api.c b/drivers/misc/imx_ele/ele_api.c index 0c01773..e0ec22c 100644 --- a/drivers/misc/imx_ele/ele_api.c +++ b/drivers/misc/imx_ele/ele_api.c @@ -528,6 +528,38 @@ int ele_start_rng(void) return ret; } +int ele_commit(u16 fuse_id, u32 *response, u32 *info_type) +{ + struct udevice *dev = gd->arch.ele_dev; + int size = sizeof(struct ele_msg); + struct ele_msg msg; + int ret = 0; + + if (!dev) { + printf("ele dev is not initialized\n"); + return -ENODEV; + } + + msg.version = ELE_VERSION; + msg.tag = ELE_CMD_TAG; + msg.size = 2; + msg.command = ELE_COMMIT_REQ; + msg.data[0] = fuse_id; + + ret = misc_call(dev, false, &msg, size, &msg, size); + if (ret) + printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n", + __func__, ret, fuse_id, msg.data[0]); + + if (response) + *response = msg.data[0]; + + if (info_type) + *info_type = msg.data[1]; + + return ret; +} + int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response) { struct udevice *dev = gd->arch.ele_dev; diff --git a/drivers/misc/rockchip-io-domain.c b/drivers/misc/rockchip-io-domain.c index 3f6227f..0ffea32 100644 --- a/drivers/misc/rockchip-io-domain.c +++ b/drivers/misc/rockchip-io-domain.c @@ -5,7 +5,6 @@ * Ported from linux drivers/soc/rockchip/io-domain.c */ -#include <common.h> #include <dm.h> #include <dm/device_compat.h> #include <regmap.h> @@ -28,6 +27,10 @@ #define MAX_VOLTAGE_1_8 1980000 #define MAX_VOLTAGE_3_3 3600000 +#define RK3399_PMUGRF_CON0 0x180 +#define RK3399_PMUGRF_CON0_VSEL BIT(8) +#define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9 + #define RK3568_PMU_GRF_IO_VSEL0 0x0140 #define RK3568_PMU_GRF_IO_VSEL1 0x0144 #define RK3568_PMU_GRF_IO_VSEL2 0x0148 @@ -35,10 +38,10 @@ struct rockchip_iodomain_soc_data { int grf_offset; const char *supply_names[MAX_SUPPLIES]; - int (*write)(struct regmap *grf, int idx, int uV); + int (*write)(struct regmap *grf, uint offset, int idx, int uV); }; -static int rk3568_iodomain_write(struct regmap *grf, int idx, int uV) +static int rk3568_iodomain_write(struct regmap *grf, uint offset, int idx, int uV) { u32 is_3v3 = uV > MAX_VOLTAGE_1_8; u32 val0, val1; @@ -78,6 +81,64 @@ static int rk3568_iodomain_write(struct regmap *grf, int idx, int uV) return 0; } +static int rockchip_iodomain_write(struct regmap *grf, uint offset, int idx, int uV) +{ + u32 val; + + /* set value bit */ + val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1; + val <<= idx; + + /* apply hiword-mask */ + val |= (BIT(idx) << 16); + + return regmap_write(grf, offset, val); +} + +static int rk3399_pmu_iodomain_write(struct regmap *grf, uint offset, int idx, int uV) +{ + int ret = rockchip_iodomain_write(grf, offset, idx, uV); + + if (!ret && idx == RK3399_PMUGRF_VSEL_SUPPLY_NUM) { + /* + * set pmu io iodomain to also use this framework + * instead of a special gpio. + */ + u32 val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16); + ret = regmap_write(grf, RK3399_PMUGRF_CON0, val); + } + + return ret; +} + +static const struct rockchip_iodomain_soc_data soc_data_rk3399 = { + .grf_offset = 0xe640, + .supply_names = { + "bt656-supply", /* APIO2_VDD */ + "audio-supply", /* APIO5_VDD */ + "sdmmc-supply", /* SDMMC0_VDD */ + "gpio1830-supply", /* APIO4_VDD */ + }, + .write = rockchip_iodomain_write, +}; + +static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = { + .grf_offset = 0x180, + .supply_names = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "pmu1830-supply", /* PMUIO2_VDD */ + }, + .write = rk3399_pmu_iodomain_write, +}; + static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = { .grf_offset = 0x140, .supply_names = { @@ -96,6 +157,14 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = { static const struct udevice_id rockchip_iodomain_ids[] = { { + .compatible = "rockchip,rk3399-io-voltage-domain", + .data = (ulong)&soc_data_rk3399, + }, + { + .compatible = "rockchip,rk3399-pmu-io-voltage-domain", + .data = (ulong)&soc_data_rk3399_pmu, + }, + { .compatible = "rockchip,rk3568-pmu-io-voltage-domain", .data = (ulong)&soc_data_rk3568_pmu, }, @@ -152,7 +221,9 @@ static int rockchip_iodomain_probe(struct udevice *dev) continue; } - soc_data->write(grf, i, uV); + ret = soc_data->write(grf, soc_data->grf_offset, i, uV); + if (ret) + dev_err(dev, "%s: Couldn't write to GRF\n", supply_name); } return 0; diff --git a/drivers/misc/socfpga_dtreg.c b/drivers/misc/socfpga_dtreg.c new file mode 100644 index 0000000..ea5d0bc --- /dev/null +++ b/drivers/misc/socfpga_dtreg.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2024 Intel Corporation <www.intel.com> + */ + +#include <dm.h> +#include <errno.h> +#include <asm/io.h> +#include <linux/sizes.h> + +#define NUMBER_OF_ELEMENTS 3 + +static int socfpga_dtreg_probe(struct udevice *dev) +{ + const fdt32_t *list; + fdt_addr_t offset, base; + fdt_val_t val, read_val, mask, set_mask; + int size, i; + u32 blk_sz, reg; + ofnode node; + const char *name = NULL; + + debug("%s(dev=%p)\n", __func__, dev); + + if (!dev_has_ofnode(dev)) + return 0; + + dev_for_each_subnode(node, dev) { + name = ofnode_get_name(node); + if (!name) + return -EINVAL; + + if (ofnode_read_u32_index(node, "reg", 1, &blk_sz)) + return -EINVAL; + + base = ofnode_get_addr(node); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + debug("%s(node_offset 0x%lx node_name %s ", __func__, + node.of_offset, name); + debug("node addr 0x%llx blk sz 0x%x)\n", base, blk_sz); + + list = ofnode_read_prop(node, "intel,offset-settings", &size); + if (!list) + return -EINVAL; + + debug("%s(intel,offset-settings property size=%x)\n", __func__, + size); + size /= sizeof(*list) * NUMBER_OF_ELEMENTS; + + /* + * First element: offset + * Second element: val + * Third element: mask + */ + for (i = 0; i < size; i++) { + offset = fdt32_to_cpu(*list++); + val = fdt32_to_cpu(*list++); + + /* Reads the masking bit value from the list */ + mask = fdt32_to_cpu(*list++); + + /* + * Reads out the offsets, value and masking bits + * Ex: <0x00000000 0x00000230 0xffffffff> + */ + debug("%s(intel,offset-settings 0x%llx : 0x%llx : 0x%llx)\n", + __func__, offset, val, mask); + + if (blk_sz < offset + SZ_4) { + printf("%s: Overflow as offset 0x%llx or reg", + __func__, offset); + printf(" write is more than block size 0x%x\n", + blk_sz); + return -EINVAL; + } + + if (mask != 0) { + if (mask == 0xffffffff) { + reg = base + offset; + writel(val, (uintptr_t)reg); + } else { + /* Mask the value with the masking bits */ + set_mask = val & mask; + + reg = base + offset; + + /* Clears and sets specific bits in the register */ + clrsetbits_le32((uintptr_t)reg, mask, set_mask); + } + } + + read_val = readl((uintptr_t)reg); + + /* Reads out the register, masked value and the read value */ + debug("%s(reg 0x%x = wr : 0x%llx rd : 0x%llx)\n", + __func__, reg, set_mask, read_val); + } + } + + return 0; +}; + +static const struct udevice_id socfpga_dtreg_ids[] = { + {.compatible = "intel,socfpga-dtreg"}, + { } +}; + +U_BOOT_DRIVER(socfpga_dtreg) = { + .name = "socfpga-dtreg", + .id = UCLASS_NOP, + .of_match = socfpga_dtreg_ids, + .probe = socfpga_dtreg_probe, +}; diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index fe1e754..059cb3d 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -44,6 +44,7 @@ struct msm_sdhc_plat { struct msm_sdhc { struct sdhci_host host; void *base; + struct clk_bulk clks; }; struct msm_sdhc_variant_info { @@ -54,35 +55,57 @@ DECLARE_GLOBAL_DATA_PTR; static int msm_sdc_clk_init(struct udevice *dev) { - int node = dev_of_offset(dev); - uint clk_rate = fdtdec_get_uint(gd->fdt_blob, node, "clock-frequency", - 400000); - uint clkd[2]; /* clk_id and clk_no */ - int clk_offset; - struct udevice *clk_dev; - struct clk clk; - int ret; + struct msm_sdhc *prv = dev_get_priv(dev); + ofnode node = dev_ofnode(dev); + ulong clk_rate; + int ret, i = 0, n_clks; + const char *clk_name; - ret = fdtdec_get_int_array(gd->fdt_blob, node, "clock", clkd, 2); + ret = ofnode_read_u32(node, "clock-frequency", (uint *)(&clk_rate)); if (ret) - return ret; - - clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]); - if (clk_offset < 0) - return clk_offset; + clk_rate = 400000; - ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev); - if (ret) + ret = clk_get_bulk(dev, &prv->clks); + if (ret) { + log_warning("Couldn't get mmc clocks: %d\n", ret); return ret; + } - clk.id = clkd[1]; - ret = clk_request(clk_dev, &clk); - if (ret < 0) + ret = clk_enable_bulk(&prv->clks); + if (ret) { + log_warning("Couldn't enable mmc clocks: %d\n", ret); return ret; + } - ret = clk_set_rate(&clk, clk_rate); - if (ret < 0) - return ret; + /* If clock-names is unspecified, then the first clock is the core clock */ + if (!ofnode_get_property(node, "clock-names", &n_clks)) { + if (!clk_set_rate(&prv->clks.clks[0], clk_rate)) { + log_warning("Couldn't set core clock rate: %d\n", ret); + return -EINVAL; + } + } + + /* Find the index of the "core" clock */ + while (i < n_clks) { + ofnode_read_string_index(node, "clock-names", i, &clk_name); + if (!strcmp(clk_name, "core")) + break; + i++; + } + + if (i >= prv->clks.count) { + log_warning("Couldn't find core clock (index %d but only have %d clocks)\n", i, + prv->clks.count); + return -EINVAL; + } + + /* The clock is already enabled by the clk_bulk above */ + clk_rate = clk_set_rate(&prv->clks.clks[i], clk_rate); + /* If we get a rate of 0 then something has probably gone wrong. */ + if (clk_rate == 0 || IS_ERR((void *)clk_rate)) { + log_warning("Couldn't set MMC core clock rate: %dE\n", clk_rate ? (int)PTR_ERR((void *)clk_rate) : 0); + return -EINVAL; + } return 0; } @@ -187,6 +210,8 @@ static int msm_sdc_remove(struct udevice *dev) if (!var_info->mci_removed) writel(0, priv->base + SDCC_MCI_HC_MODE); + clk_release_bulk(&priv->clks); + return 0; } diff --git a/drivers/mux/mux-uclass.c b/drivers/mux/mux-uclass.c index c98576c..8833888 100644 --- a/drivers/mux/mux-uclass.c +++ b/drivers/mux/mux-uclass.c @@ -318,7 +318,8 @@ int dm_mux_init(void) return ret; } uclass_foreach_dev(dev, uc) { - if (dev_read_bool(dev, "u-boot,mux-autoprobe")) { + if (dev_read_bool(dev, "u-boot,mux-autoprobe") || + dev_read_bool(dev, "idle-states")) { ret = device_probe(dev); if (ret) log_debug("unable to probe device %s\n", diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c index 04008d2..c1bae3f 100644 --- a/drivers/net/gmac_rockchip.c +++ b/drivers/net/gmac_rockchip.c @@ -13,7 +13,6 @@ #include <phy.h> #include <syscon.h> #include <asm/global_data.h> -#include <asm/io.h> #include <asm/arch-rockchip/periph.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/net/macb.c b/drivers/net/macb.c index bfc48da..bca014c 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -128,6 +128,8 @@ struct macb_device { unsigned long dummy_desc_dma; const struct device *dev; + unsigned int duplex; + unsigned int speed; unsigned short phy_addr; struct mii_dev *bus; #ifdef CONFIG_PHYLIB @@ -178,6 +180,12 @@ static int gem_is_gigabit_capable(struct macb_device *macb) return macb_is_gem(macb) && !cpu_is_sama5d2() && !cpu_is_sama5d4(); } +/* Is the port a fixed link */ +static int macb_port_is_fixed_link(struct macb_device *macb) +{ + return macb->phy_addr > PHY_MAX_ADDR; +} + static void macb_mdio_write(struct macb_device *macb, u8 phy_adr, u8 reg, u16 value) { @@ -666,97 +674,109 @@ static int macb_phy_init(struct udevice *dev, const char *name) int i; arch_get_mdio_control(name); - /* Auto-detect phy_addr */ - ret = macb_phy_find(macb, name); - if (ret) - return ret; + /* If port is not fixed -> setup PHY */ + if (!macb_port_is_fixed_link(macb)) { + /* Auto-detect phy_addr */ + ret = macb_phy_find(macb, name); + if (ret) + return ret; - /* Check if the PHY is up to snuff... */ - phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1); - if (phy_id == 0xffff) { - printf("%s: No PHY present\n", name); - return -ENODEV; - } + /* Check if the PHY is up to snuff... */ + phy_id = macb_mdio_read(macb, macb->phy_addr, MII_PHYSID1); + if (phy_id == 0xffff) { + printf("%s: No PHY present\n", name); + return -ENODEV; + } #ifdef CONFIG_PHYLIB - macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev, - macb->phy_interface); - if (!macb->phydev) { - printf("phy_connect failed\n"); - return -ENODEV; - } + macb->phydev = phy_connect(macb->bus, macb->phy_addr, dev, + macb->phy_interface); + if (!macb->phydev) { + printf("phy_connect failed\n"); + return -ENODEV; + } - phy_config(macb->phydev); + phy_config(macb->phydev); #endif - status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR); - if (!(status & BMSR_LSTATUS)) { - /* Try to re-negotiate if we don't have link already. */ - macb_phy_reset(macb, name); - - for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { - status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR); - if (status & BMSR_LSTATUS) { - /* - * Delay a bit after the link is established, - * so that the next xfer does not fail - */ - mdelay(10); - break; + status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR); + if (!(status & BMSR_LSTATUS)) { + /* Try to re-negotiate if we don't have link already. */ + macb_phy_reset(macb, name); + + for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) { + status = macb_mdio_read(macb, macb->phy_addr, MII_BMSR); + if (status & BMSR_LSTATUS) { + /* + * Delay a bit after the link is established, + * so that the next xfer does not fail + */ + mdelay(10); + break; + } + udelay(100); } - udelay(100); } - } - if (!(status & BMSR_LSTATUS)) { - printf("%s: link down (status: 0x%04x)\n", - name, status); - return -ENETDOWN; - } + if (!(status & BMSR_LSTATUS)) { + printf("%s: link down (status: 0x%04x)\n", + name, status); + return -ENETDOWN; + } - /* First check for GMAC and that it is GiB capable */ - if (gem_is_gigabit_capable(macb)) { - lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000); + /* First check for GMAC and that it is GiB capable */ + if (gem_is_gigabit_capable(macb)) { + lpa = macb_mdio_read(macb, macb->phy_addr, MII_STAT1000); - if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL | - LPA_1000XHALF)) { - duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ? - 1 : 0); + if (lpa & (LPA_1000FULL | LPA_1000HALF | LPA_1000XFULL | + LPA_1000XHALF)) { + duplex = ((lpa & (LPA_1000FULL | LPA_1000XFULL)) ? + 1 : 0); - printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n", - name, - duplex ? "full" : "half", - lpa); + printf("%s: link up, 1000Mbps %s-duplex (lpa: 0x%04x)\n", + name, + duplex ? "full" : "half", + lpa); - ncfgr = macb_readl(macb, NCFGR); - ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); - ncfgr |= GEM_BIT(GBE); + ncfgr = macb_readl(macb, NCFGR); + ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + ncfgr |= GEM_BIT(GBE); - if (duplex) - ncfgr |= MACB_BIT(FD); + if (duplex) + ncfgr |= MACB_BIT(FD); - macb_writel(macb, NCFGR, ncfgr); + macb_writel(macb, NCFGR, ncfgr); - ret = macb_linkspd_cb(dev, _1000BASET); - if (ret) - return ret; + ret = macb_linkspd_cb(dev, _1000BASET); + if (ret) + return ret; - return 0; + return 0; + } } - } - /* fall back for EMAC checking */ - adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE); - lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA); - media = mii_nway_result(lpa & adv); - speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) - ? 1 : 0); - duplex = (media & ADVERTISE_FULL) ? 1 : 0; - printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", - name, - speed ? "100" : "10", - duplex ? "full" : "half", - lpa); + /* fall back for EMAC checking */ + adv = macb_mdio_read(macb, macb->phy_addr, MII_ADVERTISE); + lpa = macb_mdio_read(macb, macb->phy_addr, MII_LPA); + media = mii_nway_result(lpa & adv); + speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) + ? 1 : 0); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; + printf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n", + name, + speed ? "100" : "10", + duplex ? "full" : "half", + lpa); + } else { + /* if macb port is a fixed link */ + /* TODO : manage gigabit capable processors */ + speed = macb->speed; + duplex = macb->duplex; + printf("%s: link up, %sMbps %s-duplex\n", + name, + speed ? "100" : "10", + duplex ? "full" : "half"); + } ncfgr = macb_readl(macb, NCFGR); ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD) | GEM_BIT(GBE)); @@ -1276,6 +1296,28 @@ int __weak macb_late_eth_of_to_plat(struct udevice *dev) static int macb_eth_of_to_plat(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); + struct macb_device *macb = dev_get_priv(dev); + void *blob = (void *)gd->fdt_blob; + int node = dev_of_offset(dev); + int fl_node, speed_fdt; + + /* fetch 'fixed-link' property */ + fl_node = fdt_subnode_offset(blob, node, "fixed-link"); + if (fl_node >= 0) { + /* set phy_addr to invalid value for fixed link */ + macb->phy_addr = PHY_MAX_ADDR + 1; + macb->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex"); + speed_fdt = fdtdec_get_int(blob, fl_node, "speed", 0); + if (speed_fdt == 100) { + macb->speed = 1; + } else if (speed_fdt == 10) { + macb->speed = 0; + } else { + printf("%s: The given speed %d of ethernet in the DT is not supported\n", + __func__, speed_fdt); + return -EINVAL; + } + } pdata->iobase = (uintptr_t)dev_remap_addr(dev); if (!pdata->iobase) diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c index 3cfce05..75e7bcf 100644 --- a/drivers/net/mtk_eth.c +++ b/drivers/net/mtk_eth.c @@ -137,6 +137,7 @@ struct mtk_eth_priv { int force_mode; int speed; int duplex; + int mdc; bool pn_swap; struct phy_device *phydev; @@ -1245,7 +1246,8 @@ static int mtk_phy_start(struct mtk_eth_priv *priv) } if (!priv->force_mode) { - if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII) + if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII || + priv->phy_interface == PHY_INTERFACE_MODE_XGMII) mtk_xphy_link_adjust(priv); else mtk_phy_link_adjust(priv); @@ -1515,7 +1517,7 @@ static void mtk_mac_init(struct mtk_eth_priv *priv) static void mtk_xmac_init(struct mtk_eth_priv *priv) { - u32 sts; + u32 force_link = 0; switch (priv->phy_interface) { case PHY_INTERFACE_MODE_USXGMII: @@ -1530,15 +1532,19 @@ static void mtk_xmac_init(struct mtk_eth_priv *priv) SYSCFG0_GE_MODE_M << SYSCFG0_GE_MODE_S(priv->gmac_id), 0); - if (priv->gmac_id == 1) { + if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII && + priv->gmac_id == 1) { mtk_infra_rmw(priv, TOPMISC_NETSYS_PCS_MUX, NETSYS_PCS_MUX_MASK, MUX_G2_USXGMII_SEL); - } else if (priv->gmac_id == 2) { - sts = mtk_gmac_read(priv, XGMAC_STS(priv->gmac_id)); - sts |= XGMAC_FORCE_LINK; - mtk_gmac_write(priv, XGMAC_STS(priv->gmac_id), sts); } + if (priv->phy_interface == PHY_INTERFACE_MODE_XGMII || + priv->gmac_id == 2) + force_link = XGMAC_FORCE_LINK(priv->gmac_id); + + mtk_gmac_rmw(priv, XGMAC_STS(priv->gmac_id), + XGMAC_FORCE_LINK(priv->gmac_id), force_link); + /* Force GMAC link down */ mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), FORCE_MODE); } @@ -1607,6 +1613,26 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv) mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0); } +static void mtk_eth_mdc_init(struct mtk_eth_priv *priv) +{ + u32 divider; + + if (priv->mdc == 0) + return; + + divider = min_t(u32, DIV_ROUND_UP(MDC_MAX_FREQ, priv->mdc), MDC_MAX_DIVIDER); + + /* Configure MDC turbo mode */ + if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3)) + mtk_gmac_rmw(priv, GMAC_MAC_MISC_REG, 0, MISC_MDC_TURBO); + else + mtk_gmac_rmw(priv, GMAC_PPSC_REG, 0, MISC_MDC_TURBO); + + /* Configure MDC divider */ + mtk_gmac_rmw(priv, GMAC_PPSC_REG, PHY_MDC_CFG, + FIELD_PREP(PHY_MDC_CFG, divider)); +} + static int mtk_eth_start(struct udevice *dev) { struct mtk_eth_priv *priv = dev_get_priv(dev); @@ -1803,8 +1829,12 @@ static int mtk_eth_probe(struct udevice *dev) noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC, ARCH_DMA_MINALIGN); + /* Set MDC divider */ + mtk_eth_mdc_init(priv); + /* Set MAC mode */ - if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII) + if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII || + priv->phy_interface == PHY_INTERFACE_MODE_XGMII) mtk_xmac_init(priv); else mtk_mac_init(priv); @@ -1881,6 +1911,17 @@ static int mtk_eth_of_to_plat(struct udevice *dev) priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0); + priv->mdc = 0; + subnode = ofnode_find_subnode(dev_ofnode(dev), "mdio"); + if (ofnode_valid(subnode)) { + priv->mdc = ofnode_read_u32_default(subnode, "clock-frequency", 2500000); + if (priv->mdc > MDC_MAX_FREQ || + priv->mdc < MDC_MAX_FREQ / MDC_MAX_DIVIDER) { + printf("error: MDIO clock frequency out of range\n"); + return -EINVAL; + } + } + /* Interface mode is required */ pdata->phy_interface = dev_read_phy_mode(dev); priv->phy_interface = pdata->phy_interface; diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h index 491cac5..fd31c78 100644 --- a/drivers/net/mtk_eth.h +++ b/drivers/net/mtk_eth.h @@ -180,6 +180,12 @@ enum mkt_eth_capabilities { /* GMAC Registers */ +#define GMAC_PPSC_REG 0x0000 +#define PHY_MDC_CFG GENMASK(29, 24) +#define MDC_TURBO BIT(20) +#define MDC_MAX_FREQ 25000000 +#define MDC_MAX_DIVIDER 63 + #define GMAC_PIAC_REG 0x0004 #define PHY_ACS_ST BIT(31) #define MDIO_REG_ADDR_S 25 @@ -197,6 +203,7 @@ enum mkt_eth_capabilities { #define P1_XGMAC_FORCE_LINK BIT(15) #define GMAC_MAC_MISC_REG 0x0010 +#define MISC_MDC_TURBO BIT(4) #define GMAC_GSW_CFG_REG 0x0080 #define GSWTX_IPG_M 0xF0000 @@ -261,7 +268,7 @@ enum mkt_eth_capabilities { /* XGMAC Status Registers */ #define XGMAC_STS(x) (((x) == 2) ? 0x001C : 0x000C) -#define XGMAC_FORCE_LINK BIT(15) +#define XGMAC_FORCE_LINK(x) (((x) == 1) ? BIT(31) : BIT(15)) /* XGMAC Registers */ #define XGMAC_PORT_MCR(x) (0x2000 + (((x) - 1) * 0x1000)) diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig index c75f4186..72eccc9 100644 --- a/drivers/net/ti/Kconfig +++ b/drivers/net/ti/Kconfig @@ -45,7 +45,15 @@ config TI_AM65_CPSW_NUSS imply MISC_INIT_R imply MISC imply SYSCON + imply MDIO_TI_CPSW select PHYLIB help This driver supports TI K3 MCU CPSW Nuss Ethernet controller in Texas Instruments K3 AM65x SoCs. + +config MDIO_TI_CPSW + bool "TI CPSW MDIO interface support" + depends on DM_MDIO + help + This driver supports the TI CPSW MDIO interface found in various + TI SoCs. diff --git a/drivers/net/ti/Makefile b/drivers/net/ti/Makefile index 0ce0cf2..30c4c4b 100644 --- a/drivers/net/ti/Makefile +++ b/drivers/net/ti/Makefile @@ -5,4 +5,5 @@ obj-$(CONFIG_DRIVER_TI_CPSW) += cpsw.o cpsw-common.o cpsw_mdio.o obj-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o obj-$(CONFIG_DRIVER_TI_KEYSTONE_NET) += keystone_net.o cpsw_mdio.o -obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o cpsw_mdio.o +obj-$(CONFIG_TI_AM65_CPSW_NUSS) += am65-cpsw-nuss.o +obj-$(CONFIG_MDIO_TI_CPSW) += cpsw_mdio.o diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index 6da018c..d68ed67 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -31,8 +31,6 @@ #include <linux/printk.h> #include <linux/soc/ti/ti-udma.h> -#include "cpsw_mdio.h" - #define AM65_CPSW_CPSWNU_MAX_PORTS 9 #define AM65_CPSW_SS_BASE 0x0 @@ -113,7 +111,6 @@ struct am65_cpsw_common { struct udevice *dev; fdt_addr_t ss_base; fdt_addr_t cpsw_base; - fdt_addr_t mdio_base; fdt_addr_t ale_base; struct clk fclk; @@ -122,13 +119,8 @@ struct am65_cpsw_common { u32 port_num; struct am65_cpsw_port ports[AM65_CPSW_CPSWNU_MAX_PORTS]; - struct mii_dev *bus; u32 bus_freq; - struct gpio_desc mdio_gpio_reset; - u32 reset_delay_us; - u32 reset_post_delay_us; - struct dma dma_tx; struct dma dma_rx; u32 rx_next; @@ -140,13 +132,7 @@ struct am65_cpsw_priv { struct udevice *dev; struct am65_cpsw_common *cpsw_common; u32 port_id; - struct phy_device *phydev; - bool has_phy; - ofnode phy_node; - u32 phy_addr; - - bool mdio_manual_mode; }; #ifdef PKTSIZE_ALIGN @@ -622,111 +608,15 @@ static const struct eth_ops am65_cpsw_ops = { .read_rom_hwaddr = am65_cpsw_read_rom_hwaddr, }; -static const struct soc_attr k3_mdio_soc_data[] = { - { .family = "AM62X", .revision = "SR1.0" }, - { .family = "AM64X", .revision = "SR1.0" }, - { .family = "AM64X", .revision = "SR2.0" }, - { .family = "AM65X", .revision = "SR1.0" }, - { .family = "AM65X", .revision = "SR2.0" }, - { .family = "J7200", .revision = "SR1.0" }, - { .family = "J7200", .revision = "SR2.0" }, - { .family = "J721E", .revision = "SR1.0" }, - { .family = "J721E", .revision = "SR1.1" }, - { .family = "J721S2", .revision = "SR1.0" }, - { /* sentinel */ }, -}; - -static ofnode am65_cpsw_find_mdio(ofnode parent) -{ - ofnode node; - - ofnode_for_each_subnode(node, parent) - if (ofnode_device_is_compatible(node, "ti,cpsw-mdio")) - return node; - - return ofnode_null(); -} - -static int am65_cpsw_mdio_setup(struct udevice *dev) -{ - struct am65_cpsw_priv *priv = dev_get_priv(dev); - struct am65_cpsw_common *cpsw_common = priv->cpsw_common; - struct udevice *mdio_dev; - ofnode mdio; - int ret; - - mdio = am65_cpsw_find_mdio(dev_ofnode(cpsw_common->dev)); - if (!ofnode_valid(mdio)) - return 0; - - /* - * The MDIO controller is represented in the DT binding by a - * subnode of the MAC controller. - * - * We don't have a DM driver for the MDIO device yet, and thus any - * pinctrl setting on its node will be ignored. - * - * However, we do need to make sure the pins states tied to the - * MDIO node are configured properly. Fortunately, the core DM - * does that for use when we get a device, so we can work around - * that whole issue by just requesting a dummy MDIO driver to - * probe, and our pins will get muxed. - */ - ret = uclass_get_device_by_ofnode(UCLASS_MDIO, mdio, &mdio_dev); - if (ret) - return ret; - - return 0; -} - -static int am65_cpsw_mdio_init(struct udevice *dev) -{ - struct am65_cpsw_priv *priv = dev_get_priv(dev); - struct am65_cpsw_common *cpsw_common = priv->cpsw_common; - int ret; - - if (!priv->has_phy || cpsw_common->bus) - return 0; - - if (IS_ENABLED(CONFIG_DM_GPIO)) { - if (dm_gpio_is_valid(&cpsw_common->mdio_gpio_reset)) { - dm_gpio_set_value(&cpsw_common->mdio_gpio_reset, 1); - udelay(cpsw_common->reset_delay_us); - dm_gpio_set_value(&cpsw_common->mdio_gpio_reset, 0); - if (cpsw_common->reset_post_delay_us > 0) - udelay(cpsw_common->reset_post_delay_us); - } - } - - ret = am65_cpsw_mdio_setup(dev); - if (ret) - return ret; - - cpsw_common->bus = cpsw_mdio_init(dev->name, - cpsw_common->mdio_base, - cpsw_common->bus_freq, - clk_get_rate(&cpsw_common->fclk), - priv->mdio_manual_mode); - if (!cpsw_common->bus) - return -EFAULT; - - return 0; -} - static int am65_cpsw_phy_init(struct udevice *dev) { struct am65_cpsw_priv *priv = dev_get_priv(dev); - struct am65_cpsw_common *cpsw_common = priv->cpsw_common; struct eth_pdata *pdata = dev_get_plat(dev); struct phy_device *phydev; u32 supported = PHY_GBIT_FEATURES; int ret; - phydev = phy_connect(cpsw_common->bus, - priv->phy_addr, - priv->dev, - pdata->phy_interface); - + phydev = dm_eth_phy_connect(dev); if (!phydev) { dev_err(dev, "phy_connect() failed\n"); return -ENODEV; @@ -740,13 +630,10 @@ static int am65_cpsw_phy_init(struct udevice *dev) } phydev->advertising = phydev->supported; - if (ofnode_valid(priv->phy_node)) - phydev->node = priv->phy_node; - priv->phydev = phydev; ret = phy_config(phydev); if (ret < 0) - pr_err("phy_config() failed: %d", ret); + dev_err(dev, "phy_config() failed: %d", ret); return ret; } @@ -755,8 +642,6 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct am65_cpsw_priv *priv = dev_get_priv(dev); - struct ofnode_phandle_args out_args; - int ret = 0; dev_read_u32(dev, "reg", &priv->port_id); @@ -771,28 +656,7 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev) dev_err(dev, "Port %u speed froced to %uMbit\n", priv->port_id, pdata->max_speed); - priv->has_phy = true; - ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "phy-handle", - NULL, 0, 0, &out_args); - if (ret) { - dev_err(dev, "can't parse phy-handle port %u (%d)\n", - priv->port_id, ret); - priv->has_phy = false; - ret = 0; - } - - priv->phy_node = out_args.node; - if (priv->has_phy) { - ret = ofnode_read_u32(priv->phy_node, "reg", &priv->phy_addr); - if (ret) { - dev_err(dev, "failed to get phy_addr port %u (%d)\n", - priv->port_id, ret); - goto out; - } - } - -out: - return ret; + return 0; } static int am65_cpsw_port_probe(struct udevice *dev) @@ -811,10 +675,6 @@ static int am65_cpsw_port_probe(struct udevice *dev) sprintf(portname, "%s%s", dev->parent->name, dev->name); device_set_name(dev, portname); - priv->mdio_manual_mode = false; - if (soc_device_match(k3_mdio_soc_data)) - priv->mdio_manual_mode = true; - ret = am65_cpsw_ofdata_parse_phy(dev); if (ret) goto out; @@ -823,13 +683,8 @@ static int am65_cpsw_port_probe(struct udevice *dev) if (ret) goto out; - ret = am65_cpsw_mdio_init(dev); - if (ret) - goto out; - ret = am65_cpsw_phy_init(dev); - if (ret) - goto out; + out: return ret; } @@ -837,7 +692,7 @@ out: static int am65_cpsw_probe_nuss(struct udevice *dev) { struct am65_cpsw_common *cpsw_common = dev_get_priv(dev); - ofnode ports_np, node, mdio_np; + ofnode ports_np, node; int ret, i; struct udevice *port_dev; @@ -862,25 +717,6 @@ static int am65_cpsw_probe_nuss(struct udevice *dev) cpsw_common->cpsw_base = cpsw_common->ss_base + AM65_CPSW_CPSW_NU_BASE; cpsw_common->ale_base = cpsw_common->cpsw_base + AM65_CPSW_CPSW_NU_ALE_BASE; - cpsw_common->mdio_base = cpsw_common->ss_base + AM65_CPSW_MDIO_BASE; - - if (IS_ENABLED(CONFIG_DM_GPIO)) { - /* get bus level PHY reset GPIO details */ - mdio_np = dev_read_subnode(dev, "mdio"); - if (!ofnode_valid(mdio_np)) { - ret = -ENOENT; - goto out; - } - - cpsw_common->reset_delay_us = ofnode_read_u32_default(mdio_np, "reset-delay-us", - DEFAULT_GPIO_RESET_DELAY); - cpsw_common->reset_post_delay_us = ofnode_read_u32_default(mdio_np, - "reset-post-delay-us", - 0); - ret = gpio_request_by_name_nodev(mdio_np, "reset-gpios", 0, - &cpsw_common->mdio_gpio_reset, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); - } ports_np = dev_read_subnode(dev, "ethernet-ports"); if (!ofnode_valid(ports_np)) { @@ -940,12 +776,11 @@ static int am65_cpsw_probe_nuss(struct udevice *dev) dev_read_u32_default(dev, "bus_freq", AM65_CPSW_MDIO_BUS_FREQ_DEF); - dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u mdio_freq:%u\n", + dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u\n", readl(cpsw_common->ss_base), readl(cpsw_common->cpsw_base), readl(cpsw_common->ale_base), - cpsw_common->port_num, - cpsw_common->bus_freq); + cpsw_common->port_num); out: power_domain_free(&cpsw_common->pwrdmn); @@ -976,14 +811,3 @@ U_BOOT_DRIVER(am65_cpsw_nuss_port) = { .plat_auto = sizeof(struct eth_pdata), .flags = DM_FLAG_ALLOC_PRIV_DMA | DM_FLAG_OS_PREPARE, }; - -static const struct udevice_id am65_cpsw_mdio_ids[] = { - { .compatible = "ti,cpsw-mdio" }, - { } -}; - -U_BOOT_DRIVER(am65_cpsw_mdio) = { - .name = "am65_cpsw_mdio", - .id = UCLASS_MDIO, - .of_match = am65_cpsw_mdio_ids, -}; diff --git a/drivers/net/ti/cpsw_mdio.c b/drivers/net/ti/cpsw_mdio.c index 74cc956..f1b1eba 100644 --- a/drivers/net/ti/cpsw_mdio.c +++ b/drivers/net/ti/cpsw_mdio.c @@ -5,11 +5,15 @@ * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/ */ +#include <clk.h> #include <common.h> +#include <dm/device_compat.h> #include <log.h> #include <malloc.h> +#include <phy.h> #include <asm/io.h> #include <miiphy.h> +#include <soc.h> #include <wait_bit.h> #include <linux/bitops.h> #include <linux/delay.h> @@ -22,6 +26,7 @@ struct cpsw_mdio_regs { #define CONTROL_FAULT BIT(19) #define CONTROL_FAULT_ENABLE BIT(18) #define CONTROL_DIV_MASK GENMASK(15, 0) +#define CONTROL_MAX_DIV CONTROL_DIV_MASK #define MDIO_MAN_MDCLK_O BIT(2) #define MDIO_MAN_OE BIT(1) @@ -72,6 +77,8 @@ struct cpsw_mdio_regs { */ #define CPSW_MDIO_TIMEOUT 100 /* msecs */ +#define CPSW_MDIO_DEF_BUS_FREQ 2200000 /* 2.2 MHz */ + enum cpsw_mdio_manual { MDIO_PIN = 0, MDIO_OE, @@ -82,8 +89,35 @@ struct cpsw_mdio { struct cpsw_mdio_regs *regs; struct mii_dev *bus; int div; + bool manual_mode; + struct clk clk; + unsigned long bus_freq; }; +static int cpsw_mdio_enable(struct cpsw_mdio *data) +{ + int ret; + + /* set enable and clock divider */ + writel(data->div | CONTROL_ENABLE, &data->regs->control); + ret = wait_for_bit_le32(&data->regs->control, + CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true); + if (ret) + return ret; + + /* + * wait for scan logic to settle: + * the scan time consists of (a) a large fixed component, and (b) a + * small component that varies with the mii bus frequency. These + * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x + * silicon. Since the effect of (b) was found to be largely + * negligible, we keep things simple here. + */ + mdelay(1); + + return 0; +} + static void cpsw_mdio_disable(struct cpsw_mdio *mdio) { u32 reg; @@ -206,10 +240,16 @@ static void cpsw_mdio_sw_preamble(struct cpsw_mdio *mdio) } } +#if defined(CONFIG_DM_MDIO) +#define MII_TO_CPSW_MDIO(bus) (dev_get_priv((struct udevice *)(bus)->priv)) +#else +#define MII_TO_CPSW_MDIO(bus) ((bus)->priv) +#endif + static int cpsw_mdio_sw_read(struct mii_dev *bus, int phy_id, int dev_addr, int phy_reg) { - struct cpsw_mdio *mdio = bus->priv; + struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus); u32 reg, i; u8 ack; @@ -266,7 +306,7 @@ static int cpsw_mdio_sw_read(struct mii_dev *bus, int phy_id, static int cpsw_mdio_sw_write(struct mii_dev *bus, int phy_id, int dev_addr, int phy_reg, u16 phy_data) { - struct cpsw_mdio *mdio = bus->priv; + struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus); if ((phy_reg & ~PHY_REG_MASK) || (phy_id & ~PHY_ID_MASK)) return -EINVAL; @@ -316,7 +356,7 @@ static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio) static int cpsw_mdio_read(struct mii_dev *bus, int phy_id, int dev_addr, int phy_reg) { - struct cpsw_mdio *mdio = bus->priv; + struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus); int data, ret; u32 reg; @@ -342,7 +382,7 @@ static int cpsw_mdio_read(struct mii_dev *bus, int phy_id, static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr, int phy_reg, u16 data) { - struct cpsw_mdio *mdio = bus->priv; + struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus); u32 reg; int ret; @@ -361,9 +401,10 @@ static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr, return cpsw_mdio_wait_for_user_access(mdio); } +#if !defined(CONFIG_MDIO_TI_CPSW) u32 cpsw_mdio_get_alive(struct mii_dev *bus) { - struct cpsw_mdio *mdio = bus->priv; + struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus); u32 val; val = readl(&mdio->regs->alive); @@ -396,22 +437,11 @@ struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base, else cpsw_mdio->div = (fck_freq / bus_freq) - 1; cpsw_mdio->div &= CONTROL_DIV_MASK; - - /* set enable and clock divider */ - writel(cpsw_mdio->div | CONTROL_ENABLE | CONTROL_FAULT | - CONTROL_FAULT_ENABLE, &cpsw_mdio->regs->control); - wait_for_bit_le32(&cpsw_mdio->regs->control, - CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true); - - /* - * wait for scan logic to settle: - * the scan time consists of (a) a large fixed component, and (b) a - * small component that varies with the mii bus frequency. These - * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x - * silicon. Since the effect of (b) was found to be largely - * negligible, we keep things simple here. - */ - mdelay(1); + ret = cpsw_mdio_enable(cpsw_mdio); + if (ret) { + debug("mdio_enable failed: %d\n", ret); + goto free_bus; + } if (manual_mode) { cpsw_mdio->bus->read = cpsw_mdio_sw_read; @@ -452,3 +482,129 @@ void cpsw_mdio_free(struct mii_dev *bus) mdio_free(bus); free(mdio); } + +#else + +static int cpsw_mdio_init_clk(struct cpsw_mdio *data) +{ + u32 mdio_in, div; + + mdio_in = clk_get_rate(&data->clk); + div = (mdio_in / data->bus_freq) - 1; + if (div > CONTROL_MAX_DIV) + div = CONTROL_MAX_DIV; + + data->div = div; + return cpsw_mdio_enable(data); +} + +static int cpsw_mdio_bus_read(struct udevice *dev, int addr, + int devad, int reg) +{ + struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) : + NULL; + struct cpsw_mdio *priv = dev_get_priv(dev); + + if (pdata && pdata->mii_bus) { + if (priv->manual_mode) + return cpsw_mdio_sw_read(pdata->mii_bus, addr, devad, reg); + else + return cpsw_mdio_read(pdata->mii_bus, addr, devad, reg); + } + + return -1; +} + +static int cpsw_mdio_bus_write(struct udevice *dev, int addr, + int devad, int reg, u16 val) +{ + struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) : + NULL; + struct cpsw_mdio *priv = dev_get_priv(dev); + + if (pdata && pdata->mii_bus) { + if (priv->manual_mode) + return cpsw_mdio_sw_write(pdata->mii_bus, addr, devad, reg, val); + else + return cpsw_mdio_write(pdata->mii_bus, addr, devad, reg, val); + } + + return -1; +} + +static const struct mdio_ops cpsw_mdio_ops = { + .read = cpsw_mdio_bus_read, + .write = cpsw_mdio_bus_write, +}; + +static const struct soc_attr k3_mdio_soc_data[] = { + { .family = "AM62X", .revision = "SR1.0" }, + { .family = "AM64X", .revision = "SR1.0" }, + { .family = "AM64X", .revision = "SR2.0" }, + { .family = "AM65X", .revision = "SR1.0" }, + { .family = "AM65X", .revision = "SR2.0" }, + { .family = "J7200", .revision = "SR1.0" }, + { .family = "J7200", .revision = "SR2.0" }, + { .family = "J721E", .revision = "SR1.0" }, + { .family = "J721E", .revision = "SR1.1" }, + { .family = "J721S2", .revision = "SR1.0" }, + { /* sentinel */ }, +}; + +static const struct udevice_id cpsw_mdio_ids[] = { + { .compatible = "ti,davinci_mdio", }, + { .compatible = "ti,cpsw-mdio", }, + { /* sentinel */ }, +}; + +static int cpsw_mdio_probe(struct udevice *dev) +{ + struct cpsw_mdio *priv = dev_get_priv(dev); + int ret; + + if (!priv) { + dev_err(dev, "dev_get_priv(dev %p) = NULL\n", dev); + return -ENOMEM; + } + + priv->regs = dev_remap_addr(dev); + + if (soc_device_match(k3_mdio_soc_data)) + priv->manual_mode = true; + + ret = clk_get_by_name(dev, "fck", &priv->clk); + if (ret) { + dev_err(dev, "failed to get clock %d\n", ret); + return ret; + } + + priv->bus_freq = dev_read_u32_default(dev, "bus_freq", + CPSW_MDIO_DEF_BUS_FREQ); + ret = cpsw_mdio_init_clk(priv); + if (ret) { + dev_err(dev, "init clock failed: %d\n", ret); + return ret; + } + + return 0; +} + +static int cpsw_mdio_remove(struct udevice *dev) +{ + struct cpsw_mdio *priv = dev_get_priv(dev); + + cpsw_mdio_disable(priv); + + return 0; +} + +U_BOOT_DRIVER(cpsw_mdio) = { + .name = "cpsw_mdio", + .id = UCLASS_MDIO, + .of_match = cpsw_mdio_ids, + .probe = cpsw_mdio_probe, + .remove = cpsw_mdio_remove, + .ops = &cpsw_mdio_ops, + .priv_auto = sizeof(struct cpsw_mdio), +}; +#endif /* CONFIG_MDIO_TI_CPSW */ diff --git a/drivers/net/ti/cpsw_mdio.h b/drivers/net/ti/cpsw_mdio.h index ddf65a4..240c972 100644 --- a/drivers/net/ti/cpsw_mdio.h +++ b/drivers/net/ti/cpsw_mdio.h @@ -10,9 +10,11 @@ struct cpsw_mdio; +#if !defined(CONFIG_MDIO_TI_CPSW) struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base, u32 bus_freq, int fck_freq, bool manual_mode); void cpsw_mdio_free(struct mii_dev *bus); u32 cpsw_mdio_get_alive(struct mii_dev *bus); +#endif /* CONFIG_MDIO_TI_CPSW */ #endif /* CPSW_MDIO_H_ */ diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 463ec47..8d02ab8 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -413,4 +413,15 @@ config PCIE_STARFIVE_JH7110 Say Y here if you want to enable PLDA XpressRich PCIe controller support on StarFive JH7110 SoC. +config PCIE_DW_IMX + bool "i.MX DW PCIe controller support" + depends on ARCH_IMX8M + select PCIE_DW_COMMON + select DM_REGULATOR + select REGMAP + select SYSCON + help + Say Y here if you want to enable DW PCIe controller support on + iMX SoCs. + endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 72ef8b4..2927c51 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -53,3 +53,4 @@ obj-$(CONFIG_PCIE_UNIPHIER) += pcie_uniphier.o obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o obj-$(CONFIG_PCIE_PLDA_COMMON) += pcie_plda_common.o obj-$(CONFIG_PCIE_STARFIVE_JH7110) += pcie_starfive_jh7110.o +obj-$(CONFIG_PCIE_DW_IMX) += pcie_dw_imx.o diff --git a/drivers/pci/pcie_dw_imx.c b/drivers/pci/pcie_dw_imx.c new file mode 100644 index 0000000..a2ee228 --- /dev/null +++ b/drivers/pci/pcie_dw_imx.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Linaro Ltd. + * + * Author: Sumit Garg <sumit.garg@linaro.org> + */ + +#include <asm/io.h> +#include <asm-generic/gpio.h> +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <generic-phy.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/iopoll.h> +#include <log.h> +#include <pci.h> +#include <power/regulator.h> +#include <regmap.h> +#include <reset.h> +#include <syscon.h> +#include <time.h> + +#include "pcie_dw_common.h" + +#define PCIE_LINK_CAPABILITY 0x7c +#define TARGET_LINK_SPEED_MASK 0xf +#define LINK_SPEED_GEN_1 0x1 +#define LINK_SPEED_GEN_2 0x2 +#define LINK_SPEED_GEN_3 0x3 + +#define PCIE_MISC_CONTROL_1_OFF 0x8bc +#define PCIE_DBI_RO_WR_EN BIT(0) + +#define PCIE_PORT_DEBUG0 0x728 +#define PCIE_PORT_DEBUG1 0x72c +#define PCIE_PORT_DEBUG1_LINK_UP BIT(4) +#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING BIT(29) + +#define PCIE_LINK_UP_TIMEOUT_MS 100 + +#define IOMUXC_GPR14_OFFSET 0x38 +#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN BIT(10) +#define IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE BIT(11) + +struct pcie_dw_imx { + /* Must be first member of the struct */ + struct pcie_dw dw; + struct regmap *iomuxc_gpr; + struct clk_bulk clks; + struct gpio_desc reset_gpio; + struct reset_ctl apps_reset; + struct phy phy; + struct udevice *vpcie; +}; + +static void pcie_dw_configure(struct pcie_dw_imx *priv, u32 cap_speed) +{ + dw_pcie_dbi_write_enable(&priv->dw, true); + + clrsetbits_le32(priv->dw.dbi_base + PCIE_LINK_CAPABILITY, + TARGET_LINK_SPEED_MASK, cap_speed); + + dw_pcie_dbi_write_enable(&priv->dw, false); +} + +static void imx_pcie_ltssm_enable(struct pcie_dw_imx *priv) +{ + reset_deassert(&priv->apps_reset); +} + +static void imx_pcie_ltssm_disable(struct pcie_dw_imx *priv) +{ + reset_assert(&priv->apps_reset); +} + +static bool is_link_up(u32 val) +{ + return ((val & PCIE_PORT_DEBUG1_LINK_UP) && + (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING))); +} + +static int wait_link_up(struct pcie_dw_imx *priv) +{ + u32 val; + + return readl_poll_sleep_timeout(priv->dw.dbi_base + PCIE_PORT_DEBUG1, + val, is_link_up(val), 10000, 100000); +} + +static int pcie_link_up(struct pcie_dw_imx *priv, u32 cap_speed) +{ + int ret; + + /* DW pre link configurations */ + pcie_dw_configure(priv, cap_speed); + + /* Initiate link training */ + imx_pcie_ltssm_enable(priv); + + /* Check that link was established */ + ret = wait_link_up(priv); + if (ret) + imx_pcie_ltssm_disable(priv); + + return ret; +} + +static int imx_pcie_assert_core_reset(struct pcie_dw_imx *priv) +{ + if (dm_gpio_is_valid(&priv->reset_gpio)) { + dm_gpio_set_value(&priv->reset_gpio, 1); + mdelay(20); + } + + return reset_assert(&priv->apps_reset); +} + +static int imx_pcie_clk_enable(struct pcie_dw_imx *priv) +{ + int ret; + + ret = clk_enable_bulk(&priv->clks); + if (ret) + return ret; + + /* + * Set the over ride low and enabled make sure that + * REF_CLK is turned on. + */ + regmap_update_bits(priv->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE, 0); + regmap_update_bits(priv->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN, + IMX8M_GPR_PCIE_CLK_REQ_OVERRIDE_EN); + + /* allow the clocks to stabilize */ + udelay(500); + + return 0; +} + +static void imx_pcie_deassert_core_reset(struct pcie_dw_imx *priv) +{ + if (!dm_gpio_is_valid(&priv->reset_gpio)) + return; + + mdelay(100); + dm_gpio_set_value(&priv->reset_gpio, 0); + /* Wait for 100ms after PERST# deassertion (PCIe r5.0, 6.6.1) */ + mdelay(100); +} + +static int pcie_dw_imx_probe(struct udevice *dev) +{ + struct pcie_dw_imx *priv = dev_get_priv(dev); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + int ret; + + if (priv->vpcie) { + ret = regulator_set_enable(priv->vpcie, true); + if (ret) { + dev_err(dev, "failed to enable vpcie regulator\n"); + return ret; + } + } + + ret = imx_pcie_assert_core_reset(priv); + if (ret) { + dev_err(dev, "failed to assert core reset\n"); + return ret; + } + + ret = imx_pcie_clk_enable(priv); + if (ret) { + dev_err(dev, "failed to enable clocks\n"); + goto err_clk; + } + + ret = generic_phy_init(&priv->phy); + if (ret) { + dev_err(dev, "failed to initialize PHY\n"); + goto err_phy_init; + } + + ret = generic_phy_power_on(&priv->phy); + if (ret) { + dev_err(dev, "failed to power on PHY\n"); + goto err_phy_power; + } + + imx_pcie_deassert_core_reset(priv); + + priv->dw.first_busno = dev_seq(dev); + priv->dw.dev = dev; + pcie_dw_setup_host(&priv->dw); + + if (pcie_link_up(priv, LINK_SPEED_GEN_1)) { + printf("PCIE-%d: Link down\n", dev_seq(dev)); + ret = -ENODEV; + goto err_link; + } + + printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev_seq(dev), + pcie_dw_get_link_speed(&priv->dw), + pcie_dw_get_link_width(&priv->dw), + hose->first_busno); + + pcie_dw_prog_outbound_atu_unroll(&priv->dw, PCIE_ATU_REGION_INDEX0, + PCIE_ATU_TYPE_MEM, + priv->dw.mem.phys_start, + priv->dw.mem.bus_start, priv->dw.mem.size); + + return 0; + +err_link: + generic_shutdown_phy(&priv->phy); +err_phy_power: + generic_phy_exit(&priv->phy); +err_phy_init: + clk_disable_bulk(&priv->clks); +err_clk: + imx_pcie_deassert_core_reset(priv); + + return ret; +} + +static int pcie_dw_imx_remove(struct udevice *dev) +{ + struct pcie_dw_imx *priv = dev_get_priv(dev); + + generic_shutdown_phy(&priv->phy); + dm_gpio_free(dev, &priv->reset_gpio); + reset_free(&priv->apps_reset); + clk_release_bulk(&priv->clks); + + return 0; +} + +static int pcie_dw_imx_of_to_plat(struct udevice *dev) +{ + struct pcie_dw_imx *priv = dev_get_priv(dev); + ofnode gpr; + int ret; + + /* Get the controller base address */ + priv->dw.dbi_base = (void *)dev_read_addr_name(dev, "dbi"); + if ((fdt_addr_t)priv->dw.dbi_base == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get dbi_base address\n"); + return -EINVAL; + } + + /* Get the config space base address and size */ + priv->dw.cfg_base = (void *)dev_read_addr_size_name(dev, "config", + &priv->dw.cfg_size); + if ((fdt_addr_t)priv->dw.cfg_base == FDT_ADDR_T_NONE) { + dev_err(dev, "failed to get cfg_base address\n"); + return -EINVAL; + } + + ret = clk_get_bulk(dev, &priv->clks); + if (ret) { + dev_err(dev, "failed to get PCIe clks\n"); + return ret; + } + + ret = reset_get_by_name(dev, "apps", &priv->apps_reset); + if (ret) { + dev_err(dev, + "Failed to get PCIe apps reset control\n"); + goto err_reset; + } + + ret = gpio_request_by_name(dev, "reset-gpio", 0, &priv->reset_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (ret) { + dev_err(dev, "unable to get reset-gpio\n"); + goto err_gpio; + } + + ret = generic_phy_get_by_name(dev, "pcie-phy", &priv->phy); + if (ret) { + dev_err(dev, "failed to get pcie phy\n"); + goto err_phy; + } + + gpr = ofnode_by_compatible(ofnode_null(), "fsl,imx8mp-iomuxc-gpr"); + if (ofnode_equal(gpr, ofnode_null())) { + dev_err(dev, "unable to find GPR node\n"); + ret = -ENODEV; + goto err_phy; + } + + priv->iomuxc_gpr = syscon_node_to_regmap(gpr); + if (IS_ERR(priv->iomuxc_gpr)) { + dev_err(dev, "unable to find iomuxc registers\n"); + ret = PTR_ERR(priv->iomuxc_gpr); + goto err_phy; + } + + /* vpcie-supply regulator is optional */ + device_get_supply_regulator(dev, "vpcie-supply", &priv->vpcie); + + return 0; + +err_phy: + dm_gpio_free(dev, &priv->reset_gpio); +err_gpio: + reset_free(&priv->apps_reset); +err_reset: + clk_release_bulk(&priv->clks); + + return ret; +} + +static const struct dm_pci_ops pcie_dw_imx_ops = { + .read_config = pcie_dw_read_config, + .write_config = pcie_dw_write_config, +}; + +static const struct udevice_id pcie_dw_imx_ids[] = { + { .compatible = "fsl,imx8mp-pcie" }, + { } +}; + +U_BOOT_DRIVER(pcie_dw_imx) = { + .name = "pcie_dw_imx", + .id = UCLASS_PCI, + .of_match = pcie_dw_imx_ids, + .ops = &pcie_dw_imx_ops, + .of_to_plat = pcie_dw_imx_of_to_plat, + .probe = pcie_dw_imx_probe, + .remove = pcie_dw_imx_remove, + .priv_auto = sizeof(struct pcie_dw_imx), +}; diff --git a/drivers/pci/pcie_ecam_generic.c b/drivers/pci/pcie_ecam_generic.c index 2e089b0..f5bc6e3 100644 --- a/drivers/pci/pcie_ecam_generic.c +++ b/drivers/pci/pcie_ecam_generic.c @@ -10,7 +10,7 @@ #include <common.h> #include <dm.h> #include <pci.h> -#include <asm/global_data.h> +#include <linux/ioport.h> #include <linux/printk.h> #include <asm/io.h> @@ -133,18 +133,17 @@ static int pci_generic_ecam_write_config(struct udevice *bus, pci_dev_t bdf, static int pci_generic_ecam_of_to_plat(struct udevice *dev) { struct generic_ecam_pcie *pcie = dev_get_priv(dev); - struct fdt_resource reg_res; - DECLARE_GLOBAL_DATA_PTR; + ofnode node = dev_ofnode(dev); + struct resource reg_res; int err; - err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg", - 0, ®_res); + err = ofnode_read_resource(node, 0, ®_res); if (err < 0) { pr_err("\"reg\" resource not found\n"); return err; } - pcie->size = fdt_resource_size(®_res); + pcie->size = resource_size(®_res); pcie->cfg_base = map_physmem(reg_res.start, pcie->size, MAP_NOCACHE); return 0; diff --git a/drivers/pci/pcie_imx.c b/drivers/pci/pcie_imx.c index 4a18b0e09..78f2c7d 100644 --- a/drivers/pci/pcie_imx.c +++ b/drivers/pci/pcie_imx.c @@ -7,6 +7,14 @@ * Based on upstream Linux kernel driver: * pci-imx6.c: Sean Cross <xobs@kosagi.com> * pcie-designware.c: Jingoo Han <jg1.han@samsung.com> + * + * This is a legacy PCIe iMX driver kept to support older iMX6 SoCs. It is + * rather tied to quite old port of pcie-designware driver from Linux which + * suffices only iMX6 specific needs. But now we have modern PCIe iMX driver + * (drivers/pci/pcie_dw_imx.c) utilizing all the common DWC specific bits from + * (drivers/pci/pcie_dw_common.*). So you are encouraged to add any further iMX + * SoC support there or even better if you posses older iMX6 SoCs then switch + * those too in order to have a single modern PCIe iMX driver. */ #include <common.h> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 60138be..8f76787 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -284,6 +284,17 @@ config PHY_IMX8MQ_USB help Support the USB3.0 PHY in NXP i.MX8MQ or i.MX8MP SoC +config PHY_IMX8M_PCIE + bool "NXP i.MX8MM/i.MX8MP PCIe PHY Driver" + depends on PHY + depends on IMX8MM || IMX8MP + select REGMAP + select SYSCON + help + Support the PCIe PHY in NXP i.MX8MM or i.MX8MP SoC + + This PHY is found on i.MX8M devices supporting PCIe. + config PHY_XILINX_ZYNQMP tristate "Xilinx ZynqMP PHY driver" depends on PHY && ARCH_ZYNQMP diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 2e87231..7a2b764 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o obj-$(CONFIG_PHY_MTK_TPHY) += phy-mtk-tphy.o obj-$(CONFIG_PHY_NPCM_USB) += phy-npcm-usb.o obj-$(CONFIG_PHY_IMX8MQ_USB) += phy-imx8mq-usb.o +obj-$(CONFIG_PHY_IMX8M_PCIE) += phy-imx8m-pcie.o obj-$(CONFIG_PHY_XILINX_ZYNQMP) += phy-zynqmp.o obj-y += cadence/ obj-y += ti/ diff --git a/drivers/phy/phy-imx8m-pcie.c b/drivers/phy/phy-imx8m-pcie.c new file mode 100644 index 0000000..2418388 --- /dev/null +++ b/drivers/phy/phy-imx8m-pcie.c @@ -0,0 +1,283 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2024 Linaro Ltd. + * + * Derived from Linux counterpart driver + */ + +#include <asm/io.h> +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <generic-phy.h> +#include <linux/bitfield.h> +#include <linux/clk-provider.h> +#include <linux/iopoll.h> +#include <syscon.h> +#include <regmap.h> +#include <reset.h> + +#include <dt-bindings/phy/phy-imx8-pcie.h> + +#define IMX8MM_PCIE_PHY_CMN_REG061 0x184 +#define ANA_PLL_CLK_OUT_TO_EXT_IO_EN BIT(0) +#define IMX8MM_PCIE_PHY_CMN_REG062 0x188 +#define ANA_PLL_CLK_OUT_TO_EXT_IO_SEL BIT(3) +#define IMX8MM_PCIE_PHY_CMN_REG063 0x18C +#define AUX_PLL_REFCLK_SEL_SYS_PLL GENMASK(7, 6) +#define IMX8MM_PCIE_PHY_CMN_REG064 0x190 +#define ANA_AUX_RX_TX_SEL_TX BIT(7) +#define ANA_AUX_RX_TERM_GND_EN BIT(3) +#define ANA_AUX_TX_TERM BIT(2) +#define IMX8MM_PCIE_PHY_CMN_REG065 0x194 +#define ANA_AUX_RX_TERM (BIT(7) | BIT(4)) +#define ANA_AUX_TX_LVL GENMASK(3, 0) +#define IMX8MM_PCIE_PHY_CMN_REG075 0x1D4 +#define ANA_PLL_DONE 0x3 +#define PCIE_PHY_TRSV_REG5 0x414 +#define PCIE_PHY_TRSV_REG6 0x418 + +#define IMX8MM_GPR_PCIE_REF_CLK_SEL GENMASK(25, 24) +#define IMX8MM_GPR_PCIE_REF_CLK_PLL FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x3) +#define IMX8MM_GPR_PCIE_REF_CLK_EXT FIELD_PREP(IMX8MM_GPR_PCIE_REF_CLK_SEL, 0x2) +#define IMX8MM_GPR_PCIE_AUX_EN BIT(19) +#define IMX8MM_GPR_PCIE_CMN_RST BIT(18) +#define IMX8MM_GPR_PCIE_POWER_OFF BIT(17) +#define IMX8MM_GPR_PCIE_SSC_EN BIT(16) +#define IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE BIT(9) + +#define IOMUXC_GPR14_OFFSET 0x38 + +enum imx8_pcie_phy_type { + IMX8MM, + IMX8MP, +}; + +struct imx8_pcie_phy_drvdata { + const char *gpr; + enum imx8_pcie_phy_type variant; +}; + +struct imx8_pcie_phy { + ulong base; + struct clk hsio_clk; + struct regmap *iomuxc_gpr; + struct reset_ctl perst; + struct reset_ctl reset; + u32 refclk_pad_mode; + u32 tx_deemph_gen1; + u32 tx_deemph_gen2; + bool clkreq_unused; + const struct imx8_pcie_phy_drvdata *drvdata; +}; + +static int imx8_pcie_phy_power_on(struct phy *phy) +{ + int ret; + u32 val, pad_mode; + struct imx8_pcie_phy *imx8_phy = dev_get_priv(phy->dev); + + pad_mode = imx8_phy->refclk_pad_mode; + switch (imx8_phy->drvdata->variant) { + case IMX8MM: + reset_assert(&imx8_phy->reset); + + /* Tune PHY de-emphasis setting to pass PCIe compliance. */ + if (imx8_phy->tx_deemph_gen1) + writel(imx8_phy->tx_deemph_gen1, + imx8_phy->base + PCIE_PHY_TRSV_REG5); + if (imx8_phy->tx_deemph_gen2) + writel(imx8_phy->tx_deemph_gen2, + imx8_phy->base + PCIE_PHY_TRSV_REG6); + break; + case IMX8MP: /* Do nothing. */ + break; + } + + if (pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT || + pad_mode == IMX8_PCIE_REFCLK_PAD_UNUSED) { + /* Configure the pad as input */ + val = readl(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061); + writel(val & ~ANA_PLL_CLK_OUT_TO_EXT_IO_EN, + imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061); + } else { + /* Configure the PHY to output the refclock via pad */ + writel(ANA_PLL_CLK_OUT_TO_EXT_IO_EN, + imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG061); + } + + if (pad_mode == IMX8_PCIE_REFCLK_PAD_OUTPUT || + pad_mode == IMX8_PCIE_REFCLK_PAD_UNUSED) { + /* Source clock from SoC internal PLL */ + writel(ANA_PLL_CLK_OUT_TO_EXT_IO_SEL, + imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG062); + writel(AUX_PLL_REFCLK_SEL_SYS_PLL, + imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG063); + val = ANA_AUX_RX_TX_SEL_TX | ANA_AUX_TX_TERM; + writel(val | ANA_AUX_RX_TERM_GND_EN, + imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG064); + writel(ANA_AUX_RX_TERM | ANA_AUX_TX_LVL, + imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG065); + } + + /* Set AUX_EN_OVERRIDE 1'b0, when the CLKREQ# isn't hooked */ + regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE, + imx8_phy->clkreq_unused ? + 0 : IMX8MM_GPR_PCIE_AUX_EN_OVERRIDE); + regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8MM_GPR_PCIE_AUX_EN, + IMX8MM_GPR_PCIE_AUX_EN); + regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8MM_GPR_PCIE_POWER_OFF, 0); + regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8MM_GPR_PCIE_SSC_EN, 0); + + regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8MM_GPR_PCIE_REF_CLK_SEL, + pad_mode == IMX8_PCIE_REFCLK_PAD_INPUT ? + IMX8MM_GPR_PCIE_REF_CLK_EXT : + IMX8MM_GPR_PCIE_REF_CLK_PLL); + udelay(200); + + /* Do the PHY common block reset */ + regmap_update_bits(imx8_phy->iomuxc_gpr, IOMUXC_GPR14_OFFSET, + IMX8MM_GPR_PCIE_CMN_RST, + IMX8MM_GPR_PCIE_CMN_RST); + + switch (imx8_phy->drvdata->variant) { + case IMX8MP: + reset_deassert(&imx8_phy->perst); + fallthrough; + case IMX8MM: + reset_deassert(&imx8_phy->reset); + udelay(500); + break; + } + + /* Polling to check the phy is ready or not. */ + ret = readl_poll_timeout(imx8_phy->base + IMX8MM_PCIE_PHY_CMN_REG075, + val, val == ANA_PLL_DONE, 20000); + return ret; +} + +static int imx8_pcie_phy_init(struct phy *phy) +{ + struct imx8_pcie_phy *imx8_phy = dev_get_priv(phy->dev); + + return clk_enable(&imx8_phy->hsio_clk); +} + +static int imx8_pcie_phy_exit(struct phy *phy) +{ + struct imx8_pcie_phy *imx8_phy = dev_get_priv(phy->dev); + + return clk_disable(&imx8_phy->hsio_clk); +} + +static const struct phy_ops imx8_pcie_phy_ops = { + .init = imx8_pcie_phy_init, + .exit = imx8_pcie_phy_exit, + .power_on = imx8_pcie_phy_power_on, +}; + +static const struct imx8_pcie_phy_drvdata imx8mm_drvdata = { + .gpr = "fsl,imx8mm-iomuxc-gpr", + .variant = IMX8MM, +}; + +static const struct imx8_pcie_phy_drvdata imx8mp_drvdata = { + .gpr = "fsl,imx8mp-iomuxc-gpr", + .variant = IMX8MP, +}; + +static const struct udevice_id imx8_pcie_phy_of_match[] = { + {.compatible = "fsl,imx8mm-pcie-phy", .data = (ulong)&imx8mm_drvdata, }, + {.compatible = "fsl,imx8mp-pcie-phy", .data = (ulong)&imx8mp_drvdata, }, + { }, +}; + +static int imx8_pcie_phy_probe(struct udevice *dev) +{ + struct imx8_pcie_phy *imx8_phy = dev_get_priv(dev); + ofnode gpr; + int ret = 0; + + imx8_phy->drvdata = (void *)dev_get_driver_data(dev); + imx8_phy->base = dev_read_addr(dev); + if (!imx8_phy->base) + return -EINVAL; + + /* get PHY refclk pad mode */ + dev_read_u32(dev, "fsl,refclk-pad-mode", &imx8_phy->refclk_pad_mode); + + imx8_phy->tx_deemph_gen1 = dev_read_u32_default(dev, + "fsl,tx-deemph-gen1", + 0); + imx8_phy->tx_deemph_gen2 = dev_read_u32_default(dev, + "fsl,tx-deemph-gen2", + 0); + imx8_phy->clkreq_unused = dev_read_bool(dev, "fsl,clkreq-unsupported"); + + /* Grab GPR config register range */ + gpr = ofnode_by_compatible(ofnode_null(), imx8_phy->drvdata->gpr); + if (ofnode_equal(gpr, ofnode_null())) { + dev_err(dev, "unable to find GPR node\n"); + return -ENODEV; + } + + imx8_phy->iomuxc_gpr = syscon_node_to_regmap(gpr); + if (IS_ERR(imx8_phy->iomuxc_gpr)) { + dev_err(dev, "unable to find iomuxc registers\n"); + return PTR_ERR(imx8_phy->iomuxc_gpr); + } + + ret = clk_get_by_name(dev, "ref", &imx8_phy->hsio_clk); + if (ret) { + dev_err(dev, "Failed to get PCIEPHY ref clock\n"); + return ret; + } + + ret = reset_get_by_name(dev, "pciephy", &imx8_phy->reset); + if (ret) { + dev_err(dev, "Failed to get PCIEPHY reset control\n"); + return ret; + } + + if (imx8_phy->drvdata->variant == IMX8MP) { + ret = reset_get_by_name(dev, "perst", &imx8_phy->perst); + if (ret) { + dev_err(dev, + "Failed to get PCIEPHY PHY PERST control\n"); + goto err_perst; + } + } + + return 0; + +err_perst: + reset_free(&imx8_phy->reset); + return ret; +} + +static int imx8_pcie_phy_remove(struct udevice *dev) +{ + struct imx8_pcie_phy *imx8_phy = dev_get_priv(dev); + + if (imx8_phy->drvdata->variant == IMX8MP) + reset_free(&imx8_phy->perst); + + reset_free(&imx8_phy->reset); + + return 0; +} + +U_BOOT_DRIVER(nxp_imx8_pcie_phy) = { + .name = "nxp_imx8_pcie_phy", + .id = UCLASS_PHY, + .of_match = imx8_pcie_phy_of_match, + .probe = imx8_pcie_phy_probe, + .remove = imx8_pcie_phy_remove, + .ops = &imx8_pcie_phy_ops, + .priv_auto = sizeof(struct imx8_pcie_phy), +}; diff --git a/drivers/phy/qcom/msm8916-usbh-phy.c b/drivers/phy/qcom/msm8916-usbh-phy.c index 7c9d030..f52046f 100644 --- a/drivers/phy/qcom/msm8916-usbh-phy.c +++ b/drivers/phy/qcom/msm8916-usbh-phy.c @@ -74,7 +74,7 @@ static int msm_phy_probe(struct udevice *dev) { struct msm_phy_priv *priv = dev_get_priv(dev); - priv->regs = dev_remap_addr(dev); + priv->regs = dev_remap_addr(dev_get_parent(dev)); if (!priv->regs) return -EINVAL; @@ -96,7 +96,7 @@ static struct phy_ops msm_phy_ops = { }; static const struct udevice_id msm_phy_ids[] = { - { .compatible = "qcom,apq8016-usbphy" }, + { .compatible = "qcom,usb-hs-phy-msm8916" }, { } }; diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index 70e61ec..d392aed 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -6,23 +6,16 @@ * Copyright (C) 2020 Amarula Solutions(India) */ -#include <common.h> #include <clk-uclass.h> #include <dm.h> -#include <asm/global_data.h> #include <dm/device_compat.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <generic-phy.h> -#include <reset.h> +#include <regmap.h> #include <syscon.h> -#include <asm/gpio.h> -#include <asm/io.h> -#include <linux/iopoll.h> #include <asm/arch-rockchip/clock.h> -DECLARE_GLOBAL_DATA_PTR; - #define usleep_range(a, b) udelay((b)) #define BIT_WRITEABLE_SHIFT 16 @@ -42,16 +35,6 @@ struct usb2phy_reg { struct rockchip_usb2phy_port_cfg { struct usb2phy_reg phy_sus; - struct usb2phy_reg bvalid_det_en; - struct usb2phy_reg bvalid_det_st; - struct usb2phy_reg bvalid_det_clr; - struct usb2phy_reg ls_det_en; - struct usb2phy_reg ls_det_st; - struct usb2phy_reg ls_det_clr; - struct usb2phy_reg utmi_avalid; - struct usb2phy_reg utmi_bvalid; - struct usb2phy_reg utmi_ls; - struct usb2phy_reg utmi_hstdet; }; struct rockchip_usb2phy_cfg { @@ -61,30 +44,39 @@ struct rockchip_usb2phy_cfg { }; struct rockchip_usb2phy { - void *reg_base; + struct regmap *reg_base; struct clk phyclk; const struct rockchip_usb2phy_cfg *phy_cfg; }; -static inline int property_enable(void *reg_base, +static inline int property_enable(struct regmap *base, const struct usb2phy_reg *reg, bool en) { unsigned int val, mask, tmp; + if (!reg->offset && !reg->enable && !reg->disable) + return 0; + tmp = en ? reg->enable : reg->disable; mask = GENMASK(reg->bitend, reg->bitstart); val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); - return writel(val, reg_base + reg->offset); + return regmap_write(base, reg->offset, val); } -static inline bool property_enabled(void *reg_base, +static inline bool property_enabled(struct regmap *base, const struct usb2phy_reg *reg) { + int ret; unsigned int tmp, orig; unsigned int mask = GENMASK(reg->bitend, reg->bitstart); - orig = readl(reg_base + reg->offset); + if (!reg->offset && !reg->enable && !reg->disable) + return false; + + ret = regmap_read(base, reg->offset, &orig); + if (ret) + return false; tmp = (orig & mask) >> reg->bitstart; return tmp != reg->disable; @@ -129,7 +121,6 @@ static int rockchip_usb2phy_init(struct phy *phy) { struct udevice *parent = dev_get_parent(phy->dev); struct rockchip_usb2phy *priv = dev_get_priv(parent); - const struct rockchip_usb2phy_port_cfg *port_cfg = us2phy_get_port(phy); int ret; ret = clk_enable(&priv->phyclk); @@ -138,14 +129,6 @@ static int rockchip_usb2phy_init(struct phy *phy) return ret; } - if (phy->id == USB2PHY_PORT_OTG) { - property_enable(priv->reg_base, &port_cfg->bvalid_det_clr, true); - property_enable(priv->reg_base, &port_cfg->bvalid_det_en, true); - } else if (phy->id == USB2PHY_PORT_HOST) { - property_enable(priv->reg_base, &port_cfg->bvalid_det_clr, true); - property_enable(priv->reg_base, &port_cfg->bvalid_det_en, true); - } - return 0; } @@ -248,7 +231,11 @@ static int rockchip_usb2phy_probe(struct udevice *dev) unsigned int reg; int index, ret; - priv->reg_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + if (dev_read_bool(dev, "rockchip,usbgrf")) + priv->reg_base = + syscon_regmap_lookup_by_phandle(dev, "rockchip,usbgrf"); + else + priv->reg_base = syscon_get_regmap(dev_get_parent(dev)); if (IS_ERR(priv->reg_base)) return PTR_ERR(priv->reg_base); @@ -305,11 +292,8 @@ static int rockchip_usb2phy_bind(struct udevice *dev) int ret = 0; dev_for_each_subnode(node, dev) { - if (!ofnode_valid(node)) { - dev_info(dev, "subnode %s not found\n", dev->name); - ret = -ENXIO; - goto bind_fail; - } + if (!ofnode_is_enabled(node)) + continue; name = ofnode_get_name(node); dev_dbg(dev, "subnode %s\n", name); @@ -348,27 +332,13 @@ bind_fail: static const struct rockchip_usb2phy_cfg rk3328_usb2phy_cfgs[] = { { .reg = 0x100, - .clkout_ctl = { 0x108, 4, 4, 1, 0 }, + .clkout_ctl = { 0x0108, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { - .phy_sus = { 0x0100, 15, 0, 0, 0x1d1 }, - .bvalid_det_en = { 0x0110, 3, 2, 0, 3 }, - .bvalid_det_st = { 0x0114, 3, 2, 0, 3 }, - .bvalid_det_clr = { 0x0118, 3, 2, 0, 3 }, - .ls_det_en = { 0x0110, 0, 0, 0, 1 }, - .ls_det_st = { 0x0114, 0, 0, 0, 1 }, - .ls_det_clr = { 0x0118, 0, 0, 0, 1 }, - .utmi_avalid = { 0x0120, 10, 10, 0, 1 }, - .utmi_bvalid = { 0x0120, 9, 9, 0, 1 }, - .utmi_ls = { 0x0120, 5, 4, 0, 1 }, + .phy_sus = { 0x0100, 1, 0, 2, 1 }, }, [USB2PHY_PORT_HOST] = { - .phy_sus = { 0x104, 15, 0, 0, 0x1d1 }, - .ls_det_en = { 0x110, 1, 1, 0, 1 }, - .ls_det_st = { 0x114, 1, 1, 0, 1 }, - .ls_det_clr = { 0x118, 1, 1, 0, 1 }, - .utmi_ls = { 0x120, 17, 16, 0, 1 }, - .utmi_hstdet = { 0x120, 19, 19, 0, 1 } + .phy_sus = { 0x0104, 1, 0, 2, 1 }, } }, }, @@ -382,19 +352,9 @@ static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = { .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0xe454, 1, 0, 2, 1 }, - .bvalid_det_en = { 0xe3c0, 3, 3, 0, 1 }, - .bvalid_det_st = { 0xe3e0, 3, 3, 0, 1 }, - .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 }, - .utmi_avalid = { 0xe2ac, 7, 7, 0, 1 }, - .utmi_bvalid = { 0xe2ac, 12, 12, 0, 1 }, }, [USB2PHY_PORT_HOST] = { - .phy_sus = { 0xe458, 1, 0, 0x2, 0x1 }, - .ls_det_en = { 0xe3c0, 6, 6, 0, 1 }, - .ls_det_st = { 0xe3e0, 6, 6, 0, 1 }, - .ls_det_clr = { 0xe3d0, 6, 6, 0, 1 }, - .utmi_ls = { 0xe2ac, 22, 21, 0, 1 }, - .utmi_hstdet = { 0xe2ac, 23, 23, 0, 1 } + .phy_sus = { 0xe458, 1, 0, 2, 1 }, } }, }, @@ -404,19 +364,9 @@ static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = { .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0xe464, 1, 0, 2, 1 }, - .bvalid_det_en = { 0xe3c0, 8, 8, 0, 1 }, - .bvalid_det_st = { 0xe3e0, 8, 8, 0, 1 }, - .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 }, - .utmi_avalid = { 0xe2ac, 10, 10, 0, 1 }, - .utmi_bvalid = { 0xe2ac, 16, 16, 0, 1 }, }, [USB2PHY_PORT_HOST] = { - .phy_sus = { 0xe468, 1, 0, 0x2, 0x1 }, - .ls_det_en = { 0xe3c0, 11, 11, 0, 1 }, - .ls_det_st = { 0xe3e0, 11, 11, 0, 1 }, - .ls_det_clr = { 0xe3d0, 11, 11, 0, 1 }, - .utmi_ls = { 0xe2ac, 26, 25, 0, 1 }, - .utmi_hstdet = { 0xe2ac, 27, 27, 0, 1 } + .phy_sus = { 0xe468, 1, 0, 2, 1 }, } }, }, @@ -429,24 +379,10 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { - .phy_sus = { 0x0000, 8, 0, 0x052, 0x1d1 }, - .bvalid_det_en = { 0x0080, 2, 2, 0, 1 }, - .bvalid_det_st = { 0x0084, 2, 2, 0, 1 }, - .bvalid_det_clr = { 0x0088, 2, 2, 0, 1 }, - .ls_det_en = { 0x0080, 0, 0, 0, 1 }, - .ls_det_st = { 0x0084, 0, 0, 0, 1 }, - .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, - .utmi_avalid = { 0x00c0, 10, 10, 0, 1 }, - .utmi_bvalid = { 0x00c0, 9, 9, 0, 1 }, - .utmi_ls = { 0x00c0, 5, 4, 0, 1 }, + .phy_sus = { 0x0000, 1, 0, 2, 1 }, }, [USB2PHY_PORT_HOST] = { - .phy_sus = { 0x0004, 8, 0, 0x1d2, 0x1d1 }, - .ls_det_en = { 0x0080, 1, 1, 0, 1 }, - .ls_det_st = { 0x0084, 1, 1, 0, 1 }, - .ls_det_clr = { 0x0088, 1, 1, 0, 1 }, - .utmi_ls = { 0x00c0, 17, 16, 0, 1 }, - .utmi_hstdet = { 0x00c0, 19, 19, 0, 1 } + .phy_sus = { 0x0004, 1, 0, 2, 1 }, } }, }, @@ -455,20 +391,10 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { .clkout_ctl = { 0x0008, 4, 4, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { - .phy_sus = { 0x0000, 8, 0, 0x1d2, 0x1d1 }, - .ls_det_en = { 0x0080, 0, 0, 0, 1 }, - .ls_det_st = { 0x0084, 0, 0, 0, 1 }, - .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, - .utmi_ls = { 0x00c0, 5, 4, 0, 1 }, - .utmi_hstdet = { 0x00c0, 7, 7, 0, 1 } + .phy_sus = { 0x0000, 1, 0, 2, 1 }, }, [USB2PHY_PORT_HOST] = { - .phy_sus = { 0x0004, 8, 0, 0x1d2, 0x1d1 }, - .ls_det_en = { 0x0080, 1, 1, 0, 1 }, - .ls_det_st = { 0x0084, 1, 1, 0, 1 }, - .ls_det_clr = { 0x0088, 1, 1, 0, 1 }, - .utmi_ls = { 0x00c0, 17, 16, 0, 1 }, - .utmi_hstdet = { 0x00c0, 19, 19, 0, 1 } + .phy_sus = { 0x0004, 1, 0, 2, 1 }, } }, }, @@ -478,49 +404,37 @@ static const struct rockchip_usb2phy_cfg rk3568_phy_cfgs[] = { static const struct rockchip_usb2phy_cfg rk3588_phy_cfgs[] = { { .reg = 0x0000, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { .phy_sus = { 0x000c, 11, 11, 0, 1 }, - .ls_det_en = { 0x0080, 0, 0, 0, 1 }, - .ls_det_st = { 0x0084, 0, 0, 0, 1 }, - .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, - .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, } }, }, { .reg = 0x4000, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_OTG] = { - .phy_sus = { 0x000c, 11, 11, 0, 0 }, - .ls_det_en = { 0x0080, 0, 0, 0, 1 }, - .ls_det_st = { 0x0084, 0, 0, 0, 1 }, - .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, - .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, + .phy_sus = { 0x000c, 11, 11, 0, 1 }, } }, }, { .reg = 0x8000, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_HOST] = { .phy_sus = { 0x0008, 2, 2, 0, 1 }, - .ls_det_en = { 0x0080, 0, 0, 0, 1 }, - .ls_det_st = { 0x0084, 0, 0, 0, 1 }, - .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, - .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, } }, }, { .reg = 0xc000, + .clkout_ctl = { 0x0000, 0, 0, 1, 0 }, .port_cfgs = { [USB2PHY_PORT_HOST] = { .phy_sus = { 0x0008, 2, 2, 0, 1 }, - .ls_det_en = { 0x0080, 0, 0, 0, 1 }, - .ls_det_st = { 0x0084, 0, 0, 0, 1 }, - .ls_det_clr = { 0x0088, 0, 0, 0, 1 }, - .utmi_ls = { 0x00c0, 10, 9, 0, 1 }, } }, }, diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2600.c b/drivers/pinctrl/aspeed/pinctrl_ast2600.c index 97e8b4e..8a4f970 100644 --- a/drivers/pinctrl/aspeed/pinctrl_ast2600.c +++ b/drivers/pinctrl/aspeed/pinctrl_ast2600.c @@ -267,6 +267,14 @@ static struct aspeed_sig_desc fmcquad_link[] = { { 0x438, GENMASK(5, 4), 0 }, }; +static struct aspeed_sig_desc siopbi_link[] = { + { 0x418, BIT(6), 0 }, +}; + +static struct aspeed_sig_desc siopbo_link[] = { + { 0x418, BIT(5), 0 }, +}; + static struct aspeed_sig_desc spi1_link[] = { { 0x438, GENMASK(13, 11), 0 }, }; @@ -303,6 +311,22 @@ static struct aspeed_sig_desc spi2quad_link[] = { { 0x434, GENMASK(31, 30), 0 }, }; +static struct aspeed_sig_desc thru0_link[] = { + { 0x4bc, GENMASK(25, 24), 0 }, +}; + +static struct aspeed_sig_desc thru1_link[] = { + { 0x4bc, GENMASK(27, 26), 0 }, +}; + +static struct aspeed_sig_desc thru2_link[] = { + { 0x4bc, GENMASK(29, 28), 0 }, +}; + +static struct aspeed_sig_desc thru3_link[] = { + { 0x4bc, GENMASK(31, 30), 0 }, +}; + static struct aspeed_sig_desc fsi1[] = { { 0xd48, GENMASK(21, 20), 0 }, }; @@ -458,6 +482,8 @@ static const struct aspeed_group_config ast2600_groups[] = { { "EMMC", ARRAY_SIZE(emmc_link), emmc_link }, { "EMMCG8", ARRAY_SIZE(emmcg8_link), emmcg8_link }, { "FMCQUAD", ARRAY_SIZE(fmcquad_link), fmcquad_link }, + { "SIOPBI", ARRAY_SIZE(siopbi_link), siopbi_link }, + { "SIOPBO", ARRAY_SIZE(siopbo_link), siopbo_link }, { "SPI1", ARRAY_SIZE(spi1_link), spi1_link }, { "SPI1ABR", ARRAY_SIZE(spi1abr_link), spi1abr_link }, { "SPI1CS1", ARRAY_SIZE(spi1cs1_link), spi1cs1_link }, @@ -467,6 +493,10 @@ static const struct aspeed_group_config ast2600_groups[] = { { "SPI2CS1", ARRAY_SIZE(spi2cs1_link), spi2cs1_link }, { "SPI2CS2", ARRAY_SIZE(spi2cs2_link), spi2cs2_link }, { "SPI2QUAD", ARRAY_SIZE(spi2quad_link), spi2quad_link }, + { "THRU0", ARRAY_SIZE(thru0_link), thru0_link }, + { "THRU1", ARRAY_SIZE(thru1_link), thru1_link }, + { "THRU2", ARRAY_SIZE(thru2_link), thru2_link }, + { "THRU3", ARRAY_SIZE(thru3_link), thru3_link }, { "I2C1", ARRAY_SIZE(i2c1_link), i2c1_link }, { "I2C2", ARRAY_SIZE(i2c2_link), i2c2_link }, { "I2C3", ARRAY_SIZE(i2c3_link), i2c3_link }, diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 73dd7b1..fe2ba50 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -100,6 +100,22 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename) return 0; } +static bool ofnode_pre_reloc_recursive(ofnode parent) +{ + ofnode child; + + if (ofnode_pre_reloc(parent)) + return true; + + if (CONFIG_IS_ENABLED(PINCONF_RECURSIVE)) { + ofnode_for_each_subnode(child, parent) + if (ofnode_pre_reloc_recursive(child)) + return true; + } + + return false; +} + /** * pinconfig_post_bind() - post binding for PINCONFIG uclass * Recursively bind its children as pinconfig devices. @@ -119,7 +135,7 @@ static int pinconfig_post_bind(struct udevice *dev) dev_for_each_subnode(node, dev) { if (pre_reloc_only && - !ofnode_pre_reloc(node)) + !ofnode_pre_reloc_recursive(node)) continue; /* * If this node has "compatible" property, this is not diff --git a/drivers/pinctrl/qcom/pinctrl-apq8016.c b/drivers/pinctrl/qcom/pinctrl-apq8016.c index 8149ffd..db0e212 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8016.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8016.c @@ -14,22 +14,22 @@ #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); static const char * const msm_pinctrl_pins[] = { - "SDC1_CLK", - "SDC1_CMD", - "SDC1_DATA", - "SDC2_CLK", - "SDC2_CMD", - "SDC2_DATA", - "QDSD_CLK", - "QDSD_CMD", - "QDSD_DATA0", - "QDSD_DATA1", - "QDSD_DATA2", - "QDSD_DATA3", + "sdc1_clk", + "sdc1_cmd", + "sdc1_data", + "sdc2_clk", + "sdc2_cmd", + "sdc2_data", + "qdsd_clk", + "qdsd_cmd", + "qdsd_data0", + "qdsd_data1", + "qdsd_data2", + "qdsd_data3", }; static const struct pinctrl_function msm_pinctrl_functions[] = { - {"blsp1_uart", 2}, + {"blsp_uart2", 2}, }; static const char *apq8016_get_function_name(struct udevice *dev, @@ -42,7 +42,7 @@ static const char *apq8016_get_pin_name(struct udevice *dev, unsigned int selector) { if (selector < 122) { - snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); return pin_name; } else { return msm_pinctrl_pins[selector - 122]; @@ -55,7 +55,10 @@ static unsigned int apq8016_get_function_mux(unsigned int selector) } static const struct msm_pinctrl_data apq8016_data = { - .pin_data = { .pin_count = 133, }, + .pin_data = { + .pin_count = 133, + .special_pins_start = 122, + }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = apq8016_get_function_name, .get_function_mux = apq8016_get_function_mux, @@ -73,4 +76,5 @@ U_BOOT_DRIVER(pinctrl_apq8016) = { .of_match = msm_pinctrl_ids, .ops = &msm_pinctrl_ops, .bind = msm_pinctrl_bind, + .flags = DM_FLAG_PRE_RELOC, }; diff --git a/drivers/pinctrl/qcom/pinctrl-apq8096.c b/drivers/pinctrl/qcom/pinctrl-apq8096.c index d64ab1f..880df8f 100644 --- a/drivers/pinctrl/qcom/pinctrl-apq8096.c +++ b/drivers/pinctrl/qcom/pinctrl-apq8096.c @@ -14,13 +14,13 @@ #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); static const char * const msm_pinctrl_pins[] = { - "SDC1_CLK", - "SDC1_CMD", - "SDC1_DATA", - "SDC2_CLK", - "SDC2_CMD", - "SDC2_DATA", - "SDC1_RCLK", + "sdc1_clk", + "sdc1_cmd", + "sdc1_data", + "sdc2_clk", + "sdc2_cmd", + "sdc2_data", + "sdc1_rclk", }; static const struct pinctrl_function msm_pinctrl_functions[] = { @@ -37,7 +37,7 @@ static const char *apq8096_get_pin_name(struct udevice *dev, unsigned int selector) { if (selector < 150) { - snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); return pin_name; } else { return msm_pinctrl_pins[selector - 150]; @@ -50,7 +50,10 @@ static unsigned int apq8096_get_function_mux(unsigned int selector) } static const struct msm_pinctrl_data apq8096_data = { - .pin_data = { .pin_count = 157, }, + .pin_data = { + .pin_count = 157, + .special_pins_start = 150, + }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = apq8096_get_function_name, .get_function_mux = apq8096_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-ipq4019.c b/drivers/pinctrl/qcom/pinctrl-ipq4019.c index 2d99f99..74c04ab 100644 --- a/drivers/pinctrl/qcom/pinctrl-ipq4019.c +++ b/drivers/pinctrl/qcom/pinctrl-ipq4019.c @@ -46,7 +46,10 @@ static unsigned int ipq4019_get_function_mux(unsigned int selector) } static const struct msm_pinctrl_data ipq4019_data = { - .pin_data = { .pin_count = 100, }, + .pin_data = { + .pin_count = 100, + .special_pins_start = 100, /* There are no special pins */ + }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = ipq4019_get_function_name, .get_function_mux = ipq4019_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-qcom.c b/drivers/pinctrl/qcom/pinctrl-qcom.c index dc3d8c4..ee0624d 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcom.c +++ b/drivers/pinctrl/qcom/pinctrl-qcom.c @@ -16,6 +16,7 @@ #include <asm/gpio.h> #include <dm/pinctrl.h> #include <linux/bitops.h> +#include <linux/bug.h> #include <mach/gpio.h> #include "pinctrl-qcom.h" @@ -83,6 +84,10 @@ static int msm_pinmux_set(struct udevice *dev, unsigned int pin_selector, { struct msm_pinctrl_priv *priv = dev_get_priv(dev); + /* Always NOP for special pins, assume they're in the correct state */ + if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) + return 0; + clrsetbits_le32(priv->base + GPIO_CONFIG_REG(priv, pin_selector), TLMM_FUNC_SEL_MASK | TLMM_GPIO_DISABLE, priv->data->get_function_mux(func_selector) << 2); @@ -94,6 +99,10 @@ static int msm_pinconf_set(struct udevice *dev, unsigned int pin_selector, { struct msm_pinctrl_priv *priv = dev_get_priv(dev); + /* Always NOP for special pins */ + if (qcom_is_special_pin(&priv->data->pin_data, pin_selector)) + return 0; + switch (param) { case PIN_CONFIG_DRIVE_STRENGTH: argument = (argument / 2) - 1; @@ -136,6 +145,9 @@ int msm_pinctrl_bind(struct udevice *dev) const char *name; int ret; + if (!data->pin_data.special_pins_start) + dev_warn(dev, "Special pins start index not defined!\n"); + drv = lists_driver_lookup_name("pinctrl_qcom"); if (!drv) return -ENOENT; diff --git a/drivers/pinctrl/qcom/pinctrl-qcs404.c b/drivers/pinctrl/qcom/pinctrl-qcs404.c index ac00afa..3a2d468 100644 --- a/drivers/pinctrl/qcom/pinctrl-qcs404.c +++ b/drivers/pinctrl/qcom/pinctrl-qcs404.c @@ -10,20 +10,24 @@ #include "pinctrl-qcom.h" +#define NORTH 0x00300000 +#define SOUTH 0x00000000 +#define EAST 0x06b00000 + #define MAX_PIN_NAME_LEN 32 static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); static const char * const msm_pinctrl_pins[] = { - "SDC1_RCLK", - "SDC1_CLK", - "SDC1_CMD", - "SDC1_DATA", - "SDC2_CLK", - "SDC2_CMD", - "SDC2_DATA", + "sdc1_rclk", + "sdc1_clk", + "sdc1_cmd", + "sdc1_data", + "sdc2_clk", + "sdc2_cmd", + "sdc2_data", }; static const struct pinctrl_function msm_pinctrl_functions[] = { - {"blsp_uart2", 1}, + {"gpio", 0}, {"rgmii_int", 1}, {"rgmii_ck", 1}, {"rgmii_tx", 1}, @@ -37,6 +41,40 @@ static const struct pinctrl_function msm_pinctrl_functions[] = { {"blsp_i2c_scl_a2", 3}, {"blsp_i2c3", 2}, {"blsp_i2c4", 1}, + {"blsp_uart_tx_a2", 1}, + {"blsp_uart_rx_a2", 1}, +}; + +static const unsigned int qcs404_pin_offsets[] = { + [0] = SOUTH, [1] = SOUTH, [2] = SOUTH, [3] = SOUTH, [4] = SOUTH, + [5] = SOUTH, [6] = SOUTH, [7] = SOUTH, [8] = SOUTH, [9] = SOUTH, + [10] = SOUTH, [11] = SOUTH, [12] = SOUTH, [13] = SOUTH, [14] = SOUTH, + [15] = SOUTH, [16] = SOUTH, [17] = NORTH, [18] = NORTH, [19] = NORTH, + [20] = NORTH, [21] = SOUTH, [22] = NORTH, [23] = NORTH, [24] = NORTH, + [25] = NORTH, [26] = EAST, [27] = EAST, [28] = EAST, [29] = EAST, + [30] = NORTH, [31] = NORTH, [32] = NORTH, [33] = NORTH, [34] = SOUTH, + [35] = SOUTH, [36] = NORTH, [37] = NORTH, [38] = NORTH, [39] = EAST, + [40] = EAST, [41] = EAST, [42] = EAST, [43] = EAST, [44] = EAST, + [45] = EAST, [46] = EAST, [47] = EAST, [48] = EAST, [49] = EAST, + [50] = EAST, [51] = EAST, [52] = EAST, [53] = EAST, [54] = EAST, + [55] = EAST, [56] = EAST, [57] = EAST, [58] = EAST, [59] = EAST, + [60] = NORTH, [61] = NORTH, [62] = NORTH, [63] = NORTH, [64] = NORTH, + [65] = NORTH, [66] = NORTH, [67] = NORTH, [68] = NORTH, [69] = NORTH, + [70] = NORTH, [71] = NORTH, [72] = NORTH, [73] = NORTH, [74] = NORTH, + [75] = NORTH, [76] = NORTH, [77] = NORTH, [78] = EAST, [79] = EAST, + [80] = EAST, [81] = EAST, [82] = NORTH, [83] = NORTH, [84] = NORTH, + [85] = NORTH, [86] = EAST, [87] = EAST, [88] = EAST, [89] = EAST, + [90] = EAST, [91] = EAST, [92] = EAST, [93] = EAST, [94] = EAST, + [95] = EAST, [96] = EAST, [97] = EAST, [98] = EAST, [99] = EAST, + [100] = EAST, [101] = EAST, [102] = EAST, [103] = EAST, [104] = EAST, + [105] = EAST, [106] = EAST, [107] = EAST, [108] = EAST, [109] = EAST, + [110] = EAST, [111] = EAST, [112] = EAST, [113] = EAST, [114] = EAST, + [115] = EAST, [116] = EAST, [117] = NORTH, [118] = NORTH, [119] = EAST, + /* + * There's 126 pins but the last ones are special and have non-standard registers + * so we leave them out here. The pinctrl and GPIO drivers both currently ignore + * these pins. + */ }; static const char *qcs404_get_function_name(struct udevice *dev, @@ -49,7 +87,7 @@ static const char *qcs404_get_pin_name(struct udevice *dev, unsigned int selector) { if (selector < 120) { - snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); + snprintf(pin_name, MAX_PIN_NAME_LEN, "gpio%u", selector); return pin_name; } else { return msm_pinctrl_pins[selector - 120]; @@ -61,8 +99,12 @@ static unsigned int qcs404_get_function_mux(unsigned int selector) return msm_pinctrl_functions[selector].val; } -static struct msm_pinctrl_data qcs404_data = { - .pin_data = { .pin_count = 126, }, +static const struct msm_pinctrl_data qcs404_data = { + .pin_data = { + .pin_count = 126, + .pin_offsets = qcs404_pin_offsets, + .special_pins_start = 120, + }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = qcs404_get_function_name, .get_function_mux = qcs404_get_function_mux, diff --git a/drivers/pinctrl/qcom/pinctrl-sdm845.c b/drivers/pinctrl/qcom/pinctrl-sdm845.c index 9f0f408..76bd8c4 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdm845.c +++ b/drivers/pinctrl/qcom/pinctrl-sdm845.c @@ -75,10 +75,11 @@ static unsigned int sdm845_get_function_mux(unsigned int selector) return msm_pinctrl_functions[selector].val; } -static struct msm_pinctrl_data sdm845_data = { +static const struct msm_pinctrl_data sdm845_data = { .pin_data = { .pin_offsets = sdm845_pin_offsets, - .pin_count = ARRAY_SIZE(sdm845_pin_offsets), + .pin_count = 154, + .special_pins_start = 150, }, .functions_count = ARRAY_SIZE(msm_pinctrl_functions), .get_function_name = sdm845_get_function_name, diff --git a/drivers/power/domain/imx8mp-hsiomix.c b/drivers/power/domain/imx8mp-hsiomix.c index e2d772c..6188a04 100644 --- a/drivers/power/domain/imx8mp-hsiomix.c +++ b/drivers/power/domain/imx8mp-hsiomix.c @@ -6,9 +6,15 @@ #include <common.h> #include <asm/io.h> #include <clk.h> +#include <clk-uclass.h> #include <dm.h> #include <dm/device.h> #include <dm/device_compat.h> +#include <dm/device-internal.h> +#include <dm/lists.h> +#include <linux/bitfield.h> +#include <linux/delay.h> +#include <linux/iopoll.h> #include <power-domain-uclass.h> #include <dt-bindings/power/imx8mp-power.h> @@ -16,48 +22,94 @@ #define GPR_REG0 0x0 #define PCIE_CLOCK_MODULE_EN BIT(0) #define USB_CLOCK_MODULE_EN BIT(1) +#define PCIE_PHY_APB_RST BIT(4) +#define PCIE_PHY_INIT_RST BIT(5) +#define GPR_REG1 0x4 +#define PLL_LOCK BIT(13) +#define GPR_REG2 0x8 +#define P_PLL_MASK GENMASK(5, 0) +#define M_PLL_MASK GENMASK(15, 6) +#define S_PLL_MASK GENMASK(18, 16) +#define GPR_REG3 0xc +#define PLL_CKE BIT(17) +#define PLL_RST BIT(31) struct imx8mp_hsiomix_priv { void __iomem *base; struct clk clk_usb; + struct clk clk_pcie; struct power_domain pd_bus; struct power_domain pd_usb; + struct power_domain pd_pcie; struct power_domain pd_usb_phy1; struct power_domain pd_usb_phy2; + struct power_domain pd_pcie_phy; }; -static int imx8mp_hsiomix_on(struct power_domain *power_domain) +static int imx8mp_hsiomix_set(struct power_domain *power_domain, bool power_on) { struct udevice *dev = power_domain->dev; struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev); - struct power_domain *domain; + struct power_domain *domain = NULL; + struct clk *clk = NULL; + u32 gpr_reg0_bits = 0; int ret; - ret = power_domain_on(&priv->pd_bus); - if (ret) - return ret; - - if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) { + switch (power_domain->id) { + case IMX8MP_HSIOBLK_PD_USB: domain = &priv->pd_usb; - } else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY1) { + clk = &priv->clk_usb; + gpr_reg0_bits |= USB_CLOCK_MODULE_EN; + break; + case IMX8MP_HSIOBLK_PD_USB_PHY1: domain = &priv->pd_usb_phy1; - } else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY2) { + break; + case IMX8MP_HSIOBLK_PD_USB_PHY2: domain = &priv->pd_usb_phy2; - } else { - ret = -EINVAL; - goto err_pd; + break; + case IMX8MP_HSIOBLK_PD_PCIE: + domain = &priv->pd_pcie; + clk = &priv->clk_pcie; + gpr_reg0_bits |= PCIE_CLOCK_MODULE_EN; + break; + case IMX8MP_HSIOBLK_PD_PCIE_PHY: + domain = &priv->pd_pcie_phy; + /* Bits to deassert PCIe PHY reset */ + gpr_reg0_bits |= PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST; + break; + default: + dev_err(dev, "unknown power domain id: %ld\n", + power_domain->id); + return -EINVAL; } - ret = power_domain_on(domain); - if (ret) - goto err_pd; + if (power_on) { + ret = power_domain_on(&priv->pd_bus); + if (ret) + return ret; - ret = clk_enable(&priv->clk_usb); - if (ret) - goto err_clk; + ret = power_domain_on(domain); + if (ret) + goto err_pd; - if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) - setbits_le32(priv->base + GPR_REG0, USB_CLOCK_MODULE_EN); + if (clk) { + ret = clk_enable(clk); + if (ret) + goto err_clk; + } + + if (gpr_reg0_bits) + setbits_le32(priv->base + GPR_REG0, gpr_reg0_bits); + } else { + if (gpr_reg0_bits) + clrbits_le32(priv->base + GPR_REG0, gpr_reg0_bits); + + if (clk) + clk_disable(clk); + + power_domain_off(domain); + power_domain_off(&priv->pd_bus); + } return 0; @@ -68,36 +120,85 @@ err_pd: return ret; } +static int imx8mp_hsiomix_on(struct power_domain *power_domain) +{ + return imx8mp_hsiomix_set(power_domain, true); +} + static int imx8mp_hsiomix_off(struct power_domain *power_domain) { - struct udevice *dev = power_domain->dev; - struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev); + return imx8mp_hsiomix_set(power_domain, false); +} + +static int imx8mp_hsiomix_of_xlate(struct power_domain *power_domain, + struct ofnode_phandle_args *args) +{ + power_domain->id = args->args[0]; + + return 0; +} - if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) - clrbits_le32(priv->base + GPR_REG0, USB_CLOCK_MODULE_EN); +static int hsio_pll_clk_enable(struct clk *clk) +{ + void *base = (void *)dev_get_driver_data(clk->dev); + u32 val; + int ret; - clk_disable(&priv->clk_usb); + /* Setup HSIO PLL as 100 MHz output clock */ + clrsetbits_le32(base + GPR_REG2, + P_PLL_MASK | M_PLL_MASK | S_PLL_MASK, + FIELD_PREP(P_PLL_MASK, 12) | + FIELD_PREP(M_PLL_MASK, 800) | + FIELD_PREP(S_PLL_MASK, 4)); - if (power_domain->id == IMX8MP_HSIOBLK_PD_USB) - power_domain_off(&priv->pd_usb); - else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY1) - power_domain_off(&priv->pd_usb_phy1); - else if (power_domain->id == IMX8MP_HSIOBLK_PD_USB_PHY2) - power_domain_off(&priv->pd_usb_phy2); + /* de-assert PLL reset */ + setbits_le32(base + GPR_REG3, PLL_RST); - power_domain_off(&priv->pd_bus); + /* enable PLL */ + setbits_le32(base + GPR_REG3, PLL_CKE); - return 0; + /* Check if PLL is locked */ + ret = readl_poll_sleep_timeout(base + GPR_REG1, val, + val & PLL_LOCK, 10, 100000); + if (ret) + dev_err(clk->dev, "failed to lock HSIO PLL\n"); + + return ret; } -static int imx8mp_hsiomix_of_xlate(struct power_domain *power_domain, - struct ofnode_phandle_args *args) +static int hsio_pll_clk_disable(struct clk *clk) { - power_domain->id = args->args[0]; + void *base = (void *)dev_get_driver_data(clk->dev); + + clrbits_le32(base + GPR_REG3, PLL_CKE | PLL_RST); return 0; } +static const struct clk_ops hsio_pll_clk_ops = { + .enable = hsio_pll_clk_enable, + .disable = hsio_pll_clk_disable, +}; + +U_BOOT_DRIVER(hsio_pll) = { + .name = "hsio-pll", + .id = UCLASS_CLK, + .ops = &hsio_pll_clk_ops, +}; + +int imx8mp_hsiomix_bind(struct udevice *dev) +{ + struct driver *drv; + + drv = lists_driver_lookup_name("hsio-pll"); + if (!drv) + return -ENOENT; + + return device_bind_with_driver_data(dev, drv, "hsio-pll", + (ulong)dev_read_addr_ptr(dev), + dev_ofnode(dev), NULL); +} + static int imx8mp_hsiomix_probe(struct udevice *dev) { struct imx8mp_hsiomix_priv *priv = dev_get_priv(dev); @@ -109,6 +210,10 @@ static int imx8mp_hsiomix_probe(struct udevice *dev) if (ret < 0) return ret; + ret = clk_get_by_name(dev, "pcie", &priv->clk_pcie); + if (ret < 0) + return ret; + ret = power_domain_get_by_name(dev, &priv->pd_bus, "bus"); if (ret < 0) return ret; @@ -125,8 +230,20 @@ static int imx8mp_hsiomix_probe(struct udevice *dev) if (ret < 0) goto err_pd_usb_phy2; + ret = power_domain_get_by_name(dev, &priv->pd_pcie, "pcie"); + if (ret < 0) + goto err_pd_pcie; + + ret = power_domain_get_by_name(dev, &priv->pd_pcie_phy, "pcie-phy"); + if (ret < 0) + goto err_pd_pcie_phy; + return 0; +err_pd_pcie_phy: + power_domain_free(&priv->pd_pcie); +err_pd_pcie: + power_domain_free(&priv->pd_usb_phy2); err_pd_usb_phy2: power_domain_free(&priv->pd_usb_phy1); err_pd_usb_phy1: @@ -152,6 +269,7 @@ U_BOOT_DRIVER(imx8mp_hsiomix) = { .id = UCLASS_POWER_DOMAIN, .of_match = imx8mp_hsiomix_ids, .probe = imx8mp_hsiomix_probe, + .bind = imx8mp_hsiomix_bind, .priv_auto = sizeof(struct imx8mp_hsiomix_priv), .ops = &imx8mp_hsiomix_ops, }; diff --git a/drivers/power/domain/ti-power-domain.c b/drivers/power/domain/ti-power-domain.c index b34c982..8996c40 100644 --- a/drivers/power/domain/ti-power-domain.c +++ b/drivers/power/domain/ti-power-domain.c @@ -81,24 +81,37 @@ static const struct soc_attr ti_k3_soc_pd_data[] = { .family = "J7200", .data = &j7200_pd_platdata, }, -#elif CONFIG_SOC_K3_J721S2 +#endif +#if IS_ENABLED(CONFIG_SOC_K3_J721S2) { .family = "J721S2", .data = &j721s2_pd_platdata, }, #endif -#ifdef CONFIG_SOC_K3_AM625 +#if IS_ENABLED(CONFIG_SOC_K3_AM625) { .family = "AM62X", .data = &am62x_pd_platdata, }, #endif -#ifdef CONFIG_SOC_K3_AM62A7 +#if IS_ENABLED(CONFIG_SOC_K3_AM62A7) { .family = "AM62AX", .data = &am62ax_pd_platdata, }, #endif +#if IS_ENABLED(CONFIG_SOC_K3_J784S4) + { + .family = "J784S4", + .data = &j784s4_pd_platdata, + }, +#endif +#if IS_ENABLED(CONFIG_SOC_K3_AM62P5) + { + .family = "AM62PX", + .data = &am62px_pd_platdata, + }, +#endif { /* sentinel */ } }; diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig index 9b61b18..562c1a3 100644 --- a/drivers/power/pmic/Kconfig +++ b/drivers/power/pmic/Kconfig @@ -250,7 +250,7 @@ config PMIC_RK8XX This driver implements register read/write operations. config SPL_PMIC_RK8XX - bool "Enable support for Rockchip PMIC RK8XX" + bool "Enable support for Rockchip PMIC RK8XX in SPL" depends on SPL_DM_PMIC ---help--- The Rockchip RK808 PMIC provides four buck DC-DC convertors, 8 LDOs, diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c index 4e3a173..3a8261d 100644 --- a/drivers/power/pmic/rk8xx.c +++ b/drivers/power/pmic/rk8xx.c @@ -9,8 +9,10 @@ #include <dm/lists.h> #include <errno.h> #include <log.h> +#include <linux/bitfield.h> #include <power/rk8xx_pmic.h> #include <power/pmic.h> +#include <spi.h> #include <sysreset.h> static int rk8xx_sysreset_request(struct udevice *dev, enum sysreset_t type) @@ -32,6 +34,10 @@ static int rk8xx_sysreset_request(struct udevice *dev, enum sysreset_t type) pmic_clrsetbits(dev->parent, RK817_REG_SYS_CFG3, 0, BIT(0)); break; + case RK806_ID: + pmic_clrsetbits(dev->parent, RK806_REG_SYS_CFG3, 0, + BIT(0)); + break; default: printf("Unknown PMIC RK%x: Cannot shutdown\n", priv->variant); @@ -83,6 +89,11 @@ 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)}, +}; + static struct reg_data rk817_init_reg[] = { /* enable the under-voltage protection, * the under-voltage protection will shutdown the LDO3 and reset the PMIC @@ -92,7 +103,10 @@ static struct reg_data rk817_init_reg[] = { static const struct pmic_child_info pmic_children_info[] = { { .prefix = "DCDC_REG", .driver = "rk8xx_buck"}, + { .prefix = "dcdc-reg", .driver = "rk8xx_buck"}, { .prefix = "LDO_REG", .driver = "rk8xx_ldo"}, + { .prefix = "nldo-reg", .driver = "rk8xx_nldo"}, + { .prefix = "pldo-reg", .driver = "rk8xx_pldo"}, { .prefix = "SWITCH_REG", .driver = "rk8xx_switch"}, { }, }; @@ -102,11 +116,51 @@ static int rk8xx_reg_count(struct udevice *dev) return RK808_NUM_OF_REGS; } +#if CONFIG_IS_ENABLED(SPI) && CONFIG_IS_ENABLED(DM_SPI) +struct rk806_cmd { + uint8_t len: 4; /* Payload size in bytes - 1 */ + uint8_t reserved: 2; + uint8_t crc_en: 1; + uint8_t op: 1; /* READ=0; WRITE=1; */ + uint8_t reg_l; +#define REG_L_MASK GENMASK(7, 0) + uint8_t reg_h; +#define REG_H_MASK GENMASK(15, 8) +}; +#endif + static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff, int len) { int ret; +#if CONFIG_IS_ENABLED(SPI) && CONFIG_IS_ENABLED(DM_SPI) + if (device_get_uclass_id(dev->parent) == UCLASS_SPI) { + struct spi_slave *spi = dev_get_parent_priv(dev); + struct rk806_cmd cmd = { + .op = 1, + .len = len - 1, + .reg_l = FIELD_GET(REG_L_MASK, reg), + .reg_h = FIELD_GET(REG_H_MASK, reg), + }; + + ret = dm_spi_claim_bus(dev); + if (ret) { + debug("Couldn't claim bus for device: %p!\n", dev); + return ret; + } + + ret = spi_write_then_read(spi, (u8 *)&cmd, sizeof(cmd), buff, NULL, len); + if (ret) + debug("write error to device: %p register: %#x!\n", + dev, reg); + + dm_spi_release_bus(dev); + + return ret; + } +#endif + ret = dm_i2c_write(dev, reg, buff, len); if (ret) { debug("write error to device: %p register: %#x!\n", dev, reg); @@ -120,6 +174,33 @@ static int rk8xx_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { int ret; +#if CONFIG_IS_ENABLED(SPI) && CONFIG_IS_ENABLED(DM_SPI) + if (device_get_uclass_id(dev->parent) == UCLASS_SPI) { + struct spi_slave *spi = dev_get_parent_priv(dev); + struct rk806_cmd cmd = { + .op = 0, + .len = len - 1, + .reg_l = FIELD_GET(REG_L_MASK, reg), + .reg_h = FIELD_GET(REG_H_MASK, reg), + }; + + ret = dm_spi_claim_bus(dev); + if (ret) { + debug("Couldn't claim bus for device: %p!\n", dev); + return ret; + } + + ret = spi_write_then_read(spi, (u8 *)&cmd, sizeof(cmd), NULL, buff, len); + if (ret) + debug("read error to device: %p register: %#x!\n", + dev, reg); + + dm_spi_release_bus(dev); + + return ret; + } +#endif + ret = dm_i2c_read(dev, reg, buff, len); if (ret) { debug("read error from device: %p register: %#x!\n", dev, reg); @@ -181,6 +262,9 @@ static int rk8xx_probe(struct udevice *dev) device_is_compatible(dev, "rockchip,rk809")) { id_msb = RK817_ID_MSB; id_lsb = RK817_ID_LSB; + } else if (device_is_compatible(dev, "rockchip,rk806")) { + id_msb = RK806_ID_MSB; + id_lsb = RK806_ID_LSB; } else { id_msb = ID_MSB; id_lsb = ID_LSB; @@ -221,6 +305,12 @@ static int rk8xx_probe(struct udevice *dev) value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4); pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value); break; + case RK806_ID: + on_source = RK806_ON_SOURCE; + off_source = RK806_OFF_SOURCE; + init_data = rk806_init_reg; + init_data_num = ARRAY_SIZE(rk806_init_reg); + break; default: printf("Unknown PMIC: RK%x!!\n", priv->variant); return -EINVAL; @@ -263,6 +353,7 @@ static struct dm_pmic_ops rk8xx_ops = { static const struct udevice_id rk8xx_ids[] = { { .compatible = "rockchip,rk805" }, + { .compatible = "rockchip,rk806" }, { .compatible = "rockchip,rk808" }, { .compatible = "rockchip,rk809" }, { .compatible = "rockchip,rk816" }, diff --git a/drivers/power/regulator/rk8xx.c b/drivers/power/regulator/rk8xx.c index e80bd6c..1bd4605 100644 --- a/drivers/power/regulator/rk8xx.c +++ b/drivers/power/regulator/rk8xx.c @@ -25,6 +25,19 @@ #define NA 0xff /* Field Definitions */ +#define RK806_BUCK_CONFIG(n) (0x10 + (n) - 1) +#define RK806_BUCK_ON_VSEL(n) (0x1a + (n) - 1) +#define RK806_BUCK_SLP_VSEL(n) (0x24 + (n) - 1) +#define RK806_BUCK_VSEL_MASK 0xff + +#define RK806_NLDO_ON_VSEL(n) (0x43 + (n) - 1) +#define RK806_NLDO_SLP_VSEL(n) (0x48 + (n) - 1) +#define RK806_NLDO_VSEL_MASK 0xff + +#define RK806_PLDO_ON_VSEL(n) (0x4e + (n) - 1) +#define RK806_PLDO_SLP_VSEL(n) (0x54 + (n) - 1) +#define RK806_PLDO_VSEL_MASK 0xff + #define RK808_BUCK_VSEL_MASK 0x3f #define RK808_BUCK4_VSEL_MASK 0xf #define RK808_LDO_VSEL_MASK 0x1f @@ -91,6 +104,49 @@ struct rk8xx_reg_info { u8 max_sel; }; +static const struct rk8xx_reg_info rk806_buck[] = { + /* buck 1 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(1), RK806_BUCK_SLP_VSEL(1), RK806_BUCK_CONFIG(1), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 2 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(2), RK806_BUCK_SLP_VSEL(2), RK806_BUCK_CONFIG(2), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 3 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(3), RK806_BUCK_SLP_VSEL(3), RK806_BUCK_CONFIG(3), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 4 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(4), RK806_BUCK_SLP_VSEL(4), RK806_BUCK_CONFIG(4), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 5 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(5), RK806_BUCK_SLP_VSEL(5), RK806_BUCK_CONFIG(5), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 6 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(6), RK806_BUCK_SLP_VSEL(6), RK806_BUCK_CONFIG(6), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 7 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(7), RK806_BUCK_SLP_VSEL(7), RK806_BUCK_CONFIG(7), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 8 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(8), RK806_BUCK_SLP_VSEL(8), RK806_BUCK_CONFIG(8), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 9 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(9), RK806_BUCK_SLP_VSEL(9), RK806_BUCK_CONFIG(9), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, + /* buck 10 */ + { 500000, 6250, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0x00, 0x9f }, + { 1500000, 25000, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xa0, 0xeb }, + { 3400000, 0, RK806_BUCK_ON_VSEL(10), RK806_BUCK_SLP_VSEL(10), RK806_BUCK_CONFIG(10), RK806_BUCK_VSEL_MASK, 0xec, 0xff }, +}; + static const struct rk8xx_reg_info rk808_buck[] = { { 712500, 12500, REG_BUCK1_ON_VSEL, REG_BUCK1_SLP_VSEL, REG_BUCK1_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f }, { 712500, 12500, REG_BUCK2_ON_VSEL, REG_BUCK2_SLP_VSEL, REG_BUCK2_CONFIG, RK808_BUCK_VSEL_MASK, 0x00, 0x3f }, @@ -148,6 +204,45 @@ static const struct rk8xx_reg_info rk818_buck[] = { }; #ifdef ENABLE_DRIVER +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}, + { 3400000, 0, RK806_NLDO_ON_VSEL(1), RK806_NLDO_SLP_VSEL(1), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff}, + /* nldo 2 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_NLDO_ON_VSEL(2), RK806_NLDO_SLP_VSEL(2), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff}, + /* nldo 3 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_NLDO_ON_VSEL(3), RK806_NLDO_SLP_VSEL(3), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff}, + /* nldo 4 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_NLDO_ON_VSEL(4), RK806_NLDO_SLP_VSEL(4), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff}, + /* nldo 5 */ + { 500000, 12500, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_NLDO_ON_VSEL(5), RK806_NLDO_SLP_VSEL(5), NA, RK806_NLDO_VSEL_MASK, 0xe8, 0xff}, +}; + +static const struct rk8xx_reg_info rk806_pldo[] = { + /* pldo 1 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_PLDO_ON_VSEL(1), RK806_PLDO_SLP_VSEL(1), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff}, + /* pldo 2 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_PLDO_ON_VSEL(2), RK806_PLDO_SLP_VSEL(2), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff}, + /* pldo 3 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_PLDO_ON_VSEL(3), RK806_PLDO_SLP_VSEL(3), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff}, + /* pldo 4 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_PLDO_ON_VSEL(4), RK806_PLDO_SLP_VSEL(4), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff}, + /* pldo 5 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_PLDO_ON_VSEL(5), RK806_PLDO_SLP_VSEL(5), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff}, + /* pldo 6 */ + { 500000, 12500, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0x00, 0xe7}, + { 3400000, 0, RK806_PLDO_ON_VSEL(6), RK806_PLDO_SLP_VSEL(6), NA, RK806_PLDO_VSEL_MASK, 0xe8, 0xff}, +}; + static const struct rk8xx_reg_info rk808_ldo[] = { { 1800000, 100000, REG_LDO1_ON_VSEL, REG_LDO1_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, }, { 1800000, 100000, REG_LDO2_ON_VSEL, REG_LDO2_SLP_VSEL, NA, RK808_LDO_VSEL_MASK, }, @@ -210,14 +305,6 @@ static const struct rk8xx_reg_info rk818_ldo[] = { }; #endif -static const u16 rk818_chrg_cur_input_array[] = { - 450, 800, 850, 1000, 1250, 1500, 1750, 2000, 2250, 2500, 2750, 3000 -}; - -static const uint rk818_chrg_shutdown_vsel_array[] = { - 2780000, 2850000, 2920000, 2990000, 3060000, 3130000, 3190000, 3260000 -}; - static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, int num, int uvolt) { @@ -238,7 +325,12 @@ static const struct rk8xx_reg_info *get_buck_reg(struct udevice *pmic, default: return &rk816_buck[num + 4]; } - + case RK806_ID: + if (uvolt < 1500000) + return &rk806_buck[num * 3 + 0]; + else if (uvolt < 3400000) + return &rk806_buck[num * 3 + 1]; + return &rk806_buck[num * 3 + 2]; case RK809_ID: case RK817_ID: switch (num) { @@ -322,7 +414,11 @@ static int _buck_set_enable(struct udevice *pmic, int buck, bool enable) value = ((0 << buck) | (1 << (buck + 4))); ret = pmic_reg_write(pmic, en_reg, value); break; - + case RK806_ID: + value = RK806_POWER_EN_CLRSETBITS(buck % 4, enable); + en_reg = RK806_POWER_EN((buck + 1) / 4); + ret = pmic_reg_write(pmic, en_reg, value); + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -397,6 +493,10 @@ static int _buck_get_enable(struct udevice *pmic, int buck) ret = pmic_reg_read(pmic, RK816_REG_DCDC_EN1); } break; + case RK806_ID: + mask = BIT(buck % 4); + ret = pmic_reg_read(pmic, RK806_POWER_EN((buck + 1) / 4)); + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -436,6 +536,20 @@ static int _buck_set_suspend_enable(struct udevice *pmic, int buck, bool enable) ret = pmic_clrsetbits(pmic, RK816_REG_DCDC_SLP_EN, mask, enable ? mask : 0); break; + case RK806_ID: + { + u8 reg; + + if (buck + 1 >= 9) { + reg = RK806_POWER_SLP_EN1; + mask = BIT(buck + 1 - 3); + } else { + reg = RK806_POWER_SLP_EN0; + mask = BIT(buck + 1); + } + ret = pmic_clrsetbits(pmic, reg, mask, enable ? mask : 0); + } + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -473,6 +587,21 @@ static int _buck_get_suspend_enable(struct udevice *pmic, int buck) return val; ret = val & mask ? 1 : 0; break; + case RK806_ID: + { + u8 reg; + + if (buck + 1 >= 9) { + reg = RK806_POWER_SLP_EN1; + mask = BIT(buck + 1 - 3); + } else { + reg = RK806_POWER_SLP_EN0; + mask = BIT(buck + 1); + } + val = pmic_reg_read(pmic, reg); + } + ret = (val & mask) ? 1 : 0; + break; case RK808_ID: case RK818_ID: mask = 1 << buck; @@ -522,6 +651,34 @@ static const struct rk8xx_reg_info *get_ldo_reg(struct udevice *pmic, } } +static const struct rk8xx_reg_info *get_nldo_reg(struct udevice *pmic, + int num, int uvolt) +{ + const struct rk8xx_priv *priv = dev_get_priv(pmic); + + switch (priv->variant) { + case RK806_ID: + default: + if (uvolt < 3400000) + return &rk806_nldo[num * 2 + 0]; + return &rk806_nldo[num * 2 + 1]; + } +} + +static const struct rk8xx_reg_info *get_pldo_reg(struct udevice *pmic, + int num, int uvolt) +{ + const struct rk8xx_priv *priv = dev_get_priv(pmic); + + switch (priv->variant) { + case RK806_ID: + default: + if (uvolt < 3400000) + return &rk806_pldo[num * 2 + 0]; + return &rk806_pldo[num * 2 + 1]; + } +} + static int _ldo_get_enable(struct udevice *pmic, int ldo) { struct rk8xx_priv *priv = dev_get_priv(pmic); @@ -569,6 +726,63 @@ static int _ldo_get_enable(struct udevice *pmic, int ldo) return ret & mask ? true : false; } +static int _nldo_get_enable(struct udevice *pmic, int nldo) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint mask = 0; + int ret = 0; + u8 en_reg = 0; + + switch (priv->variant) { + case RK806_ID: + default: + if (nldo + 1 >= 5) { + mask = BIT(2); + en_reg = RK806_POWER_EN(5); + } else { + mask = BIT(nldo); + en_reg = RK806_POWER_EN(3); + } + ret = pmic_reg_read(pmic, en_reg); + break; + } + + if (ret < 0) + return ret; + + return (ret & mask) ? 1 : 0; +} + +static int _pldo_get_enable(struct udevice *pmic, int pldo) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint mask = 0; + int ret = 0; + u8 en_reg = 0; + + switch (priv->variant) { + case RK806_ID: + default: + if (pldo + 1 <= 3) { + mask = BIT(pldo + 1); + en_reg = RK806_POWER_EN(4); + } else if (pldo + 1 == 6) { + mask = BIT(0); + en_reg = RK806_POWER_EN(4); + } else { + mask = BIT((pldo + 1) % 4); + en_reg = RK806_POWER_EN(5); + } + ret = pmic_reg_read(pmic, en_reg); + break; + } + + if (ret < 0) + return ret; + + return (ret & mask) ? 1 : 0; +} + static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) { struct rk8xx_priv *priv = dev_get_priv(pmic); @@ -624,6 +838,62 @@ static int _ldo_set_enable(struct udevice *pmic, int ldo, bool enable) return ret; } +static int _nldo_set_enable(struct udevice *pmic, int nldo, bool enable) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint value, en_reg; + int ret = 0; + + switch (priv->variant) { + case RK806_ID: + default: + if (nldo + 1 >= 5) { + value = RK806_POWER_EN_CLRSETBITS(2, enable); + en_reg = RK806_POWER_EN(5); + } else { + value = RK806_POWER_EN_CLRSETBITS(nldo, enable); + en_reg = RK806_POWER_EN(3); + } + ret = pmic_reg_write(pmic, en_reg, value); + break; + } + + if (enable) + udelay(500); + + return ret; +} + +static int _pldo_set_enable(struct udevice *pmic, int pldo, bool enable) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint value, en_reg; + int ret = 0; + + switch (priv->variant) { + case RK806_ID: + default: + /* PLDO */ + if (pldo + 1 <= 3) { + value = RK806_POWER_EN_CLRSETBITS(pldo + 1, enable); + en_reg = RK806_POWER_EN(4); + } else if (pldo + 1 == 6) { + value = RK806_POWER_EN_CLRSETBITS(0, enable); + en_reg = RK806_POWER_EN(4); + } else { + value = RK806_POWER_EN_CLRSETBITS((pldo + 1) % 4, enable); + en_reg = RK806_POWER_EN(5); + } + ret = pmic_reg_write(pmic, en_reg, value); + break; + } + + if (enable) + udelay(500); + + return ret; +} + static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) { struct rk8xx_priv *priv = dev_get_priv(pmic); @@ -660,6 +930,43 @@ static int _ldo_set_suspend_enable(struct udevice *pmic, int ldo, bool enable) return ret; } +static int _nldo_set_suspend_enable(struct udevice *pmic, int nldo, bool enable) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint mask; + int ret = 0; + + switch (priv->variant) { + case RK806_ID: + default: + mask = BIT(nldo); + ret = pmic_clrsetbits(pmic, RK806_POWER_SLP_EN1, mask, enable ? mask : 0); + break; + } + + return ret; +} + +static int _pldo_set_suspend_enable(struct udevice *pmic, int pldo, bool enable) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + uint mask; + int ret = 0; + + switch (priv->variant) { + case RK806_ID: + default: + if (pldo + 1 >= 6) + mask = BIT(0); + else + mask = BIT(pldo + 1); + ret = pmic_clrsetbits(pmic, RK806_POWER_SLP_EN2, mask, enable ? mask : 0); + break; + } + + return ret; +} + static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) { struct rk8xx_priv *priv = dev_get_priv(pmic); @@ -704,6 +1011,45 @@ static int _ldo_get_suspend_enable(struct udevice *pmic, int ldo) return ret; } +static int _nldo_get_suspend_enable(struct udevice *pmic, int nldo) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + int val, ret = 0; + uint mask; + + switch (priv->variant) { + case RK806_ID: + default: + mask = BIT(nldo); + val = pmic_reg_read(pmic, RK806_POWER_SLP_EN1); + ret = (val & mask) ? 1 : 0; + break; + } + + return ret; +} + +static int _pldo_get_suspend_enable(struct udevice *pmic, int pldo) +{ + struct rk8xx_priv *priv = dev_get_priv(pmic); + int val, ret = 0; + uint mask; + + switch (priv->variant) { + case RK806_ID: + default: + if (pldo + 1 >= 6) + mask = BIT(0); + else + mask = BIT(pldo + 1); + val = pmic_reg_read(pmic, RK806_POWER_SLP_EN2); + ret = (val & mask) ? 1 : 0; + break; + } + + return ret; +} + static int buck_get_value(struct udevice *dev) { int buck = dev->driver_data - 1; @@ -788,10 +1134,8 @@ static int buck_get_enable(struct udevice *dev) return _buck_get_enable(dev->parent, buck); } -static int ldo_get_value(struct udevice *dev) +static int _ldo_get_value(struct udevice *dev, const struct rk8xx_reg_info *info) { - int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0); int mask = info->vsel_mask; int ret, val; @@ -805,10 +1149,32 @@ static int ldo_get_value(struct udevice *dev) return info->min_uv + val * info->step_uv; } -static int ldo_set_value(struct udevice *dev, int uvolt) +static int ldo_get_value(struct udevice *dev) { int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt); + const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0); + + return _ldo_get_value(dev, info); +} + +static int nldo_get_value(struct udevice *dev) +{ + int nldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, 0); + + return _ldo_get_value(dev, info); +} + +static int pldo_get_value(struct udevice *dev) +{ + int pldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, 0); + + return _ldo_get_value(dev, info); +} + +static int _ldo_set_value(struct udevice *dev, const struct rk8xx_reg_info *info, int uvolt) +{ int mask = info->vsel_mask; int val; @@ -820,16 +1186,38 @@ static int ldo_set_value(struct udevice *dev, int uvolt) else val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, ldo + 1, info->vsel_reg, mask, val); + debug("%s: volt=%d, reg=0x%x, mask=0x%x, val=0x%x\n", + __func__, uvolt, info->vsel_reg, mask, val); return pmic_clrsetbits(dev->parent, info->vsel_reg, mask, val); } -static int ldo_set_suspend_value(struct udevice *dev, int uvolt) +static int ldo_set_value(struct udevice *dev, int uvolt) { int ldo = dev->driver_data - 1; const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt); + + return _ldo_set_value(dev, info, uvolt); +} + +static int nldo_set_value(struct udevice *dev, int uvolt) +{ + int nldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, uvolt); + + return _ldo_set_value(dev, info, uvolt); +} + +static int pldo_set_value(struct udevice *dev, int uvolt) +{ + int pldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, uvolt); + + return _ldo_set_value(dev, info, uvolt); +} + +static int _ldo_set_suspend_value(struct udevice *dev, const struct rk8xx_reg_info *info, int uvolt) +{ int mask = info->vsel_mask; int val; @@ -841,16 +1229,38 @@ static int ldo_set_suspend_value(struct udevice *dev, int uvolt) else val = ((uvolt - info->min_uv) / info->step_uv) + info->min_sel; - debug("%s: volt=%d, ldo=%d, reg=0x%x, mask=0x%x, val=0x%x\n", - __func__, uvolt, ldo + 1, info->vsel_sleep_reg, mask, val); + debug("%s: volt=%d, reg=0x%x, mask=0x%x, val=0x%x\n", + __func__, uvolt, info->vsel_sleep_reg, mask, val); return pmic_clrsetbits(dev->parent, info->vsel_sleep_reg, mask, val); } -static int ldo_get_suspend_value(struct udevice *dev) +static int ldo_set_suspend_value(struct udevice *dev, int uvolt) { int ldo = dev->driver_data - 1; - const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0); + const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, uvolt); + + return _ldo_set_suspend_value(dev->parent, info, uvolt); +} + +static int nldo_set_suspend_value(struct udevice *dev, int uvolt) +{ + int nldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, uvolt); + + return _ldo_set_suspend_value(dev->parent, info, uvolt); +} + +static int pldo_set_suspend_value(struct udevice *dev, int uvolt) +{ + int pldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, uvolt); + + return _ldo_set_suspend_value(dev->parent, info, uvolt); +} + +static int _ldo_get_suspend_value(struct udevice *dev, const struct rk8xx_reg_info *info) +{ int mask = info->vsel_mask; int val, ret; @@ -866,6 +1276,30 @@ static int ldo_get_suspend_value(struct udevice *dev) return info->min_uv + val * info->step_uv; } +static int ldo_get_suspend_value(struct udevice *dev) +{ + int ldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_ldo_reg(dev->parent, ldo, 0); + + return _ldo_get_suspend_value(dev->parent, info); +} + +static int nldo_get_suspend_value(struct udevice *dev) +{ + int nldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_nldo_reg(dev->parent, nldo, 0); + + return _ldo_get_suspend_value(dev->parent, info); +} + +static int pldo_get_suspend_value(struct udevice *dev) +{ + int pldo = dev->driver_data - 1; + const struct rk8xx_reg_info *info = get_pldo_reg(dev->parent, pldo, 0); + + return _ldo_get_suspend_value(dev->parent, info); +} + static int ldo_set_enable(struct udevice *dev, bool enable) { int ldo = dev->driver_data - 1; @@ -873,6 +1307,20 @@ static int ldo_set_enable(struct udevice *dev, bool enable) return _ldo_set_enable(dev->parent, ldo, enable); } +static int nldo_set_enable(struct udevice *dev, bool enable) +{ + int nldo = dev->driver_data - 1; + + return _nldo_set_enable(dev->parent, nldo, enable); +} + +static int pldo_set_enable(struct udevice *dev, bool enable) +{ + int pldo = dev->driver_data - 1; + + return _pldo_set_enable(dev->parent, pldo, enable); +} + static int ldo_set_suspend_enable(struct udevice *dev, bool enable) { int ldo = dev->driver_data - 1; @@ -880,6 +1328,20 @@ static int ldo_set_suspend_enable(struct udevice *dev, bool enable) return _ldo_set_suspend_enable(dev->parent, ldo, enable); } +static int nldo_set_suspend_enable(struct udevice *dev, bool enable) +{ + int nldo = dev->driver_data - 1; + + return _nldo_set_suspend_enable(dev->parent, nldo, enable); +} + +static int pldo_set_suspend_enable(struct udevice *dev, bool enable) +{ + int pldo = dev->driver_data - 1; + + return _pldo_set_suspend_enable(dev->parent, pldo, enable); +} + static int ldo_get_suspend_enable(struct udevice *dev) { int ldo = dev->driver_data - 1; @@ -887,6 +1349,20 @@ static int ldo_get_suspend_enable(struct udevice *dev) return _ldo_get_suspend_enable(dev->parent, ldo); } +static int nldo_get_suspend_enable(struct udevice *dev) +{ + int nldo = dev->driver_data - 1; + + return _nldo_get_suspend_enable(dev->parent, nldo); +} + +static int pldo_get_suspend_enable(struct udevice *dev) +{ + int pldo = dev->driver_data - 1; + + return _pldo_get_suspend_enable(dev->parent, pldo); +} + static int ldo_get_enable(struct udevice *dev) { int ldo = dev->driver_data - 1; @@ -894,6 +1370,20 @@ static int ldo_get_enable(struct udevice *dev) return _ldo_get_enable(dev->parent, ldo); } +static int nldo_get_enable(struct udevice *dev) +{ + int nldo = dev->driver_data - 1; + + return _nldo_get_enable(dev->parent, nldo); +} + +static int pldo_get_enable(struct udevice *dev) +{ + int pldo = dev->driver_data - 1; + + return _pldo_get_enable(dev->parent, pldo); +} + static int switch_set_enable(struct udevice *dev, bool enable) { struct rk8xx_priv *priv = dev_get_priv(dev->parent); @@ -909,7 +1399,7 @@ static int switch_set_enable(struct udevice *dev, bool enable) case RK809_ID: mask = (1 << (sw + 2)) | (1 << (sw + 6)); ret = pmic_clrsetbits(dev->parent, RK817_POWER_EN(3), mask, - enable ? mask : 0); + enable ? mask : (1 << (sw + 6))); break; case RK818_ID: mask = 1 << 6; @@ -1117,6 +1607,28 @@ static const struct dm_regulator_ops rk8xx_ldo_ops = { .get_suspend_enable = ldo_get_suspend_enable, }; +static const struct dm_regulator_ops rk8xx_nldo_ops = { + .get_value = nldo_get_value, + .set_value = nldo_set_value, + .set_suspend_value = nldo_set_suspend_value, + .get_suspend_value = nldo_get_suspend_value, + .get_enable = nldo_get_enable, + .set_enable = nldo_set_enable, + .set_suspend_enable = nldo_set_suspend_enable, + .get_suspend_enable = nldo_get_suspend_enable, +}; + +static const struct dm_regulator_ops rk8xx_pldo_ops = { + .get_value = pldo_get_value, + .set_value = pldo_set_value, + .set_suspend_value = pldo_set_suspend_value, + .get_suspend_value = pldo_get_suspend_value, + .get_enable = pldo_get_enable, + .set_enable = pldo_set_enable, + .set_suspend_enable = pldo_set_suspend_enable, + .get_suspend_enable = pldo_get_suspend_enable, +}; + static const struct dm_regulator_ops rk8xx_switch_ops = { .get_value = switch_get_value, .set_value = switch_set_value, @@ -1142,6 +1654,20 @@ U_BOOT_DRIVER(rk8xx_ldo) = { .probe = rk8xx_ldo_probe, }; +U_BOOT_DRIVER(rk8xx_nldo) = { + .name = "rk8xx_nldo", + .id = UCLASS_REGULATOR, + .ops = &rk8xx_nldo_ops, + .probe = rk8xx_ldo_probe, +}; + +U_BOOT_DRIVER(rk8xx_pldo) = { + .name = "rk8xx_pldo", + .id = UCLASS_REGULATOR, + .ops = &rk8xx_pldo_ops, + .probe = rk8xx_ldo_probe, +}; + U_BOOT_DRIVER(rk8xx_switch) = { .name = "rk8xx_switch", .id = UCLASS_REGULATOR, @@ -1160,26 +1686,3 @@ int rk8xx_spl_configure_buck(struct udevice *pmic, int buck, int uvolt) return _buck_set_enable(pmic, buck, true); } - -int rk818_spl_configure_usb_input_current(struct udevice *pmic, int current_ma) -{ - uint i; - - for (i = 0; i < ARRAY_SIZE(rk818_chrg_cur_input_array); i++) - if (current_ma <= rk818_chrg_cur_input_array[i]) - break; - - return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_ILIM_SEL_MASK, i); -} - -int rk818_spl_configure_usb_chrg_shutdown(struct udevice *pmic, int uvolt) -{ - uint i; - - for (i = 0; i < ARRAY_SIZE(rk818_chrg_shutdown_vsel_array); i++) - if (uvolt <= rk818_chrg_shutdown_vsel_array[i]) - break; - - return pmic_clrsetbits(pmic, REG_USB_CTRL, RK818_USB_CHG_SD_VSEL_MASK, - i); -} diff --git a/drivers/ram/Kconfig b/drivers/ram/Kconfig index 5b07e92..9838a27 100644 --- a/drivers/ram/Kconfig +++ b/drivers/ram/Kconfig @@ -62,10 +62,10 @@ choice depends on K3_DDRSS prompt "K3 DDRSS Arch Support" - default K3_J721E_DDRSS if SOC_K3_J721E || SOC_K3_J721S2 + default K3_J721E_DDRSS if SOC_K3_J721E || SOC_K3_J721S2 || SOC_K3_J784S4 default K3_AM64_DDRSS if SOC_K3_AM642 default K3_AM64_DDRSS if SOC_K3_AM625 - default K3_AM62A_DDRSS if SOC_K3_AM62A7 + default K3_AM62A_DDRSS if SOC_K3_AM62A7 || SOC_K3_AM62P5 config K3_J721E_DDRSS bool "Enable J721E DDRSS support" diff --git a/drivers/ram/rockchip/dmc-rk3368.c b/drivers/ram/rockchip/dmc-rk3368.c index f36be94..5279bf0 100644 --- a/drivers/ram/rockchip/dmc-rk3368.c +++ b/drivers/ram/rockchip/dmc-rk3368.c @@ -13,10 +13,10 @@ #include <ram.h> #include <regmap.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3368.h> #include <asm/arch-rockchip/grf_rk3368.h> +#include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/ddr_rk3368.h> #include <asm/arch-rockchip/sdram.h> #include <asm/arch-rockchip/sdram_rk3288.h> diff --git a/drivers/ram/rockchip/sdram_px30.c b/drivers/ram/rockchip/sdram_px30.c index 2728d93..21498e8 100644 --- a/drivers/ram/rockchip/sdram_px30.c +++ b/drivers/ram/rockchip/sdram_px30.c @@ -10,7 +10,6 @@ #include <log.h> #include <ram.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_px30.h> #include <asm/arch-rockchip/grf_px30.h> diff --git a/drivers/ram/rockchip/sdram_rk3066.c b/drivers/ram/rockchip/sdram_rk3066.c index 39c0be5..562cf54 100644 --- a/drivers/ram/rockchip/sdram_rk3066.c +++ b/drivers/ram/rockchip/sdram_rk3066.c @@ -17,7 +17,6 @@ #include <ram.h> #include <regmap.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3066.h> #include <asm/arch-rockchip/ddr_rk3188.h> diff --git a/drivers/ram/rockchip/sdram_rk3188.c b/drivers/ram/rockchip/sdram_rk3188.c index ad9f936..e1b28c6 100644 --- a/drivers/ram/rockchip/sdram_rk3188.c +++ b/drivers/ram/rockchip/sdram_rk3188.c @@ -17,11 +17,11 @@ #include <ram.h> #include <regmap.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3188.h> #include <asm/arch-rockchip/ddr_rk3188.h> #include <asm/arch-rockchip/grf_rk3188.h> +#include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/pmu_rk3188.h> #include <asm/arch-rockchip/sdram.h> #include <asm/arch-rockchip/sdram_rk3288.h> diff --git a/drivers/ram/rockchip/sdram_rk322x.c b/drivers/ram/rockchip/sdram_rk322x.c index 892766a..5fc23c1 100644 --- a/drivers/ram/rockchip/sdram_rk322x.c +++ b/drivers/ram/rockchip/sdram_rk322x.c @@ -12,7 +12,6 @@ #include <regmap.h> #include <syscon.h> #include <asm/global_data.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk322x.h> #include <asm/arch-rockchip/grf_rk322x.h> diff --git a/drivers/ram/rockchip/sdram_rk3288.c b/drivers/ram/rockchip/sdram_rk3288.c index c99118f..242d564 100644 --- a/drivers/ram/rockchip/sdram_rk3288.c +++ b/drivers/ram/rockchip/sdram_rk3288.c @@ -17,11 +17,11 @@ #include <ram.h> #include <regmap.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru.h> #include <asm/arch-rockchip/ddr_rk3288.h> #include <asm/arch-rockchip/grf_rk3288.h> +#include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/pmu_rk3288.h> #include <asm/arch-rockchip/sdram.h> #include <asm/arch-rockchip/sdram_rk3288.h> diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index 2bf8d48..02cc4a3 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -14,7 +14,6 @@ #include <ram.h> #include <regmap.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru.h> #include <asm/arch-rockchip/grf_rk3399.h> diff --git a/drivers/ram/rockchip/sdram_rv1126.c b/drivers/ram/rockchip/sdram_rv1126.c index 0a78e18..849e15a 100644 --- a/drivers/ram/rockchip/sdram_rv1126.c +++ b/drivers/ram/rockchip/sdram_rv1126.c @@ -9,7 +9,6 @@ #include <dm.h> #include <ram.h> #include <syscon.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/cru_rv1126.h> diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 781de53..a49802c 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -102,4 +102,11 @@ config REMOTEPROC_TI_IPU help Say 'y' here to add support for TI' K3 remoteproc driver. +config REMOTEPROC_MAX_FW_SIZE + hex "Maximum size of firmware file that needs to be loaded to the remote processor" + default 0x10000 + help + Maximum size of the firmware file (elf, binary) that needs to be + loaded to the remote processor. + endmenu diff --git a/drivers/remoteproc/rproc-uclass.c b/drivers/remoteproc/rproc-uclass.c index 28b362c..aa7f758 100644 --- a/drivers/remoteproc/rproc-uclass.c +++ b/drivers/remoteproc/rproc-uclass.c @@ -13,6 +13,7 @@ #include <log.h> #include <malloc.h> #include <virtio_ring.h> +#include <fs_loader.h> #include <remoteproc.h> #include <asm/io.h> #include <dm/device-internal.h> @@ -961,3 +962,106 @@ unsigned long rproc_parse_resource_table(struct udevice *dev, struct rproc *cfg) return 1; } + +int rproc_set_firmware(struct udevice *rproc_dev, const char *fw_name) +{ + struct dm_rproc_uclass_pdata *uc_pdata; + int len; + char *p; + + if (!rproc_dev || !fw_name) + return -EINVAL; + + uc_pdata = dev_get_uclass_plat(rproc_dev); + if (!uc_pdata) + return -EINVAL; + + len = strcspn(fw_name, "\n"); + if (!len) { + debug("invalid firmware name\n"); + return -EINVAL; + } + + if (uc_pdata->fw_name) + free(uc_pdata->fw_name); + + p = strndup(fw_name, len); + if (!p) + return -ENOMEM; + + uc_pdata->fw_name = p; + + return 0; +} + +#if CONFIG_IS_ENABLED(FS_LOADER) +int rproc_boot(struct udevice *rproc_dev) +{ + struct dm_rproc_uclass_pdata *uc_pdata; + struct udevice *fs_loader; + int core_id, ret = 0; + char *firmware; + void *addr; + + if (!rproc_dev) + return -EINVAL; + + uc_pdata = dev_get_uclass_plat(rproc_dev); + if (!uc_pdata) + return -EINVAL; + + core_id = dev_seq(rproc_dev); + firmware = uc_pdata->fw_name; + if (!firmware) { + debug("No firmware name set for rproc core %d\n", core_id); + return -EINVAL; + } + + /* Initialize all rproc cores */ + if (!rproc_is_initialized()) { + ret = rproc_init(); + if (ret) { + debug("rproc_init() failed: %d\n", ret); + return ret; + } + } + + /* Loading firmware to a given address */ + ret = get_fs_loader(&fs_loader); + if (ret) { + debug("could not get fs loader: %d\n", ret); + return ret; + } + + if (CONFIG_REMOTEPROC_MAX_FW_SIZE) { + addr = malloc(CONFIG_REMOTEPROC_MAX_FW_SIZE); + if (!addr) + return -ENOMEM; + } else { + debug("CONFIG_REMOTEPROC_MAX_FW_SIZE not defined\n"); + return -EINVAL; + } + + ret = request_firmware_into_buf(fs_loader, firmware, addr, CONFIG_REMOTEPROC_MAX_FW_SIZE, + 0); + if (ret < 0) { + debug("could not request %s: %d\n", firmware, ret); + goto free_buffer; + } + + ret = rproc_load(core_id, (ulong)addr, ret); + if (ret) { + debug("failed to load %s to rproc core %d from addr 0x%08lX err %d\n", + uc_pdata->fw_name, core_id, (ulong)addr, ret); + goto free_buffer; + } + + ret = rproc_start(core_id); + if (ret) + debug("failed to start rproc core %d\n", core_id); + +free_buffer: + free(addr); + return ret; +} +#endif diff --git a/drivers/remoteproc/ti_k3_dsp_rproc.c b/drivers/remoteproc/ti_k3_dsp_rproc.c index 1c6515f..e790406 100644 --- a/drivers/remoteproc/ti_k3_dsp_rproc.c +++ b/drivers/remoteproc/ti_k3_dsp_rproc.c @@ -338,7 +338,8 @@ static int k3_dsp_of_get_memories(struct udevice *dev) for (i = 0; i < dsp->num_mems; i++) { /* C71 cores only have a L1P Cache, there are no L1P SRAMs */ - if (device_is_compatible(dev, "ti,j721e-c71-dsp") && + if (((device_is_compatible(dev, "ti,j721e-c71-dsp")) || + (device_is_compatible(dev, "ti,j721s2-c71-dsp"))) && !strcmp(mem_names[i], "l1pram")) { dsp->mem[i].bus_addr = FDT_ADDR_T_NONE; dsp->mem[i].dev_addr = FDT_ADDR_T_NONE; @@ -457,6 +458,7 @@ static const struct k3_dsp_boot_data c71_data = { static const struct udevice_id k3_dsp_ids[] = { { .compatible = "ti,j721e-c66-dsp", .data = (ulong)&c66_data, }, { .compatible = "ti,j721e-c71-dsp", .data = (ulong)&c71_data, }, + { .compatible = "ti,j721s2-c71-dsp", .data = (ulong)&c71_data, }, {} }; diff --git a/drivers/remoteproc/ti_k3_r5f_rproc.c b/drivers/remoteproc/ti_k3_r5f_rproc.c index 6f3e12d..631e548 100644 --- a/drivers/remoteproc/ti_k3_r5f_rproc.c +++ b/drivers/remoteproc/ti_k3_r5f_rproc.c @@ -855,7 +855,7 @@ static const struct k3_r5f_ip_data k3_data = { .tcm_ecc_autoinit = false, }; -static const struct k3_r5f_ip_data j7200_data = { +static const struct k3_r5f_ip_data j7200_j721s2_data = { .tcm_is_double = true, .tcm_ecc_autoinit = true, }; @@ -863,7 +863,8 @@ static const struct k3_r5f_ip_data j7200_data = { static const struct udevice_id k3_r5f_rproc_ids[] = { { .compatible = "ti,am654-r5f", .data = (ulong)&k3_data, }, { .compatible = "ti,j721e-r5f", .data = (ulong)&k3_data, }, - { .compatible = "ti,j7200-r5f", .data = (ulong)&j7200_data, }, + { .compatible = "ti,j7200-r5f", .data = (ulong)&j7200_j721s2_data, }, + { .compatible = "ti,j721s2-r5f", .data = (ulong)&j7200_j721s2_data, }, {} }; @@ -901,6 +902,7 @@ static const struct udevice_id k3_r5fss_ids[] = { { .compatible = "ti,am654-r5fss"}, { .compatible = "ti,j721e-r5fss"}, { .compatible = "ti,j7200-r5fss"}, + { .compatible = "ti,j721s2-r5fss"}, {} }; diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c index eaef2cc..a3b3132 100644 --- a/drivers/reset/reset-imx7.c +++ b/drivers/reset/reset-imx7.c @@ -9,12 +9,13 @@ #include <common.h> #include <dm.h> #include <dt-bindings/reset/imx7-reset.h> +#include <dt-bindings/reset/imx8mp-reset.h> #include <dt-bindings/reset/imx8mq-reset.h> #include <reset-uclass.h> #include <linux/bitops.h> #include <linux/delay.h> -struct imx7_reset_priv { +struct imx_reset_priv { void __iomem *base; struct reset_ops ops; }; @@ -64,9 +65,9 @@ static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = { [IMX7_RESET_DDRC_CORE_RST] = { SRC_DDRC_RCR, BIT(1) }, }; -static int imx7_reset_deassert_imx7(struct reset_ctl *rst) +static int imx7_reset_deassert(struct reset_ctl *rst) { - struct imx7_reset_priv *priv = dev_get_priv(rst->dev); + struct imx_reset_priv *priv = dev_get_priv(rst->dev); const struct imx7_src_signal *sig = imx7_src_signals; u32 val; @@ -95,9 +96,9 @@ static int imx7_reset_deassert_imx7(struct reset_ctl *rst) return 0; } -static int imx7_reset_assert_imx7(struct reset_ctl *rst) +static int imx7_reset_assert(struct reset_ctl *rst) { - struct imx7_reset_priv *priv = dev_get_priv(rst->dev); + struct imx_reset_priv *priv = dev_get_priv(rst->dev); const struct imx7_src_signal *sig = imx7_src_signals; u32 val; @@ -185,9 +186,9 @@ static const struct imx7_src_signal imx8mq_src_signals[IMX8MQ_RESET_NUM] = { [IMX8MQ_RESET_DDRC2_PRST] = { SRC_DDRC2_RCR, BIT(2) }, }; -static int imx7_reset_deassert_imx8mq(struct reset_ctl *rst) +static int imx8mq_reset_deassert(struct reset_ctl *rst) { - struct imx7_reset_priv *priv = dev_get_priv(rst->dev); + struct imx_reset_priv *priv = dev_get_priv(rst->dev); const struct imx7_src_signal *sig = imx8mq_src_signals; u32 val; @@ -223,9 +224,9 @@ static int imx7_reset_deassert_imx8mq(struct reset_ctl *rst) return 0; } -static int imx7_reset_assert_imx8mq(struct reset_ctl *rst) +static int imx8mq_reset_assert(struct reset_ctl *rst) { - struct imx7_reset_priv *priv = dev_get_priv(rst->dev); + struct imx_reset_priv *priv = dev_get_priv(rst->dev); const struct imx7_src_signal *sig = imx8mq_src_signals; u32 val; @@ -252,43 +253,143 @@ static int imx7_reset_assert_imx8mq(struct reset_ctl *rst) return 0; } -static int imx7_reset_assert(struct reset_ctl *rst) +enum imx8mp_src_registers { + SRC_SUPERMIX_RCR = 0x0018, + SRC_AUDIOMIX_RCR = 0x001c, + SRC_MLMIX_RCR = 0x0028, + SRC_GPU2D_RCR = 0x0038, + SRC_GPU3D_RCR = 0x003c, + SRC_VPU_G1_RCR = 0x0048, + SRC_VPU_G2_RCR = 0x004c, + SRC_VPUVC8KE_RCR = 0x0050, + SRC_NOC_RCR = 0x0054, +}; + +static const struct imx7_src_signal imx8mp_src_signals[IMX8MP_RESET_NUM] = { + [IMX8MP_RESET_A53_CORE_POR_RESET0] = { SRC_A53RCR0, BIT(0) }, + [IMX8MP_RESET_A53_CORE_POR_RESET1] = { SRC_A53RCR0, BIT(1) }, + [IMX8MP_RESET_A53_CORE_POR_RESET2] = { SRC_A53RCR0, BIT(2) }, + [IMX8MP_RESET_A53_CORE_POR_RESET3] = { SRC_A53RCR0, BIT(3) }, + [IMX8MP_RESET_A53_CORE_RESET0] = { SRC_A53RCR0, BIT(4) }, + [IMX8MP_RESET_A53_CORE_RESET1] = { SRC_A53RCR0, BIT(5) }, + [IMX8MP_RESET_A53_CORE_RESET2] = { SRC_A53RCR0, BIT(6) }, + [IMX8MP_RESET_A53_CORE_RESET3] = { SRC_A53RCR0, BIT(7) }, + [IMX8MP_RESET_A53_DBG_RESET0] = { SRC_A53RCR0, BIT(8) }, + [IMX8MP_RESET_A53_DBG_RESET1] = { SRC_A53RCR0, BIT(9) }, + [IMX8MP_RESET_A53_DBG_RESET2] = { SRC_A53RCR0, BIT(10) }, + [IMX8MP_RESET_A53_DBG_RESET3] = { SRC_A53RCR0, BIT(11) }, + [IMX8MP_RESET_A53_ETM_RESET0] = { SRC_A53RCR0, BIT(12) }, + [IMX8MP_RESET_A53_ETM_RESET1] = { SRC_A53RCR0, BIT(13) }, + [IMX8MP_RESET_A53_ETM_RESET2] = { SRC_A53RCR0, BIT(14) }, + [IMX8MP_RESET_A53_ETM_RESET3] = { SRC_A53RCR0, BIT(15) }, + [IMX8MP_RESET_A53_SOC_DBG_RESET] = { SRC_A53RCR0, BIT(20) }, + [IMX8MP_RESET_A53_L2RESET] = { SRC_A53RCR0, BIT(21) }, + [IMX8MP_RESET_SW_NON_SCLR_M7C_RST] = { SRC_M4RCR, BIT(0) }, + [IMX8MP_RESET_OTG1_PHY_RESET] = { SRC_USBOPHY1_RCR, BIT(0) }, + [IMX8MP_RESET_OTG2_PHY_RESET] = { SRC_USBOPHY2_RCR, BIT(0) }, + [IMX8MP_RESET_SUPERMIX_RESET] = { SRC_SUPERMIX_RCR, BIT(0) }, + [IMX8MP_RESET_AUDIOMIX_RESET] = { SRC_AUDIOMIX_RCR, BIT(0) }, + [IMX8MP_RESET_MLMIX_RESET] = { SRC_MLMIX_RCR, BIT(0) }, + [IMX8MP_RESET_PCIEPHY] = { SRC_PCIEPHY_RCR, BIT(2) }, + [IMX8MP_RESET_PCIEPHY_PERST] = { SRC_PCIEPHY_RCR, BIT(3) }, + [IMX8MP_RESET_PCIE_CTRL_APPS_EN] = { SRC_PCIEPHY_RCR, BIT(6) }, + [IMX8MP_RESET_PCIE_CTRL_APPS_TURNOFF] = { SRC_PCIEPHY_RCR, BIT(11) }, + [IMX8MP_RESET_HDMI_PHY_APB_RESET] = { SRC_HDMI_RCR, BIT(0) }, + [IMX8MP_RESET_MEDIA_RESET] = { SRC_DISP_RCR, BIT(0) }, + [IMX8MP_RESET_GPU2D_RESET] = { SRC_GPU2D_RCR, BIT(0) }, + [IMX8MP_RESET_GPU3D_RESET] = { SRC_GPU3D_RCR, BIT(0) }, + [IMX8MP_RESET_GPU_RESET] = { SRC_GPU_RCR, BIT(0) }, + [IMX8MP_RESET_VPU_RESET] = { SRC_VPU_RCR, BIT(0) }, + [IMX8MP_RESET_VPU_G1_RESET] = { SRC_VPU_G1_RCR, BIT(0) }, + [IMX8MP_RESET_VPU_G2_RESET] = { SRC_VPU_G2_RCR, BIT(0) }, + [IMX8MP_RESET_VPUVC8KE_RESET] = { SRC_VPUVC8KE_RCR, BIT(0) }, + [IMX8MP_RESET_NOC_RESET] = { SRC_NOC_RCR, BIT(0) }, +}; + +static int imx8mp_reset_set(struct reset_ctl *rst, bool assert) { - struct imx7_reset_priv *priv = dev_get_priv(rst->dev); + struct imx_reset_priv *priv = dev_get_priv(rst->dev); + unsigned int bit, value; + + if (rst->id >= IMX8MP_RESET_NUM) + return -EINVAL; + + bit = imx8mp_src_signals[rst->id].bit; + value = assert ? bit : 0; + + switch (rst->id) { + case IMX8MP_RESET_PCIEPHY: + /* + * wait for more than 10us to release phy g_rst and + * btnrst + */ + if (!assert) + udelay(10); + break; + + case IMX8MP_RESET_PCIE_CTRL_APPS_EN: + case IMX8MP_RESET_PCIEPHY_PERST: + value = assert ? 0 : bit; + break; + } + + clrsetbits_le32(priv->base + imx8mp_src_signals[rst->id].offset, bit, + value); + + return 0; +} + +static int imx8mp_reset_assert(struct reset_ctl *rst) +{ + return imx8mp_reset_set(rst, true); +} + +static int imx8mp_reset_deassert(struct reset_ctl *rst) +{ + return imx8mp_reset_set(rst, false); +} + +static int imx_reset_assert(struct reset_ctl *rst) +{ + struct imx_reset_priv *priv = dev_get_priv(rst->dev); return priv->ops.rst_assert(rst); } -static int imx7_reset_deassert(struct reset_ctl *rst) +static int imx_reset_deassert(struct reset_ctl *rst) { - struct imx7_reset_priv *priv = dev_get_priv(rst->dev); + struct imx_reset_priv *priv = dev_get_priv(rst->dev); return priv->ops.rst_deassert(rst); } static const struct reset_ops imx7_reset_reset_ops = { - .rst_assert = imx7_reset_assert, - .rst_deassert = imx7_reset_deassert, + .rst_assert = imx_reset_assert, + .rst_deassert = imx_reset_deassert, }; static const struct udevice_id imx7_reset_ids[] = { { .compatible = "fsl,imx7d-src" }, { .compatible = "fsl,imx8mq-src" }, + { .compatible = "fsl,imx8mp-src" }, { } }; static int imx7_reset_probe(struct udevice *dev) { - struct imx7_reset_priv *priv = dev_get_priv(dev); + struct imx_reset_priv *priv = dev_get_priv(dev); priv->base = dev_remap_addr(dev); if (!priv->base) return -ENOMEM; if (device_is_compatible(dev, "fsl,imx8mq-src")) { - priv->ops.rst_assert = imx7_reset_assert_imx8mq; - priv->ops.rst_deassert = imx7_reset_deassert_imx8mq; + priv->ops.rst_assert = imx8mq_reset_assert; + priv->ops.rst_deassert = imx8mq_reset_deassert; } else if (device_is_compatible(dev, "fsl,imx7d-src")) { - priv->ops.rst_assert = imx7_reset_assert_imx7; - priv->ops.rst_deassert = imx7_reset_deassert_imx7; + priv->ops.rst_assert = imx7_reset_assert; + priv->ops.rst_deassert = imx7_reset_deassert; + } else if (device_is_compatible(dev, "fsl,imx8mp-src")) { + priv->ops.rst_assert = imx8mp_reset_assert; + priv->ops.rst_deassert = imx8mp_reset_deassert; } return 0; @@ -300,5 +401,5 @@ U_BOOT_DRIVER(imx7_reset) = { .of_match = imx7_reset_ids, .ops = &imx7_reset_reset_ops, .probe = imx7_reset_probe, - .priv_auto = sizeof(struct imx7_reset_priv), + .priv_auto = sizeof(struct imx_reset_priv), }; diff --git a/drivers/rng/arm_rndr.c b/drivers/rng/arm_rndr.c index 4512330..bf54aec 100644 --- a/drivers/rng/arm_rndr.c +++ b/drivers/rng/arm_rndr.c @@ -9,11 +9,10 @@ #define LOG_CATEGORY UCLASS_RNG -#include <common.h> #include <dm.h> -#include <linux/kernel.h> #include <rng.h> #include <asm/system.h> +#include <linux/kernel.h> #define DRIVER_NAME "arm-rndr" diff --git a/drivers/rng/iproc_rng200.c b/drivers/rng/iproc_rng200.c index 85ac15b..4c49aa9 100644 --- a/drivers/rng/iproc_rng200.c +++ b/drivers/rng/iproc_rng200.c @@ -5,11 +5,10 @@ * Driver for Raspberry Pi hardware random number generator */ -#include <common.h> #include <dm.h> -#include <linux/delay.h> #include <rng.h> #include <asm/io.h> +#include <linux/delay.h> #define usleep_range(a, b) udelay((b)) diff --git a/drivers/rng/meson-rng.c b/drivers/rng/meson-rng.c index fd2988e..49037d1 100644 --- a/drivers/rng/meson-rng.c +++ b/drivers/rng/meson-rng.c @@ -5,7 +5,6 @@ * Driver for Amlogic hardware random number generator */ -#include <common.h> #include <clk.h> #include <dm.h> #include <rng.h> diff --git a/drivers/rng/msm_rng.c b/drivers/rng/msm_rng.c index 29e7354..658c153 100644 --- a/drivers/rng/msm_rng.c +++ b/drivers/rng/msm_rng.c @@ -9,12 +9,11 @@ * Based on Linux driver */ -#include <asm/io.h> #include <clk.h> -#include <common.h> #include <dm.h> -#include <linux/bitops.h> #include <rng.h> +#include <asm/io.h> +#include <linux/bitops.h> /* Device specific register offsets */ #define PRNG_DATA_OUT 0x0000 diff --git a/drivers/rng/npcm_rng.c b/drivers/rng/npcm_rng.c index 70c1c03..3922aca 100644 --- a/drivers/rng/npcm_rng.c +++ b/drivers/rng/npcm_rng.c @@ -3,7 +3,6 @@ * Copyright (c) 2022 Nuvoton Technology Corp. */ -#include <common.h> #include <dm.h> #include <malloc.h> #include <rng.h> diff --git a/drivers/rng/optee_rng.c b/drivers/rng/optee_rng.c index 410dfc0..f692681 100644 --- a/drivers/rng/optee_rng.c +++ b/drivers/rng/optee_rng.c @@ -4,8 +4,6 @@ */ #define LOG_CATEGORY UCLASS_RNG -#include <common.h> - #include <rng.h> #include <tee.h> #include <dm/device.h> diff --git a/drivers/rng/rng-uclass.c b/drivers/rng/rng-uclass.c index 53108e1..06ddfa1 100644 --- a/drivers/rng/rng-uclass.c +++ b/drivers/rng/rng-uclass.c @@ -5,7 +5,6 @@ #define LOG_CATEGORY UCLASS_RNG -#include <common.h> #include <dm.h> #include <rng.h> diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c index 705b424..2426648 100644 --- a/drivers/rng/rockchip_rng.c +++ b/drivers/rng/rockchip_rng.c @@ -2,14 +2,13 @@ /* * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd */ -#include <asm/arch-rockchip/hardware.h> -#include <asm/io.h> -#include <common.h> + #include <dm.h> +#include <rng.h> +#include <asm/arch-rockchip/hardware.h> #include <linux/bitops.h> #include <linux/iopoll.h> #include <linux/string.h> -#include <rng.h> #define RK_HW_RNG_MAX 32 @@ -302,7 +301,15 @@ static const struct dm_rng_ops rockchip_rng_ops = { static const struct udevice_id rockchip_rng_match[] = { { - .compatible = "rockchip,cryptov1-rng", + .compatible = "rockchip,rk3288-crypto", + .data = (ulong)&rk_cryptov1_soc_data, + }, + { + .compatible = "rockchip,rk3328-crypto", + .data = (ulong)&rk_cryptov1_soc_data, + }, + { + .compatible = "rockchip,rk3399-crypto", .data = (ulong)&rk_cryptov1_soc_data, }, { diff --git a/drivers/rng/sandbox_rng.c b/drivers/rng/sandbox_rng.c index cc5e1f6..071a322 100644 --- a/drivers/rng/sandbox_rng.c +++ b/drivers/rng/sandbox_rng.c @@ -3,11 +3,10 @@ * Copyright (c) 2019, Linaro Limited */ -#include <common.h> #include <dm.h> #include <rand.h> #include <rng.h> - +#include <time.h> #include <linux/string.h> static int sandbox_rng_read(struct udevice *dev, void *data, size_t len) diff --git a/drivers/rng/smccc_trng.c b/drivers/rng/smccc_trng.c index 3a4bb33..f59b806 100644 --- a/drivers/rng/smccc_trng.c +++ b/drivers/rng/smccc_trng.c @@ -5,7 +5,6 @@ #define LOG_CATEGORY UCLASS_RNG -#include <common.h> #include <dm.h> #include <linker_lists.h> #include <log.h> @@ -166,7 +165,7 @@ static int smccc_trng_probe(struct udevice *dev) struct smccc_trng_priv *priv = dev_get_priv(dev); struct arm_smccc_res res; - if (!(smccc_trng_is_supported(smccc->invoke_fn))) + if (!smccc || !(smccc_trng_is_supported(smccc->invoke_fn))) return -ENODEV; /* At least one of 64bit and 32bit interfaces is available */ diff --git a/drivers/rng/stm32_rng.c b/drivers/rng/stm32_rng.c index c397b4d..61d5ed6 100644 --- a/drivers/rng/stm32_rng.c +++ b/drivers/rng/stm32_rng.c @@ -5,16 +5,14 @@ #define LOG_CATEGORY UCLASS_RNG -#include <common.h> #include <clk.h> #include <dm.h> #include <log.h> #include <reset.h> #include <rng.h> +#include <asm/io.h> #include <linux/bitops.h> #include <linux/delay.h> - -#include <asm/io.h> #include <linux/iopoll.h> #include <linux/kernel.h> diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 88d6786..8b19e26 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -319,6 +319,14 @@ config DEBUG_UART_S5P will need to provide parameters to make this work. The driver will be available until the real driver-model serial is running. +config DEBUG_UART_MSM + bool "Qualcomm QUP UART debug" + depends on ARCH_SNAPDRAGON + help + Select this to enable a debug UART using the serial_msm driver. You + will need to provide parameters to make this work. The driver will + be available until the real driver-model serial is running. + config DEBUG_UART_MSM_GENI bool "Qualcomm snapdragon" depends on ARCH_SNAPDRAGON diff --git a/drivers/serial/serial_msm.c b/drivers/serial/serial_msm.c index f4d9631..ac4280c 100644 --- a/drivers/serial/serial_msm.c +++ b/drivers/serial/serial_msm.c @@ -160,29 +160,14 @@ static int msm_uart_clk_init(struct udevice *dev) { uint clk_rate = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), "clock-frequency", 115200); - uint clkd[2]; /* clk_id and clk_no */ - int clk_offset; - struct udevice *clk_dev; struct clk clk; int ret; - ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), "clock", - clkd, 2); - if (ret) - return ret; - - clk_offset = fdt_node_offset_by_phandle(gd->fdt_blob, clkd[0]); - if (clk_offset < 0) - return clk_offset; - - ret = uclass_get_device_by_of_offset(UCLASS_CLK, clk_offset, &clk_dev); - if (ret) - return ret; - - clk.id = clkd[1]; - ret = clk_request(clk_dev, &clk); - if (ret < 0) + ret = clk_get_by_name(dev, "core", &clk); + if (ret < 0) { + pr_warn("%s: Failed to get clock: %d\n", __func__, ret); return ret; + } ret = clk_set_rate(&clk, clk_rate); if (ret < 0) @@ -218,7 +203,6 @@ static int msm_serial_probe(struct udevice *dev) if (ret) return ret; - pinctrl_select_state(dev, "uart"); uart_dm_init(priv); return 0; @@ -251,4 +235,42 @@ U_BOOT_DRIVER(serial_msm) = { .priv_auto = sizeof(struct msm_serial_data), .probe = msm_serial_probe, .ops = &msm_serial_ops, + .flags = DM_FLAG_PRE_RELOC, }; + +#ifdef CONFIG_DEBUG_UART_MSM + +static struct msm_serial_data init_serial_data = { + .base = CONFIG_VAL(DEBUG_UART_BASE), + .clk_rate = 7372800, +}; + +#include <debug_uart.h> + +/* Uncomment to turn on UART clocks when debugging U-Boot as aboot on MSM8916 */ +//int apq8016_clk_init_uart(phys_addr_t gcc_base); + +static inline void _debug_uart_init(void) +{ + /* Uncomment to turn on UART clocks when debugging U-Boot as aboot on MSM8916 */ + //apq8016_clk_init_uart(0x1800000); + uart_dm_init(&init_serial_data); +} + +static inline void _debug_uart_putc(int ch) +{ + struct msm_serial_data *priv = &init_serial_data; + + while (!(readl(priv->base + UARTDM_SR) & UARTDM_SR_TX_EMPTY) && + !(readl(priv->base + UARTDM_ISR) & UARTDM_ISR_TX_READY)) + ; + + writel(UARTDM_CR_CMD_RESET_TX_READY, priv->base + UARTDM_CR); + + writel(1, priv->base + UARTDM_NCF_TX); + writel(ch, priv->base + UARTDM_TF); +} + +DEBUG_UART_FUNCS + +#endif diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 428a4d2..f04c21e 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -290,6 +290,7 @@ int pl01x_serial_probe(struct udevice *dev) { struct pl01x_serial_plat *plat = dev_get_plat(dev); struct pl01x_priv *priv = dev_get_priv(dev); + int ret; #if CONFIG_IS_ENABLED(OF_PLATDATA) struct dtd_serial_pl01x *dtplat = &plat->dtplat; @@ -301,10 +302,14 @@ int pl01x_serial_probe(struct udevice *dev) #endif priv->type = plat->type; - if (!plat->skip_init) - return pl01x_generic_serial_init(priv->regs, priv->type); - else + if (!plat->skip_init) { + ret = pl01x_generic_serial_init(priv->regs, priv->type); + if (ret) + return ret; + return pl01x_serial_setbrg(dev, gd->baudrate); + } else { return 0; + } } int pl01x_serial_getc(struct udevice *dev) diff --git a/drivers/soc/soc_ti_k3.c b/drivers/soc/soc_ti_k3.c index 355a536..3a4e58b 100644 --- a/drivers/soc/soc_ti_k3.c +++ b/drivers/soc/soc_ti_k3.c @@ -45,6 +45,12 @@ static const char *get_family_string(u32 idreg) case JTAG_ID_PARTNO_AM62AX: family = "AM62AX"; break; + case JTAG_ID_PARTNO_J784S4: + family = "J784S4"; + break; + case JTAG_ID_PARTNO_AM62PX: + family = "AM62PX"; + break; default: family = "Unknown Silicon"; }; diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c index 7de9433..c8694fd 100644 --- a/drivers/spi/rk_spi.c +++ b/drivers/spi/rk_spi.c @@ -453,8 +453,17 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen, * case of read-only transfers by using the full 16bits of each * FIFO element. */ - if (!out) + if (!out) { ret = rockchip_spi_16bit_reader(dev, &in, &len); + /* + * If "in" isn't 16b-aligned, we need to send the last byte + * ourselves. We however need to have the controller in RO mode + * which differs from the default. + */ + clrsetbits_le32(®s->ctrlr0, + TMOD_MASK << TMOD_SHIFT, + TMOD_RO << TMOD_SHIFT); + } /* This is the original 8bit reader/writer code */ while (len > 0) { @@ -465,12 +474,13 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen, rkspi_enable_chip(regs, true); toread = todo; - towrite = todo; + /* Only write if we have something to write */ + towrite = out ? todo : 0; while (toread || towrite) { u32 status = readl(®s->sr); if (towrite && !(status & SR_TF_FULL)) { - writel(out ? *out++ : 0, regs->txdr); + writel(*out++, regs->txdr); towrite--; } if (toread && !(status & SR_RF_EMPT)) { @@ -501,6 +511,10 @@ static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen, spi_cs_deactivate(dev, slave_plat->cs); rkspi_enable_chip(regs, false); + if (!out) + clrsetbits_le32(®s->ctrlr0, + TMOD_MASK << TMOD_SHIFT, + TMOD_TR << TMOD_SHIFT); return ret; } diff --git a/drivers/sysreset/sysreset_rockchip.c b/drivers/sysreset/sysreset_rockchip.c index 0fc6b68..f353f9b 100644 --- a/drivers/sysreset/sysreset_rockchip.c +++ b/drivers/sysreset/sysreset_rockchip.c @@ -7,7 +7,6 @@ #include <dm.h> #include <errno.h> #include <sysreset.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/cru_rk3328.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/thermal/imx_tmu.c b/drivers/thermal/imx_tmu.c index 4721cfb..c7fe0f0 100644 --- a/drivers/thermal/imx_tmu.c +++ b/drivers/thermal/imx_tmu.c @@ -570,12 +570,14 @@ static int imx_tmu_parse_fdt(struct udevice *dev) { struct imx_tmu_plat *pdata = dev_get_plat(dev), *p_parent_data; struct ofnode_phandle_args args; - ofnode trips_np; + ofnode trips_np, cpu_thermal_np; int ret; dev_dbg(dev, "%s\n", __func__); - pdata->polling_delay = IMX_TMU_POLLING_DELAY_MS; + cpu_thermal_np = ofnode_path("/thermal-zones/cpu-thermal"); + pdata->polling_delay = ofnode_read_u32_default(cpu_thermal_np, "polling-delay", + IMX_TMU_POLLING_DELAY_MS); if (pdata->zone_node) { pdata->regs = (union tmu_regs *)dev_read_addr_ptr(dev); diff --git a/drivers/usb/dwc3/dwc3-generic.c b/drivers/usb/dwc3/dwc3-generic.c index 6fb2de8..a379a00 100644 --- a/drivers/usb/dwc3/dwc3-generic.c +++ b/drivers/usb/dwc3/dwc3-generic.c @@ -21,6 +21,7 @@ #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <malloc.h> +#include <power/regulator.h> #include <usb.h> #include "core.h" #include "gadget.h" @@ -47,6 +48,7 @@ struct dwc3_generic_priv { struct dwc3_generic_host_priv { struct xhci_ctrl xhci_ctrl; struct dwc3_generic_priv gen_priv; + struct udevice *vbus_supply; }; static int dwc3_generic_probe(struct udevice *dev, @@ -240,11 +242,24 @@ static int dwc3_generic_host_probe(struct udevice *dev) if (rc) return rc; + rc = device_get_supply_regulator(dev, "vbus-supply", &priv->vbus_supply); + if (rc) + debug("%s: No vbus regulator found: %d\n", dev->name, rc); + + /* Only returns an error if regulator is valid and failed to enable due to a driver issue */ + rc = regulator_set_enable_if_allowed(priv->vbus_supply, true); + if (rc) + return rc; + hccr = (struct xhci_hccr *)priv->gen_priv.base; hcor = (struct xhci_hcor *)(priv->gen_priv.base + HC_LENGTH(xhci_readl(&(hccr)->cr_capbase))); - return xhci_register(dev, hccr, hcor); + rc = xhci_register(dev, hccr, hcor); + if (rc) + regulator_set_enable_if_allowed(priv->vbus_supply, false); + + return rc; } static int dwc3_generic_host_remove(struct udevice *dev) @@ -252,9 +267,12 @@ static int dwc3_generic_host_remove(struct udevice *dev) struct dwc3_generic_host_priv *priv = dev_get_priv(dev); int rc; - rc = xhci_deregister(dev); + /* This function always returns 0 */ + xhci_deregister(dev); + + rc = regulator_set_enable_if_allowed(priv->vbus_supply, false); if (rc) - return rc; + debug("%s: Failed to disable vbus regulator: %d\n", dev->name, rc); return dwc3_generic_remove(dev, &priv->gen_priv); } diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index c72a804..4621a6f 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -70,12 +70,21 @@ config USB_GADGET_PRODUCT_NUM hex "Product ID of the USB device" default 0x701a if ARCH_TEGRA default 0x1010 if ARCH_SUNXI - default 0x310a if ROCKCHIP_RK3036 + default 0x110a if ROCKCHIP_RV1108 + default 0x110b if ROCKCHIP_RV1126 default 0x300a if ROCKCHIP_RK3066 + default 0x301a if ROCKCHIP_RK3036 + default 0x310b if ROCKCHIP_RK3188 default 0x310c if ROCKCHIP_RK3128 - default 0x320a if ROCKCHIP_RK3229 || ROCKCHIP_RK3288 - default 0x330a if ROCKCHIP_RK3328 + default 0x320a if ROCKCHIP_RK3288 + default 0x320b if ROCKCHIP_RK322X + default 0x320c if ROCKCHIP_RK3328 + default 0x330a if ROCKCHIP_RK3368 default 0x330c if ROCKCHIP_RK3399 + default 0x330d if ROCKCHIP_PX30 + default 0x330e if ROCKCHIP_RK3308 + default 0x350a if ROCKCHIP_RK3568 + default 0x350b if ROCKCHIP_RK3588 default 0x0 help Product ID of the USB device emulated, reported to the host device. diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index dd0d153..98fe7bc 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -9,6 +9,7 @@ #include <common.h> #include <dm.h> +#include <dm/lists.h> #include <errno.h> #include <usb.h> #include <usb/ehci-ci.h> @@ -119,6 +120,24 @@ static int ehci_usb_of_to_plat(struct udevice *dev) return 0; } +static int ehci_usb_of_bind(struct udevice *dev) +{ + ofnode ulpi_node = ofnode_first_subnode(dev_ofnode(dev)); + ofnode phy_node; + + if (!ofnode_valid(ulpi_node)) + return 0; + + phy_node = ofnode_first_subnode(ulpi_node); + if (!ofnode_valid(phy_node)) { + printf("%s: ulpi subnode with no phy\n", __func__); + return -ENOENT; + } + + return device_bind_driver_to_node(dev, "msm8916_usbphy", "msm8916_usbphy", + phy_node, NULL); +} + #if defined(CONFIG_CI_UDC) /* Little quirk that MSM needs with Chipidea controller * Must reinit phy after reset @@ -132,7 +151,7 @@ void ci_init_after_reset(struct ehci_ctrl *ctrl) #endif static const struct udevice_id ehci_usb_ids[] = { - { .compatible = "qcom,ehci-host", }, + { .compatible = "qcom,ci-hdrc", }, { } }; @@ -141,6 +160,7 @@ U_BOOT_DRIVER(usb_ehci) = { .id = UCLASS_USB, .of_match = ehci_usb_ids, .of_to_plat = ehci_usb_of_to_plat, + .bind = ehci_usb_of_bind, .probe = ehci_usb_probe, .remove = ehci_usb_remove, .ops = &ehci_usb_ops, diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c index a023129..34ef5a5 100644 --- a/drivers/video/console_normal.c +++ b/drivers/video/console_normal.c @@ -7,6 +7,7 @@ */ #include <common.h> +#include <charset.h> #include <dm.h> #include <video.h> #include <video_console.h> @@ -63,7 +64,7 @@ static int console_move_rows(struct udevice *dev, uint rowdst, return 0; } -static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -73,8 +74,9 @@ static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; diff --git a/drivers/video/console_rotate.c b/drivers/video/console_rotate.c index 65358a1..e4303df 100644 --- a/drivers/video/console_rotate.c +++ b/drivers/video/console_rotate.c @@ -7,6 +7,7 @@ */ #include <common.h> +#include <charset.h> #include <dm.h> #include <video.h> #include <video_console.h> @@ -67,7 +68,7 @@ static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -77,8 +78,9 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int x, linenum, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -145,7 +147,7 @@ static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -155,8 +157,9 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; @@ -227,7 +230,7 @@ static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc, return 0; } -static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) +static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -237,8 +240,9 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch) int pbytes = VNBYTES(vid_priv->bpix); int linenum, x, ret; void *start, *line; + u8 ch = console_utf_to_cp437(cp); uchar *pfont = fontdata->video_fontdata + - (u8)ch * fontdata->char_pixel_bytes; + ch * fontdata->char_pixel_bytes; if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac) return -EAGAIN; diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 547e5a8..362458a 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -262,7 +262,7 @@ static int console_truetype_move_rows(struct udevice *dev, uint rowdst, } static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, - char ch) + int cp) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct udevice *vid = dev->parent; @@ -281,7 +281,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, int row, ret; /* First get some basic metrics about this character */ - stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb); + stbtt_GetCodepointHMetrics(font, cp, &advance, &lsb); /* * First out our current X position in fractional pixels. If we wrote @@ -290,7 +290,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, xpos = frac(VID_TO_PIXEL((double)x)); if (vc_priv->last_ch) { xpos += met->scale * stbtt_GetCodepointKernAdvance(font, - vc_priv->last_ch, ch); + vc_priv->last_ch, cp); } /* @@ -320,7 +320,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, * return NULL; */ data = stbtt_GetCodepointBitmapSubpixel(font, met->scale, met->scale, - x_shift, 0, ch, &width, &height, + x_shift, 0, cp, &width, &height, &xoff, &yoff); if (!data) return width_frac; diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c index 5e75b6e..fb78463 100644 --- a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c +++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c @@ -27,7 +27,6 @@ #include <common.h> #include <log.h> #include <video.h> -#include <asm/io.h> #include <dm/device-internal.h> #include <linux/bitops.h> #include <linux/time.h> diff --git a/drivers/video/rockchip/rk3288_hdmi.c b/drivers/video/rockchip/rk3288_hdmi.c index 8bedee5..efa8754 100644 --- a/drivers/video/rockchip/rk3288_hdmi.c +++ b/drivers/video/rockchip/rk3288_hdmi.c @@ -14,7 +14,6 @@ #include <regmap.h> #include <syscon.h> #include <asm/gpio.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/grf_rk3288.h> diff --git a/drivers/video/rockchip/rk3288_mipi.c b/drivers/video/rockchip/rk3288_mipi.c index c0dffa3..9d42119 100644 --- a/drivers/video/rockchip/rk3288_mipi.c +++ b/drivers/video/rockchip/rk3288_mipi.c @@ -14,7 +14,6 @@ #include "rk_mipi.h" #include <syscon.h> #include <asm/gpio.h> -#include <asm/io.h> #include <dm/uclass-internal.h> #include <linux/err.h> #include <linux/kernel.h> diff --git a/drivers/video/rockchip/rk3288_vop.c b/drivers/video/rockchip/rk3288_vop.c index 44f32bb..a468385 100644 --- a/drivers/video/rockchip/rk3288_vop.c +++ b/drivers/video/rockchip/rk3288_vop.c @@ -12,7 +12,6 @@ #include <syscon.h> #include <video.h> #include <asm/global_data.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/grf_rk3288.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/video/rockchip/rk3399_hdmi.c b/drivers/video/rockchip/rk3399_hdmi.c index 3041360..5f3f5d2 100644 --- a/drivers/video/rockchip/rk3399_hdmi.c +++ b/drivers/video/rockchip/rk3399_hdmi.c @@ -12,7 +12,6 @@ #include <regmap.h> #include <syscon.h> #include <asm/gpio.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/grf_rk3399.h> diff --git a/drivers/video/rockchip/rk3399_mipi.c b/drivers/video/rockchip/rk3399_mipi.c index 7fc79ba..b62d808 100644 --- a/drivers/video/rockchip/rk3399_mipi.c +++ b/drivers/video/rockchip/rk3399_mipi.c @@ -14,7 +14,6 @@ #include "rk_mipi.h" #include <syscon.h> #include <asm/gpio.h> -#include <asm/io.h> #include <dm/uclass-internal.h> #include <linux/err.h> #include <linux/kernel.h> diff --git a/drivers/video/rockchip/rk3399_vop.c b/drivers/video/rockchip/rk3399_vop.c index a34b491..cb589c7 100644 --- a/drivers/video/rockchip/rk3399_vop.c +++ b/drivers/video/rockchip/rk3399_vop.c @@ -13,7 +13,6 @@ #include <video.h> #include <asm/arch-rockchip/hardware.h> #include <asm/global_data.h> -#include <asm/io.h> #include "rk_vop.h" DECLARE_GLOBAL_DATA_PTR; diff --git a/drivers/video/rockchip/rk_edp.c b/drivers/video/rockchip/rk_edp.c index dbd70ad..5f68a61 100644 --- a/drivers/video/rockchip/rk_edp.c +++ b/drivers/video/rockchip/rk_edp.c @@ -17,7 +17,6 @@ #include <reset.h> #include <syscon.h> #include <asm/gpio.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> #include <asm/arch-rockchip/edp_rk3288.h> diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c index 8dcd4d5..044a29e 100644 --- a/drivers/video/rockchip/rk_hdmi.c +++ b/drivers/video/rockchip/rk_hdmi.c @@ -15,7 +15,6 @@ #include <regmap.h> #include <syscon.h> #include <asm/gpio.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> #include "rk_hdmi.h" diff --git a/drivers/video/rockchip/rk_lvds.c b/drivers/video/rockchip/rk_lvds.c index 9cf3e3c..d0a015e 100644 --- a/drivers/video/rockchip/rk_lvds.c +++ b/drivers/video/rockchip/rk_lvds.c @@ -13,7 +13,6 @@ #include <syscon.h> #include <asm/global_data.h> #include <asm/gpio.h> -#include <asm/io.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/grf_rk3288.h> #include <asm/arch-rockchip/hardware.h> diff --git a/drivers/video/vidconsole-uclass.c b/drivers/video/vidconsole-uclass.c index 22d55df..5f89f6a 100644 --- a/drivers/video/vidconsole-uclass.c +++ b/drivers/video/vidconsole-uclass.c @@ -11,6 +11,7 @@ #include <common.h> #include <abuf.h> +#include <charset.h> #include <command.h> #include <console.h> #include <log.h> @@ -20,7 +21,7 @@ #include <video_font.h> /* Bitmap font for code page 437 */ #include <linux/ctype.h> -int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch) +int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, int ch) { struct vidconsole_ops *ops = vidconsole_get_ops(dev); @@ -426,8 +427,8 @@ error: priv->escape = 0; } -/* Put that actual character on the screen (using the CP437 code page). */ -static int vidconsole_output_glyph(struct udevice *dev, char ch) +/* Put that actual character on the screen (using the UTF-32 code points). */ +static int vidconsole_output_glyph(struct udevice *dev, int ch) { struct vidconsole_priv *priv = dev_get_uclass_priv(dev); int ret; @@ -455,7 +456,7 @@ static int vidconsole_output_glyph(struct udevice *dev, char ch) int vidconsole_put_char(struct udevice *dev, char ch) { struct vidconsole_priv *priv = dev_get_uclass_priv(dev); - int ret; + int cp, ret; if (priv->escape) { vidconsole_escape_char(dev, ch); @@ -489,7 +490,14 @@ int vidconsole_put_char(struct udevice *dev, char ch) priv->last_ch = 0; break; default: - ret = vidconsole_output_glyph(dev, ch); + if (CONFIG_IS_ENABLED(CHARSET)) { + cp = utf8_to_utf32_stream(ch, priv->utf8_buf); + if (cp == 0) + return 0; + } else { + cp = ch; + } + ret = vidconsole_output_glyph(dev, cp); if (ret < 0) return ret; break; diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h index 0ec581b..bb0277e 100644 --- a/drivers/video/vidconsole_internal.h +++ b/drivers/video/vidconsole_internal.h @@ -6,6 +6,9 @@ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com> */ +#include <charset.h> +#include <config.h> + #define FLIPPED_DIRECTION 1 #define NORMAL_DIRECTION 0 @@ -142,3 +145,19 @@ int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *i * See details in video_console.h select_font function **/ int console_simple_select_font(struct udevice *dev, const char *name, uint size); + +/** + * Internal function to convert Unicode code points to code page 437. + * Used by video consoles using bitmap fonts. + * + * @param codepoint Unicode code point + * @returns code page 437 character. + */ +static inline u8 console_utf_to_cp437(int codepoint) +{ + if (CONFIG_IS_ENABLED(CHARSET)) { + utf_to_cp(&codepoint, codepage_437); + return codepoint; + } + return codepoint; +} diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index cf5dfb1..aa89604 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c @@ -107,7 +107,7 @@ static int virtio_pci_get_config(struct udevice *udev, unsigned int offset, int i; for (i = 0; i < len; i++) - ptr[i] = ioread8(ioaddr + i); + ptr[i] = ioread8(ioaddr + offset + i); return 0; } @@ -121,7 +121,7 @@ static int virtio_pci_set_config(struct udevice *udev, unsigned int offset, int i; for (i = 0; i < len; i++) - iowrite8(ptr[i], ioaddr + i); + iowrite8(ptr[i], ioaddr + offset + i); return 0; } |