diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/imx/Kconfig | 16 | ||||
-rw-r--r-- | drivers/clk/imx/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/imx/clk-imxrt1020.c | 227 | ||||
-rw-r--r-- | drivers/clk/imx/clk-imxrt1050.c | 30 | ||||
-rw-r--r-- | drivers/clk/imx/clk-pllv3.c | 9 | ||||
-rw-r--r-- | drivers/phy/meson-gxl-usb2.c | 30 | ||||
-rw-r--r-- | drivers/phy/meson-gxl-usb3.c | 44 | ||||
-rw-r--r-- | drivers/phy/phy-uclass.c | 16 | ||||
-rw-r--r-- | drivers/power/pmic/pfuze100.c | 2 | ||||
-rw-r--r-- | drivers/video/mxsfb.c | 94 | ||||
-rw-r--r-- | drivers/video/sunxi/sunxi_display.c | 33 | ||||
-rw-r--r-- | drivers/video/videomodes.c | 29 | ||||
-rw-r--r-- | drivers/video/videomodes.h | 11 |
13 files changed, 451 insertions, 91 deletions
diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index 059bc2fbb9..96721bcbf3 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -69,6 +69,22 @@ config CLK_IMX8MP help This enables support clock driver for i.MX8MP platforms. +config SPL_CLK_IMXRT1020 + bool "SPL clock support for i.MXRT1020" + depends on ARCH_IMXRT && SPL + select SPL_CLK + select SPL_CLK_CCF + help + This enables SPL DM/DTS support for clock driver in i.MXRT1020 + +config CLK_IMXRT1020 + bool "Clock support for i.MXRT1020" + depends on ARCH_IMXRT + select CLK + select CLK_CCF + help + This enables support clock driver for i.MXRT1020 platforms. + config SPL_CLK_IMXRT1050 bool "SPL clock support for i.MXRT1050" depends on ARCH_IMXRT && SPL diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index 1e8a49d0f3..01bbbdf3ae 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -17,4 +17,5 @@ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MN) += clk-imx8mn.o clk-pll14xx.o \ obj-$(CONFIG_$(SPL_TPL_)CLK_IMX8MP) += clk-imx8mp.o clk-pll14xx.o \ clk-composite-8m.o +obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1020) += clk-imxrt1020.o obj-$(CONFIG_$(SPL_TPL_)CLK_IMXRT1050) += clk-imxrt1050.o diff --git a/drivers/clk/imx/clk-imxrt1020.c b/drivers/clk/imx/clk-imxrt1020.c new file mode 100644 index 0000000000..840f783940 --- /dev/null +++ b/drivers/clk/imx/clk-imxrt1020.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright(C) 2020 + * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com> + */ + +#include <common.h> +#include <clk.h> +#include <clk-uclass.h> +#include <dm.h> +#include <asm/arch/clock.h> +#include <asm/arch/imx-regs.h> +#include <dt-bindings/clock/imxrt1020-clock.h> + +#include "clk.h" + +static ulong imxrt1020_clk_get_rate(struct clk *clk) +{ + struct clk *c; + int ret; + + debug("%s(#%lu)\n", __func__, clk->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_get_rate(c); +} + +static ulong imxrt1020_clk_set_rate(struct clk *clk, unsigned long rate) +{ + struct clk *c; + int ret; + + debug("%s(#%lu), rate: %lu\n", __func__, clk->id, rate); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + return clk_set_rate(c, rate); +} + +static int __imxrt1020_clk_enable(struct clk *clk, bool enable) +{ + struct clk *c; + int ret; + + debug("%s(#%lu) en: %d\n", __func__, clk->id, enable); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + if (enable) + ret = clk_enable(c); + else + ret = clk_disable(c); + + return ret; +} + +static int imxrt1020_clk_disable(struct clk *clk) +{ + return __imxrt1020_clk_enable(clk, 0); +} + +static int imxrt1020_clk_enable(struct clk *clk) +{ + return __imxrt1020_clk_enable(clk, 1); +} + +static struct clk_ops imxrt1020_clk_ops = { + .set_rate = imxrt1020_clk_set_rate, + .get_rate = imxrt1020_clk_get_rate, + .enable = imxrt1020_clk_enable, + .disable = imxrt1020_clk_disable, +}; + +static const char * const pll2_bypass_sels[] = {"pll2_sys", "osc", }; +static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "osc", }; + +static const char *const pre_periph_sels[] = { "pll2_sys", "pll2_pfd3_297m", "pll3_pfd3_454_74m", "arm_podf", }; +static const char *const periph_sels[] = { "pre_periph_sel", "todo", }; +static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *const lpuart_sels[] = { "pll3_80m", "osc", }; +static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", }; +static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", }; + +static int imxrt1020_clk_probe(struct udevice *dev) +{ + void *base; + + /* Anatop clocks */ + base = (void *)ANATOP_BASE_ADDR; + + clk_dm(IMXRT1020_CLK_PLL2_SYS, + imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_sys", "osc", + base + 0x30, 0x1)); + clk_dm(IMXRT1020_CLK_PLL3_USB_OTG, + imx_clk_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", "osc", + base + 0x10, 0x1)); + + /* PLL bypass out */ + clk_dm(IMXRT1020_CLK_PLL2_BYPASS, + imx_clk_mux_flags("pll2_bypass", base + 0x30, 16, 1, + pll2_bypass_sels, + ARRAY_SIZE(pll2_bypass_sels), + CLK_SET_RATE_PARENT)); + clk_dm(IMXRT1020_CLK_PLL3_BYPASS, + imx_clk_mux_flags("pll3_bypass", base + 0x10, 16, 1, + pll3_bypass_sels, + ARRAY_SIZE(pll3_bypass_sels), + CLK_SET_RATE_PARENT)); + + clk_dm(IMXRT1020_CLK_PLL3_80M, + imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6)); + + clk_dm(IMXRT1020_CLK_PLL2_PFD0_352M, + imx_clk_pfd("pll2_pfd0_352m", "pll2_sys", base + 0x100, 0)); + clk_dm(IMXRT1020_CLK_PLL2_PFD1_594M, + imx_clk_pfd("pll2_pfd1_594m", "pll2_sys", base + 0x100, 1)); + clk_dm(IMXRT1020_CLK_PLL2_PFD2_396M, + imx_clk_pfd("pll2_pfd2_396m", "pll2_sys", base + 0x100, 2)); + clk_dm(IMXRT1020_CLK_PLL2_PFD3_297M, + imx_clk_pfd("pll2_pfd3_297m", "pll2_sys", base + 0x100, 3)); + clk_dm(IMXRT1020_CLK_PLL3_PFD1_664_62M, + imx_clk_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", base + 0xf0, 1)); + clk_dm(IMXRT1020_CLK_PLL3_PFD3_454_74M, + imx_clk_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", base + 0xf0, 3)); + + /* CCM clocks */ + base = dev_read_addr_ptr(dev); + if (base == (void *)FDT_ADDR_T_NONE) + return -EINVAL; + + clk_dm(IMXRT1020_CLK_PRE_PERIPH_SEL, + imx_clk_mux("pre_periph_sel", base + 0x18, 18, 2, + pre_periph_sels, ARRAY_SIZE(pre_periph_sels))); + clk_dm(IMXRT1020_CLK_PERIPH_SEL, + imx_clk_mux("periph_sel", base + 0x14, 25, 1, + periph_sels, ARRAY_SIZE(periph_sels))); + clk_dm(IMXRT1020_CLK_USDHC1_SEL, + imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, + usdhc_sels, ARRAY_SIZE(usdhc_sels))); + clk_dm(IMXRT1020_CLK_USDHC2_SEL, + imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, + usdhc_sels, ARRAY_SIZE(usdhc_sels))); + clk_dm(IMXRT1020_CLK_LPUART_SEL, + imx_clk_mux("lpuart_sel", base + 0x24, 6, 1, + lpuart_sels, ARRAY_SIZE(lpuart_sels))); + clk_dm(IMXRT1020_CLK_SEMC_ALT_SEL, + imx_clk_mux("semc_alt_sel", base + 0x14, 7, 1, + semc_alt_sels, ARRAY_SIZE(semc_alt_sels))); + clk_dm(IMXRT1020_CLK_SEMC_SEL, + imx_clk_mux("semc_sel", base + 0x14, 6, 1, + semc_sels, ARRAY_SIZE(semc_sels))); + + clk_dm(IMXRT1020_CLK_AHB_PODF, + imx_clk_divider("ahb_podf", "periph_sel", + base + 0x14, 10, 3)); + clk_dm(IMXRT1020_CLK_USDHC1_PODF, + imx_clk_divider("usdhc1_podf", "usdhc1_sel", + base + 0x24, 11, 3)); + clk_dm(IMXRT1020_CLK_USDHC2_PODF, + imx_clk_divider("usdhc2_podf", "usdhc2_sel", + base + 0x24, 16, 3)); + clk_dm(IMXRT1020_CLK_LPUART_PODF, + imx_clk_divider("lpuart_podf", "lpuart_sel", + base + 0x24, 0, 6)); + clk_dm(IMXRT1020_CLK_SEMC_PODF, + imx_clk_divider("semc_podf", "semc_sel", + base + 0x14, 16, 3)); + + clk_dm(IMXRT1020_CLK_USDHC1, + imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2)); + clk_dm(IMXRT1020_CLK_USDHC2, + imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4)); + clk_dm(IMXRT1020_CLK_LPUART1, + imx_clk_gate2("lpuart1", "lpuart_podf", base + 0x7c, 24)); + clk_dm(IMXRT1020_CLK_SEMC, + imx_clk_gate2("semc", "semc_podf", base + 0x74, 4)); + +#ifdef CONFIG_SPL_BUILD + struct clk *clk, *clk1; + + clk_get_by_id(IMXRT1020_CLK_SEMC_SEL, &clk1); + clk_get_by_id(IMXRT1020_CLK_SEMC_ALT_SEL, &clk); + clk_set_parent(clk1, clk); + + /* Configure PLL3_USB_OTG to 480MHz */ + clk_get_by_id(IMXRT1020_CLK_PLL3_USB_OTG, &clk); + clk_enable(clk); + clk_set_rate(clk, 480000000UL); + + clk_get_by_id(IMXRT1020_CLK_PLL3_BYPASS, &clk1); + clk_set_parent(clk1, clk); + + clk_get_by_id(IMXRT1020_CLK_PLL2_PFD3_297M, &clk); + clk_set_rate(clk, 297000000UL); + + clk_get_by_id(IMXRT1020_CLK_PLL2_SYS, &clk); + clk_enable(clk); + clk_set_rate(clk, 528000000UL); + + clk_get_by_id(IMXRT1020_CLK_PLL2_BYPASS, &clk1); + clk_set_parent(clk1, clk); + +#endif + + return 0; +} + +static const struct udevice_id imxrt1020_clk_ids[] = { + { .compatible = "fsl,imxrt1020-ccm" }, + { }, +}; + +U_BOOT_DRIVER(imxrt1020_clk) = { + .name = "clk_imxrt1020", + .id = UCLASS_CLK, + .of_match = imxrt1020_clk_ids, + .ops = &imxrt1020_clk_ops, + .probe = imxrt1020_clk_probe, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c index 44ca52c013..329f4580c5 100644 --- a/drivers/clk/imx/clk-imxrt1050.c +++ b/drivers/clk/imx/clk-imxrt1050.c @@ -71,11 +71,30 @@ static int imxrt1050_clk_enable(struct clk *clk) return __imxrt1050_clk_enable(clk, 1); } +static int imxrt1050_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct clk *c, *cp; + int ret; + + debug("%s(#%lu), parent: %lu\n", __func__, clk->id, parent->id); + + ret = clk_get_by_id(clk->id, &c); + if (ret) + return ret; + + ret = clk_get_by_id(parent->id, &cp); + if (ret) + return ret; + + return clk_set_parent(c, cp); +} + static struct clk_ops imxrt1050_clk_ops = { .set_rate = imxrt1050_clk_set_rate, .get_rate = imxrt1050_clk_get_rate, .enable = imxrt1050_clk_enable, .disable = imxrt1050_clk_disable, + .set_parent = imxrt1050_clk_set_parent, }; static const char * const pll_ref_sels[] = {"osc", "dummy", }; @@ -90,7 +109,7 @@ static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; static const char *const lpuart_sels[] = { "pll3_80m", "osc", }; static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", }; static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", }; -static const char *const lcdif_sels[] = { "pll2_sys", "pll3_pfd3_454_74m", "pll5_video:", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_664_62m"}; +static const char *const lcdif_sels[] = { "pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_664_62m"}; static int imxrt1050_clk_probe(struct udevice *dev) { @@ -238,9 +257,9 @@ static int imxrt1050_clk_probe(struct udevice *dev) clk_dm(IMXRT1050_CLK_LCDIF, imx_clk_gate2("lcdif", "lcdif_podf", base + 0x70, 28)); -#ifdef CONFIG_SPL_BUILD struct clk *clk, *clk1; +#ifdef CONFIG_SPL_BUILD /* bypass pll1 before setting its rate */ clk_get_by_id(IMXRT1050_CLK_PLL1_REF_SEL, &clk); clk_get_by_id(IMXRT1050_CLK_PLL1_BYPASS, &clk1); @@ -271,7 +290,14 @@ static int imxrt1050_clk_probe(struct udevice *dev) clk_get_by_id(IMXRT1050_CLK_PLL3_BYPASS, &clk1); clk_set_parent(clk1, clk); +#else + /* Set PLL5 for LCDIF to its default 650Mhz */ + clk_get_by_id(IMXRT1050_CLK_PLL5_VIDEO, &clk); + clk_enable(clk); + clk_set_rate(clk, 650000000UL); + clk_get_by_id(IMXRT1050_CLK_PLL5_BYPASS, &clk1); + clk_set_parent(clk1, clk); #endif return 0; diff --git a/drivers/clk/imx/clk-pllv3.c b/drivers/clk/imx/clk-pllv3.c index 525442debf..b4a9d587e1 100644 --- a/drivers/clk/imx/clk-pllv3.c +++ b/drivers/clk/imx/clk-pllv3.c @@ -25,6 +25,7 @@ #define PLL_DENOM_OFFSET 0x20 #define BM_PLL_POWER (0x1 << 12) +#define BM_PLL_ENABLE (0x1 << 13) #define BM_PLL_LOCK (0x1 << 31) struct clk_pllv3 { @@ -32,6 +33,7 @@ struct clk_pllv3 { void __iomem *base; u32 power_bit; bool powerup_set; + u32 enable_bit; u32 div_mask; u32 div_shift; }; @@ -83,6 +85,9 @@ static int clk_pllv3_generic_enable(struct clk *clk) val |= pll->power_bit; else val &= ~pll->power_bit; + + val |= pll->enable_bit; + writel(val, pll->base); return 0; @@ -98,6 +103,9 @@ static int clk_pllv3_generic_disable(struct clk *clk) val &= ~pll->power_bit; else val |= pll->power_bit; + + val &= ~pll->enable_bit; + writel(val, pll->base); return 0; @@ -238,6 +246,7 @@ struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name, return ERR_PTR(-ENOMEM); pll->power_bit = BM_PLL_POWER; + pll->enable_bit = BM_PLL_ENABLE; switch (type) { case IMX_PLLV3_GENERIC: diff --git a/drivers/phy/meson-gxl-usb2.c b/drivers/phy/meson-gxl-usb2.c index c98d12b627..b4f4c3c76b 100644 --- a/drivers/phy/meson-gxl-usb2.c +++ b/drivers/phy/meson-gxl-usb2.c @@ -17,6 +17,9 @@ #include <regmap.h> #include <power/regulator.h> #include <clk.h> +#include <linux/usb/otg.h> + +#include <asm/arch/usb-gx.h> #include <linux/bitops.h> #include <linux/compat.h> @@ -121,15 +124,30 @@ static void phy_meson_gxl_usb2_reset(struct phy_meson_gxl_usb2_priv *priv) udelay(RESET_COMPLETE_TIME); } -static void -phy_meson_gxl_usb2_set_host_mode(struct phy_meson_gxl_usb2_priv *priv) +void phy_meson_gxl_usb2_set_mode(struct phy *phy, enum usb_dr_mode mode) { + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb2_priv *priv = dev_get_priv(dev); uint val; regmap_read(priv->regmap, U2P_R0, &val); - val |= U2P_R0_DM_PULLDOWN; - val |= U2P_R0_DP_PULLDOWN; - val &= ~U2P_R0_ID_PULLUP; + + switch (mode) { + case USB_DR_MODE_UNKNOWN: + case USB_DR_MODE_HOST: + case USB_DR_MODE_OTG: + val |= U2P_R0_DM_PULLDOWN; + val |= U2P_R0_DP_PULLDOWN; + val &= ~U2P_R0_ID_PULLUP; + break; + + case USB_DR_MODE_PERIPHERAL: + val &= ~U2P_R0_DM_PULLDOWN; + val &= ~U2P_R0_DP_PULLDOWN; + val |= U2P_R0_ID_PULLUP; + break; + } + regmap_write(priv->regmap, U2P_R0, val); phy_meson_gxl_usb2_reset(priv); @@ -146,7 +164,7 @@ static int phy_meson_gxl_usb2_power_on(struct phy *phy) val &= ~U2P_R0_POWER_ON_RESET; regmap_write(priv->regmap, U2P_R0, val); - phy_meson_gxl_usb2_set_host_mode(priv); + phy_meson_gxl_usb2_set_mode(phy, USB_DR_MODE_HOST); #if CONFIG_IS_ENABLED(DM_REGULATOR) if (priv->phy_supply) { diff --git a/drivers/phy/meson-gxl-usb3.c b/drivers/phy/meson-gxl-usb3.c index c2a8593b39..9de55bb5df 100644 --- a/drivers/phy/meson-gxl-usb3.c +++ b/drivers/phy/meson-gxl-usb3.c @@ -16,6 +16,9 @@ #include <generic-phy.h> #include <regmap.h> #include <clk.h> +#include <linux/usb/otg.h> + +#include <asm/arch/usb-gx.h> #include <linux/bitops.h> #include <linux/compat.h> @@ -93,20 +96,35 @@ struct phy_meson_gxl_usb3_priv { #endif }; -static int -phy_meson_gxl_usb3_set_host_mode(struct phy_meson_gxl_usb3_priv *priv) +void phy_meson_gxl_usb3_set_mode(struct phy *phy, enum usb_dr_mode mode) { + struct udevice *dev = phy->dev; + struct phy_meson_gxl_usb3_priv *priv = dev_get_priv(dev); uint val; - regmap_read(priv->regmap, USB_R0, &val); - val &= ~USB_R0_U2D_ACT; - regmap_write(priv->regmap, USB_R0, val); - - regmap_read(priv->regmap, USB_R4, &val); - val &= ~USB_R4_P21_SLEEP_M0; - regmap_write(priv->regmap, USB_R4, val); - - return 0; + switch (mode) { + case USB_DR_MODE_UNKNOWN: + case USB_DR_MODE_HOST: + case USB_DR_MODE_OTG: + regmap_read(priv->regmap, USB_R0, &val); + val &= ~USB_R0_U2D_ACT; + regmap_write(priv->regmap, USB_R0, val); + + regmap_read(priv->regmap, USB_R4, &val); + val &= ~USB_R4_P21_SLEEP_M0; + regmap_write(priv->regmap, USB_R4, val); + break; + + case USB_DR_MODE_PERIPHERAL: + regmap_read(priv->regmap, USB_R0, &val); + val |= USB_R0_U2D_ACT; + regmap_write(priv->regmap, USB_R0, val); + + regmap_read(priv->regmap, USB_R4, &val); + val |= USB_R4_P21_SLEEP_M0; + regmap_write(priv->regmap, USB_R4, val); + break; + } } static int phy_meson_gxl_usb3_power_on(struct phy *phy) @@ -122,7 +140,9 @@ static int phy_meson_gxl_usb3_power_on(struct phy *phy) val |= FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff); regmap_write(priv->regmap, USB_R5, val); - return phy_meson_gxl_usb3_set_host_mode(priv); + phy_meson_gxl_usb3_set_mode(phy, USB_DR_MODE_HOST); + + return 0; } static int phy_meson_gxl_usb3_power_off(struct phy *phy) diff --git a/drivers/phy/phy-uclass.c b/drivers/phy/phy-uclass.c index e201a90c8c..e463b0b400 100644 --- a/drivers/phy/phy-uclass.c +++ b/drivers/phy/phy-uclass.c @@ -31,20 +31,20 @@ static int generic_phy_xlate_offs_flags(struct phy *phy, return 0; } -int generic_phy_get_by_index(struct udevice *dev, int index, - struct phy *phy) +int generic_phy_get_by_node(ofnode node, int index, struct phy *phy) { struct ofnode_phandle_args args; struct phy_ops *ops; struct udevice *phydev; int i, ret; - debug("%s(dev=%p, index=%d, phy=%p)\n", __func__, dev, index, phy); + debug("%s(node=%s, index=%d, phy=%p)\n", + __func__, ofnode_get_name(node), index, phy); assert(phy); phy->dev = NULL; - ret = dev_read_phandle_with_args(dev, "phys", "#phy-cells", 0, index, - &args); + ret = ofnode_parse_phandle_with_args(node, "phys", "#phy-cells", 0, + index, &args); if (ret) { debug("%s: dev_read_phandle_with_args failed: err=%d\n", __func__, ret); @@ -90,6 +90,12 @@ err: return ret; } +int generic_phy_get_by_index(struct udevice *dev, int index, + struct phy *phy) +{ + return generic_phy_get_by_node(dev_ofnode(dev), index, phy); +} + int generic_phy_get_by_name(struct udevice *dev, const char *phy_name, struct phy *phy) { diff --git a/drivers/power/pmic/pfuze100.c b/drivers/power/pmic/pfuze100.c index 6cf5f35f0f..db630f3ad0 100644 --- a/drivers/power/pmic/pfuze100.c +++ b/drivers/power/pmic/pfuze100.c @@ -41,7 +41,7 @@ static int pfuze100_write(struct udevice *dev, uint reg, const uint8_t *buff, static int pfuze100_read(struct udevice *dev, uint reg, uint8_t *buff, int len) { if (dm_i2c_read(dev, reg, buff, len)) { - pr_err("read error from device: %p register: %#x!\n", dev, reg); + debug("read error from device: %p register: %#x!\n", dev, reg); return -EIO; } diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 585af3d571..8a5a61c9fb 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -5,6 +5,7 @@ * Copyright (C) 2011-2013 Marek Vasut <marex@denx.de> */ #include <common.h> +#include <clk.h> #include <dm.h> #include <env.h> #include <dm/device_compat.h> @@ -52,14 +53,34 @@ __weak void mxsfb_system_setup(void) * le:89,ri:164,up:23,lo:10,hs:10,vs:10,sync:0,vmode:0 */ -static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp) +static void mxs_lcd_init(struct udevice *dev, u32 fb_addr, + struct display_timing *timings, int bpp) { struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE; + const enum display_flags flags = timings->flags; uint32_t word_len = 0, bus_width = 0; uint8_t valid_data = 0; + uint32_t vdctrl0; +#if CONFIG_IS_ENABLED(CLK) + struct clk per_clk; + int ret; + + ret = clk_get_by_name(dev, "per", &per_clk); + if (ret) { + dev_err(dev, "Failed to get mxs clk: %d\n", ret); + return; + } + + ret = clk_set_rate(&per_clk, timings->pixelclock.typ); + if (ret < 0) { + dev_err(dev, "Failed to set mxs clk: %d\n", ret); + return; + } +#else /* Kick in the LCDIF clock */ - mxs_set_lcdclk(MXS_LCDIF_BASE, PS2KHZ(mode->pixclock)); + mxs_set_lcdclk(MXS_LCDIF_BASE, timings->pixelclock.typ / 1000); +#endif /* Restart the LCDIF block */ mxs_reset_block(®s->hw_lcdif_ctrl_reg); @@ -96,25 +117,36 @@ static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp) mxsfb_system_setup(); - writel((mode->yres << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | mode->xres, - ®s->hw_lcdif_transfer_count); - - writel(LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL | - LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT | - LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | - mode->vsync_len, ®s->hw_lcdif_vdctrl0); - writel(mode->upper_margin + mode->lower_margin + - mode->vsync_len + mode->yres, + writel((timings->vactive.typ << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) | + timings->hactive.typ, ®s->hw_lcdif_transfer_count); + + vdctrl0 = LCDIF_VDCTRL0_ENABLE_PRESENT | LCDIF_VDCTRL0_ENABLE_POL | + LCDIF_VDCTRL0_VSYNC_PERIOD_UNIT | + LCDIF_VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | + timings->vsync_len.typ; + + if(flags & DISPLAY_FLAGS_HSYNC_HIGH) + vdctrl0 |= LCDIF_VDCTRL0_HSYNC_POL; + if(flags & DISPLAY_FLAGS_VSYNC_HIGH) + vdctrl0 |= LCDIF_VDCTRL0_VSYNC_POL; + if(flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) + vdctrl0 |= LCDIF_VDCTRL0_DOTCLK_POL; + if(flags & DISPLAY_FLAGS_DE_HIGH) + vdctrl0 |= LCDIF_VDCTRL0_ENABLE_POL; + + writel(vdctrl0, ®s->hw_lcdif_vdctrl0); + writel(timings->vback_porch.typ + timings->vfront_porch.typ + + timings->vsync_len.typ + timings->vactive.typ, ®s->hw_lcdif_vdctrl1); - writel((mode->hsync_len << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) | - (mode->left_margin + mode->right_margin + - mode->hsync_len + mode->xres), + writel((timings->hsync_len.typ << LCDIF_VDCTRL2_HSYNC_PULSE_WIDTH_OFFSET) | + (timings->hback_porch.typ + timings->hfront_porch.typ + + timings->hsync_len.typ + timings->hactive.typ), ®s->hw_lcdif_vdctrl2); - writel(((mode->left_margin + mode->hsync_len) << + writel(((timings->hback_porch.typ + timings->hsync_len.typ) << LCDIF_VDCTRL3_HORIZONTAL_WAIT_CNT_OFFSET) | - (mode->upper_margin + mode->vsync_len), + (timings->vback_porch.typ + timings->vsync_len.typ), ®s->hw_lcdif_vdctrl3); - writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | mode->xres, + writel((0 << LCDIF_VDCTRL4_DOTCLK_DLY_SEL_OFFSET) | timings->hactive.typ, ®s->hw_lcdif_vdctrl4); writel(fb_addr, ®s->hw_lcdif_cur_buf); @@ -135,10 +167,11 @@ static void mxs_lcd_init(u32 fb_addr, struct ctfb_res_modes *mode, int bpp) writel(LCDIF_CTRL_RUN, ®s->hw_lcdif_ctrl_set); } -static int mxs_probe_common(struct ctfb_res_modes *mode, int bpp, u32 fb) +static int mxs_probe_common(struct udevice *dev, struct display_timing *timings, + int bpp, u32 fb) { /* Start framebuffer */ - mxs_lcd_init(fb, mode, bpp); + mxs_lcd_init(dev, fb, timings, bpp); #ifdef CONFIG_VIDEO_MXS_MODE_SYSTEM /* @@ -204,6 +237,7 @@ void *video_hw_init(void) char *penv; void *fb = NULL; struct ctfb_res_modes mode; + struct display_timing timings; puts("Video: "); @@ -260,7 +294,9 @@ void *video_hw_init(void) printf("%s\n", panel.modeIdent); - ret = mxs_probe_common(&mode, bpp, (u32)fb); + video_ctfb_mode_to_display_timing(&mode, &timings); + + ret = mxs_probe_common(NULL, &timings, bpp, (u32)fb); if (ret) goto dealloc_fb; @@ -314,7 +350,6 @@ static int mxs_video_probe(struct udevice *dev) struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); - struct ctfb_res_modes mode; struct display_timing timings; u32 bpp = 0; u32 fb_start, fb_end; @@ -327,17 +362,7 @@ static int mxs_video_probe(struct udevice *dev) if (ret) return ret; - mode.xres = timings.hactive.typ; - mode.yres = timings.vactive.typ; - mode.left_margin = timings.hback_porch.typ; - mode.right_margin = timings.hfront_porch.typ; - mode.upper_margin = timings.vback_porch.typ; - mode.lower_margin = timings.vfront_porch.typ; - mode.hsync_len = timings.hsync_len.typ; - mode.vsync_len = timings.vsync_len.typ; - mode.pixclock = HZ2PS(timings.pixelclock.typ); - - ret = mxs_probe_common(&mode, bpp, plat->base); + ret = mxs_probe_common(dev, &timings, bpp, plat->base); if (ret) return ret; @@ -358,8 +383,8 @@ static int mxs_video_probe(struct udevice *dev) return -EINVAL; } - uc_priv->xsize = mode.xres; - uc_priv->ysize = mode.yres; + uc_priv->xsize = timings.hactive.typ; + uc_priv->ysize = timings.vactive.typ; /* Enable dcache for the frame buffer */ fb_start = plat->base & ~(MMU_SECTION_SIZE - 1); @@ -420,6 +445,7 @@ static const struct udevice_id mxs_video_ids[] = { { .compatible = "fsl,imx23-lcdif" }, { .compatible = "fsl,imx28-lcdif" }, { .compatible = "fsl,imx7ulp-lcdif" }, + { .compatible = "fsl,imxrt-lcdif" }, { /* sentinel */ } }; diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index 4e1720ef7e..40ee009f62 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -615,35 +615,6 @@ static void sunxi_lcdc_backlight_enable(void) gpio_direction_output(pin, PWM_ON); } -static void sunxi_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode, - struct display_timing *timing) -{ - timing->pixelclock.typ = mode->pixclock_khz * 1000; - - timing->hactive.typ = mode->xres; - timing->hfront_porch.typ = mode->right_margin; - timing->hback_porch.typ = mode->left_margin; - timing->hsync_len.typ = mode->hsync_len; - - timing->vactive.typ = mode->yres; - timing->vfront_porch.typ = mode->lower_margin; - timing->vback_porch.typ = mode->upper_margin; - timing->vsync_len.typ = mode->vsync_len; - - timing->flags = 0; - - if (mode->sync & FB_SYNC_HOR_HIGH_ACT) - timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH; - else - timing->flags |= DISPLAY_FLAGS_HSYNC_LOW; - if (mode->sync & FB_SYNC_VERT_HIGH_ACT) - timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH; - else - timing->flags |= DISPLAY_FLAGS_VSYNC_LOW; - if (mode->vmode == FB_VMODE_INTERLACED) - timing->flags |= DISPLAY_FLAGS_INTERLACED; -} - static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, bool for_ext_vga_dac) { @@ -673,7 +644,7 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double, sunxi_is_composite()); - sunxi_ctfb_mode_to_display_timing(mode, &timing); + video_ctfb_mode_to_display_timing(mode, &timing); lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac, sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE); } @@ -689,7 +660,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct display_timing timing; - sunxi_ctfb_mode_to_display_timing(mode, &timing); + video_ctfb_mode_to_display_timing(mode, &timing); lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync, sunxi_is_composite()); diff --git a/drivers/video/videomodes.c b/drivers/video/videomodes.c index ac25b45f81..89003eea72 100644 --- a/drivers/video/videomodes.c +++ b/drivers/video/videomodes.c @@ -444,3 +444,32 @@ int video_edid_dtd_to_ctfb_res_modes(struct edid_detailed_timing *t, return 0; } + +void video_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode, + struct display_timing *timing) +{ + timing->pixelclock.typ = mode->pixclock_khz * 1000; + + timing->hactive.typ = mode->xres; + timing->hfront_porch.typ = mode->right_margin; + timing->hback_porch.typ = mode->left_margin; + timing->hsync_len.typ = mode->hsync_len; + + timing->vactive.typ = mode->yres; + timing->vfront_porch.typ = mode->lower_margin; + timing->vback_porch.typ = mode->upper_margin; + timing->vsync_len.typ = mode->vsync_len; + + timing->flags = 0; + + if (mode->sync & FB_SYNC_HOR_HIGH_ACT) + timing->flags |= DISPLAY_FLAGS_HSYNC_HIGH; + else + timing->flags |= DISPLAY_FLAGS_HSYNC_LOW; + if (mode->sync & FB_SYNC_VERT_HIGH_ACT) + timing->flags |= DISPLAY_FLAGS_VSYNC_HIGH; + else + timing->flags |= DISPLAY_FLAGS_VSYNC_LOW; + if (mode->vmode == FB_VMODE_INTERLACED) + timing->flags |= DISPLAY_FLAGS_INTERLACED; +} diff --git a/drivers/video/videomodes.h b/drivers/video/videomodes.h index 29a3db4ae3..aefe4ef94a 100644 --- a/drivers/video/videomodes.h +++ b/drivers/video/videomodes.h @@ -92,3 +92,14 @@ int video_get_option_int(const char *options, const char *name, int def); int video_edid_dtd_to_ctfb_res_modes(struct edid_detailed_timing *t, struct ctfb_res_modes *mode); +/** + * video_ctfb_mode_to_display_timing() - Convert a ctfb(Cathode Tube Frame + * Buffer)_res_modes struct to a + * display_timing struct. + * + * @mode: Input ctfb_res_modes structure pointer to be converted + * from + * @timing: Output display_timing structure pointer to be converted to + */ +void video_ctfb_mode_to_display_timing(const struct ctfb_res_modes *mode, + struct display_timing *timing); |