aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/imx/clk-imxrt1050.c8
-rw-r--r--drivers/timer/Kconfig7
-rw-r--r--drivers/timer/Makefile1
-rw-r--r--drivers/timer/imx-gpt-timer.c162
-rw-r--r--drivers/usb/host/Kconfig2
-rw-r--r--drivers/usb/host/ehci-mx6.c13
-rw-r--r--drivers/video/mxsfb.c36
7 files changed, 213 insertions, 16 deletions
diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
index 594093e..3e17161 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 80743a2..ee81dfa 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 2ebdeab..e2bd530 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 0000000..72be297
--- /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(&regs->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(&regs->cr, GPT_CR_SWR);
+
+ /* Wait for timer to finish reset */
+ while (readl(&regs->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), &regs->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, &regs->cr);
+ } else {
+ if (prescaler > GPT_PR_PRESCALER_MAX)
+ return -EINVAL;
+
+ /* Set prescaler */
+ writel((prescaler << GPT_PR_PRESCALER_SHIFT), &regs->pr);
+ /* Set Peripheral as clock source and set gpt in free-running
+ * mode
+ */
+ writel(GPT_CLKSRC_IPG_CLK | GPT_CR_FRR, &regs->cr);
+ }
+
+ /* Start timer */
+ setbits_le32(&regs->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 bf5d82f..f34cba2 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 06be9de..238c931 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 e1fd36a..523d8a8 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);