Module Name: src
Committed By: jmcneill
Date: Wed Jan 15 01:09:57 UTC 2020
Modified Files:
src/sys/arch/arm/imx: if_enet.c if_enet_imx6.c if_enet_imx7.c
if_enetvar.h imx6_board.c imx6_pcie.c imx6_usdhc.c imx7_usdhc.c
imxgpio.c imxgpiovar.h imxuart.c
src/sys/arch/arm/imx/fdt: files.imx6 if_enet_imx.c imx6_com.c
imx6_gpio.c imx6_iomux.c imx6_sdhc.c
src/sys/arch/evbarm/conf: GENERIC64 files.generic64
src/sys/dev/fdt: dwc3_fdt.c
Added Files:
src/sys/arch/arm/imx/fdt: imx7_gpc.c imx8mq_ccm.c imx8mq_ccm.h
imx8mq_usbphy.c imx_ccm.c imx_ccm.h imx_ccm_composite.c
imx_ccm_extclk.c imx_ccm_fixed.c imx_ccm_fixed_factor.c
imx_ccm_gate.c
Log Message:
Add support for NXP i.MX 8M Dual/8M QuadLite/8M Quad family SoCs.
To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/sys/arch/arm/imx/if_enet.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/imx/if_enet_imx6.c \
src/sys/arch/arm/imx/imx6_usdhc.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/imx/if_enet_imx7.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/imx/if_enetvar.h
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/arm/imx/imx6_board.c \
src/sys/arch/arm/imx/imx6_pcie.c
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/arm/imx/imx7_usdhc.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/imx/imxgpio.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/imx/imxgpiovar.h
cvs rdiff -u -r1.23 -r1.24 src/sys/arch/arm/imx/imxuart.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/arm/imx/fdt/files.imx6
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/arm/imx/fdt/if_enet_imx.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/imx/fdt/imx6_com.c \
src/sys/arch/arm/imx/fdt/imx6_iomux.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/arm/imx/fdt/imx6_gpio.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/imx/fdt/imx6_sdhc.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/arm/imx/fdt/imx7_gpc.c \
src/sys/arch/arm/imx/fdt/imx8mq_ccm.c \
src/sys/arch/arm/imx/fdt/imx8mq_ccm.h \
src/sys/arch/arm/imx/fdt/imx8mq_usbphy.c \
src/sys/arch/arm/imx/fdt/imx_ccm.c src/sys/arch/arm/imx/fdt/imx_ccm.h \
src/sys/arch/arm/imx/fdt/imx_ccm_composite.c \
src/sys/arch/arm/imx/fdt/imx_ccm_extclk.c \
src/sys/arch/arm/imx/fdt/imx_ccm_fixed.c \
src/sys/arch/arm/imx/fdt/imx_ccm_fixed_factor.c \
src/sys/arch/arm/imx/fdt/imx_ccm_gate.c
cvs rdiff -u -r1.131 -r1.132 src/sys/arch/evbarm/conf/GENERIC64
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/evbarm/conf/files.generic64
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/fdt/dwc3_fdt.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/arm/imx/if_enet.c
diff -u src/sys/arch/arm/imx/if_enet.c:1.29 src/sys/arch/arm/imx/if_enet.c:1.30
--- src/sys/arch/arm/imx/if_enet.c:1.29 Fri Nov 29 17:20:30 2019
+++ src/sys/arch/arm/imx/if_enet.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_enet.c,v 1.29 2019/11/29 17:20:30 ryo Exp $ */
+/* $NetBSD: if_enet.c,v 1.30 2020/01/15 01:09:56 jmcneill Exp $ */
/*
* Copyright (c) 2014 Ryo Shimizu <[email protected]>
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_enet.c,v 1.29 2019/11/29 17:20:30 ryo Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_enet.c,v 1.30 2020/01/15 01:09:56 jmcneill Exp $");
#include "vlan.h"
@@ -247,7 +247,7 @@ enet_attach_common(device_t self)
ifmedia_init(&mii->mii_media, 0, ether_mediachange, enet_mediastatus);
/* try to attach PHY */
- mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 0);
+ mii_attach(self, mii, 0xffffffff, sc->sc_phyid, MII_OFFSET_ANY, 0);
if (LIST_FIRST(&mii->mii_phys) == NULL) {
ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL);
ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL);
Index: src/sys/arch/arm/imx/if_enet_imx6.c
diff -u src/sys/arch/arm/imx/if_enet_imx6.c:1.8 src/sys/arch/arm/imx/if_enet_imx6.c:1.9
--- src/sys/arch/arm/imx/if_enet_imx6.c:1.8 Mon Nov 25 00:54:47 2019
+++ src/sys/arch/arm/imx/if_enet_imx6.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_enet_imx6.c,v 1.8 2019/11/25 00:54:47 hkenken Exp $ */
+/* $NetBSD: if_enet_imx6.c,v 1.9 2020/01/15 01:09:56 jmcneill Exp $ */
/*
* Copyright (c) 2014 Ryo Shimizu <[email protected]>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_enet_imx6.c,v 1.8 2019/11/25 00:54:47 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_enet_imx6.c,v 1.9 2020/01/15 01:09:56 jmcneill Exp $");
#include "locators.h"
#include "imxccm.h"
@@ -88,6 +88,7 @@ enet_attach(device_t parent, device_t se
sc->sc_dmat = aa->aa_dmat;
sc->sc_imxtype = 6; /* i.MX6 */
+ sc->sc_phyid = MII_PHY_ANY;
if (IMX6_CHIPID_MAJOR(imx6_chip_id()) == CHIPID_MAJOR_IMX6UL)
sc->sc_rgmii = 0;
else
Index: src/sys/arch/arm/imx/imx6_usdhc.c
diff -u src/sys/arch/arm/imx/imx6_usdhc.c:1.8 src/sys/arch/arm/imx/imx6_usdhc.c:1.9
--- src/sys/arch/arm/imx/imx6_usdhc.c:1.8 Wed Jul 24 12:33:18 2019
+++ src/sys/arch/arm/imx/imx6_usdhc.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx6_usdhc.c,v 1.8 2019/07/24 12:33:18 hkenken Exp $ */
+/* $NetBSD: imx6_usdhc.c,v 1.9 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2012 Genetec Corporation. All rights reserved.
* Written by Hiroyuki Bessho for Genetec Corporation.
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx6_usdhc.c,v 1.8 2019/07/24 12:33:18 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx6_usdhc.c,v 1.9 2020/01/15 01:09:56 jmcneill Exp $");
#include "imxgpio.h"
@@ -184,7 +184,7 @@ imx6_sdhc_card_detect(struct sdhc_softc
sc = device_private(ssc->sc_dev);
if (sc->sc_gpio_cd >= 0) {
- detect = gpio_data_read(sc->sc_gpio_cd);
+ detect = imxgpio_data_read(sc->sc_gpio_cd);
if (sc->sc_gpio_cd_active == GPIO_PIN_LOW)
detect = !detect;
} else
Index: src/sys/arch/arm/imx/if_enet_imx7.c
diff -u src/sys/arch/arm/imx/if_enet_imx7.c:1.5 src/sys/arch/arm/imx/if_enet_imx7.c:1.6
--- src/sys/arch/arm/imx/if_enet_imx7.c:1.5 Tue Nov 12 05:09:29 2019
+++ src/sys/arch/arm/imx/if_enet_imx7.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_enet_imx7.c,v 1.5 2019/11/12 05:09:29 hkenken Exp $ */
+/* $NetBSD: if_enet_imx7.c,v 1.6 2020/01/15 01:09:56 jmcneill Exp $ */
/*
* Copyright (c) 2014 Ryo Shimizu <[email protected]>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_enet_imx7.c,v 1.5 2019/11/12 05:09:29 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_enet_imx7.c,v 1.6 2020/01/15 01:09:56 jmcneill Exp $");
#include "locators.h"
#include "imxccm.h"
@@ -84,6 +84,7 @@ enet_attach(device_t parent, device_t se
sc->sc_imxtype = 7; /* i.MX7 */
sc->sc_rgmii = 1;
+ sc->sc_phyid = MII_PHY_ANY;
switch (aa->aa_addr) {
case (IMX7_AIPS_BASE + AIPS3_ENET1_BASE):
Index: src/sys/arch/arm/imx/if_enetvar.h
diff -u src/sys/arch/arm/imx/if_enetvar.h:1.6 src/sys/arch/arm/imx/if_enetvar.h:1.7
--- src/sys/arch/arm/imx/if_enetvar.h:1.6 Tue Nov 12 05:09:29 2019
+++ src/sys/arch/arm/imx/if_enetvar.h Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_enetvar.h,v 1.6 2019/11/12 05:09:29 hkenken Exp $ */
+/* $NetBSD: if_enetvar.h,v 1.7 2020/01/15 01:09:56 jmcneill Exp $ */
/*
* Copyright (c) 2014 Ryo Shimizu <[email protected]>
@@ -58,6 +58,7 @@ struct enet_softc {
int sc_unit;
int sc_imxtype;
int sc_rgmii;
+ int sc_phyid;
unsigned int sc_clock;
struct clk *sc_clk_ipg;
Index: src/sys/arch/arm/imx/imx6_board.c
diff -u src/sys/arch/arm/imx/imx6_board.c:1.14 src/sys/arch/arm/imx/imx6_board.c:1.15
--- src/sys/arch/arm/imx/imx6_board.c:1.14 Sat Jul 27 08:02:04 2019
+++ src/sys/arch/arm/imx/imx6_board.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx6_board.c,v 1.14 2019/07/27 08:02:04 skrll Exp $ */
+/* $NetBSD: imx6_board.c,v 1.15 2020/01/15 01:09:56 jmcneill Exp $ */
/*
* Copyright (c) 2012 Genetec Corporation. All rights reserved.
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: imx6_board.c,v 1.14 2019/07/27 08:02:04 skrll Exp $");
+__KERNEL_RCSID(1, "$NetBSD: imx6_board.c,v 1.15 2020/01/15 01:09:56 jmcneill Exp $");
#include "arml2cc.h"
#include "imxgpio.h"
@@ -281,6 +281,6 @@ imx6_set_gpio(device_t self, const char
*gpio = GPIO_NO(grp, pin);
#if NIMXGPIO > 0
- gpio_set_direction(*gpio, dir);
+ imxgpio_set_direction(*gpio, dir);
#endif
}
Index: src/sys/arch/arm/imx/imx6_pcie.c
diff -u src/sys/arch/arm/imx/imx6_pcie.c:1.14 src/sys/arch/arm/imx/imx6_pcie.c:1.15
--- src/sys/arch/arm/imx/imx6_pcie.c:1.14 Wed Oct 16 11:16:30 2019
+++ src/sys/arch/arm/imx/imx6_pcie.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx6_pcie.c,v 1.14 2019/10/16 11:16:30 hkenken Exp $ */
+/* $NetBSD: imx6_pcie.c,v 1.15 2020/01/15 01:09:56 jmcneill Exp $ */
/*
* Copyright (c) 2016 Genetec Corporation. All rights reserved.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx6_pcie.c,v 1.14 2019/10/16 11:16:30 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx6_pcie.c,v 1.15 2020/01/15 01:09:56 jmcneill Exp $");
#include "opt_pci.h"
@@ -231,9 +231,9 @@ imx6_pcie_reset(void *cookie)
#if NIMXGPIO > 0
if (ipsc->sc_gpio_reset >= 0) {
- gpio_data_write(ipsc->sc_gpio_reset, ipsc->sc_gpio_reset_active);
+ imxgpio_data_write(ipsc->sc_gpio_reset, ipsc->sc_gpio_reset_active);
delay(100 * 1000);
- gpio_data_write(ipsc->sc_gpio_reset, !ipsc->sc_gpio_reset_active);
+ imxgpio_data_write(ipsc->sc_gpio_reset, !ipsc->sc_gpio_reset_active);
}
#endif
}
Index: src/sys/arch/arm/imx/imx7_usdhc.c
diff -u src/sys/arch/arm/imx/imx7_usdhc.c:1.3 src/sys/arch/arm/imx/imx7_usdhc.c:1.4
--- src/sys/arch/arm/imx/imx7_usdhc.c:1.3 Wed Jul 24 12:33:18 2019
+++ src/sys/arch/arm/imx/imx7_usdhc.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx7_usdhc.c,v 1.3 2019/07/24 12:33:18 hkenken Exp $ */
+/* $NetBSD: imx7_usdhc.c,v 1.4 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2012 Genetec Corporation. All rights reserved.
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx7_usdhc.c,v 1.3 2019/07/24 12:33:18 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx7_usdhc.c,v 1.4 2020/01/15 01:09:56 jmcneill Exp $");
#include "imxgpio.h"
@@ -93,7 +93,7 @@ imx7_sdhc_card_detect(struct sdhc_softc
sc = device_private(ssc->sc_dev);
#if NIMXGPIO > 0
if (sc->sc_gpio_cd >= 0) {
- detect = gpio_data_read(sc->sc_gpio_cd);
+ detect = imxgpio_data_read(sc->sc_gpio_cd);
} else
#endif
detect = 1;
@@ -143,7 +143,7 @@ sdhc_set_gpio_cd(struct sdhc_axi_softc *
sc->sc_gpio_cd = GPIO_NO(grp, pin);
#if NIMXGPIO > 0
- gpio_set_direction(sc->sc_gpio_cd, GPIO_PIN_INPUT);
+ imxgpio_set_direction(sc->sc_gpio_cd, GPIO_PIN_INPUT);
#endif
}
Index: src/sys/arch/arm/imx/imxgpio.c
diff -u src/sys/arch/arm/imx/imxgpio.c:1.7 src/sys/arch/arm/imx/imxgpio.c:1.8
--- src/sys/arch/arm/imx/imxgpio.c:1.7 Wed Nov 27 07:26:08 2019
+++ src/sys/arch/arm/imx/imxgpio.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imxgpio.c,v 1.7 2019/11/27 07:26:08 hkenken Exp $ */
+/* $NetBSD: imxgpio.c,v 1.8 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imxgpio.c,v 1.7 2019/11/27 07:26:08 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imxgpio.c,v 1.8 2020/01/15 01:09:56 jmcneill Exp $");
#define _INTR_PRIVATE
@@ -327,25 +327,26 @@ imxgpio_attach_common(device_t self)
{
struct imxgpio_softc * const gpio = device_private(self);
- KASSERT(gpio->gpio_unit < MAX_NGROUP);
-
gpio->gpio_dev = self;
- if (gpio->gpio_irqbase > 0) {
- aprint_normal_dev(gpio->gpio_dev, "interrupts %d..%d\n",
- gpio->gpio_irqbase, gpio->gpio_irqbase + GPIO_NPINS - 1);
-
+ if (gpio->gpio_irqbase == PIC_IRQBASE_ALLOC || gpio->gpio_irqbase > 0) {
gpio->gpio_pic.pic_ops = &imxgpio_pic_ops;
strlcpy(gpio->gpio_pic.pic_name, device_xname(self),
sizeof(gpio->gpio_pic.pic_name));
- gpio->gpio_pic.pic_maxsources = 32;
+ gpio->gpio_pic.pic_maxsources = GPIO_NPINS;
- pic_add(&gpio->gpio_pic, gpio->gpio_irqbase);
+ gpio->gpio_irqbase = pic_add(&gpio->gpio_pic, gpio->gpio_irqbase);
+
+ aprint_normal_dev(gpio->gpio_dev, "interrupts %d..%d\n",
+ gpio->gpio_irqbase, gpio->gpio_irqbase + GPIO_NPINS - 1);
}
mutex_init(&gpio->gpio_lock, MUTEX_DEFAULT, IPL_VM);
- imxgpio_handles[gpio->gpio_unit] = gpio;
+ if (gpio->gpio_unit != -1) {
+ KASSERT(gpio->gpio_unit < MAX_NGROUP);
+ imxgpio_handles[gpio->gpio_unit] = gpio;
+ }
#if NGPIO > 0
imxgpio_attach_ports(gpio);
@@ -354,7 +355,7 @@ imxgpio_attach_common(device_t self)
/* in-kernel GPIO access utility functions */
void
-gpio_set_direction(u_int gpio, int dir)
+imxgpio_set_direction(u_int gpio, int dir)
{
int index = gpio / GPIO_NPINS;
int pin = gpio % GPIO_NPINS;
@@ -366,7 +367,7 @@ gpio_set_direction(u_int gpio, int dir)
}
void
-gpio_data_write(u_int gpio, u_int value)
+imxgpio_data_write(u_int gpio, u_int value)
{
int index = gpio / GPIO_NPINS;
int pin = gpio % GPIO_NPINS;
@@ -378,7 +379,7 @@ gpio_data_write(u_int gpio, u_int value)
}
bool
-gpio_data_read(u_int gpio)
+imxgpio_data_read(u_int gpio)
{
int index = gpio / GPIO_NPINS;
int pin = gpio % GPIO_NPINS;
Index: src/sys/arch/arm/imx/imxgpiovar.h
diff -u src/sys/arch/arm/imx/imxgpiovar.h:1.2 src/sys/arch/arm/imx/imxgpiovar.h:1.3
--- src/sys/arch/arm/imx/imxgpiovar.h:1.2 Wed Jul 24 12:33:18 2019
+++ src/sys/arch/arm/imx/imxgpiovar.h Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imxgpiovar.h,v 1.2 2019/07/24 12:33:18 hkenken Exp $ */
+/* $NetBSD: imxgpiovar.h,v 1.3 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -45,8 +45,8 @@ struct imxgpio_softc {
void *gpio_is;
void *gpio_is_high;
- uint gpio_unit;
- uint gpio_irqbase;
+ int gpio_unit;
+ int gpio_irqbase;
uint32_t gpio_enable_mask;
uint32_t gpio_edge_mask;
uint32_t gpio_level_mask;
@@ -75,9 +75,9 @@ void imxgpio_pin_write(void *, int, int)
void imxgpio_pin_ctl(void *, int, int);
/* in-kernel GPIO access utility functions */
-void gpio_set_direction(u_int, int);
-void gpio_data_write(u_int, u_int);
-bool gpio_data_read(u_int);
+void imxgpio_set_direction(u_int, int);
+void imxgpio_data_write(u_int, u_int);
+bool imxgpio_data_read(u_int);
#define GPIO_NO(group, pin) (((group) - 1) * GPIO_NPINS + (pin))
#define GPIO_MODULE(pin) ((pin) / GPIO_NPINS)
Index: src/sys/arch/arm/imx/imxuart.c
diff -u src/sys/arch/arm/imx/imxuart.c:1.23 src/sys/arch/arm/imx/imxuart.c:1.24
--- src/sys/arch/arm/imx/imxuart.c:1.23 Sun Jan 12 00:35:11 2020
+++ src/sys/arch/arm/imx/imxuart.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imxuart.c,v 1.23 2020/01/12 00:35:11 jmcneill Exp $ */
+/* $NetBSD: imxuart.c,v 1.24 2020/01/15 01:09:56 jmcneill Exp $ */
/*
* Copyright (c) 2009, 2010 Genetec Corporation. All rights reserved.
@@ -96,7 +96,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imxuart.c,v 1.23 2020/01/12 00:35:11 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imxuart.c,v 1.24 2020/01/15 01:09:56 jmcneill Exp $");
#include "opt_imxuart.h"
#include "opt_ddb.h"
@@ -1459,9 +1459,11 @@ imxustart(struct tty *tp)
space = imxuart_txfifo_space(sc);
n = MIN(sc->sc_tbc, space);
- bus_space_write_multi_1(iot, ioh, IMX_UTXD, sc->sc_tba, n);
- sc->sc_tbc -= n;
- sc->sc_tba += n;
+ if (n > 0) {
+ bus_space_write_multi_1(iot, ioh, IMX_UTXD, sc->sc_tba, n);
+ sc->sc_tbc -= n;
+ sc->sc_tba += n;
+ }
/* Enable transmit completion interrupts */
imxuart_control_txint(sc, true);
Index: src/sys/arch/arm/imx/fdt/files.imx6
diff -u src/sys/arch/arm/imx/fdt/files.imx6:1.7 src/sys/arch/arm/imx/fdt/files.imx6:1.8
--- src/sys/arch/arm/imx/fdt/files.imx6:1.7 Sat Oct 12 06:46:13 2019
+++ src/sys/arch/arm/imx/fdt/files.imx6 Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-# $NetBSD: files.imx6,v 1.7 2019/10/12 06:46:13 skrll Exp $
+# $NetBSD: files.imx6,v 1.8 2020/01/15 01:09:56 jmcneill Exp $
#
# Configuration info for the Freescale i.MX6
#
@@ -15,11 +15,30 @@ attach imxccm at fdt
file arch/arm/imx/imx6_ccm.c imxccm
file arch/arm/imx/fdt/imx6_clk.c imxccm
+
+# Common FDT clock framework
+define imx_ccm
+file arch/arm/imx/fdt/imx_ccm.c imx_ccm
+file arch/arm/imx/fdt/imx_ccm_extclk.c imx_ccm
+file arch/arm/imx/fdt/imx_ccm_gate.c imx_ccm
+file arch/arm/imx/fdt/imx_ccm_composite.c imx_ccm
+file arch/arm/imx/fdt/imx_ccm_fixed.c imx_ccm
+file arch/arm/imx/fdt/imx_ccm_fixed_factor.c imx_ccm
+
+# CCM (iMX8MQ)
+device imx8mqccm: imx_ccm
+attach imx8mqccm at fdt with imx8mq_ccm
+file arch/arm/imx/fdt/imx8mq_ccm.c imx8mq_ccm
+
# GPC
device imxgpc
attach imxgpc at fdt
file arch/arm/imx/fdt/imx6_gpc.c imxgpc
+device imx7gpc
+attach imx7gpc at fdt
+file arch/arm/imx/fdt/imx7_gpc.c imx7gpc
+
# IOMUX
device imxiomux
attach imxiomux at fdt
@@ -61,6 +80,11 @@ device imxusbphy
attach imxusbphy at fdt
file arch/arm/imx/fdt/imx6_usbphy.c imxusbphy
+device imx8mqusbphy
+attach imx8mqusbphy at fdt
+file arch/arm/imx/fdt/imx8mq_usbphy.c imx8mqusbphy
+
+
# SDMMC
attach sdhc at fdt with imx6_sdhc
file arch/arm/imx/fdt/imx6_sdhc.c imx6_sdhc
Index: src/sys/arch/arm/imx/fdt/if_enet_imx.c
diff -u src/sys/arch/arm/imx/fdt/if_enet_imx.c:1.8 src/sys/arch/arm/imx/fdt/if_enet_imx.c:1.9
--- src/sys/arch/arm/imx/fdt/if_enet_imx.c:1.8 Thu Nov 14 06:00:16 2019
+++ src/sys/arch/arm/imx/fdt/if_enet_imx.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: if_enet_imx.c,v 1.8 2019/11/14 06:00:16 hkenken Exp $ */
+/* $NetBSD: if_enet_imx.c,v 1.9 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
* Written by Hashimoto Kenichi for Genetec Corporation.
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_enet_imx.c,v 1.8 2019/11/14 06:00:16 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_enet_imx.c,v 1.9 2020/01/15 01:09:56 jmcneill Exp $");
#include "opt_fdt.h"
@@ -49,20 +49,24 @@ struct enet_fdt_softc {
CFATTACH_DECL_NEW(enet_fdt, sizeof(struct enet_fdt_softc),
enet_match, enet_attach, NULL, NULL);
-static const char * const compatible[] = {
- "fsl,imx6q-fec",
- NULL
+static const struct of_compat_data compat_data[] = {
+ /* compatible imxtype */
+ { "fsl,imx6q-fec", 6 },
+ { "fsl,imx6sx-fec", 7 },
+ { NULL }
};
static int enet_init_clocks(struct enet_softc *);
static void enet_phy_reset(struct enet_fdt_softc *, const int);
+static int enet_phy_id(struct enet_softc *, const int);
+static void *enet_intr_establish(struct enet_softc *, int, u_int);
int
enet_match(device_t parent, cfdata_t cf, void *aux)
{
struct fdt_attach_args * const faa = aux;
- return of_match_compatible(faa->faa_phandle, compatible);
+ return of_match_compat_data(faa->faa_phandle, compat_data);
}
void
@@ -100,12 +104,21 @@ enet_attach(device_t parent, device_t se
aprint_error(": couldn't get clock ahb\n");
goto failure;
}
- sc->sc_clk_enet_ref= fdtbus_clock_get(phandle, "ptp");
+ sc->sc_clk_enet_ref = fdtbus_clock_get(phandle, "ptp");
if (sc->sc_clk_enet_ref == NULL) {
aprint_error(": couldn't get clock ptp\n");
goto failure;
}
+ if (fdtbus_clock_enable(phandle, "enet_clk_ref", false) != 0) {
+ aprint_error(": couldn't enable clock enet_clk_ref\n");
+ goto failure;
+ }
+ if (fdtbus_clock_enable(phandle, "enet_out", false) != 0) {
+ aprint_error(": couldn't enable clock enet_out\n");
+ goto failure;
+ }
+
aprint_naive("\n");
aprint_normal(": Gigabit Ethernet Controller\n");
@@ -114,8 +127,9 @@ enet_attach(device_t parent, device_t se
sc->sc_ioh = bsh;
sc->sc_dmat = faa->faa_dmat;
- sc->sc_imxtype = 6; /* i.MX6 */
+ sc->sc_imxtype = of_search_compatible(phandle, compat_data)->data;
sc->sc_unit = 0;
+ sc->sc_phyid = enet_phy_id(sc, phandle);
const char *phy_mode = fdtbus_get_string(phandle, "phy-mode");
if (phy_mode == NULL) {
@@ -139,19 +153,16 @@ enet_attach(device_t parent, device_t se
sc->sc_rgmii = 0;
}
- char intrstr[128];
- if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
- aprint_error_dev(self, "failed to decode interrupt\n");
- goto failure;
- }
- sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_NET,
- FDT_INTR_MPSAFE, enet_intr, sc);
- if (sc->sc_ih == NULL) {
- aprint_error_dev(self, "failed to establish interrupt on %s\n",
- intrstr);
+ sc->sc_ih = enet_intr_establish(sc, phandle, 0);
+ if (sc->sc_ih == NULL)
goto failure;
+
+ if (sc->sc_imxtype == 7) {
+ sc->sc_ih2 = enet_intr_establish(sc, phandle, 1);
+ sc->sc_ih3 = enet_intr_establish(sc, phandle, 2);
+ if (sc->sc_ih2 == NULL || sc->sc_ih3 == NULL)
+ goto failure;
}
- aprint_normal_dev(self, "interrupting on %s\n", intrstr);
enet_init_clocks(sc);
sc->sc_clock = clk_get_rate(sc->sc_clk_ipg);
@@ -168,6 +179,29 @@ failure:
return;
}
+static void *
+enet_intr_establish(struct enet_softc *sc, int phandle, u_int index)
+{
+ char intrstr[128];
+ void *ih;
+
+ if (!fdtbus_intr_str(phandle, index, intrstr, sizeof(intrstr))) {
+ aprint_error_dev(sc->sc_dev, "failed to decode interrupt %d\n",
+ index);
+ return NULL;
+ }
+
+ ih = fdtbus_intr_establish(phandle, index, IPL_NET, 0, enet_intr, sc);
+ if (ih == NULL) {
+ aprint_error_dev(sc->sc_dev, "failed to establish interrupt on %s\n",
+ intrstr);
+ return NULL;
+ }
+ aprint_normal_dev(sc->sc_dev, "interrupting on %s\n", intrstr);
+
+ return ih;
+}
+
static int
enet_init_clocks(struct enet_softc *sc)
{
@@ -198,8 +232,10 @@ enet_phy_reset(struct enet_fdt_softc *sc
u_int msec;
sc->sc_pin_reset = fdtbus_gpio_acquire(phandle, "phy-reset-gpios", GPIO_PIN_OUTPUT);
- if (sc->sc_pin_reset == NULL)
+ if (sc->sc_pin_reset == NULL) {
+ aprint_error_dev(sc->sc_enet.sc_dev, "couldn't find phy reset gpios\n");
return;
+ }
if (of_getprop_uint32(phandle, "phy-reset-duration", &msec))
msec = 1;
@@ -215,3 +251,19 @@ enet_phy_reset(struct enet_fdt_softc *sc
delay(msec * 1000);
}
+
+static int
+enet_phy_id(struct enet_softc *sc, const int phandle)
+{
+ int phy_phandle;
+ bus_addr_t addr;
+
+ phy_phandle = fdtbus_get_phandle(phandle, "phy-handle");
+ if (phy_phandle == -1)
+ return MII_PHY_ANY;
+
+ if (fdtbus_get_reg(phy_phandle, 0, &addr, NULL) != 0)
+ return MII_PHY_ANY;
+
+ return (int)addr;
+}
Index: src/sys/arch/arm/imx/fdt/imx6_com.c
diff -u src/sys/arch/arm/imx/fdt/imx6_com.c:1.2 src/sys/arch/arm/imx/fdt/imx6_com.c:1.3
--- src/sys/arch/arm/imx/fdt/imx6_com.c:1.2 Thu Nov 28 14:13:37 2019
+++ src/sys/arch/arm/imx/fdt/imx6_com.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx6_com.c,v 1.2 2019/11/28 14:13:37 hkenken Exp $ */
+/* $NetBSD: imx6_com.c,v 1.3 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
* Written by Hashimoto Kenichi for Genetec Corporation.
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx6_com.c,v 1.2 2019/11/28 14:13:37 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx6_com.c,v 1.3 2020/01/15 01:09:56 jmcneill Exp $");
#include "opt_fdt.h"
#include "opt_imxuart.h"
@@ -70,6 +70,7 @@ imx6_com_attach(device_t parent, device_
bus_space_tag_t bst = faa->faa_bst;
bus_space_handle_t bsh;
char intrstr[128];
+ struct clk *per;
bus_addr_t addr;
bus_size_t size;
@@ -83,11 +84,28 @@ imx6_com_attach(device_t parent, device_
return;
}
+ if (fdtbus_clock_enable(phandle, "ipg", false) != 0) {
+ aprint_error(": couldn't enable ipg clock\n");
+ return;
+ }
+
+ per = fdtbus_clock_get(phandle, "per");
+ if (per != NULL && clk_enable(per) != 0) {
+ aprint_error(": couldn't enable per clock\n");
+ return;
+ }
+
sc->sc_dev = self;
regsp->ur_iot = bst;
regsp->ur_iobase = addr;
regsp->ur_ioh = bsh;
+ if (per != NULL) {
+ aprint_normal(", %u Hz", clk_get_rate(per));
+ /* XXX */
+ imxuart_set_frequency(clk_get_rate(per), 2);
+ }
+
if (imxuart_is_console(regsp->ur_iot, regsp->ur_iobase, ®sp->ur_ioh))
aprint_normal(" (console)");
@@ -108,7 +126,6 @@ imx6_com_attach(device_t parent, device_
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
imxuart_attach_subr(sc);
-
}
/*
Index: src/sys/arch/arm/imx/fdt/imx6_iomux.c
diff -u src/sys/arch/arm/imx/fdt/imx6_iomux.c:1.2 src/sys/arch/arm/imx/fdt/imx6_iomux.c:1.3
--- src/sys/arch/arm/imx/fdt/imx6_iomux.c:1.2 Wed Oct 2 01:34:09 2019
+++ src/sys/arch/arm/imx/fdt/imx6_iomux.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx6_iomux.c,v 1.2 2019/10/02 01:34:09 hkenken Exp $ */
+/* $NetBSD: imx6_iomux.c,v 1.3 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
* Written by Hashimoto Kenichi for Genetec Corporation.
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx6_iomux.c,v 1.2 2019/10/02 01:34:09 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx6_iomux.c,v 1.3 2020/01/15 01:09:56 jmcneill Exp $");
#include "opt_fdt.h"
@@ -132,7 +132,11 @@ CFATTACH_DECL_NEW(imxiomux, sizeof(struc
static int
imxiomux_match(device_t parent, cfdata_t cf, void *aux)
{
- const char * const compatible[] = { "fsl,imx6q-iomuxc", NULL };
+ const char * const compatible[] = {
+ "fsl,imx6q-iomuxc",
+ "fsl,imx8mq-iomuxc",
+ NULL
+ };
struct fdt_attach_args * const faa = aux;
return of_match_compatible(faa->faa_phandle, compatible);
@@ -166,10 +170,14 @@ imxiomux_attach(device_t parent, device_
aprint_normal(": IOMUX Controller\n");
for (int child = OF_child(phandle); child; child = OF_peer(child)) {
- for (int sub = OF_child(child); sub; sub = OF_peer(sub)) {
- if (!of_hasprop(sub, "fsl,pins"))
- continue;
- fdtbus_register_pinctrl_config(self, sub, &imx6_pinctrl_funcs);
+ if (of_hasprop(child, "fsl,pins")) {
+ fdtbus_register_pinctrl_config(self, child, &imx6_pinctrl_funcs);
+ } else {
+ for (int sub = OF_child(child); sub; sub = OF_peer(sub)) {
+ if (!of_hasprop(sub, "fsl,pins"))
+ continue;
+ fdtbus_register_pinctrl_config(self, sub, &imx6_pinctrl_funcs);
+ }
}
}
}
Index: src/sys/arch/arm/imx/fdt/imx6_gpio.c
diff -u src/sys/arch/arm/imx/fdt/imx6_gpio.c:1.4 src/sys/arch/arm/imx/fdt/imx6_gpio.c:1.5
--- src/sys/arch/arm/imx/fdt/imx6_gpio.c:1.4 Wed Nov 27 07:26:08 2019
+++ src/sys/arch/arm/imx/fdt/imx6_gpio.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx6_gpio.c,v 1.4 2019/11/27 07:26:08 hkenken Exp $ */
+/* $NetBSD: imx6_gpio.c,v 1.5 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
* Written by Hashimoto Kenichi for Genetec Corporation.
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx6_gpio.c,v 1.4 2019/11/27 07:26:08 hkenken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx6_gpio.c,v 1.5 2020/01/15 01:09:56 jmcneill Exp $");
#include "opt_fdt.h"
#include "gpio.h"
@@ -80,7 +80,7 @@ int
imxgpio_match(device_t parent, cfdata_t cf, void *aux)
{
const char * const compatible[] = {
- "fsl,imx6q-gpio",
+ "fsl,imx35-gpio",
NULL
};
struct fdt_attach_args * const faa = aux;
@@ -116,8 +116,8 @@ imxgpio_attach(device_t parent, device_t
sc->gpio_memt = faa->faa_bst;
sc->gpio_memh = ioh;
- sc->gpio_unit = (addr - IMX6_AIPS1_BASE - AIPS1_GPIO1_BASE) / 0x4000;
- sc->gpio_irqbase = PIC_MAXSOURCES + sc->gpio_unit * GPIO_NPINS;
+ sc->gpio_unit = -1;
+ sc->gpio_irqbase = PIC_IRQBASE_ALLOC;
if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
aprint_error_dev(self, "failed to decode interrupt\n");
Index: src/sys/arch/arm/imx/fdt/imx6_sdhc.c
diff -u src/sys/arch/arm/imx/fdt/imx6_sdhc.c:1.5 src/sys/arch/arm/imx/fdt/imx6_sdhc.c:1.6
--- src/sys/arch/arm/imx/fdt/imx6_sdhc.c:1.5 Sun Nov 24 11:07:19 2019
+++ src/sys/arch/arm/imx/fdt/imx6_sdhc.c Wed Jan 15 01:09:56 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: imx6_sdhc.c,v 1.5 2019/11/24 11:07:19 skrll Exp $ */
+/* $NetBSD: imx6_sdhc.c,v 1.6 2020/01/15 01:09:56 jmcneill Exp $ */
/*-
* Copyright (c) 2019 Genetec Corporation. All rights reserved.
* Written by Hashimoto Kenichi for Genetec Corporation.
@@ -25,7 +25,7 @@
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: imx6_sdhc.c,v 1.5 2019/11/24 11:07:19 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: imx6_sdhc.c,v 1.6 2020/01/15 01:09:56 jmcneill Exp $");
#include "opt_fdt.h"
@@ -63,6 +63,7 @@ struct imx6_sdhc_softc {
void *sc_ih;
struct clk *sc_clk_per;
+ struct fdtbus_regulator *sc_vmmc_supply;
struct fdtbus_gpio_pin *sc_pin_cd;
struct fdtbus_gpio_pin *sc_pin_wp;
@@ -71,9 +72,23 @@ struct imx6_sdhc_softc {
CFATTACH_DECL_NEW(imx6_sdhc, sizeof(struct imx6_sdhc_softc),
imx6_sdhc_match, imx6_sdhc_attach, NULL, NULL);
-static const char * const compatible[] = {
- "fsl,imx6q-usdhc",
- NULL
+struct imx6_sdhc_config {
+ uint32_t flags;
+};
+
+static const struct imx6_sdhc_config imx6q_config = {
+ .flags = SDHC_FLAG_BROKEN_ADMA2_ZEROLEN |
+ SDHC_FLAG_NO_BUSY_INTR,
+};
+
+static const struct imx6_sdhc_config imx7d_config = {
+ .flags = 0
+};
+
+static const struct of_compat_data compat_data[] = {
+ { "fsl,imx6q-usdhc", (uintptr_t)&imx6q_config },
+ { "fsl,imx7d-usdhc", (uintptr_t)&imx7d_config },
+ { NULL }
};
static int
@@ -81,7 +96,7 @@ imx6_sdhc_match(device_t parent, cfdata_
{
struct fdt_attach_args * const faa = aux;
- return of_match_compatible(faa->faa_phandle, compatible);
+ return of_match_compat_data(faa->faa_phandle, compat_data);
}
static void
@@ -89,26 +104,34 @@ imx6_sdhc_attach(device_t parent, device
{
struct imx6_sdhc_softc * const sc = device_private(self);
struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ const struct imx6_sdhc_config *conf;
char intrstr[128];
bus_addr_t addr;
bus_size_t size;
u_int bus_width;
int error;
- if (fdtbus_get_reg(faa->faa_phandle, 0, &addr, &size) != 0) {
+ fdtbus_clock_assign(phandle);
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
aprint_error(": couldn't get registers\n");
return;
}
- if (of_getprop_uint32(faa->faa_phandle, "bus-width", &bus_width))
- bus_width = 4;
-
- sc->sc_clk_per = fdtbus_clock_get(faa->faa_phandle, "per");
+ sc->sc_clk_per = fdtbus_clock_get(phandle, "per");
if (sc->sc_clk_per == NULL) {
aprint_error(": couldn't get clock\n");
return;
}
+ if (of_getprop_uint32(phandle, "bus-width", &bus_width))
+ bus_width = 4;
+
+ sc->sc_vmmc_supply = fdtbus_regulator_acquire(phandle, "vmmc-supply");
+
+ conf = (void *)of_search_compatible(phandle, compat_data)->data;
+
sc->sc_sdhc.sc_dev = self;
sc->sc_sdhc.sc_dmat = faa->faa_dmat;
@@ -119,13 +142,12 @@ imx6_sdhc_attach(device_t parent, device
SDHC_FLAG_HAVE_DVS |
SDHC_FLAG_32BIT_ACCESS |
SDHC_FLAG_USE_ADMA2 |
- SDHC_FLAG_USDHC |
- SDHC_FLAG_NO_BUSY_INTR |
- SDHC_FLAG_BROKEN_ADMA2_ZEROLEN;
+ SDHC_FLAG_USDHC;
+ sc->sc_sdhc.sc_flags |= conf->flags;
if (bus_width == 8)
sc->sc_sdhc.sc_flags |= SDHC_FLAG_8BIT_MODE;
- if (of_hasprop(faa->faa_phandle, "no-1-8-v"))
+ if (of_hasprop(phandle, "no-1-8-v"))
sc->sc_sdhc.sc_flags |= SDHC_FLAG_NO_1_8_V;
sc->sc_sdhc.sc_host = &sc->sc_host;
@@ -138,14 +160,14 @@ imx6_sdhc_attach(device_t parent, device
}
sc->sc_bsz = size;
- sc->sc_pin_cd = fdtbus_gpio_acquire(faa->faa_phandle,
+ sc->sc_pin_cd = fdtbus_gpio_acquire(phandle,
"cd-gpios", GPIO_PIN_INPUT);
if (sc->sc_pin_cd) {
sc->sc_sdhc.sc_vendor_card_detect = imx6_sdhc_card_detect;
sc->sc_sdhc.sc_flags |= SDHC_FLAG_POLL_CARD_DET;
}
- sc->sc_pin_wp = fdtbus_gpio_acquire(faa->faa_phandle,
+ sc->sc_pin_wp = fdtbus_gpio_acquire(phandle,
"wp-gpios", GPIO_PIN_INPUT);
if (sc->sc_pin_wp) {
sc->sc_sdhc.sc_vendor_write_protect = imx6_sdhc_write_protect;
@@ -157,6 +179,14 @@ imx6_sdhc_attach(device_t parent, device
return;
}
+ if (sc->sc_vmmc_supply != NULL) {
+ error = fdtbus_regulator_enable(sc->sc_vmmc_supply);
+ if (error) {
+ aprint_error(": couldn't enable vmmc supply: %d\n", error);
+ return;
+ }
+ }
+
aprint_naive("\n");
aprint_normal(": SDMMC (%u kHz)\n", sc->sc_sdhc.sc_clkbase);
@@ -165,12 +195,12 @@ imx6_sdhc_attach(device_t parent, device
return;
}
- if (!fdtbus_intr_str(faa->faa_phandle, 0, intrstr, sizeof(intrstr))) {
+ if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
aprint_error_dev(self, "failed to decode interrupt\n");
return;
}
- sc->sc_ih = fdtbus_intr_establish(faa->faa_phandle, 0, IPL_SDMMC,
+ sc->sc_ih = fdtbus_intr_establish(phandle, 0, IPL_SDMMC,
FDT_INTR_MPSAFE, sdhc_intr, &sc->sc_sdhc);
if (sc->sc_ih == NULL) {
aprint_error_dev(self, "couldn't establish interrupt on %s\n",
@@ -183,7 +213,7 @@ imx6_sdhc_attach(device_t parent, device
if (error) {
aprint_error_dev(self, "couldn't initialize host, error = %d\n",
error);
- fdtbus_intr_disestablish(faa->faa_phandle, sc->sc_ih);
+ fdtbus_intr_disestablish(phandle, sc->sc_ih);
sc->sc_ih = NULL;
return;
}
Index: src/sys/arch/evbarm/conf/GENERIC64
diff -u src/sys/arch/evbarm/conf/GENERIC64:1.131 src/sys/arch/evbarm/conf/GENERIC64:1.132
--- src/sys/arch/evbarm/conf/GENERIC64:1.131 Sun Jan 12 21:52:36 2020
+++ src/sys/arch/evbarm/conf/GENERIC64 Wed Jan 15 01:09:57 2020
@@ -1,5 +1,5 @@
#
-# $NetBSD: GENERIC64,v 1.131 2020/01/12 21:52:36 riastradh Exp $
+# $NetBSD: GENERIC64,v 1.132 2020/01/15 01:09:57 jmcneill Exp $
#
# GENERIC ARM (aarch64) kernel
#
@@ -16,7 +16,7 @@ maxusers 64
#
makeoptions DTSARCH="arm aarch64"
makeoptions DTSGNUARCH="arm arm64"
-makeoptions DTSSUBDIR="allwinner amlogic broadcom nvidia rockchip"
+makeoptions DTSSUBDIR="allwinner amlogic broadcom freescale nvidia rockchip"
makeoptions DTS="
bcm2711-rpi-4-b.dts
bcm2837-rpi-3-a-plus.dts
@@ -24,6 +24,14 @@ makeoptions DTS="
bcm2837-rpi-3-b.dts
bcm2837-rpi-cm3-io3.dts
+ imx8mq-evk.dts
+ imx8mq-hummingboard-pulse.dts
+ imx8mq-librem5-devkit.dts
+ imx8mq-nitrogen.dts
+ imx8mq-pico-pi.dts
+ imx8mq-zii-ultra-rmb3.dts
+ imx8mq-zii-ultra-zest.dts
+
meson-gxbb-nanopi-k2.dts
meson-gxbb-nexbox-a95x.dts
meson-gxbb-odroidc2.dts
@@ -234,6 +242,7 @@ gic* at acpi?
armgic0 at gic?
gicvthree* at fdt? pass 1 # ARM GICv3
gicvthree* at acpi?
+imx7gpc* at fdt? pass 2 # IMX GPCv2
sunxinmi* at fdt? pass 2 # Allwinner NMI / R_INTC
# Memory controller
@@ -263,6 +272,7 @@ bcmcprman* at fdt? pass 1 # Broadcom BC
bcmaux* at fdt? pass 1 # Broadcom BCM283x Aux Periph Clocks
gxbbaoclkc* at fdt? pass 2 # Amlogic Meson GXBB AO clock controller
gxbbclkc* at fdt? pass 2 # Amlogic Meson GXBB/GXL EE clock controller
+imx8mqccm* at fdt? pass 2 # NXP iMX8MQ CCM
mesonresets* at fdt? pass 2 # Amlogic Meson misc. clock resets
rkcru* at fdt? pass 2 # Rockchip RK3328 CRU
sun8ih3ccu* at fdt? pass 2 # Allwinner H3/H5 CCU
@@ -279,6 +289,7 @@ tegra210car* at fdt? pass 3 # NVIDIA Te
# GPIO controller
bcmgpio* at fdt? # Broadcom BCM283x GPIO
+imxgpio* at fdt? pass 3 # IMX GPIO
mesonpinctrl* at fdt? pass 2 # Amlogic Meson GPIO
plgpio* at fdt? # ARM PrimeCell PL061 GPIO
plgpio* at acpi?
@@ -292,6 +303,7 @@ rkpwm* at fdt? pass 3 # Rockchip PWM
sunxipwm* at fdt? pass 3 # Allwinner PWM
# MPIO / Pinmux
+imxiomux* at fdt? pass 2 # IMX IOMUX
rkiomux* at fdt? pass 3 # Rockchip IOMUX
tegrapinmux* at fdt? # NVIDIA Tegra MPIO
@@ -312,6 +324,7 @@ pci* at ppb?
# Ethernet
awge* at fdt? # DesignWare Gigabit Ethernet
emac* at fdt? # Allwinner Gigabit Ethernet (EMAC)
+enet* at fdt? # IMX FEC
aq* at pci? dev ? function ? # Aquantia AQC 10 gigabit
ena* at pci? dev ? function ? # Amazon.com Elastic Network Adapter
mcx* at pci? dev ? function ? # Mellanox 5th generation Ethernet
@@ -321,6 +334,7 @@ re* at pci? dev ? function ? # Realtek
wm* at pci? dev ? function ? # Intel Gigabit Ethernet
# MII/PHY support
+atphy* at mii? phy ? # Attansic/Atheros PHYs
exphy* at mii? phy ? # 3Com internal PHYs
gentbi* at mii? phy ? # Generic Ten-Bit 1000BASE-[CLS]X PHYs
glxtphy* at mii? phy ? # Level One LXT-1000 PHYs
@@ -354,6 +368,8 @@ ukphy* at mii? phy ? # generic unknown
# UART
com* at fdt? pass 4 # UART
com* at acpi?
+imxuart* at fdt? pass 4 # IMX UART
+options IMXUARTCONSOLE
mesonuart* at fdt? pass 4 # Amlogic Meson UART
plcom* at fdt? pass 4 # ARM PL011 UART
plcom* at acpi?
@@ -513,6 +529,7 @@ tegrasoctherm* at fdt? # NVIDIA Tegra
rktsadc* at fdt? # RockChip TSASC
# USB
+imx8mqusbphy* at fdt? pass 9 # IMX USB PHY
mesonusbphy* at fdt? pass 9 # Amlogic Meson USB2 PHY
mesongxlu2phy* at fdt? pass 9 # Amlogic Meson GXL USB2 PHY
mesongxlu3phy* at fdt? pass 9 # Amlogic Meson GXL USB3 PHY
Index: src/sys/arch/evbarm/conf/files.generic64
diff -u src/sys/arch/evbarm/conf/files.generic64:1.14 src/sys/arch/evbarm/conf/files.generic64:1.15
--- src/sys/arch/evbarm/conf/files.generic64:1.14 Sun Jan 5 17:26:31 2020
+++ src/sys/arch/evbarm/conf/files.generic64 Wed Jan 15 01:09:57 2020
@@ -1,4 +1,4 @@
-# $NetBSD: files.generic64,v 1.14 2020/01/05 17:26:31 jmcneill Exp $
+# $NetBSD: files.generic64,v 1.15 2020/01/15 01:09:57 jmcneill Exp $
#
# A generic (aarch64) kernel configuration info
#
@@ -13,6 +13,7 @@ include "arch/evbarm/conf/files.fdt"
include "arch/arm/acpi/files.acpi"
include "arch/arm/amlogic/files.meson"
include "arch/arm/broadcom/files.bcm2835"
+include "arch/arm/imx/fdt/files.imx6"
include "arch/arm/nvidia/files.tegra"
include "arch/arm/rockchip/files.rockchip"
include "arch/arm/sunxi/files.sunxi"
Index: src/sys/dev/fdt/dwc3_fdt.c
diff -u src/sys/dev/fdt/dwc3_fdt.c:1.8 src/sys/dev/fdt/dwc3_fdt.c:1.9
--- src/sys/dev/fdt/dwc3_fdt.c:1.8 Thu Dec 12 00:45:59 2019
+++ src/sys/dev/fdt/dwc3_fdt.c Wed Jan 15 01:09:57 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc3_fdt.c,v 1.8 2019/12/12 00:45:59 jmcneill Exp $ */
+/* $NetBSD: dwc3_fdt.c,v 1.9 2020/01/15 01:09:57 jmcneill Exp $ */
/*-
* Copyright (c) 2018 Jared McNeill <[email protected]>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc3_fdt.c,v 1.8 2019/12/12 00:45:59 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc3_fdt.c,v 1.9 2020/01/15 01:09:57 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -208,6 +208,7 @@ dwc3_fdt_match(device_t parent, cfdata_t
const char * const compatible[] = {
"allwinner,sun50i-h6-dwc3",
"amlogic,meson-gxl-dwc3",
+ "fsl,imx8mq-dwc3",
"rockchip,rk3328-dwc3",
"rockchip,rk3399-dwc3",
"samsung,exynos5250-dwusb3",
@@ -221,6 +222,7 @@ dwc3_fdt_match(device_t parent, cfdata_t
static void
dwc3_fdt_attach(device_t parent, device_t self, void *aux)
{
+ const char * const dwc3_compatible[] = { "snps,dwc3", NULL };
struct xhci_softc * const sc = device_private(self);
struct fdt_attach_args * const faa = aux;
const int phandle = faa->faa_phandle;
@@ -230,12 +232,16 @@ dwc3_fdt_attach(device_t parent, device_
char intrstr[128];
bus_addr_t addr;
bus_size_t size;
- int error;
+ int error, dwc3_phandle;
void *ih;
u_int n;
/* Find dwc3 sub-node */
- const int dwc3_phandle = of_find_firstchild_byname(phandle, "dwc3");
+ if (of_match_compatible(phandle, dwc3_compatible) > 0) {
+ dwc3_phandle = phandle;
+ } else {
+ dwc3_phandle = of_find_firstchild_byname(phandle, "dwc3");
+ }
if (dwc3_phandle <= 0) {
aprint_error(": couldn't find dwc3 child node\n");
return;
@@ -249,6 +255,7 @@ dwc3_fdt_attach(device_t parent, device_
}
/* Enable clocks */
+ fdtbus_clock_assign(phandle);
for (n = 0; (clk = fdtbus_clock_get_index(phandle, n)) != NULL; n++)
if (clk_enable(clk) != 0) {
aprint_error(": couldn't enable clock #%d\n", n);
Added files:
Index: src/sys/arch/arm/imx/fdt/imx7_gpc.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx7_gpc.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx7_gpc.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,264 @@
+/* $NetBSD: imx7_gpc.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+/*-
+ * Copyright (c) 2019 Genetec Corporation. All rights reserved.
+ * Written by Hashimoto Kenichi for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx7_gpc.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include "opt_fdt.h"
+
+#define _INTR_PRIVATE
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+
+#include <arm/imx/imx6var.h>
+#include <arm/imx/imx6_reg.h>
+#include <arm/imx/imx6_gpcreg.h>
+
+#include <arm/cortex/gic_intr.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define GPC_PCG_CPU_0_1_MAPPING 0xec
+#define OTG2_A53_DOMAIN __BIT(5)
+#define OTG1_A53_DOMAIN __BIT(4)
+
+#define GPC_PU_PGC_SW_PUP_REQ 0xf8
+#define USB_OTG2_SW_PUP_REQ __BIT(3)
+#define USB_OTG1_SW_PUP_REQ __BIT(2)
+
+#define IMXGPC_MAXCPUS 4
+
+/* Mapping of CPU number to GPC_IMR1_COREx base offset */
+static const bus_size_t imx7gpc_imr_base[IMXGPC_MAXCPUS] = {
+ 0x30,
+ 0x40,
+ 0x1c0,
+ 0x1d0,
+};
+
+#define GPC_IMRn_COREx(n,x) (imx7gpc_imr_base[(x)] + (n) * 0x4)
+
+struct imx7gpc_softc {
+ device_t sc_dev;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+};
+
+static int imx7gpc_match(device_t, struct cfdata *, void *);
+static void imx7gpc_attach(device_t, device_t, void *);
+
+static void imx7gpc_powerup(struct imx7gpc_softc *, uint32_t, uint32_t);
+static void imx7gpc_mask(struct imx7gpc_softc *, u_int, bool);
+static void imx7gpc_unmask(struct imx7gpc_softc *, u_int, bool);
+
+static void *imx7gpc_establish(device_t, u_int *, int, int,
+ int (*)(void *), void *);
+static void imx7gpc_disestablish(device_t, void *);
+static bool imx7gpc_intrstr(device_t, u_int *, char *, size_t);
+
+struct fdtbus_interrupt_controller_func imx7gpc_funcs = {
+ .establish = imx7gpc_establish,
+ .disestablish = imx7gpc_disestablish,
+ .intrstr = imx7gpc_intrstr
+};
+
+CFATTACH_DECL_NEW(imx7gpc, sizeof(struct imx7gpc_softc),
+ imx7gpc_match, imx7gpc_attach, NULL, NULL);
+
+static int
+imx7gpc_match(device_t parent, cfdata_t cf, void *aux)
+{
+ const char * const compatible[] = {
+ "fsl,imx7d-gpc",
+ "fsl,imx8mq-gpc",
+ NULL
+ };
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+imx7gpc_attach(device_t parent, device_t self, void *aux)
+{
+ struct imx7gpc_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t gpc_addr;
+ bus_size_t gpc_size;
+ int error;
+
+ KASSERT(ncpu <= IMXGPC_MAXCPUS);
+
+ if (fdtbus_get_reg(phandle, 0, &gpc_addr, &gpc_size) != 0) {
+ aprint_error(": couldn't get gpc registers\n");
+ return;
+ }
+
+ sc->sc_dev = self;
+ sc->sc_iot = faa->faa_bst;
+
+ error = bus_space_map(sc->sc_iot, gpc_addr, gpc_size, 0,
+ &sc->sc_ioh);
+ if (error) {
+ aprint_error(": couldn't map gpc registers: %d\n", error);
+ return;
+ }
+
+ error = fdtbus_register_interrupt_controller(self, faa->faa_phandle,
+ &imx7gpc_funcs);
+ if (error) {
+ aprint_error(": couldn't register with fdtbus: %d\n", error);
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": General Power Controller\n");
+
+ /* XXX enable OTG power domains */
+ imx7gpc_powerup(sc, USB_OTG2_SW_PUP_REQ | USB_OTG1_SW_PUP_REQ,
+ OTG2_A53_DOMAIN | OTG1_A53_DOMAIN);
+}
+
+static void
+imx7gpc_powerup(struct imx7gpc_softc *sc, uint32_t req, uint32_t map)
+{
+ uint32_t val;
+
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GPC_PCG_CPU_0_1_MAPPING);
+ val |= map;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, GPC_PCG_CPU_0_1_MAPPING, val);
+
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GPC_PU_PGC_SW_PUP_REQ);
+ val |= req;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, GPC_PU_PGC_SW_PUP_REQ, val);
+
+ delay(5000);
+
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GPC_PCG_CPU_0_1_MAPPING);
+ val &= ~map;
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, GPC_PCG_CPU_0_1_MAPPING, val);
+}
+
+static void
+imx7gpc_mask(struct imx7gpc_softc *sc, u_int irq, bool mpsafe)
+{
+ const u_int reg = irq / 32;
+ const u_int bit = irq % 32;
+ uint32_t val;
+
+ for (u_int cpu = 0; cpu < (mpsafe ? ncpu : 1); cpu++) {
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ GPC_IMRn_COREx(reg, cpu));
+ val |= __BIT(bit);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+ GPC_IMRn_COREx(reg, cpu), val);
+ }
+}
+
+static void
+imx7gpc_unmask(struct imx7gpc_softc *sc, u_int irq, bool mpsafe)
+{
+ const u_int reg = irq / 32;
+ const u_int bit = irq % 32;
+ uint32_t val;
+
+ for (u_int cpu = 0; cpu < (mpsafe ? ncpu : 1); cpu++) {
+ val = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+ GPC_IMRn_COREx(reg, cpu));
+ val &= ~__BIT(bit);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+ GPC_IMRn_COREx(reg, cpu), val);
+ }
+}
+
+
+static void *
+imx7gpc_establish(device_t dev, u_int *specifier, int ipl, int flags,
+ int (*func)(void *), void *arg)
+{
+ struct imx7gpc_softc * const sc = device_private(dev);
+ void *ih;
+
+ /* 1st cell is the interrupt type; 0 is SPI, 1 is PPI */
+ /* 2nd cell is the interrupt number */
+ /* 3rd cell is flags */
+
+ const u_int type = be32toh(specifier[0]);
+ const u_int intr = be32toh(specifier[1]);
+ const u_int irq = type == 0 ? IRQ_SPI(intr) : IRQ_PPI(intr);
+ const u_int trig = be32toh(specifier[2]) & 0xf;
+ const u_int level = (trig & 0x3) ? IST_EDGE : IST_LEVEL;
+
+ const u_int mpsafe = (flags & FDT_INTR_MPSAFE) ? IST_MPSAFE : 0;
+
+ if (type != 0)
+ return NULL; /* Only SPIs are supported */
+
+ KASSERT(irq >= 32);
+
+ aprint_debug_dev(dev, "intr establish irq %d, level %d\n", irq, level);
+
+ ih = intr_establish(irq, ipl, level | mpsafe, func, arg);
+ if (ih != NULL)
+ imx7gpc_unmask(sc, irq - 32, mpsafe == IST_MPSAFE);
+
+ return ih;
+}
+
+static void
+imx7gpc_disestablish(device_t dev, void *ih)
+{
+ struct imx7gpc_softc * const sc = device_private(dev);
+ struct intrsource *is = ih;
+ const u_int irq = is->is_irq;
+ const bool mpsafe = is->is_mpsafe;
+
+ intr_disestablish(ih);
+ imx7gpc_mask(sc, irq - 32, mpsafe);
+}
+
+static bool
+imx7gpc_intrstr(device_t dev, u_int *specifier, char *buf, size_t buflen)
+{
+ /* 1st cell is the interrupt type; 0 is SPI, 1 is PPI */
+ /* 2nd cell is the interrupt number */
+ /* 3rd cell is flags */
+
+ if (!specifier)
+ return false;
+
+ const u_int type = be32toh(specifier[0]);
+ const u_int intr = be32toh(specifier[1]);
+ const u_int irq = type == 0 ? IRQ_SPI(intr) : IRQ_PPI(intr);
+
+ snprintf(buf, buflen, "irq %d", irq);
+
+ return true;
+}
Index: src/sys/arch/arm/imx/fdt/imx8mq_ccm.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx8mq_ccm.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx8mq_ccm.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,194 @@
+/* $NetBSD: imx8mq_ccm.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD: imx8mq_ccm.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <arm/imx/fdt/imx_ccm.h>
+#include <arm/imx/fdt/imx8mq_ccm.h>
+
+static int imx8mq_ccm_match(device_t, cfdata_t, void *);
+static void imx8mq_ccm_attach(device_t, device_t, void *);
+
+static const char * const compatible[] = {
+ "fsl,imx8mq-ccm",
+ NULL
+};
+
+static const char *uart_p[] = {
+ "osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m", "sys3_pll_out", "clk_ext2", "clk_ext4", "audio_pll2_out"
+};
+static const char *usdhc_p[] = {
+ "osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m", "audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m"
+};
+static const char *enet_axi_p[] = {
+ "osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_250m", "sys2_pll_200m", "audio_pll1_out", "video_pll1_out", "sys3_pll_out"
+};
+static const char *enet_ref_p[] = {
+ "osc_25m", "sys2_pll_125m", "sys2_pll_500m", "sys2_pll_100m", "sys1_pll_160m", "audio_pll1_out", "video_pll1_out", "clk_ext4"
+};
+static const char *enet_timer_p[] = {
+ "osc_25m", "sys2_pll_100m", "audio_pll1_out", "clk_ext1", "clk_ext2", "clk_ext3", "clk_ext4", "video_pll1_out"
+};
+static const char *enet_phy_ref_p[] = {
+ "osc_25m", "sys2_pll_50m", "sys2_pll_125m", "sys2_pll_500m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out"
+};
+static const char *usb_bus_p[] = {
+ "osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_100m", "sys2_pll_200m", "clk_ext2", "clk_ext4", "audio_pll2_out"
+};
+static const char *usb_core_phy_p[] = {
+ "osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m", "sys2_pll_200m", "clk_ext2", "clk_ext3", "audio_pll2_out"
+};
+
+CFATTACH_DECL_NEW(imx8mq_ccm, sizeof(struct imx_ccm_softc),
+ imx8mq_ccm_match, imx8mq_ccm_attach, NULL, NULL);
+
+static struct imx_ccm_clk imx8mq_ccm_clks[] = {
+
+ IMX_FIXED(CLK_DUMMY, "dummy", 0),
+ IMX_EXTCLK(CLK_32K, "ckil"),
+ IMX_EXTCLK(CLK_25M, "osc_25m"),
+ IMX_EXTCLK(CLK_27M, "osc_27m"),
+ IMX_EXTCLK(CLK_EXT1, "clk_ext1"),
+ IMX_EXTCLK(CLK_EXT2, "clk_ext2"),
+ IMX_EXTCLK(CLK_EXT3, "clk_ext3"),
+ IMX_EXTCLK(CLK_EXT4, "clk_ext4"),
+
+ IMX_FIXED(SYS1_PLL_OUT, "sys1_pll_out", 800000000),
+ IMX_FIXED(SYS2_PLL_OUT, "sys2_pll_out", 1000000000),
+
+ IMX_GATE(SYS1_PLL_40M_CG, "sys1_pll_40m_cg", "sys1_pll_out", 0x30, __BIT(9)),
+ IMX_GATE(SYS1_PLL_80M_CG, "sys1_pll_80m_cg", "sys1_pll_out", 0x30, __BIT(11)),
+ IMX_GATE(SYS1_PLL_100M_CG, "sys1_pll_100m_cg", "sys1_pll_out", 0x30, __BIT(13)),
+ IMX_GATE(SYS1_PLL_133M_CG, "sys1_pll_133m_cg", "sys1_pll_out", 0x30, __BIT(15)),
+ IMX_GATE(SYS1_PLL_160M_CG, "sys1_pll_160m_cg", "sys1_pll_out", 0x30, __BIT(17)),
+ IMX_GATE(SYS1_PLL_200M_CG, "sys1_pll_200m_cg", "sys1_pll_out", 0x30, __BIT(19)),
+ IMX_GATE(SYS1_PLL_266M_CG, "sys1_pll_266m_cg", "sys1_pll_out", 0x30, __BIT(21)),
+ IMX_GATE(SYS1_PLL_400M_CG, "sys1_pll_400m_cg", "sys1_pll_out", 0x30, __BIT(23)),
+ IMX_GATE(SYS1_PLL_800M_CG, "sys1_pll_800m_cg", "sys1_pll_out", 0x30, __BIT(25)),
+
+ IMX_FIXED_FACTOR(SYS1_PLL_40M, "sys1_pll_40m", "sys1_pll_40m_cg", 1, 20),
+ IMX_FIXED_FACTOR(SYS1_PLL_80M, "sys1_pll_80m", "sys1_pll_80m_cg", 1, 10),
+ IMX_FIXED_FACTOR(SYS1_PLL_100M, "sys1_pll_100m", "sys1_pll_100m_cg", 1, 8),
+ IMX_FIXED_FACTOR(SYS1_PLL_133M, "sys1_pll_133m", "sys1_pll_133m_cg", 1, 6),
+ IMX_FIXED_FACTOR(SYS1_PLL_160M, "sys1_pll_160m", "sys1_pll_160m_cg", 1, 5),
+ IMX_FIXED_FACTOR(SYS1_PLL_200M, "sys1_pll_200m", "sys1_pll_200m_cg", 1, 4),
+ IMX_FIXED_FACTOR(SYS1_PLL_266M, "sys1_pll_266m", "sys1_pll_266m_cg", 1, 3),
+ IMX_FIXED_FACTOR(SYS1_PLL_400M, "sys1_pll_400m", "sys1_pll_400m_cg", 1, 2),
+ IMX_FIXED_FACTOR(SYS1_PLL_800M, "sys1_pll_800m", "sys1_pll_800m_cg", 1, 1),
+
+ IMX_GATE(SYS2_PLL_50M_CG, "sys2_pll_50m_cg", "sys2_pll_out", 0x3c, __BIT(9)),
+ IMX_GATE(SYS2_PLL_100M_CG, "sys2_pll_100m_cg", "sys2_pll_out", 0x3c, __BIT(11)),
+ IMX_GATE(SYS2_PLL_125M_CG, "sys2_pll_125m_cg", "sys2_pll_out", 0x3c, __BIT(13)),
+ IMX_GATE(SYS2_PLL_166M_CG, "sys2_pll_166m_cg", "sys2_pll_out", 0x3c, __BIT(15)),
+ IMX_GATE(SYS2_PLL_200M_CG, "sys2_pll_200m_cg", "sys2_pll_out", 0x3c, __BIT(17)),
+ IMX_GATE(SYS2_PLL_250M_CG, "sys2_pll_250m_cg", "sys2_pll_out", 0x3c, __BIT(19)),
+ IMX_GATE(SYS2_PLL_333M_CG, "sys2_pll_333m_cg", "sys2_pll_out", 0x3c, __BIT(21)),
+ IMX_GATE(SYS2_PLL_500M_CG, "sys2_pll_500m_cg", "sys2_pll_out", 0x3c, __BIT(23)),
+ IMX_GATE(SYS2_PLL_1000M_CG, "sys2_pll_1000m_cg", "sys2_pll_out", 0x3c, __BIT(25)),
+
+ IMX_FIXED_FACTOR(SYS2_PLL_50M, "sys2_pll_50m", "sys2_pll_50m_cg", 1, 20),
+ IMX_FIXED_FACTOR(SYS2_PLL_100M, "sys2_pll_100m", "sys2_pll_100m_cg", 1, 10),
+ IMX_FIXED_FACTOR(SYS2_PLL_125M, "sys2_pll_125m", "sys2_pll_125m_cg", 1, 8),
+ IMX_FIXED_FACTOR(SYS2_PLL_166M, "sys2_pll_166m", "sys2_pll_166m_cg", 1, 6),
+ IMX_FIXED_FACTOR(SYS2_PLL_200M, "sys2_pll_200m", "sys2_pll_200m_cg", 1, 5),
+ IMX_FIXED_FACTOR(SYS2_PLL_250M, "sys2_pll_250m", "sys2_pll_250m_cg", 1, 4),
+ IMX_FIXED_FACTOR(SYS2_PLL_333M, "sys2_pll_333m", "sys2_pll_333m_cg", 1, 3),
+ IMX_FIXED_FACTOR(SYS2_PLL_500M, "sys2_pll_500m", "sys2_pll_500m_cg", 1, 2),
+ IMX_FIXED_FACTOR(SYS2_PLL_1000M, "sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1),
+
+ IMX_COMPOSITE(CLK_UART1, "uart1", uart_p, 0xaf00, 0),
+ IMX_COMPOSITE(CLK_UART2, "uart2", uart_p, 0xaf80, 0),
+ IMX_COMPOSITE(CLK_UART3, "uart3", uart_p, 0xb000, 0),
+ IMX_COMPOSITE(CLK_UART4, "uart4", uart_p, 0xb080, 0),
+
+ IMX_ROOT_GATE(CLK_UART1_ROOT, "uart1_root_clk", "uart1", 0x4490),
+ IMX_ROOT_GATE(CLK_UART2_ROOT, "uart2_root_clk", "uart2", 0x44a0),
+ IMX_ROOT_GATE(CLK_UART3_ROOT, "uart3_root_clk", "uart3", 0x44b0),
+ IMX_ROOT_GATE(CLK_UART4_ROOT, "uart4_root_clk", "uart4", 0x44c0),
+
+ IMX_COMPOSITE(CLK_USDHC1, "usdhc1", usdhc_p, 0xac00, IMX_COMPOSITE_ROUND_DOWN),
+ IMX_COMPOSITE(CLK_USDHC2, "usdhc2", usdhc_p, 0xac80, IMX_COMPOSITE_ROUND_DOWN),
+
+ IMX_ROOT_GATE(CLK_USDHC1_ROOT, "usdhc1_root_clk", "usdhc1", 0x4510),
+ IMX_ROOT_GATE(CLK_USDHC2_ROOT, "usdhc2_root_clk", "usdhc2", 0x4520),
+
+ IMX_COMPOSITE(CLK_ENET_AXI, "enet_axi", enet_axi_p, 0x8800, 0),
+ IMX_COMPOSITE(CLK_ENET_REF, "enet_ref", enet_ref_p, 0xa980, 0),
+ IMX_COMPOSITE(CLK_ENET_TIMER, "enet_timer", enet_timer_p, 0xaa00, 0),
+ IMX_COMPOSITE(CLK_ENET_PHY_REF, "enet_phy_ref", enet_phy_ref_p, 0xaa80, 0),
+
+ IMX_ROOT_GATE(CLK_ENET1_ROOT, "enet1_root_clk", "enet_axi", 0x40a0),
+
+ IMX_COMPOSITE(CLK_USB_BUS, "usb_bus", usb_bus_p, 0x8b80, 0),
+ IMX_COMPOSITE(CLK_USB_CORE_REF, "usb_core_ref", usb_core_phy_p, 0xb100, 0),
+ IMX_COMPOSITE(CLK_USB_PHY_REF, "usb_phy_ref", usb_core_phy_p, 0xb180, 0),
+
+ IMX_ROOT_GATE(CLK_USB1_CTRL_ROOT, "usb1_ctrl_root_clk", "usb_bus", 0x44d0),
+ IMX_ROOT_GATE(CLK_USB2_CTRL_ROOT, "usb2_ctrl_root_clk", "usb_bus", 0x44e0),
+ IMX_ROOT_GATE(CLK_USB1_PHY_ROOT, "usb1_phy_root_clk", "usb_phy_ref", 0x44f0),
+ IMX_ROOT_GATE(CLK_USB2_PHY_ROOT, "usb2_phy_root_clk", "usb_phy_ref", 0x4500),
+};
+
+static int
+imx8mq_ccm_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compatible(faa->faa_phandle, compatible);
+}
+
+static void
+imx8mq_ccm_attach(device_t parent, device_t self, void *aux)
+{
+ struct imx_ccm_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+
+ sc->sc_dev = self;
+ sc->sc_phandle = faa->faa_phandle;
+ sc->sc_bst = faa->faa_bst;
+
+ sc->sc_clks = imx8mq_ccm_clks;
+ sc->sc_nclks = __arraycount(imx8mq_ccm_clks);
+
+ if (imx_ccm_attach(sc) != 0)
+ return;
+
+ aprint_naive("\n");
+ aprint_normal(": Clock Control Module\n");
+
+ imx_ccm_print(sc);
+}
Index: src/sys/arch/arm/imx/fdt/imx8mq_ccm.h
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx8mq_ccm.h:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx8mq_ccm.h Wed Jan 15 01:09:56 2020
@@ -0,0 +1,321 @@
+/* $NetBSD: imx8mq_ccm.h,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _IMX8MQ_CCM_H
+#define _IMX8MQ_CCM_H
+
+/*
+ * Clocks
+ */
+
+#define CLK_DUMMY 0
+#define CLK_32K 1
+#define CLK_25M 2
+#define CLK_27M 3
+#define CLK_EXT1 4
+#define CLK_EXT2 5
+#define CLK_EXT3 6
+#define CLK_EXT4 7
+#define ARM_PLL_REF_SEL 8
+#define ARM_PLL_REF_DIV 9
+#define ARM_PLL 10
+#define ARM_PLL_BYPASS 11
+#define ARM_PLL_OUT 12
+#define GPU_PLL_REF_SEL 13
+#define GPU_PLL_REF_DIV 14
+#define GPU_PLL 15
+#define GPU_PLL_BYPASS 16
+#define GPU_PLL_OUT 17
+#define VPU_PLL_REF_SEL 18
+#define VPU_PLL_REF_DIV 19
+#define VPU_PLL 20
+#define VPU_PLL_BYPASS 21
+#define VPU_PLL_OUT 22
+#define AUDIO_PLL1_REF_SEL 23
+#define AUDIO_PLL1_REF_DIV 24
+#define AUDIO_PLL1 25
+#define AUDIO_PLL1_BYPASS 26
+#define AUDIO_PLL1_OUT 27
+#define AUDIO_PLL2_REF_SEL 28
+#define AUDIO_PLL2_REF_DIV 29
+#define AUDIO_PLL2 30
+#define AUDIO_PLL2_BYPASS 31
+#define AUDIO_PLL2_OUT 32
+#define VIDEO_PLL1_REF_SEL 33
+#define VIDEO_PLL1_REF_DIV 34
+#define VIDEO_PLL1 35
+#define VIDEO_PLL1_BYPASS 36
+#define VIDEO_PLL1_OUT 37
+#define SYS1_PLL1_REF_SEL 38
+#define SYS1_PLL1_REF_DIV 39
+#define SYS1_PLL1 40
+#define SYS1_PLL1_OUT 41
+#define SYS1_PLL1_OUT_DIV 42
+#define SYS1_PLL2 43
+#define SYS1_PLL2_DIV 44
+#define SYS1_PLL2_OUT 45
+#define SYS2_PLL1_REF_SEL 46
+#define SYS2_PLL1_REF_DIV 47
+#define SYS2_PLL1 48
+#define SYS2_PLL1_OUT 49
+#define SYS2_PLL1_OUT_DIV 50
+#define SYS2_PLL2 51
+#define SYS2_PLL2_DIV 52
+#define SYS2_PLL2_OUT 53
+#define SYS3_PLL1_REF_SEL 54
+#define SYS3_PLL1_REF_DIV 55
+#define SYS3_PLL1 56
+#define SYS3_PLL1_OUT 57
+#define SYS3_PLL1_OUT_DIV 58
+#define SYS3_PLL2 59
+#define SYS3_PLL2_DIV 60
+#define SYS3_PLL2_OUT 61
+#define DRAM_PLL1_REF_SEL 62
+#define DRAM_PLL1_REF_DIV 63
+#define DRAM_PLL1 64
+#define DRAM_PLL1_OUT 65
+#define DRAM_PLL1_OUT_DIV 66
+#define DRAM_PLL2 67
+#define DRAM_PLL2_DIV 68
+#define DRAM_PLL2_OUT 69
+#define SYS1_PLL_40M 70
+#define SYS1_PLL_80M 71
+#define SYS1_PLL_100M 72
+#define SYS1_PLL_133M 73
+#define SYS1_PLL_160M 74
+#define SYS1_PLL_200M 75
+#define SYS1_PLL_266M 76
+#define SYS1_PLL_400M 77
+#define SYS1_PLL_800M 78
+#define SYS2_PLL_50M 79
+#define SYS2_PLL_100M 80
+#define SYS2_PLL_125M 81
+#define SYS2_PLL_166M 82
+#define SYS2_PLL_200M 83
+#define SYS2_PLL_250M 84
+#define SYS2_PLL_333M 85
+#define SYS2_PLL_500M 86
+#define SYS2_PLL_1000M 87
+#define CLK_A53_SRC 88
+#define CLK_A53_CG 89
+#define CLK_A53_DIV 90
+#define CLK_M4_SRC 91
+#define CLK_M4_CG 92
+#define CLK_M4_DIV 93
+#define CLK_VPU_SRC 94
+#define CLK_VPU_CG 95
+#define CLK_VPU_DIV 96
+#define CLK_GPU_CORE_SRC 97
+#define CLK_GPU_CORE_CG 98
+#define CLK_GPU_CORE_DIV 99
+#define CLK_GPU_SHADER_SRC 100
+#define CLK_GPU_SHADER_CG 101
+#define CLK_GPU_SHADER_DIV 102
+#define CLK_MAIN_AXI 103
+#define CLK_ENET_AXI 104
+#define CLK_NAND_USDHC_BUS 105
+#define CLK_VPU_BUS 106
+#define CLK_DISP_AXI 107
+#define CLK_DISP_APB 108
+#define CLK_DISP_RTRM 109
+#define CLK_USB_BUS 110
+#define CLK_GPU_AXI 111
+#define CLK_GPU_AHB 112
+#define CLK_NOC 113
+#define CLK_NOC_APB 115
+#define CLK_AHB 116
+#define CLK_AUDIO_AHB 117
+#define CLK_DRAM_ALT 118
+#define CLK_DRAM_APB 119
+#define CLK_VPU_G1 120
+#define CLK_VPU_G2 121
+#define CLK_DISP_DTRC 122
+#define CLK_DISP_DC8000 123
+#define CLK_PCIE1_CTRL 124
+#define CLK_PCIE1_PHY 125
+#define CLK_PCIE1_AUX 126
+#define CLK_DC_PIXEL 127
+#define CLK_LCDIF_PIXEL 128
+#define CLK_SAI1 129
+#define CLK_SAI2 130
+#define CLK_SAI3 131
+#define CLK_SAI4 132
+#define CLK_SAI5 133
+#define CLK_SAI6 134
+#define CLK_SPDIF1 135
+#define CLK_SPDIF2 136
+#define CLK_ENET_REF 137
+#define CLK_ENET_TIMER 138
+#define CLK_ENET_PHY_REF 139
+#define CLK_NAND 140
+#define CLK_QSPI 141
+#define CLK_USDHC1 142
+#define CLK_USDHC2 143
+#define CLK_I2C1 144
+#define CLK_I2C2 145
+#define CLK_I2C3 146
+#define CLK_I2C4 147
+#define CLK_UART1 148
+#define CLK_UART2 149
+#define CLK_UART3 150
+#define CLK_UART4 151
+#define CLK_USB_CORE_REF 152
+#define CLK_USB_PHY_REF 153
+#define CLK_ECSPI1 154
+#define CLK_ECSPI2 155
+#define CLK_PWM1 156
+#define CLK_PWM2 157
+#define CLK_PWM3 158
+#define CLK_PWM4 159
+#define CLK_GPT1 160
+#define CLK_WDOG 161
+#define CLK_WRCLK 162
+#define CLK_DSI_CORE 163
+#define CLK_DSI_PHY_REF 164
+#define CLK_DSI_DBI 165
+#define CLK_DSI_ESC 166
+#define CLK_CSI1_CORE 167
+#define CLK_CSI1_PHY_REF 168
+#define CLK_CSI1_ESC 169
+#define CLK_CSI2_CORE 170
+#define CLK_CSI2_PHY_REF 171
+#define CLK_CSI2_ESC 172
+#define CLK_PCIE2_CTRL 173
+#define CLK_PCIE2_PHY 174
+#define CLK_PCIE2_AUX 175
+#define CLK_ECSPI3 176
+#define CLK_A53_ROOT 177
+#define CLK_DRAM_ROOT 178
+#define CLK_ECSPI1_ROOT 179
+#define CLK_ECSPI2_ROOT 180
+#define CLK_ECSPI3_ROOT 181
+#define CLK_ENET1_ROOT 182
+#define CLK_GPT1_ROOT 183
+#define CLK_I2C1_ROOT 184
+#define CLK_I2C2_ROOT 185
+#define CLK_I2C3_ROOT 186
+#define CLK_I2C4_ROOT 187
+#define CLK_M4_ROOT 188
+#define CLK_PCIE1_ROOT 189
+#define CLK_PCIE2_ROOT 190
+#define CLK_PWM1_ROOT 191
+#define CLK_PWM2_ROOT 192
+#define CLK_PWM3_ROOT 193
+#define CLK_PWM4_ROOT 194
+#define CLK_QSPI_ROOT 195
+#define CLK_SAI1_ROOT 196
+#define CLK_SAI2_ROOT 197
+#define CLK_SAI3_ROOT 198
+#define CLK_SAI4_ROOT 199
+#define CLK_SAI5_ROOT 200
+#define CLK_SAI6_ROOT 201
+#define CLK_UART1_ROOT 202
+#define CLK_UART2_ROOT 203
+#define CLK_UART3_ROOT 204
+#define CLK_UART4_ROOT 205
+#define CLK_USB1_CTRL_ROOT 206
+#define CLK_USB2_CTRL_ROOT 207
+#define CLK_USB1_PHY_ROOT 208
+#define CLK_USB2_PHY_ROOT 209
+#define CLK_USDHC1_ROOT 210
+#define CLK_USDHC2_ROOT 211
+#define CLK_WDOG1_ROOT 212
+#define CLK_WDOG2_ROOT 213
+#define CLK_WDOG3_ROOT 214
+#define CLK_GPU_ROOT 215
+#define CLK_HEVC_ROOT 216
+#define CLK_AVC_ROOT 217
+#define CLK_VP9_ROOT 218
+#define CLK_HEVC_INTER_ROOT 219
+#define CLK_DISP_ROOT 220
+#define CLK_HDMI_ROOT 221
+#define CLK_HDMI_PHY_ROOT 222
+#define CLK_VPU_DEC_ROOT 223
+#define CLK_CSI1_ROOT 224
+#define CLK_CSI2_ROOT 225
+#define CLK_RAWNAND_ROOT 226
+#define CLK_SDMA1_ROOT 227
+#define CLK_SDMA2_ROOT 228
+#define CLK_VPU_G1_ROOT 229
+#define CLK_VPU_G2_ROOT 230
+#define SYS1_PLL_OUT 231
+#define SYS2_PLL_OUT 232
+#define SYS3_PLL_OUT 233
+#define DRAM_PLL_OUT 234
+#define GPT_3M_CLK 235
+#define CLK_IPG_ROOT 236
+#define CLK_IPG_AUDIO_ROOT 237
+#define CLK_SAI1_IPG 238
+#define CLK_SAI2_IPG 239
+#define CLK_SAI3_IPG 240
+#define CLK_SAI4_IPG 241
+#define CLK_SAI5_IPG 242
+#define CLK_SAI6_IPG 243
+#define CLK_DSI_AHB 244
+#define CLK_DSI_IPG_DIV 245
+#define CLK_TMU_ROOT 246
+#define CLK_DISP_AXI_ROOT 247
+#define CLK_DISP_APB_ROOT 248
+#define CLK_DISP_RTRM_ROOT 249
+#define CLK_OCOTP_ROOT 250
+#define CLK_DRAM_ALT_ROOT 251
+#define CLK_DRAM_CORE 252
+#define CLK_MU_ROOT 253
+#define VIDEO2_PLL_OUT 254
+#define CLK_CLKO2 255
+#define CLK_NAND_USDHC_BUS_RAWNAND_CLK 256
+#define CLK_CLKO1 257
+#define CLK_ARM 258
+#define CLK_GPIO1_ROOT 259
+#define CLK_GPIO2_ROOT 260
+#define CLK_GPIO3_ROOT 261
+#define CLK_GPIO4_ROOT 262
+#define CLK_GPIO5_ROOT 263
+#define CLK_SNVS_ROOT 264
+#define CLK_GIC 265
+#define VIDEO2_PLL1_REF_SEL 266
+#define SYS1_PLL_40M_CG 267
+#define SYS1_PLL_80M_CG 268
+#define SYS1_PLL_100M_CG 269
+#define SYS1_PLL_133M_CG 270
+#define SYS1_PLL_160M_CG 271
+#define SYS1_PLL_200M_CG 272
+#define SYS1_PLL_266M_CG 273
+#define SYS1_PLL_400M_CG 274
+#define SYS1_PLL_800M_CG 275
+#define SYS2_PLL_50M_CG 276
+#define SYS2_PLL_100M_CG 277
+#define SYS2_PLL_125M_CG 278
+#define SYS2_PLL_166M_CG 279
+#define SYS2_PLL_200M_CG 280
+#define SYS2_PLL_250M_CG 281
+#define SYS2_PLL_333M_CG 282
+#define SYS2_PLL_500M_CG 283
+#define SYS2_PLL_1000M_CG 284
+
+#endif /* !_IMX8MQ_CCM_H */
Index: src/sys/arch/arm/imx/fdt/imx8mq_usbphy.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx8mq_usbphy.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx8mq_usbphy.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,184 @@
+/* $NetBSD: imx8mq_usbphy.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD: imx8mq_usbphy.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/device.h>
+#include <sys/intr.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define PHY_CTL0_ADDR 0x00
+#define REF_SSP_EN __BIT(2)
+
+#define PHY_CTL1_ADDR 0x04
+#define PHY_VDATDATENB0 __BIT(20)
+#define PHY_VDATSRCENB0 __BIT(19)
+#define PHY_ATERESET __BIT(3)
+#define PHY_COMMONONN __BIT(1)
+#define PHY_RESET __BIT(0)
+
+#define PHY_CTL2_ADDR 0x08
+#define PHY_TXENABLEN0 __BIT(8)
+
+static int imx8mq_usbphy_match(device_t, cfdata_t, void *);
+static void imx8mq_usbphy_attach(device_t, device_t, void *);
+
+static const struct of_compat_data compat_data[] = {
+ { "fsl,imx8mq-usb-phy", 0 },
+ { NULL }
+};
+
+struct imx8mq_usbphy_softc {
+ device_t sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ int sc_phandle;
+};
+
+#define PHY_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define PHY_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+CFATTACH_DECL_NEW(imx8mqusbphy, sizeof(struct imx8mq_usbphy_softc),
+ imx8mq_usbphy_match, imx8mq_usbphy_attach, NULL, NULL);
+
+static void *
+imx8mq_usbphy_acquire(device_t dev, const void *data, size_t len)
+{
+ if (len != 0)
+ return NULL;
+
+ return (void *)(uintptr_t)1;
+}
+
+static void
+imx8mq_usbphy_release(device_t dev, void *priv)
+{
+}
+
+static int
+imx8mq_usbphy_enable(device_t dev, void *priv, bool enable)
+{
+ struct imx8mq_usbphy_softc * const sc = device_private(dev);
+ struct fdtbus_regulator *reg;
+ uint32_t val;
+ int error;
+
+ if (enable) {
+ if (of_hasprop(sc->sc_phandle, "vbus-supply")) {
+ reg = fdtbus_regulator_acquire(sc->sc_phandle, "vbus-supply");
+ if (reg != NULL) {
+ error = fdtbus_regulator_enable(reg);
+ if (error != 0)
+ device_printf(dev, "WARNING: couldn't enable vbus-supply: %d\n", error);
+ } else {
+ device_printf(dev, "WARNING: couldn't acquire vbus-supply\n");
+ }
+ }
+
+ val = PHY_READ(sc, PHY_CTL1_ADDR);
+ val &= ~PHY_VDATDATENB0;
+ val &= ~PHY_VDATSRCENB0;
+ val &= ~PHY_COMMONONN;
+ val |= PHY_RESET;
+ val |= PHY_ATERESET;
+ PHY_WRITE(sc, PHY_CTL1_ADDR, val);
+
+ val = PHY_READ(sc, PHY_CTL0_ADDR);
+ val |= REF_SSP_EN;
+ PHY_WRITE(sc, PHY_CTL0_ADDR, val);
+
+ val = PHY_READ(sc, PHY_CTL2_ADDR);
+ val |= PHY_TXENABLEN0;
+ PHY_WRITE(sc, PHY_CTL2_ADDR, val);
+
+ val = PHY_READ(sc, PHY_CTL1_ADDR);
+ val &= ~PHY_RESET;
+ val &= ~PHY_ATERESET;
+ PHY_WRITE(sc, PHY_CTL1_ADDR, val);
+ }
+
+ return 0;
+}
+
+const struct fdtbus_phy_controller_func imx8mq_usbphy_funcs = {
+ .acquire = imx8mq_usbphy_acquire,
+ .release = imx8mq_usbphy_release,
+ .enable = imx8mq_usbphy_enable,
+};
+
+static int
+imx8mq_usbphy_match(device_t parent, cfdata_t cf, void *aux)
+{
+ struct fdt_attach_args * const faa = aux;
+
+ return of_match_compat_data(faa->faa_phandle, compat_data);
+}
+
+static void
+imx8mq_usbphy_attach(device_t parent, device_t self, void *aux)
+{
+ struct imx8mq_usbphy_softc * const sc = device_private(self);
+ struct fdt_attach_args * const faa = aux;
+ const int phandle = faa->faa_phandle;
+ bus_addr_t addr;
+ bus_size_t size;
+
+ sc->sc_dev = self;
+ sc->sc_bst = faa->faa_bst;
+ sc->sc_phandle = phandle;
+
+ if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return;
+ }
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return;
+ }
+
+ /* Enable clocks */
+ fdtbus_clock_assign(phandle);
+ if (fdtbus_clock_enable(phandle, "phy", true) != 0) {
+ aprint_error(": couldn't enable phy clock\n");
+ return;
+ }
+
+ aprint_naive("\n");
+ aprint_normal(": USB PHY\n");
+
+ fdtbus_register_phy_controller(self, phandle, &imx8mq_usbphy_funcs);
+}
Index: src/sys/arch/arm/imx/fdt/imx_ccm.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx_ccm.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx_ccm.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,306 @@
+/* $NetBSD: imx_ccm.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx_ccm.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/imx/fdt/imx_ccm.h>
+
+static struct clk *
+imx_ccm_clock_decode(device_t dev, int cc_phandle, const void *data, size_t len)
+{
+ struct imx_ccm_softc * const sc = device_private(dev);
+ struct imx_ccm_clk *clk;
+
+ if (len != 4)
+ return NULL;
+
+ const u_int clock_id = be32dec(data);
+
+ for (int i = 0; i < sc->sc_nclks; i++) {
+ clk = &sc->sc_clks[i];
+ if (clk->id == clock_id)
+ return &clk->base;
+ }
+
+ return NULL;
+}
+
+static const struct fdtbus_clock_controller_func imx_ccm_fdtclock_funcs = {
+ .decode = imx_ccm_clock_decode,
+};
+
+static struct clk *
+imx_ccm_clock_get(void *priv, const char *name)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk;
+
+ clk = imx_ccm_clock_find(sc, name);
+ if (clk == NULL)
+ return NULL;
+
+ return &clk->base;
+}
+
+static void
+imx_ccm_clock_put(void *priv, struct clk *clk)
+{
+}
+
+static u_int
+imx_ccm_clock_get_rate(void *priv, struct clk *clkp)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk = (struct imx_ccm_clk *)clkp;
+ struct clk *clkp_parent;
+
+ if (clk->get_rate)
+ return clk->get_rate(sc, clk);
+
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL) {
+ aprint_debug("%s: no parent for %s\n", __func__, clk->base.name);
+ return 0;
+ }
+
+ return clk_get_rate(clkp_parent);
+}
+
+static int
+imx_ccm_clock_set_rate(void *priv, struct clk *clkp, u_int rate)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk = (struct imx_ccm_clk *)clkp;
+ struct clk *clkp_parent;
+
+ if (clkp->flags & CLK_SET_RATE_PARENT) {
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL) {
+ aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
+ return ENXIO;
+ }
+ return clk_set_rate(clkp_parent, rate);
+ }
+
+ if (clk->set_rate)
+ return clk->set_rate(sc, clk, rate);
+
+ return ENXIO;
+}
+
+static u_int
+imx_ccm_clock_round_rate(void *priv, struct clk *clkp, u_int rate)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk = (struct imx_ccm_clk *)clkp;
+ struct clk *clkp_parent;
+
+ if (clkp->flags & CLK_SET_RATE_PARENT) {
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL) {
+ aprint_error("%s: no parent for %s\n", __func__, clk->base.name);
+ return 0;
+ }
+ return clk_round_rate(clkp_parent, rate);
+ }
+
+ if (clk->round_rate)
+ return clk->round_rate(sc, clk, rate);
+
+ return 0;
+}
+
+static int
+imx_ccm_clock_enable(void *priv, struct clk *clkp)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk = (struct imx_ccm_clk *)clkp;
+ struct clk *clkp_parent;
+ int error = 0;
+
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent != NULL) {
+ error = clk_enable(clkp_parent);
+ if (error != 0)
+ return error;
+ }
+
+ if (clk->enable)
+ error = clk->enable(sc, clk, 1);
+
+ return error;
+}
+
+static int
+imx_ccm_clock_disable(void *priv, struct clk *clkp)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk = (struct imx_ccm_clk *)clkp;
+ int error = EINVAL;
+
+ if (clk->enable)
+ error = clk->enable(sc, clk, 0);
+
+ return error;
+}
+
+static int
+imx_ccm_clock_set_parent(void *priv, struct clk *clkp,
+ struct clk *clkp_parent)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk = (struct imx_ccm_clk *)clkp;
+
+ if (clk->set_parent == NULL)
+ return EINVAL;
+
+ return clk->set_parent(sc, clk, clkp_parent->name);
+}
+
+static struct clk *
+imx_ccm_clock_get_parent(void *priv, struct clk *clkp)
+{
+ struct imx_ccm_softc * const sc = priv;
+ struct imx_ccm_clk *clk = (struct imx_ccm_clk *)clkp;
+ struct imx_ccm_clk *clk_parent;
+ const char *parent;
+
+ if (clk->get_parent == NULL)
+ return NULL;
+
+ parent = clk->get_parent(sc, clk);
+ if (parent == NULL)
+ return NULL;
+
+ clk_parent = imx_ccm_clock_find(sc, parent);
+ if (clk_parent != NULL)
+ return &clk_parent->base;
+
+ /* No parent in this domain, try FDT */
+ return fdtbus_clock_byname(parent);
+}
+
+static const struct clk_funcs imx_ccm_clock_funcs = {
+ .get = imx_ccm_clock_get,
+ .put = imx_ccm_clock_put,
+ .get_rate = imx_ccm_clock_get_rate,
+ .set_rate = imx_ccm_clock_set_rate,
+ .round_rate = imx_ccm_clock_round_rate,
+ .enable = imx_ccm_clock_enable,
+ .disable = imx_ccm_clock_disable,
+ .set_parent = imx_ccm_clock_set_parent,
+ .get_parent = imx_ccm_clock_get_parent,
+};
+
+struct imx_ccm_clk *
+imx_ccm_clock_find(struct imx_ccm_softc *sc, const char *name)
+{
+ for (int i = 0; i < sc->sc_nclks; i++) {
+ if (sc->sc_clks[i].base.name == NULL)
+ continue;
+ if (strcmp(sc->sc_clks[i].base.name, name) == 0)
+ return &sc->sc_clks[i];
+ }
+
+ return NULL;
+}
+
+int
+imx_ccm_attach(struct imx_ccm_softc *sc)
+{
+ bus_addr_t addr;
+ bus_size_t size;
+ int i;
+
+ if (fdtbus_get_reg(sc->sc_phandle, 0, &addr, &size) != 0) {
+ aprint_error(": couldn't get registers\n");
+ return ENXIO;
+ }
+ if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+ aprint_error(": couldn't map registers\n");
+ return ENXIO;
+ }
+
+ sc->sc_clkdom.name = device_xname(sc->sc_dev);
+ sc->sc_clkdom.funcs = &imx_ccm_clock_funcs;
+ sc->sc_clkdom.priv = sc;
+ for (i = 0; i < sc->sc_nclks; i++) {
+ sc->sc_clks[i].base.domain = &sc->sc_clkdom;
+ clk_attach(&sc->sc_clks[i].base);
+ }
+
+ fdtbus_register_clock_controller(sc->sc_dev, sc->sc_phandle,
+ &imx_ccm_fdtclock_funcs);
+
+ return 0;
+}
+
+void
+imx_ccm_print(struct imx_ccm_softc *sc)
+{
+ struct imx_ccm_clk *clk;
+ struct clk *clkp_parent;
+ const char *type;
+ int i;
+
+ for (i = 0; i < sc->sc_nclks; i++) {
+ clk = &sc->sc_clks[i];
+ if (clk->type == IMX_CCM_UNKNOWN)
+ continue;
+
+ clkp_parent = clk_get_parent(&clk->base);
+
+ switch (clk->type) {
+ case IMX_CCM_EXTCLK: type = "extclk"; break;
+ case IMX_CCM_GATE: type = "gate"; break;
+ case IMX_CCM_COMPOSITE: type = "comp"; break;
+ case IMX_CCM_FIXED: type = "fixed"; break;
+ case IMX_CCM_FIXED_FACTOR: type = "fixed-factor"; break;
+ default: type = "???"; break;
+ }
+
+ aprint_debug_dev(sc->sc_dev,
+ "%3d %-14s %2s %-14s %-7s ",
+ clk->id,
+ clk->base.name,
+ clkp_parent ? "<-" : "",
+ clkp_parent ? clkp_parent->name : "",
+ type);
+ aprint_debug("%10d Hz\n", clk_get_rate(&clk->base));
+ }
+}
Index: src/sys/arch/arm/imx/fdt/imx_ccm.h
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx_ccm.h:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx_ccm.h Wed Jan 15 01:09:56 2020
@@ -0,0 +1,234 @@
+/* $NetBSD: imx_ccm.h,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ARM_IMX_CCM_H
+#define _ARM_IMX_CCM_H
+
+#include <dev/clk/clk_backend.h>
+#include <dev/fdt/syscon.h>
+
+struct imx_ccm_softc;
+struct imx_ccm_clk;
+
+/*
+ * Clocks
+ */
+
+enum imx_ccm_clktype {
+ IMX_CCM_UNKNOWN,
+ IMX_CCM_EXTCLK,
+ IMX_CCM_GATE,
+ IMX_CCM_COMPOSITE,
+ IMX_CCM_FIXED,
+ IMX_CCM_FIXED_FACTOR,
+};
+
+/* External clocks */
+
+int imx_ccm_extclk_enable(struct imx_ccm_softc *, struct imx_ccm_clk *, int);
+u_int imx_ccm_extclk_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
+int imx_ccm_extclk_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
+const char *imx_ccm_extclk_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
+
+#define IMX_EXTCLK(_id, _name) \
+ { \
+ .id = (_id), \
+ .type = IMX_CCM_EXTCLK, \
+ .base.name = (_name), \
+ .base.flags = 0, \
+ .u.extclk = (_name), \
+ .enable = imx_ccm_extclk_enable, \
+ .get_rate = imx_ccm_extclk_get_rate, \
+ .set_rate = imx_ccm_extclk_set_rate, \
+ .get_parent = imx_ccm_extclk_get_parent, \
+ }
+
+/* Gate clocks */
+
+struct imx_ccm_gate {
+ bus_size_t reg;
+ uint32_t mask;
+ const char *parent;
+};
+
+int imx_ccm_gate_enable(struct imx_ccm_softc *,
+ struct imx_ccm_clk *, int);
+const char *imx_ccm_gate_get_parent(struct imx_ccm_softc *,
+ struct imx_ccm_clk *);
+
+#define IMX_GATE(_id, _name, _pname, _reg, _mask) \
+ { \
+ .id = (_id), \
+ .type = IMX_CCM_GATE, \
+ .base.name = (_name), \
+ .base.flags = CLK_SET_RATE_PARENT, \
+ .u.gate.parent = (_pname), \
+ .u.gate.reg = (_reg), \
+ .u.gate.mask = (_mask), \
+ .enable = imx_ccm_gate_enable, \
+ .get_parent = imx_ccm_gate_get_parent, \
+ }
+#define IMX_ROOT_GATE(_id, _name, _pname, _reg) \
+ IMX_GATE(_id, _name, _pname, _reg, __BITS(1,0))
+
+/* Composite clocks */
+
+struct imx_ccm_composite {
+ bus_size_t reg;
+ const char **parents;
+ u_int nparents;
+ u_int flags;
+#define IMX_COMPOSITE_ROUND_DOWN 0x01
+#define IMX_COMPOSITE_SET_RATE_PARENT 0x02
+};
+
+int imx_ccm_composite_enable(struct imx_ccm_softc *, struct imx_ccm_clk *, int);
+u_int imx_ccm_composite_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
+int imx_ccm_composite_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
+const char *imx_ccm_composite_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
+int imx_ccm_composite_set_parent(struct imx_ccm_softc *, struct imx_ccm_clk *, const char *);
+
+#define IMX_COMPOSITE(_id, _name, _parents, _reg, _flags) \
+ { \
+ .id = (_id), \
+ .type = IMX_CCM_COMPOSITE, \
+ .base.name = (_name), \
+ .base.flags = 0, \
+ .u.composite.parents = (_parents), \
+ .u.composite.nparents = __arraycount(_parents), \
+ .u.composite.reg = (_reg), \
+ .u.composite.flags = (_flags), \
+ .enable = imx_ccm_composite_enable, \
+ .get_rate = imx_ccm_composite_get_rate, \
+ .set_rate = imx_ccm_composite_set_rate, \
+ .set_parent = imx_ccm_composite_set_parent, \
+ .get_parent = imx_ccm_composite_get_parent, \
+ }
+
+/* Fixed clocks */
+
+struct imx_ccm_fixed {
+ u_int rate;
+};
+
+u_int imx_ccm_fixed_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
+
+#define IMX_FIXED(_id, _name, _rate) \
+ { \
+ .id = (_id), \
+ .type = IMX_CCM_FIXED, \
+ .base.name = (_name), \
+ .base.flags = 0, \
+ .u.fixed.rate = (_rate), \
+ .get_rate = imx_ccm_fixed_get_rate, \
+ }
+
+/* Fixed factor clocks */
+
+struct imx_ccm_fixed_factor {
+ const char *parent;
+ u_int mult;
+ u_int div;
+};
+
+u_int imx_ccm_fixed_factor_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
+int imx_ccm_fixed_factor_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
+const char *imx_ccm_fixed_factor_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
+
+#define IMX_FIXED_FACTOR(_id, _name, _parent, _mult, _div) \
+ { \
+ .id = (_id), \
+ .type = IMX_CCM_FIXED_FACTOR, \
+ .base.name = (_name), \
+ .base.flags = 0, \
+ .u.fixed_factor.parent = (_parent), \
+ .u.fixed_factor.mult = (_mult), \
+ .u.fixed_factor.div = (_div), \
+ .get_rate = imx_ccm_fixed_factor_get_rate, \
+ .set_rate = imx_ccm_fixed_factor_set_rate, \
+ .get_parent = imx_ccm_fixed_factor_get_parent, \
+ }
+
+/*
+ * IMX clock definition
+ */
+
+struct imx_ccm_clk {
+ struct clk base;
+ u_int id;
+ enum imx_ccm_clktype type;
+ union {
+ struct imx_ccm_gate gate;
+ struct imx_ccm_composite composite;
+ struct imx_ccm_fixed fixed;
+ struct imx_ccm_fixed_factor fixed_factor;
+ const char *extclk;
+ } u;
+
+ int (*enable)(struct imx_ccm_softc *,
+ struct imx_ccm_clk *, int);
+ u_int (*get_rate)(struct imx_ccm_softc *,
+ struct imx_ccm_clk *);
+ int (*set_rate)(struct imx_ccm_softc *,
+ struct imx_ccm_clk *, u_int);
+ u_int (*round_rate)(struct imx_ccm_softc *,
+ struct imx_ccm_clk *, u_int);
+ const char * (*get_parent)(struct imx_ccm_softc *,
+ struct imx_ccm_clk *);
+ int (*set_parent)(struct imx_ccm_softc *,
+ struct imx_ccm_clk *,
+ const char *);
+};
+
+/*
+ * Driver state
+ */
+
+struct imx_ccm_softc {
+ device_t sc_dev;
+ int sc_phandle;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+
+ struct clk_domain sc_clkdom;
+
+ struct imx_ccm_clk *sc_clks;
+ u_int sc_nclks;
+};
+
+int imx_ccm_attach(struct imx_ccm_softc *);
+struct imx_ccm_clk *imx_ccm_clock_find(struct imx_ccm_softc *,
+ const char *);
+void imx_ccm_print(struct imx_ccm_softc *);
+
+#define CCM_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+#define CCM_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+
+#endif /* _ARM_IMX_CCM_H */
Index: src/sys/arch/arm/imx/fdt/imx_ccm_composite.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx_ccm_composite.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx_ccm_composite.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,201 @@
+/* $NetBSD: imx_ccm_composite.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx_ccm_composite.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/imx/fdt/imx_ccm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define CCM_TARGET_ROOT 0x00
+#define TARGET_ROOT_ENABLE __BIT(28)
+#define TARGET_ROOT_MUX __BITS(26,24)
+#define TARGET_ROOT_PRE_PODF __BITS(18,16)
+#define TARGET_ROOT_POST_PODF __BITS(5,0)
+
+int
+imx_ccm_composite_enable(struct imx_ccm_softc *sc, struct imx_ccm_clk *clk,
+ int enable)
+{
+ struct imx_ccm_composite *composite = &clk->u.composite;
+ uint32_t val;
+
+ KASSERT(clk->type == IMX_CCM_COMPOSITE);
+
+ val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
+ if (enable)
+ val |= TARGET_ROOT_ENABLE;
+ else
+ val &= ~TARGET_ROOT_ENABLE;
+ CCM_WRITE(sc, composite->reg + CCM_TARGET_ROOT, val);
+
+ return 0;
+}
+
+u_int
+imx_ccm_composite_get_rate(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct imx_ccm_composite *composite = &clk->u.composite;
+ struct clk *clkp, *clkp_parent;
+
+ KASSERT(clk->type == IMX_CCM_COMPOSITE);
+
+ clkp = &clk->base;
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL)
+ return 0;
+
+ const u_int prate = clk_get_rate(clkp_parent);
+ if (prate == 0)
+ return 0;
+
+ const uint32_t val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
+ const u_int pre_div = __SHIFTOUT(val, TARGET_ROOT_PRE_PODF) + 1;
+ const u_int post_div = __SHIFTOUT(val, TARGET_ROOT_POST_PODF) + 1;
+
+ return prate / pre_div / post_div;
+}
+
+int
+imx_ccm_composite_set_rate(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk, u_int rate)
+{
+ struct imx_ccm_composite *composite = &clk->u.composite;
+ u_int best_prediv, best_postdiv, best_diff;
+ struct imx_ccm_clk *rclk_parent;
+ struct clk *clk_parent;
+ uint32_t val;
+
+ KASSERT(clk->type == IMX_CCM_COMPOSITE);
+
+ if (composite->flags & IMX_COMPOSITE_SET_RATE_PARENT) {
+ clk_parent = clk_get_parent(&clk->base);
+ if (clk_parent == NULL)
+ return ENXIO;
+ return clk_set_rate(clk_parent, rate);
+ }
+
+ best_prediv = 0;
+ best_postdiv = 0;
+ best_diff = INT_MAX;
+
+ val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
+ const u_int mux = __SHIFTOUT(val, TARGET_ROOT_MUX);
+
+ if (mux >= composite->nparents)
+ return EIO;
+
+ rclk_parent = imx_ccm_clock_find(sc, composite->parents[mux]);
+ if (rclk_parent != NULL)
+ clk_parent = &rclk_parent->base;
+ else
+ clk_parent = fdtbus_clock_byname(composite->parents[mux]);
+ if (clk_parent == NULL)
+ return EIO;
+
+ const u_int prate = clk_get_rate(clk_parent);
+ if (prate == 0)
+ return ERANGE;
+
+ for (u_int prediv = 1; prediv <= __SHIFTOUT_MASK(TARGET_ROOT_PRE_PODF) + 1; prediv++) {
+ for (u_int postdiv = 1; postdiv <= __SHIFTOUT_MASK(TARGET_ROOT_POST_PODF) + 1; postdiv++) {
+ const u_int cur_rate = prate / prediv / postdiv;
+ const int diff = (int)rate - (int)cur_rate;
+ if (composite->flags & IMX_COMPOSITE_ROUND_DOWN) {
+ if (diff >= 0 && diff < best_diff) {
+ best_diff = diff;
+ best_prediv = prediv;
+ best_postdiv = postdiv;
+ }
+ } else {
+ if (abs(diff) < best_diff) {
+ best_diff = abs(diff);
+ best_prediv = prediv;
+ best_postdiv = postdiv;
+ }
+ }
+ }
+ }
+ if (best_diff == INT_MAX)
+ return ERANGE;
+
+ val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
+ val &= ~TARGET_ROOT_PRE_PODF;
+ val |= __SHIFTIN(best_prediv - 1, TARGET_ROOT_PRE_PODF);
+ val &= ~TARGET_ROOT_POST_PODF;
+ val |= __SHIFTIN(best_postdiv - 1, TARGET_ROOT_POST_PODF);
+ CCM_WRITE(sc, composite->reg + CCM_TARGET_ROOT, val);
+
+ return 0;
+}
+
+const char *
+imx_ccm_composite_get_parent(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct imx_ccm_composite *composite = &clk->u.composite;
+
+ KASSERT(clk->type == IMX_CCM_COMPOSITE);
+
+ const uint32_t val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
+ const u_int mux = __SHIFTOUT(val, TARGET_ROOT_MUX);
+
+ if (mux >= composite->nparents)
+ return NULL;
+
+ return composite->parents[mux];
+}
+
+int
+imx_ccm_composite_set_parent(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk, const char *parent)
+{
+ struct imx_ccm_composite *composite = &clk->u.composite;
+ uint32_t val;
+
+ KASSERT(clk->type == IMX_CCM_COMPOSITE);
+
+ for (u_int mux = 0; mux < composite->nparents; mux++) {
+ if (strcmp(composite->parents[mux], parent) == 0) {
+ val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
+ val &= ~TARGET_ROOT_MUX;
+ val |= __SHIFTIN(mux, TARGET_ROOT_MUX);
+ CCM_WRITE(sc, composite->reg + CCM_TARGET_ROOT, val);
+ return 0;
+ }
+ }
+
+ return EINVAL;
+}
Index: src/sys/arch/arm/imx/fdt/imx_ccm_extclk.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx_ccm_extclk.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx_ccm_extclk.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,99 @@
+/* $NetBSD: imx_ccm_extclk.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx_ccm_extclk.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/imx/fdt/imx_ccm.h>
+
+#include <dev/fdt/fdtvar.h>
+
+int
+imx_ccm_extclk_enable(struct imx_ccm_softc *sc, struct imx_ccm_clk *clk,
+ int enable)
+{
+ struct clk *extclk;
+
+ KASSERT(clk->type == IMX_CCM_EXTCLK);
+
+ if ((extclk = fdtbus_clock_byname(clk->u.extclk)) == NULL)
+ return ENXIO;
+
+ return clk_enable(extclk);
+}
+
+u_int
+imx_ccm_extclk_get_rate(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct clk *extclk;
+
+ KASSERT(clk->type == IMX_CCM_EXTCLK);
+
+ if ((extclk = fdtbus_clock_byname(clk->u.extclk)) == NULL)
+ return 0;
+
+ return clk_get_rate(extclk);
+}
+
+int
+imx_ccm_extclk_set_rate(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk, u_int rate)
+{
+ struct clk *extclk;
+
+ KASSERT(clk->type == IMX_CCM_EXTCLK);
+
+ if ((extclk = fdtbus_clock_byname(clk->u.extclk)) == NULL)
+ return ENXIO;
+
+ return clk_set_rate(extclk, rate);
+}
+
+const char *
+imx_ccm_extclk_get_parent(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct clk *extclk, *clkp;
+
+ KASSERT(clk->type == IMX_CCM_EXTCLK);
+
+ if ((extclk = fdtbus_clock_byname(clk->u.extclk)) == NULL)
+ return NULL;
+
+ clkp = clk_get_parent(extclk);
+ if (clkp == NULL)
+ return NULL;
+
+ return clkp->name;
+}
Index: src/sys/arch/arm/imx/fdt/imx_ccm_fixed.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx_ccm_fixed.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx_ccm_fixed.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,48 @@
+/* $NetBSD: imx_ccm_fixed.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx_ccm_fixed.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/imx/fdt/imx_ccm.h>
+
+u_int
+imx_ccm_fixed_get_rate(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct imx_ccm_fixed *fixed = &clk->u.fixed;
+
+ KASSERT(clk->type == IMX_CCM_FIXED);
+
+ return fixed->rate;
+}
Index: src/sys/arch/arm/imx/fdt/imx_ccm_fixed_factor.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx_ccm_fixed_factor.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx_ccm_fixed_factor.c Wed Jan 15 01:09:56 2020
@@ -0,0 +1,103 @@
+/* $NetBSD: imx_ccm_fixed_factor.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx_ccm_fixed_factor.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/imx/fdt/imx_ccm.h>
+
+static u_int
+imx_ccm_fixed_factor_get_parent_rate(struct clk *clkp)
+{
+ struct clk *clkp_parent;
+
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL)
+ return 0;
+
+ return clk_get_rate(clkp_parent);
+}
+
+u_int
+imx_ccm_fixed_factor_get_rate(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct imx_ccm_fixed_factor *fixed_factor = &clk->u.fixed_factor;
+ struct clk *clkp = &clk->base;
+
+ KASSERT(clk->type == IMX_CCM_FIXED_FACTOR);
+
+ const u_int p_rate = imx_ccm_fixed_factor_get_parent_rate(clkp);
+ if (p_rate == 0)
+ return 0;
+
+ return (u_int)(((uint64_t)p_rate * fixed_factor->mult) / fixed_factor->div);
+}
+
+static int
+imx_ccm_fixed_factor_set_parent_rate(struct clk *clkp, u_int rate)
+{
+ struct clk *clkp_parent;
+
+ clkp_parent = clk_get_parent(clkp);
+ if (clkp_parent == NULL)
+ return ENXIO;
+
+ return clk_set_rate(clkp_parent, rate);
+}
+
+int
+imx_ccm_fixed_factor_set_rate(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk, u_int rate)
+{
+ struct imx_ccm_fixed_factor *fixed_factor = &clk->u.fixed_factor;
+ struct clk *clkp = &clk->base;
+
+ KASSERT(clk->type == IMX_CCM_FIXED_FACTOR);
+
+ rate *= fixed_factor->div;
+ rate /= fixed_factor->mult;
+
+ return imx_ccm_fixed_factor_set_parent_rate(clkp, rate);
+}
+
+const char *
+imx_ccm_fixed_factor_get_parent(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct imx_ccm_fixed_factor *fixed_factor = &clk->u.fixed_factor;
+
+ KASSERT(clk->type == IMX_CCM_FIXED_FACTOR);
+
+ return fixed_factor->parent;
+}
Index: src/sys/arch/arm/imx/fdt/imx_ccm_gate.c
diff -u /dev/null src/sys/arch/arm/imx/fdt/imx_ccm_gate.c:1.1
--- /dev/null Wed Jan 15 01:09:57 2020
+++ src/sys/arch/arm/imx/fdt/imx_ccm_gate.c Wed Jan 15 01:09:57 2020
@@ -0,0 +1,67 @@
+/* $NetBSD: imx_ccm_gate.c,v 1.1 2020/01/15 01:09:57 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2020 Jared McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: imx_ccm_gate.c,v 1.1 2020/01/15 01:09:57 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include <dev/clk/clk_backend.h>
+
+#include <arm/imx/fdt/imx_ccm.h>
+
+int
+imx_ccm_gate_enable(struct imx_ccm_softc *sc, struct imx_ccm_clk *clk,
+ int enable)
+{
+ struct imx_ccm_gate *gate = &clk->u.gate;
+ uint32_t val;
+
+ KASSERT(clk->type == IMX_CCM_GATE);
+
+ val = CCM_READ(sc, gate->reg);
+ if (enable)
+ val |= gate->mask;
+ else
+ val &= ~gate->mask;
+ CCM_WRITE(sc, gate->reg, val);
+
+ return 0;
+}
+
+const char *
+imx_ccm_gate_get_parent(struct imx_ccm_softc *sc,
+ struct imx_ccm_clk *clk)
+{
+ struct imx_ccm_gate *gate = &clk->u.gate;
+
+ KASSERT(clk->type == IMX_CCM_GATE);
+
+ return gate->parent;
+}