From 771ee9b6ede985f6d63a196885c799f616b90d08 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Mon, 28 Jan 2019 15:37:27 +0100 Subject: watchdog: bcm6345: switch to raw I/O functions This driver is used on several big endian mips board. So we could use raw I/O function instead of forcing big endian access. Signed-off-by: Philippe Reynes Reviewed-by: Daniel Schwierzeck --- drivers/watchdog/bcm6345_wdt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/bcm6345_wdt.c b/drivers/watchdog/bcm6345_wdt.c index e1bd73dfd4d..44f56620382 100644 --- a/drivers/watchdog/bcm6345_wdt.c +++ b/drivers/watchdog/bcm6345_wdt.c @@ -32,8 +32,8 @@ static int bcm6345_wdt_reset(struct udevice *dev) { struct bcm6345_wdt_priv *priv = dev_get_priv(dev); - writel_be(WDT_CTL_START1_MASK, priv->regs + WDT_CTL_REG); - writel_be(WDT_CTL_START2_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_START1_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_START2_MASK, priv->regs + WDT_CTL_REG); return 0; } @@ -50,7 +50,7 @@ static int bcm6345_wdt_start(struct udevice *dev, u64 timeout, ulong flags) timeout = WDT_VAL_MAX; } - writel_be(timeout, priv->regs + WDT_VAL_REG); + writel(timeout, priv->regs + WDT_VAL_REG); return bcm6345_wdt_reset(dev); } @@ -64,8 +64,8 @@ static int bcm6345_wdt_stop(struct udevice *dev) { struct bcm6345_wdt_priv *priv = dev_get_priv(dev); - writel_be(WDT_CTL_STOP1_MASK, priv->regs + WDT_CTL_REG); - writel_be(WDT_CTL_STOP2_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_STOP1_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_STOP2_MASK, priv->regs + WDT_CTL_REG); return 0; } -- cgit v1.3.1 From 47b68d00a383daefdc233f4b92f016caf43d712b Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Mon, 28 Jan 2019 15:37:28 +0100 Subject: watchdog: bcm6345: allow to use this driver on arm bcm6858 This IP is also used on some arm SoC, so we allow to use it on arm bcm6858 too. Signed-off-by: Philippe Reynes --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 10fd3039aa2..9456abd16b8 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -88,7 +88,7 @@ config WDT_ASPEED config WDT_BCM6345 bool "BCM6345 watchdog timer support" - depends on WDT && ARCH_BMIPS + depends on WDT && (ARCH_BMIPS || ARCH_BCM6858) help Select this to enable watchdog timer for BCM6345 SoCs. The watchdog timer is stopped when initialized. -- cgit v1.3.1 From ba8ba69b66923362a379822d77a6e78c117721e1 Mon Sep 17 00:00:00 2001 From: Vabhav Sharma Date: Wed, 30 Jan 2019 11:24:00 +0000 Subject: drivers: serial: dm: Enable DM_FLAG_PRE_RELOC in SBSA pl011 uart driver The DM_FLAG_PRE_RELOC shall be enabled in SBSA PL011 uart driver as this driver is used in NXP based SoCs It is necessary to have Serial console running before relocation The !CONFIG_IS_ENABLED(OF_CONTROL) [*] check is set as "workaround" for DM problem : 4687919684e This flag is set if board does not support device-tree and using platform data, In DM Model either of device tree or platform data can be used to fetch device configuration It is possible to use SBSA UART with CONFIG_DM_SERIAL but witout corresponding device tree description (OF_CONTROL) Other board/SoCs have this flag set unconditionally Signed-off-by: Vabhav Sharma --- drivers/serial/serial_pl01x.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 12512f65782..2a5f256184f 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -363,9 +363,7 @@ U_BOOT_DRIVER(serial_pl01x) = { .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata), .probe = pl01x_serial_probe, .ops = &pl01x_serial_ops, -#if !CONFIG_IS_ENABLED(OF_CONTROL) .flags = DM_FLAG_PRE_RELOC, -#endif .priv_auto_alloc_size = sizeof(struct pl01x_priv), }; -- cgit v1.3.1 From 86617dd1402c506a989da74f1f9c13ce1580fa82 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 30 Jan 2019 13:07:00 +0100 Subject: clk: stm32mp1: no more get ck_usbo_48m in device tree Remove support of ck_usbo_48m clock node in device tree, but force 48MHz frequency to prepare alignment with kernel device tree. Signed-off-by: Patrick Delaunay --- drivers/clk/clk_stm32mp1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index b7c5d34fe06..88f453caa8d 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -241,7 +241,6 @@ enum stm32mp1_parent_id { _LSI, _LSE, _I2S_CKIN, - _USB_PHY_48, NB_OSC, /* other parent source */ @@ -273,6 +272,7 @@ enum stm32mp1_parent_id { _CK_MPU, _CK_MCU, _DSI_PHY, + _USB_PHY_48, _PARENT_NB, _UNKNOWN_ID = 0xff, }; @@ -1079,7 +1079,7 @@ static ulong stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) break; /* other */ case _USB_PHY_48: - clock = stm32mp1_clk_get_fixed(priv, _USB_PHY_48); + clock = 48000000; break; case _DSI_PHY: { @@ -1859,7 +1859,7 @@ static void stm32mp1_osc_init(struct udevice *dev) [_HSE] = "clk-hse", [_CSI] = "clk-csi", [_I2S_CKIN] = "i2s_ckin", - [_USB_PHY_48] = "ck_usbo_48m"}; + }; for (i = 0; i < NB_OSC; i++) { stm32mp1_osc_clk_init(name[i], priv, i); -- cgit v1.3.1 From d661f61847696dc5ac54b397908f886bd3583484 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 30 Jan 2019 13:07:01 +0100 Subject: clk: stm32mp1: add IPCC clock Add support for enable/disable of IPCC clock using AHB3 registers Signed-off-by: Patrick Delaunay --- drivers/clk/clk_stm32mp1.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 88f453caa8d..a2ab5ed2634 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -536,6 +536,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), STM32MP1_CLK_SET_CLR(RCC_MP_AHB3ENSETR, 11, HSEM, _UNKNOWN_SEL), + STM32MP1_CLK_SET_CLR(RCC_MP_AHB3ENSETR, 12, IPCC, _UNKNOWN_SEL), STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), -- cgit v1.3.1 From 63201281e5e51116676bf3a2b028035856d3f2a6 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 30 Jan 2019 13:07:02 +0100 Subject: clk: stm32mp1: correct access to RCC_OCENSETR/RCC_OCENCLRR Remove unnecessary setbits on set/clear registers. Avoid to deactivate HSI with HSE. Signed-off-by: Patrick Delaunay --- drivers/clk/clk_stm32mp1.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index a2ab5ed2634..39eaf64cdd1 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -1180,10 +1180,7 @@ static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset, static void stm32mp1_hs_ocs_set(int enable, fdt_addr_t rcc, u32 mask_on) { - if (enable) - setbits_le32(rcc + RCC_OCENSETR, mask_on); - else - setbits_le32(rcc + RCC_OCENCLRR, mask_on); + writel(mask_on, rcc + (enable ? RCC_OCENSETR : RCC_OCENCLRR)); } static int stm32mp1_osc_wait(int enable, fdt_addr_t rcc, u32 offset, @@ -1254,20 +1251,20 @@ static void stm32mp1_lsi_set(fdt_addr_t rcc, int enable) static void stm32mp1_hse_enable(fdt_addr_t rcc, int bypass, int digbyp, int css) { if (digbyp) - setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_DIGBYP); + writel(RCC_OCENR_DIGBYP, rcc + RCC_OCENSETR); if (bypass || digbyp) - setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_HSEBYP); + writel(RCC_OCENR_HSEBYP, rcc + RCC_OCENSETR); stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON); stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY); if (css) - setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_HSECSSON); + writel(RCC_OCENR_HSECSSON, rcc + RCC_OCENSETR); } static void stm32mp1_csi_set(fdt_addr_t rcc, int enable) { - stm32mp1_ls_osc_set(enable, rcc, RCC_OCENSETR, RCC_OCENR_CSION); + stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_CSION); stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY); } -- cgit v1.3.1 From f3a23c26097144de9ad08644a4bfc9c238df873a Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 30 Jan 2019 13:07:03 +0100 Subject: clk: stm32mp1: recalculate counter when switching freq Because stgen is initialized with HSI clock, we need to recalculate the counter when changing frequency. Signed-off-by: Lionel Debieve Signed-off-by: Patrick Delaunay --- drivers/clk/clk_stm32mp1.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 39eaf64cdd1..916f9f9e8c0 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -1469,10 +1469,15 @@ static void stgen_config(struct stm32mp1_clk_priv *priv) rate = stm32mp1_clk_get(priv, p); if (cntfid0 != rate) { + u64 counter; + pr_debug("System Generic Counter (STGEN) update\n"); clrbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN); - writel(0x0, stgenc + STGENC_CNTCVL); - writel(0x0, stgenc + STGENC_CNTCVU); + counter = (u64)readl(stgenc + STGENC_CNTCVL); + counter |= ((u64)(readl(stgenc + STGENC_CNTCVU))) << 32; + counter = lldiv(counter * (u64)rate, cntfid0); + writel((u32)counter, stgenc + STGENC_CNTCVL); + writel((u32)(counter >> 32), stgenc + STGENC_CNTCVU); writel(rate, stgenc + STGENC_CNTFID0); setbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN); -- cgit v1.3.1 From 8d6310aa0ba2bee92e14c0702c5ceec64943383a Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 30 Jan 2019 13:07:04 +0100 Subject: clk: stm32mp1: add debug information Add support of clk dump command and display information during probe (under CONFIG_DISPLAY_CPUINFO). Signed-off-by: Patrick Delaunay --- configs/stm32mp15_basic_defconfig | 1 + drivers/clk/clk_stm32mp1.c | 83 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/configs/stm32mp15_basic_defconfig b/configs/stm32mp15_basic_defconfig index 304688e56f8..d20b2ab3508 100644 --- a/configs/stm32mp15_basic_defconfig +++ b/configs/stm32mp15_basic_defconfig @@ -19,6 +19,7 @@ CONFIG_SYS_PROMPT="STM32MP> " # CONFIG_CMD_IMPORTENV is not set CONFIG_CMD_MEMINFO=y CONFIG_CMD_ADC=y +CONFIG_CMD_CLK=y CONFIG_CMD_FUSE=y CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 916f9f9e8c0..09227cf8db5 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -666,8 +666,8 @@ static const u8 stm32mp1_axi_div[8] = { 1, 2, 3, 4, 4, 4, 4, 4 }; -#ifdef DEBUG -static const char * const stm32mp1_clk_parent_name[_PARENT_NB] = { +static const __maybe_unused +char * const stm32mp1_clk_parent_name[_PARENT_NB] = { [_HSI] = "HSI", [_HSE] = "HSE", [_CSI] = "CSI", @@ -705,7 +705,8 @@ static const char * const stm32mp1_clk_parent_name[_PARENT_NB] = { [_DSI_PHY] = "DSI_PHY_PLL", }; -static const char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = { +static const __maybe_unused +char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = { [_I2C12_SEL] = "I2C12", [_I2C35_SEL] = "I2C35", [_I2C46_SEL] = "I2C46", @@ -724,7 +725,6 @@ static const char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = { [_DSI_SEL] = "DSI", [_ADC12_SEL] = "ADC12", }; -#endif static const struct stm32mp1_clk_data stm32mp1_data = { .gate = stm32mp1_clk_gate, @@ -1870,6 +1870,54 @@ static void stm32mp1_osc_init(struct udevice *dev) } } +static void __maybe_unused stm32mp1_clk_dump(struct stm32mp1_clk_priv *priv) +{ + char buf[32]; + int i, s, p; + + printf("Clocks:\n"); + for (i = 0; i < _PARENT_NB; i++) { + printf("- %s : %s MHz\n", + stm32mp1_clk_parent_name[i], + strmhz(buf, stm32mp1_clk_get(priv, i))); + } + printf("Source Clocks:\n"); + for (i = 0; i < _PARENT_SEL_NB; i++) { + p = (readl(priv->base + priv->data->sel[i].offset) >> + priv->data->sel[i].src) & priv->data->sel[i].msk; + if (p < priv->data->sel[i].nb_parent) { + s = priv->data->sel[i].parent[p]; + printf("- %s(%d) => parent %s(%d)\n", + stm32mp1_clk_parent_sel_name[i], i, + stm32mp1_clk_parent_name[s], s); + } else { + printf("- %s(%d) => parent index %d is invalid\n", + stm32mp1_clk_parent_sel_name[i], i, p); + } + } +} + +#ifdef CONFIG_CMD_CLK +int soc_clk_dump(void) +{ + struct udevice *dev; + struct stm32mp1_clk_priv *priv; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_CLK, + DM_GET_DRIVER(stm32mp1_clock), + &dev); + if (ret) + return ret; + + priv = dev_get_priv(dev); + + stm32mp1_clk_dump(priv); + + return 0; +} +#endif + static int stm32mp1_clk_probe(struct udevice *dev) { int result = 0; @@ -1893,6 +1941,33 @@ static int stm32mp1_clk_probe(struct udevice *dev) result = stm32mp1_clktree(dev); #endif +#ifndef CONFIG_SPL_BUILD +#if defined(DEBUG) + /* display debug information for probe after relocation */ + if (gd->flags & GD_FLG_RELOC) + stm32mp1_clk_dump(priv); +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) + if (gd->flags & GD_FLG_RELOC) { + char buf[32]; + + printf("Clocks:\n"); + printf("- MPU : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _CK_MPU))); + printf("- MCU : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _CK_MCU))); + printf("- AXI : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _ACLK))); + printf("- PER : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _CK_PER))); + /* DDRPHYC father */ + printf("- DDR : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _PLL2_R))); + } +#endif /* CONFIG_DISPLAY_CPUINFO */ +#endif + return result; } -- cgit v1.3.1 From bbd108a08225b1239b1ec1c10e8131fba6a3a95a Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Wed, 30 Jan 2019 13:07:06 +0100 Subject: clk: stm32mp1: correctly handle Clock Spreading Generator To activate the csg option, the driver need to set the bit2 of PLLNCR register = SSCG_CTRL: Spread Spectrum Clock Generator of PLLn enable. Signed-off-by: Patrick Delaunay --- doc/device-tree-bindings/clock/st,stm32mp1.txt | 10 +++++----- drivers/clk/clk_stm32mp1.c | 8 +++++++- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/doc/device-tree-bindings/clock/st,stm32mp1.txt b/doc/device-tree-bindings/clock/st,stm32mp1.txt index 6a9397e1054..ffcf8cd31dc 100644 --- a/doc/device-tree-bindings/clock/st,stm32mp1.txt +++ b/doc/device-tree-bindings/clock/st,stm32mp1.txt @@ -132,15 +132,15 @@ Optional Properties: frac = < 0x810 >; }; st,pll@1 { - cfg = < 1 43 1 0 0 PQR(0,1,1)>; - csg = <10 20 1>; + cfg = < 1 43 1 0 0 PQR(0,1,1) >; + csg = < 10 20 1 >; }; st,pll@2 { - cfg = < 2 85 3 13 3 0>; - csg = <10 20 SSCG_MODE_CENTER_SPREAD>; + cfg = < 2 85 3 13 3 0 >; + csg = < 10 20 SSCG_MODE_CENTER_SPREAD >; }; st,pll@3 { - cfg = < 2 78 4 7 9 3>; + cfg = < 2 78 4 7 9 3 >; }; st,pkcs = < CLK_STGEN_HSE diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index 09227cf8db5..aebc6f0a34c 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -165,6 +165,7 @@ /* used for ALL PLLNCR registers */ #define RCC_PLLNCR_PLLON BIT(0) #define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) #define RCC_PLLNCR_DIVPEN BIT(4) #define RCC_PLLNCR_DIVQEN BIT(5) #define RCC_PLLNCR_DIVREN BIT(6) @@ -1319,7 +1320,10 @@ static void pll_start(struct stm32mp1_clk_priv *priv, int pll_id) { const struct stm32mp1_clk_pll *pll = priv->data->pll; - writel(RCC_PLLNCR_PLLON, priv->base + pll[pll_id].pllxcr); + clrsetbits_le32(priv->base + pll[pll_id].pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); } static int pll_output(struct stm32mp1_clk_priv *priv, int pll_id, int output) @@ -1438,6 +1442,8 @@ static void pll_csg(struct stm32mp1_clk_priv *priv, int pll_id, u32 *csg) RCC_PLLNCSGR_SSCG_MODE_MASK); writel(pllxcsg, priv->base + pll[pll_id].pllxcsgr); + + setbits_le32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_SSCG_CTRL); } static int set_clksrc(struct stm32mp1_clk_priv *priv, unsigned int clksrc) -- cgit v1.3.1 From 351a4aa050c834954498e2114cab3429597b7c92 Mon Sep 17 00:00:00 2001 From: Faiz Abbas Date: Wed, 30 Jan 2019 18:08:42 +0530 Subject: mmc: omap_hsmmc: Workaround errata regarding SDR104/HS200 tuning failures (i929) Errata i929 in certain OMAP5/DRA7XX/AM57XX silicon revisions (SPRZ426D - November 2014 - Revised February 2018 [1]) mentions unexpected tuning pattern errors. A small failure band may be present in the tuning range which may be missed by the current algorithm. Furthermore, the failure bands vary with temperature leading to different optimum tuning values for different temperatures. As suggested in the related Application Report (SPRACA9B - October 2017 - Revised July 2018 [2]), tuning should be done in two stages. In stage 1, assign the optimum ratio in the maximum pass window for the current temperature. In stage 2, if the chosen value is close to the small failure band, move away from it in the appropriate direction. References: [1] http://www.ti.com/lit/pdf/sprz426 [2] http://www.ti.com/lit/pdf/SPRACA9 Signed-off-by: Faiz Abbas --- drivers/mmc/omap_hsmmc.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 5cb97eb02af..b11c71cae77 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -47,6 +47,7 @@ #endif #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -622,6 +623,10 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) u32 phase_delay = 0; u32 start_window = 0, max_window = 0; u32 length = 0, max_len = 0; + bool single_point_failure = false; + struct udevice *thermal_dev; + int temperature; + int i; mmc_base = priv->base_addr; val = readl(&mmc_base->capa2); @@ -632,9 +637,25 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) ((mmc->selected_mode == UHS_SDR50) && (val & CAPA2_TSDR50)))) return 0; + ret = uclass_first_device(UCLASS_THERMAL, &thermal_dev); + if (ret) { + printf("Couldn't get thermal device for tuning\n"); + return ret; + } + ret = thermal_get_temp(thermal_dev, &temperature); + if (ret) { + printf("Couldn't get temperature for tuning\n"); + return ret; + } val = readl(&mmc_base->dll); val |= DLL_SWT; writel(val, &mmc_base->dll); + + /* + * Stage 1: Search for a maximum pass window ignoring any + * any single point failures. If the tuning value ends up + * near it, move away from it in stage 2 below + */ while (phase_delay <= MAX_PHASE_DELAY) { omap_hsmmc_set_dll(mmc, phase_delay); @@ -643,10 +664,16 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) if (cur_match) { if (prev_match) { length++; + } else if (single_point_failure) { + /* ignore single point failure */ + length++; + single_point_failure = false; } else { start_window = phase_delay; length = 1; } + } else { + single_point_failure = prev_match; } if (length > max_len) { @@ -668,8 +695,71 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) ret = -EIO; goto tuning_error; } + /* + * Assign tuning value as a ratio of maximum pass window based + * on temperature + */ + if (temperature < -20000) + phase_delay = min(max_window + 4 * max_len - 24, + max_window + + DIV_ROUND_UP(13 * max_len, 16) * 4); + else if (temperature < 20000) + phase_delay = max_window + DIV_ROUND_UP(9 * max_len, 16) * 4; + else if (temperature < 40000) + phase_delay = max_window + DIV_ROUND_UP(8 * max_len, 16) * 4; + else if (temperature < 70000) + phase_delay = max_window + DIV_ROUND_UP(7 * max_len, 16) * 4; + else if (temperature < 90000) + phase_delay = max_window + DIV_ROUND_UP(5 * max_len, 16) * 4; + else if (temperature < 120000) + phase_delay = max_window + DIV_ROUND_UP(4 * max_len, 16) * 4; + else + phase_delay = max_window + DIV_ROUND_UP(3 * max_len, 16) * 4; + + /* + * Stage 2: Search for a single point failure near the chosen tuning + * value in two steps. First in the +3 to +10 range and then in the + * +2 to -10 range. If found, move away from it in the appropriate + * direction by the appropriate amount depending on the temperature. + */ + for (i = 3; i <= 10; i++) { + omap_hsmmc_set_dll(mmc, phase_delay + i); + if (mmc_send_tuning(mmc, opcode, NULL)) { + if (temperature < 10000) + phase_delay += i + 6; + else if (temperature < 20000) + phase_delay += i - 12; + else if (temperature < 70000) + phase_delay += i - 8; + else if (temperature < 90000) + phase_delay += i - 6; + else + phase_delay += i - 6; + + goto single_failure_found; + } + } + + for (i = 2; i >= -10; i--) { + omap_hsmmc_set_dll(mmc, phase_delay + i); + if (mmc_send_tuning(mmc, opcode, NULL)) { + if (temperature < 10000) + phase_delay += i + 12; + else if (temperature < 20000) + phase_delay += i + 8; + else if (temperature < 70000) + phase_delay += i + 8; + else if (temperature < 90000) + phase_delay += i + 10; + else + phase_delay += i + 12; + + goto single_failure_found; + } + } + +single_failure_found: - phase_delay = max_window + 4 * ((3 * max_len) >> 2); omap_hsmmc_set_dll(mmc, phase_delay); mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); -- cgit v1.3.1 From dcae39e55f1e6987b4bd4732c17350a1f10eaa09 Mon Sep 17 00:00:00 2001 From: Philippe Reynes Date: Thu, 31 Jan 2019 18:57:37 +0100 Subject: watchdog: bcm6345: allow to use this driver on arm bcm63158 This IP is also used on some arm SoC, so we allow to use it on arm bcm63158 too. Signed-off-by: Philippe Reynes --- drivers/watchdog/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 9456abd16b8..115fc4551ff 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -88,7 +88,7 @@ config WDT_ASPEED config WDT_BCM6345 bool "BCM6345 watchdog timer support" - depends on WDT && (ARCH_BMIPS || ARCH_BCM6858) + depends on WDT && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158) help Select this to enable watchdog timer for BCM6345 SoCs. The watchdog timer is stopped when initialized. -- cgit v1.3.1 From f3885649657b4dfb669ae4505a0516c3affb8694 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 1 Feb 2019 16:01:07 +0100 Subject: dm: device: fail uclass_find_first_device() if list_empty While uclass_find_device() fails with -ENODEV in case of list_empty strangely uclass_find_first_device() returns 0. Fix uclass_find_first_device() to also fail with -ENODEV instead. Signed-off-by: Marcel Ziswiler Reviewed-by: Simon Glass --- drivers/core/uclass.c | 2 +- test/dm/core.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index a622f079410..fc3157de39c 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -225,7 +225,7 @@ int uclass_find_first_device(enum uclass_id id, struct udevice **devp) if (ret) return ret; if (list_empty(&uc->dev_head)) - return 0; + return -ENODEV; *devp = list_first_entry(&uc->dev_head, struct udevice, uclass_node); diff --git a/test/dm/core.c b/test/dm/core.c index 260f6494a2e..edd55b05d6e 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -749,6 +749,10 @@ static int dm_test_uclass_devices_find(struct unit_test_state *uts) ut_assert(dev); } + ret = uclass_find_first_device(UCLASS_TEST_DUMMY, &dev); + ut_assert(ret == -ENODEV); + ut_assert(!dev); + return 0; } DM_TEST(dm_test_uclass_devices_find, DM_TESTF_SCAN_PDATA); -- cgit v1.3.1