FDT-ize i.MX7. I don't have a board so this has only been tested on QEMU.

This commit is contained in:
jmcneill 2020-06-10 17:57:50 +00:00
parent 089d36aae0
commit 0b98f54e0a
14 changed files with 1525 additions and 39 deletions

View File

@ -1,30 +1,40 @@
# $NetBSD: files.imx6,v 1.12 2020/06/03 13:14:01 jmcneill Exp $
# $NetBSD: files.imx6,v 1.13 2020/06/10 17:57:50 jmcneill Exp $
#
# Configuration info for the Freescale i.MX6
#
file arch/arm/imx/fdt/imx6_platform.c soc_imx
file arch/arm/imx/fdt/imx7_platform.c soc_imx
# SOC parameters
defflag opt_soc.h SOC_IMX
defflag opt_soc.h SOC_IMX6DL: SOC_IMX
defflag opt_soc.h SOC_IMX6Q: SOC_IMX
defflag opt_soc.h SOC_IMX6QDL: SOC_IMX
defflag opt_soc.h SOC_IMX7D: SOC_IMX
# Clock
device imxccm: clk
attach imxccm at fdt
file arch/arm/imx/imx6_ccm.c imxccm
file arch/arm/imx/fdt/imx6_clk.c imxccm
device imx6ccm: clk
attach imx6ccm at fdt
file arch/arm/imx/imx6_ccm.c imx6ccm
file arch/arm/imx/fdt/imx6_clk.c imx6ccm
# Common FDT clock framework
define imx_ccm: clk
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_div.c imx_ccm
file arch/arm/imx/fdt/imx_ccm_extclk.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
file arch/arm/imx/fdt/imx_ccm_gate.c imx_ccm
file arch/arm/imx/fdt/imx_ccm_mux.c imx_ccm
file arch/arm/imx/fdt/imx_ccm_pll.c imx_ccm
# CCM (iMX7D)
device imx7dccm: imx_ccm
attach imx7dccm at fdt with imx7d_ccm
file arch/arm/imx/fdt/imx7d_ccm.c imx7d_ccm
# CCM (iMX8MQ)
device imx8mqccm: imx_ccm

View File

@ -1,4 +1,4 @@
/* $NetBSD: imx6_clk.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $ */
/* $NetBSD: imx6_clk.c,v 1.2 2020/06/10 17:57:50 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_clk.c,v 1.1 2019/07/24 13:12:33 hkenken Exp $");
__KERNEL_RCSID(0, "$NetBSD: imx6_clk.c,v 1.2 2020/06/10 17:57:50 jmcneill Exp $");
#include "opt_fdt.h"
@ -86,7 +86,7 @@ imx6_clk_fixed_from_fdt(const char *name)
static int imxccm_match(device_t, cfdata_t, void *);
static void imxccm_attach(device_t, device_t, void *);
CFATTACH_DECL_NEW(imxccm, sizeof(struct imxccm_softc),
CFATTACH_DECL_NEW(imx6ccm, sizeof(struct imxccm_softc),
imxccm_match, imxccm_attach, NULL, NULL);
static int

View File

@ -0,0 +1,195 @@
/* $NetBSD: imx7_platform.c,v 1.1 2020/06/10 17:57:50 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_platform.c,v 1.1 2020/06/10 17:57:50 jmcneill Exp $");
#include "opt_console.h"
#include "opt_fdt.h"
#include "opt_multiprocessor.h"
#include "opt_soc.h"
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/cpu.h>
#include <sys/device.h>
#include <sys/termios.h>
#include <dev/fdt/fdtvar.h>
#include <arm/fdt/arm_fdtvar.h>
#include <uvm/uvm_extern.h>
#include <arm/arm32/machdep.h>
#include <machine/bootconfig.h>
#include <arm/cpufunc.h>
#include <arm/cortex/gtmr_var.h>
#include <arm/cortex/gic_reg.h>
#include <arm/imx/imx7reg.h>
#include <arm/imx/imx7_srcreg.h>
#include <arm/imx/imx7_ccmreg.h>
#include <arm/imx/imxuartreg.h>
#include <arm/imx/imxwdogreg.h>
#include <arm/imx/fdt/imx7_platform.h>
#include <libfdt.h>
extern struct bus_space armv7_generic_bs_tag;
extern struct bus_space armv7_generic_a4x_bs_tag;
extern struct arm32_bus_dma_tag arm_generic_dma_tag;
static const struct pmap_devmap *
imx7_platform_devmap(void)
{
static const struct pmap_devmap devmap[] = {
DEVMAP_ENTRY(KERNEL_IO_IOREG_VBASE, IMX7_IOREG_PBASE, IMX7_IOREG_SIZE),
DEVMAP_ENTRY(KERNEL_IO_ARMCORE_VBASE, IMX7_ARMCORE_PBASE, IMX7_ARMCORE_SIZE),
DEVMAP_ENTRY_END
};
return devmap;
}
static void
imx7_platform_init_attach_args(struct fdt_attach_args *faa)
{
faa->faa_bst = &armv7_generic_bs_tag;
faa->faa_a4x_bst = &armv7_generic_a4x_bs_tag;
faa->faa_dmat = &arm_generic_dma_tag;
}
void imx7_platform_early_putchar(char);
void
imx7_platform_early_putchar(char c)
{
#ifdef CONSADDR
#define CONSADDR_VA ((CONSADDR - IMX7_IOREG_PBASE) + KERNEL_IO_IOREG_VBASE)
volatile uint32_t *uartaddr = cpu_earlydevice_va_p() ?
(volatile uint32_t *)CONSADDR_VA :
(volatile uint32_t *)CONSADDR;
while ((le32toh(uartaddr[(IMX_USR2/4)]) & IMX_USR2_TXDC) == 0)
;
uartaddr[(IMX_UTXD/4)] = htole32(c);
#endif
}
static void
imx7_platform_device_register(device_t self, void *aux)
{
prop_dictionary_t prop = device_properties(self);
if (device_is_a(self, "atphy")) {
const char * compat[] = {
"fsl,imx7dl-sabresd",
"fsl,imx7q-sabresd",
"fsl,imx7qp-sabresd",
NULL
};
if (of_match_compatible(OF_finddevice("/"), compat))
prop_dictionary_set_uint32(prop, "clk_25m", 125000000);
}
}
static u_int
imx7_platform_uart_freq(void)
{
return IMX7_OSC_FREQ;
}
static int
imx7_platform_mpstart(void)
{
#if defined(MULTIPROCESSOR)
bus_space_tag_t bst = &armv7_generic_bs_tag;
bus_space_handle_t bsh;
if (bus_space_map(bst, IMX7_IOREG_PBASE + AIPS1_SRC_BASE, AIPS1_SRC_SIZE, 0, &bsh) != 0)
panic("couldn't map aips1 src registers");
const paddr_t mpstart = KERN_VTOPHYS((vaddr_t)cpu_mpstart);
bus_space_write_4(bst, bsh, SRC_GPR3, mpstart);
uint32_t rcr1 = bus_space_read_4(bst, bsh, SRC_A7RCR1);
rcr1 |= SRC_A7RCR1_A7_CORE1_ENABLE;
bus_space_write_4(bst, bsh, SRC_A7RCR1, rcr1);
arm_dsb();
__asm __volatile("sev" ::: "memory");
/* Wait for AP to start */
for (u_int i = 0x1000000; i > 0; i--) {
if (cpu_hatched_p(1))
break;
}
if (!cpu_hatched_p(1))
printf("cpu1: WARNING: failed to start\n");
bus_space_unmap(bst, bsh, AIPS1_SRC_SIZE);
#endif
return 0;
}
static void
imx7_platform_reset(void)
{
bus_space_tag_t bst = &armv7_generic_bs_tag;
bus_space_handle_t bsh;
if (bus_space_map(bst, IMX7_IOREG_PBASE + AIPS1_WDOG1_BASE, AIPS1_WDOG_SIZE, 0, &bsh))
panic("couldn't map wdog1 registers");
delay(1000); /* wait for flushing FIFO of serial console */
cpsid(I32_bit|F32_bit);
/* software reset signal on wdog */
bus_space_write_2(bst, bsh, IMX_WDOG_WCR, WCR_WDE);
for (;;)
__asm("wfi");
}
const struct arm_platform imx7_platform = {
.ap_devmap = imx7_platform_devmap,
.ap_bootstrap = arm_fdt_cpu_bootstrap,
.ap_init_attach_args = imx7_platform_init_attach_args,
.ap_device_register = imx7_platform_device_register,
.ap_reset = imx7_platform_reset,
.ap_delay = gtmr_delay,
.ap_uart_freq = imx7_platform_uart_freq,
.ap_mpstart = imx7_platform_mpstart,
};
ARM_PLATFORM(imx7d, "fsl,imx7d", &imx7_platform);

View File

@ -0,0 +1,35 @@
/* $NetBSD: imx7_platform.h,v 1.1 2020/06/10 17:57:50 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.
*/
#ifndef _ARM_IMX_FDT_IMX7_PLATFORM_H
#define _ARM_IMX_FDT_IMX7_PLATFORM_H
#include <arch/evbarm/fdt/platform.h>
#define KERNEL_IO_IOREG_VBASE KERNEL_IO_VBASE
#define KERNEL_IO_ARMCORE_VBASE (KERNEL_IO_IOREG_VBASE + IMX7_IOREG_SIZE)
#endif /* _ARM_IMX_FDT_IMX7_PLATFORM_H */

View File

@ -0,0 +1,325 @@
/* $NetBSD: imx7d_ccm.c,v 1.1 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@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: imx7d_ccm.c,v 1.1 2020/06/10 17:57:50 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/imx7d_ccm.h>
static int imx7d_ccm_match(device_t, cfdata_t, void *);
static void imx7d_ccm_attach(device_t, device_t, void *);
static const char * const compatible[] = {
"fsl,imx7d-ccm",
NULL
};
static const char * const anatop_compatible[] = {
"fsl,imx7d-anatop",
NULL
};
static const char *pll_bypass_p[] = {
"osc", "dummy"
};
static const char *pll_sys_main_bypass_p[] = {
"pll_sys_main", "pll_sys_main_src"
};
static const char *pll_enet_main_bypass_p[] = {
"pll_enet_main", "pll_enet_main_src"
};
static const char *uart1357_p[] = {
"osc", "pll_sys_main_240m_clk", "pll_enet_40m_clk", "pll_enet_100m_clk", "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", "pll_usb_main_clk"
};
static const char *uart246_p[] = {
"osc", "pll_sys_main_240m_clk", "pll_enet_40m_clk", "pll_enet_100m_clk", "pll_sys_main_clk", "ext_clk_2", "ext_clk_4", "pll_usb_main_clk"
};
static const char *i2c_p[] = {
"osc", "pll_sys_main_120m_clk", "pll_enet_50m_clk", "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div", "pll_usb_main_clk", "pll_sys_pfd2_135m_clk"
};
static const char *enet_axi_p[] = {
"osc", "pll_sys_pfd2_270m_clk", "pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_main_240m_clk", "pll_audio_post_div", "pll_video_post_div", "pll_sys_pfd4_clk"
};
static const char *enet_time_p[] = {
"osc", "pll_enet_100m_clk", "pll_audio_post_div", "ext_clk_1", "ext_clk_2", "ext_clk_3", "ext_clk_4", "pll_video_post_div"
};
static const char *enet_phy_ref_p[] = {
"osc", "pll_enet_25m_clk", "pll_enet_50m_clk", "pll_enet_125m_clk", "pll_dram_533m_clk", "pll_audio_post_div", "pll_video_post_div", "pll_sys_pfd3_clk"
};
static const char *ahb_channel_p[] = {
"osc", "pll_sys_pfd2_270m_clk", "pll_dram_533m_clk", "pll_sys_pfd0_392m_clk", "pll_enet_250m_clk", "pll_usb_main_clk", "pll_audio_post_div", "pll_video_post_div"
};
static const char *nand_usdhc_p[] = {
"osc", "pll_sys_pfd2_270m_clk", "pll_dram_533m_clk", "pll_sys_main_240m_clk", "pll_sys_pfd2_135m_clk", "pll_sys_pfd6_clk", "pll_enet_250m_clk", "pll_audio_post_div"
};
static const char *usdhc_p[] = {
"osc", "pll_sys_pfd0_392m_clk", "pll_dram_533m_clk", "pll_enet_500m_clk", "pll_sys_pfd4_clk", "pll_sys_pfd2_270m_clk", "pll_sys_pfd6_clk", "pll_sys_pfd7_clk"
};
CFATTACH_DECL_NEW(imx7d_ccm, sizeof(struct imx_ccm_softc),
imx7d_ccm_match, imx7d_ccm_attach, NULL, NULL);
enum {
REGIDX_CCM = 0,
REGIDX_ANATOP = 1,
};
#define ANATOP_MUX(_id, _name, _parents, _reg, _mask) \
IMX_MUX_INDEX(_id, REGIDX_ANATOP, _name, _parents, _reg, _mask)
#define ANATOP_GATE(_id, _name, _parent, _reg, _mask) \
IMX_GATE_INDEX(_id, REGIDX_ANATOP, _name, _parent, _reg, _mask)
#define ANATOP_PLL(_id, _name, _parent, _reg, _div_mask, _flags) \
IMX_PLL_INDEX(_id, REGIDX_ANATOP, _name, _parent, _reg, _div_mask, _flags)
static struct imx_ccm_clk imx7d_ccm_clks[] = {
IMX_FIXED(CLK_DUMMY, "dummy", 0),
IMX_EXTCLK(CKIL, "ckil"),
IMX_EXTCLK(OSC_24M_CLK, "osc"),
/*
* CCM_ANALOG
*/
ANATOP_MUX(PLL_SYS_MAIN_SRC, "pll_sys_main_src", pll_bypass_p, 0xb0, __BITS(15,14)),
ANATOP_MUX(PLL_ENET_MAIN_SRC, "pll_enet_main_src", pll_bypass_p, 0xe0, __BITS(15,14)),
ANATOP_PLL(PLL_SYS_MAIN, "pll_sys_main", "osc", 0xb0, __BIT(0), IMX_PLL_480M_528M),
ANATOP_PLL(PLL_ENET_MAIN, "pll_enet_main", "osc", 0xe0, 1000000000, IMX_PLL_ENET),
ANATOP_MUX(PLL_SYS_MAIN_BYPASS, "pll_sys_main_bypass", pll_sys_main_bypass_p, 0xb0, __BIT(16)),
ANATOP_MUX(PLL_ENET_MAIN_BYPASS, "pll_enet_main_bypass", pll_enet_main_bypass_p, 0xe0, __BIT(16)),
ANATOP_GATE(PLL_SYS_MAIN_CLK, "pll_sys_main_clk", "pll_sys_main_bypass", 0xb0, __BIT(13)),
IMX_FIXED_FACTOR(PLL_SYS_MAIN_240M, "pll_sys_main_240m", "pll_sys_main_clk", 1, 2),
ANATOP_GATE(PLL_SYS_MAIN_240M_CLK, "pll_sys_main_240m_clk", "pll_sys_main_240m", 0xb0, __BIT(5)),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_CLK, "pll_enet_main_clk", "pll_enet_main_bypass", 1, 1),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_500M, "pll_enet_500m", "pll_enet_main_clk", 1, 2),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_250M, "pll_enet_250m", "pll_enet_main_clk", 1, 4),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_125M, "pll_enet_125m", "pll_enet_main_clk", 1, 8),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_100M, "pll_enet_100m", "pll_enet_main_clk", 1, 10),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_50M, "pll_enet_50m", "pll_enet_main_clk", 1, 20),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_40M, "pll_enet_40m", "pll_enet_main_clk", 1, 25),
IMX_FIXED_FACTOR(PLL_ENET_MAIN_25M, "pll_enet_25m", "pll_enet_main_clk", 1, 40),
ANATOP_GATE(PLL_ENET_MAIN_500M_CLK, "pll_enet_500m_clk", "pll_enet_500m", 0xe0, __BIT(12)),
ANATOP_GATE(PLL_ENET_MAIN_250M_CLK, "pll_enet_250m_clk", "pll_enet_250m", 0xe0, __BIT(11)),
ANATOP_GATE(PLL_ENET_MAIN_250M_CLK, "pll_enet_250m_clk", "pll_enet_250m", 0xe0, __BIT(11)),
ANATOP_GATE(PLL_ENET_MAIN_125M_CLK, "pll_enet_125m_clk", "pll_enet_125m", 0xe0, __BIT(10)),
ANATOP_GATE(PLL_ENET_MAIN_100M_CLK, "pll_enet_100m_clk", "pll_enet_100m", 0xe0, __BIT(9)),
ANATOP_GATE(PLL_ENET_MAIN_50M_CLK, "pll_enet_50m_clk", "pll_enet_50m", 0xe0, __BIT(8)),
ANATOP_GATE(PLL_ENET_MAIN_40M_CLK, "pll_enet_40m_clk", "pll_enet_40m", 0xe0, __BIT(7)),
ANATOP_GATE(PLL_ENET_MAIN_25M_CLK, "pll_enet_25m_clk", "pll_enet_25m", 0xe0, __BIT(6)),
IMX_FIXED_FACTOR(USB1_MAIN_480M_CLK, "pll_usb1_main_clk", "osc", 20, 1),
IMX_FIXED_FACTOR(USB_MAIN_480M_CLK, "pll_usb_main_clk", "osc", 20, 1),
/*
* CCM (regidx=0)
*/
IMX_MUX(UART1_ROOT_SRC, "uart1_src", uart1357_p, 0xaf80, __BITS(26,24)),
IMX_MUX(UART2_ROOT_SRC, "uart2_src", uart246_p, 0xb000, __BITS(26,24)),
IMX_MUX(UART3_ROOT_SRC, "uart3_src", uart1357_p, 0xb080, __BITS(26,24)),
IMX_MUX(UART4_ROOT_SRC, "uart4_src", uart246_p, 0xb100, __BITS(26,24)),
IMX_MUX(UART5_ROOT_SRC, "uart5_src", uart1357_p, 0xb180, __BITS(26,24)),
IMX_MUX(UART6_ROOT_SRC, "uart6_src", uart246_p, 0xb200, __BITS(26,24)),
IMX_MUX(UART7_ROOT_SRC, "uart7_src", uart1357_p, 0xb280, __BITS(26,24)),
IMX_GATE(UART1_ROOT_CG, "uart1_cg", "uart1_src", 0xaf80, __BIT(18)),
IMX_GATE(UART2_ROOT_CG, "uart2_cg", "uart2_src", 0xb000, __BIT(18)),
IMX_GATE(UART3_ROOT_CG, "uart3_cg", "uart3_src", 0xb080, __BIT(18)),
IMX_GATE(UART4_ROOT_CG, "uart4_cg", "uart4_src", 0xb100, __BIT(18)),
IMX_GATE(UART5_ROOT_CG, "uart5_cg", "uart5_src", 0xb180, __BIT(18)),
IMX_GATE(UART6_ROOT_CG, "uart6_cg", "uart6_src", 0xb200, __BIT(18)),
IMX_GATE(UART7_ROOT_CG, "uart7_cg", "uart7_src", 0xb280, __BIT(18)),
IMX_DIV(UART1_ROOT_PRE_DIV, "uart1_pre_div", "uart1_cg", 0xaf80, __BITS(18,16), 0),
IMX_DIV(UART2_ROOT_PRE_DIV, "uart2_pre_div", "uart2_cg", 0xb000, __BITS(18,16), 0),
IMX_DIV(UART3_ROOT_PRE_DIV, "uart3_pre_div", "uart3_cg", 0xb080, __BITS(18,16), 0),
IMX_DIV(UART4_ROOT_PRE_DIV, "uart4_pre_div", "uart4_cg", 0xb100, __BITS(18,16), 0),
IMX_DIV(UART5_ROOT_PRE_DIV, "uart5_pre_div", "uart5_cg", 0xb100, __BITS(18,16), 0),
IMX_DIV(UART6_ROOT_PRE_DIV, "uart6_pre_div", "uart6_cg", 0xb200, __BITS(18,16), 0),
IMX_DIV(UART7_ROOT_PRE_DIV, "uart7_pre_div", "uart7_cg", 0xb280, __BITS(18,16), 0),
IMX_DIV(UART1_ROOT_DIV, "uart1_post_div", "uart1_pre_div", 0xaf80, __BITS(5,0), 0),
IMX_DIV(UART2_ROOT_DIV, "uart2_post_div", "uart2_pre_div", 0xb000, __BITS(5,0), 0),
IMX_DIV(UART3_ROOT_DIV, "uart3_post_div", "uart3_pre_div", 0xb080, __BITS(5,0), 0),
IMX_DIV(UART4_ROOT_DIV, "uart4_post_div", "uart4_pre_div", 0xb100, __BITS(5,0), 0),
IMX_DIV(UART5_ROOT_DIV, "uart5_post_div", "uart5_pre_div", 0xb100, __BITS(5,0), 0),
IMX_DIV(UART6_ROOT_DIV, "uart6_post_div", "uart6_pre_div", 0xb200, __BITS(5,0), 0),
IMX_DIV(UART7_ROOT_DIV, "uart7_post_div", "uart7_pre_div", 0xb280, __BITS(5,0), 0),
IMX_GATE(UART1_ROOT_CLK, "uart1_root_clk", "uart1_post_div", 0x4940, __BIT(0)),
IMX_GATE(UART2_ROOT_CLK, "uart2_root_clk", "uart2_post_div", 0x4950, __BIT(0)),
IMX_GATE(UART3_ROOT_CLK, "uart3_root_clk", "uart3_post_div", 0x4960, __BIT(0)),
IMX_GATE(UART4_ROOT_CLK, "uart4_root_clk", "uart4_post_div", 0x4970, __BIT(0)),
IMX_GATE(UART5_ROOT_CLK, "uart5_root_clk", "uart5_post_div", 0x4980, __BIT(0)),
IMX_GATE(UART6_ROOT_CLK, "uart6_root_clk", "uart6_post_div", 0x4990, __BIT(0)),
IMX_GATE(UART7_ROOT_CLK, "uart7_root_clk", "uart7_post_div", 0x49a0, __BIT(0)),
IMX_MUX(I2C1_ROOT_SRC, "i2c1_src", i2c_p, 0xad80, __BITS(26,24)),
IMX_MUX(I2C2_ROOT_SRC, "i2c2_src", i2c_p, 0xae00, __BITS(26,24)),
IMX_MUX(I2C3_ROOT_SRC, "i2c3_src", i2c_p, 0xae80, __BITS(26,24)),
IMX_MUX(I2C4_ROOT_SRC, "i2c4_src", i2c_p, 0xaf00, __BITS(26,24)),
IMX_GATE(I2C1_ROOT_CG, "i2c1_cg", "i2c1_src", 0xad80, __BIT(0)),
IMX_GATE(I2C2_ROOT_CG, "i2c2_cg", "i2c2_src", 0xae00, __BIT(0)),
IMX_GATE(I2C3_ROOT_CG, "i2c3_cg", "i2c3_src", 0xae80, __BIT(0)),
IMX_GATE(I2C4_ROOT_CG, "i2c4_cg", "i2c4_src", 0xaf00, __BIT(0)),
IMX_DIV(I2C1_ROOT_PRE_DIV, "i2c1_pre_div", "i2c1_cg", 0xad80, __BITS(18,16), 0),
IMX_DIV(I2C2_ROOT_PRE_DIV, "i2c2_pre_div", "i2c2_cg", 0xae00, __BITS(18,16), 0),
IMX_DIV(I2C3_ROOT_PRE_DIV, "i2c3_pre_div", "i2c3_cg", 0xae80, __BITS(18,16), 0),
IMX_DIV(I2C4_ROOT_PRE_DIV, "i2c4_pre_div", "i2c4_cg", 0xaf00, __BITS(18,16), 0),
IMX_DIV(I2C1_ROOT_DIV, "i2c1_post_div", "i2c1_pre_div", 0xad80, __BITS(5,0), 0),
IMX_DIV(I2C2_ROOT_DIV, "i2c2_post_div", "i2c2_pre_div", 0xae00, __BITS(5,0), 0),
IMX_DIV(I2C3_ROOT_DIV, "i2c3_post_div", "i2c3_pre_div", 0xae80, __BITS(5,0), 0),
IMX_DIV(I2C4_ROOT_DIV, "i2c4_post_div", "i2c4_pre_div", 0xaf00, __BITS(5,0), 0),
IMX_GATE(I2C1_ROOT_CLK, "i2c1_root_clk", "i2c1_post_div", 0x4880, __BIT(0)),
IMX_GATE(I2C2_ROOT_CLK, "i2c2_root_clk", "i2c2_post_div", 0x4890, __BIT(0)),
IMX_GATE(I2C3_ROOT_CLK, "i2c3_root_clk", "i2c3_post_div", 0x48a0, __BIT(0)),
IMX_GATE(I2C4_ROOT_CLK, "i2c4_root_clk", "i2c4_post_div", 0x48b0, __BIT(0)),
IMX_MUX(ENET_AXI_ROOT_SRC, "enet_axi_src", enet_axi_p, 0x8900, __BITS(26,24)),
IMX_GATE(ENET_AXI_ROOT_CG, "enet_axi_cg", "enet_axi_src", 0x8900, __BIT(28)),
IMX_DIV(ENET_AXI_ROOT_PRE_DIV, "enet_axi_pre_div", "enet_axi_cg", 0x8900, __BITS(18,16), 0),
IMX_DIV(ENET_AXI_ROOT_DIV, "enet_axi_post_div", "enet_axi_pre_div", 0x8900, __BITS(5,0), 0),
IMX_MUX(ENET1_TIME_ROOT_SRC, "enet1_time_src", enet_time_p, 0xa780, __BITS(26,24)),
IMX_MUX(ENET2_TIME_ROOT_SRC, "enet2_time_src", enet_time_p, 0xa880, __BITS(26,24)),
IMX_GATE(ENET1_TIME_ROOT_CG, "enet1_time_cg", "enet1_time_src", 0xa780, __BIT(28)),
IMX_GATE(ENET2_TIME_ROOT_CG, "enet2_time_cg", "enet2_time_src", 0xa880, __BIT(28)),
IMX_DIV(ENET1_TIME_ROOT_PRE_DIV, "enet1_time_pre_div", "enet1_time_cg", 0xa780, __BITS(18,16), 0),
IMX_DIV(ENET2_TIME_ROOT_PRE_DIV, "enet2_time_pre_div", "enet2_time_cg", 0xa880, __BITS(18,16), 0),
IMX_DIV(ENET1_TIME_ROOT_DIV, "enet1_time_post_div", "enet1_time_pre_div", 0xa780, __BITS(5,0), 0),
IMX_DIV(ENET2_TIME_ROOT_DIV, "enet2_time_post_div", "enet2_time_pre_div", 0xa880, __BITS(5,0), 0),
IMX_GATE(ENET1_IPG_ROOT_CLK, "enet1_ipg_root_clk", "enet_axi_post_div", 0x4700, __BIT(0)),
IMX_GATE(ENET2_IPG_ROOT_CLK, "enet2_ipg_root_clk", "enet_axi_post_div", 0x4710, __BIT(0)),
IMX_GATE(ENET1_TIME_ROOT_CLK, "enet1_time_root_clk", "enet1_time_post_div", 0x4700, __BIT(0)),
IMX_GATE(ENET2_TIME_ROOT_CLK, "enet2_time_root_clk", "enet2_time_post_div", 0x4710, __BIT(0)),
IMX_GATE(ENET_AXI_ROOT_CLK, "enet_axi_root_clk", "enet_axi_post_div", 0x4060, __BIT(0)),
IMX_MUX(ENET_PHY_REF_ROOT_SRC, "enet_phy_ref_src", enet_phy_ref_p, 0xa900, __BITS(26,24)),
IMX_GATE(ENET_PHY_REF_ROOT_CG, "enet_phy_ref_cg", "enet_phy_ref_src", 0xa900, __BIT(28)),
IMX_DIV(ENET_PHY_REF_ROOT_PRE_DIV, "enet_phy_ref_pre_div", "enet_phy_ref_cg", 0xa900, __BITS(18,16), 0),
IMX_DIV(ENET_PHY_REF_ROOT_CLK, "enet_phy_ref_root_clk", "enet_phy_ref_pre_div", 0xa900, __BITS(5,0), 0),
IMX_MUX(AHB_CHANNEL_ROOT_SRC, "ahb_src", ahb_channel_p, 0x9000, __BITS(26,24)),
IMX_GATE(AHB_CHANNEL_ROOT_CG, "ahb_cg", "ahb_src", 0x9000, __BIT(28)),
IMX_DIV(AHB_CHANNEL_ROOT_PRE_DIV, "ahb_pre_div", "ahb_cg", 0x9000, __BITS(18,16), 0),
IMX_DIV(AHB_CHANNEL_ROOT_DIV, "ahb_root_clk", "ahb_pre_div", 0x9000, __BITS(5,0), 0),
IMX_DIV(IPG_ROOT_CLK, "ipg_root_clk", "ahb_root_clk", 0x9080, __BITS(1,0), IMX_DIV_SET_RATE_PARENT),
IMX_MUX(NAND_USDHC_BUS_ROOT_SRC, "nand_usdhc_src", nand_usdhc_p, 0x8980, __BITS(26,24)),
IMX_GATE(NAND_USDHC_BUS_ROOT_CG, "nand_usdhc_cg", "nand_usdhc_src", 0x8980, __BIT(28)),
IMX_DIV(NAND_USDHC_BUS_ROOT_PRE_DIV, "nand_usdhc_pre_div", "nand_usdhc_cg", 0x8980, __BITS(18,16), 0),
IMX_DIV(NAND_USDHC_BUS_ROOT_CLK, "nand_usdhc_root_clk", "nand_usdhc_pre_div", 0x8980, __BITS(5,0), 0),
IMX_MUX(USDHC1_ROOT_SRC, "usdhc1_src", usdhc_p, 0xab00, __BITS(26,24)),
IMX_MUX(USDHC2_ROOT_SRC, "usdhc2_src", usdhc_p, 0xab80, __BITS(26,24)),
IMX_MUX(USDHC3_ROOT_SRC, "usdhc3_src", usdhc_p, 0xac00, __BITS(26,24)),
IMX_GATE(USDHC1_ROOT_CG, "usdhc1_cg", "usdhc1_src", 0xab00, __BIT(28)),
IMX_GATE(USDHC2_ROOT_CG, "usdhc2_cg", "usdhc2_src", 0xab80, __BIT(28)),
IMX_GATE(USDHC3_ROOT_CG, "usdhc3_cg", "usdhc3_src", 0xac00, __BIT(28)),
IMX_DIV(USDHC1_ROOT_PRE_DIV, "usdhc1_pre_div", "usdhc1_cg", 0xab00, __BITS(18,16), 0),
IMX_DIV(USDHC1_ROOT_PRE_DIV, "usdhc2_pre_div", "usdhc2_cg", 0xab80, __BITS(18,16), 0),
IMX_DIV(USDHC1_ROOT_PRE_DIV, "usdhc3_pre_div", "usdhc3_cg", 0xac00, __BITS(18,16), 0),
IMX_DIV(USDHC1_ROOT_DIV, "usdhc1_post_div", "usdhc1_pre_div", 0xab00, __BITS(5,0), 0),
IMX_DIV(USDHC2_ROOT_DIV, "usdhc2_post_div", "usdhc2_pre_div", 0xab80, __BITS(5,0), 0),
IMX_DIV(USDHC3_ROOT_DIV, "usdhc3_post_div", "usdhc3_pre_div", 0xac00, __BITS(5,0), 0),
IMX_GATE(USDHC1_ROOT_CLK, "usdhc1_root_clk", "usdhc1_post_div", 0x46c0, __BIT(0)),
IMX_GATE(USDHC2_ROOT_CLK, "usdhc2_root_clk", "usdhc2_post_div", 0x46d0, __BIT(0)),
IMX_GATE(USDHC3_ROOT_CLK, "usdhc3_root_clk", "usdhc3_post_div", 0x46e0, __BIT(0)),
};
static int
imx7d_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
imx7d_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;
const int phandle = faa->faa_phandle;
bus_addr_t anatop_addr;
bus_size_t anatop_size;
int anatop = -1, child;
sc->sc_dev = self;
sc->sc_phandle = phandle;
sc->sc_bst = faa->faa_bst;
sc->sc_clks = imx7d_ccm_clks;
sc->sc_nclks = __arraycount(imx7d_ccm_clks);
for (child = OF_child(OF_parent(phandle)); child; child = OF_peer(child)) {
if (of_match_compatible(child, anatop_compatible) > 0) {
anatop = child;
break;
}
}
if (anatop == -1) {
aprint_error(": couldn't find anatop node\n");
return;
}
if (fdtbus_get_reg(anatop, 0, &anatop_addr, &anatop_size) != 0) {
aprint_error(": couldn't get anatop registers\n");
return;
}
if (bus_space_map(sc->sc_bst, anatop_addr, anatop_size, 0, &sc->sc_bsh[REGIDX_ANATOP]) != 0) {
aprint_error(": couldn't map anatop registers\n");
return;
}
if (imx_ccm_attach(sc) != 0)
return;
aprint_naive("\n");
aprint_normal(": Clock Control Module\n");
imx_ccm_print(sc);
}

