aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/uart/uart_dev_imx.c
diff options
context:
space:
mode:
authorOleksandr Tymoshenko <gonzo@FreeBSD.org>2020-07-01 00:33:16 +0000
committerOleksandr Tymoshenko <gonzo@FreeBSD.org>2020-07-01 00:33:16 +0000
commit94bc2117b4adaf7101cc412f4277e5812ad61ae2 (patch)
tree7abc9e04dbaae994cff6a1be36445f1a320bac92 /sys/dev/uart/uart_dev_imx.c
parent39ca7ca5689a978460d2a6634a27a31f7ab40280 (diff)
Add i.MX 8M Quad support
- Add CCM driver and clocks implementations for i.MX 8M - Add GPC driver for iMX8 - Add clock tree for i.MX 8M Quad - Add clocks support and new compat strings (where required) for existing i.MX 6 UART, I2C, and GPIO drivers - Enable aarch64-compatible drivers form i.MX 6 in arm64 GENERIC kernel config - Add dtb/imx8 kernel module with DTBs for Nitrogen8M and iMX8MQ EVK With this patch both Nitrogen8M and iMX8MQ EVK boot with NFS root up to multiuser login prompt Reviewed by: manu Differential Revision: https://reviews.freebsd.org/D25274
Notes
svn path=/head/; revision=362817
Diffstat (limited to 'sys/dev/uart/uart_dev_imx.c')
-rw-r--r--sys/dev/uart/uart_dev_imx.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c
index 35d6788f0c23..14dba82dd9ee 100644
--- a/sys/dev/uart/uart_dev_imx.c
+++ b/sys/dev/uart/uart_dev_imx.c
@@ -40,13 +40,21 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <sys/kdb.h>
#include <machine/bus.h>
-#include <machine/fdt.h>
#include <dev/uart/uart.h>
#include <dev/uart/uart_cpu.h>
#include <dev/uart/uart_cpu_fdt.h>
#include <dev/uart/uart_bus.h>
#include <dev/uart/uart_dev_imx.h>
+
+#if defined(EXT_RESOURCES) && defined(__aarch64__)
+#define IMX_ENABLE_CLOCKS
+#endif
+
+#ifdef IMX_ENABLE_CLOCKS
+#include <dev/extres/clk/clk.h>
+#endif
+
#include "uart_if.h"
#include <arm/freescale/imx/imx_ccmvar.h>
@@ -125,7 +133,7 @@ imx_uart_getbaud(struct uart_bas *bas)
*/
i = (GETREG(bas, REG(UFCR)) & IMXUART_UFCR_RFDIV_MASK) >>
IMXUART_UFCR_RFDIV_SHIFT;
- rate = imx_ccm_uart_hz() / predivs[i];
+ rate = bas->rclk / predivs[i];
ubir = GETREG(bas, REG(UBIR)) + 1;
ubmr = GETREG(bas, REG(UBMR)) + 1;
baud = ((rate / 16 ) * ubir) / ubmr;
@@ -193,8 +201,8 @@ imx_uart_init(struct uart_bas *bas, int baudrate, int databits,
* Note that a quirk of the hardware requires that both UBIR and UBMR be
* set back to back in order for the change to take effect.
*/
- if (baudrate > 0) {
- baseclk = imx_ccm_uart_hz();
+ if ((baudrate > 0) && (bas->rclk != 0)) {
+ baseclk = bas->rclk;
reg = GETREG(bas, REG(UFCR));
reg = (reg & ~IMXUART_UFCR_RFDIV_MASK) | IMXUART_UFCR_RFDIV_DIV1;
SETREG(bas, REG(UFCR), reg);
@@ -323,6 +331,42 @@ UART_FDT_CLASS_AND_DEVICE(compat_data);
i = (i & s) ? (i & ~s) | d : i; \
}
+#ifdef IMX_ENABLE_CLOCKS
+static int
+imx_uart_setup_clocks(struct uart_softc *sc)
+{
+ struct uart_bas *bas;
+ clk_t ipgclk, perclk;
+ uint64_t freq;
+ int error;
+
+ bas = &sc->sc_bas;
+
+ if (clk_get_by_ofw_name(sc->sc_dev, 0, "ipg", &ipgclk) != 0)
+ return (ENOENT);
+
+ if (clk_get_by_ofw_name(sc->sc_dev, 0, "per", &perclk) != 0) {
+ return (ENOENT);
+ }
+
+ error = clk_enable(ipgclk);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "cannot enable ipg clock\n");
+ return (error);
+ }
+
+ error = clk_get_freq(perclk, &freq);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "cannot get frequency\n");
+ return (error);
+ }
+
+ bas->rclk = (uint32_t)freq;
+
+ return (0);
+}
+#endif
+
static int
imx_uart_bus_attach(struct uart_softc *sc)
{
@@ -330,6 +374,15 @@ imx_uart_bus_attach(struct uart_softc *sc)
struct uart_devinfo *di;
bas = &sc->sc_bas;
+
+#ifdef IMX_ENABLE_CLOCKS
+ int error = imx_uart_setup_clocks(sc);
+ if (error)
+ return (error);
+#else
+ bas->rclk = imx_ccm_uart_hz();
+#endif
+
if (sc->sc_sysdev != NULL) {
di = sc->sc_sysdev;
imx_uart_init(bas, di->baudrate, di->databits, di->stopbits,