* [PATCH v2 05/28] i.MX: Add support for VF610 Tower board
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Add support for VF610 Tower board.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
arch/arm/boards/Makefile | 1 +
arch/arm/boards/freescale-vf610-twr/Makefile | 3 +
.../flash-header-vf610-twr.imxcfg | 278 +++++++++++++++++++++
arch/arm/boards/freescale-vf610-twr/lowlevel.c | 45 ++++
arch/arm/dts/Makefile | 1 +
arch/arm/dts/vf610-twr.dts | 14 ++
arch/arm/mach-imx/Kconfig | 4 +
images/Makefile.imx | 5 +
8 files changed, 351 insertions(+)
create mode 100644 arch/arm/boards/freescale-vf610-twr/Makefile
create mode 100644 arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
create mode 100644 arch/arm/boards/freescale-vf610-twr/lowlevel.c
create mode 100644 arch/arm/dts/vf610-twr.dts
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 1a0f63f..ff0a86f 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -140,3 +140,4 @@ obj-$(CONFIG_MACH_ZYLONITE) += zylonite/
obj-$(CONFIG_MACH_VARISCITE_MX6) += variscite-mx6/
obj-$(CONFIG_MACH_VSCOM_BALTOS) += vscom-baltos/
obj-$(CONFIG_MACH_QEMU_VIRT64) += qemu-virt64/
+obj-$(CONFIG_MACH_VF610_TWR) += freescale-vf610-twr/
diff --git a/arch/arm/boards/freescale-vf610-twr/Makefile b/arch/arm/boards/freescale-vf610-twr/Makefile
new file mode 100644
index 0000000..6b029ce
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/Makefile
@@ -0,0 +1,3 @@
+obj-y += flash-header-vf610-twr.dcd.o
+extra-y += flash-header-vf610-twr.dcd.S flash-header-vf610-twr.dcd
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
new file mode 100644
index 0000000..01ffc69
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
@@ -0,0 +1,278 @@
+soc vf610
+loadaddr 0x80000000
+dcdofs 0x400
+
+#define VF610_DDR_PAD_CTRL 0x00000180 /* 25 Ohm drive strength */
+#define VF610_DDR_PAD_CTRL_1 0x00010180 /* 25 Ohm drive strength + differential input */
+
+#define DDRMC_PHY_DQ_TIMING 0x00002613
+#define DDRMC_PHY_DQS_TIMING 0x00002615
+#define DDRMC_PHY_CTRL 0x00210000
+#define DDRMC_PHY_MASTER_CTRL 0x0001012a
+#define DDRMC_PHY_SLAVE_CTRL 0x00002000
+#define DDRMC_PHY_OFF 0x00000000
+#define DDRMC_PHY_PROC_PAD_ODT 0x00010101
+
+#ifdef DEBUG
+#define CHECKPOINT(n) wm 32 0x3f040000 n
+#else
+#define CHECKPOINT(n)
+#endif
+
+CHECKPOINT(1)
+
+/* ======================= Clock initialization =======================*/
+
+/*
+ * Ungate all IP block clocks
+ */
+wm 32 0x4006b040 0xffffffff
+wm 32 0x4006b044 0xffffffff
+wm 32 0x4006b048 0xffffffff
+wm 32 0x4006b04c 0xffffffff
+wm 32 0x4006b050 0xffffffff
+wm 32 0x4006b058 0xffffffff
+wm 32 0x4006b05c 0xffffffff
+wm 32 0x4006b060 0xffffffff
+wm 32 0x4006b064 0xffffffff
+wm 32 0x4006b068 0xffffffff
+wm 32 0x4006b06c 0xffffffff
+
+
+/*
+ * We have to options to clock DDR controller:
+ *
+ * - Use Core-A5 clock
+ * - Use PLL2 PFD2 clock
+ *
+
+ * Using first option without changing PLL settings doesn't seem to be
+ * possible given that DDRMC requires minimum of 300Mhz and MaskROM
+ * configures it to be clocked at 264Mhz. Changing PLL1 settings
+ * proved to be challenging becuase MaskROM code executing this DCD
+ * will also be fetching the rest of the bootloader via some
+ * peripheral interface whose clock is derived from Cortex-A5 clock.
+ *
+ * As a result this DCD configuration code uses the second option of
+ * clocking DDR wiht PLL2 PFD2 clock output
+ *
+ * Turn PLL2 on
+ */
+wm 32 0x40050030 0x00002001 /* Fout = Fin * 22 */
+
+CHECKPOINT(2)
+
+/*
+ * Wait for PLLs to lock
+ */
+check 32 while_any_bit_clear 0x40050030 0x80000000
+
+
+CHECKPOINT(3)
+
+/*
+ * Switch DDRMC to be clocked with PLL2 PFD2 and enable PFD2 output
+ */
+clear_bits 32 0x4006b008 0x00000040
+set_bits 32 0x4006b008 0x00002000
+
+
+
+/* ======================= DDR IOMUX ======================= */
+
+CHECKPOINT(4)
+
+wm 32 0x40048220 VF610_DDR_PAD_CTRL
+wm 32 0x40048224 VF610_DDR_PAD_CTRL
+wm 32 0x40048228 VF610_DDR_PAD_CTRL
+wm 32 0x4004822c VF610_DDR_PAD_CTRL
+wm 32 0x40048230 VF610_DDR_PAD_CTRL
+wm 32 0x40048234 VF610_DDR_PAD_CTRL
+wm 32 0x40048238 VF610_DDR_PAD_CTRL
+wm 32 0x4004823c VF610_DDR_PAD_CTRL
+wm 32 0x40048240 VF610_DDR_PAD_CTRL
+wm 32 0x40048244 VF610_DDR_PAD_CTRL
+wm 32 0x40048248 VF610_DDR_PAD_CTRL
+wm 32 0x4004824c VF610_DDR_PAD_CTRL
+wm 32 0x40048250 VF610_DDR_PAD_CTRL
+wm 32 0x40048254 VF610_DDR_PAD_CTRL
+wm 32 0x40048258 VF610_DDR_PAD_CTRL
+wm 32 0x4004825c VF610_DDR_PAD_CTRL
+wm 32 0x40048260 VF610_DDR_PAD_CTRL
+wm 32 0x40048264 VF610_DDR_PAD_CTRL
+wm 32 0x40048268 VF610_DDR_PAD_CTRL
+wm 32 0x4004826c VF610_DDR_PAD_CTRL
+wm 32 0x40048270 VF610_DDR_PAD_CTRL
+wm 32 0x40048274 VF610_DDR_PAD_CTRL
+wm 32 0x40048278 VF610_DDR_PAD_CTRL
+wm 32 0x4004827c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048280 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048284 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048288 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004828c VF610_DDR_PAD_CTRL_1
+wm 32 0x40048290 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048294 VF610_DDR_PAD_CTRL_1
+wm 32 0x40048298 VF610_DDR_PAD_CTRL_1
+wm 32 0x4004829c VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482a8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482ac VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482b8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482bc VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c0 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c4 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482c8 VF610_DDR_PAD_CTRL_1
+wm 32 0x400482cc VF610_DDR_PAD_CTRL
+wm 32 0x400482d0 VF610_DDR_PAD_CTRL
+wm 32 0x400482d4 VF610_DDR_PAD_CTRL
+wm 32 0x400482d8 VF610_DDR_PAD_CTRL
+wm 32 0x4004821c VF610_DDR_PAD_CTRL
+
+/* ======================= DDR Controller =======================*/
+
+CHECKPOINT(5)
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae008 0x00000020
+wm 32 0x400ae028 0x00013880
+wm 32 0x400ae02c 0x00030d40
+wm 32 0x400ae030 0x0000050c
+wm 32 0x400ae034 0x15040400
+wm 32 0x400ae038 0x1406040f
+wm 32 0x400ae040 0x04040000
+wm 32 0x400ae044 0x006db00c
+wm 32 0x400ae048 0x00000403
+wm 32 0x400ae050 0x01000000
+wm 32 0x400ae054 0x00060001
+wm 32 0x400ae058 0x000c0000
+wm 32 0x400ae05c 0x03000200
+wm 32 0x400ae060 0x00000006
+wm 32 0x400ae064 0x00010000
+wm 32 0x400ae068 0x0c30002c
+wm 32 0x400ae070 0x00000000
+wm 32 0x400ae074 0x00000003
+wm 32 0x400ae078 0x0000000a
+wm 32 0x400ae07c 0x003001d4
+wm 32 0x400ae084 0x00010000
+wm 32 0x400ae088 0x00050500
+wm 32 0x400ae098 0x00000000
+wm 32 0x400ae09c 0x04001002
+wm 32 0x400ae0a4 0x00000001
+wm 32 0x400ae0c0 0x00460420
+wm 32 0x400ae108 0x01000200
+wm 32 0x400ae10c 0x00000040
+wm 32 0x400ae114 0x00000200
+wm 32 0x400ae118 0x00000040
+wm 32 0x400ae120 0x00000000
+wm 32 0x400ae124 0x0a010300
+wm 32 0x400ae128 0x01014040
+wm 32 0x400ae12c 0x01010101
+wm 32 0x400ae130 0x03030100
+wm 32 0x400ae134 0x01000101
+wm 32 0x400ae138 0x0700000c
+wm 32 0x400ae13c 0x00000000
+wm 32 0x400ae148 0x10000000
+wm 32 0x400ae15c 0x01000000
+wm 32 0x400ae160 0x00040000
+wm 32 0x400ae164 0x00000002
+wm 32 0x400ae16c 0x00020000
+wm 32 0x400ae180 0x00002819
+wm 32 0x400ae184 0x01000000
+wm 32 0x400ae188 0x00000000
+wm 32 0x400ae18c 0x00000000
+wm 32 0x400ae198 0x00010100
+wm 32 0x400ae1a4 0x00000000
+wm 32 0x400ae1a8 0x00000004
+wm 32 0x400ae1b8 0x00040000
+wm 32 0x400ae1c8 0x00000000
+wm 32 0x400ae1cc 0x00000000
+wm 32 0x400ae1d4 0x00000000
+wm 32 0x400ae1d8 0x01010000
+wm 32 0x400ae1e0 0x02020000
+wm 32 0x400ae1e4 0x00000202
+wm 32 0x400ae1e8 0x01010064
+wm 32 0x400ae1ec 0x00010101
+wm 32 0x400ae1f0 0x00000064
+wm 32 0x400ae1f8 0x00000800
+wm 32 0x400ae210 0x00000506
+wm 32 0x400ae224 0x00020000
+wm 32 0x400ae228 0x01000000
+wm 32 0x400ae22c 0x04070303
+wm 32 0x400ae230 0x00000040
+wm 32 0x400ae23c 0x06000080
+wm 32 0x400ae240 0x04070303
+wm 32 0x400ae244 0x00000040
+wm 32 0x400ae248 0x00000040
+wm 32 0x400ae24c 0x000f0000
+wm 32 0x400ae250 0x000f0000
+wm 32 0x400ae25c 0x00000101
+wm 32 0x400ae268 0x682c4000
+wm 32 0x400ae26c 0x00000012
+wm 32 0x400ae278 0x00000006
+wm 32 0x400ae284 0x00010202
+
+/* ======================= DDR PHY =======================*/
+
+CHECKPOINT(6)
+
+wm 32 0x400ae400 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae440 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae480 DDRMC_PHY_DQ_TIMING
+wm 32 0x400ae404 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae444 DDRMC_PHY_DQS_TIMING
+wm 32 0x400ae408 DDRMC_PHY_CTRL
+wm 32 0x400ae448 DDRMC_PHY_CTRL
+wm 32 0x400ae488 DDRMC_PHY_CTRL
+wm 32 0x400ae40c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae44c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae48c DDRMC_PHY_MASTER_CTRL
+wm 32 0x400ae410 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae450 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae490 DDRMC_PHY_SLAVE_CTRL
+wm 32 0x400ae4c4 DDRMC_PHY_OFF
+wm 32 0x400ae4c8 0x00001100
+wm 32 0x400ae4d0 DDRMC_PHY_PROC_PAD_ODT
+
+wm 32 0x400ae000 0x00000601
+
+CHECKPOINT(7)
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(8)
+
+/*
+ * Cargo cult DDR controller initialization here we come!
+ *
+ * Experemintation with VF610 Tower Board shows that without the
+ * following code the board would not boot off of SD card when
+ * power-cycled. It will however happily boot when reset via SW3/Reset
+ * button. For whatever reason the following actions appear to be
+ * necessary:
+ *
+ * - Initialize DDRMC as usual
+ * - Issue a read to location in DDR address space
+ * - Disable DDRMC
+ * - Enable DDRMC and wait for it to finish initializing
+ *
+ * I am sure this is all going to be extrememly embarrassing to read
+ * if/when the real problem and real solution is found.
+ */
+
+/*
+ * Because there's no standalone read command what we do here instead
+ * is write a pattern to memory and then checking that memory address
+ * against that pattern
+ */
+wm 32 0x80000000 0xa5a5a5a5
+check 32 while_any_bit_clear 0x80000000 0xa5a5a5a5
+
+wm 32 0x400ae000 0x00000600
+wm 32 0x400ae000 0x00000601
+
+check 32 while_any_bit_clear 0x400ae140 0x100
+
+CHECKPOINT(9)
\ No newline at end of file
diff --git a/arch/arm/boards/freescale-vf610-twr/lowlevel.c b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
new file mode 100644
index 0000000..6504273
--- /dev/null
+++ b/arch/arm/boards/freescale-vf610-twr/lowlevel.c
@@ -0,0 +1,45 @@
+#include <common.h>
+#include <linux/sizes.h>
+#include <mach/generic.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <mach/vf610-regs.h>
+#include <mach/clock-vf610.h>
+#include <mach/iomux-vf610.h>
+#include <debug_ll.h>
+
+static inline void setup_uart(void)
+{
+ void __iomem *iomuxbase = IOMEM(VF610_IOMUXC_BASE_ADDR);
+
+ vf610_ungate_all_peripherals();
+
+ /*
+ * VF610_PAD_PTB4__UART1_TX
+ */
+ writel(VF610_UART_PAD_CTRL | (2 << 20), iomuxbase + 0x0068);
+ writel(0, iomuxbase + 0x0380);
+
+ vf610_uart_setup_ll();
+}
+
+extern char __dtb_vf610_twr_start[];
+
+ENTRY_FUNCTION(start_vf610_twr, r0, r1, r2)
+{
+ int i;
+ void *fdt;
+ void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR);
+
+ vf610_cpu_lowlevel_init();
+
+ for (i = 0; i < VF610_MSCM_IRSPRC_NUM; i++)
+ writew(VF610_MSCM_IRSPRC_CP0_EN,
+ mscm + VF610_MSCM_IRSPRC(i));
+
+ if (IS_ENABLED(CONFIG_DEBUG_LL))
+ setup_uart();
+
+ fdt = __dtb_vf610_twr_start - get_runtime_offset();
+ barebox_arm_entry(0x80000000, SZ_128M, fdt);
+}
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 8d8d1fb..607c620 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -78,5 +78,6 @@ pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
pbl-dtb-$(CONFIG_MACH_VSCOM_BALTOS) += am335x-baltos-minimal.dtb.o
+pbl-dtb-$(CONFIG_MACH_VF610_TWR) += vf610-twr.dtb.o
clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts *.dtb.lzo
diff --git a/arch/arm/dts/vf610-twr.dts b/arch/arm/dts/vf610-twr.dts
new file mode 100644
index 0000000..54b4435
--- /dev/null
+++ b/arch/arm/dts/vf610-twr.dts
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <arm/vf610-twr.dts>
+
+&usbdev0 {
+ status = "disabled";
+};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index cfbaaa2..5f4fdc6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -337,6 +337,10 @@ config MACH_CM_FX6
bool "CM FX6"
select ARCH_IMX6
+config MACH_VF610_TWR
+ bool "Freescale VF610 Tower Board"
+ select ARCH_VF610
+
endif
# ----------------------------------------------------------
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 8db9c75..983d896 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -403,3 +403,8 @@ pblx-$(CONFIG_MACH_ELTEC_HIPERCAM) += start_imx6dl_eltec_hipercam
CFG_start_imx6dl_eltec_hipercam.pblx.imximg = $(board)/eltec-hipercam/flash-header-eltec-hipercam.imxcfg
FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblx.imximg
image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img
+
+pblx-$(CONFIG_MACH_VF610_TWR) += start_vf610_twr
+CFG_start_vf610_twr.pblx.imximg = $(board)/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
+FILE_barebox-vf610-twr.img = start_vf610_twr.pblx.imximg
+image-$(CONFIG_MACH_VF610_TWR) += barebox-vf610-twr.img
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH v2 09/28] clk: Port of_clk_set_defaults()
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Port of_clk_set_defautls() from Linux kernel in order to support DT
configurations that require it (e. g. Vybrid).
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/clk/Makefile | 2 +-
drivers/clk/clk-conf.c | 144 +++++++++++++++++++++++++++++++++++++++++++
drivers/clk/clk.c | 2 +
include/linux/clk/clk-conf.h | 14 +++++
4 files changed, 161 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/clk-conf.c
create mode 100644 include/linux/clk/clk-conf.h
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 47ed7b1..0fe8f1e 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,6 +1,6 @@
obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \
clk-mux.o clk-gate.o clk-composite.o \
- clk-fractional-divider.o
+ clk-fractional-divider.o clk-conf.o
obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
obj-$(CONFIG_ARCH_MVEBU) += mvebu/
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
new file mode 100644
index 0000000..961fad8
--- /dev/null
+++ b/drivers/clk/clk-conf.c
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <io.h>
+#include <malloc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/clk/clk-conf.h>
+
+static int __set_clk_parents(struct device_node *node, bool clk_supplier)
+{
+ struct of_phandle_args clkspec;
+ int index, rc, num_parents;
+ struct clk *clk, *pclk;
+
+ num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells");
+ if (num_parents == -EINVAL)
+ pr_err("clk: invalid value of clock-parents property at %s\n",
+ node->full_name);
+
+ for (index = 0; index < num_parents; index++) {
+ rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return rc;
+ }
+ if (clkspec.np == node && !clk_supplier)
+ return 0;
+ pclk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(pclk)) {
+ pr_warn("clk: couldn't get parent clock %d for %s\n",
+ index, node->full_name);
+ return PTR_ERR(pclk);
+ }
+
+ rc = of_parse_phandle_with_args(node, "assigned-clocks",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0)
+ goto err;
+ if (clkspec.np == node && !clk_supplier) {
+ rc = 0;
+ goto err;
+ }
+ clk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(clk)) {
+ pr_warn("clk: couldn't get parent clock %d for %s\n",
+ index, node->full_name);
+ rc = PTR_ERR(clk);
+ goto err;
+ }
+
+ rc = clk_set_parent(clk, pclk);
+ if (rc < 0)
+ pr_err("clk: failed to reparent %s to %s: %d\n",
+ __clk_get_name(clk), __clk_get_name(pclk), rc);
+ clk_put(clk);
+ clk_put(pclk);
+ }
+ return 0;
+err:
+ clk_put(pclk);
+ return rc;
+}
+
+static int __set_clk_rates(struct device_node *node, bool clk_supplier)
+{
+ struct of_phandle_args clkspec;
+ struct property *prop;
+ const __be32 *cur;
+ int rc, index = 0;
+ struct clk *clk;
+ u32 rate;
+
+ of_property_for_each_u32(node, "assigned-clock-rates", prop, cur, rate) {
+ if (rate) {
+ rc = of_parse_phandle_with_args(node, "assigned-clocks",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return rc;
+ }
+ if (clkspec.np == node && !clk_supplier)
+ return 0;
+
+ clk = of_clk_get_from_provider(&clkspec);
+ if (IS_ERR(clk)) {
+ pr_warn("clk: couldn't get clock %d for %s\n",
+ index, node->full_name);
+ return PTR_ERR(clk);
+ }
+
+ rc = clk_set_rate(clk, rate);
+ if (rc < 0)
+ pr_err("clk: couldn't set %s clk rate to %d (%d), current rate: %ld\n",
+ __clk_get_name(clk), rate, rc,
+ clk_get_rate(clk));
+ clk_put(clk);
+ }
+ index++;
+ }
+ return 0;
+}
+
+/**
+ * of_clk_set_defaults() - parse and set assigned clocks configuration
+ * @node: device node to apply clock settings for
+ * @clk_supplier: true if clocks supplied by @node should also be considered
+ *
+ * This function parses 'assigned-{clocks/clock-parents/clock-rates}' properties
+ * and sets any specified clock parents and rates. The @clk_supplier argument
+ * should be set to true if @node may be also a clock supplier of any clock
+ * listed in its 'assigned-clocks' or 'assigned-clock-parents' properties.
+ * If @clk_supplier is false the function exits returning 0 as soon as it
+ * determines the @node is also a supplier of any of the clocks.
+ */
+int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
+{
+ int rc;
+
+ if (!node)
+ return 0;
+
+ rc = __set_clk_parents(node, clk_supplier);
+ if (rc < 0)
+ return rc;
+
+ return __set_clk_rates(node, clk_supplier);
+}
+EXPORT_SYMBOL_GPL(of_clk_set_defaults);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a38f339..28a1be5 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -19,6 +19,7 @@
#include <malloc.h>
#include <linux/clk.h>
#include <linux/err.h>
+#include <linux/clk/clk-conf.h>
static LIST_HEAD(clks);
@@ -525,6 +526,7 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
if (force || parent_ready(clk_provider->np)) {
clk_provider->clk_init_cb(clk_provider->np);
+ of_clk_set_defaults(clk_provider->np, true);
list_del(&clk_provider->node);
free(clk_provider);
diff --git a/include/linux/clk/clk-conf.h b/include/linux/clk/clk-conf.h
new file mode 100644
index 0000000..0b8a973
--- /dev/null
+++ b/include/linux/clk/clk-conf.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2014 Samsung Electronics Co., Ltd.
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/types.h>
+
+struct device_node;
+int of_clk_set_defaults(struct device_node *node, bool clk_supplier);
+
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH v2 03/28] i.MX: Add DEBUG_LL hooks for VF610
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Add code to support DEBUG_LL functionality on VF610/Vybrid platform.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
arch/arm/mach-imx/include/mach/debug_ll.h | 27 ++-
common/Kconfig | 10 +-
include/serial/lpuart.h | 281 ++++++++++++++++++++++++++++++
3 files changed, 316 insertions(+), 2 deletions(-)
create mode 100644 include/serial/lpuart.h
diff --git a/arch/arm/mach-imx/include/mach/debug_ll.h b/arch/arm/mach-imx/include/mach/debug_ll.h
index 5c2db6c..a132f3c 100644
--- a/arch/arm/mach-imx/include/mach/debug_ll.h
+++ b/arch/arm/mach-imx/include/mach/debug_ll.h
@@ -14,8 +14,10 @@
#include <mach/imx51-regs.h>
#include <mach/imx53-regs.h>
#include <mach/imx6-regs.h>
+#include <mach/vf610-regs.h>
#include <serial/imx-uart.h>
+#include <serial/lpuart.h>
#ifdef CONFIG_DEBUG_LL
@@ -42,6 +44,8 @@
#define IMX_DEBUG_SOC MX53
#elif defined CONFIG_DEBUG_IMX6Q_UART
#define IMX_DEBUG_SOC MX6
+#elif defined CONFIG_DEBUG_VF610_UART
+#define IMX_DEBUG_SOC VF610
#else
#error "unknown i.MX debug uart soc type"
#endif
@@ -74,6 +78,13 @@ static inline void imx6_uart_setup_ll(void)
imx6_uart_setup(base);
}
+static inline void vf610_uart_setup_ll(void)
+{
+ void *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC, CONFIG_DEBUG_IMX_UART_PORT));
+
+ lpuart_setup(base, 66000000);
+}
+
static inline void PUTC_LL(int c)
{
void __iomem *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC,
@@ -82,14 +93,19 @@ static inline void PUTC_LL(int c)
if (!base)
return;
- imx_uart_putc(base, c);
+ if (IS_ENABLED(CONFIG_DEBUG_VF610_UART))
+ lpuart_putc(base, c);
+ else
+ imx_uart_putc(base, c);
}
+
#else
static inline void imx50_uart_setup_ll(void) {}
static inline void imx51_uart_setup_ll(void) {}
static inline void imx53_uart_setup_ll(void) {}
static inline void imx6_uart_setup_ll(void) {}
+static inline void vf610_uart_setup_ll(void) {}
#endif /* CONFIG_DEBUG_LL */
@@ -115,4 +131,13 @@ static inline void imx53_ungate_all_peripherals(void)
imx_ungate_all_peripherals(IOMEM(MX53_CCM_BASE_ADDR));
}
+static inline void vf610_ungate_all_peripherals(void)
+{
+ void __iomem *ccmbase = IOMEM(VF610_CCM_BASE_ADDR);
+ int i;
+
+ for (i = 0x40; i <= 0x6c; i += 4)
+ writel(0xffffffff, ccmbase + i);
+}
+
#endif /* __MACH_DEBUG_LL_H__ */
diff --git a/common/Kconfig b/common/Kconfig
index efd1949..ed472a0 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -1071,6 +1071,13 @@ config DEBUG_IMX6Q_UART
Say Y here if you want kernel low-level debugging support
on i.MX6Q.
+config DEBUG_VF610_UART
+ bool "VF610 Debug UART"
+ depends on ARCH_VF610
+ help
+ Say Y here if you want kernel low-level debugging support
+ on VF610.
+
config DEBUG_OMAP3_UART
bool "OMAP3 Debug UART"
depends on ARCH_OMAP3
@@ -1111,7 +1118,8 @@ config DEBUG_IMX_UART_PORT
DEBUG_IMX51_UART || \
DEBUG_IMX53_UART || \
DEBUG_IMX6Q_UART || \
- DEBUG_IMX6SL_UART
+ DEBUG_IMX6SL_UART || \
+ DEBUG_VF610_UART
default 1
depends on ARCH_IMX
help
diff --git a/include/serial/lpuart.h b/include/serial/lpuart.h
new file mode 100644
index 0000000..917f644
--- /dev/null
+++ b/include/serial/lpuart.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2016 Zodiac Inflight Innovation
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on code found in Linux kernel and U-Boot.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __LPUART_H__
+#define __LPUART_H__
+
+
+/* All registers are 8-bit width */
+#define UARTBDH 0x00
+#define UARTBDL 0x01
+#define UARTCR1 0x02
+#define UARTCR2 0x03
+#define UARTSR1 0x04
+#define UARTCR3 0x06
+#define UARTDR 0x07
+#define UARTCR4 0x0a
+#define UARTCR5 0x0b
+#define UARTMODEM 0x0d
+#define UARTPFIFO 0x10
+#define UARTCFIFO 0x11
+#define UARTSFIFO 0x12
+#define UARTTWFIFO 0x13
+#define UARTTCFIFO 0x14
+#define UARTRWFIFO 0x15
+#define UARTRCFIFO 0x16
+
+#define UARTBDH_LBKDIE 0x80
+#define UARTBDH_RXEDGIE 0x40
+#define UARTBDH_SBR_MASK 0x1f
+
+#define UARTCR1_LOOPS 0x80
+#define UARTCR1_RSRC 0x20
+#define UARTCR1_M 0x10
+#define UARTCR1_WAKE 0x08
+#define UARTCR1_ILT 0x04
+#define UARTCR1_PE 0x02
+#define UARTCR1_PT 0x01
+
+#define UARTCR2_TIE 0x80
+#define UARTCR2_TCIE 0x40
+#define UARTCR2_RIE 0x20
+#define UARTCR2_ILIE 0x10
+#define UARTCR2_TE 0x08
+#define UARTCR2_RE 0x04
+#define UARTCR2_RWU 0x02
+#define UARTCR2_SBK 0x01
+
+#define UARTSR1_TDRE 0x80
+#define UARTSR1_TC 0x40
+#define UARTSR1_RDRF 0x20
+#define UARTSR1_IDLE 0x10
+#define UARTSR1_OR 0x08
+#define UARTSR1_NF 0x04
+#define UARTSR1_FE 0x02
+#define UARTSR1_PE 0x01
+
+#define UARTCR3_R8 0x80
+#define UARTCR3_T8 0x40
+#define UARTCR3_TXDIR 0x20
+#define UARTCR3_TXINV 0x10
+#define UARTCR3_ORIE 0x08
+#define UARTCR3_NEIE 0x04
+#define UARTCR3_FEIE 0x02
+#define UARTCR3_PEIE 0x01
+
+#define UARTCR4_MAEN1 0x80
+#define UARTCR4_MAEN2 0x40
+#define UARTCR4_M10 0x20
+#define UARTCR4_BRFA_MASK 0x1f
+#define UARTCR4_BRFA_OFF 0
+
+#define UARTCR5_TDMAS 0x80
+#define UARTCR5_RDMAS 0x20
+
+#define UARTMODEM_RXRTSE 0x08
+#define UARTMODEM_TXRTSPOL 0x04
+#define UARTMODEM_TXRTSE 0x02
+#define UARTMODEM_TXCTSE 0x01
+
+#define UARTPFIFO_TXFE 0x80
+#define UARTPFIFO_FIFOSIZE_MASK 0x7
+#define UARTPFIFO_TXSIZE_OFF 4
+#define UARTPFIFO_RXFE 0x08
+#define UARTPFIFO_RXSIZE_OFF 0
+
+#define UARTCFIFO_TXFLUSH 0x80
+#define UARTCFIFO_RXFLUSH 0x40
+#define UARTCFIFO_RXOFE 0x04
+#define UARTCFIFO_TXOFE 0x02
+#define UARTCFIFO_RXUFE 0x01
+
+#define UARTSFIFO_TXEMPT 0x80
+#define UARTSFIFO_RXEMPT 0x40
+#define UARTSFIFO_RXOF 0x04
+#define UARTSFIFO_TXOF 0x02
+#define UARTSFIFO_RXUF 0x01
+
+/* 32-bit register defination */
+#define UARTBAUD 0x00
+#define UARTSTAT 0x04
+#define UARTCTRL 0x08
+#define UARTDATA 0x0C
+#define UARTMATCH 0x10
+#define UARTMODIR 0x14
+#define UARTFIFO 0x18
+#define UARTWATER 0x1c
+
+#define UARTBAUD_MAEN1 0x80000000
+#define UARTBAUD_MAEN2 0x40000000
+#define UARTBAUD_M10 0x20000000
+#define UARTBAUD_TDMAE 0x00800000
+#define UARTBAUD_RDMAE 0x00200000
+#define UARTBAUD_MATCFG 0x00400000
+#define UARTBAUD_BOTHEDGE 0x00020000
+#define UARTBAUD_RESYNCDIS 0x00010000
+#define UARTBAUD_LBKDIE 0x00008000
+#define UARTBAUD_RXEDGIE 0x00004000
+#define UARTBAUD_SBNS 0x00002000
+#define UARTBAUD_SBR 0x00000000
+#define UARTBAUD_SBR_MASK 0x1fff
+
+#define UARTSTAT_LBKDIF 0x80000000
+#define UARTSTAT_RXEDGIF 0x40000000
+#define UARTSTAT_MSBF 0x20000000
+#define UARTSTAT_RXINV 0x10000000
+#define UARTSTAT_RWUID 0x08000000
+#define UARTSTAT_BRK13 0x04000000
+#define UARTSTAT_LBKDE 0x02000000
+#define UARTSTAT_RAF 0x01000000
+#define UARTSTAT_TDRE 0x00800000
+#define UARTSTAT_TC 0x00400000
+#define UARTSTAT_RDRF 0x00200000
+#define UARTSTAT_IDLE 0x00100000
+#define UARTSTAT_OR 0x00080000
+#define UARTSTAT_NF 0x00040000
+#define UARTSTAT_FE 0x00020000
+#define UARTSTAT_PE 0x00010000
+#define UARTSTAT_MA1F 0x00008000
+#define UARTSTAT_M21F 0x00004000
+
+#define UARTCTRL_R8T9 0x80000000
+#define UARTCTRL_R9T8 0x40000000
+#define UARTCTRL_TXDIR 0x20000000
+#define UARTCTRL_TXINV 0x10000000
+#define UARTCTRL_ORIE 0x08000000
+#define UARTCTRL_NEIE 0x04000000
+#define UARTCTRL_FEIE 0x02000000
+#define UARTCTRL_PEIE 0x01000000
+#define UARTCTRL_TIE 0x00800000
+#define UARTCTRL_TCIE 0x00400000
+#define UARTCTRL_RIE 0x00200000
+#define UARTCTRL_ILIE 0x00100000
+#define UARTCTRL_TE 0x00080000
+#define UARTCTRL_RE 0x00040000
+#define UARTCTRL_RWU 0x00020000
+#define UARTCTRL_SBK 0x00010000
+#define UARTCTRL_MA1IE 0x00008000
+#define UARTCTRL_MA2IE 0x00004000
+#define UARTCTRL_IDLECFG 0x00000100
+#define UARTCTRL_LOOPS 0x00000080
+#define UARTCTRL_DOZEEN 0x00000040
+#define UARTCTRL_RSRC 0x00000020
+#define UARTCTRL_M 0x00000010
+#define UARTCTRL_WAKE 0x00000008
+#define UARTCTRL_ILT 0x00000004
+#define UARTCTRL_PE 0x00000002
+#define UARTCTRL_PT 0x00000001
+
+#define UARTDATA_NOISY 0x00008000
+#define UARTDATA_PARITYE 0x00004000
+#define UARTDATA_FRETSC 0x00002000
+#define UARTDATA_RXEMPT 0x00001000
+#define UARTDATA_IDLINE 0x00000800
+#define UARTDATA_MASK 0x3ff
+
+#define UARTMODIR_IREN 0x00020000
+#define UARTMODIR_TXCTSSRC 0x00000020
+#define UARTMODIR_TXCTSC 0x00000010
+#define UARTMODIR_RXRTSE 0x00000008
+#define UARTMODIR_TXRTSPOL 0x00000004
+#define UARTMODIR_TXRTSE 0x00000002
+#define UARTMODIR_TXCTSE 0x00000001
+
+#define UARTFIFO_TXEMPT 0x00800000
+#define UARTFIFO_RXEMPT 0x00400000
+#define UARTFIFO_TXOF 0x00020000
+#define UARTFIFO_RXUF 0x00010000
+#define UARTFIFO_TXFLUSH 0x00008000
+#define UARTFIFO_RXFLUSH 0x00004000
+#define UARTFIFO_TXOFE 0x00000200
+#define UARTFIFO_RXUFE 0x00000100
+#define UARTFIFO_TXFE 0x00000080
+#define UARTFIFO_FIFOSIZE_MASK 0x7
+#define UARTFIFO_TXSIZE_OFF 4
+#define UARTFIFO_RXFE 0x00000008
+#define UARTFIFO_RXSIZE_OFF 0
+
+#define UARTWATER_COUNT_MASK 0xff
+#define UARTWATER_TXCNT_OFF 8
+#define UARTWATER_RXCNT_OFF 24
+#define UARTWATER_WATER_MASK 0xff
+#define UARTWATER_TXWATER_OFF 0
+#define UARTWATER_RXWATER_OFF 16
+
+#define FSL_UART_RX_DMA_BUFFER_SIZE 64
+
+static inline void lpuart_setbrg(void __iomem *base,
+ unsigned int refclock,
+ unsigned int baudrate)
+{
+ unsigned int bfra;
+ u16 sbr;
+
+ sbr = (u16) (refclock / (16 * baudrate));
+
+ writeb(sbr >> 8, base + UARTBDH);
+ writeb(sbr & 0xff, base + UARTBDL);
+
+ bfra = DIV_ROUND_UP(2 * refclock, baudrate) - 32 * sbr;
+ bfra &= UARTCR4_BRFA_MASK;
+ writeb(bfra, base + UARTCR4);
+}
+
+static inline void lpuart_setup_with_fifo(void __iomem *base,
+ unsigned int refclock,
+ unsigned int twfifo)
+{
+ /* Disable UART */
+ writeb(0, base + UARTCR2);
+ writeb(0, base + UARTMODEM);
+ writeb(0, base + UARTCR1);
+
+ if (twfifo) {
+ writeb(UARTPFIFO_TXFE | UARTPFIFO_RXFE, base + UARTPFIFO);
+ writeb((u8)twfifo, base + UARTTWFIFO);
+ } else {
+ writeb(0, base + UARTPFIFO);
+ writeb(0, base + UARTTWFIFO);
+ }
+ writeb(1, base + UARTRWFIFO);
+ writeb(UARTCFIFO_RXFLUSH | UARTCFIFO_TXFLUSH, base + UARTCFIFO);
+
+ lpuart_setbrg(base, refclock, CONFIG_BAUDRATE);
+
+ writeb(UARTCR2_TE | UARTCR2_RE, base + UARTCR2);
+}
+
+static inline void lpuart_setup(void __iomem *base,
+ unsigned int refclock)
+{
+ lpuart_setup_with_fifo(base, refclock, 0x00);
+}
+
+static inline void lpuart_putc(void __iomem *base, int c)
+{
+ if (!(readb(base + UARTCR2) & UARTCR2_TE))
+ return;
+
+ while (!(readb(base + UARTSR1) & UARTSR1_TDRE));
+
+ writeb(c, base + UARTDR);
+}
+
+#endif
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH v2 08/28] clk: Port clock dependency resolution code
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Port the clock dependency resolution algorithm utilized by Linux
kernel's version of of_clk_init(), to allow for SoCs whose DT clock
configuration reqires such behaviour for correct initialization (Vybrid
is one such example).
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/clk/clk.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 82 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 630a84d..a38f339 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -404,7 +404,7 @@ EXPORT_SYMBOL_GPL(of_clk_del_provider);
struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
{
struct of_clk_provider *provider;
- struct clk *clk = ERR_PTR(-ENOENT);
+ struct clk *clk = ERR_PTR(-EPROBE_DEFER);
/* Check if we have such a provider in our array */
list_for_each_entry(provider, &of_clk_providers, link) {
@@ -437,6 +437,47 @@ char *of_clk_get_parent_name(struct device_node *np, unsigned int index)
}
EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
+struct clock_provider {
+ of_clk_init_cb_t clk_init_cb;
+ struct device_node *np;
+ struct list_head node;
+};
+
+/*
+ * This function looks for a parent clock. If there is one, then it
+ * checks that the provider for this parent clock was initialized, in
+ * this case the parent clock will be ready.
+ */
+static int parent_ready(struct device_node *np)
+{
+ int i = 0;
+
+ while (true) {
+ struct clk *clk = of_clk_get(np, i);
+
+ /* this parent is ready we can check the next one */
+ if (!IS_ERR(clk)) {
+ clk_put(clk);
+ i++;
+ continue;
+ }
+
+ /* at least one parent is not ready, we exit now */
+ if (PTR_ERR(clk) == -EPROBE_DEFER)
+ return 0;
+
+ /*
+ * Here we make assumption that the device tree is
+ * written correctly. So an error means that there is
+ * no more parent. As we didn't exit yet, then the
+ * previous parent are ready. If there is no clock
+ * parent, no need to wait for them, then we can
+ * consider their absence as being ready
+ */
+ return 1;
+ }
+}
+
/**
* of_clk_init() - Scan and init clock providers from the DT
* @root: parent of the first level to probe or NULL for the root of the tree
@@ -449,8 +490,11 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
*/
int of_clk_init(struct device_node *root, const struct of_device_id *matches)
{
+ struct clock_provider *clk_provider, *next;
+ bool is_init_done;
+ bool force = false;
+ LIST_HEAD(clk_provider_list);
const struct of_device_id *match;
- int rc;
if (!root)
root = of_find_node_by_path("/");
@@ -459,12 +503,43 @@ int of_clk_init(struct device_node *root, const struct of_device_id *matches)
if (!matches)
matches = __clk_of_table_start;
+ /* First prepare the list of the clocks providers */
for_each_matching_node_and_match(root, matches, &match) {
- of_clk_init_cb_t clk_init_cb = (of_clk_init_cb_t)match->data;
- rc = clk_init_cb(root);
- if (rc)
- pr_err("%s: failed to init clock for %s: %d\n",
- __func__, root->full_name, rc);
+ struct clock_provider *parent;
+
+ if (!of_device_is_available(root))
+ continue;
+
+ parent = xzalloc(sizeof(*parent));
+
+ parent->clk_init_cb = match->data;
+ parent->np = root;
+ list_add_tail(&parent->node, &clk_provider_list);
+ }
+
+ while (!list_empty(&clk_provider_list)) {
+ is_init_done = false;
+ list_for_each_entry_safe(clk_provider, next,
+ &clk_provider_list, node) {
+
+ if (force || parent_ready(clk_provider->np)) {
+
+ clk_provider->clk_init_cb(clk_provider->np);
+
+ list_del(&clk_provider->node);
+ free(clk_provider);
+ is_init_done = true;
+ }
+ }
+
+ /*
+ * We didn't manage to initialize any of the
+ * remaining providers during the last loop, so now we
+ * initialize all the remaining ones unconditionally
+ * in case the clock parent was not mandatory
+ */
+ if (!is_init_done)
+ force = true;
}
return 0;
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH v2 06/28] pinctrl: Add provisions to control GPIO pin direction
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Some SoC (of which Vybrid is a one example) relegate GPIO direction
control to their pinmux IP block, instead of having that functionality
within GPIO IP. Add provisions to control that aspect of pinmux to
support such SoCs.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/pinctrl/pinctrl.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
include/pinctrl.h | 21 +++++++++++++++++++++
2 files changed, 66 insertions(+)
diff --git a/drivers/pinctrl/pinctrl.c b/drivers/pinctrl/pinctrl.c
index e7b08a2..bef4fcd 100644
--- a/drivers/pinctrl/pinctrl.c
+++ b/drivers/pinctrl/pinctrl.c
@@ -24,6 +24,51 @@
static LIST_HEAD(pinctrl_list);
+static struct pinctrl_device *pin_to_pinctrl(unsigned int pin)
+{
+ struct pinctrl_device *pinctrl;
+
+ list_for_each_entry(pinctrl, &pinctrl_list, list)
+ if (pin > pinctrl->base &&
+ pin < pinctrl->base + pinctrl->npins)
+ return pinctrl;
+ return NULL;
+}
+
+static int pinctrl_gpio_direction(unsigned pin, bool input)
+{
+ struct pinctrl_device *pinctrl = pin_to_pinctrl(pin);
+
+ if (!pinctrl)
+ return -EINVAL;
+
+ BUG_ON(!pinctrl->ops->set_direction);
+
+ return pinctrl->ops->set_direction(pinctrl, pin, input);
+}
+
+int pinctrl_gpio_direction_input(unsigned int pin)
+{
+ return pinctrl_gpio_direction(pin, true);
+}
+
+int pinctrl_gpio_direction_output(unsigned int pin)
+{
+ return pinctrl_gpio_direction(pin, false);
+}
+
+int pinctrl_gpio_get_direction(unsigned pin)
+{
+ struct pinctrl_device *pinctrl = pin_to_pinctrl(pin);
+
+ if (!pinctrl)
+ return -EINVAL;
+
+ BUG_ON(!pinctrl->ops->get_direction);
+
+ return pinctrl->ops->get_direction(pinctrl, pin);
+}
+
static struct pinctrl_device *find_pinctrl(struct device_node *node)
{
struct pinctrl_device *pdev;
diff --git a/include/pinctrl.h b/include/pinctrl.h
index 0f03b10..0fde3f9 100644
--- a/include/pinctrl.h
+++ b/include/pinctrl.h
@@ -5,6 +5,8 @@ struct pinctrl_device;
struct pinctrl_ops {
int (*set_state)(struct pinctrl_device *, struct device_node *);
+ int (*set_direction)(struct pinctrl_device *, unsigned int, bool);
+ int (*get_direction)(struct pinctrl_device *, unsigned int);
};
struct pinctrl_device {
@@ -12,6 +14,7 @@ struct pinctrl_device {
struct pinctrl_ops *ops;
struct list_head list;
struct device_node *node;
+ unsigned int base, npins;
};
int pinctrl_register(struct pinctrl_device *pdev);
@@ -22,6 +25,9 @@ int pinctrl_select_state(struct device_d *dev, const char *state);
int pinctrl_select_state_default(struct device_d *dev);
int of_pinctrl_select_state(struct device_node *np, const char *state);
int of_pinctrl_select_state_default(struct device_node *np);
+int pinctrl_gpio_direction_input(unsigned pin);
+int pinctrl_gpio_direction_output(unsigned int pin);
+int pinctrl_gpio_get_direction(unsigned pin);
#else
static inline int pinctrl_select_state(struct device_d *dev, const char *state)
{
@@ -42,6 +48,21 @@ static inline int of_pinctrl_select_state_default(struct device_node *np)
{
return -ENODEV;
}
+
+static inline int pinctrl_gpio_direction_input(unsigend pin)
+{
+ return -ENOTSUPP;
+}
+
+static inline int pinctrl_gpio_direction_output(unsigned int pin)
+{
+ return -ENOTSUPP;
+}
+
+static inline int pinctrl_gpio_get_direction(unsigned pin)
+{
+ return -ENOTSUPP;
+}
#endif
#endif /* PINCTRL_H */
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH v2 04/28] i.MX: scripts: Add "vf610" soc to imx-image
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Needed in order to support Vybrid SoCs.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
scripts/imx/imx.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c
index c8ee309..bd48321 100644
--- a/scripts/imx/imx.c
+++ b/scripts/imx/imx.c
@@ -223,6 +223,7 @@ static struct soc_type socs[] = {
{ .name = "imx51", .header_version = 1, .cpu_type = IMX_CPU_IMX51 },
{ .name = "imx53", .header_version = 2, .cpu_type = IMX_CPU_IMX53 },
{ .name = "imx6", .header_version = 2, .cpu_type = IMX_CPU_IMX6 },
+ { .name = "vf610", .header_version = 2, .cpu_type = IMX_CPU_VF610 },
};
static int do_soc(struct config_data *data, int argc, char *argv[])
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH v2 01/28] i.MX: Add primitive functions for VF610 family
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Add very basic functions to support VF610 family.
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
arch/arm/mach-imx/Kconfig | 10 ++++++++++
arch/arm/mach-imx/cpu_init.c | 5 +++++
arch/arm/mach-imx/imx.c | 4 ++++
arch/arm/mach-imx/include/mach/generic.h | 13 +++++++++++++
arch/arm/mach-imx/include/mach/imx_cpu_types.h | 1 +
5 files changed, 33 insertions(+)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index f23af99..cfbaaa2 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -149,6 +149,16 @@ config ARCH_IMX6SX
select OFTREE
select COMMON_CLK_OF_PROVIDER
+config ARCH_VF610
+ bool
+ select ARCH_HAS_L2X0
+ select ARCH_HAS_FEC_IMX
+ select CPU_V7
+ select PINCTRL
+ select OFTREE
+ select COMMON_CLK
+ select COMMON_CLK_OF_PROVIDER
+
config IMX_MULTI_BOARDS
bool "Allow multiple boards to be selected"
select HAVE_PBL_MULTI_IMAGES
diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c
index 7603883..6971d89 100644
--- a/arch/arm/mach-imx/cpu_init.c
+++ b/arch/arm/mach-imx/cpu_init.c
@@ -33,3 +33,8 @@ void imx6_cpu_lowlevel_init(void)
enable_arm_errata_794072_war();
enable_arm_errata_845369_war();
}
+
+void vf610_cpu_lowlevel_init(void)
+{
+ arm_cpu_lowlevel_init();
+}
diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 5ab6afc..eb2adcd 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -63,6 +63,8 @@ static int imx_soc_from_dt(void)
return IMX_CPU_IMX6;
if (of_machine_is_compatible("fsl,imx6qp"))
return IMX_CPU_IMX6;
+ if (of_machine_is_compatible("fsl,vf610"))
+ return IMX_CPU_VF610;
return 0;
}
@@ -99,6 +101,8 @@ static int imx_init(void)
ret = imx53_init();
else if (cpu_is_mx6())
ret = imx6_init();
+ else if (cpu_is_vf610())
+ ret = 0;
else
return -EINVAL;
diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h
index 7c275df..3419450 100644
--- a/arch/arm/mach-imx/include/mach/generic.h
+++ b/arch/arm/mach-imx/include/mach/generic.h
@@ -45,6 +45,7 @@ int imx6_devices_init(void);
void imx5_cpu_lowlevel_init(void);
void imx6_cpu_lowlevel_init(void);
+void vf610_cpu_lowlevel_init(void);
/* There's a off-by-one betweem the gpio bank number and the gpiochip */
/* range e.g. GPIO_1_5 is gpio 5 under linux */
@@ -173,6 +174,18 @@ extern unsigned int __imx_cpu_type;
# define cpu_is_mx6() (0)
#endif
+#ifdef CONFIG_ARCH_VF610
+# ifdef imx_cpu_type
+# undef imx_cpu_type
+# define imx_cpu_type __imx_cpu_type
+# else
+# define imx_cpu_type IMX_CPU_VF610
+# endif
+# define cpu_is_vf610() (imx_cpu_type == IMX_CPU_VF610)
+#else
+# define cpu_is_vf610() (0)
+#endif
+
#define cpu_is_mx23() (0)
#define cpu_is_mx28() (0)
diff --git a/arch/arm/mach-imx/include/mach/imx_cpu_types.h b/arch/arm/mach-imx/include/mach/imx_cpu_types.h
index 8472488..50be0b6 100644
--- a/arch/arm/mach-imx/include/mach/imx_cpu_types.h
+++ b/arch/arm/mach-imx/include/mach/imx_cpu_types.h
@@ -11,5 +11,6 @@
#define IMX_CPU_IMX51 51
#define IMX_CPU_IMX53 53
#define IMX_CPU_IMX6 6
+#define IMX_CPU_VF610 610
#endif /* __MACH_IMX_CPU_TYPES_H */
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH v2 00/28] Vybrid support in Barebox
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
Hi everyone,
It took me a bit more than a month, but I finally put together a
second version (for v1 see [1]) of the Vybrid support patchset.
Some highlights of this version:
- Various code/commit arrangement feedback for v1 is addressed
- Added commit to move all of the i.MX clock code to drivers/clk
(Sascha, we'd probably have to coordinate with your i.MX6ul
patches on this one)
- I2C commit split in two
- clock tree is reconciled with Linux code, since having a custom
version of it proved to be difficult to compare agains Linux's
implementation
- GPIO driver (tested on a custom Vybrid board)
- FEC support (tested on a custom Vybrid board)
Any feedback is, as always, very much appreciated.
Thank you,
Andrey Smirnov
[1] http://lists.infradead.org/pipermail/barebox/2016-October/028225.html
Andrey Smirnov (28):
i.MX: Add primitive functions for VF610 family
i.MX: Add register definitions for VF610 SoC
i.MX: Add DEBUG_LL hooks for VF610
i.MX: scripts: Add "vf610" soc to imx-image
i.MX: Add support for VF610 Tower board
pinctrl: Add provisions to control GPIO pin direction
i.MX: Add pinctrl driver for VF610
clk: Port clock dependency resolution code
clk: Port of_clk_set_defaults()
i.MX: Move clk code from 'mach-imx' to 'drivers'
i.MX: clk: Port imx_clk_gate2_cgr()
i.MX: clk: Add IMX_PLLV3_USB_VF610 support
i.MX: clk: Port imx_check_clocks()
i.MX: clk: Port imx_clk_mux_flags from Linux
i.MX: Add VF610 clock tree initialization code
vf610: Give enet_osc explicit "enet_ext" name
i.MX: Add 'lpuart' serial driver
i.MX: i2c: Use read/write adapter functions
i.MX: i2c: Add Vybrid support
i.MX: esdhc: Do not rely on CPU type for quirks
i.MX: esdhc: Request "per" clock explicitly
i.MX: Kconfig: Enable OCOTP on Vybrid
i.MX: ocotp: Remove unused #define
i.MX: ocotp: Account for shadow memory gaps
i.MX: ocotp: Add Vybrid support
i.MX: fec: Enable all clocks specified for FEC
i.MX: fec: Add support for Vybrid variant
gpio: Add GPIO driver for Vybrid
arch/arm/boards/Makefile | 1 +
arch/arm/boards/freescale-vf610-twr/Makefile | 3 +
.../flash-header-vf610-twr.imxcfg | 278 +++++++++++
arch/arm/boards/freescale-vf610-twr/lowlevel.c | 45 ++
arch/arm/dts/Makefile | 1 +
arch/arm/dts/vf610-twr.dts | 18 +
arch/arm/mach-imx/Kconfig | 16 +-
arch/arm/mach-imx/Makefile | 23 +-
arch/arm/mach-imx/clk-gate-exclusive.c | 103 ----
arch/arm/mach-imx/clk-gate2.c | 145 ------
arch/arm/mach-imx/clk-imx1.c | 121 -----
arch/arm/mach-imx/clk-imx21.c | 196 --------
arch/arm/mach-imx/clk-imx25.c | 200 --------
arch/arm/mach-imx/clk-imx27.c | 270 ----------
arch/arm/mach-imx/clk-imx31.c | 146 ------
arch/arm/mach-imx/clk-imx35.c | 219 ---------
arch/arm/mach-imx/clk-imx5.c | 533 --------------------
arch/arm/mach-imx/clk-imx6.c | 541 ---------------------
arch/arm/mach-imx/clk-imx6sx.c | 483 ------------------
arch/arm/mach-imx/clk-pfd.c | 148 ------
arch/arm/mach-imx/clk-pllv1.c | 95 ----
arch/arm/mach-imx/clk-pllv2.c | 230 ---------
arch/arm/mach-imx/clk-pllv3.c | 326 -------------
arch/arm/mach-imx/clk.h | 104 ----
arch/arm/mach-imx/cpu_init.c | 5 +
arch/arm/mach-imx/imx.c | 4 +
arch/arm/mach-imx/include/mach/clock-vf610.h | 171 +++++++
arch/arm/mach-imx/include/mach/debug_ll.h | 27 +-
arch/arm/mach-imx/include/mach/generic.h | 13 +
arch/arm/mach-imx/include/mach/imx_cpu_types.h | 1 +
arch/arm/mach-imx/include/mach/iomux-vf610.h | 226 +++++++++
arch/arm/mach-imx/include/mach/vf610-regs.h | 110 +++++
arch/arm/mach-imx/ocotp.c | 51 +-
common/Kconfig | 10 +-
drivers/clk/Makefile | 3 +-
drivers/clk/clk-conf.c | 144 ++++++
drivers/clk/clk.c | 91 +++-
drivers/clk/imx/Makefile | 21 +
drivers/clk/imx/clk-gate-exclusive.c | 103 ++++
drivers/clk/imx/clk-gate2.c | 147 ++++++
drivers/clk/imx/clk-imx1.c | 121 +++++
drivers/clk/imx/clk-imx21.c | 196 ++++++++
drivers/clk/imx/clk-imx25.c | 200 ++++++++
drivers/clk/imx/clk-imx27.c | 270 ++++++++++
drivers/clk/imx/clk-imx31.c | 146 ++++++
drivers/clk/imx/clk-imx35.c | 219 +++++++++
drivers/clk/imx/clk-imx5.c | 533 ++++++++++++++++++++
drivers/clk/imx/clk-imx6.c | 541 +++++++++++++++++++++
drivers/clk/imx/clk-imx6sx.c | 483 ++++++++++++++++++
drivers/clk/imx/clk-pfd.c | 148 ++++++
drivers/clk/imx/clk-pllv1.c | 95 ++++
drivers/clk/imx/clk-pllv2.c | 230 +++++++++
drivers/clk/imx/clk-pllv3.c | 329 +++++++++++++
drivers/clk/imx/clk-vf610.c | 443 +++++++++++++++++
drivers/clk/imx/clk.c | 21 +
drivers/clk/imx/clk.h | 123 +++++
drivers/gpio/Kconfig | 3 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-vf610.c | 181 +++++++
drivers/i2c/busses/i2c-imx.c | 225 ++++++---
drivers/mci/imx-esdhc.c | 123 ++++-
drivers/net/fec_imx.c | 74 ++-
drivers/net/fec_imx.h | 10 +-
drivers/pinctrl/Kconfig | 5 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-vf610.c | 167 +++++++
drivers/pinctrl/pinctrl.c | 45 ++
drivers/serial/Kconfig | 5 +
drivers/serial/Makefile | 1 +
drivers/serial/serial_lpuart.c | 217 +++++++++
images/Makefile.imx | 5 +
include/linux/clk/clk-conf.h | 14 +
include/pinctrl.h | 21 +
include/serial/lpuart.h | 281 +++++++++++
scripts/imx/imx.c | 1 +
75 files changed, 6870 insertions(+), 3980 deletions(-)
create mode 100644 arch/arm/boards/freescale-vf610-twr/Makefile
create mode 100644 arch/arm/boards/freescale-vf610-twr/flash-header-vf610-twr.imxcfg
create mode 100644 arch/arm/boards/freescale-vf610-twr/lowlevel.c
create mode 100644 arch/arm/dts/vf610-twr.dts
delete mode 100644 arch/arm/mach-imx/clk-gate-exclusive.c
delete mode 100644 arch/arm/mach-imx/clk-gate2.c
delete mode 100644 arch/arm/mach-imx/clk-imx1.c
delete mode 100644 arch/arm/mach-imx/clk-imx21.c
delete mode 100644 arch/arm/mach-imx/clk-imx25.c
delete mode 100644 arch/arm/mach-imx/clk-imx27.c
delete mode 100644 arch/arm/mach-imx/clk-imx31.c
delete mode 100644 arch/arm/mach-imx/clk-imx35.c
delete mode 100644 arch/arm/mach-imx/clk-imx5.c
delete mode 100644 arch/arm/mach-imx/clk-imx6.c
delete mode 100644 arch/arm/mach-imx/clk-imx6sx.c
delete mode 100644 arch/arm/mach-imx/clk-pfd.c
delete mode 100644 arch/arm/mach-imx/clk-pllv1.c
delete mode 100644 arch/arm/mach-imx/clk-pllv2.c
delete mode 100644 arch/arm/mach-imx/clk-pllv3.c
delete mode 100644 arch/arm/mach-imx/clk.h
create mode 100644 arch/arm/mach-imx/include/mach/clock-vf610.h
create mode 100644 arch/arm/mach-imx/include/mach/iomux-vf610.h
create mode 100644 arch/arm/mach-imx/include/mach/vf610-regs.h
create mode 100644 drivers/clk/clk-conf.c
create mode 100644 drivers/clk/imx/Makefile
create mode 100644 drivers/clk/imx/clk-gate-exclusive.c
create mode 100644 drivers/clk/imx/clk-gate2.c
create mode 100644 drivers/clk/imx/clk-imx1.c
create mode 100644 drivers/clk/imx/clk-imx21.c
create mode 100644 drivers/clk/imx/clk-imx25.c
create mode 100644 drivers/clk/imx/clk-imx27.c
create mode 100644 drivers/clk/imx/clk-imx31.c
create mode 100644 drivers/clk/imx/clk-imx35.c
create mode 100644 drivers/clk/imx/clk-imx5.c
create mode 100644 drivers/clk/imx/clk-imx6.c
create mode 100644 drivers/clk/imx/clk-imx6sx.c
create mode 100644 drivers/clk/imx/clk-pfd.c
create mode 100644 drivers/clk/imx/clk-pllv1.c
create mode 100644 drivers/clk/imx/clk-pllv2.c
create mode 100644 drivers/clk/imx/clk-pllv3.c
create mode 100644 drivers/clk/imx/clk-vf610.c
create mode 100644 drivers/clk/imx/clk.c
create mode 100644 drivers/clk/imx/clk.h
create mode 100644 drivers/gpio/gpio-vf610.c
create mode 100644 drivers/pinctrl/pinctrl-vf610.c
create mode 100644 drivers/serial/serial_lpuart.c
create mode 100644 include/linux/clk/clk-conf.h
create mode 100644 include/serial/lpuart.h
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* [PATCH v2 07/28] i.MX: Add pinctrl driver for VF610
From: Andrey Smirnov @ 2016-11-09 16:13 UTC (permalink / raw)
To: barebox; +Cc: Andrey Smirnov
In-Reply-To: <1478708056-7875-1-git-send-email-andrew.smirnov@gmail.com>
Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com>
---
drivers/pinctrl/Kconfig | 5 ++
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinctrl-vf610.c | 167 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 173 insertions(+)
create mode 100644 drivers/pinctrl/pinctrl-vf610.c
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 5c69928..12fff4f 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -77,4 +77,9 @@ config PINCTRL_TEGRA_XUSB
source drivers/pinctrl/mvebu/Kconfig
+config PINCTRL_VF610
+ bool
+ default y if ARCH_VF610
+ help
+ Pinmux controller found on Vybrid VF610 family of SoCs
endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index af9b30d..9450dbb 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -9,5 +9,6 @@ obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o
obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o
obj-$(CONFIG_PINCTRL_TEGRA_XUSB) += pinctrl-tegra-xusb.o
+obj-$(CONFIG_PINCTRL_VF610) += pinctrl-vf610.o
obj-$(CONFIG_ARCH_MVEBU) += mvebu/
diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c
new file mode 100644
index 0000000..b479bf2
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-vf610.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2016 Zodiac Inflight Innovation
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <pinctrl.h>
+#include <malloc.h>
+#include <gpio.h>
+
+enum {
+ PINCTRL_VF610_MUX_LINE_SIZE = 20,
+ PINCTRL_VF610_MUX_SHIFT = 20,
+
+ PINCTRL_VF610_IBE = 1 << 0,
+ PINCTRL_VF610_OBE = 1 << 1,
+ PINCTRL_VF610_xBE = 0b11,
+};
+
+struct pinctrl_vf610 {
+ void __iomem *base;
+ struct pinctrl_device pinctrl;
+};
+
+static int pinctrl_vf610_set_state(struct pinctrl_device *pdev,
+ struct device_node *np)
+{
+ const __be32 *list;
+ int npins, size, i;
+
+ struct pinctrl_vf610 *iomux =
+ container_of(pdev, struct pinctrl_vf610, pinctrl);
+
+ list = of_get_property(np, "fsl,pins", &size);
+ if (!list)
+ return -EINVAL;
+
+ if (!size || size % PINCTRL_VF610_MUX_LINE_SIZE) {
+ dev_err(pdev->dev, "Invalid fsl,pins property in %s\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ npins = size / PINCTRL_VF610_MUX_LINE_SIZE;
+
+ for (i = 0; i < npins; i++) {
+ u32 mux_reg = be32_to_cpu(*list++);
+ u32 input_reg = be32_to_cpu(*list++);
+ u32 mux_val = be32_to_cpu(*list++);
+ u32 input_val = be32_to_cpu(*list++);
+ u32 conf_val = be32_to_cpu(*list++);
+
+ writel(mux_val << PINCTRL_VF610_MUX_SHIFT | conf_val,
+ iomux->base + mux_reg);
+
+ if (input_reg)
+ writel(input_val, iomux->base + input_reg);
+ }
+
+ return 0;
+}
+
+static int pinctrl_vf610_set_direction(struct pinctrl_device *pdev,
+ unsigned int pin, bool input)
+{
+ u32 pad_cr;
+ const u32 off = pin * sizeof(u32);
+ struct pinctrl_vf610 *iomux =
+ container_of(pdev, struct pinctrl_vf610, pinctrl);
+
+ pad_cr = readl(iomux->base + off);
+
+ if (input) {
+ pad_cr |= PINCTRL_VF610_IBE;
+ pad_cr &= ~PINCTRL_VF610_OBE;
+ } else {
+ pad_cr &= ~PINCTRL_VF610_IBE;
+ pad_cr |= PINCTRL_VF610_OBE;
+ }
+
+ writel(pad_cr, iomux->base + off);
+
+ return 0;
+}
+
+static int pinctrl_vf610_get_direction(struct pinctrl_device *pdev,
+ unsigned int pin)
+{
+ const u32 off = pin * sizeof(u32);
+ struct pinctrl_vf610 *iomux =
+ container_of(pdev, struct pinctrl_vf610, pinctrl);
+
+ const u32 pad_cr = readl(iomux->base + off);
+
+ switch (pad_cr & PINCTRL_VF610_xBE) {
+ case PINCTRL_VF610_IBE:
+ return GPIOF_DIR_IN;
+ case PINCTRL_VF610_OBE:
+ return GPIOF_DIR_OUT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static struct pinctrl_ops pinctrl_vf610_ops = {
+ .set_state = pinctrl_vf610_set_state,
+ .set_direction = pinctrl_vf610_set_direction,
+ .get_direction = pinctrl_vf610_get_direction,
+};
+
+static int pinctrl_vf610_probe(struct device_d *dev)
+{
+ int ret;
+ struct resource *io;
+ struct pinctrl_vf610 *iomux;
+
+ iomux = xzalloc(sizeof(*iomux));
+
+ io = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(io))
+ return PTR_ERR(io);
+
+ iomux->base = IOMEM(io->start);
+ iomux->pinctrl.dev = dev;
+ iomux->pinctrl.ops = &pinctrl_vf610_ops;
+ iomux->pinctrl.base = 0;
+ iomux->pinctrl.npins = ARCH_NR_GPIOS;
+
+ ret = pinctrl_register(&iomux->pinctrl);
+ if (ret)
+ free(iomux);
+
+ return ret;
+}
+
+static __maybe_unused struct of_device_id pinctrl_vf610_dt_ids[] = {
+ { .compatible = "fsl,vf610-iomuxc", },
+ { /* sentinel */ }
+};
+
+static struct driver_d pinctrl_vf610_driver = {
+ .name = "vf610-pinctrl",
+ .probe = pinctrl_vf610_probe,
+ .of_compatible = DRV_OF_COMPAT(pinctrl_vf610_dt_ids),
+};
+
+static int pinctrl_vf610_init(void)
+{
+ return platform_driver_register(&pinctrl_vf610_driver);
+}
+postcore_initcall(pinctrl_vf610_init);
--
2.5.5
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* Re: Designware MAC reset timeout after Linux reboot
From: Ian Abbott @ 2016-11-09 14:10 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
In-Reply-To: <d728234e-959a-c21d-7df1-b530355425de@mev.co.uk>
On 08/11/16 12:13, Ian Abbott wrote:
> On 08/11/16 08:08, Sascha Hauer wrote:
>> Hi Ian,
>>
>> On Mon, Nov 07, 2016 at 05:56:51PM +0000, Ian Abbott wrote:
>>> Perhaps the timeout isn't waiting long enough. If I interrupt the 'ifup
>>> eth0' command and display the approriate 'Bus_Mode' register
>>> (0xff703000)
>>> with the 'md' command, the DMAMAC_SRST bit (bit 0) is no longer set:
>>>
>>> barebox@xxxx:/ md -l 0xff703000+4
>>> ff703000: 00020100
>>
>> The timeout is 10ms, this should be way enough. The return value of
>> dwc_ether_init() is not checked, so the driver happily continues with
>> further register writes, I assume there must be something that clears
>> this bit afterwards, either directly or indirectly.
>
> The bit is supposed to clear itself, but I guess something else could be
> clearing it too.
>
> The code to reset the MAC DMA controller in Linux kernel 4.1 is
> dwmac1000_dma_init() in
> "drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c". In Linux kernel
> 4.6, the function is dwmac_dma_reset() in "dwmac_lib.c". In both cases,
> the code to reset the DMA controller is basically as follows:
>
> u32 value = readl(ioaddr + DMA_BUS_MODE);
> int limit;
>
> /* DMA SW reset */
> value |= DMA_BUS_MODE_SFT_RESET;
> writel(value, ioaddr + DMA_BUS_MODE);
> limit = 10;
> while (limit--) {
> if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
> break;
> mdelay(10);
> }
> if (limit < 0)
> return -EBUSY;
>
> It's interesting that it only bothers to check for reset completion
> every 10 ms (timing out after 100 ms), so it must be expecting it to
> take a while!
>
> I'll experiment with the timeout on my board to see if the bit ever
> clears itself.
>
The problem seems to be related to some other problems I've been having
with the Ethernet on this prototype board, which is something to do with
the PHY chip's passive support components (inductors, capacitors, etc.)
This problem manifests as lower-than-expected 'iperf' times when the
Ethernet port is plugged into certain models of Ethernet switch.
I experimented with the timeout in mac_reset() in designware.c, setting
it to 1 second, and printing out a debug message with the time taken for
the reset to complete.
After 20 trials of rebooting from Linux to barebox and issuing the 'ifup
eth0' command, I got a pretty random spread of times between 29.3 and
850.2 ms, with a mean of 312.5 ms. (It looks like a pretty linear
distribution. Some other stats: Q1: 141.4 ms, Median: 240.1 ms, Q3:
480.2 ms, SD: 211.9 ms.)
I ran another trial with the is_timeout() call replaced with
is_timeout_non_interruptible() and got a similar random spread of times
(but smaller than the first trial) from 11.4 ms to 654.6 ms, with a mean
of 266.2 ms.
Both of those trials were performed with the Ethernet port connected to
a 1000 Base-T Ethernet switch.
Now here's the kicker.... If I plug it into a different brand of 1000
Base-T Ethernet switch, the mac_reset() times (after rebooting from
Linux) are more like 360 ns (not ms!). If I plug it into a 100 Base-T
switch, the times are more more like 900 ns to 2300 ns. If I disconnect
it completely, the times are about 360 ns.
For comparison, after running 'ifup eth0' after powering up into
barebox, the mac_reset() times are about 360 ns independent of what the
Ethernet port is plugged into.
I'm still not sure what state my Linux kernel is leaving the Ethernet
controller and PHY in following a reboot, but I'm reasonably confident
the problem is related to the PHY hardware components on my board.
--
-=( Ian Abbott @ MEV Ltd. E-mail: <abbotti@mev.co.uk> )=-
-=( Web: http://www.mev.co.uk/ )=-
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* Re: Fwd: boot kernel with append device tree
From: Alex Vazquez @ 2016-11-09 8:41 UTC (permalink / raw)
To: Sascha Hauer; +Cc: barebox
In-Reply-To: <20161108072936.beuncvhpwxuhumkg@pengutronix.de>
Hi Sascha!
I have tested the patch with the version (2016.03.0) and now it works correctly.
Thanks!
Regards!
2016-11-08 8:29 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> On Mon, Nov 07, 2016 at 12:01:25PM +0100, Alex Vazquez wrote:
>> > Is CONFIG_OFTREE enabled in your build?
>> Yes.
>
> Ok, could you please try the following patch? Another possibility would
> be to disable CONFIG_OFTREE, but it would be good if you could test the
> patch anyway since the same bug is still present in current master.
>
> Sascha
>
> ----------------------------------8<--------------------------------
>
> From 500e5f87f9943958fa4662e29261a0abb4df24d9 Mon Sep 17 00:00:00 2001
> From: Sascha Hauer <s.hauer@pengutronix.de>
> Date: Tue, 8 Nov 2016 08:23:17 +0100
> Subject: [PATCH] ARM: Fix appended device tree when CONFIG_OFTREE is enabled
>
> When CONFIG_OFTREE is enabled the appended device tree is unflattened
> and put into data->of_root_node, but there it is never used again.
> To actually use the appended device tree put it into data->oftree
> instead.
>
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---
> arch/arm/lib/bootm.c | 13 +++++++++++--
> 1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
> index 28b4f4a..8977d08 100644
> --- a/arch/arm/lib/bootm.c
> +++ b/arch/arm/lib/bootm.c
> @@ -244,12 +244,21 @@ static int do_bootz_linux_fdt(int fd, struct image_data *data)
> }
>
> if (IS_BUILTIN(CONFIG_OFTREE)) {
> - data->of_root_node = of_unflatten_dtb(oftree);
> - if (!data->of_root_node) {
> + struct device_node *root;
> +
> + root = of_unflatten_dtb(oftree);
> + if (!root) {
> pr_err("unable to unflatten devicetree\n");
> ret = -EINVAL;
> goto err_free;
> }
> + data->oftree = of_get_fixed_tree(root);
> + if (!data->oftree) {
> + pr_err("Unable to get fixed tree\n");
> + ret = -EINVAL;
> + goto err_free;
> + }
> +
> free(oftree);
> } else {
> data->oftree = oftree;
> --
> 2.10.1
>
> --
> Pengutronix e.K. | |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* Re: Configure RAM size on iMX53 board
From: Sascha Hauer @ 2016-11-09 6:41 UTC (permalink / raw)
To: Jose Luis Zabalza; +Cc: barebox
In-Reply-To: <CAKZffXFjLerW8jK2m82znqH+Mc_9X9C4s7SVJHGyHdnV0R0q_Q@mail.gmail.com>
On Wed, Nov 09, 2016 at 05:23:10AM +0100, Jose Luis Zabalza wrote:
> There is no form of detection. UBoot (a very old version) don't use
> any CS1 address, except with the memtest command.
> If memtest command is executed with 512MB version, UBoot hangs, as expected.
> I set the mem kernel parameter using a environment variable and kernel
> can reach CS1 memory.
Then you could drop the CS1 setup from the DCD table and do the same.
You can then create a command or similar which initializes the CS1
memory and registers the new memory bank.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* Re: Configure RAM size on iMX53 board
From: Jose Luis Zabalza @ 2016-11-09 4:23 UTC (permalink / raw)
To: barebox
In-Reply-To: <20161108212434.gvlq5fy6vrbn2en5@pengutronix.de>
There is no form of detection. UBoot (a very old version) don't use
any CS1 address, except with the memtest command.
If memtest command is executed with 512MB version, UBoot hangs, as expected.
I set the mem kernel parameter using a environment variable and kernel
can reach CS1 memory.
2016-11-08 22:24 GMT+01:00 Sascha Hauer <s.hauer@pengutronix.de>:
> On Tue, Nov 08, 2016 at 09:51:36PM +0100, Jose Luis Zabalza wrote:
>> > So you have 512MiB on each chip select, so I assume that on the 512MiB
>> > board variants CS1 is not equipped.
>>
>> Yes, it is.
>>
>> >In that case you can in lowlevel.c
>> > test if you find SDRAM on CS1 and if not, disable the chip select
>> > completely in the SDRAM controller.
>>
>> OK. But how ? I enable CS0 and CS1 on DCD table. Is there any way to
>> tell barebox not to use CS1 ?
>>
>> > I am not sure how you can detect if there's SDRAM on CS1. I've seen
>> > situations in which the board just hangs if you access non existent RAM
>> > areas.
>>
>> I have tried it, but I have not be able to implement a code for
>> autodetect. If the code write or read a value on a position without
>> physical chip, the microcontroller hangs. ????
>>
>> But it's not a problem. A solution is configure both CS and MMU. If
>> bootloader don't access to high positions, there is not problem. After
>> I set a environment variable with memory size and the mem kernel
>> parameter (or ATAG) does the rest.
>
> You said that both board variants work with the same U-Boot binary, how
> does it work there? Is there some detection mechanism or is it only some
> environment variable that you have to set manually?
>
> Sascha
>
> --
> Pengutronix e.K. | |
> Industrial Linux Solutions | http://www.pengutronix.de/ |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
--
jlz.3008 a t gmail.com
Linux Counter 172551
https://linuxcounter.net/cert/172551.png
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* Re: Configure RAM size on iMX53 board
From: Sascha Hauer @ 2016-11-08 21:24 UTC (permalink / raw)
To: Jose Luis Zabalza; +Cc: barebox
In-Reply-To: <CAKZffXG5CG9R8e4xoMdP6DFJq42ng5EQqwmhafikNn6HNzuedQ@mail.gmail.com>
On Tue, Nov 08, 2016 at 09:51:36PM +0100, Jose Luis Zabalza wrote:
> > So you have 512MiB on each chip select, so I assume that on the 512MiB
> > board variants CS1 is not equipped.
>
> Yes, it is.
>
> >In that case you can in lowlevel.c
> > test if you find SDRAM on CS1 and if not, disable the chip select
> > completely in the SDRAM controller.
>
> OK. But how ? I enable CS0 and CS1 on DCD table. Is there any way to
> tell barebox not to use CS1 ?
>
> > I am not sure how you can detect if there's SDRAM on CS1. I've seen
> > situations in which the board just hangs if you access non existent RAM
> > areas.
>
> I have tried it, but I have not be able to implement a code for
> autodetect. If the code write or read a value on a position without
> physical chip, the microcontroller hangs. ????
>
> But it's not a problem. A solution is configure both CS and MMU. If
> bootloader don't access to high positions, there is not problem. After
> I set a environment variable with memory size and the mem kernel
> parameter (or ATAG) does the rest.
You said that both board variants work with the same U-Boot binary, how
does it work there? Is there some detection mechanism or is it only some
environment variable that you have to set manually?
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* Re: Configure RAM size on iMX53 board
From: Jose Luis Zabalza @ 2016-11-08 20:51 UTC (permalink / raw)
To: barebox
In-Reply-To: <20161108075317.j4xkf7zpkdfyt5y3@pengutronix.de>
> So you have 512MiB on each chip select, so I assume that on the 512MiB
> board variants CS1 is not equipped.
Yes, it is.
>In that case you can in lowlevel.c
> test if you find SDRAM on CS1 and if not, disable the chip select
> completely in the SDRAM controller.
OK. But how ? I enable CS0 and CS1 on DCD table. Is there any way to
tell barebox not to use CS1 ?
> I am not sure how you can detect if there's SDRAM on CS1. I've seen
> situations in which the board just hangs if you access non existent RAM
> areas.
I have tried it, but I have not be able to implement a code for
autodetect. If the code write or read a value on a position without
physical chip, the microcontroller hangs. ????
But it's not a problem. A solution is configure both CS and MMU. If
bootloader don't access to high positions, there is not problem. After
I set a environment variable with memory size and the mem kernel
parameter (or ATAG) does the rest.
So, I have to make sure Barebox don't reach CS1 memory positions. That is all.
Thanks for your help. See you later.
--
jlz.3008 a t gmail.com
Linux Counter 172551
https://linuxcounter.net/cert/172551.png
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* [PATCH] clk: add clock command completion
From: Sascha Hauer @ 2016-11-08 17:34 UTC (permalink / raw)
To: Barebox List
This adds tab completion for the clk_* commands.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
commands/clk.c | 5 +++++
drivers/clk/clk.c | 22 ++++++++++++++++++++++
include/linux/clk.h | 4 ++++
3 files changed, 31 insertions(+)
diff --git a/commands/clk.c b/commands/clk.c
index f862c45..47159dd 100644
--- a/commands/clk.c
+++ b/commands/clk.c
@@ -25,6 +25,7 @@ BAREBOX_CMD_START(clk_enable)
BAREBOX_CMD_DESC("enable a clock")
BAREBOX_CMD_OPTS("CLK")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_COMPLETE(clk_name_complete)
BAREBOX_CMD_END
static int do_clk_disable(int argc, char *argv[])
@@ -48,6 +49,7 @@ BAREBOX_CMD_START(clk_disable)
BAREBOX_CMD_DESC("disable a clock")
BAREBOX_CMD_OPTS("CLK")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_COMPLETE(clk_name_complete)
BAREBOX_CMD_END
static int do_clk_set_rate(int argc, char *argv[])
@@ -77,6 +79,7 @@ BAREBOX_CMD_START(clk_set_rate)
BAREBOX_CMD_OPTS("CLK HZ")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_clk_set_rate_help)
+ BAREBOX_CMD_COMPLETE(clk_name_complete)
BAREBOX_CMD_END
static int do_clk_get_rate(int argc, char *argv[])
@@ -130,6 +133,7 @@ BAREBOX_CMD_START(clk_get_rate)
BAREBOX_CMD_OPTS("[-s VARNAME] CLK")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_clk_get_rate_help)
+ BAREBOX_CMD_COMPLETE(clk_name_complete)
BAREBOX_CMD_END
static int do_clk_dump(int argc, char *argv[])
@@ -187,4 +191,5 @@ BAREBOX_CMD_START(clk_set_parent)
BAREBOX_CMD_DESC("set parent of a clock")
BAREBOX_CMD_OPTS("CLK PARENT")
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
+ BAREBOX_CMD_COMPLETE(clk_name_complete)
BAREBOX_CMD_END
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 630a84d..15e424d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -17,6 +17,8 @@
#include <common.h>
#include <errno.h>
#include <malloc.h>
+#include <stringlist.h>
+#include <complete.h>
#include <linux/clk.h>
#include <linux/err.h>
@@ -508,3 +510,23 @@ void clk_dump(int verbose)
dump_one(c, verbose, 0);
}
}
+
+int clk_name_complete(struct string_list *sl, char *instr)
+{
+ struct clk *c;
+ int len;
+
+ if (!instr)
+ instr = "";
+
+ len = strlen(instr);
+
+ list_for_each_entry(c, &clks, list) {
+ if (strncmp(instr, c->name, len))
+ continue;
+
+ string_list_add_asprintf(sl, "%s ", c->name);
+ }
+
+ return COMPLETE_CONTINUE;
+}
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 7a0ee11..8cb9731 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -362,4 +362,8 @@ static inline int of_clk_init(struct device_node *root,
}
#endif
+struct string_list;
+
+int clk_name_complete(struct string_list *sl, char *instr);
+
#endif
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH 7/7] ARM: i.MX6 esdctl: Add i.MX6ul support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
In-Reply-To: <20161108171907.20726-1-s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/esdctl.c | 19 +++++++++++++++++++
arch/arm/mach-imx/include/mach/esdctl.h | 1 +
2 files changed, 20 insertions(+)
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index 106e648..ffe708f 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -377,6 +377,11 @@ static __maybe_unused struct imx_esdctl_data imx6q_data = {
.add_mem = imx6_mmdc_add_mem,
};
+static __maybe_unused struct imx_esdctl_data imx6ul_data = {
+ .base0 = 0x80000000,
+ .add_mem = imx6_mmdc_add_mem,
+};
+
static struct platform_device_id imx_esdctl_ids[] = {
#ifdef CONFIG_ARCH_IMX1
{
@@ -427,6 +432,9 @@ static struct platform_device_id imx_esdctl_ids[] = {
static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = {
{
+ .compatible = "fsl,imx6ul-mmdc",
+ .data = &imx6ul_data
+ }, {
.compatible = "fsl,imx6q-mmdc",
.data = &imx6q_data
}, {
@@ -589,3 +597,14 @@ void __noreturn imx6q_barebox_entry(void *boarddata)
barebox_arm_entry(0x10000000, size, boarddata);
}
+
+void __noreturn imx6ul_barebox_entry(void *boarddata)
+{
+ u64 size_cs0 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 0);
+ u64 size_cs1 = imx6_mmdc_sdram_size((void *)MX6_MMDC_P0_BASE_ADDR, 1);
+ u64 total = size_cs0 + size_cs1;
+
+ resource_size_t size = min(total, (u64)IMX6_MAX_SDRAM_SIZE);
+
+ barebox_arm_entry(0x80000000, size, boarddata);
+}
diff --git a/arch/arm/mach-imx/include/mach/esdctl.h b/arch/arm/mach-imx/include/mach/esdctl.h
index cf8d89d..66dcc89 100644
--- a/arch/arm/mach-imx/include/mach/esdctl.h
+++ b/arch/arm/mach-imx/include/mach/esdctl.h
@@ -136,6 +136,7 @@ void __noreturn imx35_barebox_entry(void *boarddata);
void __noreturn imx51_barebox_entry(void *boarddata);
void __noreturn imx53_barebox_entry(void *boarddata);
void __noreturn imx6q_barebox_entry(void *boarddata);
+void __noreturn imx6ul_barebox_entry(void *boarddata);
void imx_esdctl_disable(void);
#endif
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH 4/7] pinmux: imx-iomux-v3: Add i.MX6ul support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
In-Reply-To: <20161108171907.20726-1-s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/pinctrl/imx-iomux-v3.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c
index 92fac18..4b3f033 100644
--- a/drivers/pinctrl/imx-iomux-v3.c
+++ b/drivers/pinctrl/imx-iomux-v3.c
@@ -207,6 +207,8 @@ static __maybe_unused struct of_device_id imx_iomux_v3_dt_ids[] = {
}, {
.compatible = "fsl,imx6sx-iomuxc",
}, {
+ .compatible = "fsl,imx6ul-iomuxc",
+ }, {
/* sentinel */
}
};
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH 2/7] ARM: i.MX6ul: Add clock support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
In-Reply-To: <20161108171907.20726-1-s.hauer@pengutronix.de>
Nearly identical to Linux-4.8 clock support, only some unnecessary
clocks skipped.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/Makefile | 1 +
arch/arm/mach-imx/clk-imx6ul.c | 426 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 427 insertions(+)
create mode 100644 arch/arm/mach-imx/clk-imx6ul.c
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 0763944..9922fed 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -14,6 +14,7 @@ pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o
obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o clk-imx6.o
lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
obj-$(CONFIG_ARCH_IMX6SX) += clk-imx6sx.o
+obj-$(CONFIG_ARCH_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o
obj-$(CONFIG_IMX_IIM) += iim.o
obj-$(CONFIG_IMX_OCOTP) += ocotp.o
diff --git a/arch/arm/mach-imx/clk-imx6ul.c b/arch/arm/mach-imx/clk-imx6ul.c
new file mode 100644
index 0000000..72b5fa2
--- /dev/null
+++ b/arch/arm/mach-imx/clk-imx6ul.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <linux/clk.h>
+#include <io.h>
+#include <of.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <mach/imx6-regs.h>
+#include <mach/revision.h>
+#include <mach/imx6.h>
+#include <dt-bindings/clock/imx6ul-clock.h>
+
+#include "clk.h"
+
+#define BM_CCM_CCDR_MMDC_CH0_MASK (0x2 << 16)
+#define CCDR 0x4
+
+static const char *pll_bypass_src_sels[] = { "osc", "dummy", };
+static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
+static const char *pll2_bypass_sels[] = { "pll2", "pll2_bypass_src", };
+static const char *pll3_bypass_sels[] = { "pll3", "pll3_bypass_src", };
+static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
+static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
+static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
+static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char *ca7_secondary_sels[] = { "pll2_pfd2_396m", "pll2_bus", };
+static const char *step_sels[] = { "osc", "ca7_secondary_sel", };
+static const char *pll1_sw_sels[] = { "pll1_sys", "step", };
+static const char *axi_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_540m", };
+static const char *axi_sels[] = {"periph", "axi_alt_sel", };
+static const char *periph_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
+static const char *periph2_pre_sels[] = { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll4_audio_div", };
+static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", "osc", };
+static const char *periph2_clk2_sels[] = { "pll3_usb_otg", "osc", };
+static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
+static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
+static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *bch_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *gpmi_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
+static const char *eim_slow_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd0_720m", };
+static const char *spdif_sels[] = { "pll4_audio_div", "pll3_pfd2_508m", "pll5_video_div", "pll3_usb_otg", };
+static const char *sai_sels[] = { "pll3_pfd2_508m", "pll5_video_div", "pll4_audio_div", };
+static const char *lcdif_pre_sels[] = { "pll2_bus", "pll3_pfd3_454m", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd1_594m", "pll3_pfd1_540m", };
+static const char *sim_pre_sels[] = { "pll2_bus", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd2_508m", };
+static const char *ldb_di0_sels[] = { "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_pfd3_594m", "pll2_pfd1_594m", "pll3_pfd3_454m", };
+static const char *ldb_di0_div_sels[] = { "ldb_di0_div_3_5", "ldb_di0_div_7", };
+static const char *ldb_di1_div_sels[] = { "ldb_di1_div_3_5", "ldb_di1_div_7", };
+static const char *qspi1_sels[] = { "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll2_bus", "pll3_pfd3_454m", "pll3_pfd2_508m", };
+static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", "pll3_pfd3_454m", "dummy", "dummy", "dummy", };
+static const char *can_sels[] = { "pll3_60m", "osc", "pll3_80m", "dummy", };
+static const char *ecspi_sels[] = { "pll3_60m", "osc", };
+static const char *uart_sels[] = { "pll3_80m", "osc", };
+static const char *perclk_sels[] = { "ipg", "osc", };
+static const char *lcdif_sels[] = { "lcdif_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+static const char *csi_sels[] = { "osc", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
+static const char *sim_sels[] = { "sim_podf", "ipp_di0", "ipp_di1", "ldb_di0", "ldb_di1", };
+
+static struct clk *clks[IMX6UL_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static int const clks_init_on[] __initconst = {
+ IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2, IMX6UL_CLK_AIPSTZ3,
+ IMX6UL_CLK_AXI, IMX6UL_CLK_ARM, IMX6UL_CLK_ROM,
+ IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG,
+};
+
+static struct clk_div_table clk_enet_ref_table[] = {
+ { .val = 0, .div = 20, },
+ { .val = 1, .div = 10, },
+ { .val = 2, .div = 5, },
+ { .val = 3, .div = 4, },
+ { }
+};
+
+static int imx6_ccm_probe(struct device_d *dev)
+{
+ struct resource *iores;
+ void __iomem *base, *anatop_base, *ccm_base;
+ int i;
+ struct device_node *ccm_node = dev->device_node;
+
+ iores = dev_request_mem_resource(dev, 0);
+ if (IS_ERR(iores))
+ return PTR_ERR(iores);
+ ccm_base = IOMEM(iores->start);
+
+ base = anatop_base;
+
+ clks[IMX6UL_CLK_DUMMY] = clk_fixed("dummy", 0);
+
+ base = IOMEM(MX6_ANATOP_BASE_ADDR);
+
+ clks[IMX6UL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6UL_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6UL_PLL3_BYPASS_SRC] = imx_clk_mux("pll3_bypass_src", base + 0x10, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6UL_PLL4_BYPASS_SRC] = imx_clk_mux("pll4_bypass_src", base + 0x70, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6UL_PLL5_BYPASS_SRC] = imx_clk_mux("pll5_bypass_src", base + 0xa0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6UL_PLL6_BYPASS_SRC] = imx_clk_mux("pll6_bypass_src", base + 0xe0, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+ clks[IMX6UL_PLL7_BYPASS_SRC] = imx_clk_mux("pll7_bypass_src", base + 0x20, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
+
+ clks[IMX6UL_CLK_PLL1] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1", "osc", base + 0x00, 0x7f);
+ clks[IMX6UL_CLK_PLL2] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2", "osc", base + 0x30, 0x1);
+ clks[IMX6UL_CLK_PLL3] = imx_clk_pllv3(IMX_PLLV3_USB, "pll3", "osc", base + 0x10, 0x3);
+ clks[IMX6UL_CLK_PLL4] = imx_clk_pllv3(IMX_PLLV3_AV, "pll4", "osc", base + 0x70, 0x7f);
+ clks[IMX6UL_CLK_PLL5] = imx_clk_pllv3(IMX_PLLV3_AV, "pll5", "osc", base + 0xa0, 0x7f);
+ clks[IMX6UL_CLK_PLL6] = imx_clk_pllv3(IMX_PLLV3_ENET, "pll6", "osc", base + 0xe0, 0x3);
+ clks[IMX6UL_CLK_PLL7] = imx_clk_pllv3(IMX_PLLV3_USB, "pll7", "osc", base + 0x20, 0x3);
+
+ clks[IMX6UL_PLL1_BYPASS] = imx_clk_mux_p("pll1_bypass", base + 0x00, 16, 1, pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels));
+ clks[IMX6UL_PLL2_BYPASS] = imx_clk_mux_p("pll2_bypass", base + 0x30, 16, 1, pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels));
+ clks[IMX6UL_PLL3_BYPASS] = imx_clk_mux_p("pll3_bypass", base + 0x10, 16, 1, pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels));
+ clks[IMX6UL_PLL4_BYPASS] = imx_clk_mux_p("pll4_bypass", base + 0x70, 16, 1, pll4_bypass_sels, ARRAY_SIZE(pll4_bypass_sels));
+ clks[IMX6UL_PLL5_BYPASS] = imx_clk_mux_p("pll5_bypass", base + 0xa0, 16, 1, pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels));
+ clks[IMX6UL_PLL6_BYPASS] = imx_clk_mux_p("pll6_bypass", base + 0xe0, 16, 1, pll6_bypass_sels, ARRAY_SIZE(pll6_bypass_sels));
+ clks[IMX6UL_PLL7_BYPASS] = imx_clk_mux_p("pll7_bypass", base + 0x20, 16, 1, pll7_bypass_sels, ARRAY_SIZE(pll7_bypass_sels));
+ clks[IMX6UL_CLK_CSI_SEL] = imx_clk_mux_p("csi_sel", base + 0x3c, 9, 2, csi_sels, ARRAY_SIZE(csi_sels));
+
+ /* Do not bypass PLLs initially */
+ clk_set_parent(clks[IMX6UL_PLL1_BYPASS], clks[IMX6UL_CLK_PLL1]);
+ clk_set_parent(clks[IMX6UL_PLL2_BYPASS], clks[IMX6UL_CLK_PLL2]);
+ clk_set_parent(clks[IMX6UL_PLL3_BYPASS], clks[IMX6UL_CLK_PLL3]);
+ clk_set_parent(clks[IMX6UL_PLL4_BYPASS], clks[IMX6UL_CLK_PLL4]);
+ clk_set_parent(clks[IMX6UL_PLL5_BYPASS], clks[IMX6UL_CLK_PLL5]);
+ clk_set_parent(clks[IMX6UL_PLL6_BYPASS], clks[IMX6UL_CLK_PLL6]);
+ clk_set_parent(clks[IMX6UL_PLL7_BYPASS], clks[IMX6UL_CLK_PLL7]);
+
+ clks[IMX6UL_CLK_PLL1_SYS] = imx_clk_fixed_factor("pll1_sys", "pll1_bypass", 1, 1);
+ clks[IMX6UL_CLK_PLL2_BUS] = imx_clk_gate("pll2_bus", "pll2_bypass", base + 0x30, 13);
+ clks[IMX6UL_CLK_PLL3_USB_OTG] = imx_clk_gate("pll3_usb_otg", "pll3_bypass", base + 0x10, 13);
+ clks[IMX6UL_CLK_PLL4_AUDIO] = imx_clk_gate("pll4_audio", "pll4_bypass", base + 0x70, 13);
+ clks[IMX6UL_CLK_PLL5_VIDEO] = imx_clk_gate("pll5_video", "pll5_bypass", base + 0xa0, 13);
+ clks[IMX6UL_CLK_PLL6_ENET] = imx_clk_gate("pll6_enet", "pll6_bypass", base + 0xe0, 13);
+ clks[IMX6UL_CLK_PLL7_USB_HOST] = imx_clk_gate("pll7_usb_host", "pll7_bypass", base + 0x20, 13);
+
+ /*
+ * Bit 20 is the reserved and read-only bit, we do this only for:
+ * - Do nothing for usbphy clk_enable/disable
+ * - Keep refcount when do usbphy clk_enable/disable, in that case,
+ * the clk framework many need to enable/disable usbphy's parent
+ */
+ clks[IMX6UL_CLK_USBPHY1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 20);
+ clks[IMX6UL_CLK_USBPHY2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 20);
+
+ /*
+ * usbphy*_gate needs to be on after system boots up, and software
+ * never needs to control it anymore.
+ */
+ clks[IMX6UL_CLK_USBPHY1_GATE] = imx_clk_gate("usbphy1_gate", "dummy", base + 0x10, 6);
+ clks[IMX6UL_CLK_USBPHY2_GATE] = imx_clk_gate("usbphy2_gate", "dummy", base + 0x20, 6);
+
+ /* name parent_name reg idx */
+ clks[IMX6UL_CLK_PLL2_PFD0] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
+ clks[IMX6UL_CLK_PLL2_PFD1] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus", base + 0x100, 1);
+ clks[IMX6UL_CLK_PLL2_PFD2] = imx_clk_pfd("pll2_pfd2_396m", "pll2_bus", base + 0x100, 2);
+ clks[IMX6UL_CLK_PLL2_PFD3] = imx_clk_pfd("pll2_pfd3_594m", "pll2_bus", base + 0x100, 3);
+ clks[IMX6UL_CLK_PLL3_PFD0] = imx_clk_pfd("pll3_pfd0_720m", "pll3_usb_otg", base + 0xf0, 0);
+ clks[IMX6UL_CLK_PLL3_PFD1] = imx_clk_pfd("pll3_pfd1_540m", "pll3_usb_otg", base + 0xf0, 1);
+ clks[IMX6UL_CLK_PLL3_PFD2] = imx_clk_pfd("pll3_pfd2_508m", "pll3_usb_otg", base + 0xf0, 2);
+ clks[IMX6UL_CLK_PLL3_PFD3] = imx_clk_pfd("pll3_pfd3_454m", "pll3_usb_otg", base + 0xf0, 3);
+
+ clks[IMX6UL_CLK_ENET_REF] = imx_clk_divider_table("enet_ref", "pll6_enet",
+ base + 0xe0, 0, 2, clk_enet_ref_table);
+ clks[IMX6UL_CLK_ENET2_REF] = imx_clk_divider_table("enet2_ref", "pll6_enet",
+ base + 0xe0, 2, 2, clk_enet_ref_table);
+
+ clks[IMX6UL_CLK_ENET2_REF_125M] = imx_clk_gate("enet_ref_125m", "enet2_ref", base + 0xe0, 20);
+ clks[IMX6UL_CLK_ENET_PTP_REF] = imx_clk_fixed_factor("enet_ptp_ref", "pll6_enet", 1, 20);
+ clks[IMX6UL_CLK_ENET_PTP] = imx_clk_gate("enet_ptp", "enet_ptp_ref", base + 0xe0, 21);
+
+ /* name parent_name mult div */
+ clks[IMX6UL_CLK_PLL2_198M] = imx_clk_fixed_factor("pll2_198m", "pll2_pfd2_396m", 1, 2);
+ clks[IMX6UL_CLK_PLL3_80M] = imx_clk_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6);
+ clks[IMX6UL_CLK_PLL3_60M] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
+ clks[IMX6UL_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
+
+ base = ccm_base;
+
+ clks[IMX6UL_CA7_SECONDARY_SEL] = imx_clk_mux("ca7_secondary_sel", base + 0xc, 3, 1, ca7_secondary_sels, ARRAY_SIZE(ca7_secondary_sels));
+ clks[IMX6UL_CLK_STEP] = imx_clk_mux("step", base + 0x0c, 8, 1, step_sels, ARRAY_SIZE(step_sels));
+ clks[IMX6UL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0x0c, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
+ clks[IMX6UL_CLK_AXI_ALT_SEL] = imx_clk_mux("axi_alt_sel", base + 0x14, 7, 1, axi_alt_sels, ARRAY_SIZE(axi_alt_sels));
+ clks[IMX6UL_CLK_AXI_SEL] = imx_clk_mux("axi_sel", base + 0x14, 6, 1, axi_sels, ARRAY_SIZE(axi_sels));
+ clks[IMX6UL_CLK_PERIPH_PRE] = imx_clk_mux("periph_pre", base + 0x18, 18, 2, periph_pre_sels, ARRAY_SIZE(periph_pre_sels));
+ clks[IMX6UL_CLK_PERIPH2_PRE] = imx_clk_mux("periph2_pre", base + 0x18, 21, 2, periph2_pre_sels, ARRAY_SIZE(periph2_pre_sels));
+ clks[IMX6UL_CLK_PERIPH_CLK2_SEL] = imx_clk_mux("periph_clk2_sel", base + 0x18, 12, 2, periph_clk2_sels, ARRAY_SIZE(periph_clk2_sels));
+ clks[IMX6UL_CLK_PERIPH2_CLK2_SEL] = imx_clk_mux("periph2_clk2_sel", base + 0x18, 20, 1, periph2_clk2_sels, ARRAY_SIZE(periph2_clk2_sels));
+ clks[IMX6UL_CLK_EIM_SLOW_SEL] = imx_clk_mux("eim_slow_sel", base + 0x1c, 29, 2, eim_slow_sels, ARRAY_SIZE(eim_slow_sels));
+ clks[IMX6UL_CLK_GPMI_SEL] = imx_clk_mux("gpmi_sel", base + 0x1c, 19, 1, gpmi_sels, ARRAY_SIZE(gpmi_sels));
+ clks[IMX6UL_CLK_BCH_SEL] = imx_clk_mux("bch_sel", base + 0x1c, 18, 1, bch_sels, ARRAY_SIZE(bch_sels));
+ clks[IMX6UL_CLK_USDHC2_SEL] = imx_clk_mux("usdhc2_sel", base + 0x1c, 17, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6UL_CLK_USDHC1_SEL] = imx_clk_mux("usdhc1_sel", base + 0x1c, 16, 1, usdhc_sels, ARRAY_SIZE(usdhc_sels));
+ clks[IMX6UL_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel", base + 0x1c, 14, 2, sai_sels, ARRAY_SIZE(sai_sels));
+ clks[IMX6UL_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel", base + 0x1c, 12, 2, sai_sels, ARRAY_SIZE(sai_sels));
+ clks[IMX6UL_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel", base + 0x1c, 10, 2, sai_sels, ARRAY_SIZE(sai_sels));
+ clks[IMX6UL_CLK_QSPI1_SEL] = imx_clk_mux("qspi1_sel", base + 0x1c, 7, 3, qspi1_sels, ARRAY_SIZE(qspi1_sels));
+ clks[IMX6UL_CLK_PERCLK_SEL] = imx_clk_mux("perclk_sel", base + 0x1c, 6, 1, perclk_sels, ARRAY_SIZE(perclk_sels));
+ clks[IMX6UL_CLK_CAN_SEL] = imx_clk_mux("can_sel", base + 0x20, 8, 2, can_sels, ARRAY_SIZE(can_sels));
+ clks[IMX6UL_CLK_UART_SEL] = imx_clk_mux("uart_sel", base + 0x24, 6, 1, uart_sels, ARRAY_SIZE(uart_sels));
+ clks[IMX6UL_CLK_ENFC_SEL] = imx_clk_mux("enfc_sel", base + 0x2c, 15, 3, enfc_sels, ARRAY_SIZE(enfc_sels));
+ clks[IMX6UL_CLK_LDB_DI0_SEL] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di0_sels, ARRAY_SIZE(ldb_di0_sels));
+ clks[IMX6UL_CLK_SPDIF_SEL] = imx_clk_mux("spdif_sel", base + 0x30, 20, 2, spdif_sels, ARRAY_SIZE(spdif_sels));
+ clks[IMX6UL_CLK_SIM_PRE_SEL] = imx_clk_mux("sim_pre_sel", base + 0x34, 15, 3, sim_pre_sels, ARRAY_SIZE(sim_pre_sels));
+ clks[IMX6UL_CLK_SIM_SEL] = imx_clk_mux("sim_sel", base + 0x34, 9, 3, sim_sels, ARRAY_SIZE(sim_sels));
+ clks[IMX6UL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
+ clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
+ clks[IMX6UL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
+
+ clks[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));
+ clks[IMX6UL_CLK_LDB_DI1_DIV_SEL] = imx_clk_mux("ldb_di1", base + 0x20, 11, 1, ldb_di1_div_sels, ARRAY_SIZE(ldb_di1_div_sels));
+
+ clks[IMX6UL_CLK_LDB_DI0_DIV_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+ clks[IMX6UL_CLK_LDB_DI0_DIV_7] = imx_clk_fixed_factor("ldb_di0_div_7", "ldb_di0_sel", 1, 7);
+ clks[IMX6UL_CLK_LDB_DI1_DIV_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "qspi1_sel", 2, 7);
+ clks[IMX6UL_CLK_LDB_DI1_DIV_7] = imx_clk_fixed_factor("ldb_di1_div_7", "qspi1_sel", 1, 7);
+
+ clks[IMX6UL_CLK_PERIPH] = imx_clk_busy_mux("periph", base + 0x14, 25, 1, base + 0x48, 5, periph_sels, ARRAY_SIZE(periph_sels));
+ clks[IMX6UL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
+
+ clks[IMX6UL_CLK_PERIPH_CLK2] = imx_clk_divider("periph_clk2", "periph_clk2_sel", base + 0x14, 27, 3);
+ clks[IMX6UL_CLK_PERIPH2_CLK2] = imx_clk_divider("periph2_clk2", "periph2_clk2_sel", base + 0x14, 0, 3);
+ clks[IMX6UL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
+ clks[IMX6UL_CLK_LCDIF_PODF] = imx_clk_divider("lcdif_podf", "lcdif_pred", base + 0x18, 23, 3);
+ clks[IMX6UL_CLK_QSPI1_PDOF] = imx_clk_divider("qspi1_podf", "qspi1_sel", base + 0x1c, 26, 3);
+ clks[IMX6UL_CLK_EIM_SLOW_PODF] = imx_clk_divider("eim_slow_podf", "eim_slow_sel", base + 0x1c, 23, 3);
+ clks[IMX6UL_CLK_PERCLK] = imx_clk_divider("perclk", "perclk_sel", base + 0x1c, 0, 6);
+ clks[IMX6UL_CLK_CAN_PODF] = imx_clk_divider("can_podf", "can_sel", base + 0x20, 2, 6);
+ clks[IMX6UL_CLK_GPMI_PODF] = imx_clk_divider("gpmi_podf", "gpmi_sel", base + 0x24, 22, 3);
+ clks[IMX6UL_CLK_BCH_PODF] = imx_clk_divider("bch_podf", "bch_sel", base + 0x24, 19, 3);
+ clks[IMX6UL_CLK_USDHC2_PODF] = imx_clk_divider("usdhc2_podf", "usdhc2_sel", base + 0x24, 16, 3);
+ clks[IMX6UL_CLK_USDHC1_PODF] = imx_clk_divider("usdhc1_podf", "usdhc1_sel", base + 0x24, 11, 3);
+ clks[IMX6UL_CLK_UART_PODF] = imx_clk_divider("uart_podf", "uart_sel", base + 0x24, 0, 6);
+ clks[IMX6UL_CLK_SAI3_PRED] = imx_clk_divider("sai3_pred", "sai3_sel", base + 0x28, 22, 3);
+ clks[IMX6UL_CLK_SAI3_PODF] = imx_clk_divider("sai3_podf", "sai3_pred", base + 0x28, 16, 6);
+ clks[IMX6UL_CLK_SAI1_PRED] = imx_clk_divider("sai1_pred", "sai1_sel", base + 0x28, 6, 3);
+ clks[IMX6UL_CLK_SAI1_PODF] = imx_clk_divider("sai1_podf", "sai1_pred", base + 0x28, 0, 6);
+ clks[IMX6UL_CLK_ENFC_PRED] = imx_clk_divider("enfc_pred", "enfc_sel", base + 0x2c, 18, 3);
+ clks[IMX6UL_CLK_ENFC_PODF] = imx_clk_divider("enfc_podf", "enfc_pred", base + 0x2c, 21, 6);
+ clks[IMX6UL_CLK_SAI2_PRED] = imx_clk_divider("sai2_pred", "sai2_sel", base + 0x2c, 6, 3);
+ clks[IMX6UL_CLK_SAI2_PODF] = imx_clk_divider("sai2_podf", "sai2_pred", base + 0x2c, 0, 6);
+ clks[IMX6UL_CLK_SPDIF_PRED] = imx_clk_divider("spdif_pred", "spdif_sel", base + 0x30, 25, 3);
+ clks[IMX6UL_CLK_SPDIF_PODF] = imx_clk_divider("spdif_podf", "spdif_pred", base + 0x30, 22, 3);
+ clks[IMX6UL_CLK_SIM_PODF] = imx_clk_divider("sim_podf", "sim_pre_sel", base + 0x34, 12, 3);
+ clks[IMX6UL_CLK_ECSPI_PODF] = imx_clk_divider("ecspi_podf", "ecspi_sel", base + 0x38, 19, 6);
+ clks[IMX6UL_CLK_LCDIF_PRED] = imx_clk_divider("lcdif_pred", "lcdif_pre_sel", base + 0x38, 12, 3);
+ clks[IMX6UL_CLK_CSI_PODF] = imx_clk_divider("csi_podf", "csi_sel", base + 0x3c, 11, 3);
+
+ clks[IMX6UL_CLK_ARM] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16);
+ clks[IMX6UL_CLK_MMDC_PODF] = imx_clk_busy_divider("mmdc_podf", "periph2", base + 0x14, 3, 3, base + 0x48, 2);
+ clks[IMX6UL_CLK_AXI_PODF] = imx_clk_busy_divider("axi_podf", "axi_sel", base + 0x14, 16, 3, base + 0x48, 0);
+ clks[IMX6UL_CLK_AHB] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1);
+
+ /* CCGR0 */
+ clks[IMX6UL_CLK_AIPSTZ1] = imx_clk_gate2("aips_tz1", "ahb", base + 0x68, 0);
+ clks[IMX6UL_CLK_AIPSTZ2] = imx_clk_gate2("aips_tz2", "ahb", base + 0x68, 2);
+ clks[IMX6UL_CLK_APBHDMA] = imx_clk_gate2("apbh_dma", "bch_podf", base + 0x68, 4);
+ clks[IMX6UL_CLK_CAAM_MEM] = imx_clk_gate2("caam_mem", "ahb", base + 0x68, 8);
+ clks[IMX6UL_CLK_CAAM_ACLK] = imx_clk_gate2("caam_aclk", "ahb", base + 0x68, 10);
+ clks[IMX6UL_CLK_CAAM_IPG] = imx_clk_gate2("caam_ipg", "ipg", base + 0x68, 12);
+ clks[IMX6UL_CLK_CAN1_IPG] = imx_clk_gate2("can1_ipg", "ipg", base + 0x68, 14);
+ clks[IMX6UL_CLK_CAN1_SERIAL] = imx_clk_gate2("can1_serial", "can_podf", base + 0x68, 16);
+ clks[IMX6UL_CLK_CAN2_IPG] = imx_clk_gate2("can2_ipg", "ipg", base + 0x68, 18);
+ clks[IMX6UL_CLK_CAN2_SERIAL] = imx_clk_gate2("can2_serial", "can_podf", base + 0x68, 20);
+ clks[IMX6UL_CLK_GPT2_BUS] = imx_clk_gate2("gpt2_bus", "perclk", base + 0x68, 24);
+ clks[IMX6UL_CLK_GPT2_SERIAL] = imx_clk_gate2("gpt2_serial", "perclk", base + 0x68, 26);
+ clks[IMX6UL_CLK_UART2_IPG] = imx_clk_gate2("uart2_ipg", "ipg", base + 0x68, 28);
+ clks[IMX6UL_CLK_UART2_SERIAL] = imx_clk_gate2("uart2_serial", "uart_podf", base + 0x68, 28);
+ clks[IMX6UL_CLK_AIPSTZ3] = imx_clk_gate2("aips_tz3", "ahb", base + 0x68, 30);
+
+ /* CCGR1 */
+ clks[IMX6UL_CLK_ECSPI1] = imx_clk_gate2("ecspi1", "ecspi_podf", base + 0x6c, 0);
+ clks[IMX6UL_CLK_ECSPI2] = imx_clk_gate2("ecspi2", "ecspi_podf", base + 0x6c, 2);
+ clks[IMX6UL_CLK_ECSPI3] = imx_clk_gate2("ecspi3", "ecspi_podf", base + 0x6c, 4);
+ clks[IMX6UL_CLK_ECSPI4] = imx_clk_gate2("ecspi4", "ecspi_podf", base + 0x6c, 6);
+ clks[IMX6UL_CLK_ADC2] = imx_clk_gate2("adc2", "ipg", base + 0x6c, 8);
+ clks[IMX6UL_CLK_UART3_IPG] = imx_clk_gate2("uart3_ipg", "ipg", base + 0x6c, 10);
+ clks[IMX6UL_CLK_UART3_SERIAL] = imx_clk_gate2("uart3_serial", "uart_podf", base + 0x6c, 10);
+ clks[IMX6UL_CLK_EPIT1] = imx_clk_gate2("epit1", "perclk", base + 0x6c, 12);
+ clks[IMX6UL_CLK_EPIT2] = imx_clk_gate2("epit2", "perclk", base + 0x6c, 14);
+ clks[IMX6UL_CLK_ADC1] = imx_clk_gate2("adc1", "ipg", base + 0x6c, 16);
+ clks[IMX6UL_CLK_GPT1_BUS] = imx_clk_gate2("gpt1_bus", "perclk", base + 0x6c, 20);
+ clks[IMX6UL_CLK_GPT1_SERIAL] = imx_clk_gate2("gpt1_serial", "perclk", base + 0x6c, 22);
+ clks[IMX6UL_CLK_UART4_IPG] = imx_clk_gate2("uart4_ipg", "ipg", base + 0x6c, 24);
+ clks[IMX6UL_CLK_UART4_SERIAL] = imx_clk_gate2("uart4_serail", "uart_podf", base + 0x6c, 24);
+
+ /* CCGR2 */
+ clks[IMX6UL_CLK_CSI] = imx_clk_gate2("csi", "csi_podf", base + 0x70, 2);
+ clks[IMX6UL_CLK_I2C1] = imx_clk_gate2("i2c1", "perclk", base + 0x70, 6);
+ clks[IMX6UL_CLK_I2C2] = imx_clk_gate2("i2c2", "perclk", base + 0x70, 8);
+ clks[IMX6UL_CLK_I2C3] = imx_clk_gate2("i2c3", "perclk", base + 0x70, 10);
+ clks[IMX6UL_CLK_OCOTP] = imx_clk_gate2("ocotp", "ipg", base + 0x70, 12);
+ clks[IMX6UL_CLK_IOMUXC] = imx_clk_gate2("iomuxc", "lcdif_podf", base + 0x70, 14);
+ clks[IMX6UL_CLK_LCDIF_APB] = imx_clk_gate2("lcdif_apb", "axi", base + 0x70, 28);
+ clks[IMX6UL_CLK_PXP] = imx_clk_gate2("pxp", "axi", base + 0x70, 30);
+
+ /* CCGR3 */
+ clks[IMX6UL_CLK_UART5_IPG] = imx_clk_gate2("uart5_ipg", "ipg", base + 0x74, 2);
+ clks[IMX6UL_CLK_UART5_SERIAL] = imx_clk_gate2("uart5_serial", "uart_podf", base + 0x74, 2);
+ clks[IMX6UL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x74, 4);
+ clks[IMX6UL_CLK_ENET_AHB] = imx_clk_gate2("enet_ahb", "ahb", base + 0x74, 4);
+ clks[IMX6UL_CLK_UART6_IPG] = imx_clk_gate2("uart6_ipg", "ipg", base + 0x74, 6);
+ clks[IMX6UL_CLK_UART6_SERIAL] = imx_clk_gate2("uart6_serial", "uart_podf", base + 0x74, 6);
+ clks[IMX6UL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_podf", base + 0x74, 10);
+ clks[IMX6UL_CLK_QSPI] = imx_clk_gate2("qspi1", "qspi1_podf", base + 0x74, 14);
+ clks[IMX6UL_CLK_WDOG1] = imx_clk_gate2("wdog1", "ipg", base + 0x74, 16);
+ clks[IMX6UL_CLK_MMDC_P0_FAST] = imx_clk_gate("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20);
+ clks[IMX6UL_CLK_MMDC_P0_IPG] = imx_clk_gate2("mmdc_p0_ipg", "ipg", base + 0x74, 24);
+ clks[IMX6UL_CLK_AXI] = imx_clk_gate("axi", "axi_podf", base + 0x74, 28);
+
+ /* CCGR4 */
+ clks[IMX6UL_CLK_PER_BCH] = imx_clk_gate2("per_bch", "bch_podf", base + 0x78, 12);
+ clks[IMX6UL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16);
+ clks[IMX6UL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18);
+ clks[IMX6UL_CLK_PWM3] = imx_clk_gate2("pwm3", "perclk", base + 0x78, 20);
+ clks[IMX6UL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22);
+ clks[IMX6UL_CLK_GPMI_BCH_APB] = imx_clk_gate2("gpmi_bch_apb", "bch_podf", base + 0x78, 24);
+ clks[IMX6UL_CLK_GPMI_BCH] = imx_clk_gate2("gpmi_bch", "gpmi_podf", base + 0x78, 26);
+ clks[IMX6UL_CLK_GPMI_IO] = imx_clk_gate2("gpmi_io", "enfc_podf", base + 0x78, 28);
+ clks[IMX6UL_CLK_GPMI_APB] = imx_clk_gate2("gpmi_apb", "bch_podf", base + 0x78, 30);
+
+ /* CCGR5 */
+ clks[IMX6UL_CLK_ROM] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0);
+ clks[IMX6UL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
+ clks[IMX6UL_CLK_KPP] = imx_clk_gate2("kpp", "ipg", base + 0x7c, 8);
+ clks[IMX6UL_CLK_WDOG2] = imx_clk_gate2("wdog2", "ipg", base + 0x7c, 10);
+ clks[IMX6UL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
+ clks[IMX6UL_CLK_UART1_IPG] = imx_clk_gate2("uart1_ipg", "ipg", base + 0x7c, 24);
+ clks[IMX6UL_CLK_UART1_SERIAL] = imx_clk_gate2("uart1_serial", "uart_podf", base + 0x7c, 24);
+ clks[IMX6UL_CLK_UART7_IPG] = imx_clk_gate2("uart7_ipg", "ipg", base + 0x7c, 26);
+ clks[IMX6UL_CLK_UART7_SERIAL] = imx_clk_gate2("uart7_serial", "uart_podf", base + 0x7c, 26);
+
+ /* CCGR6 */
+ clks[IMX6UL_CLK_USBOH3] = imx_clk_gate2("usboh3", "ipg", base + 0x80, 0);
+ clks[IMX6UL_CLK_USDHC1] = imx_clk_gate2("usdhc1", "usdhc1_podf", base + 0x80, 2);
+ clks[IMX6UL_CLK_USDHC2] = imx_clk_gate2("usdhc2", "usdhc2_podf", base + 0x80, 4);
+ clks[IMX6UL_CLK_SIM1] = imx_clk_gate2("sim1", "sim_sel", base + 0x80, 6);
+ clks[IMX6UL_CLK_SIM2] = imx_clk_gate2("sim2", "sim_sel", base + 0x80, 8);
+ clks[IMX6UL_CLK_EIM] = imx_clk_gate2("eim", "eim_slow_podf", base + 0x80, 10);
+ clks[IMX6UL_CLK_PWM8] = imx_clk_gate2("pwm8", "perclk", base + 0x80, 16);
+ clks[IMX6UL_CLK_UART8_IPG] = imx_clk_gate2("uart8_ipg", "ipg", base + 0x80, 14);
+ clks[IMX6UL_CLK_UART8_SERIAL] = imx_clk_gate2("uart8_serial", "uart_podf", base + 0x80, 14);
+ clks[IMX6UL_CLK_WDOG3] = imx_clk_gate2("wdog3", "ipg", base + 0x80, 20);
+ clks[IMX6UL_CLK_I2C4] = imx_clk_gate2("i2c4", "perclk", base + 0x80, 24);
+ clks[IMX6UL_CLK_PWM5] = imx_clk_gate2("pwm5", "perclk", base + 0x80, 26);
+ clks[IMX6UL_CLK_PWM6] = imx_clk_gate2("pwm6", "perclk", base + 0x80, 28);
+ clks[IMX6UL_CLK_PWM7] = imx_clk_gate2("pwm7", "perclk", base + 0x80, 30);
+
+ /* mask handshake of mmdc */
+ writel(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data);
+
+ /*
+ * Lower the AHB clock rate before changing the parent clock source,
+ * as AHB clock rate can NOT be higher than 133MHz, but its parent
+ * will be switched from 396MHz PFD to 528MHz PLL in order to increase
+ * AXI clock rate, so we need to lower AHB rate first to make sure at
+ * any time, AHB rate is <= 133MHz.
+ */
+ clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000);
+
+ /* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]);
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]);
+ clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]);
+
+ /* Make sure AHB rate is 132MHz */
+ clk_set_rate(clks[IMX6UL_CLK_AHB], 132000000);
+
+ /* set perclk to from OSC */
+ clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
+
+ clk_set_rate(clks[IMX6UL_CLK_ENET_REF], 50000000);
+ clk_set_rate(clks[IMX6UL_CLK_ENET2_REF], 50000000);
+ clk_set_rate(clks[IMX6UL_CLK_CSI], 24000000);
+
+ /* keep all the clks on just for bringup */
+ for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
+ clk_enable(clks[clks_init_on[i]]);
+
+ if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
+ clk_enable(clks[IMX6UL_CLK_USBPHY1_GATE]);
+ clk_enable(clks[IMX6UL_CLK_USBPHY2_GATE]);
+ }
+
+ clk_set_parent(clks[IMX6UL_CLK_CAN_SEL], clks[IMX6UL_CLK_PLL3_60M]);
+ clk_set_parent(clks[IMX6UL_CLK_SIM_PRE_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
+
+ clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id imx6_ccm_dt_ids[] = {
+ {
+ .compatible = "fsl,imx6ul-ccm",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d imx6_ccm_driver = {
+ .probe = imx6_ccm_probe,
+ .name = "imx6-ccm",
+ .of_compatible = DRV_OF_COMPAT(imx6_ccm_dt_ids),
+};
+
+static int imx6_ccm_init(void)
+{
+ return platform_driver_register(&imx6_ccm_driver);
+}
+core_initcall(imx6_ccm_init);
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH 3/7] ARM: i.MX6 gpt: Add i.MX6ul support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
In-Reply-To: <20161108171907.20726-1-s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/clocksource.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c
index b6873a7..8d00bbb 100644
--- a/arch/arm/mach-imx/clocksource.c
+++ b/arch/arm/mach-imx/clocksource.c
@@ -152,6 +152,9 @@ static __maybe_unused struct of_device_id imx_gpt_dt_ids[] = {
.compatible = "fsl,imx6dl-gpt",
.data = ®s_imx31,
}, {
+ .compatible = "fsl,imx6ul-gpt",
+ .data = ®s_imx31,
+ }, {
/* sentinel */
}
};
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH 6/7] ARM: i.MX: ocotp: Add i.MX6ul support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
In-Reply-To: <20161108171907.20726-1-s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/ocotp.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 3acec7f..e1d0c25 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -510,6 +510,9 @@ static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = {
.compatible = "fsl,imx6sl-ocotp",
.data = &imx6sl_ocotp_data,
}, {
+ .compatible = "fsl,imx6ul-ocotp",
+ .data = &imx6q_ocotp_data,
+ }, {
/* sentinel */
}
};
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH 1/7] ARM: i.MX: beginning i.MX6ul support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
In-Reply-To: <20161108171907.20726-1-s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/Kconfig | 4 ++++
arch/arm/mach-imx/imx.c | 2 ++
arch/arm/mach-imx/imx6.c | 3 +++
arch/arm/mach-imx/include/mach/imx6.h | 2 ++
4 files changed, 11 insertions(+)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index a80bc6b..b315f7d 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -149,6 +149,10 @@ config ARCH_IMX6SX
select OFTREE
select COMMON_CLK_OF_PROVIDER
+config ARCH_IMX6UL
+ bool
+ select ARCH_IMX6
+
config IMX_MULTI_BOARDS
bool "Allow multiple boards to be selected"
select HAVE_DEFAULT_ENVIRONMENT_NEW
diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c
index 5ab6afc..1d3f18c 100644
--- a/arch/arm/mach-imx/imx.c
+++ b/arch/arm/mach-imx/imx.c
@@ -63,6 +63,8 @@ static int imx_soc_from_dt(void)
return IMX_CPU_IMX6;
if (of_machine_is_compatible("fsl,imx6qp"))
return IMX_CPU_IMX6;
+ if (of_machine_is_compatible("fsl,imx6ul"))
+ return IMX_CPU_IMX6;
return 0;
}
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 18509a7..b242230 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -179,6 +179,9 @@ int imx6_init(void)
case IMX6_CPUTYPE_IMX6SX:
cputypestr = "i.MX6 SoloX";
break;
+ case IMX6_CPUTYPE_IMX6UL:
+ cputypestr = "i.MX6 UltraLite";
+ break;
default:
cputypestr = "unknown i.MX6";
break;
diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h
index e8ffa47..1d70d39 100644
--- a/arch/arm/mach-imx/include/mach/imx6.h
+++ b/arch/arm/mach-imx/include/mach/imx6.h
@@ -14,6 +14,7 @@ void imx6_init_lowlevel(void);
#define IMX6_CPUTYPE_IMX6SX 0x462
#define IMX6_CPUTYPE_IMX6D 0x263
#define IMX6_CPUTYPE_IMX6Q 0x463
+#define IMX6_CPUTYPE_IMX6UL 0x164
#define SCU_CONFIG 0x04
@@ -66,5 +67,6 @@ DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL);
DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q);
DEFINE_MX6_CPU_TYPE(mx6d, IMX6_CPUTYPE_IMX6D);
DEFINE_MX6_CPU_TYPE(mx6sx, IMX6_CPUTYPE_IMX6SX);
+DEFINE_MX6_CPU_TYPE(mx6ul, IMX6_CPUTYPE_IMX6UL);
#endif /* __MACH_IMX6_H */
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* i.MX6ul support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
This series adds i.MX6ul support. The only new thing really added is
the clock support, the rest is mainly adding compatible strings for
the different drivers.
Sascha
----------------------------------------------------------------
Sascha Hauer (7):
ARM: i.MX: beginning i.MX6ul support
ARM: i.MX6ul: Add clock support
ARM: i.MX6 gpt: Add i.MX6ul support
pinmux: imx-iomux-v3: Add i.MX6ul support
serial: i.MX: Add i.MX6ul support
ARM: i.MX: ocotp: Add i.MX6ul support
ARM: i.MX6 esdctl: Add i.MX6ul support
arch/arm/mach-imx/Kconfig | 4 +
arch/arm/mach-imx/Makefile | 1 +
arch/arm/mach-imx/clk-imx6ul.c | 426 ++++++++++++++++++++++++++++++++
arch/arm/mach-imx/clocksource.c | 3 +
arch/arm/mach-imx/esdctl.c | 19 ++
arch/arm/mach-imx/imx.c | 2 +
arch/arm/mach-imx/imx6.c | 3 +
arch/arm/mach-imx/include/mach/esdctl.h | 1 +
arch/arm/mach-imx/include/mach/imx6.h | 2 +
arch/arm/mach-imx/ocotp.c | 3 +
drivers/pinctrl/imx-iomux-v3.c | 2 +
drivers/serial/serial_imx.c | 3 +
12 files changed, 469 insertions(+)
create mode 100644 arch/arm/mach-imx/clk-imx6ul.c
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply
* [PATCH 5/7] serial: i.MX: Add i.MX6ul support
From: Sascha Hauer @ 2016-11-08 17:19 UTC (permalink / raw)
To: Barebox List
In-Reply-To: <20161108171907.20726-1-s.hauer@pengutronix.de>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/serial/serial_imx.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index f140310..2b1e5e0 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -287,6 +287,9 @@ static __maybe_unused struct of_device_id imx_serial_dt_ids[] = {
.compatible = "fsl,imx21-uart",
.data = &imx21_data,
}, {
+ .compatible = "fsl,imx6ul-uart",
+ .data = &imx21_data,
+ }, {
/* sentinel */
}
};
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
* [PATCH] ARM: i.MX: OCOTP: Add functions to access fuses field wise
From: Sascha Hauer @ 2016-11-08 13:43 UTC (permalink / raw)
To: Barebox List
Add functions to access the OCOTP fuses field wise, similar to what has
been done for the IIM. Also add a i.MX6 fusemap header file.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
arch/arm/mach-imx/include/mach/imx6-fusemap.h | 63 ++++++++++++++++++++++++++
arch/arm/mach-imx/include/mach/ocotp.h | 20 +++++++++
arch/arm/mach-imx/ocotp.c | 65 +++++++++++++++++++++++++++
3 files changed, 148 insertions(+)
create mode 100644 arch/arm/mach-imx/include/mach/imx6-fusemap.h
create mode 100644 arch/arm/mach-imx/include/mach/ocotp.h
diff --git a/arch/arm/mach-imx/include/mach/imx6-fusemap.h b/arch/arm/mach-imx/include/mach/imx6-fusemap.h
new file mode 100644
index 0000000..5fdd904
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/imx6-fusemap.h
@@ -0,0 +1,63 @@
+#ifndef __MACH_IMX_IMX6_OCOTP_H
+#define __MACH_IMX_IMX6_OCOTP_H
+
+#include <mach/ocotp.h>
+
+#define IMX6_OCOTP_TESTER_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(0) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_BOOT_CFG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(2) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_MEM_TRIM_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(4) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_SJC_RESP_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(6) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_MAC_ADDR_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(8) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_GP1_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(10) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_GP2_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(12) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_SRK_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(14) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_ANALOG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(18) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_MISC_CONF_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(22) | OCOTP_WIDTH(1))
+
+/* 0 <= n <= 1 */
+#define IMX6_OCOTP_UNIQUE_ID(n) (OCOTP_WORD(0x410 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32))
+#define IMX6_OCOTP_SI_REV (OCOTP_WORD(0x430) | OCOTP_BIT(16) | OCOTP_WIDTH(4))
+#define IMX6_OCOTP_NUM_CORES (OCOTP_WORD(0x430) | OCOTP_BIT(20) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_SATA_RST_SRC (OCOTP_WORD(0x430) | OCOTP_BIT(24) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_MLB_DISABLE (OCOTP_WORD(0x430) | OCOTP_BIT(26) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_VPU_DISABLE (OCOTP_WORD(0x440) | OCOTP_BIT(15) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_SPEED_GRADING (OCOTP_WORD(0x440) | OCOTP_BIT(16) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_BOOT_CFG1 (OCOTP_WORD(0x450) | OCOTP_BIT(0) | OCOTP_WIDTH(8))
+#define IMX6_OCOTP_BOOT_CFG2 (OCOTP_WORD(0x450) | OCOTP_BIT(8) | OCOTP_WIDTH(8))
+#define IMX6_OCOTP_BOOT_CFG3 (OCOTP_WORD(0x450) | OCOTP_BIT(16) | OCOTP_WIDTH(8))
+#define IMX6_OCOTP_BOOT_CFG4 (OCOTP_WORD(0x450) | OCOTP_BIT(24) | OCOTP_WIDTH(8))
+#define IMX6_OCOTP_SEC_CONFIG (OCOTP_WORD(0x460) | OCOTP_BIT(1) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_DIR_BT_DIS (OCOTP_WORD(0x460) | OCOTP_BIT(3) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_BT_FUSE_SEL (OCOTP_WORD(0x460) | OCOTP_BIT(4) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_DDR3_CONFIG (OCOTP_WORD(0x460) | OCOTP_BIT(8) | OCOTP_WIDTH(8))
+#define IMX6_OCOTP_HDCP (OCOTP_WORD(0x460) | OCOTP_BIT(16) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_SJC_DISABLE (OCOTP_WORD(0x460) | OCOTP_BIT(20) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_WDOG_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(21) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_JTAG_SMODE (OCOTP_WORD(0x460) | OCOTP_BIT(22) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_KTE (OCOTP_WORD(0x460) | OCOTP_BIT(26) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_JTAG_HEO (OCOTP_WORD(0x460) | OCOTP_BIT(27) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_TZASC_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(28) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_SDMMC_HYS_EN (OCOTP_WORD(0x460) | OCOTP_BIT(29) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_eMMC_RESET_EN (OCOTP_WORD(0x460) | OCOTP_BIT(30) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_NAND_READ_CMD_CODE1 (OCOTP_WORD(0x470) | OCOTP_BIT(0) | OCOTP_WIDTH(8))
+#define IMX6_OCOTP_NAND_READ_CMD_CODE2 (OCOTP_WORD(0x470) | OCOTP_BIT(8) | OCOTP_WIDTH(8))
+#define IMX6_OCOTP_BT_LPB_POLARITY (OCOTP_WORD(0x470) | OCOTP_BIT(20) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_LPB_BOOT (OCOTP_WORD(0x470) | OCOTP_BIT(21) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_MMC_DLL_DLY (OCOTP_WORD(0x470) | OCOTP_BIT(24) | OCOTP_WIDTH(7))
+#define IMX6_OCOTP_TEMPERATURE_GRADE (OCOTP_WORD(0x480) | OCOTP_BIT(6) | OCOTP_WIDTH(2))
+#define IMX6_OCOTP_POWER_GATE_CORES (OCOTP_WORD(0x4d0) | OCOTP_BIT(31) | OCOTP_WIDTH(1))
+#define IMX6_OCOTP_USB_VID (OCOTP_WORD(0x4f0) | OCOTP_BIT(0) | OCOTP_WIDTH(16))
+#define IMX6_OCOTP_USB_PID (OCOTP_WORD(0x4f0) | OCOTP_BIT(16) | OCOTP_WIDTH(16))
+/* 0 <= n <= 7 */
+#define IMX6_OCOTP_SRK_HASH(n) (OCOTP_WORD(0x580 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32))
+#define IMX6_OCOTP_SJC_RESP_31_0 (OCOTP_WORD(0x600) | OCOTP_BIT(0) | OCOTP_WIDTH(32))
+#define IMX6_OCOTP_SJC_RESP_55_32 (OCOTP_WORD(0x610) | OCOTP_BIT(0) | OCOTP_WIDTH(24))
+#define IMX6_OCOTP_MAC_ADDR_31_0 (OCOTP_WORD(0x620) | OCOTP_BIT(0) | OCOTP_WIDTH(32))
+#define IMX6_OCOTP_MAC_ADDR_47_32 (OCOTP_WORD(0x630) | OCOTP_BIT(0) | OCOTP_WIDTH(16))
+#define IMX6_OCOTP_GP1 (OCOTP_WORD(0x660) | OCOTP_BIT(0) | OCOTP_WIDTH(32))
+#define IMX6_OCOTP_GP2 (OCOTP_WORD(0x670) | OCOTP_BIT(0) | OCOTP_WIDTH(32))
+#define IMX6_OCOTP_PAD_SETTINGS (OCOTP_WORD(0x6d0) | OCOTP_BIT(0) | OCOTP_WIDTH(6))
+#define IMX6DQ_OCOTP_TEST_PORT_DISABLE (OCOTP_WORD(0x6e0) | OCOTP_BIT(1) | OCOTP_WIDTH(1))
+#define IMX6SDL_OCOTP_FIELD_RETURN (OCOTP_WORD(0x6e0) | OCOTP_BIT(0) | OCOTP_WIDTH(1))
+
+#endif /* __MACH_IMX_IMX6_OCOTP_H */
diff --git a/arch/arm/mach-imx/include/mach/ocotp.h b/arch/arm/mach-imx/include/mach/ocotp.h
new file mode 100644
index 0000000..430bc75
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/ocotp.h
@@ -0,0 +1,20 @@
+#ifndef __MACH_IMX_OCOTP_H
+#define __MACH_IMX_OCOTP_H
+
+#define OCOTP_WORD_MASK_WIDTH 8
+#define OCOTP_WORD_MASK_SHIFT 0
+#define OCOTP_WORD(n) ((((n) - 0x400) >> 4) & ((1 << OCOTP_WORD_MASK_WIDTH) - 1))
+
+#define OCOTP_BIT_MASK_WIDTH 5
+#define OCOTP_BIT_MASK_SHIFT (OCOTP_WORD_MASK_SHIFT + OCOTP_WORD_MASK_WIDTH)
+#define OCOTP_BIT(n) (((n) & ((1 << OCOTP_BIT_MASK_WIDTH) - 1)) << OCOTP_BIT_MASK_SHIFT)
+
+#define OCOTP_WIDTH_MASK_WIDTH 5
+#define OCOTP_WIDTH_MASK_SHIFT (OCOTP_BIT_MASK_SHIFT + OCOTP_BIT_MASK_WIDTH)
+#define OCOTP_WIDTH(n) ((((n) - 1) & ((1 << OCOTP_WIDTH_MASK_WIDTH) - 1)) << OCOTP_WIDTH_MASK_SHIFT)
+
+int imx_ocotp_read_field(uint32_t field, unsigned *value);
+int imx_ocotp_write_field(uint32_t field, unsigned value);
+int imx_ocotp_permanent_write(int enable);
+
+#endif /* __MACH_IMX_OCOTP_H */
diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c
index 17b944b..3acec7f 100644
--- a/arch/arm/mach-imx/ocotp.c
+++ b/arch/arm/mach-imx/ocotp.c
@@ -28,6 +28,7 @@
#include <clock.h>
#include <regmap.h>
#include <linux/clk.h>
+#include <mach/ocotp.h>
/*
* a single MAC address reference has the form
@@ -87,6 +88,8 @@ struct ocotp_priv {
struct regmap_config map_config;
};
+static struct ocotp_priv *imx_ocotp;
+
static int imx6_ocotp_set_timing(struct ocotp_priv *priv)
{
u32 clk_rate;
@@ -282,6 +285,66 @@ static int imx_ocotp_reg_write(void *ctx, unsigned int reg, unsigned int val)
return 0;
}
+static void imx_ocotp_field_decode(uint32_t field, unsigned *word,
+ unsigned *bit, unsigned *mask)
+{
+ unsigned width;
+
+ *word = ((field >> OCOTP_WORD_MASK_SHIFT) & ((1 << OCOTP_WORD_MASK_WIDTH) - 1)) * 4;
+ *bit = (field >> OCOTP_BIT_MASK_SHIFT) & ((1 << OCOTP_BIT_MASK_WIDTH) - 1);
+ width = ((field >> OCOTP_WIDTH_MASK_SHIFT) & ((1 << OCOTP_WIDTH_MASK_WIDTH) - 1)) + 1;
+ *mask = (1 << width) - 1;
+}
+
+int imx_ocotp_read_field(uint32_t field, unsigned *value)
+{
+ unsigned word, bit, mask, val;
+ int ret;
+
+ imx_ocotp_field_decode(field, &word, &bit, &mask);
+
+ ret = imx_ocotp_reg_read(imx_ocotp, word, &val);
+ if (ret)
+ return ret;
+
+ val >>= bit;
+ val &= mask;
+
+ dev_dbg(&imx_ocotp->dev, "%s: word: 0x%x bit: %d mask: 0x%x val: 0x%x\n",
+ __func__, word, bit, mask, val);
+
+ *value = val;
+
+ return 0;
+}
+
+int imx_ocotp_write_field(uint32_t field, unsigned value)
+{
+ unsigned word, bit, mask;
+ int ret;
+
+ imx_ocotp_field_decode(field, &word, &bit, &mask);
+
+ value &= mask;
+ value <<= bit;
+
+ ret = imx_ocotp_reg_write(imx_ocotp, word, value);
+ if (ret)
+ return ret;
+
+ dev_dbg(&imx_ocotp->dev, "%s: word: 0x%x bit: %d mask: 0x%x val: 0x%x\n",
+ __func__, word, bit, mask, value);
+
+ return 0;
+}
+
+int imx_ocotp_permanent_write(int enable)
+{
+ imx_ocotp->permanent_write_enable = enable;
+
+ return 0;
+}
+
static uint32_t inc_offset(uint32_t offset)
{
if ((offset & 0x3) == 0x3)
@@ -412,6 +475,8 @@ static int imx_ocotp_probe(struct device_d *dev)
if (ret)
return ret;
+ imx_ocotp = priv;
+
if (IS_ENABLED(CONFIG_IMX_OCOTP_WRITE)) {
dev_add_param_bool(&(priv->dev), "permanent_write_enable",
NULL, NULL, &priv->permanent_write_enable, NULL);
--
2.10.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox