diff options
author | Tom Rini | 2021-06-16 11:18:11 -0400 |
---|---|---|
committer | Tom Rini | 2021-06-16 11:18:11 -0400 |
commit | b2c4b7f66553401e0eb1176da8b97a1511f26b2c (patch) | |
tree | 688ffdcaf5c88b26b149492d0a351cea5ebf0a88 /drivers | |
parent | 9301a5cc99dd0c298e2f7fe2fa98a7287fcda772 (diff) | |
parent | 40496ac3b71b9589a9149d423b81133eebce07b1 (diff) |
Merge tag 'u-boot-imx-20210616' of https://gitlab.denx.de/u-boot/custodians/u-boot-imx
u-boot-imx-20210616
-------------------
- imxrt : fixes, USB, imxrt1020-evk
- imx8m:
fix for verdin-imx8mm
Add conga-QMX8 board
- imx6 :
documentation for pico-imx6:
Add SeeedStudio NPI-IMX6ULL Support
ventana: DM PCI
- imx7d:
added SMEGW01 board
CI : https://source.denx.de/u-boot/custodians/u-boot-imx/-/pipelines/7765
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/imx/clk-imxrt1050.c | 8 | ||||
-rw-r--r-- | drivers/timer/Kconfig | 7 | ||||
-rw-r--r-- | drivers/timer/Makefile | 1 | ||||
-rw-r--r-- | drivers/timer/imx-gpt-timer.c | 162 | ||||
-rw-r--r-- | drivers/usb/host/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-mx6.c | 13 | ||||
-rw-r--r-- | drivers/video/mxsfb.c | 36 |
7 files changed, 213 insertions, 16 deletions
diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c index 594093ee5fb..3e171610024 100644 --- a/drivers/clk/imx/clk-imxrt1050.c +++ b/drivers/clk/imx/clk-imxrt1050.c @@ -255,8 +255,12 @@ static int imxrt1050_clk_probe(struct udevice *dev) imx_clk_gate2("lpuart1", "lpuart_podf", base + 0x7c, 24)); clk_dm(IMXRT1050_CLK_SEMC, imx_clk_gate2("semc", "semc_podf", base + 0x74, 4)); - clk_dm(IMXRT1050_CLK_LCDIF, - imx_clk_gate2("lcdif", "lcdif_podf", base + 0x74, 10)); + clk_dm(IMXRT1050_CLK_LCDIF_APB, + imx_clk_gate2("lcdif", "lcdif_podf", base + 0x70, 28)); + clk_dm(IMXRT1050_CLK_LCDIF_PIX, + imx_clk_gate2("lcdif_pix", "lcdif", base + 0x74, 10)); + clk_dm(IMXRT1050_CLK_USBOH3, + imx_clk_gate2("usboh3", "pll3_usb_otg", base + 0x80, 0)); struct clk *clk, *clk1; diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 80743a25519..ee81dfa7768 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -227,4 +227,11 @@ config MCHP_PIT64B_TIMER Select this to enable support for Microchip 64-bit periodic interval timer. +config IMX_GPT_TIMER + bool "NXP i.MX GPT timer support" + depends on TIMER + help + Select this to enable support for the timer found on + NXP i.MX devices. + endmenu diff --git a/drivers/timer/Makefile b/drivers/timer/Makefile index 2ebdeab0ce1..e2bd530eb04 100644 --- a/drivers/timer/Makefile +++ b/drivers/timer/Makefile @@ -25,3 +25,4 @@ obj-$(CONFIG_STM32_TIMER) += stm32_timer.o obj-$(CONFIG_X86_TSC_TIMER) += tsc_timer.o obj-$(CONFIG_MTK_TIMER) += mtk_timer.o obj-$(CONFIG_MCHP_PIT64B_TIMER) += mchp-pit64b-timer.o +obj-$(CONFIG_IMX_GPT_TIMER) += imx-gpt-timer.o diff --git a/drivers/timer/imx-gpt-timer.c b/drivers/timer/imx-gpt-timer.c new file mode 100644 index 00000000000..72be2977547 --- /dev/null +++ b/drivers/timer/imx-gpt-timer.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 + * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com> + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <fdtdec.h> +#include <timer.h> +#include <dm/device_compat.h> + +#include <asm/io.h> + +#define GPT_CR_EN BIT(0) +#define GPT_CR_FRR BIT(9) +#define GPT_CR_EN_24M BIT(10) +#define GPT_CR_SWR BIT(15) + +#define GPT_PR_PRESCALER24M_MASK 0x0000F000 +#define GPT_PR_PRESCALER24M_SHIFT 12 +#define GPT_PR_PRESCALER24M_MAX (GPT_PR_PRESCALER24M_MASK >> GPT_PR_PRESCALER24M_SHIFT) +#define GPT_PR_PRESCALER_MASK 0x00000FFF +#define GPT_PR_PRESCALER_SHIFT 0 +#define GPT_PR_PRESCALER_MAX (GPT_PR_PRESCALER_MASK >> GPT_PR_PRESCALER_SHIFT) + +#define GPT_CLKSRC_IPG_CLK (1 << 6) +#define GPT_CLKSRC_IPG_CLK_24M (5 << 6) + +/* If CONFIG_SYS_HZ_CLOCK not specified et's default to 3Mhz */ +#ifndef CONFIG_SYS_HZ_CLOCK +#define CONFIG_SYS_HZ_CLOCK 3000000 +#endif + +struct imx_gpt_timer_regs { + u32 cr; + u32 pr; + u32 sr; + u32 ir; + u32 ocr1; + u32 ocr2; + u32 ocr3; + u32 icr1; + u32 icr2; + u32 cnt; +}; + +struct imx_gpt_timer_priv { + struct imx_gpt_timer_regs *base; +}; + +static u64 imx_gpt_timer_get_count(struct udevice *dev) +{ + struct imx_gpt_timer_priv *priv = dev_get_priv(dev); + struct imx_gpt_timer_regs *regs = priv->base; + + return timer_conv_64(readl(®s->cnt)); +} + +static int imx_gpt_setup(struct imx_gpt_timer_regs *regs, u32 rate) +{ + u32 prescaler = (rate / CONFIG_SYS_HZ_CLOCK) - 1; + + /* Reset the timer */ + setbits_le32(®s->cr, GPT_CR_SWR); + + /* Wait for timer to finish reset */ + while (readl(®s->cr) & GPT_CR_SWR) + ; + + if (rate == 24000000UL) { + /* Set timer frequency if using 24M clock source */ + if (prescaler > GPT_PR_PRESCALER24M_MAX) + return -EINVAL; + + /* Set 24M prescaler */ + writel((prescaler << GPT_PR_PRESCALER24M_SHIFT), ®s->pr); + /* Set Oscillator as clock source, enable 24M input and set gpt + * in free-running mode + */ + writel(GPT_CLKSRC_IPG_CLK_24M | GPT_CR_EN_24M | GPT_CR_FRR, ®s->cr); + } else { + if (prescaler > GPT_PR_PRESCALER_MAX) + return -EINVAL; + + /* Set prescaler */ + writel((prescaler << GPT_PR_PRESCALER_SHIFT), ®s->pr); + /* Set Peripheral as clock source and set gpt in free-running + * mode + */ + writel(GPT_CLKSRC_IPG_CLK | GPT_CR_FRR, ®s->cr); + } + + /* Start timer */ + setbits_le32(®s->cr, GPT_CR_EN); + + return 0; +} + +static int imx_gpt_timer_probe(struct udevice *dev) +{ + struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); + struct imx_gpt_timer_priv *priv = dev_get_priv(dev); + struct imx_gpt_timer_regs *regs; + struct clk clk; + fdt_addr_t addr; + u32 clk_rate; + int ret; + + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = (struct imx_gpt_timer_regs *)addr; + regs = priv->base; + + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret) { + dev_err(dev, "Failed to enable clock\n"); + return ret; + } + + /* Get timer clock rate */ + clk_rate = clk_get_rate(&clk); + if (clk_rate <= 0) { + dev_err(dev, "Could not get clock rate...\n"); + return -EINVAL; + } + + ret = imx_gpt_setup(regs, clk_rate); + if (ret) { + dev_err(dev, "Could not setup timer\n"); + return ret; + } + + uc_priv->clock_rate = CONFIG_SYS_HZ_CLOCK; + + return 0; +} + +static const struct timer_ops imx_gpt_timer_ops = { + .get_count = imx_gpt_timer_get_count, +}; + +static const struct udevice_id imx_gpt_timer_ids[] = { + { .compatible = "fsl,imxrt-gpt" }, + {} +}; + +U_BOOT_DRIVER(imx_gpt_timer) = { + .name = "imx_gpt_timer", + .id = UCLASS_TIMER, + .of_match = imx_gpt_timer_ids, + .priv_auto = sizeof(struct imx_gpt_timer_priv), + .probe = imx_gpt_timer_probe, + .ops = &imx_gpt_timer_ops, +}; diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index bf5d82f0350..f34cba2395c 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -149,7 +149,7 @@ config USB_EHCI_MX5 config USB_EHCI_MX6 bool "Support for i.MX6/i.MX7ULP on-chip EHCI USB controller" - depends on ARCH_MX6 || ARCH_MX7ULP + depends on ARCH_MX6 || ARCH_MX7ULP || ARCH_IMXRT default y ---help--- Enables support for the on-chip EHCI controller on i.MX6 SoCs. diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 06be9deaaae..238c93183b0 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -177,7 +177,7 @@ static void __maybe_unused usb_power_config_mx7ulp(void *usbphy) { } #endif -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT) static const unsigned phy_bases[] = { USB_PHY0_BASE_ADDR, #if defined(USB_PHY1_BASE_ADDR) @@ -340,7 +340,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { enum usb_init_type type; -#if defined(CONFIG_MX6) +#if defined(CONFIG_MX6) || defined(CONFIG_IMXRT) u32 controller_spacing = 0x200; struct anatop_regs __iomem *anatop = (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; @@ -382,7 +382,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, return ret; } -#if defined(CONFIG_MX6) +#if defined(CONFIG_MX6) || defined(CONFIG_IMXRT) usb_power_config_mx6(anatop, index); #elif defined (CONFIG_MX7) usb_power_config_mx7(usbnc); @@ -392,7 +392,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, usb_oc_config(usbnc, index); -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT) if (index < ARRAY_SIZE(phy_bases)) { usb_internal_phy_clock_gate((void __iomem *)phy_bases[index], 1); usb_phy_enable(ehci, (void __iomem *)phy_bases[index]); @@ -504,7 +504,7 @@ static int ehci_usb_phy_mode(struct udevice *dev) * About fsl,usbphy, Refer to * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt. */ - if (is_mx6() || is_mx7ulp()) { + if (is_mx6() || is_mx7ulp() || is_imxrt()) { phy_off = fdtdec_lookup_phandle(blob, offset, "fsl,usbphy"); @@ -671,7 +671,7 @@ static int ehci_usb_probe(struct udevice *dev) usb_oc_config(priv->misc_addr, priv->portnr); -#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT) usb_internal_phy_clock_gate(priv->phy_addr, 1); usb_phy_enable(ehci, priv->phy_addr); #endif @@ -757,6 +757,7 @@ int ehci_usb_remove(struct udevice *dev) static const struct udevice_id mx6_usb_ids[] = { { .compatible = "fsl,imx27-usb" }, { .compatible = "fsl,imx7d-usb" }, + { .compatible = "fsl,imxrt-usb" }, { } }; diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index e1fd36a62d6..523d8a8d983 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -67,26 +67,48 @@ static void mxs_lcd_init(struct udevice *dev, u32 fb_addr, uint32_t vdctrl0; #if CONFIG_IS_ENABLED(CLK) - struct clk per_clk; + struct clk clk; int ret; - ret = clk_get_by_name(dev, "per", &per_clk); + ret = clk_get_by_name(dev, "pix", &clk); if (ret) { - dev_err(dev, "Failed to get mxs clk: %d\n", ret); + dev_err(dev, "Failed to get mxs pix clk: %d\n", ret); return; } - ret = clk_set_rate(&per_clk, timings->pixelclock.typ); + ret = clk_set_rate(&clk, timings->pixelclock.typ); if (ret < 0) { - dev_err(dev, "Failed to set mxs clk: %d\n", ret); + dev_err(dev, "Failed to set mxs pix clk: %d\n", ret); return; } - ret = clk_enable(&per_clk); + ret = clk_enable(&clk); if (ret < 0) { - dev_err(dev, "Failed to enable mxs clk: %d\n", ret); + dev_err(dev, "Failed to enable mxs pix clk: %d\n", ret); return; } + + ret = clk_get_by_name(dev, "axi", &clk); + if (!ret) { + debug("%s: Failed to get mxs axi clk: %d\n", __func__, ret); + } else { + ret = clk_enable(&clk); + if (ret < 0) { + dev_err(dev, "Failed to enable mxs axi clk: %d\n", ret); + return; + } + } + + ret = clk_get_by_name(dev, "disp_axi", &clk); + if (!ret) { + debug("%s: Failed to get mxs disp_axi clk: %d\n", __func__, ret); + } else { + ret = clk_enable(&clk); + if (ret < 0) { + dev_err(dev, "Failed to enable mxs disp_axi clk: %d\n", ret); + return; + } + } #else /* Kick in the LCDIF clock */ mxs_set_lcdclk(MXS_LCDIF_BASE, timings->pixelclock.typ / 1000); |