View File

@ -0,0 +1,482 @@
/* $NetBSD: imx7d_ccm.h,v 1.1 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@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 _IMX7D_CCM_H
#define _IMX7D_CCM_H
/*
* Clocks
*/
#define OSC_24M_CLK 0
#define PLL_ARM_MAIN 1
#define PLL_ARM_MAIN_CLK 2
#define PLL_ARM_MAIN_SRC 3
#define PLL_ARM_MAIN_BYPASS 4
#define PLL_SYS_MAIN 5
#define PLL_SYS_MAIN_CLK 6
#define PLL_SYS_MAIN_SRC 7
#define PLL_SYS_MAIN_BYPASS 8
#define PLL_SYS_MAIN_480M 9
#define PLL_SYS_MAIN_240M 10
#define PLL_SYS_MAIN_120M 11
#define PLL_SYS_MAIN_480M_CLK 12
#define PLL_SYS_MAIN_240M_CLK 13
#define PLL_SYS_MAIN_120M_CLK 14
#define PLL_SYS_PFD0_392M_CLK 15
#define PLL_SYS_PFD0_196M 16
#define PLL_SYS_PFD0_196M_CLK 17
#define PLL_SYS_PFD1_332M_CLK 18
#define PLL_SYS_PFD1_166M 19
#define PLL_SYS_PFD1_166M_CLK 20
#define PLL_SYS_PFD2_270M_CLK 21
#define PLL_SYS_PFD2_135M 22
#define PLL_SYS_PFD2_135M_CLK 23
#define PLL_SYS_PFD3_CLK 24
#define PLL_SYS_PFD4_CLK 25
#define PLL_SYS_PFD5_CLK 26
#define PLL_SYS_PFD6_CLK 27
#define PLL_SYS_PFD7_CLK 28
#define PLL_ENET_MAIN 29
#define PLL_ENET_MAIN_CLK 30
#define PLL_ENET_MAIN_SRC 31
#define PLL_ENET_MAIN_BYPASS 32
#define PLL_ENET_MAIN_500M 33
#define PLL_ENET_MAIN_250M 34
#define PLL_ENET_MAIN_125M 35
#define PLL_ENET_MAIN_100M 36
#define PLL_ENET_MAIN_50M 37
#define PLL_ENET_MAIN_40M 38
#define PLL_ENET_MAIN_25M 39
#define PLL_ENET_MAIN_500M_CLK 40
#define PLL_ENET_MAIN_250M_CLK 41
#define PLL_ENET_MAIN_125M_CLK 42
#define PLL_ENET_MAIN_100M_CLK 43
#define PLL_ENET_MAIN_50M_CLK 44
#define PLL_ENET_MAIN_40M_CLK 45
#define PLL_ENET_MAIN_25M_CLK 46
#define PLL_DRAM_MAIN 47
#define PLL_DRAM_MAIN_CLK 48
#define PLL_DRAM_MAIN_SRC 49
#define PLL_DRAM_MAIN_BYPASS 50
#define PLL_DRAM_MAIN_533M 51
#define PLL_DRAM_MAIN_533M_CLK 52
#define PLL_AUDIO_MAIN 53
#define PLL_AUDIO_MAIN_CLK 54
#define PLL_AUDIO_MAIN_SRC 55
#define PLL_AUDIO_MAIN_BYPASS 56
#define PLL_VIDEO_MAIN_CLK 57
#define PLL_VIDEO_MAIN 58
#define PLL_VIDEO_MAIN_SRC 59
#define PLL_VIDEO_MAIN_BYPASS 60
#define USB_MAIN_480M_CLK 61
#define ARM_A7_ROOT_CLK 62
#define ARM_A7_ROOT_SRC 63
#define ARM_A7_ROOT_CG 64
#define ARM_A7_ROOT_DIV 65
#define ARM_M4_ROOT_CLK 66
#define ARM_M4_ROOT_SRC 67
#define ARM_M4_ROOT_CG 68
#define ARM_M4_ROOT_DIV 69
#define ARM_M0_ROOT_CLK 70
#define ARM_M0_ROOT_SRC 71
#define ARM_M0_ROOT_CG 72
#define ARM_M0_ROOT_DIV 73
#define MAIN_AXI_ROOT_CLK 74
#define MAIN_AXI_ROOT_SRC 75
#define MAIN_AXI_ROOT_CG 76
#define MAIN_AXI_ROOT_DIV 77
#define DISP_AXI_ROOT_CLK 78
#define DISP_AXI_ROOT_SRC 79
#define DISP_AXI_ROOT_CG 80
#define DISP_AXI_ROOT_DIV 81
#define ENET_AXI_ROOT_CLK 82
#define ENET_AXI_ROOT_SRC 83
#define ENET_AXI_ROOT_CG 84
#define ENET_AXI_ROOT_DIV 85
#define NAND_USDHC_BUS_ROOT_CLK 86
#define NAND_USDHC_BUS_ROOT_SRC 87
#define NAND_USDHC_BUS_ROOT_CG 88
#define NAND_USDHC_BUS_ROOT_DIV 89
#define AHB_CHANNEL_ROOT_CLK 90
#define AHB_CHANNEL_ROOT_SRC 91
#define AHB_CHANNEL_ROOT_CG 92
#define AHB_CHANNEL_ROOT_DIV 93
#define DRAM_PHYM_ROOT_CLK 94
#define DRAM_PHYM_ROOT_SRC 95
#define DRAM_PHYM_ROOT_CG 96
#define DRAM_PHYM_ROOT_DIV 97
#define DRAM_ROOT_CLK 98
#define DRAM_ROOT_SRC 99
#define DRAM_ROOT_CG 100
#define DRAM_ROOT_DIV 101
#define DRAM_PHYM_ALT_ROOT_CLK 102
#define DRAM_PHYM_ALT_ROOT_SRC 103
#define DRAM_PHYM_ALT_ROOT_CG 104
#define DRAM_PHYM_ALT_ROOT_DIV 105
#define DRAM_ALT_ROOT_CLK 106
#define DRAM_ALT_ROOT_SRC 107
#define DRAM_ALT_ROOT_CG 108
#define DRAM_ALT_ROOT_DIV 109
#define USB_HSIC_ROOT_CLK 110
#define USB_HSIC_ROOT_SRC 111
#define USB_HSIC_ROOT_CG 112
#define USB_HSIC_ROOT_DIV 113
#define PCIE_CTRL_ROOT_CLK 114
#define PCIE_CTRL_ROOT_SRC 115
#define PCIE_CTRL_ROOT_CG 116
#define PCIE_CTRL_ROOT_DIV 117
#define PCIE_PHY_ROOT_CLK 118
#define PCIE_PHY_ROOT_SRC 119
#define PCIE_PHY_ROOT_CG 120
#define PCIE_PHY_ROOT_DIV 121
#define EPDC_PIXEL_ROOT_CLK 122
#define EPDC_PIXEL_ROOT_SRC 123
#define EPDC_PIXEL_ROOT_CG 124
#define EPDC_PIXEL_ROOT_DIV 125
#define LCDIF_PIXEL_ROOT_CLK 126
#define LCDIF_PIXEL_ROOT_SRC 127
#define LCDIF_PIXEL_ROOT_CG 128
#define LCDIF_PIXEL_ROOT_DIV 129
#define MIPI_DSI_ROOT_CLK 130
#define MIPI_DSI_ROOT_SRC 131
#define MIPI_DSI_ROOT_CG 132
#define MIPI_DSI_ROOT_DIV 133
#define MIPI_CSI_ROOT_CLK 134
#define MIPI_CSI_ROOT_SRC 135
#define MIPI_CSI_ROOT_CG 136
#define MIPI_CSI_ROOT_DIV 137
#define MIPI_DPHY_ROOT_CLK 138
#define MIPI_DPHY_ROOT_SRC 139
#define MIPI_DPHY_ROOT_CG 140
#define MIPI_DPHY_ROOT_DIV 141
#define SAI1_ROOT_CLK 142
#define SAI1_ROOT_SRC 143
#define SAI1_ROOT_CG 144
#define SAI1_ROOT_DIV 145
#define SAI2_ROOT_CLK 146
#define SAI2_ROOT_SRC 147
#define SAI2_ROOT_CG 148
#define SAI2_ROOT_DIV 149
#define SAI3_ROOT_CLK 150
#define SAI3_ROOT_SRC 151
#define SAI3_ROOT_CG 152
#define SAI3_ROOT_DIV 153
#define SPDIF_ROOT_CLK 154
#define SPDIF_ROOT_SRC 155
#define SPDIF_ROOT_CG 156
#define SPDIF_ROOT_DIV 157
#define ENET1_IPG_ROOT_CLK 158
#define ENET1_REF_ROOT_SRC 159
#define ENET1_REF_ROOT_CG 160
#define ENET1_REF_ROOT_DIV 161
#define ENET1_TIME_ROOT_CLK 162
#define ENET1_TIME_ROOT_SRC 163
#define ENET1_TIME_ROOT_CG 164
#define ENET1_TIME_ROOT_DIV 165
#define ENET2_IPG_ROOT_CLK 166
#define ENET2_REF_ROOT_SRC 167
#define ENET2_REF_ROOT_CG 168
#define ENET2_REF_ROOT_DIV 169
#define ENET2_TIME_ROOT_CLK 170
#define ENET2_TIME_ROOT_SRC 171
#define ENET2_TIME_ROOT_CG 172
#define ENET2_TIME_ROOT_DIV 173
#define ENET_PHY_REF_ROOT_CLK 174
#define ENET_PHY_REF_ROOT_SRC 175
#define ENET_PHY_REF_ROOT_CG 176
#define ENET_PHY_REF_ROOT_DIV 177
#define EIM_ROOT_CLK 178
#define EIM_ROOT_SRC 179
#define EIM_ROOT_CG 180
#define EIM_ROOT_DIV 181
#define NAND_ROOT_CLK 182
#define NAND_ROOT_SRC 183
#define NAND_ROOT_CG 184
#define NAND_ROOT_DIV 185
#define QSPI_ROOT_CLK 186
#define QSPI_ROOT_SRC 187
#define QSPI_ROOT_CG 188
#define QSPI_ROOT_DIV 189
#define USDHC1_ROOT_CLK 190
#define USDHC1_ROOT_SRC 191
#define USDHC1_ROOT_CG 192
#define USDHC1_ROOT_DIV 193
#define USDHC2_ROOT_CLK 194
#define USDHC2_ROOT_SRC 195
#define USDHC2_ROOT_CG 196
#define USDHC2_ROOT_DIV 197
#define USDHC3_ROOT_CLK 198
#define USDHC3_ROOT_SRC 199
#define USDHC3_ROOT_CG 200
#define USDHC3_ROOT_DIV 201
#define CAN1_ROOT_CLK 202
#define CAN1_ROOT_SRC 203
#define CAN1_ROOT_CG 204
#define CAN1_ROOT_DIV 205
#define CAN2_ROOT_CLK 206
#define CAN2_ROOT_SRC 207
#define CAN2_ROOT_CG 208
#define CAN2_ROOT_DIV 209
#define I2C1_ROOT_CLK 210
#define I2C1_ROOT_SRC 211
#define I2C1_ROOT_CG 212
#define I2C1_ROOT_DIV 213
#define I2C2_ROOT_CLK 214
#define I2C2_ROOT_SRC 215
#define I2C2_ROOT_CG 216
#define I2C2_ROOT_DIV 217
#define I2C3_ROOT_CLK 218
#define I2C3_ROOT_SRC 219
#define I2C3_ROOT_CG 220
#define I2C3_ROOT_DIV 221
#define I2C4_ROOT_CLK 222
#define I2C4_ROOT_SRC 223
#define I2C4_ROOT_CG 224
#define I2C4_ROOT_DIV 225
#define UART1_ROOT_CLK 226
#define UART1_ROOT_SRC 227
#define UART1_ROOT_CG 228
#define UART1_ROOT_DIV 229
#define UART2_ROOT_CLK 230
#define UART2_ROOT_SRC 231
#define UART2_ROOT_CG 232
#define UART2_ROOT_DIV 233
#define UART3_ROOT_CLK 234
#define UART3_ROOT_SRC 235
#define UART3_ROOT_CG 236
#define UART3_ROOT_DIV 237
#define UART4_ROOT_CLK 238
#define UART4_ROOT_SRC 239
#define UART4_ROOT_CG 240
#define UART4_ROOT_DIV 241
#define UART5_ROOT_CLK 242
#define UART5_ROOT_SRC 243
#define UART5_ROOT_CG 244
#define UART5_ROOT_DIV 245
#define UART6_ROOT_CLK 246
#define UART6_ROOT_SRC 247
#define UART6_ROOT_CG 248
#define UART6_ROOT_DIV 249
#define UART7_ROOT_CLK 250
#define UART7_ROOT_SRC 251
#define UART7_ROOT_CG 252
#define UART7_ROOT_DIV 253
#define ECSPI1_ROOT_CLK 254
#define ECSPI1_ROOT_SRC 255
#define ECSPI1_ROOT_CG 256
#define ECSPI1_ROOT_DIV 257
#define ECSPI2_ROOT_CLK 258
#define ECSPI2_ROOT_SRC 259
#define ECSPI2_ROOT_CG 260
#define ECSPI2_ROOT_DIV 261
#define ECSPI3_ROOT_CLK 262
#define ECSPI3_ROOT_SRC 263
#define ECSPI3_ROOT_CG 264
#define ECSPI3_ROOT_DIV 265
#define ECSPI4_ROOT_CLK 266
#define ECSPI4_ROOT_SRC 267
#define ECSPI4_ROOT_CG 268
#define ECSPI4_ROOT_DIV 269
#define PWM1_ROOT_CLK 270
#define PWM1_ROOT_SRC 271
#define PWM1_ROOT_CG 272
#define PWM1_ROOT_DIV 273
#define PWM2_ROOT_CLK 274
#define PWM2_ROOT_SRC 275
#define PWM2_ROOT_CG 276
#define PWM2_ROOT_DIV 277
#define PWM3_ROOT_CLK 278
#define PWM3_ROOT_SRC 279
#define PWM3_ROOT_CG 280
#define PWM3_ROOT_DIV 281
#define PWM4_ROOT_CLK 282
#define PWM4_ROOT_SRC 283
#define PWM4_ROOT_CG 284
#define PWM4_ROOT_DIV 285
#define FLEXTIMER1_ROOT_CLK 286
#define FLEXTIMER1_ROOT_SRC 287
#define FLEXTIMER1_ROOT_CG 288
#define FLEXTIMER1_ROOT_DIV 289
#define FLEXTIMER2_ROOT_CLK 290
#define FLEXTIMER2_ROOT_SRC 291
#define FLEXTIMER2_ROOT_CG 292
#define FLEXTIMER2_ROOT_DIV 293
#define SIM1_ROOT_CLK 294
#define SIM1_ROOT_SRC 295
#define SIM1_ROOT_CG 296
#define SIM1_ROOT_DIV 297
#define SIM2_ROOT_CLK 298
#define SIM2_ROOT_SRC 299
#define SIM2_ROOT_CG 300
#define SIM2_ROOT_DIV 301
#define GPT1_ROOT_CLK 302
#define GPT1_ROOT_SRC 303
#define GPT1_ROOT_CG 304
#define GPT1_ROOT_DIV 305
#define GPT2_ROOT_CLK 306
#define GPT2_ROOT_SRC 307
#define GPT2_ROOT_CG 308
#define GPT2_ROOT_DIV 309
#define GPT3_ROOT_CLK 310
#define GPT3_ROOT_SRC 311
#define GPT3_ROOT_CG 312
#define GPT3_ROOT_DIV 313
#define GPT4_ROOT_CLK 314
#define GPT4_ROOT_SRC 315
#define GPT4_ROOT_CG 316
#define GPT4_ROOT_DIV 317
#define TRACE_ROOT_CLK 318
#define TRACE_ROOT_SRC 319
#define TRACE_ROOT_CG 320
#define TRACE_ROOT_DIV 321
#define WDOG1_ROOT_CLK 322
#define WDOG_ROOT_SRC 323
#define WDOG_ROOT_CG 324
#define WDOG_ROOT_DIV 325
#define CSI_MCLK_ROOT_CLK 326
#define CSI_MCLK_ROOT_SRC 327
#define CSI_MCLK_ROOT_CG 328
#define CSI_MCLK_ROOT_DIV 329
#define AUDIO_MCLK_ROOT_CLK 330
#define AUDIO_MCLK_ROOT_SRC 331
#define AUDIO_MCLK_ROOT_CG 332
#define AUDIO_MCLK_ROOT_DIV 333
#define WRCLK_ROOT_CLK 334
#define WRCLK_ROOT_SRC 335
#define WRCLK_ROOT_CG 336
#define WRCLK_ROOT_DIV 337
#define CLKO1_ROOT_SRC 338
#define CLKO1_ROOT_CG 339
#define CLKO1_ROOT_DIV 340
#define CLKO2_ROOT_SRC 341
#define CLKO2_ROOT_CG 342
#define CLKO2_ROOT_DIV 343
#define MAIN_AXI_ROOT_PRE_DIV 344
#define DISP_AXI_ROOT_PRE_DIV 345
#define ENET_AXI_ROOT_PRE_DIV 346
#define NAND_USDHC_BUS_ROOT_PRE_DIV 347
#define AHB_CHANNEL_ROOT_PRE_DIV 348
#define USB_HSIC_ROOT_PRE_DIV 349
#define PCIE_CTRL_ROOT_PRE_DIV 350
#define PCIE_PHY_ROOT_PRE_DIV 351
#define EPDC_PIXEL_ROOT_PRE_DIV 352
#define LCDIF_PIXEL_ROOT_PRE_DIV 353
#define MIPI_DSI_ROOT_PRE_DIV 354
#define MIPI_CSI_ROOT_PRE_DIV 355
#define MIPI_DPHY_ROOT_PRE_DIV 356
#define SAI1_ROOT_PRE_DIV 357
#define SAI2_ROOT_PRE_DIV 358
#define SAI3_ROOT_PRE_DIV 359
#define SPDIF_ROOT_PRE_DIV 360
#define ENET1_REF_ROOT_PRE_DIV 361
#define ENET1_TIME_ROOT_PRE_DIV 362
#define ENET2_REF_ROOT_PRE_DIV 363
#define ENET2_TIME_ROOT_PRE_DIV 364
#define ENET_PHY_REF_ROOT_PRE_DIV 365
#define EIM_ROOT_PRE_DIV 366
#define NAND_ROOT_PRE_DIV 367
#define QSPI_ROOT_PRE_DIV 368
#define USDHC1_ROOT_PRE_DIV 369
#define USDHC2_ROOT_PRE_DIV 370
#define USDHC3_ROOT_PRE_DIV 371
#define CAN1_ROOT_PRE_DIV 372
#define CAN2_ROOT_PRE_DIV 373
#define I2C1_ROOT_PRE_DIV 374
#define I2C2_ROOT_PRE_DIV 375
#define I2C3_ROOT_PRE_DIV 376
#define I2C4_ROOT_PRE_DIV 377
#define UART1_ROOT_PRE_DIV 378
#define UART2_ROOT_PRE_DIV 379
#define UART3_ROOT_PRE_DIV 380
#define UART4_ROOT_PRE_DIV 381
#define UART5_ROOT_PRE_DIV 382
#define UART6_ROOT_PRE_DIV 383
#define UART7_ROOT_PRE_DIV 384
#define ECSPI1_ROOT_PRE_DIV 385
#define ECSPI2_ROOT_PRE_DIV 386
#define ECSPI3_ROOT_PRE_DIV 387
#define ECSPI4_ROOT_PRE_DIV 388
#define PWM1_ROOT_PRE_DIV 389
#define PWM2_ROOT_PRE_DIV 390
#define PWM3_ROOT_PRE_DIV 391
#define PWM4_ROOT_PRE_DIV 392
#define FLEXTIMER1_ROOT_PRE_DIV 393
#define FLEXTIMER2_ROOT_PRE_DIV 394
#define SIM1_ROOT_PRE_DIV 395
#define SIM2_ROOT_PRE_DIV 396
#define GPT1_ROOT_PRE_DIV 397
#define GPT2_ROOT_PRE_DIV 398
#define GPT3_ROOT_PRE_DIV 399
#define GPT4_ROOT_PRE_DIV 400
#define TRACE_ROOT_PRE_DIV 401
#define WDOG_ROOT_PRE_DIV 402
#define CSI_MCLK_ROOT_PRE_DIV 403
#define AUDIO_MCLK_ROOT_PRE_DIV 404
#define WRCLK_ROOT_PRE_DIV 405
#define CLKO1_ROOT_PRE_DIV 406
#define CLKO2_ROOT_PRE_DIV 407
#define DRAM_PHYM_ALT_ROOT_PRE_DIV 408
#define DRAM_ALT_ROOT_PRE_DIV 409
#define LVDS1_IN_CLK 410
#define LVDS1_OUT_SEL 411
#define LVDS1_OUT_CLK 412
#define CLK_DUMMY 413
#define GPT_3M_CLK 414
#define OCRAM_CLK 415
#define OCRAM_S_CLK 416
#define WDOG2_ROOT_CLK 417
#define WDOG3_ROOT_CLK 418
#define WDOG4_ROOT_CLK 419
#define SDMA_CORE_CLK 420
#define USB1_MAIN_480M_CLK 421
#define USB_CTRL_CLK 422
#define USB_PHY1_CLK 423
#define USB_PHY2_CLK 424
#define IPG_ROOT_CLK 425
#define SAI1_IPG_CLK 426
#define SAI2_IPG_CLK 427
#define SAI3_IPG_CLK 428
#define PLL_AUDIO_TEST_DIV 429
#define PLL_AUDIO_POST_DIV 430
#define PLL_VIDEO_TEST_DIV 431
#define PLL_VIDEO_POST_DIV 432
#define MU_ROOT_CLK 433
#define SEMA4_HS_ROOT_CLK 434
#define PLL_DRAM_TEST_DIV 435
#define ADC_ROOT_CLK 436
#define CLK_ARM 437
#define CKIL 438
#define OCOTP_CLK 439
#define NAND_RAWNAND_CLK 440
#define NAND_USDHC_BUS_RAWNAND_CLK 441
#define SNVS_CLK 442
#define CAAM_CLK 443
#define KPP_ROOT_CLK 444
#endif /* !_IMX7D_CCM_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: imx_ccm.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
/* $NetBSD: imx_ccm.c,v 1.2 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: imx_ccm.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: imx_ccm.c,v 1.2 2020/06/10 17:57:50 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -215,7 +215,7 @@ imx_ccm_clock_get_parent(void *priv, struct clk *clkp)
return fdtbus_clock_byname(parent);
}
static const struct clk_funcs imx_ccm_clock_funcs = {
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,
@ -251,7 +251,7 @@ imx_ccm_attach(struct imx_ccm_softc *sc)
aprint_error(": couldn't get registers\n");
return ENXIO;
}
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh[0]) != 0) {
aprint_error(": couldn't map registers\n");
return ENXIO;
}
@ -289,8 +289,11 @@ imx_ccm_print(struct imx_ccm_softc *sc)
case IMX_CCM_EXTCLK: type = "extclk"; break;
case IMX_CCM_GATE: type = "gate"; break;
case IMX_CCM_COMPOSITE: type = "comp"; break;
case IMX_CCM_PLL: type = "pll"; break;
case IMX_CCM_FIXED: type = "fixed"; break;
case IMX_CCM_FIXED_FACTOR: type = "fixed-factor"; break;
case IMX_CCM_MUX: type = "mux"; break;
case IMX_CCM_DIV: type = "div"; break;
default: type = "???"; break;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: imx_ccm.h,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
/* $NetBSD: imx_ccm.h,v 1.2 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
@ -44,8 +44,11 @@ enum imx_ccm_clktype {
IMX_CCM_EXTCLK,
IMX_CCM_GATE,
IMX_CCM_COMPOSITE,
IMX_CCM_PLL,
IMX_CCM_FIXED,
IMX_CCM_FIXED_FACTOR,
IMX_CCM_MUX,
IMX_CCM_DIV,
};
/* External clocks */
@ -81,9 +84,12 @@ int imx_ccm_gate_enable(struct imx_ccm_softc *,
const char *imx_ccm_gate_get_parent(struct imx_ccm_softc *,
struct imx_ccm_clk *);
#define IMX_GATE(_id, _name, _pname, _reg, _mask) \
#define IMX_GATE(_id, _name, _pname, _reg, _mask) \
IMX_GATE_INDEX(_id, 0, _name, _pname, _reg, _mask)
#define IMX_GATE_INDEX(_id, _regidx, _name, _pname, _reg, _mask) \
{ \
.id = (_id), \
.regidx = (_regidx), \
.type = IMX_CCM_GATE, \
.base.name = (_name), \
.base.flags = CLK_SET_RATE_PARENT, \
@ -94,7 +100,9 @@ const char *imx_ccm_gate_get_parent(struct imx_ccm_softc *,
.get_parent = imx_ccm_gate_get_parent, \
}
#define IMX_ROOT_GATE(_id, _name, _pname, _reg) \
IMX_GATE(_id, _name, _pname, _reg, __BITS(1,0))
IMX_ROOT_GATE_INDEX(_id, 0, _name, _pname, _reg)
#define IMX_ROOT_GATE_INDEX(_id, _regidx, _name, _pname, _reg) \
IMX_GATE_INDEX(_id, _regidx, _name, _pname, _reg, __BITS(1,0))
/* Composite clocks */
@ -114,8 +122,12 @@ const char *imx_ccm_composite_get_parent(struct imx_ccm_softc *, struct imx_ccm_
int imx_ccm_composite_set_parent(struct imx_ccm_softc *, struct imx_ccm_clk *, const char *);
#define IMX_COMPOSITE(_id, _name, _parents, _reg, _flags) \
IMX_COMPOSITE_INDEX(_id, 0, _name, _parents, _reg, _flags)
#define IMX_COMPOSITE_INDEX(_id, _regidx, _name, _parents, _reg, _flags) \
{ \
.id = (_id), \
.regidx = (_regidx), \
.type = IMX_CCM_COMPOSITE, \
.base.name = (_name), \
.base.flags = 0, \
@ -130,6 +142,40 @@ int imx_ccm_composite_set_parent(struct imx_ccm_softc *, struct imx_ccm_clk *, c
.get_parent = imx_ccm_composite_get_parent, \
}
/* PLLs */
struct imx_ccm_pll {
bus_size_t reg;
const char *parent;
uint32_t div_mask;
u_int flags;
#define IMX_PLL_ARM __BIT(0)
#define IMX_PLL_480M_528M __BIT(1)
#define IMX_PLL_ENET __BIT(2)
};
int imx_ccm_pll_enable(struct imx_ccm_softc *, struct imx_ccm_clk *, int);
u_int imx_ccm_pll_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
const char *imx_ccm_pll_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
#define IMX_PLL(_id, _name, _parent, _reg, _div_mask, _flags) \
IMX_PLL_INDEX(_id, 0, _name, _parent, _reg, _div_mask, _flags)
#define IMX_PLL_INDEX(_id, _regidx, _name, _parent, _reg, _div_mask, _flags) \
{ \
.id = (_id), \
.regidx = (_regidx), \
.type = IMX_CCM_PLL, \
.base.name = (_name), \
.base.flags = 0, \
.u.pll.parent = (_parent), \
.u.pll.reg = (_reg), \
.u.pll.div_mask = (_div_mask), \
.u.pll.flags = (_flags), \
.enable = imx_ccm_pll_enable, \
.get_rate = imx_ccm_pll_get_rate, \
.get_parent = imx_ccm_pll_get_parent, \
}
/* Fixed clocks */
struct imx_ccm_fixed {
@ -174,6 +220,69 @@ const char *imx_ccm_fixed_factor_get_parent(struct imx_ccm_softc *, struct imx_c
.get_parent = imx_ccm_fixed_factor_get_parent, \
}
/* Mux clocks */
struct imx_ccm_mux {
bus_size_t reg;
const char **parents;
u_int nparents;
uint32_t sel;
};
const char *imx_ccm_mux_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
int imx_ccm_mux_set_parent(struct imx_ccm_softc *, struct imx_ccm_clk *, const char *);
#define IMX_MUX(_id, _name, _parents, _reg, _sel) \
IMX_MUX_INDEX(_id, 0, _name, _parents, _reg, _sel)
#define IMX_MUX_INDEX(_id, _regidx, _name, _parents, _reg, _sel) \
{ \
.id = (_id), \
.regidx = (_regidx), \
.type = IMX_CCM_MUX, \
.base.name = (_name), \
.base.flags = CLK_SET_RATE_PARENT, \
.u.mux.parents = (_parents), \
.u.mux.nparents = __arraycount(_parents), \
.u.mux.reg = (_reg), \
.u.mux.sel = (_sel), \
.get_parent = imx_ccm_mux_get_parent, \
.set_parent = imx_ccm_mux_set_parent, \
}
/* Divider clocks */
struct imx_ccm_div {
bus_size_t reg;
const char *parent;
uint32_t mask;
u_int flags;
#define IMX_DIV_SET_RATE_PARENT __BIT(0)
#define IMX_DIV_ROUND_DOWN __BIT(1)
};
u_int imx_ccm_div_get_rate(struct imx_ccm_softc *, struct imx_ccm_clk *);
int imx_ccm_div_set_rate(struct imx_ccm_softc *, struct imx_ccm_clk *, u_int);
const char *imx_ccm_div_get_parent(struct imx_ccm_softc *, struct imx_ccm_clk *);
#define IMX_DIV(_id, _name, _parent, _reg, _mask, _flags) \
IMX_DIV_INDEX(_id, 0, _name, _parent, _reg, _mask, _flags)
#define IMX_DIV_INDEX(_id, _regidx, _name, _parent, _reg, _mask, _flags) \
{ \
.id = (_id), \
.regidx = (_regidx), \
.type = IMX_CCM_DIV, \
.base.name = (_name), \
.base.flags = 0, \
.u.div.parent = (_parent), \
.u.div.reg = (_reg), \
.u.div.mask = (_mask), \
.u.div.flags = (_flags), \
.get_rate = imx_ccm_div_get_rate, \
.set_rate = imx_ccm_div_set_rate, \
.get_parent = imx_ccm_div_get_parent, \
}
/*
* IMX clock definition
*/
@ -181,12 +290,16 @@ const char *imx_ccm_fixed_factor_get_parent(struct imx_ccm_softc *, struct imx_c
struct imx_ccm_clk {
struct clk base;
u_int id;
u_int regidx;
enum imx_ccm_clktype type;
union {
struct imx_ccm_gate gate;
struct imx_ccm_composite composite;
struct imx_ccm_pll pll;
struct imx_ccm_fixed fixed;
struct imx_ccm_fixed_factor fixed_factor;
struct imx_ccm_mux mux;
struct imx_ccm_div div;
const char *extclk;
} u;
@ -213,7 +326,9 @@ struct imx_ccm_softc {
device_t sc_dev;
int sc_phandle;
bus_space_tag_t sc_bst;
bus_space_handle_t sc_bsh;
bus_space_handle_t sc_bsh[2];
bus_addr_t sc_baseaddr;
struct clk_domain sc_clkdom;
@ -226,9 +341,11 @@ 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))
extern const struct clk_funcs imx_ccm_clock_funcs;
#define CCM_READ(sc, idx, reg) \
bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh[idx], (reg))
#define CCM_WRITE(sc, idx, reg, val) \
bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh[idx], (reg), (val))
#endif /* _ARM_IMX_CCM_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: imx_ccm_composite.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $ */
/* $NetBSD: imx_ccm_composite.c,v 1.2 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: imx_ccm_composite.c,v 1.1 2020/01/15 01:09:56 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: imx_ccm_composite.c,v 1.2 2020/06/10 17:57:50 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -53,12 +53,12 @@ imx_ccm_composite_enable(struct imx_ccm_softc *sc, struct imx_ccm_clk *clk,
KASSERT(clk->type == IMX_CCM_COMPOSITE);
val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
val = CCM_READ(sc, clk->regidx, 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);
CCM_WRITE(sc, clk->regidx, composite->reg + CCM_TARGET_ROOT, val);
return 0;
}
@ -81,7 +81,7 @@ imx_ccm_composite_get_rate(struct imx_ccm_softc *sc,
if (prate == 0)
return 0;
const uint32_t val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
const uint32_t val = CCM_READ(sc, clk->regidx, 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;
@ -111,7 +111,7 @@ imx_ccm_composite_set_rate(struct imx_ccm_softc *sc,
best_postdiv = 0;
best_diff = INT_MAX;
val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
val = CCM_READ(sc, clk->regidx, composite->reg + CCM_TARGET_ROOT);
const u_int mux = __SHIFTOUT(val, TARGET_ROOT_MUX);
if (mux >= composite->nparents)
@ -151,12 +151,12 @@ imx_ccm_composite_set_rate(struct imx_ccm_softc *sc,
if (best_diff == INT_MAX)
return ERANGE;
val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
val = CCM_READ(sc, clk->regidx, 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);
CCM_WRITE(sc, clk->regidx, composite->reg + CCM_TARGET_ROOT, val);
return 0;
}
@ -169,7 +169,7 @@ imx_ccm_composite_get_parent(struct imx_ccm_softc *sc,
KASSERT(clk->type == IMX_CCM_COMPOSITE);
const uint32_t val = CCM_READ(sc, composite->reg + CCM_TARGET_ROOT);
const uint32_t val = CCM_READ(sc, clk->regidx, composite->reg + CCM_TARGET_ROOT);
const u_int mux = __SHIFTOUT(val, TARGET_ROOT_MUX);
if (mux >= composite->nparents)
@ -189,10 +189,10 @@ imx_ccm_composite_set_parent(struct imx_ccm_softc *sc,
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 = CCM_READ(sc, clk->regidx, composite->reg + CCM_TARGET_ROOT);
val &= ~TARGET_ROOT_MUX;
val |= __SHIFTIN(mux, TARGET_ROOT_MUX);
CCM_WRITE(sc, composite->reg + CCM_TARGET_ROOT, val);
CCM_WRITE(sc, clk->regidx, composite->reg + CCM_TARGET_ROOT, val);
return 0;
}
}

View File

@ -0,0 +1,124 @@
/* $NetBSD: imx_ccm_div.c,v 1.1 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@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_div.c,v 1.1 2020/06/10 17:57:50 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>
u_int
imx_ccm_div_get_rate(struct imx_ccm_softc *sc,
struct imx_ccm_clk *clk)
{
struct imx_ccm_div *div = &clk->u.div;
struct clk *clkp, *clkp_parent;
KASSERT(clk->type == IMX_CCM_DIV);
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, clk->regidx, div->reg);
const u_int n = __SHIFTOUT(val, div->mask);
return prate / (n + 1);
}
int
imx_ccm_div_set_rate(struct imx_ccm_softc *sc,
struct imx_ccm_clk *clk, u_int rate)
{
struct imx_ccm_div *div = &clk->u.div;
struct clk *clkp, *clkp_parent;
int best_diff = INT_MAX;
u_int n, best_n;
uint32_t val;
KASSERT(clk->type == IMX_CCM_DIV);
clkp = &clk->base;
clkp_parent = clk_get_parent(clkp);
if (clkp_parent == NULL)
return ENXIO;
if ((div->flags & IMX_DIV_SET_RATE_PARENT) != 0)
return clk_set_rate(clkp, rate);
const u_int prate = clk_get_rate(clkp_parent);
if (prate == 0)
return EIO;
for (n = 0; n < __SHIFTOUT_MASK(div->mask); n++) {
const u_int tmp_rate = prate / (n + 1);
const int diff = (int)rate - (int)tmp_rate;
if ((div->flags & IMX_DIV_ROUND_DOWN) != 0) {
if (diff >= 0 && diff < best_diff) {
best_n = n;
best_diff = diff;
}
} else {
if (abs(diff) < abs(best_diff)) {
best_n = n;
best_diff = diff;
}
}
}
if (best_diff == INT_MAX)
return EIO;
val = CCM_READ(sc, clk->regidx, div->reg);
val &= ~div->mask;
val |= __SHIFTIN(best_n, div->mask);
CCM_WRITE(sc, clk->regidx, div->reg, val);
return 0;
}
const char *
imx_ccm_div_get_parent(struct imx_ccm_softc *sc,
struct imx_ccm_clk *clk)
{
struct imx_ccm_div *div = &clk->u.div;
KASSERT(clk->type == IMX_CCM_DIV);
return div->parent;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: imx_ccm_gate.c,v 1.1 2020/01/15 01:09:57 jmcneill Exp $ */
/* $NetBSD: imx_ccm_gate.c,v 1.2 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: imx_ccm_gate.c,v 1.1 2020/01/15 01:09:57 jmcneill Exp $");
__KERNEL_RCSID(0, "$NetBSD: imx_ccm_gate.c,v 1.2 2020/06/10 17:57:50 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@ -45,12 +45,12 @@ imx_ccm_gate_enable(struct imx_ccm_softc *sc, struct imx_ccm_clk *clk,
KASSERT(clk->type == IMX_CCM_GATE);
val = CCM_READ(sc, gate->reg);
val = CCM_READ(sc, clk->regidx, gate->reg);
if (enable)
val |= gate->mask;
else
val &= ~gate->mask;
CCM_WRITE(sc, gate->reg, val);
CCM_WRITE(sc, clk->regidx, gate->reg, val);
return 0;
}

View File

@ -0,0 +1,78 @@
/* $NetBSD: imx_ccm_mux.c,v 1.1 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@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_mux.c,v 1.1 2020/06/10 17:57:50 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>
const char *
imx_ccm_mux_get_parent(struct imx_ccm_softc *sc,
struct imx_ccm_clk *clk)
{
struct imx_ccm_mux *mux = &clk->u.mux;
KASSERT(clk->type == IMX_CCM_MUX);
const uint32_t val = CCM_READ(sc, clk->regidx, mux->reg);
const u_int sel = __SHIFTOUT(val, mux->sel);
if (sel >= mux->nparents)
return NULL;
return mux->parents[sel];
}
int
imx_ccm_mux_set_parent(struct imx_ccm_softc *sc,
struct imx_ccm_clk *clk, const char *parent)
{
struct imx_ccm_mux *mux = &clk->u.mux;
uint32_t val;
KASSERT(clk->type == IMX_CCM_MUX);
for (u_int sel = 0; sel < mux->nparents; sel++) {
if (strcmp(mux->parents[sel], parent) == 0) {
val = CCM_READ(sc, clk->regidx, mux->reg);
val &= ~mux->sel;
val |= __SHIFTIN(sel, mux->sel);
CCM_WRITE(sc, clk->regidx, mux->reg, val);
return 0;
}
}
return EINVAL;
}

View File

@ -0,0 +1,114 @@
/* $NetBSD: imx_ccm_pll.c,v 1.1 2020/06/10 17:57:50 jmcneill Exp $ */
/*-
* Copyright (c) 2020 Jared McNeill <jmcneill@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_pll.c,v 1.1 2020/06/10 17:57:50 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 PLL_POWERDOWN __BIT(12)
#define PLL_POWERDOWN_ENET __BIT(5)
int
imx_ccm_pll_enable(struct imx_ccm_softc *sc, struct imx_ccm_clk *clk,
int enable)
{
struct imx_ccm_pll *pll = &clk->u.pll;
uint32_t val, mask;
KASSERT(clk->type == IMX_CCM_PLL);
if ((pll->flags & IMX_PLL_ENET) != 0)
mask = PLL_POWERDOWN_ENET;
else
mask = PLL_POWERDOWN;
val = CCM_READ(sc, clk->regidx, pll->reg);
if (enable)
val &= ~mask;
else
val |= mask;
CCM_WRITE(sc, clk->regidx, pll->reg, val);
return 0;
}
u_int
imx_ccm_pll_get_rate(struct imx_ccm_softc *sc,
struct imx_ccm_clk *clk)
{
struct imx_ccm_pll *pll= &clk->u.pll;
struct clk *clkp, *clkp_parent;
KASSERT(clk->type == IMX_CCM_PLL);
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;
if ((pll->flags & IMX_PLL_ENET) != 0) {
/* For ENET PLL, div_mask contains the fixed output rate */
return pll->div_mask;
}
const uint32_t val = CCM_READ(sc, clk->regidx, pll->reg);
const u_int div = __SHIFTOUT(val, pll->div_mask);
if ((pll->flags & IMX_PLL_ARM) != 0) {
return prate * div / 2;
}
if ((pll->flags & IMX_PLL_480M_528M) != 0) {
return div == 1 ? 528000000 : 480000000;
}
return 0;
}
const char *
imx_ccm_pll_get_parent(struct imx_ccm_softc *sc,
struct imx_ccm_clk *clk)
{
struct imx_ccm_pll *pll = &clk->u.pll;
KASSERT(clk->type == IMX_CCM_PLL);
return pll->parent;
}

View File

@ -1,5 +1,5 @@
#
# $NetBSD: GENERIC,v 1.79 2020/06/08 11:51:48 jmcneill Exp $
# $NetBSD: GENERIC,v 1.80 2020/06/10 17:57:50 jmcneill Exp $
#
# GENERIC ARM (aarch32) kernel
#
@ -22,6 +22,7 @@ options SOC_EXYNOS5422
options SOC_IMX6DL
options SOC_IMX6Q
options SOC_IMX6QDL
options SOC_IMX7D
options SOC_MESON8B
options SOC_OMAP3
options SOC_SUN4I_A10
@ -106,7 +107,8 @@ cycvclkmgr* at fdt? pass 1 # Cyclone V clock manager
cycvrstmgr* at fdt? pass 0 # Cyclone V reset manager
exy5410clk* at fdt? pass 3 # Exynos5410 clock controller
exy5422clk* at fdt? pass 3 # Exynos5422 clock controller
imxccm* at fdt? pass 1 # i.MX6 ccm
imx6ccm* at fdt? pass 1 # i.MX6 CCM
imx7dccm* at fdt? pass 2 # i.MX7D CCM
meson8bclkc* at fdt? pass 2 # Amlogic Meson8b clock controller
mesonresets* at fdt? pass 2 # Amlogic Meson misc. clock resets
omap3cm* at fdt? pass 1 # TI OMAP3 CM
@ -178,6 +180,7 @@ armgic0 at gic?
bcmicu* at fdt? pass 1 # Broadcom BCM283x ICU
exyointr* at fdt? pass 1 # Samsung Exynos ICU
imxgpc* at fdt? pass 2 # i.MX General Power Controller INTC
imx7gpc* at fdt? pass 2 # i.MX General Power Controller v2 INTC
omapintc* at fdt? pass 2 # TI OMAP INTC
tegralic* at fdt? pass 1 # NVIDIA Tegra LIC
sunxiintc* at fdt? pass 1 # Allwinner INTC