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 <r...@nerv.org> @@ -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 <r...@nerv.org> @@ -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 <r...@nerv.org> @@ -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 <r...@nerv.org> @@ -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 <jmcne...@invisible.ca> @@ -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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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; +}