All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support
@ 2018-12-31 16:59 Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 01/26] clk: Add Allwinner A64 CLK driver Jagan Teki
                   ` (27 more replies)
  0 siblings, 28 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Although the previous version[1] is properly handled the clock gates
with enable and disable management, but this series is trying to add
some more complex Allwinner CLK architecture by handling parent clock
and other CLK attributes.

Allwinner Clock control unit comprises of parent clocks, gates, multiplexers,
dividers, multipliers, pre/post dividers and flags etc.

So, the U-Boot implementation of ccu has divided into gates and tree.
gates are generic clock configuration of enable/disable bit management
and these can be handled via ccu_clock_gate, which is almost same as
previous version changes.

Tree clock has more Allwinner CLK attributes like clock type, fixed clocks,
misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be
managed via ccu_clock_tree.

On top of initial clock gates supported from previous version, this 
series is trying to add support for MP, NK, MISC, FIXED clock types
with get_rate functionality and that can eventually used by uart driver.

On the summary, this would be an initial infrasture that can fit into
remaining clock handle support like set_rate, so the rest of code will
add on the requirement basics.

Once this is fine, I will try to add code for other parts especially for
MMC since we have migration deadline for BLK, MMC, SCSI.

So, please do let me know if anyone have any inputs.

All these changes available at u-boot-sunxi/clk-next

thanks,
Jagan.

[1] https://patchwork.ozlabs.org/cover/962226/

Jagan Teki (26):
  clk: Add Allwinner A64 CLK driver
  reset: Add Allwinner RESET driver
  clk: sunxi: Add Allwinner H3/H5 CLK driver
  clk: sunxi: Add Allwinner A10/A20 CLK driver
  clk: sunxi: Add Allwinner A10s/A13 CLK driver
  clk: sunxi: Add Allwinner A31 CLK driver
  clk: sunxi: Add Allwinner A23/A33 CLK driver
  clk: sunxi: Add Allwinner A83T CLK driver
  clk: sunxi: Add Allwinner R40 CLK driver
  clk: sunxi: Add Allwinner V3S CLK driver
  clk: sunxi: Implement UART clocks
  clk: sunxi: Implement UART resets
  clk: sunxi: Add Allwinner H6 CLK driver
  sunxi: A64: Update sun50i-a64-ccu.h
  clk: sunxi: Add ccu clock tree support
  sunxi: Enable CLK
  phy: sun4i-usb: Use CLK and RESET support
  reset: Add reset valid
  musb-new: sunxi: Use CLK and RESET support
  sunxi: usb: Switch to Generic host controllers
  usb: host: Drop [e-o]hci-sunxi drivers
  clk: sunxi: Implement SPI clocks
  spi: sun4i: Add CLK support
  clk: sunxi: Implement A64 SPI clocks, resets
  spi: Add Allwinner A31 SPI driver
  board: sopine: Enable SPI/SPI-FLASH

 .../sun50i-a64-sopine-baseboard-u-boot.dtsi   |  16 +
 arch/arm/include/asm/arch-sunxi/ccu.h         | 284 +++++++++++++
 arch/arm/mach-sunxi/Kconfig                   |  12 +
 configs/A10-OLinuXino-Lime_defconfig          |   1 +
 configs/A10s-OLinuXino-M_defconfig            |   1 +
 configs/A13-OLinuXinoM_defconfig              |   1 +
 configs/A13-OLinuXino_defconfig               |   1 +
 configs/A20-OLinuXino-Lime2-eMMC_defconfig    |   1 +
 configs/A20-OLinuXino-Lime2_defconfig         |   1 +
 configs/A20-OLinuXino-Lime_defconfig          |   1 +
 configs/A20-Olimex-SOM204-EVB_defconfig       |   1 +
 configs/Auxtek-T003_defconfig                 |   1 +
 configs/Auxtek-T004_defconfig                 |   1 +
 configs/Bananapi_defconfig                    |   1 +
 configs/Bananapi_m2m_defconfig                |   1 +
 configs/Bananapro_defconfig                   |   1 +
 configs/CHIP_defconfig                        |   1 +
 configs/CHIP_pro_defconfig                    |   1 +
 configs/CSQ_CS908_defconfig                   |   1 +
 configs/Colombus_defconfig                    |   1 +
 configs/Cubieboard2_defconfig                 |   1 +
 configs/Cubieboard_defconfig                  |   1 +
 configs/Cubietruck_plus_defconfig             |   1 +
 configs/Hummingbird_A31_defconfig             |   1 +
 configs/Itead_Ibox_A20_defconfig              |   1 +
 configs/Linksprite_pcDuino3_Nano_defconfig    |   1 +
 configs/Linksprite_pcDuino3_defconfig         |   1 +
 configs/Linksprite_pcDuino_defconfig          |   1 +
 configs/MK808C_defconfig                      |   1 +
 configs/Marsboard_A10_defconfig               |   1 +
 configs/Mele_A1000G_quad_defconfig            |   1 +
 configs/Mele_A1000_defconfig                  |   1 +
 configs/Mele_I7_defconfig                     |   1 +
 configs/Mele_M3_defconfig                     |   1 +
 configs/Mele_M5_defconfig                     |   1 +
 configs/Mele_M9_defconfig                     |   1 +
 configs/Mini-X_defconfig                      |   1 +
 configs/Orangepi_defconfig                    |   1 +
 configs/Orangepi_mini_defconfig               |   1 +
 configs/Sinlinx_SinA31s_defconfig             |   1 +
 configs/Sinlinx_SinA33_defconfig              |   1 +
 configs/Sinovoip_BPI_M2_Plus_defconfig        |   1 +
 configs/Sinovoip_BPI_M2_defconfig             |   1 +
 configs/Sinovoip_BPI_M3_defconfig             |   1 +
 configs/Wexler_TAB7200_defconfig              |   1 +
 configs/Wobo_i5_defconfig                     |   1 +
 configs/a64-olinuxino_defconfig               |   1 +
 configs/ba10_tv_box_defconfig                 |   1 +
 configs/bananapi_m1_plus_defconfig            |   1 +
 configs/bananapi_m64_defconfig                |   1 +
 configs/ga10h_v1_1_defconfig                  |   1 +
 configs/h8_homlet_v2_defconfig                |   1 +
 configs/i12-tvbox_defconfig                   |   1 +
 configs/icnova-a20-swac_defconfig             |   1 +
 configs/inet1_defconfig                       |   1 +
 configs/inet_q972_defconfig                   |   1 +
 configs/jesurun_q5_defconfig                  |   1 +
 configs/libretech_all_h3_cc_h2_plus_defconfig |   1 +
 configs/libretech_all_h3_cc_h3_defconfig      |   1 +
 configs/libretech_all_h3_cc_h5_defconfig      |   1 +
 configs/mixtile_loftq_defconfig               |   1 +
 configs/mk802_a10s_defconfig                  |   1 +
 configs/mk802_defconfig                       |   1 +
 configs/mk802ii_defconfig                     |   1 +
 configs/nanopi_a64_defconfig                  |   1 +
 configs/nanopi_m1_defconfig                   |   1 +
 configs/nanopi_m1_plus_defconfig              |   1 +
 configs/nanopi_neo2_defconfig                 |   1 +
 configs/nanopi_neo_air_defconfig              |   1 +
 configs/nanopi_neo_defconfig                  |   1 +
 configs/nanopi_neo_plus2_defconfig            |   1 +
 configs/orangepi_2_defconfig                  |   1 +
 configs/orangepi_lite_defconfig               |   1 +
 configs/orangepi_one_defconfig                |   1 +
 configs/orangepi_pc2_defconfig                |   1 +
 configs/orangepi_pc_defconfig                 |   1 +
 configs/orangepi_pc_plus_defconfig            |   1 +
 configs/orangepi_plus2e_defconfig             |   1 +
 configs/orangepi_plus_defconfig               |   1 +
 configs/orangepi_prime_defconfig              |   1 +
 configs/orangepi_r1_defconfig                 |   1 +
 configs/orangepi_win_defconfig                |   1 +
 configs/orangepi_zero_defconfig               |   1 +
 configs/orangepi_zero_plus2_defconfig         |   1 +
 configs/orangepi_zero_plus_defconfig          |   1 +
 configs/parrot_r16_defconfig                  |   1 +
 configs/pine64_plus_defconfig                 |   1 +
 configs/r7-tv-dongle_defconfig                |   1 +
 configs/sopine_baseboard_defconfig            |   8 +
 configs/sun8i_a23_evb_defconfig               |   1 +
 configs/sunxi_Gemei_G9_defconfig              |   1 +
 configs/tbs_a711_defconfig                    |   1 +
 drivers/clk/Kconfig                           |   1 +
 drivers/clk/Makefile                          |   1 +
 drivers/clk/sunxi/Kconfig                     |  82 ++++
 drivers/clk/sunxi/Makefile                    |  18 +
 drivers/clk/sunxi/clk_a10.c                   |  77 ++++
 drivers/clk/sunxi/clk_a10s.c                  |  68 +++
 drivers/clk/sunxi/clk_a23.c                   |  75 ++++
 drivers/clk/sunxi/clk_a31.c                   |  82 ++++
 drivers/clk/sunxi/clk_a64.c                   | 125 ++++++
 drivers/clk/sunxi/clk_a83t.c                  |  75 ++++
 drivers/clk/sunxi/clk_h3.c                    |  89 ++++
 drivers/clk/sunxi/clk_h6.c                    |  53 +++
 drivers/clk/sunxi/clk_r40.c                   |  88 ++++
 drivers/clk/sunxi/clk_sunxi.c                 | 256 +++++++++++
 drivers/clk/sunxi/clk_v3s.c                   |  59 +++
 drivers/phy/allwinner/phy-sun4i-usb.c         |  77 +++-
 drivers/reset/Kconfig                         |   8 +
 drivers/reset/Makefile                        |   1 +
 drivers/reset/reset-sunxi.c                   | 125 ++++++
 drivers/spi/Kconfig                           |   6 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/sun4i_spi.c                       |  46 +-
 drivers/spi/sun6i_spi.c                       | 398 ++++++++++++++++++
 drivers/usb/host/Kconfig                      |   2 +
 drivers/usb/host/Makefile                     |   2 -
 drivers/usb/host/ehci-sunxi.c                 | 204 ---------
 drivers/usb/host/ohci-sunxi.c                 | 233 ----------
 drivers/usb/musb-new/sunxi.c                  |  81 ++--
 include/configs/sun4i.h                       |   4 -
 include/configs/sun50i.h                      |   5 -
 include/configs/sun5i.h                       |   4 -
 include/configs/sun6i.h                       |   4 -
 include/configs/sun7i.h                       |   4 -
 include/configs/sun8i.h                       |   4 -
 include/configs/sunxi-common.h                |   1 -
 include/dt-bindings/clock/sun50i-a64-ccu.h    |   2 +
 include/reset.h                               |  11 +
 scripts/config_whitelist.txt                  |   2 -
 130 files changed, 2248 insertions(+), 534 deletions(-)
 create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
 create mode 100644 arch/arm/include/asm/arch-sunxi/ccu.h
 create mode 100644 drivers/clk/sunxi/Kconfig
 create mode 100644 drivers/clk/sunxi/Makefile
 create mode 100644 drivers/clk/sunxi/clk_a10.c
 create mode 100644 drivers/clk/sunxi/clk_a10s.c
 create mode 100644 drivers/clk/sunxi/clk_a23.c
 create mode 100644 drivers/clk/sunxi/clk_a31.c
 create mode 100644 drivers/clk/sunxi/clk_a64.c
 create mode 100644 drivers/clk/sunxi/clk_a83t.c
 create mode 100644 drivers/clk/sunxi/clk_h3.c
 create mode 100644 drivers/clk/sunxi/clk_h6.c
 create mode 100644 drivers/clk/sunxi/clk_r40.c
 create mode 100644 drivers/clk/sunxi/clk_sunxi.c
 create mode 100644 drivers/clk/sunxi/clk_v3s.c
 create mode 100644 drivers/reset/reset-sunxi.c
 create mode 100644 drivers/spi/sun6i_spi.c
 delete mode 100644 drivers/usb/host/ehci-sunxi.c
 delete mode 100644 drivers/usb/host/ohci-sunxi.c

-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 01/26] clk: Add Allwinner A64 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 02/26] reset: Add Allwinner RESET driver Jagan Teki
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner A64.

Implement USB clock enable and disable functions for
OHCI, EHCI, OTG and USBPHY gate and clock registers
via ccu clk gate table.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 arch/arm/include/asm/arch-sunxi/ccu.h | 65 +++++++++++++++++++++++
 drivers/clk/Kconfig                   |  1 +
 drivers/clk/Makefile                  |  1 +
 drivers/clk/sunxi/Kconfig             | 18 +++++++
 drivers/clk/sunxi/Makefile            |  9 ++++
 drivers/clk/sunxi/clk_a64.c           | 46 +++++++++++++++++
 drivers/clk/sunxi/clk_sunxi.c         | 74 +++++++++++++++++++++++++++
 7 files changed, 214 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-sunxi/ccu.h
 create mode 100644 drivers/clk/sunxi/Kconfig
 create mode 100644 drivers/clk/sunxi/Makefile
 create mode 100644 drivers/clk/sunxi/clk_a64.c
 create mode 100644 drivers/clk/sunxi/clk_sunxi.c

diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
new file mode 100644
index 0000000000..db69c8f0d5
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/ccu.h
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#ifndef _ASM_ARCH_CCU_H
+#define _ASM_ARCH_CCU_H
+
+/**
+ * enum ccu_clk_flags - ccu clock flags
+ *
+ * @CCU_CLK_F_INIT_DONE:		clock gate init done check
+ */
+enum ccu_clk_flags {
+	CCU_CLK_F_INIT_DONE		= BIT(0),
+};
+
+/**
+ * struct ccu_clk_gate - ccu clock gate
+ * @off:	gate offset
+ * @bit:	gate bit
+ * @flags:	clock gate flags
+ */
+struct ccu_clk_gate {
+	u16 off;
+	u32 bit;
+	enum ccu_clk_flags flags;
+};
+
+#define GATE(_off, _bit) {			\
+	.off = _off,				\
+	.bit = _bit,				\
+	.flags = CCU_CLK_F_INIT_DONE,		\
+}
+
+/**
+ * struct ccu_desc - clock control unit descriptor
+ *
+ * @gates:	clock gates
+ */
+struct ccu_desc {
+	const struct ccu_clk_gate *gates;
+};
+
+/**
+ * struct ccu_priv - sunxi clock control unit
+ *
+ * @base:	base address
+ * @desc:	ccu descriptor
+ */
+struct ccu_priv {
+	void *base;
+	const struct ccu_desc *desc;
+};
+
+/**
+ * sunxi_clk_probe - common sunxi clock probe
+ * @dev:	clock device
+ */
+int sunxi_clk_probe(struct udevice *dev);
+
+extern struct clk_ops sunxi_clk_ops;
+
+#endif /* _ASM_ARCH_CCU_H */
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index eadf7f8250..51c931b906 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -104,6 +104,7 @@ source "drivers/clk/imx/Kconfig"
 source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/owl/Kconfig"
 source "drivers/clk/renesas/Kconfig"
+source "drivers/clk/sunxi/Kconfig"
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/uniphier/Kconfig"
 
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 9acbb1a650..6a4ff9143b 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_CLK_HSDK) += clk-hsdk-cgu.o
 obj-$(CONFIG_CLK_MPC83XX) += mpc83xx_clk.o
 obj-$(CONFIG_CLK_OWL) += owl/
 obj-$(CONFIG_CLK_RENESAS) += renesas/
+obj-$(CONFIG_ARCH_SUNXI) += sunxi/
 obj-$(CONFIG_CLK_STM32F) += clk_stm32f.o
 obj-$(CONFIG_CLK_STM32MP1) += clk_stm32mp1.o
 obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
new file mode 100644
index 0000000000..bf5ecb3801
--- /dev/null
+++ b/drivers/clk/sunxi/Kconfig
@@ -0,0 +1,18 @@
+config CLK_SUNXI
+	bool "Clock support for Allwinner SoCs"
+	depends on CLK && ARCH_SUNXI
+	default y
+	help
+	  This enables support for common clock driver API on Allwinner
+	  SoCs.
+
+if CLK_SUNXI
+
+config CLK_SUN50I_A64
+	bool "Clock driver for Allwinner A64"
+	default MACH_SUN50I
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner A64 SoC.
+
+endif # CLK_SUNXI
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
new file mode 100644
index 0000000000..fb20d28333
--- /dev/null
+++ b/drivers/clk/sunxi/Makefile
@@ -0,0 +1,9 @@
+#
+# Copyright (C) 2018 Amarula Solutions.
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
+
+obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
new file mode 100644
index 0000000000..803a2f711d
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun50i-a64-ccu.h>
+
+static const struct ccu_clk_gate a64_gates[] = {
+	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
+	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
+	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(25)),
+	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(28)),
+	[CLK_BUS_OHCI1]		= GATE(0x060, BIT(29)),
+
+	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
+	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
+	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
+	[CLK_USB_HSIC_12M]	= GATE(0x0cc, BIT(11)),
+	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(16)),
+	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(17)),
+};
+
+static const struct ccu_desc a64_ccu_desc = {
+	.gates = a64_gates,
+};
+
+static const struct udevice_id a64_ccu_ids[] = {
+	{ .compatible = "allwinner,sun50i-a64-ccu",
+	  .data = (ulong)&a64_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun50i_a64) = {
+	.name		= "sun50i_a64_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= a64_ccu_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+};
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
new file mode 100644
index 0000000000..345d706c2a
--- /dev/null
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/arch/ccu.h>
+#include <linux/log2.h>
+
+static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
+					       unsigned long id)
+{
+	return &priv->desc->gates[id];
+}
+
+static int sunxi_set_gate(struct clk *clk, bool on)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_gate *gate = priv_to_gate(priv, clk->id);
+	u32 reg;
+
+	if (!(gate->flags & CCU_CLK_F_INIT_DONE)) {
+		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
+		return 0;
+	}
+
+	debug("%s: (CLK#%ld) off#0x%x, BIT(%d)\n", __func__,
+	      clk->id, gate->off, ilog2(gate->bit));
+
+	reg = readl(priv->base + gate->off);
+	if (on)
+		reg |= gate->bit;
+	else
+		reg &= ~gate->bit;
+
+	writel(reg, priv->base + gate->off);
+
+	return 0;
+}
+
+static int sunxi_clk_enable(struct clk *clk)
+{
+	return sunxi_set_gate(clk, true);
+}
+
+static int sunxi_clk_disable(struct clk *clk)
+{
+	return sunxi_set_gate(clk, false);
+}
+
+struct clk_ops sunxi_clk_ops = {
+	.enable = sunxi_clk_enable,
+	.disable = sunxi_clk_disable,
+};
+
+int sunxi_clk_probe(struct udevice *dev)
+{
+	struct ccu_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
+	if (!priv->desc)
+		return -EINVAL;
+
+	return 0;
+}
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 02/26] reset: Add Allwinner RESET driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 01/26] clk: Add Allwinner A64 CLK driver Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2019-01-10  0:50   ` André Przywara
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 03/26] clk: sunxi: Add Allwinner H3/H5 CLK driver Jagan Teki
                   ` (25 subsequent siblings)
  27 siblings, 1 reply; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add common reset driver for all Allwinner SoC's.

Since CLK and RESET share common DT compatible, it is CLK driver
job is to bind the reset driver. So add CLK bind call on respective
SoC driver by passing ccu map descriptor so-that reset deassert,
deassert operations held based on ccu reset table defined from
CLK driver.

Select DM_RESET via CLK_SUNXI, this make hidden section of RESET
since CLK and RESET share common DT compatible and code.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 arch/arm/include/asm/arch-sunxi/ccu.h |  29 ++++++
 drivers/clk/sunxi/Kconfig             |   1 +
 drivers/clk/sunxi/clk_a64.c           |  20 +++++
 drivers/reset/Kconfig                 |   8 ++
 drivers/reset/Makefile                |   1 +
 drivers/reset/reset-sunxi.c           | 125 ++++++++++++++++++++++++++
 6 files changed, 184 insertions(+)
 create mode 100644 drivers/reset/reset-sunxi.c

diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
index db69c8f0d5..3fdc26978d 100644
--- a/arch/arm/include/asm/arch-sunxi/ccu.h
+++ b/arch/arm/include/asm/arch-sunxi/ccu.h
@@ -34,13 +34,33 @@ struct ccu_clk_gate {
 	.flags = CCU_CLK_F_INIT_DONE,		\
 }
 
+/**
+ * struct ccu_reset - ccu reset
+ * @off:	reset offset
+ * @bit:	reset bit
+ * @flags:	reset flags
+ */
+struct ccu_reset {
+	u16 off;
+	u32 bit;
+	enum ccu_clk_flags flags;
+};
+
+#define RESET(_off, _bit) {			\
+	.off = _off,				\
+	.bit = _bit,				\
+	.flags = CCU_CLK_F_INIT_DONE,		\
+}
+
 /**
  * struct ccu_desc - clock control unit descriptor
  *
  * @gates:	clock gates
+ * @resets:	reset unit
  */
 struct ccu_desc {
 	const struct ccu_clk_gate *gates;
+	const struct ccu_reset *resets;
 };
 
 /**
@@ -62,4 +82,13 @@ int sunxi_clk_probe(struct udevice *dev);
 
 extern struct clk_ops sunxi_clk_ops;
 
+/**
+ * sunxi_reset_bind() - reset binding
+ *
+ * @dev:       reset device
+ * @count:     reset count
+ * @return 0 success, or error value
+ */
+int sunxi_reset_bind(struct udevice *dev, ulong count);
+
 #endif /* _ASM_ARCH_CCU_H */
diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index bf5ecb3801..041d711e58 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -1,6 +1,7 @@
 config CLK_SUNXI
 	bool "Clock support for Allwinner SoCs"
 	depends on CLK && ARCH_SUNXI
+	select DM_RESET
 	default y
 	help
 	  This enables support for common clock driver API on Allwinner
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 803a2f711d..28bda1f497 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -10,6 +10,7 @@
 #include <errno.h>
 #include <asm/arch/ccu.h>
 #include <dt-bindings/clock/sun50i-a64-ccu.h>
+#include <dt-bindings/reset/sun50i-a64-ccu.h>
 
 static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
@@ -26,10 +27,28 @@ static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(17)),
 };
 
+static const struct ccu_reset a64_resets[] = {
+	[RST_USB_PHY0]          = RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]          = RESET(0x0cc, BIT(1)),
+	[RST_USB_HSIC]          = RESET(0x0cc, BIT(2)),
+
+	[RST_BUS_OTG]           = RESET(0x2c0, BIT(23)),
+	[RST_BUS_EHCI0]         = RESET(0x2c0, BIT(24)),
+	[RST_BUS_EHCI1]         = RESET(0x2c0, BIT(25)),
+	[RST_BUS_OHCI0]         = RESET(0x2c0, BIT(28)),
+	[RST_BUS_OHCI1]         = RESET(0x2c0, BIT(29)),
+};
+
 static const struct ccu_desc a64_ccu_desc = {
 	.gates = a64_gates,
+	.resets = a64_resets,
 };
 
+static int a64_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 50);
+}
+
 static const struct udevice_id a64_ccu_ids[] = {
 	{ .compatible = "allwinner,sun50i-a64-ccu",
 	  .data = (ulong)&a64_ccu_desc },
@@ -43,4 +62,5 @@ U_BOOT_DRIVER(clk_sun50i_a64) = {
 	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
 	.ops		= &sunxi_clk_ops,
 	.probe		= sunxi_clk_probe,
+	.bind		= a64_clk_bind,
 };
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 9c5208b7da..b6b40b6ce9 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -106,4 +106,12 @@ config RESET_SOCFPGA
 	help
 	  Support for reset controller on SoCFPGA platform.
 
+config RESET_SUNXI
+	bool "RESET support for Allwinner SoCs"
+	depends on DM_RESET && ARCH_SUNXI
+	default y
+	help
+	  This enables support for common reset driver for
+	  Allwinner SoCs.
+
 endmenu
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index f4520878b7..377c038163 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
 obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o
 obj-$(CONFIG_RESET_MESON) += reset-meson.o
 obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
new file mode 100644
index 0000000000..af63cac64e
--- /dev/null
+++ b/drivers/reset/reset-sunxi.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <reset-uclass.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <linux/log2.h>
+#include <asm/arch/ccu.h>
+
+struct sunxi_reset_priv {
+	void *base;
+	ulong count;
+	const struct ccu_desc *desc;
+};
+
+static const struct ccu_reset *priv_to_reset(struct sunxi_reset_priv *priv,
+					     unsigned long id)
+{
+	return	&priv->desc->resets[id];
+}
+
+static int sunxi_reset_request(struct reset_ctl *reset_ctl)
+{
+	struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+
+	debug("%s: (RST#%ld)\n", __func__, reset_ctl->id);
+
+	/* check dt-bindings/reset/sun8i-h3-ccu.h for max id */
+	if (reset_ctl->id >= priv->count)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int sunxi_reset_free(struct reset_ctl *reset_ctl)
+{
+	debug("%s: (RST#%ld)\n", __func__, reset_ctl->id);
+
+	return 0;
+}
+
+static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on)
+{
+	struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev);
+	const struct ccu_reset *reset = priv_to_reset(priv, reset_ctl->id);
+	u32 reg;
+
+	if (!(reset->flags & CCU_CLK_F_INIT_DONE)) {
+		printf("%s: (RST#%ld) unhandled\n", __func__, reset_ctl->id);
+		return 0;
+	}
+
+	debug("%s: (RST#%ld) off#0x%x, BIT(%d)\n", __func__,
+	      reset_ctl->id, reset->off, ilog2(reset->bit));
+
+	reg = readl(priv->base + reset->off);
+	if (on)
+		reg |= reset->bit;
+	else
+		reg &= ~reset->bit;
+
+	writel(reg, priv->base + reset->off);
+
+	return 0;
+}
+
+static int sunxi_reset_assert(struct reset_ctl *reset_ctl)
+{
+	return sunxi_set_reset(reset_ctl, false);
+}
+
+static int sunxi_reset_deassert(struct reset_ctl *reset_ctl)
+{
+	return sunxi_set_reset(reset_ctl, true);
+}
+
+struct reset_ops sunxi_reset_ops = {
+	.request = sunxi_reset_request,
+	.free = sunxi_reset_free,
+	.rst_assert = sunxi_reset_assert,
+	.rst_deassert = sunxi_reset_deassert,
+};
+
+static int sunxi_reset_probe(struct udevice *dev)
+{
+	struct sunxi_reset_priv *priv = dev_get_priv(dev);
+
+	priv->base = dev_read_addr_ptr(dev);
+
+	return 0;
+}
+
+int sunxi_reset_bind(struct udevice *dev, ulong count)
+{
+	struct udevice *rst_dev;
+	struct sunxi_reset_priv *priv;
+	int ret;
+
+	ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset",
+					 dev_ofnode(dev), &rst_dev);
+	if (ret) {
+		debug("failed to bind sunxi_reset driver (ret=%d)\n", ret);
+		return ret;
+	}
+	priv = malloc(sizeof(struct sunxi_reset_priv));
+	priv->count = count;
+	priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
+	rst_dev->priv = priv;
+
+	return 0;
+}
+
+U_BOOT_DRIVER(sunxi_reset) = {
+	.name		= "sunxi_reset",
+	.id		= UCLASS_RESET,
+	.ops		= &sunxi_reset_ops,
+	.probe		= sunxi_reset_probe,
+	.priv_auto_alloc_size = sizeof(struct sunxi_reset_priv),
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 03/26] clk: sunxi: Add Allwinner H3/H5 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 01/26] clk: Add Allwinner A64 CLK driver Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 02/26] reset: Add Allwinner RESET driver Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 04/26] clk: sunxi: Add Allwinner A10/A20 " Jagan Teki
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner H3/H5.

- Implement USB bus and USB clocks via ccu_clk_gate table for
  H3/H5, so it can accessed in common clk enable and disable
  functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table for
  H3/H5, so it can accessed in common reset deassert and assert
  functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig  |  7 ++++
 drivers/clk/sunxi/Makefile |  1 +
 drivers/clk/sunxi/clk_h3.c | 79 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_h3.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index 041d711e58..c3713bbac2 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -9,6 +9,13 @@ config CLK_SUNXI
 
 if CLK_SUNXI
 
+config CLK_SUN8I_H3
+	bool "Clock driver for Allwinner H3/H5"
+	default MACH_SUNXI_H3_H5
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner H3/H5 SoC.
+
 config CLK_SUN50I_A64
 	bool "Clock driver for Allwinner A64"
 	default MACH_SUN50I
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index fb20d28333..dec49f27a1 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -6,4 +6,5 @@
 
 obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
 
+obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
new file mode 100644
index 0000000000..283fc31b01
--- /dev/null
+++ b/drivers/clk/sunxi/clk_h3.c
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun8i-h3-ccu.h>
+#include <dt-bindings/reset/sun8i-h3-ccu.h>
+
+static struct ccu_clk_gate h3_gates[] = {
+	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
+	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
+	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(25)),
+	[CLK_BUS_EHCI2]		= GATE(0x060, BIT(26)),
+	[CLK_BUS_EHCI3]		= GATE(0x060, BIT(27)),
+	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(28)),
+	[CLK_BUS_OHCI1]		= GATE(0x060, BIT(29)),
+	[CLK_BUS_OHCI2]		= GATE(0x060, BIT(30)),
+	[CLK_BUS_OHCI3]		= GATE(0x060, BIT(31)),
+
+	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
+	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
+	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
+	[CLK_USB_PHY3]		= GATE(0x0cc, BIT(11)),
+	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(16)),
+	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(17)),
+	[CLK_USB_OHCI2]		= GATE(0x0cc, BIT(18)),
+	[CLK_USB_OHCI3]		= GATE(0x0cc, BIT(19)),
+};
+
+static struct ccu_reset h3_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]		= RESET(0x0cc, BIT(1)),
+	[RST_USB_PHY2]		= RESET(0x0cc, BIT(2)),
+	[RST_USB_PHY3]		= RESET(0x0cc, BIT(3)),
+
+	[RST_BUS_OTG]		= RESET(0x2c0, BIT(23)),
+	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(24)),
+	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(25)),
+	[RST_BUS_EHCI2]		= RESET(0x2c0, BIT(26)),
+	[RST_BUS_EHCI3]		= RESET(0x2c0, BIT(27)),
+	[RST_BUS_OHCI0]		= RESET(0x2c0, BIT(28)),
+	[RST_BUS_OHCI1]		= RESET(0x2c0, BIT(29)),
+	[RST_BUS_OHCI2]		= RESET(0x2c0, BIT(30)),
+	[RST_BUS_OHCI3]		= RESET(0x2c0, BIT(31)),
+};
+
+static const struct ccu_desc h3_ccu_desc = {
+	.gates = h3_gates,
+	.resets = h3_resets,
+};
+
+static int h3_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 53);
+}
+
+static const struct udevice_id h3_ccu_ids[] = {
+	{ .compatible = "allwinner,sun8i-h3-ccu",
+	  .data = (ulong)&h3_ccu_desc },
+	{ .compatible = "allwinner,sun50i-h5-ccu",
+	  .data = (ulong)&h3_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun8i_h3) = {
+	.name		= "sun8i_h3_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= h3_ccu_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= h3_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 04/26] clk: sunxi: Add Allwinner A10/A20 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (2 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 03/26] clk: sunxi: Add Allwinner H3/H5 CLK driver Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 05/26] clk: sunxi: Add Allwinner A10s/A13 " Jagan Teki
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner A10/A20.

- Implement USB ahb and USB clocks via ccu_clk_gate table
  for A10/A20, so it can accessed in common clk enable and
  disable functions from clk_sunxi.c
- Implement USB resets via ccu_reset table for A10/A20,
  so it can accessed in common reset deassert and assert
  functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig   |  7 +++++
 drivers/clk/sunxi/Makefile  |  1 +
 drivers/clk/sunxi/clk_a10.c | 59 +++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_a10.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index c3713bbac2..fbbf94ef55 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -9,6 +9,13 @@ config CLK_SUNXI
 
 if CLK_SUNXI
 
+config CLK_SUN4I_A10
+	bool "Clock driver for Allwinner A10/A20"
+	default MACH_SUN4I || MACH_SUN7I
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner A10/A20 SoC.
+
 config CLK_SUN8I_H3
 	bool "Clock driver for Allwinner H3/H5"
 	default MACH_SUNXI_H3_H5
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index dec49f27a1..bba830922f 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -6,5 +6,6 @@
 
 obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
 
+obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
new file mode 100644
index 0000000000..59d9d90a19
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a10.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun4i-a10-ccu.h>
+#include <dt-bindings/reset/sun4i-a10-ccu.h>
+
+static struct ccu_clk_gate a10_gates[] = {
+	[CLK_AHB_OTG]		= GATE(0x060, BIT(0)),
+	[CLK_AHB_EHCI0]		= GATE(0x060, BIT(1)),
+	[CLK_AHB_OHCI0]		= GATE(0x060, BIT(2)),
+	[CLK_AHB_EHCI1]		= GATE(0x060, BIT(3)),
+	[CLK_AHB_OHCI1]		= GATE(0x060, BIT(4)),
+
+	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(6)),
+	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(7)),
+	[CLK_USB_PHY]		= GATE(0x0cc, BIT(8)),
+};
+
+static struct ccu_reset a10_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]		= RESET(0x0cc, BIT(1)),
+	[RST_USB_PHY2]		= RESET(0x0cc, BIT(2)),
+};
+
+static const struct ccu_desc a10_ccu_desc = {
+	.gates = a10_gates,
+	.resets = a10_resets,
+};
+
+static int a10_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 22);
+}
+
+static const struct udevice_id a10_ccu_ids[] = {
+	{ .compatible = "allwinner,sun4i-a10-ccu",
+	  .data = (ulong)&a10_ccu_desc },
+	{ .compatible = "allwinner,sun7i-a20-ccu",
+	  .data = (ulong)&a10_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun4i_a10) = {
+	.name		= "sun4i_a10_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= a10_ccu_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= a10_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 05/26] clk: sunxi: Add Allwinner A10s/A13 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (3 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 04/26] clk: sunxi: Add Allwinner A10/A20 " Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 06/26] clk: sunxi: Add Allwinner A31 " Jagan Teki
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner A10s/A13.

- Implement USB ahb and USB clocks via ccu_clk_gate table
  for A10s/A13, so it can accessed in common clk enable and
  disable functions from clk_sunxi.c
- Implement USB resets via ccu_reset table for A10s/A13,
  so it can accessed in common reset deassert and assert
  functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig    |  7 +++++
 drivers/clk/sunxi/Makefile   |  1 +
 drivers/clk/sunxi/clk_a10s.c | 56 ++++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_a10s.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index fbbf94ef55..b228c2fa3a 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -16,6 +16,13 @@ config CLK_SUN4I_A10
 	  This enables common clock driver support for platforms based
 	  on Allwinner A10/A20 SoC.
 
+config CLK_SUN5I_A10S
+	bool "Clock driver for Allwinner A10s/A13"
+	default MACH_SUN5I
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner A10s/A13 SoC.
+
 config CLK_SUN8I_H3
 	bool "Clock driver for Allwinner H3/H5"
 	default MACH_SUNXI_H3_H5
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index bba830922f..466d4b79d6 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -7,5 +7,6 @@
 obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
 
 obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o
+obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
new file mode 100644
index 0000000000..474f37d607
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a10s.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun5i-ccu.h>
+#include <dt-bindings/reset/sun5i-ccu.h>
+
+static struct ccu_clk_gate a10s_gates[] = {
+	[CLK_AHB_OTG]		= GATE(0x060, BIT(0)),
+	[CLK_AHB_EHCI]		= GATE(0x060, BIT(1)),
+	[CLK_AHB_OHCI]		= GATE(0x060, BIT(2)),
+
+	[CLK_USB_OHCI]		= GATE(0x0cc, BIT(6)),
+	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
+	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
+};
+
+static struct ccu_reset a10s_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]		= RESET(0x0cc, BIT(1)),
+};
+
+static const struct ccu_desc a10s_ccu_desc = {
+	.gates = a10s_gates,
+	.resets = a10s_resets,
+};
+
+static int a10s_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 10);
+}
+
+static const struct udevice_id a10s_ccu_ids[] = {
+	{ .compatible = "allwinner,sun5i-a10s-ccu",
+	  .data = (ulong)&a10s_ccu_desc },
+	{ .compatible = "allwinner,sun5i-a13-ccu",
+	  .data = (ulong)&a10s_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun5i_a10s) = {
+	.name		= "sun5i_a10s_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= a10s_ccu_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= a10s_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 06/26] clk: sunxi: Add Allwinner A31 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (4 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 05/26] clk: sunxi: Add Allwinner A10s/A13 " Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 07/26] clk: sunxi: Add Allwinner A23/A33 " Jagan Teki
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner A31.

- Implement USB ahb1 and USB clocks via ccu_clk_gate table
  for A31, so it can accessed in common clk enable and disable
  functions from clk_sunxi.c
- Implement USB ahb1 and USB resets via ccu_reset table
  for A31, so it can accessed in common reset deassert
  and assert functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig   |  7 ++++
 drivers/clk/sunxi/Makefile  |  1 +
 drivers/clk/sunxi/clk_a31.c | 68 +++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_a31.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index b228c2fa3a..535b0dc02c 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -23,6 +23,13 @@ config CLK_SUN5I_A10S
 	  This enables common clock driver support for platforms based
 	  on Allwinner A10s/A13 SoC.
 
+config CLK_SUN6I_A31
+	bool "Clock driver for Allwinner A31/A31s"
+	default MACH_SUN6I
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner A31/A31s SoC.
+
 config CLK_SUN8I_H3
 	bool "Clock driver for Allwinner H3/H5"
 	default MACH_SUNXI_H3_H5
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 466d4b79d6..3cf0071b0c 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -8,5 +8,6 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
 
 obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o
 obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o
+obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c
new file mode 100644
index 0000000000..03dd9ae913
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a31.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun6i-a31-ccu.h>
+#include <dt-bindings/reset/sun6i-a31-ccu.h>
+
+static struct ccu_clk_gate a31_gates[] = {
+	[CLK_AHB1_OTG]		= GATE(0x060, BIT(24)),
+	[CLK_AHB1_EHCI0]	= GATE(0x060, BIT(26)),
+	[CLK_AHB1_EHCI1]	= GATE(0x060, BIT(27)),
+	[CLK_AHB1_OHCI0]	= GATE(0x060, BIT(29)),
+	[CLK_AHB1_OHCI1]	= GATE(0x060, BIT(30)),
+	[CLK_AHB1_OHCI2]	= GATE(0x060, BIT(31)),
+
+	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
+	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
+	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
+	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(16)),
+	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(17)),
+	[CLK_USB_OHCI2]		= GATE(0x0cc, BIT(18)),
+};
+
+static struct ccu_reset a31_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]		= RESET(0x0cc, BIT(1)),
+	[RST_USB_PHY2]		= RESET(0x0cc, BIT(2)),
+
+	[RST_AHB1_OTG]		= RESET(0x2c0, BIT(24)),
+	[RST_AHB1_EHCI0]	= RESET(0x2c0, BIT(26)),
+	[RST_AHB1_EHCI1]	= RESET(0x2c0, BIT(27)),
+	[RST_AHB1_OHCI0]	= RESET(0x2c0, BIT(29)),
+	[RST_AHB1_OHCI1]	= RESET(0x2c0, BIT(30)),
+	[RST_AHB1_OHCI2]	= RESET(0x2c0, BIT(31)),
+};
+
+static const struct ccu_desc a31_ccu_desc = {
+	.gates = a31_gates,
+	.resets = a31_resets,
+};
+
+static int a31_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 56);
+}
+
+static const struct udevice_id a31_clk_ids[] = {
+	{ .compatible = "allwinner,sun6i-a31-ccu",
+	  .data = (ulong)&a31_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun6i_a31) = {
+	.name		= "sun6i_a31_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= a31_clk_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= a31_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 07/26] clk: sunxi: Add Allwinner A23/A33 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (5 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 06/26] clk: sunxi: Add Allwinner A31 " Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 08/26] clk: sunxi: Add Allwinner A83T " Jagan Teki
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner A23/A33.

- Implement USB bus and USB clocks via ccu_clk_gate table
  for A23/A33, so it can accessed in common clk enable and
  disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table
  for A23/A33, so it can accessed in common reset deassert
  and assert functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig   |  7 +++++
 drivers/clk/sunxi/Makefile  |  1 +
 drivers/clk/sunxi/clk_a23.c | 63 +++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_a23.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index 535b0dc02c..38ff99d345 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -30,6 +30,13 @@ config CLK_SUN6I_A31
 	  This enables common clock driver support for platforms based
 	  on Allwinner A31/A31s SoC.
 
+config CLK_SUN8I_A23
+	bool "Clock driver for Allwinner A23/A33"
+	default MACH_SUN8I_A23 || MACH_SUN8I_A33
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner A23/A33 SoC.
+
 config CLK_SUN8I_H3
 	bool "Clock driver for Allwinner H3/H5"
 	default MACH_SUNXI_H3_H5
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 3cf0071b0c..6924897036 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -9,5 +9,6 @@ obj-$(CONFIG_CLK_SUNXI) += clk_sunxi.o
 obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o
 obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o
 obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o
+obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c
new file mode 100644
index 0000000000..0fc8a5821c
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a23.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun8i-a23-a33-ccu.h>
+#include <dt-bindings/reset/sun8i-a23-a33-ccu.h>
+
+static struct ccu_clk_gate a23_gates[] = {
+	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
+	[CLK_BUS_EHCI]		= GATE(0x060, BIT(26)),
+	[CLK_BUS_OHCI]		= GATE(0x060, BIT(29)),
+
+	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
+	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
+	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
+	[CLK_USB_HSIC_12M]	= GATE(0x0cc, BIT(11)),
+	[CLK_USB_OHCI]		= GATE(0x0cc, BIT(16)),
+};
+
+static struct ccu_reset a23_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]		= RESET(0x0cc, BIT(1)),
+	[RST_USB_HSIC]		= RESET(0x0cc, BIT(2)),
+
+	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
+	[RST_BUS_EHCI]		= RESET(0x2c0, BIT(26)),
+	[RST_BUS_OHCI]		= RESET(0x2c0, BIT(29)),
+};
+
+static const struct ccu_desc a23_ccu_desc = {
+	.gates = a23_gates,
+	.resets = a23_resets,
+};
+
+static int a23_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 39);
+}
+
+static const struct udevice_id a23_clk_ids[] = {
+	{ .compatible = "allwinner,sun8i-a23-ccu",
+	  .data = (ulong)&a23_ccu_desc },
+	{ .compatible = "allwinner,sun8i-a33-ccu",
+	  .data = (ulong)&a23_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun8i_a23) = {
+	.name		= "sun8i_a23_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= a23_clk_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= a23_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 08/26] clk: sunxi: Add Allwinner A83T CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (6 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 07/26] clk: sunxi: Add Allwinner A23/A33 " Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 09/26] clk: sunxi: Add Allwinner R40 " Jagan Teki
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner A83T.

- Implement USB bus and USB clocks via ccu_clk_gate table
  for A83T, so it can accessed in common clk enable and
  disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table
  for A83T, so it can accessed in common reset deassert
  and assert functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig    |  7 ++++
 drivers/clk/sunxi/Makefile   |  1 +
 drivers/clk/sunxi/clk_a83t.c | 63 ++++++++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_a83t.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index 38ff99d345..90af70d171 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -37,6 +37,13 @@ config CLK_SUN8I_A23
 	  This enables common clock driver support for platforms based
 	  on Allwinner A23/A33 SoC.
 
+config CLK_SUN8I_A83T
+	bool "Clock driver for Allwinner A83T"
+	default MACH_SUN8I_A83T
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner A83T SoC.
+
 config CLK_SUN8I_H3
 	bool "Clock driver for Allwinner H3/H5"
 	default MACH_SUNXI_H3_H5
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 6924897036..4a254c8671 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -10,5 +10,6 @@ obj-$(CONFIG_CLK_SUN4I_A10) += clk_a10.o
 obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o
 obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o
 obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o
+obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
new file mode 100644
index 0000000000..45faef2f11
--- /dev/null
+++ b/drivers/clk/sunxi/clk_a83t.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun8i-a83t-ccu.h>
+#include <dt-bindings/reset/sun8i-a83t-ccu.h>
+
+static struct ccu_clk_gate a83t_gates[] = {
+	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
+	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(26)),
+	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
+	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(29)),
+
+	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
+	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
+	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
+	[CLK_USB_HSIC_12M]	= GATE(0x0cc, BIT(11)),
+	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(16)),
+};
+
+static struct ccu_reset a83t_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]		= RESET(0x0cc, BIT(1)),
+	[RST_USB_HSIC]		= RESET(0x0cc, BIT(2)),
+
+	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
+	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(26)),
+	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
+	[RST_BUS_OHCI0]		= RESET(0x2c0, BIT(29)),
+};
+
+static const struct ccu_desc a83t_ccu_desc = {
+	.gates = a83t_gates,
+	.resets = a83t_resets,
+};
+
+static int a83t_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 44);
+}
+
+static const struct udevice_id a83t_clk_ids[] = {
+	{ .compatible = "allwinner,sun8i-a83t-ccu",
+	  .data = (ulong)&a83t_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun8i_a83t) = {
+	.name		= "sun8i_a83t_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= a83t_clk_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= a83t_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 09/26] clk: sunxi: Add Allwinner R40 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (7 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 08/26] clk: sunxi: Add Allwinner A83T " Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 10/26] clk: sunxi: Add Allwinner V3S " Jagan Teki
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner R40.

- Implement USB bus and USB clocks via ccu_clk_gate
  for R40, so it can accessed in common clk enable
  and disable functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table
  for R40, so it can accessed in common reset deassert
  and assert functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig   |  7 ++++
 drivers/clk/sunxi/Makefile  |  1 +
 drivers/clk/sunxi/clk_r40.c | 70 +++++++++++++++++++++++++++++++++++++
 3 files changed, 78 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_r40.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index 90af70d171..c45a4ba378 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -44,6 +44,13 @@ config CLK_SUN8I_A83T
 	  This enables common clock driver support for platforms based
 	  on Allwinner A83T SoC.
 
+config CLK_SUN8I_R40
+	bool "Clock driver for Allwinner R40"
+	default MACH_SUN8I_R40
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner R40 SoC.
+
 config CLK_SUN8I_H3
 	bool "Clock driver for Allwinner H3/H5"
 	default MACH_SUNXI_H3_H5
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 4a254c8671..61f8b87396 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -11,5 +11,6 @@ obj-$(CONFIG_CLK_SUN5I_A10S) += clk_a10s.o
 obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o
 obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o
 obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o
+obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
new file mode 100644
index 0000000000..2a6000f4dc
--- /dev/null
+++ b/drivers/clk/sunxi/clk_r40.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun8i-r40-ccu.h>
+#include <dt-bindings/reset/sun8i-r40-ccu.h>
+
+static struct ccu_clk_gate r40_gates[] = {
+	[CLK_BUS_OTG]		= GATE(0x060, BIT(25)),
+	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(26)),
+	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
+	[CLK_BUS_EHCI2]		= GATE(0x060, BIT(28)),
+	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(29)),
+	[CLK_BUS_OHCI1]		= GATE(0x060, BIT(30)),
+	[CLK_BUS_OHCI2]		= GATE(0x060, BIT(31)),
+
+	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
+	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
+	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
+	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(16)),
+	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(17)),
+	[CLK_USB_OHCI2]		= GATE(0x0cc, BIT(18)),
+};
+
+static struct ccu_reset r40_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+	[RST_USB_PHY1]		= RESET(0x0cc, BIT(1)),
+	[RST_USB_PHY2]		= RESET(0x0cc, BIT(2)),
+
+	[RST_BUS_OTG]		= RESET(0x2c0, BIT(25)),
+	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(26)),
+	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
+	[RST_BUS_EHCI2]		= RESET(0x2c0, BIT(28)),
+	[RST_BUS_OHCI0]		= RESET(0x2c0, BIT(29)),
+	[RST_BUS_OHCI1]		= RESET(0x2c0, BIT(30)),
+	[RST_BUS_OHCI2]		= RESET(0x2c0, BIT(31)),
+};
+
+static const struct ccu_desc r40_ccu_desc = {
+	.gates = r40_gates,
+	.resets = r40_resets,
+};
+
+static int r40_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 80);
+}
+
+static const struct udevice_id r40_clk_ids[] = {
+	{ .compatible = "allwinner,sun8i-r40-ccu",
+	  .data = (ulong)&r40_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun8i_r40) = {
+	.name		= "sun8i_r40_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= r40_clk_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= r40_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 10/26] clk: sunxi: Add Allwinner V3S CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (8 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 09/26] clk: sunxi: Add Allwinner R40 " Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 11/26] clk: sunxi: Implement UART clocks Jagan Teki
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner V3S.

- Implement USB bus and USB clocks via ccu_clk_gate table
  for V3S, so it can accessed in common clk enable and disable
  functions from clk_sunxi.c
- Implement USB bus and USB resets via ccu_reset table
  for V3S, so it can accessed in common reset deassert
  and assert functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/clk/sunxi/Kconfig   |  7 +++++
 drivers/clk/sunxi/Makefile  |  1 +
 drivers/clk/sunxi/clk_v3s.c | 51 +++++++++++++++++++++++++++++++++++++
 3 files changed, 59 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_v3s.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index c45a4ba378..a6f84e9e56 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -51,6 +51,13 @@ config CLK_SUN8I_R40
 	  This enables common clock driver support for platforms based
 	  on Allwinner R40 SoC.
 
+config CLK_SUN8I_V3S
+	bool "Clock driver for Allwinner V3S"
+	default MACH_SUN8I_V3S
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner V3S SoC.
+
 config CLK_SUN8I_H3
 	bool "Clock driver for Allwinner H3/H5"
 	default MACH_SUNXI_H3_H5
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index 61f8b87396..fbd43527a6 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -12,5 +12,6 @@ obj-$(CONFIG_CLK_SUN6I_A31) += clk_a31.o
 obj-$(CONFIG_CLK_SUN8I_A23) += clk_a23.o
 obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o
 obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
+obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c
new file mode 100644
index 0000000000..0eeea84c1a
--- /dev/null
+++ b/drivers/clk/sunxi/clk_v3s.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun8i-v3s-ccu.h>
+#include <dt-bindings/reset/sun8i-v3s-ccu.h>
+
+static struct ccu_clk_gate v3s_gates[] = {
+	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
+
+	[CLK_USB_PHY0]          = GATE(0x0cc, BIT(8)),
+};
+
+static struct ccu_reset v3s_resets[] = {
+	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
+
+	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
+};
+
+static const struct ccu_desc v3s_ccu_desc = {
+	.gates = v3s_gates,
+	.resets = v3s_resets,
+};
+
+static int v3s_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 53);
+}
+
+static const struct udevice_id v3s_clk_ids[] = {
+	{ .compatible = "allwinner,sun8i-v3s-ccu",
+	  .data = (ulong)&v3s_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun8i_v3s) = {
+	.name		= "sun8i_v3s_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= v3s_clk_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= v3s_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 11/26] clk: sunxi: Implement UART clocks
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (9 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 10/26] clk: sunxi: Add Allwinner V3S " Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 12/26] clk: sunxi: Implement UART resets Jagan Teki
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Implement UART clocks for all Allwinner SoC
clock drivers via ccu clock gate table.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/clk/sunxi/clk_a10.c  | 9 +++++++++
 drivers/clk/sunxi/clk_a10s.c | 5 +++++
 drivers/clk/sunxi/clk_a23.c  | 6 ++++++
 drivers/clk/sunxi/clk_a31.c  | 7 +++++++
 drivers/clk/sunxi/clk_a64.c  | 6 ++++++
 drivers/clk/sunxi/clk_a83t.c | 6 ++++++
 drivers/clk/sunxi/clk_h3.c   | 5 +++++
 drivers/clk/sunxi/clk_r40.c  | 9 +++++++++
 drivers/clk/sunxi/clk_v3s.c  | 4 ++++
 9 files changed, 57 insertions(+)

diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
index 59d9d90a19..1b074e3872 100644
--- a/drivers/clk/sunxi/clk_a10.c
+++ b/drivers/clk/sunxi/clk_a10.c
@@ -19,6 +19,15 @@ static struct ccu_clk_gate a10_gates[] = {
 	[CLK_AHB_EHCI1]		= GATE(0x060, BIT(3)),
 	[CLK_AHB_OHCI1]		= GATE(0x060, BIT(4)),
 
+	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
+	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
+	[CLK_APB1_UART2]	= GATE(0x06c, BIT(18)),
+	[CLK_APB1_UART3]	= GATE(0x06c, BIT(19)),
+	[CLK_APB1_UART4]	= GATE(0x06c, BIT(20)),
+	[CLK_APB1_UART5]	= GATE(0x06c, BIT(21)),
+	[CLK_APB1_UART6]	= GATE(0x06c, BIT(22)),
+	[CLK_APB1_UART7]	= GATE(0x06c, BIT(23)),
+
 	[CLK_USB_OHCI0]		= GATE(0x0cc, BIT(6)),
 	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(7)),
 	[CLK_USB_PHY]		= GATE(0x0cc, BIT(8)),
diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
index 474f37d607..a50c6e3f7f 100644
--- a/drivers/clk/sunxi/clk_a10s.c
+++ b/drivers/clk/sunxi/clk_a10s.c
@@ -17,6 +17,11 @@ static struct ccu_clk_gate a10s_gates[] = {
 	[CLK_AHB_EHCI]		= GATE(0x060, BIT(1)),
 	[CLK_AHB_OHCI]		= GATE(0x060, BIT(2)),
 
+	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
+	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
+	[CLK_APB1_UART2]	= GATE(0x06c, BIT(18)),
+	[CLK_APB1_UART3]	= GATE(0x06c, BIT(19)),
+
 	[CLK_USB_OHCI]		= GATE(0x0cc, BIT(6)),
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c
index 0fc8a5821c..63004b881d 100644
--- a/drivers/clk/sunxi/clk_a23.c
+++ b/drivers/clk/sunxi/clk_a23.c
@@ -17,6 +17,12 @@ static struct ccu_clk_gate a23_gates[] = {
 	[CLK_BUS_EHCI]		= GATE(0x060, BIT(26)),
 	[CLK_BUS_OHCI]		= GATE(0x060, BIT(29)),
 
+	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
+	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
+	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
+	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
+	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c
index 03dd9ae913..c01d2a3549 100644
--- a/drivers/clk/sunxi/clk_a31.c
+++ b/drivers/clk/sunxi/clk_a31.c
@@ -20,6 +20,13 @@ static struct ccu_clk_gate a31_gates[] = {
 	[CLK_AHB1_OHCI1]	= GATE(0x060, BIT(30)),
 	[CLK_AHB1_OHCI2]	= GATE(0x060, BIT(31)),
 
+	[CLK_APB2_UART0]	= GATE(0x06c, BIT(16)),
+	[CLK_APB2_UART1]	= GATE(0x06c, BIT(17)),
+	[CLK_APB2_UART2]	= GATE(0x06c, BIT(18)),
+	[CLK_APB2_UART3]	= GATE(0x06c, BIT(19)),
+	[CLK_APB2_UART4]	= GATE(0x06c, BIT(20)),
+	[CLK_APB2_UART5]	= GATE(0x06c, BIT(21)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 28bda1f497..b427e3adda 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -19,6 +19,12 @@ static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(28)),
 	[CLK_BUS_OHCI1]		= GATE(0x060, BIT(29)),
 
+	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
+	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
+	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
+	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
+	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
index 45faef2f11..fbffa3bf5f 100644
--- a/drivers/clk/sunxi/clk_a83t.c
+++ b/drivers/clk/sunxi/clk_a83t.c
@@ -18,6 +18,12 @@ static struct ccu_clk_gate a83t_gates[] = {
 	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(27)),
 	[CLK_BUS_OHCI0]		= GATE(0x060, BIT(29)),
 
+	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
+	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
+	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
+	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
+	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
index 283fc31b01..f706e77dee 100644
--- a/drivers/clk/sunxi/clk_h3.c
+++ b/drivers/clk/sunxi/clk_h3.c
@@ -23,6 +23,11 @@ static struct ccu_clk_gate h3_gates[] = {
 	[CLK_BUS_OHCI2]		= GATE(0x060, BIT(30)),
 	[CLK_BUS_OHCI3]		= GATE(0x060, BIT(31)),
 
+	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
+	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
+	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
+	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
index 2a6000f4dc..3405b39c46 100644
--- a/drivers/clk/sunxi/clk_r40.c
+++ b/drivers/clk/sunxi/clk_r40.c
@@ -21,6 +21,15 @@ static struct ccu_clk_gate r40_gates[] = {
 	[CLK_BUS_OHCI1]		= GATE(0x060, BIT(30)),
 	[CLK_BUS_OHCI2]		= GATE(0x060, BIT(31)),
 
+	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
+	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
+	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
+	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
+	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
+	[CLK_BUS_UART5]		= GATE(0x06c, BIT(21)),
+	[CLK_BUS_UART6]		= GATE(0x06c, BIT(22)),
+	[CLK_BUS_UART7]		= GATE(0x06c, BIT(23)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_PHY2]		= GATE(0x0cc, BIT(10)),
diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c
index 0eeea84c1a..a662bc3e93 100644
--- a/drivers/clk/sunxi/clk_v3s.c
+++ b/drivers/clk/sunxi/clk_v3s.c
@@ -15,6 +15,10 @@
 static struct ccu_clk_gate v3s_gates[] = {
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(24)),
 
+	[CLK_BUS_UART0]		= GATE(0x06c, BIT(16)),
+	[CLK_BUS_UART1]		= GATE(0x06c, BIT(17)),
+	[CLK_BUS_UART2]		= GATE(0x06c, BIT(18)),
+
 	[CLK_USB_PHY0]          = GATE(0x0cc, BIT(8)),
 };
 
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 12/26] clk: sunxi: Implement UART resets
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (10 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 11/26] clk: sunxi: Implement UART clocks Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 13/26] clk: sunxi: Add Allwinner H6 CLK driver Jagan Teki
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Implement UART resets for all relevant Allwinner SoC
clock drivers via ccu reset table.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/clk/sunxi/clk_a23.c  | 6 ++++++
 drivers/clk/sunxi/clk_a31.c  | 7 +++++++
 drivers/clk/sunxi/clk_a64.c  | 6 ++++++
 drivers/clk/sunxi/clk_a83t.c | 6 ++++++
 drivers/clk/sunxi/clk_h3.c   | 5 +++++
 drivers/clk/sunxi/clk_r40.c  | 9 +++++++++
 drivers/clk/sunxi/clk_v3s.c  | 4 ++++
 7 files changed, 43 insertions(+)

diff --git a/drivers/clk/sunxi/clk_a23.c b/drivers/clk/sunxi/clk_a23.c
index 63004b881d..4661a33191 100644
--- a/drivers/clk/sunxi/clk_a23.c
+++ b/drivers/clk/sunxi/clk_a23.c
@@ -38,6 +38,12 @@ static struct ccu_reset a23_resets[] = {
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
 	[RST_BUS_EHCI]		= RESET(0x2c0, BIT(26)),
 	[RST_BUS_OHCI]		= RESET(0x2c0, BIT(29)),
+
+	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x2d8, BIT(19)),
+	[RST_BUS_UART4]		= RESET(0x2d8, BIT(20)),
 };
 
 static const struct ccu_desc a23_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_a31.c b/drivers/clk/sunxi/clk_a31.c
index c01d2a3549..b05bea5b82 100644
--- a/drivers/clk/sunxi/clk_a31.c
+++ b/drivers/clk/sunxi/clk_a31.c
@@ -46,6 +46,13 @@ static struct ccu_reset a31_resets[] = {
 	[RST_AHB1_OHCI0]	= RESET(0x2c0, BIT(29)),
 	[RST_AHB1_OHCI1]	= RESET(0x2c0, BIT(30)),
 	[RST_AHB1_OHCI2]	= RESET(0x2c0, BIT(31)),
+
+	[RST_APB2_UART0]	= RESET(0x2d8, BIT(16)),
+	[RST_APB2_UART1]	= RESET(0x2d8, BIT(17)),
+	[RST_APB2_UART2]	= RESET(0x2d8, BIT(18)),
+	[RST_APB2_UART3]	= RESET(0x2d8, BIT(19)),
+	[RST_APB2_UART4]	= RESET(0x2d8, BIT(20)),
+	[RST_APB2_UART5]	= RESET(0x2d8, BIT(21)),
 };
 
 static const struct ccu_desc a31_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index b427e3adda..162ec769d6 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -43,6 +43,12 @@ static const struct ccu_reset a64_resets[] = {
 	[RST_BUS_EHCI1]         = RESET(0x2c0, BIT(25)),
 	[RST_BUS_OHCI0]         = RESET(0x2c0, BIT(28)),
 	[RST_BUS_OHCI1]         = RESET(0x2c0, BIT(29)),
+
+	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x2d8, BIT(19)),
+	[RST_BUS_UART4]		= RESET(0x2d8, BIT(20)),
 };
 
 static const struct ccu_desc a64_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_a83t.c b/drivers/clk/sunxi/clk_a83t.c
index fbffa3bf5f..3fe96ccd84 100644
--- a/drivers/clk/sunxi/clk_a83t.c
+++ b/drivers/clk/sunxi/clk_a83t.c
@@ -40,6 +40,12 @@ static struct ccu_reset a83t_resets[] = {
 	[RST_BUS_EHCI0]		= RESET(0x2c0, BIT(26)),
 	[RST_BUS_EHCI1]		= RESET(0x2c0, BIT(27)),
 	[RST_BUS_OHCI0]		= RESET(0x2c0, BIT(29)),
+
+	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x2d8, BIT(19)),
+	[RST_BUS_UART4]		= RESET(0x2d8, BIT(20)),
 };
 
 static const struct ccu_desc a83t_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_h3.c b/drivers/clk/sunxi/clk_h3.c
index f706e77dee..89f59dbea3 100644
--- a/drivers/clk/sunxi/clk_h3.c
+++ b/drivers/clk/sunxi/clk_h3.c
@@ -53,6 +53,11 @@ static struct ccu_reset h3_resets[] = {
 	[RST_BUS_OHCI1]		= RESET(0x2c0, BIT(29)),
 	[RST_BUS_OHCI2]		= RESET(0x2c0, BIT(30)),
 	[RST_BUS_OHCI3]		= RESET(0x2c0, BIT(31)),
+
+	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x2d8, BIT(19)),
 };
 
 static const struct ccu_desc h3_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_r40.c b/drivers/clk/sunxi/clk_r40.c
index 3405b39c46..a95017f12e 100644
--- a/drivers/clk/sunxi/clk_r40.c
+++ b/drivers/clk/sunxi/clk_r40.c
@@ -50,6 +50,15 @@ static struct ccu_reset r40_resets[] = {
 	[RST_BUS_OHCI0]		= RESET(0x2c0, BIT(29)),
 	[RST_BUS_OHCI1]		= RESET(0x2c0, BIT(30)),
 	[RST_BUS_OHCI2]		= RESET(0x2c0, BIT(31)),
+
+	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x2d8, BIT(19)),
+	[RST_BUS_UART4]		= RESET(0x2d8, BIT(20)),
+	[RST_BUS_UART5]		= RESET(0x2d8, BIT(21)),
+	[RST_BUS_UART6]		= RESET(0x2d8, BIT(22)),
+	[RST_BUS_UART7]		= RESET(0x2d8, BIT(23)),
 };
 
 static const struct ccu_desc r40_ccu_desc = {
diff --git a/drivers/clk/sunxi/clk_v3s.c b/drivers/clk/sunxi/clk_v3s.c
index a662bc3e93..867b029172 100644
--- a/drivers/clk/sunxi/clk_v3s.c
+++ b/drivers/clk/sunxi/clk_v3s.c
@@ -26,6 +26,10 @@ static struct ccu_reset v3s_resets[] = {
 	[RST_USB_PHY0]		= RESET(0x0cc, BIT(0)),
 
 	[RST_BUS_OTG]		= RESET(0x2c0, BIT(24)),
+
+	[RST_BUS_UART0]		= RESET(0x2d8, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x2d8, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x2d8, BIT(18)),
 };
 
 static const struct ccu_desc v3s_ccu_desc = {
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 13/26] clk: sunxi: Add Allwinner H6 CLK driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (11 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 12/26] clk: sunxi: Implement UART resets Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 14/26] sunxi: A64: Update sun50i-a64-ccu.h Jagan Teki
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add initial clock driver for Allwinner H6.

- Implement UART bus clocks via ccu_clk_gate table for
  H6, so it can accessed in common clk enable and disable
  functions from clk_sunxi.c
- Implement UART bus resets via ccu_reset table for H6,
  so it can accessed in common reset deassert and assert
  functions from reset-sunxi.c

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/clk/sunxi/Kconfig  |  7 +++++
 drivers/clk/sunxi/Makefile |  1 +
 drivers/clk/sunxi/clk_h6.c | 53 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+)
 create mode 100644 drivers/clk/sunxi/clk_h6.c

diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
index a6f84e9e56..cb11c7c21e 100644
--- a/drivers/clk/sunxi/Kconfig
+++ b/drivers/clk/sunxi/Kconfig
@@ -65,6 +65,13 @@ config CLK_SUN8I_H3
 	  This enables common clock driver support for platforms based
 	  on Allwinner H3/H5 SoC.
 
+config CLK_SUN50I_H6
+	bool "Clock driver for Allwinner H6"
+	default MACH_SUN50I_H6
+	help
+	  This enables common clock driver support for platforms based
+	  on Allwinner H6 SoC.
+
 config CLK_SUN50I_A64
 	bool "Clock driver for Allwinner A64"
 	default MACH_SUN50I
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index fbd43527a6..794aa2461c 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -14,4 +14,5 @@ obj-$(CONFIG_CLK_SUN8I_A83T) += clk_a83t.o
 obj-$(CONFIG_CLK_SUN8I_R40) += clk_r40.o
 obj-$(CONFIG_CLK_SUN8I_V3S) += clk_v3s.o
 obj-$(CONFIG_CLK_SUN8I_H3) += clk_h3.o
+obj-$(CONFIG_CLK_SUN50I_H6) += clk_h6.o
 obj-$(CONFIG_CLK_SUN50I_A64) += clk_a64.o
diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
new file mode 100644
index 0000000000..b471ad2610
--- /dev/null
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <asm/arch/ccu.h>
+#include <dt-bindings/clock/sun50i-h6-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-ccu.h>
+
+static struct ccu_clk_gate h6_gates[] = {
+	[CLK_BUS_UART0]		= GATE(0x90c, BIT(0)),
+	[CLK_BUS_UART1]		= GATE(0x90c, BIT(1)),
+	[CLK_BUS_UART2]		= GATE(0x90c, BIT(2)),
+	[CLK_BUS_UART3]		= GATE(0x90c, BIT(3)),
+};
+
+static struct ccu_reset h6_resets[] = {
+	[RST_BUS_UART0]		= RESET(0x90c, BIT(16)),
+	[RST_BUS_UART1]		= RESET(0x90c, BIT(17)),
+	[RST_BUS_UART2]		= RESET(0x90c, BIT(18)),
+	[RST_BUS_UART3]		= RESET(0x90c, BIT(19)),
+};
+
+static const struct ccu_desc h6_ccu_desc = {
+	.gates = h6_gates,
+	.resets = h6_resets,
+};
+
+static int h6_clk_bind(struct udevice *dev)
+{
+	return sunxi_reset_bind(dev, 62);
+}
+
+static const struct udevice_id h6_ccu_ids[] = {
+	{ .compatible = "allwinner,sun50i-h6-ccu",
+	  .data = (ulong)&h6_ccu_desc },
+	{ }
+};
+
+U_BOOT_DRIVER(clk_sun50i_h6) = {
+	.name		= "sun50i_h6_ccu",
+	.id		= UCLASS_CLK,
+	.of_match	= h6_ccu_ids,
+	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
+	.ops		= &sunxi_clk_ops,
+	.probe		= sunxi_clk_probe,
+	.bind		= h6_clk_bind,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 14/26] sunxi: A64: Update sun50i-a64-ccu.h
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (12 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 13/26] clk: sunxi: Add Allwinner H6 CLK driver Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support Jagan Teki
                   ` (13 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Update sun50i-a64-ccu.h from the Linux sunxi/dt64-for-4.20 tree:
commit 679294497be31596e1c9c61507746d72b6b05f26
Author: Rodrigo Exterckötter Tjäder <rodrigo@tjader.xyz>
Date:   Wed Sep 26 19:48:24 2018 +0000
    arm64: dts: allwinner: a64: a64-olinuxino: set the PHY TX delay

This should be a part of previous sync patch from
commit 1b39a1834ed182bbd8036a5cd74a9ea111fa4691
Author: Andre Przywara <andre.przywara@arm.com>
Date:   Mon Oct 29 00:56:47 2018 +0000

    sunxi: A64: Update .dts/.dtsi files

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 include/dt-bindings/clock/sun50i-a64-ccu.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/dt-bindings/clock/sun50i-a64-ccu.h b/include/dt-bindings/clock/sun50i-a64-ccu.h
index 370c0a0473..d66432c6e6 100644
--- a/include/dt-bindings/clock/sun50i-a64-ccu.h
+++ b/include/dt-bindings/clock/sun50i-a64-ccu.h
@@ -43,6 +43,8 @@
 #ifndef _DT_BINDINGS_CLK_SUN50I_A64_H_
 #define _DT_BINDINGS_CLK_SUN50I_A64_H_
 
+#define CLK_PLL_PERIPH0		11
+
 #define CLK_BUS_MIPI_DSI	28
 #define CLK_BUS_CE		29
 #define CLK_BUS_DMA		30
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (13 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 14/26] sunxi: A64: Update sun50i-a64-ccu.h Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2019-01-07  1:03   ` André Przywara
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 16/26] sunxi: Enable CLK Jagan Teki
                   ` (12 subsequent siblings)
  27 siblings, 1 reply; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Clock control unit comprises of parent clocks, gates, multiplexers,
dividers, multipliers, pre/post dividers and flags etc.

So, the U-Boot implementation of ccu has divided into gates and tree.
gates are generic clock configuration of enable/disable bit management
which can be handle via ccu_clock_gate.

Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp,
pre/post div, flags etc. which were managed via ccu_clock_tree.

This patch add support for MP, NK, MISC, FIXED clock types as part of
ccu clock tree with get_rate functionality this eventually used by
uart driver. and rest of the infrastructure will try to add while CLK
is being used on respective peripherals.

Note that few of the tree type clock would require to enable gates on
their specific clock, in that case we need to add the gate details via
ccu_clock_gate, example: MP with gate so the gate offset, bit value
should add as part of ccu_clock_gate.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++-
 drivers/clk/sunxi/clk_a64.c           |  40 ++++++
 drivers/clk/sunxi/clk_sunxi.c         | 182 ++++++++++++++++++++++++
 3 files changed, 413 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
index 3fdc26978d..61b8c36b3b 100644
--- a/arch/arm/include/asm/arch-sunxi/ccu.h
+++ b/arch/arm/include/asm/arch-sunxi/ccu.h
@@ -7,15 +7,204 @@
 #ifndef _ASM_ARCH_CCU_H
 #define _ASM_ARCH_CCU_H
 
+#define OSC_32K_ULL		32000ULL
+#define OSC_24M_ULL		24000000ULL
+
+/**
+ * enum ccu_clk_type - ccu clock types
+ *
+ * @CCU_CLK_TYPE_MISC:			misc clock type
+ * @CCU_CLK_TYPE_FIXED:			fixed clock type
+ * @CCU_CLK_TYPE_MP:			mp clock type
+ * @CCU_CLK_TYPE_NK:			nk clock type
+ */
+enum ccu_clk_type {
+	CCU_CLK_TYPE_MISC		= 0,
+	CCU_CLK_TYPE_FIXED		= 1,
+	CCU_CLK_TYPE_MP			= 2,
+	CCU_CLK_TYPE_NK			= 3,
+};
+
 /**
  * enum ccu_clk_flags - ccu clock flags
  *
- * @CCU_CLK_F_INIT_DONE:		clock gate init done check
+ * @CCU_CLK_F_INIT_DONE:		clock tree/gate init done check
+ * @CCU_CLK_F_POSTDIV:			clock post divider
  */
 enum ccu_clk_flags {
 	CCU_CLK_F_INIT_DONE		= BIT(0),
+	CCU_CLK_F_POSTDIV		= BIT(1),
 };
 
+/**
+ * struct ccu_mult - ccu clock multiplier
+ *
+ * @shift:		multiplier shift value
+ * @width:		multiplier width value
+ * @offset:		multiplier offset
+ * @min:		minimum multiplier
+ * @max:		maximum multiplier
+ */
+struct ccu_mult {
+	u8 shift;
+	u8 width;
+	u8 offset;
+	u8 min;
+	u8 max;
+};
+
+#define _CCU_MULT_OFF_MIN_MAX(_shift, _width, _offset,		\
+			      _min, _max) {			\
+	.shift = _shift,					\
+	.width = _width,					\
+	.offset = _offset,					\
+	.min = _min,						\
+	.max = _max,						\
+}
+
+#define _CCU_MULT_MIN(_shift, _width, _min)			\
+	_CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0)
+
+#define _CCU_MULT(_shift, _width)				\
+	_CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0)
+
+/**
+ * struct ccu_mux - ccu clock multiplexer
+ *
+ * @shift:		multiplexer shift value
+ * @width:		multiplexer width value
+ */
+struct ccu_mux {
+	u8 shift;
+	u8 width;
+};
+
+#define _CCU_MUX(_shift, _width) {		\
+	.shift = _shift,			\
+	.width = _width,			\
+}
+
+/**
+ * struct ccu_div - ccu clock divider
+ *
+ * @shift:		divider shift value
+ * @width:		divider width value
+ * @offset:		divider offset
+ * @max:		maximum divider value
+ */
+struct ccu_div {
+	u8 shift;
+	u8 width;
+	u32 offset;
+	u32 max;
+};
+
+#define _CCU_DIV(_shift, _width) {		\
+	.shift = _shift,			\
+	.width = _width,			\
+	.offset = 1,				\
+	.max = 0,				\
+}
+
+/**
+ * struct ccu_clk_tree - ccu clock tree
+ *
+ * @parent:		parent clock tree
+ * @type:		clock type
+ * @off:		clock tree offset
+ * @m:			divider m
+ * @p:			divider p
+ * @mux:		multiplexer mux
+ * @post:		post divider value
+ * @n:			multiplier n
+ * @k:			multiplier k
+ * @fixed_rate:		fixed rate
+ * @flags:		clock tree flags
+ */
+struct ccu_clk_tree {
+	const unsigned long *parent;
+	enum ccu_clk_type type;
+	u16 off;
+
+	struct ccu_div m;
+	struct ccu_div p;
+	struct ccu_mux mux;
+	unsigned int postdiv;
+
+	struct ccu_mult n;
+	struct ccu_mult k;
+
+	ulong fixed_rate;
+	enum ccu_clk_flags flags;
+};
+
+#define TREE(_parent, _type, _off,				\
+	     _m, _p,						\
+	     _mux,						\
+	     _postdiv,						\
+	     _n, _k,						\
+	     _fixed_rate,					\
+	     _flags) {						\
+	.parent = _parent,					\
+	.type = _type,						\
+	.off = _off,						\
+	.m = _m,						\
+	.p = _p,						\
+	.mux = _mux,						\
+	.postdiv = _postdiv,					\
+	.n = _n,						\
+	.k = _k,						\
+	.fixed_rate = _fixed_rate,				\
+	.flags = _flags,					\
+}
+
+#define MISC(_parent)						\
+	TREE(_parent, CCU_CLK_TYPE_MISC, 0,			\
+	     {0}, {0},						\
+	     {0},						\
+	     0,							\
+	     {0}, {0},						\
+	     0,							\
+	     CCU_CLK_F_INIT_DONE)
+
+#define FIXED(_fixed_rate)					\
+	TREE(NULL, CCU_CLK_TYPE_FIXED, 0,			\
+	     {0}, {0},						\
+	     {0},						\
+	     0,							\
+	     {0}, {0},						\
+	     _fixed_rate,					\
+	     CCU_CLK_F_INIT_DONE)
+
+#define NK(_parent, _off,					\
+	   _nshift, _nwidth,					\
+	   _kshift, _kwidth, _kmin,				\
+	   _postdiv,						\
+	   _flags)						\
+	TREE(_parent, CCU_CLK_TYPE_NK, _off,			\
+	     {0}, {0},						\
+	     {0},						\
+	     _postdiv,						\
+	     _CCU_MULT(_nshift, _nwidth),			\
+	     _CCU_MULT_MIN(_kshift, _kwidth, _kmin),		\
+	     0,							\
+	     CCU_CLK_F_INIT_DONE | _flags)
+
+#define MP(_parent, _off,					\
+	   _mshift, _mwidth,					\
+	   _pshift, _pwidth,					\
+	   _muxshift, _muxwidth,				\
+	   _postdiv,						\
+	   _flags)						\
+	TREE(_parent, CCU_CLK_TYPE_MP, _off,			\
+	     _CCU_DIV(_mshift, _mwidth),			\
+	     _CCU_DIV(_pshift, _pwidth),			\
+	     _CCU_MUX(_muxshift, _muxwidth),			\
+	     _postdiv,						\
+	     {0}, {0},						\
+	     0,							\
+	     CCU_CLK_F_INIT_DONE | _flags)
+
 /**
  * struct ccu_clk_gate - ccu clock gate
  * @off:	gate offset
@@ -59,6 +248,7 @@ struct ccu_reset {
  * @resets:	reset unit
  */
 struct ccu_desc {
+	const struct ccu_clk_tree *tree;
 	const struct ccu_clk_gate *gates;
 	const struct ccu_reset *resets;
 };
diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 162ec769d6..1d0cd98183 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -12,6 +12,45 @@
 #include <dt-bindings/clock/sun50i-a64-ccu.h>
 #include <dt-bindings/reset/sun50i-a64-ccu.h>
 
+#define CLK_APB2			26
+#define CLK_OSC_32K			(CLK_GPU + 1)
+#define CLK_OSC_24M			(CLK_OSC_32K + 1)
+
+static const unsigned long periph0_parents[] = {
+	CLK_OSC_24M,
+};
+
+static const unsigned long apb2_parents[] = {
+	CLK_OSC_32K,
+	CLK_OSC_24M,
+	CLK_PLL_PERIPH0,
+	CLK_PLL_PERIPH0,
+};
+
+static const unsigned long uart_parents[] = {
+	CLK_APB2,
+};
+
+static const struct ccu_clk_tree a64_tree[] = {
+	[CLK_OSC_32K]		= FIXED(OSC_32K_ULL),
+	[CLK_OSC_24M]		= FIXED(OSC_24M_ULL),
+
+	[CLK_PLL_PERIPH0]	= NK(periph0_parents, 0x028,
+				     8, 5,	/* N */
+				     4, 2, 2,	/* K */
+				     2,		/* post-div */
+				     CCU_CLK_F_POSTDIV),
+
+	[CLK_APB2]		= MP(apb2_parents, 0x058,
+				     0, 5,	/* M */
+				     16, 2,	/* P */
+				     24, 2,	/* mux */
+				     0,
+				     0),
+
+	[CLK_BUS_UART0]		= MISC(uart_parents),
+};
+
 static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
 	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
@@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = {
 };
 
 static const struct ccu_desc a64_ccu_desc = {
+	.tree = a64_tree,
 	.gates = a64_gates,
 	.resets = a64_resets,
 };
diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
index 345d706c2a..2aebd257d1 100644
--- a/drivers/clk/sunxi/clk_sunxi.c
+++ b/drivers/clk/sunxi/clk_sunxi.c
@@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
 	return &priv->desc->gates[id];
 }
 
+static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv *priv,
+					       unsigned long id)
+{
+	return &priv->desc->tree[id];
+}
+
+static int sunxi_get_parent_idx(const struct ccu_clk_tree *tree, void *base)
+{
+	u32 reg, idx;
+
+	reg = readl(base + tree->off);
+	idx = reg >> tree->mux.shift;
+	idx &= (1 << tree->mux.width) - 1;
+
+	return idx;
+}
+
+static ulong sunxi_fixed_get_rate(struct clk *clk, unsigned long id)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
+
+	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
+		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
+		return 0;
+	}
+
+	return tree->fixed_rate;
+}
+
+static ulong sunxi_nk_get_parent_rate(struct clk *clk, unsigned long id)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
+	ulong rate = 0;
+
+	switch (tree->type) {
+	case CCU_CLK_TYPE_FIXED:
+		rate = sunxi_fixed_get_rate(clk, id);
+		break;
+	default:
+		printf("%s: Unknown (TYPE#%d)\n", __func__, tree->type);
+		break;
+	}
+
+	return rate;
+}
+
+static ulong sunxi_nk_get_rate(struct clk *clk, unsigned long id)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
+	ulong rate, parent_rate;
+	unsigned long n, k;
+	u32 reg;
+
+	parent_rate = sunxi_nk_get_parent_rate(clk, tree->parent[0]);
+
+	reg = readl(priv->base + tree->off);
+
+	n = reg >> tree->n.shift;
+	n &= (1 << tree->n.width) - 1;
+	n += tree->n.offset;
+	if (!n)
+		n++;
+
+	k = reg >> tree->k.shift;
+	k &= (1 << tree->k.width) - 1;
+	k += tree->k.offset;
+	if (!k)
+		k++;
+
+	rate = parent_rate * n * k;
+	if (tree->flags & CCU_CLK_F_POSTDIV)
+		rate /= tree->postdiv;
+
+	return rate;
+}
+
+static ulong sunxi_mp_get_parent_rate(struct clk *clk, unsigned long id)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
+	ulong rate = 0;
+
+	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
+		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
+		return 0;
+	}
+
+	switch (tree->type) {
+	case CCU_CLK_TYPE_FIXED:
+		rate = sunxi_fixed_get_rate(clk, id);
+		break;
+	case CCU_CLK_TYPE_NK:
+		rate = sunxi_nk_get_rate(clk, id);
+		break;
+	default:
+		printf("%s: (TYPE#%d) unhandled\n", __func__, tree->type);
+		break;
+	}
+
+	return rate;
+}
+
+static ulong sunxi_mp_get_rate(struct clk *clk, unsigned long id)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
+	unsigned int m, p;
+	ulong parent_rate;
+	u32 reg, idx;
+
+	idx = sunxi_get_parent_idx(tree, priv->base);
+	if (idx < 0) {
+		printf("%s: Wrong parent index %d\n", __func__, idx);
+		return 0;
+	}
+
+	parent_rate = sunxi_mp_get_parent_rate(clk, tree->parent[idx]);
+
+	reg = readl(priv->base + tree->off);
+
+	m = reg >> tree->m.shift;
+	m &= (1 << tree->m.width) - 1;
+	m += tree->m.offset;
+	if (!m)
+		m++;
+
+	p = reg >> tree->p.shift;
+	p &= (1 << tree->p.width) - 1;
+
+	return (parent_rate >> p) / m;
+}
+
+static ulong sunxi_misc_get_rate(struct clk *clk, unsigned long id)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
+	ulong rate = 0;
+
+	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
+		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
+		return 0;
+	}
+
+	switch (tree->type) {
+	case CCU_CLK_TYPE_MP:
+		rate = sunxi_mp_get_rate(clk, id);
+		break;
+	default:
+		printf("%s: (TYPE#%d) unhandled\n", __func__, tree->type);
+		break;
+	}
+
+	return rate;
+}
+
+static ulong sunxi_clk_get_rate(struct clk *clk)
+{
+	struct ccu_priv *priv = dev_get_priv(clk->dev);
+	const struct ccu_clk_tree *tree = priv_to_tree(priv, clk->id);
+	ulong rate = 0;
+
+	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
+		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
+		return 0;
+	}
+
+	switch (tree->type) {
+	case CCU_CLK_TYPE_MISC:
+		rate = sunxi_misc_get_rate(clk, tree->parent[0]);
+		break;
+	default:
+		printf("%s: (TYPE#%d) unhandled\n", __func__, tree->type);
+		break;
+	}
+
+	return rate;
+}
+
 static int sunxi_set_gate(struct clk *clk, bool on)
 {
 	struct ccu_priv *priv = dev_get_priv(clk->dev);
@@ -56,6 +237,7 @@ static int sunxi_clk_disable(struct clk *clk)
 struct clk_ops sunxi_clk_ops = {
 	.enable = sunxi_clk_enable,
 	.disable = sunxi_clk_disable,
+	.get_rate = sunxi_clk_get_rate,
 };
 
 int sunxi_clk_probe(struct udevice *dev)
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 16/26] sunxi: Enable CLK
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (14 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 17/26] phy: sun4i-usb: Use CLK and RESET support Jagan Teki
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

CLK and DM_RESET drivers are now available for most
of the Allwinner platforms, so enable in mach-sunxi/Kconfig

Enabling CLK will select DM_RESET by default.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 arch/arm/mach-sunxi/Kconfig | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index 3c54f5106d..5f51bbbed0 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -132,6 +132,7 @@ endif
 
 config MACH_SUNXI_H3_H5
 	bool
+	select CLK
 	select DM_I2C
 	select PHY_SUN4I_USB
 	select SUNXI_DE2
@@ -154,6 +155,7 @@ config MACH_SUN4I
 	bool "sun4i (Allwinner A10)"
 	select CPU_V7A
 	select ARM_CORTEX_CPU_IS_UP
+	select CLK
 	select DM_MMC if MMC
 	select DM_SCSI if SCSI
 	select PHY_SUN4I_USB
@@ -165,6 +167,7 @@ config MACH_SUN5I
 	bool "sun5i (Allwinner A13)"
 	select CPU_V7A
 	select ARM_CORTEX_CPU_IS_UP
+	select CLK
 	select DRAM_SUN4I
 	select PHY_SUN4I_USB
 	select SUNXI_GEN_SUN4I
@@ -177,6 +180,7 @@ config MACH_SUN6I
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
 	select ARCH_SUPPORT_PSCI
+	select CLK
 	select DRAM_SUN6I
 	select PHY_SUN4I_USB
 	select SUN6I_P2WI
@@ -191,6 +195,7 @@ config MACH_SUN7I
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
 	select ARCH_SUPPORT_PSCI
+	select CLK
 	select DRAM_SUN4I
 	select PHY_SUN4I_USB
 	select SUNXI_GEN_SUN4I
@@ -203,6 +208,7 @@ config MACH_SUN8I_A23
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
 	select ARCH_SUPPORT_PSCI
+	select CLK
 	select DRAM_SUN8I_A23
 	select PHY_SUN4I_USB
 	select SUNXI_GEN_SUN6I
@@ -216,6 +222,7 @@ config MACH_SUN8I_A33
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
 	select ARCH_SUPPORT_PSCI
+	select CLK
 	select DRAM_SUN8I_A33
 	select PHY_SUN4I_USB
 	select SUNXI_GEN_SUN6I
@@ -226,6 +233,7 @@ config MACH_SUN8I_A33
 config MACH_SUN8I_A83T
 	bool "sun8i (Allwinner A83T)"
 	select CPU_V7A
+	select CLK
 	select DRAM_SUN8I_A83T
 	select PHY_SUN4I_USB
 	select SUNXI_GEN_SUN6I
@@ -248,6 +256,7 @@ config MACH_SUN8I_R40
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
 	select ARCH_SUPPORT_PSCI
+	select CLK
 	select SUNXI_GEN_SUN6I
 	select SUPPORT_SPL
 	select SUNXI_DRAM_DW
@@ -259,6 +268,7 @@ config MACH_SUN8I_V3S
 	select CPU_V7_HAS_NONSEC
 	select CPU_V7_HAS_VIRT
 	select ARCH_SUPPORT_PSCI
+	select CLK
 	select SUNXI_GEN_SUN6I
 	select SUNXI_DRAM_DW
 	select SUNXI_DRAM_DW_16BIT
@@ -277,6 +287,7 @@ config MACH_SUN9I
 config MACH_SUN50I
 	bool "sun50i (Allwinner A64)"
 	select ARM64
+	select CLK
 	select DM_I2C
 	select PHY_SUN4I_USB
 	select SUN6I_PRCM
@@ -300,6 +311,7 @@ config MACH_SUN50I_H5
 config MACH_SUN50I_H6
 	bool "sun50i (Allwinner H6)"
 	select ARM64
+	select CLK
 	select SUPPORT_SPL
 	select FIT
 	select SPL_LOAD_FIT
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 17/26] phy: sun4i-usb: Use CLK and RESET support
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (15 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 16/26] sunxi: Enable CLK Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 18:29   ` Marek Vasut
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 18/26] reset: Add reset valid Jagan Teki
                   ` (10 subsequent siblings)
  27 siblings, 1 reply; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Now clock and reset drivers are available for respective
SoC's so use clk and reset ops on phy driver.

Cc: Marek Vasut <marex@denx.de> 
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/phy/allwinner/phy-sun4i-usb.c | 77 ++++++++++++++++++++-------
 1 file changed, 57 insertions(+), 20 deletions(-)

diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c
index a7d7e3f044..f206fa3f5d 100644
--- a/drivers/phy/allwinner/phy-sun4i-usb.c
+++ b/drivers/phy/allwinner/phy-sun4i-usb.c
@@ -11,10 +11,12 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <dm/device.h>
 #include <generic-phy.h>
 #include <phy-sun4i-usb.h>
+#include <reset.h>
 #include <asm/gpio.h>
 #include <asm/io.h>
 #include <asm/arch/clock.h>
@@ -80,6 +82,7 @@ struct sun4i_usb_phy_cfg {
 	enum sun4i_usb_phy_type type;
 	u32 disc_thresh;
 	u8 phyctl_offset;
+	bool dedicated_clocks;
 	bool enable_pmu_unk1;
 	bool phy0_dual_route;
 };
@@ -88,30 +91,21 @@ struct sun4i_usb_phy_info {
 	const char *gpio_vbus;
 	const char *gpio_vbus_det;
 	const char *gpio_id_det;
-	int rst_mask;
 } phy_info[] = {
 	{
 		.gpio_vbus = CONFIG_USB0_VBUS_PIN,
 		.gpio_vbus_det = CONFIG_USB0_VBUS_DET,
 		.gpio_id_det = CONFIG_USB0_ID_DET,
-		.rst_mask = (CCM_USB_CTRL_PHY0_RST | CCM_USB_CTRL_PHY0_CLK),
 	},
 	{
 		.gpio_vbus = CONFIG_USB1_VBUS_PIN,
 		.gpio_vbus_det = NULL,
 		.gpio_id_det = NULL,
-		.rst_mask = (CCM_USB_CTRL_PHY1_RST | CCM_USB_CTRL_PHY1_CLK),
 	},
 	{
 		.gpio_vbus = CONFIG_USB2_VBUS_PIN,
 		.gpio_vbus_det = NULL,
 		.gpio_id_det = NULL,
-#ifdef CONFIG_MACH_SUN8I_A83T
-		.rst_mask = (CCM_USB_CTRL_HSIC_RST | CCM_USB_CTRL_HSIC_CLK |
-			     CCM_USB_CTRL_12M_CLK),
-#else
-		.rst_mask = (CCM_USB_CTRL_PHY2_RST | CCM_USB_CTRL_PHY2_CLK),
-#endif
 	},
 	{
 		.gpio_vbus = CONFIG_USB3_VBUS_PIN,
@@ -126,13 +120,13 @@ struct sun4i_usb_phy_plat {
 	int gpio_vbus;
 	int gpio_vbus_det;
 	int gpio_id_det;
-	int rst_mask;
+	struct clk clocks;
+	struct reset_ctl resets;
 	int id;
 };
 
 struct sun4i_usb_phy_data {
 	void __iomem *base;
-	struct sunxi_ccm_reg *ccm;
 	const struct sun4i_usb_phy_cfg *cfg;
 	struct sun4i_usb_phy_plat *usb_phy;
 };
@@ -266,8 +260,19 @@ static int sun4i_usb_phy_init(struct phy *phy)
 	struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
 	struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
 	u32 val;
+	int ret;
 
-	setbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask);
+	ret = clk_enable(&usb_phy->clocks);
+	if (ret) {
+		dev_err(dev, "failed to enable usb_%ldphy clock\n", phy->id);
+		return ret;
+	}
+
+	ret = reset_deassert(&usb_phy->resets);
+	if (ret) {
+		dev_err(dev, "failed to deassert usb_%ldreset reset\n", phy->id);
+		return ret;
+	}
 
 	if (data->cfg->type == sun8i_a83t_phy) {
 		if (phy->id == 0) {
@@ -308,6 +313,7 @@ static int sun4i_usb_phy_exit(struct phy *phy)
 {
 	struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
 	struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
+	int ret;
 
 	if (phy->id == 0) {
 		if (data->cfg->type == sun8i_a83t_phy) {
@@ -320,7 +326,17 @@ static int sun4i_usb_phy_exit(struct phy *phy)
 
 	sun4i_usb_phy_passby(phy, false);
 
-	clrbits_le32(&data->ccm->usb_clk_cfg, usb_phy->rst_mask);
+	ret = clk_disable(&usb_phy->clocks);
+	if (ret) {
+		dev_err(dev, "failed to disable usb_%ldphy clock\n", phy->id);
+		return ret;
+	}
+
+	ret = reset_assert(&usb_phy->resets);
+	if (ret) {
+		dev_err(dev, "failed to assert usb_%ldreset reset\n", phy->id);
+		return ret;
+	}
 
 	return 0;
 }
@@ -407,10 +423,6 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
 	if (IS_ERR(data->base))
 		return PTR_ERR(data->base);
 
-	data->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	if (IS_ERR(data->ccm))
-		return PTR_ERR(data->ccm);
-
 	data->usb_phy = plat;
 	for (i = 0; i < data->cfg->num_phys; i++) {
 		struct sun4i_usb_phy_plat *phy = &plat[i];
@@ -448,6 +460,24 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
 			sunxi_gpio_set_pull(phy->gpio_id_det, SUNXI_GPIO_PULL_UP);
 		}
 
+		if (data->cfg->dedicated_clocks)
+			snprintf(name, sizeof(name), "usb%d_phy", i);
+		else
+			strlcpy(name, "usb_phy", sizeof(name));
+
+		ret = clk_get_by_name(dev, name, &phy->clocks);
+		if (ret) {
+			dev_err(dev, "failed to get usb%d_phy clock phandle\n", i);
+			return ret;
+		}
+
+		snprintf(name, sizeof(name), "usb%d_reset", i);
+		ret = reset_get_by_name(dev, name, &phy->resets);
+		if (ret) {
+			dev_err(dev, "failed to get usb%d_reset reset phandle\n", i);
+			return ret;
+		}
+
 		if (i || data->cfg->phy0_dual_route) {
 			snprintf(name, sizeof(name), "pmu%d", i);
 			phy->pmu = (void __iomem *)devfdt_get_addr_name(dev, name);
@@ -456,9 +486,6 @@ static int sun4i_usb_phy_probe(struct udevice *dev)
 		}
 
 		phy->id = i;
-		phy->rst_mask = info->rst_mask;
-		if ((data->cfg->type == sun8i_h3_phy) && (phy->id == 3))
-			phy->rst_mask = (BIT(3) | BIT(11));
 	};
 
 	debug("Allwinner Sun4I USB PHY driver loaded\n");
@@ -470,6 +497,7 @@ static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
 	.type = sun4i_a10_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A10,
+	.dedicated_clocks = false,
 	.enable_pmu_unk1 = false,
 };
 
@@ -478,6 +506,7 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
 	.type = sun4i_a10_phy,
 	.disc_thresh = 2,
 	.phyctl_offset = REG_PHYCTL_A10,
+	.dedicated_clocks = false,
 	.enable_pmu_unk1 = false,
 };
 
@@ -486,6 +515,7 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
 	.type = sun6i_a31_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A10,
+	.dedicated_clocks = true,
 	.enable_pmu_unk1 = false,
 };
 
@@ -494,6 +524,7 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
 	.type = sun4i_a10_phy,
 	.disc_thresh = 2,
 	.phyctl_offset = REG_PHYCTL_A10,
+	.dedicated_clocks = false,
 	.enable_pmu_unk1 = false,
 };
 
@@ -502,6 +533,7 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
 	.type = sun4i_a10_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A10,
+	.dedicated_clocks = true,
 	.enable_pmu_unk1 = false,
 };
 
@@ -510,6 +542,7 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
 	.type = sun8i_a33_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A33,
+	.dedicated_clocks = true,
 	.enable_pmu_unk1 = false,
 };
 
@@ -517,6 +550,7 @@ static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
 	.num_phys = 3,
 	.type = sun8i_a83t_phy,
 	.phyctl_offset = REG_PHYCTL_A33,
+	.dedicated_clocks = true,
 };
 
 static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
@@ -524,6 +558,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
 	.type = sun8i_h3_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A33,
+	.dedicated_clocks = true,
 	.enable_pmu_unk1 = true,
 	.phy0_dual_route = true,
 };
@@ -533,6 +568,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
 	.type = sun8i_v3s_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A33,
+	.dedicated_clocks = true,
 	.enable_pmu_unk1 = true,
 	.phy0_dual_route = true,
 };
@@ -542,6 +578,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
 	.type = sun50i_a64_phy,
 	.disc_thresh = 3,
 	.phyctl_offset = REG_PHYCTL_A33,
+	.dedicated_clocks = true,
 	.enable_pmu_unk1 = true,
 	.phy0_dual_route = true,
 };
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 18/26] reset: Add reset valid
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (16 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 17/26] phy: sun4i-usb: Use CLK and RESET support Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 19/26] musb-new: sunxi: Use CLK and RESET support Jagan Teki
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add reset_valid to check whether given reset is valid
or not.

Cc: Simon Glass <sjg@chromium.org>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 include/reset.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/reset.h b/include/reset.h
index bc495a90c2..65aa7a4ce5 100644
--- a/include/reset.h
+++ b/include/reset.h
@@ -306,4 +306,15 @@ static inline int reset_release_bulk(struct reset_ctl_bulk *bulk)
 }
 #endif
 
+/**
+ * reset_valid() - check if reset is valid
+ *
+ * @reset_ctl:		the reset to check
+ * @return TRUE if valid, or FALSE
+ */
+static inline bool reset_valid(struct reset_ctl *reset_ctl)
+{
+	return !!reset_ctl->dev;
+}
+
 #endif
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 19/26] musb-new: sunxi: Use CLK and RESET support
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (17 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 18/26] reset: Add reset valid Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 18:30   ` Marek Vasut
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 20/26] sunxi: usb: Switch to Generic host controllers Jagan Teki
                   ` (8 subsequent siblings)
  27 siblings, 1 reply; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Now clock and reset drivers are available for respective
SoC's so use clk and reset ops on musb driver.

Cc: Marek Vasut <marex@denx.de> 
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/usb/musb-new/sunxi.c | 81 ++++++++++++++++++------------------
 1 file changed, 40 insertions(+), 41 deletions(-)

diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index f542a181fa..f79b3eedcf 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -16,9 +16,11 @@
  * This file is part of the Inventra Controller Driver for Linux.
  */
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <generic-phy.h>
 #include <phy-sun4i-usb.h>
+#include <reset.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/gpio.h>
@@ -80,16 +82,12 @@
 
 struct sunxi_musb_config {
 	struct musb_hdrc_config *config;
-	bool has_reset;
-	u8 rst_bit;
-	u8 clkgate_bit;
-	u32 off_reset0;
 };
 
 struct sunxi_glue {
 	struct musb_host_data mdata;
-	struct sunxi_ccm_reg *ccm;
-	u32 *reg_reset0;
+	struct clk clk;
+	struct reset_ctl rst;
 	struct sunxi_musb_config *cfg;
 	struct device dev;
 	struct phy phy;
@@ -296,24 +294,27 @@ static int sunxi_musb_init(struct musb *musb)
 
 	pr_debug("%s():\n", __func__);
 
-	ret = generic_phy_init(&glue->phy);
+	ret = clk_enable(&glue->clk);
 	if (ret) {
-		pr_err("failed to init USB PHY\n");
+		pr_err("failed to enable clock\n");
 		return ret;
 	}
 
-	musb->isr = sunxi_musb_interrupt;
-
-	setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0));
-	if (glue->cfg->clkgate_bit)
-		setbits_le32(&glue->ccm->ahb_gate0,
-			     BIT(glue->cfg->clkgate_bit));
+	if (reset_valid(&glue->rst)) {
+		ret = reset_deassert(&glue->rst);
+		if (ret) {
+			pr_err("failed to deassert reset\n");
+			goto err_clk;
+		}
+	}
 
-	if (glue->cfg->has_reset)
-		setbits_le32(glue->reg_reset0, BIT(AHB_GATE_OFFSET_USB0));
+	ret = generic_phy_init(&glue->phy);
+	if (ret) {
+		pr_err("failed to init USB PHY\n");
+		goto err_rst;
+	}
 
-	if (glue->cfg->rst_bit)
-		setbits_le32(glue->reg_reset0, BIT(glue->cfg->rst_bit));
+	musb->isr = sunxi_musb_interrupt;
 
 	USBC_ConfigFIFO_Base();
 	USBC_EnableDpDmPullUp(musb->mregs);
@@ -329,6 +330,13 @@ static int sunxi_musb_init(struct musb *musb)
 	USBC_ForceVbusValidToHigh(musb->mregs);
 
 	return 0;
+
+err_rst:
+	if (reset_valid(&glue->rst))
+		reset_assert(&glue->rst);
+err_clk:
+	clk_disable(&glue->clk);
+	return ret;
 }
 
 static int sunxi_musb_exit(struct musb *musb)
@@ -339,21 +347,14 @@ static int sunxi_musb_exit(struct musb *musb)
 	if (generic_phy_valid(&glue->phy)) {
 		ret = generic_phy_exit(&glue->phy);
 		if (ret) {
-			dev_err(dev, "failed to power off usb phy\n");
+			pr_err("failed to power off usb phy\n");
 			return ret;
 		}
 	}
 
-	if (glue->cfg->has_reset)
-		clrbits_le32(glue->reg_reset0, BIT(AHB_GATE_OFFSET_USB0));
-
-	if (glue->cfg->rst_bit)
-		clrbits_le32(glue->reg_reset0, BIT(glue->cfg->rst_bit));
-
-	clrbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0));
-	if (glue->cfg->clkgate_bit)
-		clrbits_le32(&glue->ccm->ahb_gate0,
-			     BIT(glue->cfg->clkgate_bit));
+	if (reset_valid(&glue->rst))
+		reset_assert(&glue->rst);
+	clk_disable(&glue->clk);
 
 	return 0;
 }
@@ -450,11 +451,17 @@ static int musb_usb_probe(struct udevice *dev)
 	if (!glue->cfg)
 		return -EINVAL;
 
-	glue->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	if (IS_ERR(glue->ccm))
-		return PTR_ERR(glue->ccm);
+	ret = clk_get_by_index(dev, 0, &glue->clk);
+	if (ret) {
+		pr_err("failed to get clock\n");
+		return ret;
+	}
 
-	glue->reg_reset0 = (void *)glue->ccm + glue->cfg->off_reset0;
+	ret = reset_get_by_index(dev, 0, &glue->rst);
+	if (ret && ret != -ENOENT) {
+		pr_err("failed to get reset\n");
+		return ret;
+	}
 
 	ret = generic_phy_get_by_name(dev, "usb", &glue->phy);
 	if (ret) {
@@ -462,7 +469,6 @@ static int musb_usb_probe(struct udevice *dev)
 		return ret;
 	}
 
-
 	memset(&pdata, 0, sizeof(pdata));
 	pdata.power = 250;
 	pdata.platform_ops = &sunxi_musb_ops;
@@ -505,21 +511,14 @@ static int musb_usb_remove(struct udevice *dev)
 
 static const struct sunxi_musb_config sun4i_a10_cfg = {
 	.config = &musb_config,
-	.has_reset = false,
 };
 
 static const struct sunxi_musb_config sun6i_a31_cfg = {
 	.config = &musb_config,
-	.has_reset = true,
-	.off_reset0 = OFF_SUN6I_AHB_RESET0,
 };
 
 static const struct sunxi_musb_config sun8i_h3_cfg = {
 	.config = &musb_config_h3,
-	.has_reset = true,
-	.rst_bit = 23,
-	.clkgate_bit = 23,
-	.off_reset0 = OFF_SUN6I_AHB_RESET0,
 };
 
 static const struct udevice_id sunxi_musb_ids[] = {
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 20/26] sunxi: usb: Switch to Generic host controllers
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (18 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 19/26] musb-new: sunxi: Use CLK and RESET support Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 21/26] usb: host: Drop [e-o]hci-sunxi drivers Jagan Teki
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Once of key blocker for using USB Generic host controller
drivers in Allwinner are CLK and RESET drivers, now these
available for USB usage.

So switch sunxi USB use EHCI and OHCI Generic controllers.

Enabling USB is wisely a board choise, So Enable USB_OHCI_HCD
where it already have USB_EHCI_HCD

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 configs/A10-OLinuXino-Lime_defconfig          | 1 +
 configs/A10s-OLinuXino-M_defconfig            | 1 +
 configs/A13-OLinuXinoM_defconfig              | 1 +
 configs/A13-OLinuXino_defconfig               | 1 +
 configs/A20-OLinuXino-Lime2-eMMC_defconfig    | 1 +
 configs/A20-OLinuXino-Lime2_defconfig         | 1 +
 configs/A20-OLinuXino-Lime_defconfig          | 1 +
 configs/A20-Olimex-SOM204-EVB_defconfig       | 1 +
 configs/Auxtek-T003_defconfig                 | 1 +
 configs/Auxtek-T004_defconfig                 | 1 +
 configs/Bananapi_defconfig                    | 1 +
 configs/Bananapi_m2m_defconfig                | 1 +
 configs/Bananapro_defconfig                   | 1 +
 configs/CHIP_defconfig                        | 1 +
 configs/CHIP_pro_defconfig                    | 1 +
 configs/CSQ_CS908_defconfig                   | 1 +
 configs/Colombus_defconfig                    | 1 +
 configs/Cubieboard2_defconfig                 | 1 +
 configs/Cubieboard_defconfig                  | 1 +
 configs/Cubietruck_plus_defconfig             | 1 +
 configs/Hummingbird_A31_defconfig             | 1 +
 configs/Itead_Ibox_A20_defconfig              | 1 +
 configs/Linksprite_pcDuino3_Nano_defconfig    | 1 +
 configs/Linksprite_pcDuino3_defconfig         | 1 +
 configs/Linksprite_pcDuino_defconfig          | 1 +
 configs/MK808C_defconfig                      | 1 +
 configs/Marsboard_A10_defconfig               | 1 +
 configs/Mele_A1000G_quad_defconfig            | 1 +
 configs/Mele_A1000_defconfig                  | 1 +
 configs/Mele_I7_defconfig                     | 1 +
 configs/Mele_M3_defconfig                     | 1 +
 configs/Mele_M5_defconfig                     | 1 +
 configs/Mele_M9_defconfig                     | 1 +
 configs/Mini-X_defconfig                      | 1 +
 configs/Orangepi_defconfig                    | 1 +
 configs/Orangepi_mini_defconfig               | 1 +
 configs/Sinlinx_SinA31s_defconfig             | 1 +
 configs/Sinlinx_SinA33_defconfig              | 1 +
 configs/Sinovoip_BPI_M2_Plus_defconfig        | 1 +
 configs/Sinovoip_BPI_M2_defconfig             | 1 +
 configs/Sinovoip_BPI_M3_defconfig             | 1 +
 configs/Wexler_TAB7200_defconfig              | 1 +
 configs/Wobo_i5_defconfig                     | 1 +
 configs/a64-olinuxino_defconfig               | 1 +
 configs/ba10_tv_box_defconfig                 | 1 +
 configs/bananapi_m1_plus_defconfig            | 1 +
 configs/bananapi_m64_defconfig                | 1 +
 configs/ga10h_v1_1_defconfig                  | 1 +
 configs/h8_homlet_v2_defconfig                | 1 +
 configs/i12-tvbox_defconfig                   | 1 +
 configs/icnova-a20-swac_defconfig             | 1 +
 configs/inet1_defconfig                       | 1 +
 configs/inet_q972_defconfig                   | 1 +
 configs/jesurun_q5_defconfig                  | 1 +
 configs/libretech_all_h3_cc_h2_plus_defconfig | 1 +
 configs/libretech_all_h3_cc_h3_defconfig      | 1 +
 configs/libretech_all_h3_cc_h5_defconfig      | 1 +
 configs/mixtile_loftq_defconfig               | 1 +
 configs/mk802_a10s_defconfig                  | 1 +
 configs/mk802_defconfig                       | 1 +
 configs/mk802ii_defconfig                     | 1 +
 configs/nanopi_a64_defconfig                  | 1 +
 configs/nanopi_m1_defconfig                   | 1 +
 configs/nanopi_m1_plus_defconfig              | 1 +
 configs/nanopi_neo2_defconfig                 | 1 +
 configs/nanopi_neo_air_defconfig              | 1 +
 configs/nanopi_neo_defconfig                  | 1 +
 configs/nanopi_neo_plus2_defconfig            | 1 +
 configs/orangepi_2_defconfig                  | 1 +
 configs/orangepi_lite_defconfig               | 1 +
 configs/orangepi_one_defconfig                | 1 +
 configs/orangepi_pc2_defconfig                | 1 +
 configs/orangepi_pc_defconfig                 | 1 +
 configs/orangepi_pc_plus_defconfig            | 1 +
 configs/orangepi_plus2e_defconfig             | 1 +
 configs/orangepi_plus_defconfig               | 1 +
 configs/orangepi_prime_defconfig              | 1 +
 configs/orangepi_r1_defconfig                 | 1 +
 configs/orangepi_win_defconfig                | 1 +
 configs/orangepi_zero_defconfig               | 1 +
 configs/orangepi_zero_plus2_defconfig         | 1 +
 configs/orangepi_zero_plus_defconfig          | 1 +
 configs/parrot_r16_defconfig                  | 1 +
 configs/pine64_plus_defconfig                 | 1 +
 configs/r7-tv-dongle_defconfig                | 1 +
 configs/sopine_baseboard_defconfig            | 1 +
 configs/sun8i_a23_evb_defconfig               | 1 +
 configs/sunxi_Gemei_G9_defconfig              | 1 +
 configs/tbs_a711_defconfig                    | 1 +
 drivers/usb/host/Kconfig                      | 2 ++
 include/configs/sun4i.h                       | 4 ----
 include/configs/sun50i.h                      | 5 -----
 include/configs/sun5i.h                       | 4 ----
 include/configs/sun6i.h                       | 4 ----
 include/configs/sun7i.h                       | 4 ----
 include/configs/sun8i.h                       | 4 ----
 include/configs/sunxi-common.h                | 1 -
 97 files changed, 91 insertions(+), 26 deletions(-)

diff --git a/configs/A10-OLinuXino-Lime_defconfig b/configs/A10-OLinuXino-Lime_defconfig
index 55134a9002..9b8891eed5 100644
--- a/configs/A10-OLinuXino-Lime_defconfig
+++ b/configs/A10-OLinuXino-Lime_defconfig
@@ -22,5 +22,6 @@ CONFIG_SUN4I_EMAC=y
 CONFIG_AXP_ALDO3_VOLT=2800
 CONFIG_AXP_ALDO4_VOLT=2800
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/A10s-OLinuXino-M_defconfig b/configs/A10s-OLinuXino-M_defconfig
index d0fb4d7860..fcf4890c3a 100644
--- a/configs/A10s-OLinuXino-M_defconfig
+++ b/configs/A10s-OLinuXino-M_defconfig
@@ -18,5 +18,6 @@ CONFIG_MII=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_AXP152_POWER=y
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/A13-OLinuXinoM_defconfig b/configs/A13-OLinuXinoM_defconfig
index 88374551e3..aedb0c3f0a 100644
--- a/configs/A13-OLinuXinoM_defconfig
+++ b/configs/A13-OLinuXinoM_defconfig
@@ -19,5 +19,6 @@ CONFIG_NR_DRAM_BANKS=1
 CONFIG_DEFAULT_DEVICE_TREE="sun5i-a13-olinuxino-micro"
 CONFIG_SUNXI_NO_PMIC=y
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/A13-OLinuXino_defconfig b/configs/A13-OLinuXino_defconfig
index 7b836ddf9c..eb76bf8fea 100644
--- a/configs/A13-OLinuXino_defconfig
+++ b/configs/A13-OLinuXino_defconfig
@@ -26,6 +26,7 @@ CONFIG_DFU_RAM=y
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_AXP_ALDO3_VOLT=3300
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/A20-OLinuXino-Lime2-eMMC_defconfig b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
index dee8d028ee..41aed6edd9 100644
--- a/configs/A20-OLinuXino-Lime2-eMMC_defconfig
+++ b/configs/A20-OLinuXino-Lime2-eMMC_defconfig
@@ -31,6 +31,7 @@ CONFIG_AXP_ALDO3_VOLT=2800
 CONFIG_AXP_ALDO3_VOLT_SLOPE_08=y
 CONFIG_AXP_ALDO4_VOLT=2800
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/A20-OLinuXino-Lime2_defconfig b/configs/A20-OLinuXino-Lime2_defconfig
index 0c04ae6491..e54049087a 100644
--- a/configs/A20-OLinuXino-Lime2_defconfig
+++ b/configs/A20-OLinuXino-Lime2_defconfig
@@ -30,6 +30,7 @@ CONFIG_AXP_ALDO3_VOLT=2800
 CONFIG_AXP_ALDO3_VOLT_SLOPE_08=y
 CONFIG_AXP_ALDO4_VOLT=2800
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/A20-OLinuXino-Lime_defconfig b/configs/A20-OLinuXino-Lime_defconfig
index 91f5210762..9e13792f1a 100644
--- a/configs/A20-OLinuXino-Lime_defconfig
+++ b/configs/A20-OLinuXino-Lime_defconfig
@@ -21,5 +21,6 @@ CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO3_VOLT=2800
 CONFIG_AXP_ALDO4_VOLT=2800
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/A20-Olimex-SOM204-EVB_defconfig b/configs/A20-Olimex-SOM204-EVB_defconfig
index 1181832b2e..e853c9301c 100644
--- a/configs/A20-Olimex-SOM204-EVB_defconfig
+++ b/configs/A20-Olimex-SOM204-EVB_defconfig
@@ -29,6 +29,7 @@ CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO3_VOLT=2800
 CONFIG_AXP_ALDO4_VOLT=2800
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Auxtek-T003_defconfig b/configs/Auxtek-T003_defconfig
index a693cfdd41..c2a681c569 100644
--- a/configs/Auxtek-T003_defconfig
+++ b/configs/Auxtek-T003_defconfig
@@ -15,5 +15,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-auxtek-t003"
 CONFIG_AXP152_POWER=y
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Auxtek-T004_defconfig b/configs/Auxtek-T004_defconfig
index 5c88b2bec0..bc5fc8cee8 100644
--- a/configs/Auxtek-T004_defconfig
+++ b/configs/Auxtek-T004_defconfig
@@ -13,5 +13,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-auxtek-t004"
 CONFIG_AXP152_POWER=y
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Bananapi_defconfig b/configs/Bananapi_defconfig
index 41cb9fc225..67daec6d7f 100644
--- a/configs/Bananapi_defconfig
+++ b/configs/Bananapi_defconfig
@@ -21,5 +21,6 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Bananapi_m2m_defconfig b/configs/Bananapi_m2m_defconfig
index 990c791b76..c8dfa7d51f 100644
--- a/configs/Bananapi_m2m_defconfig
+++ b/configs/Bananapi_m2m_defconfig
@@ -15,6 +15,7 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_PARTITION_UUIDS is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-r16-bananapi-m2m"
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_FUNCTION_MASS_STORAGE=y
diff --git a/configs/Bananapro_defconfig b/configs/Bananapro_defconfig
index 41fc6a6eee..cd5d8b6cdd 100644
--- a/configs/Bananapro_defconfig
+++ b/configs/Bananapro_defconfig
@@ -24,5 +24,6 @@ CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO4_VOLT=2500
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/CHIP_defconfig b/configs/CHIP_defconfig
index ffdffcdb06..67fe58b21f 100644
--- a/configs/CHIP_defconfig
+++ b/configs/CHIP_defconfig
@@ -17,6 +17,7 @@ CONFIG_DFU_RAM=y
 CONFIG_AXP_ALDO3_VOLT=3300
 CONFIG_AXP_ALDO4_VOLT=3300
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/CHIP_pro_defconfig b/configs/CHIP_pro_defconfig
index c607adb65b..618f113ff6 100644
--- a/configs/CHIP_pro_defconfig
+++ b/configs/CHIP_pro_defconfig
@@ -22,6 +22,7 @@ CONFIG_SYS_NAND_OOBSIZE=0x100
 CONFIG_AXP_ALDO3_VOLT=3300
 CONFIG_AXP_ALDO4_VOLT=3300
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/CSQ_CS908_defconfig b/configs/CSQ_CS908_defconfig
index ffc64d6aa4..9036ffc96a 100644
--- a/configs/CSQ_CS908_defconfig
+++ b/configs/CSQ_CS908_defconfig
@@ -16,6 +16,7 @@ CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO1_VOLT=3300
 CONFIG_AXP_DLDO1_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Colombus_defconfig b/configs/Colombus_defconfig
index 77c7e9ee29..cb65647c7a 100644
--- a/configs/Colombus_defconfig
+++ b/configs/Colombus_defconfig
@@ -26,5 +26,6 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO1_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Cubieboard2_defconfig b/configs/Cubieboard2_defconfig
index 366f55b815..7fe5b83fa2 100644
--- a/configs/Cubieboard2_defconfig
+++ b/configs/Cubieboard2_defconfig
@@ -18,5 +18,6 @@ CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Cubieboard_defconfig b/configs/Cubieboard_defconfig
index efc3e2567a..ccb612a9c7 100644
--- a/configs/Cubieboard_defconfig
+++ b/configs/Cubieboard_defconfig
@@ -17,5 +17,6 @@ CONFIG_SCSI_AHCI=y
 CONFIG_MII=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Cubietruck_plus_defconfig b/configs/Cubietruck_plus_defconfig
index 2f43bbd947..cecb428b02 100644
--- a/configs/Cubietruck_plus_defconfig
+++ b/configs/Cubietruck_plus_defconfig
@@ -23,6 +23,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-cubietruck-plus"
 CONFIG_AXP_DLDO3_VOLT=2500
 CONFIG_AXP_DLDO4_VOLT=3300
 CONFIG_AXP_FLDO1_VOLT=1200
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Hummingbird_A31_defconfig b/configs/Hummingbird_A31_defconfig
index b3e9d0a530..0f0b1c2251 100644
--- a/configs/Hummingbird_A31_defconfig
+++ b/configs/Hummingbird_A31_defconfig
@@ -18,5 +18,6 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO1_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Itead_Ibox_A20_defconfig b/configs/Itead_Ibox_A20_defconfig
index 721bc87677..784c4de384 100644
--- a/configs/Itead_Ibox_A20_defconfig
+++ b/configs/Itead_Ibox_A20_defconfig
@@ -18,5 +18,6 @@ CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Linksprite_pcDuino3_Nano_defconfig b/configs/Linksprite_pcDuino3_Nano_defconfig
index 09aae78205..72d9b03929 100644
--- a/configs/Linksprite_pcDuino3_Nano_defconfig
+++ b/configs/Linksprite_pcDuino3_Nano_defconfig
@@ -21,5 +21,6 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Linksprite_pcDuino3_defconfig b/configs/Linksprite_pcDuino3_defconfig
index 00a49d1077..9156f132d1 100644
--- a/configs/Linksprite_pcDuino3_defconfig
+++ b/configs/Linksprite_pcDuino3_defconfig
@@ -20,5 +20,6 @@ CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
 CONFIG_DM_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Linksprite_pcDuino_defconfig b/configs/Linksprite_pcDuino_defconfig
index 81dbb72c75..21cfea133d 100644
--- a/configs/Linksprite_pcDuino_defconfig
+++ b/configs/Linksprite_pcDuino_defconfig
@@ -13,5 +13,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-pcduino"
 CONFIG_MII=y
 CONFIG_SUN4I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/MK808C_defconfig b/configs/MK808C_defconfig
index f634ac894a..367a164554 100644
--- a/configs/MK808C_defconfig
+++ b/configs/MK808C_defconfig
@@ -10,5 +10,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-mk808c"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Marsboard_A10_defconfig b/configs/Marsboard_A10_defconfig
index ae7c26615f..c40e452aa4 100644
--- a/configs/Marsboard_A10_defconfig
+++ b/configs/Marsboard_A10_defconfig
@@ -14,5 +14,6 @@ CONFIG_MII=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_SUNXI_NO_PMIC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Mele_A1000G_quad_defconfig b/configs/Mele_A1000G_quad_defconfig
index a2c613521e..feabbbf244 100644
--- a/configs/Mele_A1000G_quad_defconfig
+++ b/configs/Mele_A1000G_quad_defconfig
@@ -19,6 +19,7 @@ CONFIG_AXP_DCDC1_VOLT=3300
 CONFIG_AXP_ALDO1_VOLT=3300
 CONFIG_AXP_DLDO1_VOLT=3300
 CONFIG_AXP_DLDO4_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Mele_A1000_defconfig b/configs/Mele_A1000_defconfig
index 49672092e2..9375c5d424 100644
--- a/configs/Mele_A1000_defconfig
+++ b/configs/Mele_A1000_defconfig
@@ -17,5 +17,6 @@ CONFIG_SCSI_AHCI=y
 CONFIG_MII=y
 CONFIG_SUN4I_EMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Mele_I7_defconfig b/configs/Mele_I7_defconfig
index aac4fa12b2..eecf89b76e 100644
--- a/configs/Mele_I7_defconfig
+++ b/configs/Mele_I7_defconfig
@@ -18,5 +18,6 @@ CONFIG_AXP_DCDC1_VOLT=3300
 CONFIG_AXP_ALDO1_VOLT=3300
 CONFIG_AXP_DLDO1_VOLT=3300
 CONFIG_AXP_DLDO4_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Mele_M3_defconfig b/configs/Mele_M3_defconfig
index acd98bc960..9738f8ba81 100644
--- a/configs/Mele_M3_defconfig
+++ b/configs/Mele_M3_defconfig
@@ -17,5 +17,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-m3"
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Mele_M5_defconfig b/configs/Mele_M5_defconfig
index e473da772e..c76bc9f91f 100644
--- a/configs/Mele_M5_defconfig
+++ b/configs/Mele_M5_defconfig
@@ -19,5 +19,6 @@ CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Mele_M9_defconfig b/configs/Mele_M9_defconfig
index 63bf3fd5b2..d3136c67cb 100644
--- a/configs/Mele_M9_defconfig
+++ b/configs/Mele_M9_defconfig
@@ -18,5 +18,6 @@ CONFIG_AXP_DCDC1_VOLT=3300
 CONFIG_AXP_ALDO1_VOLT=3300
 CONFIG_AXP_DLDO1_VOLT=3300
 CONFIG_AXP_DLDO4_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Mini-X_defconfig b/configs/Mini-X_defconfig
index 161feea519..54b40d5696 100644
--- a/configs/Mini-X_defconfig
+++ b/configs/Mini-X_defconfig
@@ -12,5 +12,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-mini-xplus"
 CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Orangepi_defconfig b/configs/Orangepi_defconfig
index 3ea1d03d96..dae821a8d2 100644
--- a/configs/Orangepi_defconfig
+++ b/configs/Orangepi_defconfig
@@ -23,5 +23,6 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Orangepi_mini_defconfig b/configs/Orangepi_mini_defconfig
index 737c7a958e..e1cbbbd4e9 100644
--- a/configs/Orangepi_mini_defconfig
+++ b/configs/Orangepi_mini_defconfig
@@ -25,5 +25,6 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Sinlinx_SinA31s_defconfig b/configs/Sinlinx_SinA31s_defconfig
index dbc8c08e57..efa3b86b1f 100644
--- a/configs/Sinlinx_SinA31s_defconfig
+++ b/configs/Sinlinx_SinA31s_defconfig
@@ -19,5 +19,6 @@ CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_DLDO1_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Sinlinx_SinA33_defconfig b/configs/Sinlinx_SinA33_defconfig
index df078c4b64..b92d62117c 100644
--- a/configs/Sinlinx_SinA33_defconfig
+++ b/configs/Sinlinx_SinA33_defconfig
@@ -20,6 +20,7 @@ CONFIG_CMD_DFU=y
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a33-sinlinx-sina33"
 CONFIG_DFU_RAM=y
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Sinovoip_BPI_M2_Plus_defconfig b/configs/Sinovoip_BPI_M2_Plus_defconfig
index 35c4718e2d..c2025ee0a4 100644
--- a/configs/Sinovoip_BPI_M2_Plus_defconfig
+++ b/configs/Sinovoip_BPI_M2_Plus_defconfig
@@ -14,6 +14,7 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-bananapi-m2-plus"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Sinovoip_BPI_M2_defconfig b/configs/Sinovoip_BPI_M2_defconfig
index 83ef4b4dce..fd69ac5170 100644
--- a/configs/Sinovoip_BPI_M2_defconfig
+++ b/configs/Sinovoip_BPI_M2_defconfig
@@ -18,5 +18,6 @@ CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO1_VOLT=3300
 CONFIG_AXP_ALDO2_VOLT=1800
 CONFIG_AXP_DLDO1_VOLT=3000
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Sinovoip_BPI_M3_defconfig b/configs/Sinovoip_BPI_M3_defconfig
index 9f04731543..ec59feb4e4 100644
--- a/configs/Sinovoip_BPI_M3_defconfig
+++ b/configs/Sinovoip_BPI_M3_defconfig
@@ -24,6 +24,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-bananapi-m3"
 CONFIG_AXP_DCDC5_VOLT=1200
 CONFIG_AXP_DLDO3_VOLT=2500
 CONFIG_AXP_SW_ON=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Wexler_TAB7200_defconfig b/configs/Wexler_TAB7200_defconfig
index 58c65b72bb..a2351dc925 100644
--- a/configs/Wexler_TAB7200_defconfig
+++ b/configs/Wexler_TAB7200_defconfig
@@ -18,6 +18,7 @@ CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-wexler-tab7200"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/Wobo_i5_defconfig b/configs/Wobo_i5_defconfig
index a0dca6aa67..17f03c8579 100644
--- a/configs/Wobo_i5_defconfig
+++ b/configs/Wobo_i5_defconfig
@@ -15,5 +15,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-wobo-i5"
 CONFIG_AXP_ALDO3_VOLT=3300
 CONFIG_AXP_ALDO4_VOLT=3300
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/a64-olinuxino_defconfig b/configs/a64-olinuxino_defconfig
index 01fcb86599..94ac94c6ab 100644
--- a/configs/a64-olinuxino_defconfig
+++ b/configs/a64-olinuxino_defconfig
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-olinuxino"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/ba10_tv_box_defconfig b/configs/ba10_tv_box_defconfig
index 846fab2f5f..76a980e60f 100644
--- a/configs/ba10_tv_box_defconfig
+++ b/configs/ba10_tv_box_defconfig
@@ -16,6 +16,7 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-ba10-tvbox"
 CONFIG_MII=y
 CONFIG_SUN4I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/bananapi_m1_plus_defconfig b/configs/bananapi_m1_plus_defconfig
index 7286d2160b..46baf346c5 100644
--- a/configs/bananapi_m1_plus_defconfig
+++ b/configs/bananapi_m1_plus_defconfig
@@ -21,4 +21,5 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_SCSI=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/bananapi_m64_defconfig b/configs/bananapi_m64_defconfig
index aa0ad3c5f4..7dc768ff9f 100644
--- a/configs/bananapi_m64_defconfig
+++ b/configs/bananapi_m64_defconfig
@@ -12,6 +12,7 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/ga10h_v1_1_defconfig b/configs/ga10h_v1_1_defconfig
index 4c88285e24..0049982407 100644
--- a/configs/ga10h_v1_1_defconfig
+++ b/configs/ga10h_v1_1_defconfig
@@ -23,6 +23,7 @@ CONFIG_NR_DRAM_BANKS=1
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a33-ga10h-v1.1"
 CONFIG_AXP_DLDO1_VOLT=3300
 CONFIG_CONS_INDEX=5
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/h8_homlet_v2_defconfig b/configs/h8_homlet_v2_defconfig
index 7aad6f0cdf..6e1cc00357 100644
--- a/configs/h8_homlet_v2_defconfig
+++ b/configs/h8_homlet_v2_defconfig
@@ -16,6 +16,7 @@ CONFIG_CONSOLE_MUX=y
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-allwinner-h8homlet-v2"
 CONFIG_AXP_DLDO4_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/i12-tvbox_defconfig b/configs/i12-tvbox_defconfig
index 4b3a8a3d50..fea490d74d 100644
--- a/configs/i12-tvbox_defconfig
+++ b/configs/i12-tvbox_defconfig
@@ -15,5 +15,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-i12-tvbox"
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/icnova-a20-swac_defconfig b/configs/icnova-a20-swac_defconfig
index 07c89a41e7..99cc7e889f 100644
--- a/configs/icnova-a20-swac_defconfig
+++ b/configs/icnova-a20-swac_defconfig
@@ -22,5 +22,6 @@ CONFIG_DEFAULT_DEVICE_TREE="sun7i-a20-icnova-swac"
 CONFIG_ETH_DESIGNWARE=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/inet1_defconfig b/configs/inet1_defconfig
index 79e594bc15..b5b94d9c95 100644
--- a/configs/inet1_defconfig
+++ b/configs/inet1_defconfig
@@ -19,6 +19,7 @@ CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-inet1"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/inet_q972_defconfig b/configs/inet_q972_defconfig
index d15f71ae7a..7f3d04db6d 100644
--- a/configs/inet_q972_defconfig
+++ b/configs/inet_q972_defconfig
@@ -20,6 +20,7 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun6i-a31s-inet-q972"
 CONFIG_AXP_DLDO1_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/jesurun_q5_defconfig b/configs/jesurun_q5_defconfig
index ce485376f3..e6f90c09f2 100644
--- a/configs/jesurun_q5_defconfig
+++ b/configs/jesurun_q5_defconfig
@@ -15,6 +15,7 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-jesurun-q5"
 CONFIG_MII=y
 CONFIG_SUN4I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_HOST=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/libretech_all_h3_cc_h2_plus_defconfig b/configs/libretech_all_h3_cc_h2_plus_defconfig
index 2c7a3ff9ef..9c2e28f1e8 100644
--- a/configs/libretech_all_h3_cc_h2_plus_defconfig
+++ b/configs/libretech_all_h3_cc_h2_plus_defconfig
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-libretech-all-h3-cc"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/libretech_all_h3_cc_h3_defconfig b/configs/libretech_all_h3_cc_h3_defconfig
index bd2c7083b0..9130a5980b 100644
--- a/configs/libretech_all_h3_cc_h3_defconfig
+++ b/configs/libretech_all_h3_cc_h3_defconfig
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-libretech-all-h3-cc"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/libretech_all_h3_cc_h5_defconfig b/configs/libretech_all_h3_cc_h5_defconfig
index 001f53d0fe..eb0d5dc7af 100644
--- a/configs/libretech_all_h3_cc_h5_defconfig
+++ b/configs/libretech_all_h3_cc_h5_defconfig
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-libretech-all-h3-cc"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/mixtile_loftq_defconfig b/configs/mixtile_loftq_defconfig
index 9ebb55c678..55d06497c9 100644
--- a/configs/mixtile_loftq_defconfig
+++ b/configs/mixtile_loftq_defconfig
@@ -18,5 +18,6 @@ CONFIG_RGMII=y
 CONFIG_MII=y
 CONFIG_SUN7I_GMAC=y
 CONFIG_AXP_ALDO1_VOLT=3300
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/mk802_a10s_defconfig b/configs/mk802_a10s_defconfig
index 3fba55e70f..5a0b502145 100644
--- a/configs/mk802_a10s_defconfig
+++ b/configs/mk802_a10s_defconfig
@@ -14,5 +14,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-mk802"
 CONFIG_AXP152_POWER=y
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/mk802_defconfig b/configs/mk802_defconfig
index 1b59348f94..14f8feee20 100644
--- a/configs/mk802_defconfig
+++ b/configs/mk802_defconfig
@@ -10,5 +10,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-mk802"
 CONFIG_SUNXI_NO_PMIC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/mk802ii_defconfig b/configs/mk802ii_defconfig
index 7a3f3d1f74..abd261db2f 100644
--- a/configs/mk802ii_defconfig
+++ b/configs/mk802ii_defconfig
@@ -9,5 +9,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-mk802ii"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/nanopi_a64_defconfig b/configs/nanopi_a64_defconfig
index cd3b59f2dc..4dfd36ee3c 100644
--- a/configs/nanopi_a64_defconfig
+++ b/configs/nanopi_a64_defconfig
@@ -10,5 +10,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-nanopi-a64"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/nanopi_m1_defconfig b/configs/nanopi_m1_defconfig
index bf4e874b12..c8efce81e4 100644
--- a/configs/nanopi_m1_defconfig
+++ b/configs/nanopi_m1_defconfig
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/nanopi_m1_plus_defconfig b/configs/nanopi_m1_plus_defconfig
index 66e90916f7..79b1c6913e 100644
--- a/configs/nanopi_m1_plus_defconfig
+++ b/configs/nanopi_m1_plus_defconfig
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-m1-plus"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/nanopi_neo2_defconfig b/configs/nanopi_neo2_defconfig
index ee693be1a8..8892f6cd83 100644
--- a/configs/nanopi_neo2_defconfig
+++ b/configs/nanopi_neo2_defconfig
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-nanopi-neo2"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/nanopi_neo_air_defconfig b/configs/nanopi_neo_air_defconfig
index 8c362fa885..149530416b 100644
--- a/configs/nanopi_neo_air_defconfig
+++ b/configs/nanopi_neo_air_defconfig
@@ -13,5 +13,6 @@ CONFIG_CONSOLE_MUX=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-neo-air"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/nanopi_neo_defconfig b/configs/nanopi_neo_defconfig
index ffb854b4b8..b963a28ecc 100644
--- a/configs/nanopi_neo_defconfig
+++ b/configs/nanopi_neo_defconfig
@@ -14,5 +14,6 @@ CONFIG_CONSOLE_MUX=y
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-nanopi-neo"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/nanopi_neo_plus2_defconfig b/configs/nanopi_neo_plus2_defconfig
index 331dc6a8f7..efb1737a75 100644
--- a/configs/nanopi_neo_plus2_defconfig
+++ b/configs/nanopi_neo_plus2_defconfig
@@ -13,4 +13,5 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-nanopi-neo-plus2"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/configs/orangepi_2_defconfig b/configs/orangepi_2_defconfig
index b86c0ab380..3ad13cb307 100644
--- a/configs/orangepi_2_defconfig
+++ b/configs/orangepi_2_defconfig
@@ -16,5 +16,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-2"
 CONFIG_SUN8I_EMAC=y
 CONFIG_SY8106A_POWER=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_lite_defconfig b/configs/orangepi_lite_defconfig
index de08a8a2c6..e30df9be26 100644
--- a/configs/orangepi_lite_defconfig
+++ b/configs/orangepi_lite_defconfig
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-lite"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_one_defconfig b/configs/orangepi_one_defconfig
index 003f2cc7cb..346a55f1d1 100644
--- a/configs/orangepi_one_defconfig
+++ b/configs/orangepi_one_defconfig
@@ -12,5 +12,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-one"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
index 7f7e6d3264..a74fedda3f 100644
--- a/configs/orangepi_pc2_defconfig
+++ b/configs/orangepi_pc2_defconfig
@@ -13,6 +13,7 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-pc2"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_pc_defconfig b/configs/orangepi_pc_defconfig
index fd41e1a45b..14fcb66113 100644
--- a/configs/orangepi_pc_defconfig
+++ b/configs/orangepi_pc_defconfig
@@ -14,5 +14,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-pc"
 CONFIG_SUN8I_EMAC=y
 CONFIG_SY8106A_POWER=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_pc_plus_defconfig b/configs/orangepi_pc_plus_defconfig
index 1f0bf73149..0e7b4d3b1b 100644
--- a/configs/orangepi_pc_plus_defconfig
+++ b/configs/orangepi_pc_plus_defconfig
@@ -15,5 +15,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-pc-plus"
 CONFIG_SUN8I_EMAC=y
 CONFIG_SY8106A_POWER=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_plus2e_defconfig b/configs/orangepi_plus2e_defconfig
index 9baccdef78..3e79c848c3 100644
--- a/configs/orangepi_plus2e_defconfig
+++ b/configs/orangepi_plus2e_defconfig
@@ -16,5 +16,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus2e"
 CONFIG_SUN8I_EMAC=y
 CONFIG_SY8106A_POWER=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_plus_defconfig b/configs/orangepi_plus_defconfig
index 0588799b59..26bd9c439a 100644
--- a/configs/orangepi_plus_defconfig
+++ b/configs/orangepi_plus_defconfig
@@ -18,5 +18,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h3-orangepi-plus"
 CONFIG_SUN8I_EMAC=y
 CONFIG_SY8106A_POWER=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_prime_defconfig b/configs/orangepi_prime_defconfig
index 7e10ebe796..d2429b767b 100644
--- a/configs/orangepi_prime_defconfig
+++ b/configs/orangepi_prime_defconfig
@@ -11,6 +11,7 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-prime"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_r1_defconfig b/configs/orangepi_r1_defconfig
index f587bec2ec..cd3355153c 100644
--- a/configs/orangepi_r1_defconfig
+++ b/configs/orangepi_r1_defconfig
@@ -13,5 +13,6 @@ CONFIG_CONSOLE_MUX=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-orangepi-r1"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
index ab889ea8f5..78c55326c6 100644
--- a/configs/orangepi_win_defconfig
+++ b/configs/orangepi_win_defconfig
@@ -11,5 +11,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-orangepi-win"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig
index 0da9c65093..e5a4c1d9fc 100644
--- a/configs/orangepi_zero_defconfig
+++ b/configs/orangepi_zero_defconfig
@@ -13,5 +13,6 @@ CONFIG_CONSOLE_MUX=y
 # CONFIG_CMD_FLASH is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-h2-plus-orangepi-zero"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_zero_plus2_defconfig b/configs/orangepi_zero_plus2_defconfig
index 3c6ee03a53..7ae922774c 100644
--- a/configs/orangepi_zero_plus2_defconfig
+++ b/configs/orangepi_zero_plus2_defconfig
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-zero-plus2"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/orangepi_zero_plus_defconfig b/configs/orangepi_zero_plus_defconfig
index 5d783c5981..74133fa03b 100644
--- a/configs/orangepi_zero_plus_defconfig
+++ b/configs/orangepi_zero_plus_defconfig
@@ -13,5 +13,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-h5-orangepi-zero-plus"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/parrot_r16_defconfig b/configs/parrot_r16_defconfig
index a6071612c4..80c1bf1fbe 100644
--- a/configs/parrot_r16_defconfig
+++ b/configs/parrot_r16_defconfig
@@ -18,6 +18,7 @@ CONFIG_NR_DRAM_BANKS=1
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-r16-parrot"
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_CONS_INDEX=5
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig
index a5b87b9063..ded4d134f1 100644
--- a/configs/pine64_plus_defconfig
+++ b/configs/pine64_plus_defconfig
@@ -14,5 +14,6 @@ CONFIG_OF_LIST="sun50i-a64-pine64 sun50i-a64-pine64-plus"
 CONFIG_PHY_REALTEK=y
 CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/r7-tv-dongle_defconfig b/configs/r7-tv-dongle_defconfig
index 9c797c5512..d993b5d256 100644
--- a/configs/r7-tv-dongle_defconfig
+++ b/configs/r7-tv-dongle_defconfig
@@ -13,5 +13,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_DEFAULT_DEVICE_TREE="sun5i-a10s-r7-tv-dongle"
 CONFIG_AXP152_POWER=y
 CONFIG_CONS_INDEX=2
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index 9ede081c08..0a189fc03d 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -16,5 +16,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
 CONFIG_SUN8I_EMAC=y
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/sun8i_a23_evb_defconfig b/configs/sun8i_a23_evb_defconfig
index 70c4072e22..563275b65f 100644
--- a/configs/sun8i_a23_evb_defconfig
+++ b/configs/sun8i_a23_evb_defconfig
@@ -14,5 +14,6 @@ CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a23-evb"
 CONFIG_CONS_INDEX=5
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/sunxi_Gemei_G9_defconfig b/configs/sunxi_Gemei_G9_defconfig
index e07d7c7d9e..06a07df051 100644
--- a/configs/sunxi_Gemei_G9_defconfig
+++ b/configs/sunxi_Gemei_G9_defconfig
@@ -16,5 +16,6 @@ CONFIG_SPL_I2C_SUPPORT=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun4i-a10-gemei-g9"
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
diff --git a/configs/tbs_a711_defconfig b/configs/tbs_a711_defconfig
index b2bcf3be57..103ce9be46 100644
--- a/configs/tbs_a711_defconfig
+++ b/configs/tbs_a711_defconfig
@@ -19,6 +19,7 @@ CONFIG_NR_DRAM_BANKS=1
 CONFIG_DEFAULT_DEVICE_TREE="sun8i-a83t-tbs-a711"
 CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
 CONFIG_AXP_DCDC5_VOLT=1200
+CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_MUSB_GADGET=y
 CONFIG_USB_FUNCTION_MASS_STORAGE=y
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index a213c918bc..60f37f40fd 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -190,6 +190,7 @@ config USB_EHCI_GENERIC
 	bool "Support for generic EHCI USB controller"
 	depends on OF_CONTROL
 	depends on DM_USB
+	default ARCH_SUNXI
 	default n
 	---help---
 	  Enables support for generic EHCI controller.
@@ -220,6 +221,7 @@ config USB_OHCI_GENERIC
 	bool "Support for generic OHCI USB controller"
 	depends on OF_CONTROL
 	depends on DM_USB
+	default ARCH_SUNXI
 	select USB_HOST
 	---help---
 	  Enables support for generic OHCI controller.
diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h
index af079a71ee..6033760583 100644
--- a/include/configs/sun4i.h
+++ b/include/configs/sun4i.h
@@ -11,10 +11,6 @@
  * A10 specific configuration
  */
 
-#ifdef CONFIG_USB_EHCI_HCD
-#define CONFIG_USB_EHCI_SUNXI
-#endif
-
 /*
  * Include common sunxi configuration where most the settings are
  */
diff --git a/include/configs/sun50i.h b/include/configs/sun50i.h
index 2d73c75b8c..e050a5299f 100644
--- a/include/configs/sun50i.h
+++ b/include/configs/sun50i.h
@@ -10,11 +10,6 @@
  * A64 specific configuration
  */
 
-#ifdef CONFIG_USB_EHCI_HCD
-#define CONFIG_USB_EHCI_SUNXI
-#define CONFIG_USB_MAX_CONTROLLER_COUNT 1
-#endif
-
 #ifndef CONFIG_MACH_SUN50I_H6
 #define GICD_BASE		0x1c81000
 #define GICC_BASE		0x1c82000
diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h
index c3692caa73..ee42af80d4 100644
--- a/include/configs/sun5i.h
+++ b/include/configs/sun5i.h
@@ -11,10 +11,6 @@
  * High Level Configuration Options
  */
 
-#ifdef CONFIG_USB_EHCI_HCD
-#define CONFIG_USB_EHCI_SUNXI
-#endif
-
 /*
  * Include common sunxi configuration where most the settings are
  */
diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h
index 1523684fad..1e490daac1 100644
--- a/include/configs/sun6i.h
+++ b/include/configs/sun6i.h
@@ -14,10 +14,6 @@
  * A31 specific configuration
  */
 
-#ifdef CONFIG_USB_EHCI_HCD
-#define CONFIG_USB_EHCI_SUNXI
-#endif
-
 #define CONFIG_ARMV7_SECURE_BASE	SUNXI_SRAM_B_BASE
 #define CONFIG_ARMV7_SECURE_MAX_SIZE    (64 * 1024) /* 64 KB */
 
diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h
index bb8f217b25..d2fd586672 100644
--- a/include/configs/sun7i.h
+++ b/include/configs/sun7i.h
@@ -12,10 +12,6 @@
  * A20 specific configuration
  */
 
-#ifdef CONFIG_USB_EHCI_HCD
-#define CONFIG_USB_EHCI_SUNXI
-#endif
-
 #define CONFIG_ARMV7_SECURE_BASE	SUNXI_SRAM_B_BASE
 #define CONFIG_ARMV7_SECURE_MAX_SIZE	(64 * 1024) /* 64 KB */
 
diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h
index 7dc8693b76..9b4675e4c3 100644
--- a/include/configs/sun8i.h
+++ b/include/configs/sun8i.h
@@ -12,10 +12,6 @@
  * A23 specific configuration
  */
 
-#ifdef CONFIG_USB_EHCI_HCD
-#define CONFIG_USB_EHCI_SUNXI
-#endif
-
 /*
  * Include common sunxi configuration where most the settings are
  */
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index 9819d9980c..ed0cfc24f5 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -295,7 +295,6 @@ extern int soft_i2c_gpio_scl;
 
 #ifdef CONFIG_USB_EHCI_HCD
 #define CONFIG_USB_OHCI_NEW
-#define CONFIG_USB_OHCI_SUNXI
 #define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1
 #endif
 
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 21/26] usb: host: Drop [e-o]hci-sunxi drivers
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (19 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 20/26] sunxi: usb: Switch to Generic host controllers Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 22/26] clk: sunxi: Implement SPI clocks Jagan Teki
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Now Allwinner platform is all set to use Generic USB
controller drivers, so remove the legacy sunxi drivers.

Cc: Marek Vasut <marex@denx.de> 
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
---
 drivers/usb/host/Makefile     |   2 -
 drivers/usb/host/ehci-sunxi.c | 204 -----------------------------
 drivers/usb/host/ohci-sunxi.c | 233 ----------------------------------
 scripts/config_whitelist.txt  |   2 -
 4 files changed, 441 deletions(-)
 delete mode 100644 drivers/usb/host/ehci-sunxi.c
 delete mode 100644 drivers/usb/host/ohci-sunxi.c

diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 948683a52b..6aa574f6f7 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -15,7 +15,6 @@ obj-$(CONFIG_USB_OHCI_DA8XX) += ohci-da8xx.o
 obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o
 obj-$(CONFIG_USB_SL811HS) += sl811-hcd.o
 obj-$(CONFIG_USB_OHCI_EP93XX) += ohci-ep93xx.o
-obj-$(CONFIG_USB_OHCI_SUNXI) += ohci-sunxi.o
 obj-$(CONFIG_USB_OHCI_LPC32XX) += ohci-lpc32xx.o
 obj-$(CONFIG_USB_OHCI_GENERIC) += ohci-generic.o
 
@@ -37,7 +36,6 @@ obj-$(CONFIG_USB_EHCI_MARVELL) += ehci-marvell.o
 obj-$(CONFIG_USB_EHCI_MSM) += ehci-msm.o
 obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o
 obj-$(CONFIG_USB_EHCI_SPEAR) += ehci-spear.o
-obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o
 obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o
 obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
 obj-$(CONFIG_USB_EHCI_VF) += ehci-vf.o
diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c
deleted file mode 100644
index 7a79931a97..0000000000
--- a/drivers/usb/host/ehci-sunxi.c
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Sunxi ehci glue
- *
- * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
- * Copyright (C) 2014 Roman Byshko <rbyshko@gmail.com>
- *
- * Based on code from
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- */
-
-#include <common.h>
-#include <asm/arch/clock.h>
-#include <asm/io.h>
-#include <dm.h>
-#include "ehci.h"
-#include <generic-phy.h>
-
-#ifdef CONFIG_SUNXI_GEN_SUN4I
-#define BASE_DIST		0x8000
-#define AHB_CLK_DIST		2
-#else
-#define BASE_DIST		0x1000
-#define AHB_CLK_DIST		1
-#endif
-
-#define SUN6I_AHB_RESET0_CFG_OFFSET 0x2c0
-#define SUN9I_AHB_RESET0_CFG_OFFSET 0x5a0
-
-struct ehci_sunxi_cfg {
-	bool has_reset;
-	u32 extra_ahb_gate_mask;
-	u32 reset0_cfg_offset;
-};
-
-struct ehci_sunxi_priv {
-	struct ehci_ctrl ehci;
-	struct sunxi_ccm_reg *ccm;
-	u32 *reset0_cfg;
-	int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
-	struct phy phy;
-	const struct ehci_sunxi_cfg *cfg;
-};
-
-static int ehci_usb_probe(struct udevice *dev)
-{
-	struct usb_platdata *plat = dev_get_platdata(dev);
-	struct ehci_sunxi_priv *priv = dev_get_priv(dev);
-	struct ehci_hccr *hccr = (struct ehci_hccr *)devfdt_get_addr(dev);
-	struct ehci_hcor *hcor;
-	int extra_ahb_gate_mask = 0;
-	u8 reg_mask = 0;
-	int phys, ret;
-
-	priv->cfg = (const struct ehci_sunxi_cfg *)dev_get_driver_data(dev);
-	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	if (IS_ERR(priv->ccm))
-		return PTR_ERR(priv->ccm);
-
-	priv->reset0_cfg = (void *)priv->ccm +
-				   priv->cfg->reset0_cfg_offset;
-
-	phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
-	if (phys < 0) {
-		phys = 0;
-		goto no_phy;
-	}
-
-	ret = generic_phy_get_by_name(dev, "usb", &priv->phy);
-	if (ret) {
-		pr_err("failed to get %s usb PHY\n", dev->name);
-		return ret;
-	}
-
-	ret = generic_phy_init(&priv->phy);
-	if (ret) {
-		pr_err("failed to init %s USB PHY\n", dev->name);
-		return ret;
-	}
-
-	ret = generic_phy_power_on(&priv->phy);
-	if (ret) {
-		pr_err("failed to power on %s USB PHY\n", dev->name);
-		return ret;
-	}
-
-no_phy:
-	/*
-	 * This should go away once we've moved to the driver model for
-	 * clocks resp. phys.
-	 */
-	reg_mask = ((uintptr_t)hccr - SUNXI_USB1_BASE) / BASE_DIST;
-	priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0;
-	extra_ahb_gate_mask = priv->cfg->extra_ahb_gate_mask;
-	priv->ahb_gate_mask <<= reg_mask * AHB_CLK_DIST;
-	extra_ahb_gate_mask <<= reg_mask * AHB_CLK_DIST;
-
-	setbits_le32(&priv->ccm->ahb_gate0,
-		     priv->ahb_gate_mask | extra_ahb_gate_mask);
-	if (priv->cfg->has_reset)
-		setbits_le32(priv->reset0_cfg,
-			     priv->ahb_gate_mask | extra_ahb_gate_mask);
-
-	hcor = (struct ehci_hcor *)((uintptr_t)hccr +
-				    HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
-
-	return ehci_register(dev, hccr, hcor, NULL, 0, plat->init_type);
-}
-
-static int ehci_usb_remove(struct udevice *dev)
-{
-	struct ehci_sunxi_priv *priv = dev_get_priv(dev);
-	int ret;
-
-	if (generic_phy_valid(&priv->phy)) {
-		ret = generic_phy_exit(&priv->phy);
-		if (ret) {
-			pr_err("failed to exit %s USB PHY\n", dev->name);
-			return ret;
-		}
-	}
-
-	ret = ehci_deregister(dev);
-	if (ret)
-		return ret;
-
-	if (priv->cfg->has_reset)
-		clrbits_le32(priv->reset0_cfg, priv->ahb_gate_mask);
-	clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask);
-
-	return 0;
-}
-
-static const struct ehci_sunxi_cfg sun4i_a10_cfg = {
-	.has_reset = false,
-};
-
-static const struct ehci_sunxi_cfg sun6i_a31_cfg = {
-	.has_reset = true,
-	.reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET,
-};
-
-static const struct ehci_sunxi_cfg sun8i_h3_cfg = {
-	.has_reset = true,
-	.extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0,
-	.reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET,
-};
-
-static const struct ehci_sunxi_cfg sun9i_a80_cfg = {
-	.has_reset = true,
-	.reset0_cfg_offset = SUN9I_AHB_RESET0_CFG_OFFSET,
-};
-
-static const struct udevice_id ehci_usb_ids[] = {
-	{
-		.compatible = "allwinner,sun4i-a10-ehci",
-		.data = (ulong)&sun4i_a10_cfg,
-	},
-	{
-		.compatible = "allwinner,sun5i-a13-ehci",
-		.data = (ulong)&sun4i_a10_cfg,
-	},
-	{
-		.compatible = "allwinner,sun6i-a31-ehci",
-		.data = (ulong)&sun6i_a31_cfg,
-	},
-	{
-		.compatible = "allwinner,sun7i-a20-ehci",
-		.data = (ulong)&sun4i_a10_cfg,
-	},
-	{
-		.compatible = "allwinner,sun8i-a23-ehci",
-		.data = (ulong)&sun6i_a31_cfg,
-	},
-	{
-		.compatible = "allwinner,sun8i-a83t-ehci",
-		.data = (ulong)&sun6i_a31_cfg,
-	},
-	{
-		.compatible = "allwinner,sun8i-h3-ehci",
-		.data = (ulong)&sun8i_h3_cfg,
-	},
-	{
-		.compatible = "allwinner,sun9i-a80-ehci",
-		.data = (ulong)&sun9i_a80_cfg,
-	},
-	{
-		.compatible = "allwinner,sun50i-a64-ehci",
-		.data = (ulong)&sun8i_h3_cfg,
-	},
-	{ /* sentinel */ }
-};
-
-U_BOOT_DRIVER(ehci_sunxi) = {
-	.name	= "ehci_sunxi",
-	.id	= UCLASS_USB,
-	.of_match = ehci_usb_ids,
-	.probe = ehci_usb_probe,
-	.remove = ehci_usb_remove,
-	.ops	= &ehci_usb_ops,
-	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
-	.priv_auto_alloc_size = sizeof(struct ehci_sunxi_priv),
-	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
-};
diff --git a/drivers/usb/host/ohci-sunxi.c b/drivers/usb/host/ohci-sunxi.c
deleted file mode 100644
index bb3c2475df..0000000000
--- a/drivers/usb/host/ohci-sunxi.c
+++ /dev/null
@@ -1,233 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Sunxi ohci glue
- *
- * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
- *
- * Based on code from
- * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
- */
-
-#include <common.h>
-#include <asm/arch/clock.h>
-#include <asm/io.h>
-#include <dm.h>
-#include <usb.h>
-#include "ohci.h"
-#include <generic-phy.h>
-
-#ifdef CONFIG_SUNXI_GEN_SUN4I
-#define BASE_DIST		0x8000
-#define AHB_CLK_DIST		2
-#else
-#define BASE_DIST		0x1000
-#define AHB_CLK_DIST		1
-#endif
-
-#define SUN6I_AHB_RESET0_CFG_OFFSET 0x2c0
-#define SUN9I_AHB_RESET0_CFG_OFFSET 0x5a0
-
-struct ohci_sunxi_cfg {
-	bool has_reset;
-	u32 extra_ahb_gate_mask;
-	u32 extra_usb_gate_mask;
-	u32 reset0_cfg_offset;
-};
-
-struct ohci_sunxi_priv {
-	ohci_t ohci;
-	struct sunxi_ccm_reg *ccm;
-	u32 *reset0_cfg;
-	int ahb_gate_mask; /* Mask of ahb_gate0 clk gate bits for this hcd */
-	int usb_gate_mask; /* Mask of usb_clk_cfg clk gate bits for this hcd */
-	struct phy phy;
-	const struct ohci_sunxi_cfg *cfg;
-};
-
-static fdt_addr_t last_ohci_addr = 0;
-
-static int ohci_usb_probe(struct udevice *dev)
-{
-	struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev);
-	struct ohci_sunxi_priv *priv = dev_get_priv(dev);
-	struct ohci_regs *regs = (struct ohci_regs *)devfdt_get_addr(dev);
-	int extra_ahb_gate_mask = 0;
-	u8 reg_mask = 0;
-	int phys, ret;
-
-	if ((fdt_addr_t)regs > last_ohci_addr)
-		last_ohci_addr = (fdt_addr_t)regs;
-
-	priv->cfg = (const struct ohci_sunxi_cfg *)dev_get_driver_data(dev);
-	priv->ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
-	if (IS_ERR(priv->ccm))
-		return PTR_ERR(priv->ccm);
-
-	priv->reset0_cfg = (void *)priv->ccm +
-				   priv->cfg->reset0_cfg_offset;
-
-	phys = dev_count_phandle_with_args(dev, "phys", "#phy-cells");
-	if (phys < 0) {
-		phys = 0;
-		goto no_phy;
-	}
-
-	ret = generic_phy_get_by_name(dev, "usb", &priv->phy);
-	if (ret) {
-		pr_err("failed to get %s usb PHY\n", dev->name);
-		return ret;
-	}
-
-	ret = generic_phy_init(&priv->phy);
-	if (ret) {
-		pr_err("failed to init %s USB PHY\n", dev->name);
-		return ret;
-	}
-
-	ret = generic_phy_power_on(&priv->phy);
-	if (ret) {
-		pr_err("failed to power on %s USB PHY\n", dev->name);
-		return ret;
-	}
-
-no_phy:
-	bus_priv->companion = true;
-
-	/*
-	 * This should go away once we've moved to the driver model for
-	 * clocks resp. phys.
-	 */
-	reg_mask = ((uintptr_t)regs - (SUNXI_USB1_BASE + 0x400)) / BASE_DIST;
-	priv->ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_OHCI0;
-	extra_ahb_gate_mask = priv->cfg->extra_ahb_gate_mask;
-	priv->usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK;
-	priv->ahb_gate_mask <<= reg_mask * AHB_CLK_DIST;
-	extra_ahb_gate_mask <<= reg_mask * AHB_CLK_DIST;
-	priv->usb_gate_mask <<= reg_mask;
-
-	setbits_le32(&priv->ccm->ahb_gate0,
-		     priv->ahb_gate_mask | extra_ahb_gate_mask);
-	setbits_le32(&priv->ccm->usb_clk_cfg,
-		     priv->usb_gate_mask | priv->cfg->extra_usb_gate_mask);
-	if (priv->cfg->has_reset)
-		setbits_le32(priv->reset0_cfg,
-			     priv->ahb_gate_mask | extra_ahb_gate_mask);
-
-	return ohci_register(dev, regs);
-}
-
-static int ohci_usb_remove(struct udevice *dev)
-{
-	struct ohci_sunxi_priv *priv = dev_get_priv(dev);
-	fdt_addr_t base_addr = devfdt_get_addr(dev);
-	int ret;
-
-	if (generic_phy_valid(&priv->phy)) {
-		ret = generic_phy_exit(&priv->phy);
-		if (ret) {
-			pr_err("failed to exit %s USB PHY\n", dev->name);
-			return ret;
-		}
-	}
-
-	ret = ohci_deregister(dev);
-	if (ret)
-		return ret;
-
-	if (priv->cfg->has_reset)
-		clrbits_le32(priv->reset0_cfg, priv->ahb_gate_mask);
-	/*
-	 * On the A64 CLK_USB_OHCI0 is the parent of CLK_USB_OHCI1, so
-	 * we have to wait with bringing down any clock until the last
-	 * OHCI controller is removed.
-	 */
-	if (!priv->cfg->extra_usb_gate_mask || base_addr == last_ohci_addr) {
-		u32 usb_gate_mask = priv->usb_gate_mask;
-
-		usb_gate_mask |= priv->cfg->extra_usb_gate_mask;
-		clrbits_le32(&priv->ccm->usb_clk_cfg, usb_gate_mask);
-	}
-
-	clrbits_le32(&priv->ccm->ahb_gate0, priv->ahb_gate_mask);
-
-	return 0;
-}
-
-static const struct ohci_sunxi_cfg sun4i_a10_cfg = {
-	.has_reset = false,
-};
-
-static const struct ohci_sunxi_cfg sun6i_a31_cfg = {
-	.has_reset = true,
-	.reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET,
-};
-
-static const struct ohci_sunxi_cfg sun8i_h3_cfg = {
-	.has_reset = true,
-	.extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0,
-	.reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET,
-};
-
-static const struct ohci_sunxi_cfg sun9i_a80_cfg = {
-	.has_reset = true,
-	.reset0_cfg_offset = SUN9I_AHB_RESET0_CFG_OFFSET,
-};
-
-static const struct ohci_sunxi_cfg sun50i_a64_cfg = {
-	.has_reset = true,
-	.extra_ahb_gate_mask = 1 << AHB_GATE_OFFSET_USB_EHCI0,
-	.extra_usb_gate_mask = CCM_USB_CTRL_OHCI0_CLK,
-	.reset0_cfg_offset = SUN6I_AHB_RESET0_CFG_OFFSET,
-};
-
-static const struct udevice_id ohci_usb_ids[] = {
-	{
-		.compatible = "allwinner,sun4i-a10-ohci",
-		.data = (ulong)&sun4i_a10_cfg,
-	},
-	{
-		.compatible = "allwinner,sun5i-a13-ohci",
-		.data = (ulong)&sun4i_a10_cfg,
-	},
-	{
-		.compatible = "allwinner,sun6i-a31-ohci",
-		.data = (ulong)&sun6i_a31_cfg,
-	},
-	{
-		.compatible = "allwinner,sun7i-a20-ohci",
-		.data = (ulong)&sun4i_a10_cfg,
-	},
-	{
-		.compatible = "allwinner,sun8i-a23-ohci",
-		.data = (ulong)&sun6i_a31_cfg,
-	},
-	{
-		.compatible = "allwinner,sun8i-a83t-ohci",
-		.data = (ulong)&sun6i_a31_cfg,
-	},
-	{
-		.compatible = "allwinner,sun8i-h3-ohci",
-		.data = (ulong)&sun8i_h3_cfg,
-	},
-	{
-		.compatible = "allwinner,sun9i-a80-ohci",
-		.data = (ulong)&sun9i_a80_cfg,
-	},
-	{
-		.compatible = "allwinner,sun50i-a64-ohci",
-		.data = (ulong)&sun50i_a64_cfg,
-	},
-	{ /* sentinel */ }
-};
-
-U_BOOT_DRIVER(usb_ohci) = {
-	.name	= "ohci_sunxi",
-	.id	= UCLASS_USB,
-	.of_match = ohci_usb_ids,
-	.probe = ohci_usb_probe,
-	.remove = ohci_usb_remove,
-	.ops	= &ohci_usb_ops,
-	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
-	.priv_auto_alloc_size = sizeof(struct ohci_sunxi_priv),
-	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
-};
diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index b8addeaf69..5ff10ee31e 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -4548,7 +4548,6 @@ CONFIG_USB_EHCI_MX5
 CONFIG_USB_EHCI_MXC
 CONFIG_USB_EHCI_MXS
 CONFIG_USB_EHCI_SPEAR
-CONFIG_USB_EHCI_SUNXI
 CONFIG_USB_EHCI_TEGRA
 CONFIG_USB_EHCI_TXFIFO_THRESH
 CONFIG_USB_EHCI_VCT
@@ -4587,7 +4586,6 @@ CONFIG_USB_MUSB_TUSB6010
 CONFIG_USB_OHCI_EP93XX
 CONFIG_USB_OHCI_LPC32XX
 CONFIG_USB_OHCI_NEW
-CONFIG_USB_OHCI_SUNXI
 CONFIG_USB_OTG
 CONFIG_USB_OTG_BLACKLIST_HUB
 CONFIG_USB_PHY_CFG_BASE
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 22/26] clk: sunxi: Implement SPI clocks
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (20 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 21/26] usb: host: Drop [e-o]hci-sunxi drivers Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 23/26] spi: sun4i: Add CLK support Jagan Teki
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Implement SPI AHB and MOD clocks for Allwinner A10/A20
and A10s/A13 SoC clock drivers via ccu clock gate table.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/clk/sunxi/clk_a10.c  | 9 +++++++++
 drivers/clk/sunxi/clk_a10s.c | 7 +++++++
 2 files changed, 16 insertions(+)

diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
index 1b074e3872..2b834856b3 100644
--- a/drivers/clk/sunxi/clk_a10.c
+++ b/drivers/clk/sunxi/clk_a10.c
@@ -18,6 +18,15 @@ static struct ccu_clk_gate a10_gates[] = {
 	[CLK_AHB_OHCI0]		= GATE(0x060, BIT(2)),
 	[CLK_AHB_EHCI1]		= GATE(0x060, BIT(3)),
 	[CLK_AHB_OHCI1]		= GATE(0x060, BIT(4)),
+	[CLK_AHB_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_AHB_SPI1]		= GATE(0x060, BIT(21)),
+	[CLK_AHB_SPI2]		= GATE(0x060, BIT(22)),
+	[CLK_AHB_SPI3]		= GATE(0x060, BIT(23)),
+
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
+	[CLK_SPI3]		= GATE(0x0d4, BIT(31)),
 
 	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
 	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
index a50c6e3f7f..0cc48ed2e8 100644
--- a/drivers/clk/sunxi/clk_a10s.c
+++ b/drivers/clk/sunxi/clk_a10s.c
@@ -16,6 +16,13 @@ static struct ccu_clk_gate a10s_gates[] = {
 	[CLK_AHB_OTG]		= GATE(0x060, BIT(0)),
 	[CLK_AHB_EHCI]		= GATE(0x060, BIT(1)),
 	[CLK_AHB_OHCI]		= GATE(0x060, BIT(2)),
+	[CLK_AHB_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_AHB_SPI1]		= GATE(0x060, BIT(21)),
+	[CLK_AHB_SPI2]		= GATE(0x060, BIT(22)),
+
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+	[CLK_SPI2]		= GATE(0x0a8, BIT(31)),
 
 	[CLK_APB1_UART0]	= GATE(0x06c, BIT(16)),
 	[CLK_APB1_UART1]	= GATE(0x06c, BIT(17)),
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 23/26] spi: sun4i: Add CLK support
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (21 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 22/26] clk: sunxi: Implement SPI clocks Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 24/26] clk: sunxi: Implement A64 SPI clocks, resets Jagan Teki
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add CLK support to enable AHB and MOD SPI clocks
on sun4i_spi driver.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/sun4i_spi.c | 46 +++++++++++++++++++++++++++++++++++------
 1 file changed, 40 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/sun4i_spi.c b/drivers/spi/sun4i_spi.c
index b86b5a00ad..5b01aa4226 100644
--- a/drivers/spi/sun4i_spi.c
+++ b/drivers/spi/sun4i_spi.c
@@ -19,6 +19,7 @@
  */
 
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <spi.h>
 #include <errno.h>
@@ -114,6 +115,8 @@ struct sun4i_spi_platdata {
 
 struct sun4i_spi_priv {
 	struct sun4i_spi_regs *regs;
+	struct clk ahb_clk;
+	struct clk mod_clk;
 	u32 freq;
 	u32 mode;
 
@@ -238,13 +241,40 @@ static int sun4i_spi_parse_pins(struct udevice *dev)
 	return 0;
 }
 
-static inline void sun4i_spi_enable_clock(void)
+static inline int sun4i_spi_enable_clock(struct udevice *dev)
 {
-	struct sunxi_ccm_reg *const ccm =
-		(struct sunxi_ccm_reg *const)SUNXI_CCM_BASE;
+	struct sun4i_spi_priv *priv = dev_get_priv(dev);
+	int ret;
+
+	ret = clk_get_by_name(dev, "ahb", &priv->ahb_clk);
+	if (ret) {
+		dev_err(dev, "failed to get ahb clock\n");
+		return ret;
+	}
+
+	ret = clk_get_by_name(dev, "mod", &priv->mod_clk);
+	if (ret) {
+		dev_err(dev, "failed to get mod clock\n");
+		return ret;
+	}
+
+	ret = clk_enable(&priv->ahb_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_enable(&priv->mod_clk);
+	if (ret) {
+		dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret);
+		goto err_ahb;
+	}
 
-	setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_SPI0));
-	writel((1 << 31), &ccm->spi0_clk_cfg);
+	return 0;
+
+err_ahb:
+	clk_disable(&priv->ahb_clk);
+	return ret;
 }
 
 static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
@@ -267,8 +297,12 @@ static int sun4i_spi_probe(struct udevice *bus)
 {
 	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
+	int ret;
+
+	ret = sun4i_spi_enable_clock(bus);
+	if (ret)
+		return ret;
 
-	sun4i_spi_enable_clock();
 	sun4i_spi_parse_pins(bus);
 
 	priv->regs = (struct sun4i_spi_regs *)(uintptr_t)plat->base_addr;
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 24/26] clk: sunxi: Implement A64 SPI clocks, resets
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (22 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 23/26] spi: sun4i: Add CLK support Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 25/26] spi: Add Allwinner A31 SPI driver Jagan Teki
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Implement SPI AHB, MOD clocks and resets for Allwinner A64.

Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/clk/sunxi/clk_a64.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
index 1d0cd98183..09ff871aee 100644
--- a/drivers/clk/sunxi/clk_a64.c
+++ b/drivers/clk/sunxi/clk_a64.c
@@ -52,6 +52,8 @@ static const struct ccu_clk_tree a64_tree[] = {
 };
 
 static const struct ccu_clk_gate a64_gates[] = {
+	[CLK_BUS_SPI0]		= GATE(0x060, BIT(20)),
+	[CLK_BUS_SPI1]		= GATE(0x060, BIT(21)),
 	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
 	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
 	[CLK_BUS_EHCI1]		= GATE(0x060, BIT(25)),
@@ -64,6 +66,9 @@ static const struct ccu_clk_gate a64_gates[] = {
 	[CLK_BUS_UART3]		= GATE(0x06c, BIT(19)),
 	[CLK_BUS_UART4]		= GATE(0x06c, BIT(20)),
 
+	[CLK_SPI0]		= GATE(0x0a0, BIT(31)),
+	[CLK_SPI1]		= GATE(0x0a4, BIT(31)),
+
 	[CLK_USB_PHY0]		= GATE(0x0cc, BIT(8)),
 	[CLK_USB_PHY1]		= GATE(0x0cc, BIT(9)),
 	[CLK_USB_HSIC]		= GATE(0x0cc, BIT(10)),
@@ -77,6 +82,8 @@ static const struct ccu_reset a64_resets[] = {
 	[RST_USB_PHY1]          = RESET(0x0cc, BIT(1)),
 	[RST_USB_HSIC]          = RESET(0x0cc, BIT(2)),
 
+	[RST_BUS_SPI0]		= RESET(0x2c0, BIT(20)),
+	[RST_BUS_SPI1]		= RESET(0x2c0, BIT(21)),
 	[RST_BUS_OTG]           = RESET(0x2c0, BIT(23)),
 	[RST_BUS_EHCI0]         = RESET(0x2c0, BIT(24)),
 	[RST_BUS_EHCI1]         = RESET(0x2c0, BIT(25)),
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 25/26] spi: Add Allwinner A31 SPI driver
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (23 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 24/26] clk: sunxi: Implement A64 SPI clocks, resets Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Add Allwinner sun6i SPI driver for A31, H3/H5 an A64.

Cc: Fahad Sadah <fahad@sadah.uk>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 drivers/spi/Kconfig     |   6 +
 drivers/spi/Makefile    |   1 +
 drivers/spi/sun6i_spi.c | 398 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 405 insertions(+)
 create mode 100644 drivers/spi/sun6i_spi.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index a7bb5b35c2..a7d5f70bc3 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -223,6 +223,12 @@ config SUN4I_SPI
 	help
 	  SPI driver for Allwinner sun4i, sun5i and sun7i SoCs
 
+config SUN6I_SPI
+	bool "Allwinner A31 SPI controller"
+	depends on ARCH_SUNXI
+	help
+	  This enables using the SPI controller on the Allwinner A31 SoCs.
+
 config TEGRA114_SPI
 	bool "nVidia Tegra114 SPI driver"
 	help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 392a925795..54826171b5 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_SH_SPI) += sh_spi.o
 obj-$(CONFIG_SH_QSPI) += sh_qspi.o
 obj-$(CONFIG_STM32_QSPI) += stm32_qspi.o
 obj-$(CONFIG_SUN4I_SPI) += sun4i_spi.o
+obj-$(CONFIG_SUN6I_SPI) += sun6i_spi.o
 obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
 obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
diff --git a/drivers/spi/sun6i_spi.c b/drivers/spi/sun6i_spi.c
new file mode 100644
index 0000000000..957a154528
--- /dev/null
+++ b/drivers/spi/sun6i_spi.c
@@ -0,0 +1,398 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Amarula Solutions.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <reset.h>
+#include <spi.h>
+
+#include <asm/bitops.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+
+#include <asm/arch/clock.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SUN8I_FIFO_DEPTH			64
+
+#define SUN6I_GBL_CTL_BUS_ENABLE		BIT(0)
+#define SUN6I_GBL_CTL_MASTER			BIT(1)
+#define SUN6I_GBL_CTL_TP			BIT(7)
+#define SUN6I_GBL_CTL_RST			BIT(31)
+
+#define SUN6I_TFR_CTL_CPHA			BIT(0)
+#define SUN6I_TFR_CTL_CPOL			BIT(1)
+#define SUN6I_TFR_CTL_SPOL			BIT(2)
+#define SUN6I_TFR_CTL_CS_MASK			0x30
+#define SUN6I_TFR_CTL_CS(cs)			(((cs) << 4) & SUN6I_TFR_CTL_CS_MASK)
+#define SUN6I_TFR_CTL_CS_MANUAL			BIT(6)
+#define SUN6I_TFR_CTL_CS_LEVEL			BIT(7)
+#define SUN6I_TFR_CTL_DHB			BIT(8)
+#define SUN6I_TFR_CTL_FBS			BIT(12)
+#define SUN6I_TFR_CTL_XCH_MASK			0x80000000
+#define SUN6I_TFR_CTL_XCH			BIT(31)
+
+#define SUN6I_FIFO_CTL_RF_RST			BIT(15)
+#define SUN6I_FIFO_CTL_TF_RST			BIT(31)
+
+#define SUN6I_FIFO_STA_RF_CNT_MASK		0xff
+#define SUN6I_FIFO_STA_RF_CNT_BITS		0
+
+#define SUN6I_CLK_CTL_CDR2_MASK			0xff
+#define SUN6I_CLK_CTL_CDR2(div)			(((div) & SUN6I_CLK_CTL_CDR2_MASK) << 0)
+#define SUN6I_CLK_CTL_CDR1_MASK			0xf
+#define SUN6I_CLK_CTL_CDR1(div)			(((div) & SUN6I_CLK_CTL_CDR1_MASK) << 8)
+#define SUN6I_CLK_CTL_DRS			BIT(12)
+
+#define SUN6I_MAX_XFER_SIZE			0xffffff
+#define SUN6I_BURST_CNT(cnt)			((cnt) & SUN6I_MAX_XFER_SIZE)
+#define SUN6I_XMIT_CNT(cnt)			((cnt) & SUN6I_MAX_XFER_SIZE)
+#define SUN6I_BURST_CTL_CNT_STC(cnt)		((cnt) & SUN6I_MAX_XFER_SIZE)
+
+#define SUNXI_SPI_FIFO_RF_CNT_MASK      0xff
+#define SUNXI_SPI_FIFO_RF_CNT_BITS      0
+#define SUNXI_SPI_FIFO_TF_CNT_MASK      0xff
+#define SUNXI_SPI_FIFO_TF_CNT_BITS      16
+
+#define SUN6I_SPI_MAX_RATE		(24 * 1000 * 1000)
+#define SUN6I_SPI_MIN_RATE		(3 * 1000)
+
+struct sun6i_spi_regs {
+	u32 res0;
+	u32 gblctl;	/* 0x04 */
+	u32 tfrctl;	/* 0x08 */
+	u32 res1;
+	u32 intctl;	/* 0x10 */
+	u32 intsta;	/* 0x14 */
+	u32 fifoctl;	/* 0x18 */
+	u32 fifosta;	/* 0x1c */
+	u32 res2;	/* 0x20 */
+	u32 clkctl;	/* 0x24 */
+	u32 res3[2];
+	u32 burstcnt;	/* 0x30 */
+	u32 xmitcnt;	/* 0x34 */
+	u32 burstctl;	/* 0x38 */
+	u32 res4[113];
+	u32 txdata;	/* 0x200 */
+	u32 res5[63];
+	u32 rxdata;	/* 0x300 */
+};
+
+struct sun6i_spi_priv {
+	struct sun6i_spi_regs *regs;
+	u32 fifo_depth;
+	struct clk clk_ahb;
+	struct clk clk_mod;
+	struct reset_ctl reset;
+
+	const u8 *tx_buf;
+	u8 *rx_buf;
+};
+
+struct sun6i_spi_platdata {
+	u32 base;
+};
+
+static void sun6i_spi_drain_fifo(struct sun6i_spi_priv *priv, int len)
+{
+	u8 byte;
+
+	while (len--) {
+		byte = readb(&priv->regs->rxdata);
+		if (priv->rx_buf)
+			*priv->rx_buf++ = byte;
+	}
+}
+
+static void sun6i_spi_fill_fifo(struct sun6i_spi_priv *priv, int len)
+{
+	u8 byte;
+
+	while (len--) {
+		byte = priv->tx_buf ? *priv->tx_buf++ : 0;
+		writeb(byte, &priv->regs->txdata);
+	}
+}
+
+static inline u32 sun6i_spi_get_rx_fifo_count(struct sun6i_spi_priv *priv)
+{
+	u32 reg = readl(&priv->regs->fifosta);
+
+	reg >>= SUN6I_FIFO_STA_RF_CNT_BITS;
+
+	return reg & SUN6I_FIFO_STA_RF_CNT_MASK;
+}
+
+static void sun6i_spi_set_cs(struct udevice *dev, u8 cs, bool enable)
+{
+	struct udevice *bus = dev->parent;
+	struct sun6i_spi_priv *priv = dev_get_priv(bus);
+	u32 reg;
+
+	reg = readl(&priv->regs->tfrctl);
+	reg &= ~SUN6I_TFR_CTL_CS_MASK;
+
+	if (enable)
+		reg &= ~SUN6I_TFR_CTL_CS_LEVEL;
+
+	if (enable)
+		reg |= SUN6I_TFR_CTL_CS(cs);
+	else
+		reg |= SUN6I_TFR_CTL_CS_LEVEL;
+
+	writel(reg, &priv->regs->tfrctl);
+}
+
+static int sun6i_spi_claim_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev->parent;
+	struct sun6i_spi_priv *priv = dev_get_priv(bus);
+	int ret;
+
+	ret = clk_enable(&priv->clk_ahb);
+	if (ret) {
+		dev_err(dev, "failed to enable ahb clock\n");
+		return ret;
+	}
+
+	ret = clk_enable(&priv->clk_mod);
+	if (ret) {
+		dev_err(dev, "failed to enable mod clock\n");
+		goto err_ahb;
+	}
+
+	ret = reset_deassert(&priv->reset);
+	if (ret) {
+		dev_err(dev, "failed to deassert reset\n");
+		goto err_mod;
+	}
+
+	setbits_le32(&priv->regs->gblctl, SUN6I_GBL_CTL_MASTER |
+		     SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_TP |
+		     SUN6I_GBL_CTL_RST);
+	setbits_le32(&priv->regs->tfrctl, SUN6I_TFR_CTL_CS_MANUAL |
+		     SUN6I_TFR_CTL_CS_LEVEL);
+
+	return 0;
+
+err_mod:
+	clk_disable(&priv->clk_mod);
+err_ahb:
+	clk_disable(&priv->clk_ahb);
+	return ret;
+}
+
+static int sun6i_spi_release_bus(struct udevice *dev)
+{
+	struct udevice *bus = dev->parent;
+	struct sun6i_spi_priv *priv = dev_get_priv(bus);
+
+	clrbits_le32(&priv->regs->gblctl, SUN6I_GBL_CTL_BUS_ENABLE);
+	clk_disable(&priv->clk_ahb);
+	clk_disable(&priv->clk_mod);
+	reset_assert(&priv->reset);
+
+	return 0;
+}
+
+static int sun6i_spi_xfer(struct udevice *dev, unsigned int bitlen,
+			  const void *dout, void *din, unsigned long flags)
+{
+	struct udevice *bus = dev->parent;
+	struct sun6i_spi_priv *priv = dev_get_priv(bus);
+	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+	u32 len = bitlen / 8;
+	u32 rx_fifocnt;
+	u8 nbytes;
+
+	priv->tx_buf = dout;
+	priv->rx_buf = din;
+
+	if (bitlen % 8) {
+		debug("%s: non byte-aligned SPI transfer.\n", __func__);
+		return -EINVAL;
+	}
+
+	if (flags & SPI_XFER_BEGIN)
+		sun6i_spi_set_cs(dev, slave_plat->cs, true);
+
+	/* Reset FIFOs */
+	setbits_le32(&priv->regs->fifoctl, SUN6I_FIFO_CTL_RF_RST |
+		     SUN6I_FIFO_CTL_TF_RST);
+
+	while (len) {
+		/* Setup the transfer now... */
+		nbytes = min(len, priv->fifo_depth - 1);
+
+		/* Setup the counters */
+		writel(SUN6I_BURST_CNT(nbytes), &priv->regs->burstcnt);
+		writel(SUN6I_XMIT_CNT(nbytes), &priv->regs->xmitcnt);
+		writel(SUN6I_BURST_CTL_CNT_STC(nbytes), &priv->regs->burstctl);
+
+		/* Fill the TX FIFO */
+		sun6i_spi_fill_fifo(priv, nbytes);
+
+		/* Start the transfer */
+		setbits_le32(&priv->regs->tfrctl, SUN6I_TFR_CTL_XCH);
+
+		/**
+		 * Wait transfer to complete
+		 *
+		 * readl_poll_timeout cannot work since it require
+		 * an extra delay between reads.
+		 */
+		do {
+			rx_fifocnt = sun6i_spi_get_rx_fifo_count(priv);
+		} while (rx_fifocnt < nbytes);
+
+		/* Drain the RX FIFO */
+		sun6i_spi_drain_fifo(priv, nbytes);
+
+		len -= nbytes;
+	}
+
+	if (flags & SPI_XFER_END)
+		sun6i_spi_set_cs(dev, slave_plat->cs, false);
+
+	return 0;
+}
+
+static int sun6i_spi_set_speed(struct udevice *bus, uint speed)
+{
+	struct sun6i_spi_priv *priv = dev_get_priv(bus);
+	unsigned int div;
+	u32 reg;
+
+	speed = min(speed, (unsigned int)SUN6I_SPI_MAX_RATE);
+	speed = max((unsigned int)SUN6I_SPI_MIN_RATE, speed);
+
+	/*
+	 * Setup clock divider.
+	 *
+	 * We have two choices there. Either we can use the clock
+	 * divide rate 1, which is calculated thanks to this formula:
+	 * SPI_CLK = MOD_CLK / (2 ^ cdr)
+	 * Or we can use CDR2, which is calculated with the formula:
+	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
+	 * Whether we use the former or the latter is set through the
+	 * DRS bit.
+	 *
+	 * First try CDR2, and if we can't reach the expected
+	 * frequency, fall back to CDR1.
+	 */
+	reg = readl(&priv->regs->clkctl);
+	div = SUN6I_SPI_MAX_RATE / (2 * speed);
+	if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) {
+		if (div > 0)
+			div--;
+
+		reg |= SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS;
+	} else {
+		div = __ilog2(SUN6I_SPI_MAX_RATE) - __ilog2(speed);
+		reg |= SUN6I_CLK_CTL_CDR1(div);
+	}
+
+	writel(reg, &priv->regs->clkctl);
+
+	return 0;
+}
+
+static int sun6i_spi_set_mode(struct udevice *bus, uint mode)
+{
+	struct sun6i_spi_priv *priv = dev_get_priv(bus);
+	u32 reg;
+
+	reg = readl(&priv->regs->tfrctl);
+	reg &= ~(SUN6I_TFR_CTL_CPOL | SUN6I_TFR_CTL_CPHA |
+		 SUN6I_TFR_CTL_FBS);
+
+	if (mode & SPI_CPOL)
+		reg |= SUN6I_TFR_CTL_CPOL;
+
+	if (mode & SPI_CPHA)
+		reg |= SUN6I_TFR_CTL_CPHA;
+
+	if (mode & SPI_LSB_FIRST)
+		reg |= SUN6I_TFR_CTL_FBS;
+
+	writel(reg, &priv->regs->tfrctl);
+
+	return 0;
+}
+
+static int sun6i_spi_probe(struct udevice *bus)
+{
+	struct sun6i_spi_platdata *plat = dev_get_platdata(bus);
+	struct sun6i_spi_priv *priv = dev_get_priv(bus);
+	unsigned int pin_function = SUNXI_GPC_SPI0;
+	int pin, ret;
+
+	priv->regs = (struct sun6i_spi_regs *)(uintptr_t)plat->base;
+	priv->fifo_depth = dev_get_driver_data(bus);
+
+	/* TODO This pin functions will drop, once sunxi pinctrl in Mainline */
+	if (IS_ENABLED(CONFIG_MACH_SUN50I))
+		pin_function = SUN50I_GPC_SPI0;
+
+	for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(3); pin++)
+		sunxi_gpio_set_cfgpin(pin, pin_function);
+
+	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
+	if (ret) {
+		dev_err(dev, "failed to get ahb clock\n");
+		return ret;
+	}
+
+	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
+	if (ret) {
+		dev_err(dev, "failed to get mod clock\n");
+		return ret;
+	}
+
+	ret = reset_get_by_index(bus, 0, &priv->reset);
+	if (ret) {
+		dev_err(dev, "failed to get reset\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int sun6i_spi_ofdata_to_platdata(struct udevice *bus)
+{
+	struct sun6i_spi_platdata *plat = dev_get_platdata(bus);
+
+	plat->base = devfdt_get_addr(bus);
+
+	return 0;
+}
+
+static const struct dm_spi_ops sun6i_spi_ops = {
+	.claim_bus	= sun6i_spi_claim_bus,
+	.release_bus	= sun6i_spi_release_bus,
+	.xfer		= sun6i_spi_xfer,
+	.set_speed	= sun6i_spi_set_speed,
+	.set_mode	= sun6i_spi_set_mode,
+};
+
+static const struct udevice_id sun6i_spi_ids[] = {
+	{ .compatible = "allwinner,sun8i-h3-spi", .data = SUN8I_FIFO_DEPTH },
+	{ }
+};
+
+U_BOOT_DRIVER(sun6i_spi) = {
+	.name	= "sun6i_spi",
+	.id	= UCLASS_SPI,
+	.of_match = sun6i_spi_ids,
+	.ops	= &sun6i_spi_ops,
+	.ofdata_to_platdata = sun6i_spi_ofdata_to_platdata,
+	.platdata_auto_alloc_size = sizeof(struct sun6i_spi_platdata),
+	.priv_auto_alloc_size = sizeof(struct sun6i_spi_priv),
+	.probe	= sun6i_spi_probe,
+};
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (24 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 25/26] spi: Add Allwinner A31 SPI driver Jagan Teki
@ 2018-12-31 16:59 ` Jagan Teki
  2019-01-07 13:04   ` Maxime Ripard
  2019-01-22 16:32   ` Alexander Graf
  2019-01-06  9:39 ` [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
  2019-01-06 13:17 ` André Przywara
  27 siblings, 2 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 16:59 UTC (permalink / raw)
  To: u-boot

Sopine has Winbond SPI flash, so enable the same to use
flash on Sopine board.

Cc: TL Lim <tllim@pine64.org>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
---
 .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi  | 16 ++++++++++++++++
 configs/sopine_baseboard_defconfig               |  7 +++++++
 2 files changed, 23 insertions(+)
 create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi

diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
new file mode 100644
index 0000000000..9661b95d15
--- /dev/null
+++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/ {
+	aliases {
+		spi0 = &spi0;
+	};
+};
+
+&spi0  {
+	flash at 0 {
+		compatible = "spi-flash";
+	};
+};
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index 0a189fc03d..5e6dc33d4d 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -12,9 +12,16 @@ CONFIG_SPL_SPI_SUNXI=y
 CONFIG_NR_DRAM_BANKS=1
 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
 # CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
 # CONFIG_SPL_DOS_PARTITION is not set
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_SUN6I_SPI=y
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_WINBOND=y
 CONFIG_SUN8I_EMAC=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
-- 
2.18.0.321.gffc6fa0e3

^ permalink raw reply related	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 17/26] phy: sun4i-usb: Use CLK and RESET support
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 17/26] phy: sun4i-usb: Use CLK and RESET support Jagan Teki
@ 2018-12-31 18:29   ` Marek Vasut
  2018-12-31 18:38     ` Jagan Teki
  0 siblings, 1 reply; 49+ messages in thread
From: Marek Vasut @ 2018-12-31 18:29 UTC (permalink / raw)
  To: u-boot

On 12/31/18 5:59 PM, Jagan Teki wrote:
> Now clock and reset drivers are available for respective
> SoC's so use clk and reset ops on phy driver.
> 
> Cc: Marek Vasut <marex@denx.de> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>

Reviewed-by: Marek Vasut <marex@denx.de>

btw I hope this is planned for _after_ 2019.01 release ?

[...]
-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 19/26] musb-new: sunxi: Use CLK and RESET support
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 19/26] musb-new: sunxi: Use CLK and RESET support Jagan Teki
@ 2018-12-31 18:30   ` Marek Vasut
  0 siblings, 0 replies; 49+ messages in thread
From: Marek Vasut @ 2018-12-31 18:30 UTC (permalink / raw)
  To: u-boot

On 12/31/18 5:59 PM, Jagan Teki wrote:
> Now clock and reset drivers are available for respective
> SoC's so use clk and reset ops on musb driver.
> 
> Cc: Marek Vasut <marex@denx.de> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
>  drivers/usb/musb-new/sunxi.c | 81 ++++++++++++++++++------------------
>  1 file changed, 40 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
> index f542a181fa..f79b3eedcf 100644
> --- a/drivers/usb/musb-new/sunxi.c
> +++ b/drivers/usb/musb-new/sunxi.c
> @@ -16,9 +16,11 @@
>   * This file is part of the Inventra Controller Driver for Linux.
>   */
>  #include <common.h>
> +#include <clk.h>
>  #include <dm.h>
>  #include <generic-phy.h>
>  #include <phy-sun4i-usb.h>
> +#include <reset.h>
>  #include <asm/arch/cpu.h>
>  #include <asm/arch/clock.h>
>  #include <asm/arch/gpio.h>
> @@ -80,16 +82,12 @@
>  
>  struct sunxi_musb_config {
>  	struct musb_hdrc_config *config;
> -	bool has_reset;
> -	u8 rst_bit;
> -	u8 clkgate_bit;
> -	u32 off_reset0;
>  };
>  
>  struct sunxi_glue {
>  	struct musb_host_data mdata;
> -	struct sunxi_ccm_reg *ccm;
> -	u32 *reg_reset0;
> +	struct clk clk;
> +	struct reset_ctl rst;
>  	struct sunxi_musb_config *cfg;
>  	struct device dev;
>  	struct phy phy;
> @@ -296,24 +294,27 @@ static int sunxi_musb_init(struct musb *musb)
>  
>  	pr_debug("%s():\n", __func__);
>  
> -	ret = generic_phy_init(&glue->phy);
> +	ret = clk_enable(&glue->clk);
>  	if (ret) {
> -		pr_err("failed to init USB PHY\n");
> +		pr_err("failed to enable clock\n");
>  		return ret;
>  	}
>  
> -	musb->isr = sunxi_musb_interrupt;
> -
> -	setbits_le32(&glue->ccm->ahb_gate0, BIT(AHB_GATE_OFFSET_USB0));
> -	if (glue->cfg->clkgate_bit)
> -		setbits_le32(&glue->ccm->ahb_gate0,
> -			     BIT(glue->cfg->clkgate_bit));
> +	if (reset_valid(&glue->rst)) {
> +		ret = reset_deassert(&glue->rst);
> +		if (ret) {
> +			pr_err("failed to deassert reset\n");

dev_err(dev, ...), fix globally

[...]


-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 17/26] phy: sun4i-usb: Use CLK and RESET support
  2018-12-31 18:29   ` Marek Vasut
@ 2018-12-31 18:38     ` Jagan Teki
  0 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2018-12-31 18:38 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 1, 2019 at 12:01 AM Marek Vasut <marex@denx.de> wrote:
>
> On 12/31/18 5:59 PM, Jagan Teki wrote:
> > Now clock and reset drivers are available for respective
> > SoC's so use clk and reset ops on phy driver.
> >
> > Cc: Marek Vasut <marex@denx.de>
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
>
> Reviewed-by: Marek Vasut <marex@denx.de>
>
> btw I hope this is planned for _after_ 2019.01 release ?

Yes.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (25 preceding siblings ...)
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
@ 2019-01-06  9:39 ` Jagan Teki
  2019-01-06 13:17 ` André Przywara
  27 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2019-01-06  9:39 UTC (permalink / raw)
  To: u-boot

On Mon, Dec 31, 2018 at 10:30 PM Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Although the previous version[1] is properly handled the clock gates
> with enable and disable management, but this series is trying to add
> some more complex Allwinner CLK architecture by handling parent clock
> and other CLK attributes.
>
> Allwinner Clock control unit comprises of parent clocks, gates, multiplexers,
> dividers, multipliers, pre/post dividers and flags etc.
>
> So, the U-Boot implementation of ccu has divided into gates and tree.
> gates are generic clock configuration of enable/disable bit management
> and these can be handled via ccu_clock_gate, which is almost same as
> previous version changes.
>
> Tree clock has more Allwinner CLK attributes like clock type, fixed clocks,
> misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be
> managed via ccu_clock_tree.
>
> On top of initial clock gates supported from previous version, this
> series is trying to add support for MP, NK, MISC, FIXED clock types
> with get_rate functionality and that can eventually used by uart driver.
>
> On the summary, this would be an initial infrasture that can fit into
> remaining clock handle support like set_rate, so the rest of code will
> add on the requirement basics.
>
> Once this is fine, I will try to add code for other parts especially for
> MMC since we have migration deadline for BLK, MMC, SCSI.
>
> So, please do let me know if anyone have any inputs.
>
> All these changes available at u-boot-sunxi/clk-next
>
> thanks,
> Jagan.
>
> [1] https://patchwork.ozlabs.org/cover/962226/
>
> Jagan Teki (26):
>   clk: Add Allwinner A64 CLK driver
>   reset: Add Allwinner RESET driver
>   clk: sunxi: Add Allwinner H3/H5 CLK driver
>   clk: sunxi: Add Allwinner A10/A20 CLK driver
>   clk: sunxi: Add Allwinner A10s/A13 CLK driver
>   clk: sunxi: Add Allwinner A31 CLK driver
>   clk: sunxi: Add Allwinner A23/A33 CLK driver
>   clk: sunxi: Add Allwinner A83T CLK driver
>   clk: sunxi: Add Allwinner R40 CLK driver
>   clk: sunxi: Add Allwinner V3S CLK driver
>   clk: sunxi: Implement UART clocks
>   clk: sunxi: Implement UART resets
>   clk: sunxi: Add Allwinner H6 CLK driver
>   sunxi: A64: Update sun50i-a64-ccu.h
>   clk: sunxi: Add ccu clock tree support
>   sunxi: Enable CLK
>   phy: sun4i-usb: Use CLK and RESET support
>   reset: Add reset valid
>   musb-new: sunxi: Use CLK and RESET support
>   sunxi: usb: Switch to Generic host controllers
>   usb: host: Drop [e-o]hci-sunxi drivers
>   clk: sunxi: Implement SPI clocks
>   spi: sun4i: Add CLK support
>   clk: sunxi: Implement A64 SPI clocks, resets
>   spi: Add Allwinner A31 SPI driver
>   board: sopine: Enable SPI/SPI-FLASH

I'm planning to pick gate clock patches and keep tree based clock for
next version, let me know if anyone have any questions.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support
  2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
                   ` (26 preceding siblings ...)
  2019-01-06  9:39 ` [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
@ 2019-01-06 13:17 ` André Przywara
  2019-01-06 19:22   ` Jagan Teki
  27 siblings, 1 reply; 49+ messages in thread
From: André Przywara @ 2019-01-06 13:17 UTC (permalink / raw)
  To: u-boot

On 31/12/2018 16:59, Jagan Teki wrote:

Hi Jagan,

many thanks for picking this up, I was about to come back to this
myself. I am looking at the pinctrl part at the moment, so good you are
working on the clocks!

TL;DR: I am good with the first patches, but would like to drop the last
five 5 patches from this series, and discuss the whole tree approach (or
at least the patch) further.

> Although the previous version[1] is properly handled the clock gates
> with enable and disable management, but this series is trying to add
> some more complex Allwinner CLK architecture by handling parent clock
> and other CLK attributes.
> 
> Allwinner Clock control unit comprises of parent clocks, gates, multiplexers,
> dividers, multipliers, pre/post dividers and flags etc.
> 
> So, the U-Boot implementation of ccu has divided into gates and tree.
> gates are generic clock configuration of enable/disable bit management
> and these can be handled via ccu_clock_gate, which is almost same as
> previous version changes.

So I like this part very much, all those gates and resets are nicely
readable.
Also the removal of the special sunxi USB drivers is very welcome.
So up until patch including 21/26, except 15/26, I am all in.

> Tree clock has more Allwinner CLK attributes like clock type, fixed clocks,
> misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be
> managed via ccu_clock_tree.

Mmmh, this looks quite complex for U-Boot's very limited needs to me.
As far as I can see we basically have a static setup for most devices,
the ones where we actually change the parent clocks are only clock
consumers, namely DE/TCON and MMC. The former chooses a parent once,
based on the calculated clock rate. Only for MMC we switch it from OSC24
(for the initial SPI-like setup phase) to PLL_PERIPH0 at runtime.
But however this does not really affect the tree, and also we never do
re-parenting.
Under this premises, can't we do this somewhat simpler? At the end of
the day this is U-Boot, not a sophisticated kernel, and we got away with
quite simple clock code so far.

Meanwhile I am struggling to understand your approach, which looks
impressive on the first glance, but leave me scratching my head when
looking at details. I will comment on 15/26 for the parts I am wondering
about. I was trying to add MMC support and hit some issues.

On the SPI part:
I am bit puzzled about the last 5 patches dealing with SPI. I see that
they depend on the others, but would like to deal with them separately.

First, patch 25/26 (the sun6i SPI driver) is a bit surprising to find in
here. I guess you want to have an easy user for another clock, but I
believe this should be a separate series. There were other posts already
for a sun6i driver, also I think we should have a unified driver instead
of duplicating most of it again. See Oskari's latest post.

Secondly: I don't think the SPI clocks are correct. You model them as
simple gates only, kind of ignoring the divider settings. This is what
the current sun4i driver does as well, but: it writes 1U << 31 into the
clock register, which explicitly writes 0 to the other bits, setting 24
MHz as the input rate. Your approach would read-modify-write the
register, just setting bit 31 and leaving the other ones as they were
before.
So why isn't that using your new tree approach? Looks like a standard
mux/divider clock to me.

Cheers,
Andre.


> On top of initial clock gates supported from previous version, this 
> series is trying to add support for MP, NK, MISC, FIXED clock types
> with get_rate functionality and that can eventually used by uart driver.
> 
> On the summary, this would be an initial infrasture that can fit into
> remaining clock handle support like set_rate, so the rest of code will
> add on the requirement basics.
> 
> Once this is fine, I will try to add code for other parts especially for
> MMC since we have migration deadline for BLK, MMC, SCSI.
> 
> So, please do let me know if anyone have any inputs.
> 
> All these changes available at u-boot-sunxi/clk-next
> 
> thanks,
> Jagan.
> 
> [1] https://patchwork.ozlabs.org/cover/962226/
> 
> Jagan Teki (26):
>   clk: Add Allwinner A64 CLK driver
>   reset: Add Allwinner RESET driver
>   clk: sunxi: Add Allwinner H3/H5 CLK driver
>   clk: sunxi: Add Allwinner A10/A20 CLK driver
>   clk: sunxi: Add Allwinner A10s/A13 CLK driver
>   clk: sunxi: Add Allwinner A31 CLK driver
>   clk: sunxi: Add Allwinner A23/A33 CLK driver
>   clk: sunxi: Add Allwinner A83T CLK driver
>   clk: sunxi: Add Allwinner R40 CLK driver
>   clk: sunxi: Add Allwinner V3S CLK driver
>   clk: sunxi: Implement UART clocks
>   clk: sunxi: Implement UART resets
>   clk: sunxi: Add Allwinner H6 CLK driver
>   sunxi: A64: Update sun50i-a64-ccu.h
>   clk: sunxi: Add ccu clock tree support
>   sunxi: Enable CLK
>   phy: sun4i-usb: Use CLK and RESET support
>   reset: Add reset valid
>   musb-new: sunxi: Use CLK and RESET support
>   sunxi: usb: Switch to Generic host controllers
>   usb: host: Drop [e-o]hci-sunxi drivers
>   clk: sunxi: Implement SPI clocks
>   spi: sun4i: Add CLK support
>   clk: sunxi: Implement A64 SPI clocks, resets
>   spi: Add Allwinner A31 SPI driver
>   board: sopine: Enable SPI/SPI-FLASH
> 
>  .../sun50i-a64-sopine-baseboard-u-boot.dtsi   |  16 +
>  arch/arm/include/asm/arch-sunxi/ccu.h         | 284 +++++++++++++
>  arch/arm/mach-sunxi/Kconfig                   |  12 +
>  configs/A10-OLinuXino-Lime_defconfig          |   1 +
>  configs/A10s-OLinuXino-M_defconfig            |   1 +
>  configs/A13-OLinuXinoM_defconfig              |   1 +
>  configs/A13-OLinuXino_defconfig               |   1 +
>  configs/A20-OLinuXino-Lime2-eMMC_defconfig    |   1 +
>  configs/A20-OLinuXino-Lime2_defconfig         |   1 +
>  configs/A20-OLinuXino-Lime_defconfig          |   1 +
>  configs/A20-Olimex-SOM204-EVB_defconfig       |   1 +
>  configs/Auxtek-T003_defconfig                 |   1 +
>  configs/Auxtek-T004_defconfig                 |   1 +
>  configs/Bananapi_defconfig                    |   1 +
>  configs/Bananapi_m2m_defconfig                |   1 +
>  configs/Bananapro_defconfig                   |   1 +
>  configs/CHIP_defconfig                        |   1 +
>  configs/CHIP_pro_defconfig                    |   1 +
>  configs/CSQ_CS908_defconfig                   |   1 +
>  configs/Colombus_defconfig                    |   1 +
>  configs/Cubieboard2_defconfig                 |   1 +
>  configs/Cubieboard_defconfig                  |   1 +
>  configs/Cubietruck_plus_defconfig             |   1 +
>  configs/Hummingbird_A31_defconfig             |   1 +
>  configs/Itead_Ibox_A20_defconfig              |   1 +
>  configs/Linksprite_pcDuino3_Nano_defconfig    |   1 +
>  configs/Linksprite_pcDuino3_defconfig         |   1 +
>  configs/Linksprite_pcDuino_defconfig          |   1 +
>  configs/MK808C_defconfig                      |   1 +
>  configs/Marsboard_A10_defconfig               |   1 +
>  configs/Mele_A1000G_quad_defconfig            |   1 +
>  configs/Mele_A1000_defconfig                  |   1 +
>  configs/Mele_I7_defconfig                     |   1 +
>  configs/Mele_M3_defconfig                     |   1 +
>  configs/Mele_M5_defconfig                     |   1 +
>  configs/Mele_M9_defconfig                     |   1 +
>  configs/Mini-X_defconfig                      |   1 +
>  configs/Orangepi_defconfig                    |   1 +
>  configs/Orangepi_mini_defconfig               |   1 +
>  configs/Sinlinx_SinA31s_defconfig             |   1 +
>  configs/Sinlinx_SinA33_defconfig              |   1 +
>  configs/Sinovoip_BPI_M2_Plus_defconfig        |   1 +
>  configs/Sinovoip_BPI_M2_defconfig             |   1 +
>  configs/Sinovoip_BPI_M3_defconfig             |   1 +
>  configs/Wexler_TAB7200_defconfig              |   1 +
>  configs/Wobo_i5_defconfig                     |   1 +
>  configs/a64-olinuxino_defconfig               |   1 +
>  configs/ba10_tv_box_defconfig                 |   1 +
>  configs/bananapi_m1_plus_defconfig            |   1 +
>  configs/bananapi_m64_defconfig                |   1 +
>  configs/ga10h_v1_1_defconfig                  |   1 +
>  configs/h8_homlet_v2_defconfig                |   1 +
>  configs/i12-tvbox_defconfig                   |   1 +
>  configs/icnova-a20-swac_defconfig             |   1 +
>  configs/inet1_defconfig                       |   1 +
>  configs/inet_q972_defconfig                   |   1 +
>  configs/jesurun_q5_defconfig                  |   1 +
>  configs/libretech_all_h3_cc_h2_plus_defconfig |   1 +
>  configs/libretech_all_h3_cc_h3_defconfig      |   1 +
>  configs/libretech_all_h3_cc_h5_defconfig      |   1 +
>  configs/mixtile_loftq_defconfig               |   1 +
>  configs/mk802_a10s_defconfig                  |   1 +
>  configs/mk802_defconfig                       |   1 +
>  configs/mk802ii_defconfig                     |   1 +
>  configs/nanopi_a64_defconfig                  |   1 +
>  configs/nanopi_m1_defconfig                   |   1 +
>  configs/nanopi_m1_plus_defconfig              |   1 +
>  configs/nanopi_neo2_defconfig                 |   1 +
>  configs/nanopi_neo_air_defconfig              |   1 +
>  configs/nanopi_neo_defconfig                  |   1 +
>  configs/nanopi_neo_plus2_defconfig            |   1 +
>  configs/orangepi_2_defconfig                  |   1 +
>  configs/orangepi_lite_defconfig               |   1 +
>  configs/orangepi_one_defconfig                |   1 +
>  configs/orangepi_pc2_defconfig                |   1 +
>  configs/orangepi_pc_defconfig                 |   1 +
>  configs/orangepi_pc_plus_defconfig            |   1 +
>  configs/orangepi_plus2e_defconfig             |   1 +
>  configs/orangepi_plus_defconfig               |   1 +
>  configs/orangepi_prime_defconfig              |   1 +
>  configs/orangepi_r1_defconfig                 |   1 +
>  configs/orangepi_win_defconfig                |   1 +
>  configs/orangepi_zero_defconfig               |   1 +
>  configs/orangepi_zero_plus2_defconfig         |   1 +
>  configs/orangepi_zero_plus_defconfig          |   1 +
>  configs/parrot_r16_defconfig                  |   1 +
>  configs/pine64_plus_defconfig                 |   1 +
>  configs/r7-tv-dongle_defconfig                |   1 +
>  configs/sopine_baseboard_defconfig            |   8 +
>  configs/sun8i_a23_evb_defconfig               |   1 +
>  configs/sunxi_Gemei_G9_defconfig              |   1 +
>  configs/tbs_a711_defconfig                    |   1 +
>  drivers/clk/Kconfig                           |   1 +
>  drivers/clk/Makefile                          |   1 +
>  drivers/clk/sunxi/Kconfig                     |  82 ++++
>  drivers/clk/sunxi/Makefile                    |  18 +
>  drivers/clk/sunxi/clk_a10.c                   |  77 ++++
>  drivers/clk/sunxi/clk_a10s.c                  |  68 +++
>  drivers/clk/sunxi/clk_a23.c                   |  75 ++++
>  drivers/clk/sunxi/clk_a31.c                   |  82 ++++
>  drivers/clk/sunxi/clk_a64.c                   | 125 ++++++
>  drivers/clk/sunxi/clk_a83t.c                  |  75 ++++
>  drivers/clk/sunxi/clk_h3.c                    |  89 ++++
>  drivers/clk/sunxi/clk_h6.c                    |  53 +++
>  drivers/clk/sunxi/clk_r40.c                   |  88 ++++
>  drivers/clk/sunxi/clk_sunxi.c                 | 256 +++++++++++
>  drivers/clk/sunxi/clk_v3s.c                   |  59 +++
>  drivers/phy/allwinner/phy-sun4i-usb.c         |  77 +++-
>  drivers/reset/Kconfig                         |   8 +
>  drivers/reset/Makefile                        |   1 +
>  drivers/reset/reset-sunxi.c                   | 125 ++++++
>  drivers/spi/Kconfig                           |   6 +
>  drivers/spi/Makefile                          |   1 +
>  drivers/spi/sun4i_spi.c                       |  46 +-
>  drivers/spi/sun6i_spi.c                       | 398 ++++++++++++++++++
>  drivers/usb/host/Kconfig                      |   2 +
>  drivers/usb/host/Makefile                     |   2 -
>  drivers/usb/host/ehci-sunxi.c                 | 204 ---------
>  drivers/usb/host/ohci-sunxi.c                 | 233 ----------
>  drivers/usb/musb-new/sunxi.c                  |  81 ++--
>  include/configs/sun4i.h                       |   4 -
>  include/configs/sun50i.h                      |   5 -
>  include/configs/sun5i.h                       |   4 -
>  include/configs/sun6i.h                       |   4 -
>  include/configs/sun7i.h                       |   4 -
>  include/configs/sun8i.h                       |   4 -
>  include/configs/sunxi-common.h                |   1 -
>  include/dt-bindings/clock/sun50i-a64-ccu.h    |   2 +
>  include/reset.h                               |  11 +
>  scripts/config_whitelist.txt                  |   2 -
>  130 files changed, 2248 insertions(+), 534 deletions(-)
>  create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
>  create mode 100644 arch/arm/include/asm/arch-sunxi/ccu.h
>  create mode 100644 drivers/clk/sunxi/Kconfig
>  create mode 100644 drivers/clk/sunxi/Makefile
>  create mode 100644 drivers/clk/sunxi/clk_a10.c
>  create mode 100644 drivers/clk/sunxi/clk_a10s.c
>  create mode 100644 drivers/clk/sunxi/clk_a23.c
>  create mode 100644 drivers/clk/sunxi/clk_a31.c
>  create mode 100644 drivers/clk/sunxi/clk_a64.c
>  create mode 100644 drivers/clk/sunxi/clk_a83t.c
>  create mode 100644 drivers/clk/sunxi/clk_h3.c
>  create mode 100644 drivers/clk/sunxi/clk_h6.c
>  create mode 100644 drivers/clk/sunxi/clk_r40.c
>  create mode 100644 drivers/clk/sunxi/clk_sunxi.c
>  create mode 100644 drivers/clk/sunxi/clk_v3s.c
>  create mode 100644 drivers/reset/reset-sunxi.c
>  create mode 100644 drivers/spi/sun6i_spi.c
>  delete mode 100644 drivers/usb/host/ehci-sunxi.c
>  delete mode 100644 drivers/usb/host/ohci-sunxi.c
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support
  2019-01-06 13:17 ` André Przywara
@ 2019-01-06 19:22   ` Jagan Teki
  2019-01-07  1:21     ` André Przywara
  0 siblings, 1 reply; 49+ messages in thread
From: Jagan Teki @ 2019-01-06 19:22 UTC (permalink / raw)
  To: u-boot

On Sun, Jan 6, 2019 at 6:49 PM André Przywara <andre.przywara@arm.com> wrote:
>
> On 31/12/2018 16:59, Jagan Teki wrote:
>
> Hi Jagan,
>
> many thanks for picking this up, I was about to come back to this
> myself. I am looking at the pinctrl part at the moment, so good you are
> working on the clocks!
>
> TL;DR: I am good with the first patches, but would like to drop the last
> five 5 patches from this series, and discuss the whole tree approach (or
> at least the patch) further.
>
> > Although the previous version[1] is properly handled the clock gates
> > with enable and disable management, but this series is trying to add
> > some more complex Allwinner CLK architecture by handling parent clock
> > and other CLK attributes.
> >
> > Allwinner Clock control unit comprises of parent clocks, gates, multiplexers,
> > dividers, multipliers, pre/post dividers and flags etc.
> >
> > So, the U-Boot implementation of ccu has divided into gates and tree.
> > gates are generic clock configuration of enable/disable bit management
> > and these can be handled via ccu_clock_gate, which is almost same as
> > previous version changes.
>
> So I like this part very much, all those gates and resets are nicely
> readable.
> Also the removal of the special sunxi USB drivers is very welcome.
> So up until patch including 21/26, except 15/26, I am all in.

Yes my plan is to do the same.

>
> > Tree clock has more Allwinner CLK attributes like clock type, fixed clocks,
> > misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be
> > managed via ccu_clock_tree.
>
> Mmmh, this looks quite complex for U-Boot's very limited needs to me.
> As far as I can see we basically have a static setup for most devices,
> the ones where we actually change the parent clocks are only clock
> consumers, namely DE/TCON and MMC. The former chooses a parent once,
> based on the calculated clock rate. Only for MMC we switch it from OSC24
> (for the initial SPI-like setup phase) to PLL_PERIPH0 at runtime.
> But however this does not really affect the tree, and also we never do
> re-parenting.
> Under this premises, can't we do this somewhat simpler? At the end of
> the day this is U-Boot, not a sophisticated kernel, and we got away with
> quite simple clock code so far.

Yes, Idea is to go with limited clock setups but the thing is as you
know Allwinner deals numerous number of clock attributes and I found
it difficult to handle them w/o traversing the re-parenting stuff. I
have tried simple version of set_rate in previous version[2] but it
wouldn't ended as we desired. These operations need re-parenting, so
we have to handle parents in clock attributes.

So finally I came up with tree structure.

My idea here is to support get and set rate with minimal re-parenting
like OSC24, PLL_PERIPH0, PLL_PERIPH1 not adding much code like Linux
does. Like GATE macro, TREE macro is also a readable structure with
all possible/needed clk attributes at one glance. The code that handle
these tree attributes may look confusing, but it is obvious because it
would need to handle re-parenting.

If SoC has a big CLK architecture like this and to support all or
needed clock operations, re-parenting may be one of painful code for
SoC driver in U-Boot, Since CLK framework doesn't handle these
generically(may be no need) as compared to Linux. and the existing SoC
like mediatek clock code does the same.

At, this point, I think this tree approach can be possible way to move
since it handle all clock attribute types and yes we can only support
clock re-parenting which are required for U-Boot.

> Meanwhile I am struggling to understand your approach, which looks
> impressive on the first glance, but leave me scratching my head when
> looking at details. I will comment on 15/26 for the parts I am wondering
> about. I was trying to add MMC support and hit some issues.

As I said above there is no generic way to handle re-parenting in
U-Boot, and we need to traverse based on the SoC Clock architecture.

15/26 handling get_rate, say for example UART request a get_rate.


                              |==> OSC_32K
UART-->APB2--->|==> OSC_24M
                              |==> PLL_PH0   ===> OSC_24M
                              |==> PLL_PH0

Each clock tree, has clock type so UART is marked as MISC since it
can't not usual clock tree unlike MMC. MMC can be MP clock type and
so..on

So, if driver requesting get_rate with UART clock, then we need to
traverse all the UART clock tree and get the rate based on the type
and identified parent clock. UART is MISC so it can directly trigger
parent clock abp2, apb2 need to find the parent using mux shift,
width, once apb2 found the parent it will go to next as so on.

>
> On the SPI part:
> I am bit puzzled about the last 5 patches dealing with SPI. I see that
> they depend on the others, but would like to deal with them separately.

True, but these are previous version changes ie reason I grouped it
here. anyway will handle accordingly in next versions.

> First, patch 25/26 (the sun6i SPI driver) is a bit surprising to find in
> here. I guess you want to have an easy user for another clock, but I
> believe this should be a separate series. There were other posts already
> for a sun6i driver, also I think we should have a unified driver instead
> of duplicating most of it again. See Oskari's latest post.

Yes, I saw this sun6i driver is lasting for many releases and my plan
it to unified the driver w/o any ifdef.

>
> Secondly: I don't think the SPI clocks are correct. You model them as
> simple gates only, kind of ignoring the divider settings. This is what
> the current sun4i driver does as well, but: it writes 1U << 31 into the
> clock register, which explicitly writes 0 to the other bits, setting 24
> MHz as the input rate. Your approach would read-modify-write the
> register, just setting bit 31 and leaving the other ones as they were
> before.
> So why isn't that using your new tree approach? Looks like a standard
> mux/divider clock to me.

Yes these yet to implement, ie reason I have just added clk tree only
on A64. Idea is to send next version for full support on all SoC
types.

[2] https://patchwork.ozlabs.org/patch/955993/

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support Jagan Teki
@ 2019-01-07  1:03   ` André Przywara
  2019-01-07 13:01     ` Maxime Ripard
                       ` (2 more replies)
  0 siblings, 3 replies; 49+ messages in thread
From: André Przywara @ 2019-01-07  1:03 UTC (permalink / raw)
  To: u-boot

On 31/12/2018 16:59, Jagan Teki wrote:
> Clock control unit comprises of parent clocks, gates, multiplexers,
> dividers, multipliers, pre/post dividers and flags etc.
> 
> So, the U-Boot implementation of ccu has divided into gates and tree.
> gates are generic clock configuration of enable/disable bit management
> which can be handle via ccu_clock_gate.

So if I understand this correctly, you implement the gate functionality
separately from the complex clock code, even if they are the same clock
from the DT point of view? So if one wants to enable the MMC0 clock,
which is a mux/divider clock, one needs to specify an extra entry in the
gate array to describe the enable bit in this special clock register?
Sounds a bit surprising, but is probably a neat trick to keep things
simple. There should be a comment in the code to this regard then.

> Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp,
> pre/post div, flags etc. which were managed via ccu_clock_tree.

For a start, can we use more descriptive names than those very specific
MP/NK names? DIV_MUX and PLL sound more descriptive to me. I understand
that Linux uses those terms, but it would be great if uninitiated people
have a chance to understand this as well.

> This patch add support for MP, NK, MISC, FIXED clock types as part of
> ccu clock tree with get_rate functionality this eventually used by
> uart driver. and rest of the infrastructure will try to add while CLK
> is being used on respective peripherals.
> 
> Note that few of the tree type clock would require to enable gates on
> their specific clock, in that case we need to add the gate details via
> ccu_clock_gate, example: MP with gate so the gate offset, bit value
> should add as part of ccu_clock_gate.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++-
>  drivers/clk/sunxi/clk_a64.c           |  40 ++++++
>  drivers/clk/sunxi/clk_sunxi.c         | 182 ++++++++++++++++++++++++
>  3 files changed, 413 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
> index 3fdc26978d..61b8c36b3b 100644
> --- a/arch/arm/include/asm/arch-sunxi/ccu.h
> +++ b/arch/arm/include/asm/arch-sunxi/ccu.h
> @@ -7,15 +7,204 @@
>  #ifndef _ASM_ARCH_CCU_H
>  #define _ASM_ARCH_CCU_H
>  
> +#define OSC_32K_ULL		32000ULL

32768

And why ULL? The whole Allwinner clock system works with 32-bit values,
so just U would be totally sufficient. This avoid blowing this up to 64
bit unnecessarily, which sounds painful for those poor ARMv7 parts.

> +#define OSC_24M_ULL		24000000ULL
> +
> +/**
> + * enum ccu_clk_type - ccu clock types
> + *
> + * @CCU_CLK_TYPE_MISC:			misc clock type

What is MISC, exactly? Seems like an artefact clock to me, some
placeholder you need because gate clocks are handled separately in the
gates struct. Should this be called something with SIMPLE instead, or GATE?

> + * @CCU_CLK_TYPE_FIXED:			fixed clock type
> + * @CCU_CLK_TYPE_MP:			mp clock type
> + * @CCU_CLK_TYPE_NK:			nk clock type

What is the point of those comments, as you are basically repeating the
enum name? What about:
 * @CCU_CLK_TYPE_PLL:		PLL clock with two multiplier fields
 * @CCU_CLK_TYPE_MUX_DIV:	multiple parents, two divider fields

This gives more speaking names, plus some explanation.

> + */
> +enum ccu_clk_type {
> +	CCU_CLK_TYPE_MISC		= 0,
> +	CCU_CLK_TYPE_FIXED		= 1,
> +	CCU_CLK_TYPE_MP			= 2,
> +	CCU_CLK_TYPE_NK			= 3,
> +};
> +
>  /**
>   * enum ccu_clk_flags - ccu clock flags
>   *
> - * @CCU_CLK_F_INIT_DONE:		clock gate init done check
> + * @CCU_CLK_F_INIT_DONE:		clock tree/gate init done check

Is this flag to tell implemented clocks apart from unimplemented ones,
which would be reset to all zeroes by the compiler? Then it should be
called something with VALID in it.

> + * @CCU_CLK_F_POSTDIV:			clock post divider
>   */
>  enum ccu_clk_flags {
>  	CCU_CLK_F_INIT_DONE		= BIT(0),
> +	CCU_CLK_F_POSTDIV		= BIT(1),
>  };
>  
> +/**
> + * struct ccu_mult - ccu clock multiplier
> + *
> + * @shift:		multiplier shift value
> + * @width:		multiplier width value
> + * @offset:		multiplier offset
> + * @min:		minimum multiplier
> + * @max:		maximum multiplier
> + */
> +struct ccu_mult {
> +	u8 shift;
> +	u8 width;
> +	u8 offset;
> +	u8 min;
> +	u8 max;
> +};
> +
> +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width, _offset,		\
> +			      _min, _max) {			\
> +	.shift = _shift,					\
> +	.width = _width,					\
> +	.offset = _offset,					\
> +	.min = _min,						\
> +	.max = _max,						\
> +}
> +
> +#define _CCU_MULT_MIN(_shift, _width, _min)			\
> +	_CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0)
> +
> +#define _CCU_MULT(_shift, _width)				\
> +	_CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0)
> +
> +/**
> + * struct ccu_mux - ccu clock multiplexer
> + *
> + * @shift:		multiplexer shift value
> + * @width:		multiplexer width value
> + */
> +struct ccu_mux {
> +	u8 shift;
> +	u8 width;
> +};
> +
> +#define _CCU_MUX(_shift, _width) {		\
> +	.shift = _shift,			\
> +	.width = _width,			\
> +}
> +
> +/**
> + * struct ccu_div - ccu clock divider
> + *
> + * @shift:		divider shift value
> + * @width:		divider width value
> + * @offset:		divider offset
> + * @max:		maximum divider value
> + */
> +struct ccu_div {
> +	u8 shift;
> +	u8 width;
> +	u32 offset;
> +	u32 max;
> +};
> +
> +#define _CCU_DIV(_shift, _width) {		\
> +	.shift = _shift,			\
> +	.width = _width,			\
> +	.offset = 1,				\
> +	.max = 0,				\
> +}
> +
> +/**
> + * struct ccu_clk_tree - ccu clock tree
> + *
> + * @parent:		parent clock tree
> + * @type:		clock type
> + * @off:		clock tree offset
> + * @m:			divider m
> + * @p:			divider p
> + * @mux:		multiplexer mux
> + * @post:		post divider value
> + * @n:			multiplier n
> + * @k:			multiplier k
> + * @fixed_rate:		fixed rate
> + * @flags:		clock tree flags
> + */
> +struct ccu_clk_tree {
> +	const unsigned long *parent;

Shouldn't that be called "parents" instead?

> +	enum ccu_clk_type type;
> +	u16 off;
> +
> +	struct ccu_div m;
> +	struct ccu_div p;
> +	struct ccu_mux mux;
> +	unsigned int postdiv;
> +
> +	struct ccu_mult n;
> +	struct ccu_mult k;
> +
> +	ulong fixed_rate;
> +	enum ccu_clk_flags flags;
> +};
> +
> +#define TREE(_parent, _type, _off,				\

Just a nit, but TREE is somewhat confusing here, as this just constructs
a single entry in an array. The tree property is realised through the
parent array, if I get this correctly.
So should we name this ENTRY or CLK_ENTRY instead?

> +	     _m, _p,						\
> +	     _mux,						\
> +	     _postdiv,						\
> +	     _n, _k,						\
> +	     _fixed_rate,					\
> +	     _flags) {						\
> +	.parent = _parent,					\
> +	.type = _type,						\
> +	.off = _off,						\
> +	.m = _m,						\
> +	.p = _p,						\
> +	.mux = _mux,						\
> +	.postdiv = _postdiv,					\
> +	.n = _n,						\
> +	.k = _k,						\
> +	.fixed_rate = _fixed_rate,				\
> +	.flags = _flags,					\
> +}
> +
> +#define MISC(_parent)						\
> +	TREE(_parent, CCU_CLK_TYPE_MISC, 0,			\
> +	     {0}, {0},						\
> +	     {0},						\
> +	     0,							\
> +	     {0}, {0},						\
> +	     0,							\
> +	     CCU_CLK_F_INIT_DONE)

If MISC is really something like GATE or SIMPLE, would it be possible to
construct the single element array here, so that the macro just takes
the one parent clock ID here, instead of referring to an extra array?

> +
> +#define FIXED(_fixed_rate)					\
> +	TREE(NULL, CCU_CLK_TYPE_FIXED, 0,			\
> +	     {0}, {0},						\
> +	     {0},						\
> +	     0,							\
> +	     {0}, {0},						\
> +	     _fixed_rate,					\
> +	     CCU_CLK_F_INIT_DONE)
> +
> +#define NK(_parent, _off,					\
> +	   _nshift, _nwidth,					\
> +	   _kshift, _kwidth, _kmin,				\
> +	   _postdiv,						\
> +	   _flags)						\
> +	TREE(_parent, CCU_CLK_TYPE_NK, _off,			\
> +	     {0}, {0},						\
> +	     {0},						\
> +	     _postdiv,						\
> +	     _CCU_MULT(_nshift, _nwidth),			\
> +	     _CCU_MULT_MIN(_kshift, _kwidth, _kmin),		\
> +	     0,							\
> +	     CCU_CLK_F_INIT_DONE | _flags)
> +
> +#define MP(_parent, _off,					\
> +	   _mshift, _mwidth,					\
> +	   _pshift, _pwidth,					\
> +	   _muxshift, _muxwidth,				\
> +	   _postdiv,						\
> +	   _flags)						\
> +	TREE(_parent, CCU_CLK_TYPE_MP, _off,			\
> +	     _CCU_DIV(_mshift, _mwidth),			\
> +	     _CCU_DIV(_pshift, _pwidth),			\
> +	     _CCU_MUX(_muxshift, _muxwidth),			\
> +	     _postdiv,						\
> +	     {0}, {0},						\
> +	     0,							\
> +	     CCU_CLK_F_INIT_DONE | _flags)
> +
>  /**
>   * struct ccu_clk_gate - ccu clock gate
>   * @off:	gate offset
> @@ -59,6 +248,7 @@ struct ccu_reset {
>   * @resets:	reset unit
>   */
>  struct ccu_desc {
> +	const struct ccu_clk_tree *tree;
>  	const struct ccu_clk_gate *gates;
>  	const struct ccu_reset *resets;
>  };
> diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
> index 162ec769d6..1d0cd98183 100644
> --- a/drivers/clk/sunxi/clk_a64.c
> +++ b/drivers/clk/sunxi/clk_a64.c
> @@ -12,6 +12,45 @@
>  #include <dt-bindings/clock/sun50i-a64-ccu.h>
>  #include <dt-bindings/reset/sun50i-a64-ccu.h>
>  
> +#define CLK_APB2			26
> +#define CLK_OSC_32K			(CLK_GPU + 1)
> +#define CLK_OSC_24M			(CLK_OSC_32K + 1)
> +
> +static const unsigned long periph0_parents[] = {

Why is this long? That's the DT clock index, which is 32 bit wide,
right? Just unsigned int or uint32_t should be sufficient. long is quite
a treacherous type to use, especially as we share code between 32 and
64-bit architectures.

> +	CLK_OSC_24M,
> +};
> +
> +static const unsigned long apb2_parents[] = {
> +	CLK_OSC_32K,
> +	CLK_OSC_24M,
> +	CLK_PLL_PERIPH0,
> +	CLK_PLL_PERIPH0,
> +};
> +
> +static const unsigned long uart_parents[] = {
> +	CLK_APB2,
> +};
> +
> +static const struct ccu_clk_tree a64_tree[] = {
> +	[CLK_OSC_32K]		= FIXED(OSC_32K_ULL),
> +	[CLK_OSC_24M]		= FIXED(OSC_24M_ULL),
> +
> +	[CLK_PLL_PERIPH0]	= NK(periph0_parents, 0x028,
> +				     8, 5,	/* N */
> +				     4, 2, 2,	/* K */
> +				     2,		/* post-div */
> +				     CCU_CLK_F_POSTDIV),
> +
> +	[CLK_APB2]		= MP(apb2_parents, 0x058,
> +				     0, 5,	/* M */
> +				     16, 2,	/* P */
> +				     24, 2,	/* mux */
> +				     0,
> +				     0),
> +
> +	[CLK_BUS_UART0]		= MISC(uart_parents),
> +};
> +
>  static const struct ccu_clk_gate a64_gates[] = {
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
>  	[CLK_BUS_EHCI0]		= GATE(0x060, BIT(24)),
> @@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = {
>  };
>  
>  static const struct ccu_desc a64_ccu_desc = {
> +	.tree = a64_tree,
>  	.gates = a64_gates,
>  	.resets = a64_resets,
>  };
> diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
> index 345d706c2a..2aebd257d1 100644
> --- a/drivers/clk/sunxi/clk_sunxi.c
> +++ b/drivers/clk/sunxi/clk_sunxi.c
> @@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
>  	return &priv->desc->gates[id];
>  }
>  
> +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv *priv,
> +					       unsigned long id)

Again, why long here? Especially as it's u32 in the function below.

> +{
> +	return &priv->desc->tree[id];
> +}
> +
> +static int sunxi_get_parent_idx(const struct ccu_clk_tree *tree, void *base)
> +{
> +	u32 reg, idx;
> +
> +	reg = readl(base + tree->off);
> +	idx = reg >> tree->mux.shift;
> +	idx &= (1 << tree->mux.width) - 1;
> +
> +	return idx;
> +}
> +
> +static ulong sunxi_fixed_get_rate(struct clk *clk, unsigned long id)

Same "long" question for both the return type and the id.
And for everything below.

> +{
> +	struct ccu_priv *priv = dev_get_priv(clk->dev);
> +	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> +
> +	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> +		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
> +		return 0;
> +	}
> +
> +	return tree->fixed_rate;
> +}
> +

So why are there all those separate functions? Isn't that all the same
algorithm: adjust the parent rate based on the clock type?
I reworked this with recursive calls and it's MUCH less code:

(fill the gaps, using your types for your convenience ;-)

static ulong sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong
parent_rate) { NK algorithm of sunxi_nk_get_rate }
static ulong sunxi_apply_div(struct ccu_priv *priv, ulong id, ulong
parent_rate) { MP algorithm of sunxi_mp_get_rate }
static ulong sunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid)
{
....
	switch (tree->type) {
	case CCU_CLK_TYPE_MISC:
		return sunxi_calc_clk_rate(priv, tree->parent[0]);
	case CCU_CLK_TYPE_FIXED:
		return tree->fixed_rate;
	case CCU_CLK_TYPE_NK:
		rate = sunxi_calc_clk_rate(priv,
			sunxi_get_parent_id(tree, priv->base));
		return sunxi_apply_pll(priv, clkid, rate);
	(similar for _MP)
...
}

static ulong sunxi_clk_get_rate(struct clk *clk)
{
	struct ccu_priv *priv = dev_get_priv(clk->dev);

	return sunxi_calc_clk_rate(priv, clk->id);
}

This removes about 80 lines from that file.
Let me know if I should post my rework.

Cheers,
Andre.

> +static ulong sunxi_nk_get_parent_rate(struct clk *clk, unsigned long id)
> +{
> +	struct ccu_priv *priv = dev_get_priv(clk->dev);
> +	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> +	ulong rate = 0;
> +
> +	switch (tree->type) {
> +	case CCU_CLK_TYPE_FIXED:
> +		rate = sunxi_fixed_get_rate(clk, id);
> +		break;
> +	default:
> +		printf("%s: Unknown (TYPE#%d)\n", __func__, tree->type);
> +		break;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong sunxi_nk_get_rate(struct clk *clk, unsigned long id)
> +{
> +	struct ccu_priv *priv = dev_get_priv(clk->dev);
> +	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> +	ulong rate, parent_rate;
> +	unsigned long n, k;
> +	u32 reg;
> +
> +	parent_rate = sunxi_nk_get_parent_rate(clk, tree->parent[0]);
> +
> +	reg = readl(priv->base + tree->off);
> +
> +	n = reg >> tree->n.shift;
> +	n &= (1 << tree->n.width) - 1;
> +	n += tree->n.offset;
> +	if (!n)
> +		n++;
> +
> +	k = reg >> tree->k.shift;
> +	k &= (1 << tree->k.width) - 1;
> +	k += tree->k.offset;
> +	if (!k)
> +		k++;
> +
> +	rate = parent_rate * n * k;
> +	if (tree->flags & CCU_CLK_F_POSTDIV)
> +		rate /= tree->postdiv;
> +
> +	return rate;
> +}
> +
> +static ulong sunxi_mp_get_parent_rate(struct clk *clk, unsigned long id)
> +{
> +	struct ccu_priv *priv = dev_get_priv(clk->dev);
> +	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> +	ulong rate = 0;
> +
> +	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> +		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
> +		return 0;
> +	}
> +
> +	switch (tree->type) {
> +	case CCU_CLK_TYPE_FIXED:
> +		rate = sunxi_fixed_get_rate(clk, id);
> +		break;
> +	case CCU_CLK_TYPE_NK:
> +		rate = sunxi_nk_get_rate(clk, id);
> +		break;
> +	default:
> +		printf("%s: (TYPE#%d) unhandled\n", __func__, tree->type);
> +		break;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong sunxi_mp_get_rate(struct clk *clk, unsigned long id)
> +{
> +	struct ccu_priv *priv = dev_get_priv(clk->dev);
> +	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> +	unsigned int m, p;
> +	ulong parent_rate;
> +	u32 reg, idx;
> +
> +	idx = sunxi_get_parent_idx(tree, priv->base);
> +	if (idx < 0) {
> +		printf("%s: Wrong parent index %d\n", __func__, idx);
> +		return 0;
> +	}
> +
> +	parent_rate = sunxi_mp_get_parent_rate(clk, tree->parent[idx]);
> +
> +	reg = readl(priv->base + tree->off);
> +
> +	m = reg >> tree->m.shift;
> +	m &= (1 << tree->m.width) - 1;
> +	m += tree->m.offset;
> +	if (!m)
> +		m++;
> +
> +	p = reg >> tree->p.shift;
> +	p &= (1 << tree->p.width) - 1;
> +
> +	return (parent_rate >> p) / m;
> +}
> +
> +static ulong sunxi_misc_get_rate(struct clk *clk, unsigned long id)
> +{
> +	struct ccu_priv *priv = dev_get_priv(clk->dev);
> +	const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> +	ulong rate = 0;
> +
> +	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> +		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
> +		return 0;
> +	}
> +
> +	switch (tree->type) {
> +	case CCU_CLK_TYPE_MP:
> +		rate = sunxi_mp_get_rate(clk, id);
> +		break;
> +	default:
> +		printf("%s: (TYPE#%d) unhandled\n", __func__, tree->type);
> +		break;
> +	}
> +
> +	return rate;
> +}
> +
> +static ulong sunxi_clk_get_rate(struct clk *clk)
> +{
> +	struct ccu_priv *priv = dev_get_priv(clk->dev);
> +	const struct ccu_clk_tree *tree = priv_to_tree(priv, clk->id);
> +	ulong rate = 0;
> +
> +	if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> +		printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
> +		return 0;
> +	}
> +
> +	switch (tree->type) {
> +	case CCU_CLK_TYPE_MISC:
> +		rate = sunxi_misc_get_rate(clk, tree->parent[0]);
> +		break;
> +	default:
> +		printf("%s: (TYPE#%d) unhandled\n", __func__, tree->type);
> +		break;
> +	}
> +
> +	return rate;
> +}
> +
>  static int sunxi_set_gate(struct clk *clk, bool on)
>  {
>  	struct ccu_priv *priv = dev_get_priv(clk->dev);
> @@ -56,6 +237,7 @@ static int sunxi_clk_disable(struct clk *clk)
>  struct clk_ops sunxi_clk_ops = {
>  	.enable = sunxi_clk_enable,
>  	.disable = sunxi_clk_disable,
> +	.get_rate = sunxi_clk_get_rate,
>  };
>  
>  int sunxi_clk_probe(struct udevice *dev)
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support
  2019-01-06 19:22   ` Jagan Teki
@ 2019-01-07  1:21     ` André Przywara
  0 siblings, 0 replies; 49+ messages in thread
From: André Przywara @ 2019-01-07  1:21 UTC (permalink / raw)
  To: u-boot

On 06/01/2019 19:22, Jagan Teki wrote:
> On Sun, Jan 6, 2019 at 6:49 PM André Przywara <andre.przywara@arm.com> wrote:
>>
>> On 31/12/2018 16:59, Jagan Teki wrote:
>>
>> Hi Jagan,
>>
>> many thanks for picking this up, I was about to come back to this
>> myself. I am looking at the pinctrl part at the moment, so good you are
>> working on the clocks!
>>
>> TL;DR: I am good with the first patches, but would like to drop the last
>> five 5 patches from this series, and discuss the whole tree approach (or
>> at least the patch) further.
>>
>>> Although the previous version[1] is properly handled the clock gates
>>> with enable and disable management, but this series is trying to add
>>> some more complex Allwinner CLK architecture by handling parent clock
>>> and other CLK attributes.
>>>
>>> Allwinner Clock control unit comprises of parent clocks, gates, multiplexers,
>>> dividers, multipliers, pre/post dividers and flags etc.
>>>
>>> So, the U-Boot implementation of ccu has divided into gates and tree.
>>> gates are generic clock configuration of enable/disable bit management
>>> and these can be handled via ccu_clock_gate, which is almost same as
>>> previous version changes.
>>
>> So I like this part very much, all those gates and resets are nicely
>> readable.
>> Also the removal of the special sunxi USB drivers is very welcome.
>> So up until patch including 21/26, except 15/26, I am all in.
> 
> Yes my plan is to do the same.
> 
>>
>>> Tree clock has more Allwinner CLK attributes like clock type, fixed clocks,
>>> misc clocks, mp, nk, nkm, nkmp, pre/post div, flags etc and these can be
>>> managed via ccu_clock_tree.
>>
>> Mmmh, this looks quite complex for U-Boot's very limited needs to me.
>> As far as I can see we basically have a static setup for most devices,
>> the ones where we actually change the parent clocks are only clock
>> consumers, namely DE/TCON and MMC. The former chooses a parent once,
>> based on the calculated clock rate. Only for MMC we switch it from OSC24
>> (for the initial SPI-like setup phase) to PLL_PERIPH0 at runtime.
>> But however this does not really affect the tree, and also we never do
>> re-parenting.
>> Under this premises, can't we do this somewhat simpler? At the end of
>> the day this is U-Boot, not a sophisticated kernel, and we got away with
>> quite simple clock code so far.
> 
> Yes, Idea is to go with limited clock setups but the thing is as you
> know Allwinner deals numerous number of clock attributes and I found
> it difficult to handle them w/o traversing the re-parenting stuff. I
> have tried simple version of set_rate in previous version[2] but it
> wouldn't ended as we desired. These operations need re-parenting, so
> we have to handle parents in clock attributes.

Just for clarification: with re-parenting I meant selecting a different
parent clock *at runtime*, potentially adjusting other clocks which
depend on that. We would not need that in U-Boot, fortunately.

> So finally I came up with tree structure.

Yeah, so looking at patch 15/26 in more detail this is probably the way
to go. I was just hit by that wall of code. Implementing get_rate in a
recursive fashion reduces the file size drastically, see the reply to
that patch.
I was just concerned that making this all data structure based (as
opposed to handle them all in a giant switch/case) would require to
abstract this too much, up to a point where it gets more complicated.
Especially when it comes to special clocks like the MMC beast with its
new clock mode.

> My idea here is to support get and set rate with minimal re-parenting
> like OSC24, PLL_PERIPH0, PLL_PERIPH1 not adding much code like Linux
> does. Like GATE macro, TREE macro is also a readable structure with
> all possible/needed clk attributes at one glance. The code that handle
> these tree attributes may look confusing, but it is obvious because it
> would need to handle re-parenting.
> 
> If SoC has a big CLK architecture like this and to support all or
> needed clock operations, re-parenting may be one of painful code for
> SoC driver in U-Boot, Since CLK framework doesn't handle these
> generically(may be no need) as compared to Linux. and the existing SoC
> like mediatek clock code does the same.
> 
> At, this point, I think this tree approach can be possible way to move
> since it handle all clock attribute types and yes we can only support
> clock re-parenting which are required for U-Boot.

Yeah, so we need to traverse a clock tree to get and set the parent
rate. I think with the recursive rework this is now quite neat,
especially as we can keep the per-SoC code small.
We just have to see how the special clocks blend in there.

>> Meanwhile I am struggling to understand your approach, which looks
>> impressive on the first glance, but leave me scratching my head when
>> looking at details. I will comment on 15/26 for the parts I am wondering
>> about. I was trying to add MMC support and hit some issues.
> 
> As I said above there is no generic way to handle re-parenting in
> U-Boot, and we need to traverse based on the SoC Clock architecture.
> 
> 15/26 handling get_rate, say for example UART request a get_rate.
> 
> 
>                               |==> OSC_32K
> UART-->APB2--->|==> OSC_24M
>                               |==> PLL_PH0   ===> OSC_24M
>                               |==> PLL_PH0
> 
> Each clock tree, has clock type so UART is marked as MISC since it
> can't not usual clock tree unlike MMC. MMC can be MP clock type and
> so..on
> 
> So, if driver requesting get_rate with UART clock, then we need to
> traverse all the UART clock tree and get the rate based on the type
> and identified parent clock. UART is MISC so it can directly trigger
> parent clock abp2, apb2 need to find the parent using mux shift,
> width, once apb2 found the parent it will go to next as so on.

Yeah, I understand this, but was hoping we could handle this in a
switch/case, for clarity. Those macro designs look nice, but are hard to
understand for outsiders.
But I now think that your data driven approach is better to support
multiple SoCs. I can write up some documentation for this.

>> On the SPI part:
>> I am bit puzzled about the last 5 patches dealing with SPI. I see that
>> they depend on the others, but would like to deal with them separately.
> 
> True, but these are previous version changes ie reason I grouped it
> here. anyway will handle accordingly in next versions.
> 
>> First, patch 25/26 (the sun6i SPI driver) is a bit surprising to find in
>> here. I guess you want to have an easy user for another clock, but I
>> believe this should be a separate series. There were other posts already
>> for a sun6i driver, also I think we should have a unified driver instead
>> of duplicating most of it again. See Oskari's latest post.
> 
> Yes, I saw this sun6i driver is lasting for many releases and my plan
> it to unified the driver w/o any ifdef.

So I did this, basically by introducing a register map for both
versions. That works, but is not very nice. Oskari's patch has the
advantage of being quite small, and we will probably never need to
support both SPI devices in one build.

>> Secondly: I don't think the SPI clocks are correct. You model them as
>> simple gates only, kind of ignoring the divider settings. This is what
>> the current sun4i driver does as well, but: it writes 1U << 31 into the
>> clock register, which explicitly writes 0 to the other bits, setting 24
>> MHz as the input rate. Your approach would read-modify-write the
>> register, just setting bit 31 and leaving the other ones as they were
>> before.
>> So why isn't that using your new tree approach? Looks like a standard
>> mux/divider clock to me.
> 
> Yes these yet to implement, ie reason I have just added clk tree only
> on A64. Idea is to send next version for full support on all SoC
> types.

Do we need to merge this for all SoCs in the beginning? I think it would
be safer to test this on one SoC (A64) first, to avoid breaking everyone
in case of problems. Especially if we can't test this on every board.

Cheers,
Andre.


> [2] https://patchwork.ozlabs.org/patch/955993/
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-07  1:03   ` André Przywara
@ 2019-01-07 13:01     ` Maxime Ripard
  2019-01-07 14:09       ` Andre Przywara
  2019-01-08 10:57     ` Jagan Teki
  2019-01-08 11:25     ` Jagan Teki
  2 siblings, 1 reply; 49+ messages in thread
From: Maxime Ripard @ 2019-01-07 13:01 UTC (permalink / raw)
  To: u-boot

On Mon, Jan 07, 2019 at 01:03:33AM +0000, André Przywara wrote:
> On 31/12/2018 16:59, Jagan Teki wrote:
> > Clock control unit comprises of parent clocks, gates, multiplexers,
> > dividers, multipliers, pre/post dividers and flags etc.
> > 
> > So, the U-Boot implementation of ccu has divided into gates and tree.
> > gates are generic clock configuration of enable/disable bit management
> > which can be handle via ccu_clock_gate.
> 
> So if I understand this correctly, you implement the gate functionality
> separately from the complex clock code, even if they are the same clock
> from the DT point of view? So if one wants to enable the MMC0 clock,
> which is a mux/divider clock, one needs to specify an extra entry in the
> gate array to describe the enable bit in this special clock register?
> Sounds a bit surprising, but is probably a neat trick to keep things
> simple. There should be a comment in the code to this regard then.
> 
> > Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp,
> > pre/post div, flags etc. which were managed via ccu_clock_tree.
> 
> For a start, can we use more descriptive names than those very specific
> MP/NK names? DIV_MUX and PLL sound more descriptive to me. I understand
> that Linux uses those terms, but it would be great if uninitiated people
> have a chance to understand this as well.
> 
> > This patch add support for MP, NK, MISC, FIXED clock types as part of
> > ccu clock tree with get_rate functionality this eventually used by
> > uart driver. and rest of the infrastructure will try to add while CLK
> > is being used on respective peripherals.
> > 
> > Note that few of the tree type clock would require to enable gates on
> > their specific clock, in that case we need to add the gate details via
> > ccu_clock_gate, example: MP with gate so the gate offset, bit value
> > should add as part of ccu_clock_gate.
> > 
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++-
> >  drivers/clk/sunxi/clk_a64.c           |  40 ++++++
> >  drivers/clk/sunxi/clk_sunxi.c         | 182 ++++++++++++++++++++++++
> >  3 files changed, 413 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
> > index 3fdc26978d..61b8c36b3b 100644
> > --- a/arch/arm/include/asm/arch-sunxi/ccu.h
> > +++ b/arch/arm/include/asm/arch-sunxi/ccu.h
> > @@ -7,15 +7,204 @@
> >  #ifndef _ASM_ARCH_CCU_H
> >  #define _ASM_ARCH_CCU_H
> >  
> > +#define OSC_32K_ULL		32000ULL
> 
> 32768
> 
> And why ULL? The whole Allwinner clock system works with 32-bit values,
> so just U would be totally sufficient. This avoid blowing this up to 64
> bit unnecessarily, which sounds painful for those poor ARMv7 parts.
> 
> > +#define OSC_24M_ULL		24000000ULL
> > +
> > +/**
> > + * enum ccu_clk_type - ccu clock types
> > + *
> > + * @CCU_CLK_TYPE_MISC:			misc clock type
> 
> What is MISC, exactly? Seems like an artefact clock to me, some
> placeholder you need because gate clocks are handled separately in the
> gates struct. Should this be called something with SIMPLE instead, or GATE?
> 
> > + * @CCU_CLK_TYPE_FIXED:			fixed clock type
> > + * @CCU_CLK_TYPE_MP:			mp clock type
> > + * @CCU_CLK_TYPE_NK:			nk clock type
> 
> What is the point of those comments, as you are basically repeating the
> enum name? What about:
>  * @CCU_CLK_TYPE_PLL:		PLL clock with two multiplier fields

We have PLL with 2 multipliers, but also others with other factors
sets, so that will end up being confusing. If the MP, NK and so on
stuff is confusing, maybe we should just add a comment on top of that
structure to explain what those factors are and what it actually
means?

Maxime

-- 
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190107/26a42f3f/attachment.sig>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
@ 2019-01-07 13:04   ` Maxime Ripard
  2019-01-22 16:32   ` Alexander Graf
  1 sibling, 0 replies; 49+ messages in thread
From: Maxime Ripard @ 2019-01-07 13:04 UTC (permalink / raw)
  To: u-boot

On Mon, Dec 31, 2018 at 10:29:27PM +0530, Jagan Teki wrote:
> Sopine has Winbond SPI flash, so enable the same to use
> flash on Sopine board.
> 
> Cc: TL Lim <tllim@pine64.org>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi  | 16 ++++++++++++++++
>  configs/sopine_baseboard_defconfig               |  7 +++++++
>  2 files changed, 23 insertions(+)
>  create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> 
> diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> new file mode 100644
> index 0000000000..9661b95d15
> --- /dev/null
> +++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> @@ -0,0 +1,16 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2018 Jagan Teki <jagan@amarulasolutions.com>
> + */
> +
> +/ {
> +	aliases {
> +		spi0 = &spi0;
> +	};
> +};
> +
> +&spi0  {
> +	flash at 0 {
> +		compatible = "spi-flash";
> +	};
> +};
> diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
> index 0a189fc03d..5e6dc33d4d 100644
> --- a/configs/sopine_baseboard_defconfig
> +++ b/configs/sopine_baseboard_defconfig
> @@ -12,9 +12,16 @@ CONFIG_SPL_SPI_SUNXI=y
>  CONFIG_NR_DRAM_BANKS=1
>  # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
>  # CONFIG_CMD_FLASH is not set
> +CONFIG_CMD_SF=y
>  # CONFIG_SPL_DOS_PARTITION is not set
>  # CONFIG_SPL_EFI_PARTITION is not set
>  CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-sopine-baseboard"
> +CONFIG_SPI=y
> +CONFIG_DM_SPI=y
> +CONFIG_SUN6I_SPI=y
> +CONFIG_DM_SPI_FLASH=y
> +CONFIG_SPI_FLASH=y
> +CONFIG_SPI_FLASH_WINBOND=y

SPI, DM_SPI and SUN6I_SPI seem redundant to me, just like
SPI_FLASH_WINBOND, DM_SPI_FLASH, and SPI_FLASH.

We should do better to provide the needed Kconfig select/depends
on/defaults to have to enable only the SPI_FLASH_WINBOND. Everything
else can be derived from that.

Maxime

-- 
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190107/04c82823/attachment.sig>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-07 13:01     ` Maxime Ripard
@ 2019-01-07 14:09       ` Andre Przywara
  2019-01-07 18:25         ` Maxime Ripard
  0 siblings, 1 reply; 49+ messages in thread
From: Andre Przywara @ 2019-01-07 14:09 UTC (permalink / raw)
  To: u-boot

On Mon, 7 Jan 2019 14:01:01 +0100
Maxime Ripard <maxime.ripard@bootlin.com> wrote:

Hi,

> On Mon, Jan 07, 2019 at 01:03:33AM +0000, André Przywara wrote:
> > On 31/12/2018 16:59, Jagan Teki wrote:  
> > > Clock control unit comprises of parent clocks, gates,
> > > multiplexers, dividers, multipliers, pre/post dividers and flags
> > > etc.
> > > 
> > > So, the U-Boot implementation of ccu has divided into gates and
> > > tree. gates are generic clock configuration of enable/disable bit
> > > management which can be handle via ccu_clock_gate.  
> > 
> > So if I understand this correctly, you implement the gate
> > functionality separately from the complex clock code, even if they
> > are the same clock from the DT point of view? So if one wants to
> > enable the MMC0 clock, which is a mux/divider clock, one needs to
> > specify an extra entry in the gate array to describe the enable bit
> > in this special clock register? Sounds a bit surprising, but is
> > probably a neat trick to keep things simple. There should be a
> > comment in the code to this regard then. 
> > > Tree clocks are parent clock type, fixed clocks, mp, nk, nkm,
> > > nkmp, pre/post div, flags etc. which were managed via
> > > ccu_clock_tree.  
> > 
> > For a start, can we use more descriptive names than those very
> > specific MP/NK names? DIV_MUX and PLL sound more descriptive to me.
> > I understand that Linux uses those terms, but it would be great if
> > uninitiated people have a chance to understand this as well.
> >   
> > > This patch add support for MP, NK, MISC, FIXED clock types as
> > > part of ccu clock tree with get_rate functionality this
> > > eventually used by uart driver. and rest of the infrastructure
> > > will try to add while CLK is being used on respective peripherals.
> > > 
> > > Note that few of the tree type clock would require to enable
> > > gates on their specific clock, in that case we need to add the
> > > gate details via ccu_clock_gate, example: MP with gate so the
> > > gate offset, bit value should add as part of ccu_clock_gate.
> > > 
> > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > ---
> > >  arch/arm/include/asm/arch-sunxi/ccu.h | 192
> > > +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c
> > > |  40 ++++++ drivers/clk/sunxi/clk_sunxi.c         | 182
> > > ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1
> > > deletion(-)
> > > 
> > > diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h
> > > b/arch/arm/include/asm/arch-sunxi/ccu.h index
> > > 3fdc26978d..61b8c36b3b 100644 ---
> > > a/arch/arm/include/asm/arch-sunxi/ccu.h +++
> > > b/arch/arm/include/asm/arch-sunxi/ccu.h @@ -7,15 +7,204 @@
> > >  #ifndef _ASM_ARCH_CCU_H
> > >  #define _ASM_ARCH_CCU_H
> > >  
> > > +#define OSC_32K_ULL		32000ULL  
> > 
> > 32768
> > 
> > And why ULL? The whole Allwinner clock system works with 32-bit
> > values, so just U would be totally sufficient. This avoid blowing
> > this up to 64 bit unnecessarily, which sounds painful for those
> > poor ARMv7 parts. 
> > > +#define OSC_24M_ULL		24000000ULL
> > > +
> > > +/**
> > > + * enum ccu_clk_type - ccu clock types
> > > + *
> > > + * @CCU_CLK_TYPE_MISC:			misc clock type  
> > 
> > What is MISC, exactly? Seems like an artefact clock to me, some
> > placeholder you need because gate clocks are handled separately in
> > the gates struct. Should this be called something with SIMPLE
> > instead, or GATE? 
> > > + * @CCU_CLK_TYPE_FIXED:			fixed clock type
> > > + * @CCU_CLK_TYPE_MP:			mp clock type
> > > + * @CCU_CLK_TYPE_NK:			nk clock type  
> > 
> > What is the point of those comments, as you are basically repeating
> > the enum name? What about:
> >  * @CCU_CLK_TYPE_PLL:		PLL clock with two multiplier
> > fields  
> 
> We have PLL with 2 multipliers, but also others with other factors
> sets, so that will end up being confusing. If the MP, NK and so on
> stuff is confusing, maybe we should just add a comment on top of that
> structure to explain what those factors are and what it actually
> means?

Fair enough, or we name it CCU_CLK_TYPE_PLL_NK, because this is what
this type deals with. Point is that by chance I happened to know about
those naming of factors in the manual, but other might be lost by just
seeing "mp" or "nk", without any explanation - and the comment doesn't
help here at all.

The other part is that the "TYPE_MP" is twice as confusing, as it can
perfectly describe the MMC clocks, which use "N" and "M" in the A64
manual, for instance. That's why my suggestion for calling a spade a
spade and saying it's a divider clock with a multiplexer. Happy to have
the Linux naming in the comments.

Thanks,
Andre.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-07 14:09       ` Andre Przywara
@ 2019-01-07 18:25         ` Maxime Ripard
  0 siblings, 0 replies; 49+ messages in thread
From: Maxime Ripard @ 2019-01-07 18:25 UTC (permalink / raw)
  To: u-boot

On Mon, Jan 07, 2019 at 02:09:12PM +0000, Andre Przywara wrote:
> > > What is MISC, exactly? Seems like an artefact clock to me, some
> > > placeholder you need because gate clocks are handled separately in
> > > the gates struct. Should this be called something with SIMPLE
> > > instead, or GATE? 
> > > > + * @CCU_CLK_TYPE_FIXED:			fixed clock type
> > > > + * @CCU_CLK_TYPE_MP:			mp clock type
> > > > + * @CCU_CLK_TYPE_NK:			nk clock type  
> > > 
> > > What is the point of those comments, as you are basically repeating
> > > the enum name? What about:
> > >  * @CCU_CLK_TYPE_PLL:		PLL clock with two multiplier
> > > fields  
> > 
> > We have PLL with 2 multipliers, but also others with other factors
> > sets, so that will end up being confusing. If the MP, NK and so on
> > stuff is confusing, maybe we should just add a comment on top of that
> > structure to explain what those factors are and what it actually
> > means?
> 
> Fair enough, or we name it CCU_CLK_TYPE_PLL_NK, because this is what
> this type deals with. Point is that by chance I happened to know about
> those naming of factors in the manual, but other might be lost by just
> seeing "mp" or "nk", without any explanation - and the comment doesn't
> help here at all.

Either way, we should really document this properly.

> The other part is that the "TYPE_MP" is twice as confusing, as it can
> perfectly describe the MMC clocks, which use "N" and "M" in the A64
> manual, for instance. That's why my suggestion for calling a spade a
> spade and saying it's a divider clock with a multiplexer. Happy to have
> the Linux naming in the comments.

NM and MP aren't really the same though. NM is one multiplier and one
divider, while MP is one divider and one right shift.

Maxime

-- 
Maxime Ripard, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 228 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190107/6e86550c/attachment.sig>

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-07  1:03   ` André Przywara
  2019-01-07 13:01     ` Maxime Ripard
@ 2019-01-08 10:57     ` Jagan Teki
  2019-01-08 11:39       ` Andre Przywara
  2019-01-08 11:25     ` Jagan Teki
  2 siblings, 1 reply; 49+ messages in thread
From: Jagan Teki @ 2019-01-08 10:57 UTC (permalink / raw)
  To: u-boot

On Mon, Jan 7, 2019 at 6:35 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 31/12/2018 16:59, Jagan Teki wrote:
> > Clock control unit comprises of parent clocks, gates, multiplexers,
> > dividers, multipliers, pre/post dividers and flags etc.
> >
> > So, the U-Boot implementation of ccu has divided into gates and tree.
> > gates are generic clock configuration of enable/disable bit management
> > which can be handle via ccu_clock_gate.
>
> So if I understand this correctly, you implement the gate functionality
> separately from the complex clock code, even if they are the same clock
> from the DT point of view? So if one wants to enable the MMC0 clock,
> which is a mux/divider clock, one needs to specify an extra entry in the
> gate array to describe the enable bit in this special clock register?
> Sounds a bit surprising, but is probably a neat trick to keep things
> simple. There should be a comment in the code to this regard then.

Exactly. Idea is to keep the macro's as simple as possible.

Adding gates clocks separately make easy and reasonable way to
enable/disable clock operations. We even operate with single macro
with all clock attributes along with gate(either another member or
common structure like Linux does), but that seems not simple as per as
my experince since there are many IP's like USB's just need
enable/disable.

>
> > Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp,
> > pre/post div, flags etc. which were managed via ccu_clock_tree.
>
> For a start, can we use more descriptive names than those very specific
> MP/NK names? DIV_MUX and PLL sound more descriptive to me. I understand
> that Linux uses those terms, but it would be great if uninitiated people
> have a chance to understand this as well.
>
> > This patch add support for MP, NK, MISC, FIXED clock types as part of
> > ccu clock tree with get_rate functionality this eventually used by
> > uart driver. and rest of the infrastructure will try to add while CLK
> > is being used on respective peripherals.
> >
> > Note that few of the tree type clock would require to enable gates on
> > their specific clock, in that case we need to add the gate details via
> > ccu_clock_gate, example: MP with gate so the gate offset, bit value
> > should add as part of ccu_clock_gate.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++-
> >  drivers/clk/sunxi/clk_a64.c           |  40 ++++++
> >  drivers/clk/sunxi/clk_sunxi.c         | 182 ++++++++++++++++++++++++
> >  3 files changed, 413 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
> > index 3fdc26978d..61b8c36b3b 100644
> > --- a/arch/arm/include/asm/arch-sunxi/ccu.h
> > +++ b/arch/arm/include/asm/arch-sunxi/ccu.h
> > @@ -7,15 +7,204 @@
> >  #ifndef _ASM_ARCH_CCU_H
> >  #define _ASM_ARCH_CCU_H
> >
> > +#define OSC_32K_ULL          32000ULL
>
> 32768
>
> And why ULL? The whole Allwinner clock system works with 32-bit values,
> so just U would be totally sufficient. This avoid blowing this up to 64
> bit unnecessarily, which sounds painful for those poor ARMv7 parts.
>
> > +#define OSC_24M_ULL          24000000ULL
> > +
> > +/**
> > + * enum ccu_clk_type - ccu clock types
> > + *
> > + * @CCU_CLK_TYPE_MISC:                       misc clock type
>
> What is MISC, exactly? Seems like an artefact clock to me, some
> placeholder you need because gate clocks are handled separately in the
> gates struct. Should this be called something with SIMPLE instead, or GATE?

Unlike MP type in MMC, UART doesn't need any clock attributes like
dividers, mux, etc, just have attached parent. I don't think UART
clock is simple one It has parent, that indeed have another parents
and so...on, ie reason I named as MISC.

>
> > + * @CCU_CLK_TYPE_FIXED:                      fixed clock type
> > + * @CCU_CLK_TYPE_MP:                 mp clock type
> > + * @CCU_CLK_TYPE_NK:                 nk clock type
>
> What is the point of those comments, as you are basically repeating the
> enum name? What about:
>  * @CCU_CLK_TYPE_PLL:           PLL clock with two multiplier fields
>  * @CCU_CLK_TYPE_MUX_DIV:       multiple parents, two divider fields
>
> This gives more speaking names, plus some explanation.
>
> > + */
> > +enum ccu_clk_type {
> > +     CCU_CLK_TYPE_MISC               = 0,
> > +     CCU_CLK_TYPE_FIXED              = 1,
> > +     CCU_CLK_TYPE_MP                 = 2,
> > +     CCU_CLK_TYPE_NK                 = 3,
> > +};
> > +
> >  /**
> >   * enum ccu_clk_flags - ccu clock flags
> >   *
> > - * @CCU_CLK_F_INIT_DONE:             clock gate init done check
> > + * @CCU_CLK_F_INIT_DONE:             clock tree/gate init done check
>
> Is this flag to tell implemented clocks apart from unimplemented ones,
> which would be reset to all zeroes by the compiler? Then it should be
> called something with VALID in it.

Since the flags attached with real numeric initialized by macro itself
rather than some other source like complier or any, so marked
INIT_DONE seems to meaningful.
and eventually the same verified in code whether the init done or not.

>
> > + * @CCU_CLK_F_POSTDIV:                       clock post divider
> >   */
> >  enum ccu_clk_flags {
> >       CCU_CLK_F_INIT_DONE             = BIT(0),
> > +     CCU_CLK_F_POSTDIV               = BIT(1),
> >  };
> >
> > +/**
> > + * struct ccu_mult - ccu clock multiplier
> > + *
> > + * @shift:           multiplier shift value
> > + * @width:           multiplier width value
> > + * @offset:          multiplier offset
> > + * @min:             minimum multiplier
> > + * @max:             maximum multiplier
> > + */
> > +struct ccu_mult {
> > +     u8 shift;
> > +     u8 width;
> > +     u8 offset;
> > +     u8 min;
> > +     u8 max;
> > +};
> > +
> > +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width, _offset,               \
> > +                           _min, _max) {                     \
> > +     .shift = _shift,                                        \
> > +     .width = _width,                                        \
> > +     .offset = _offset,                                      \
> > +     .min = _min,                                            \
> > +     .max = _max,                                            \
> > +}
> > +
> > +#define _CCU_MULT_MIN(_shift, _width, _min)                  \
> > +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0)
> > +
> > +#define _CCU_MULT(_shift, _width)                            \
> > +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0)
> > +
> > +/**
> > + * struct ccu_mux - ccu clock multiplexer
> > + *
> > + * @shift:           multiplexer shift value
> > + * @width:           multiplexer width value
> > + */
> > +struct ccu_mux {
> > +     u8 shift;
> > +     u8 width;
> > +};
> > +
> > +#define _CCU_MUX(_shift, _width) {           \
> > +     .shift = _shift,                        \
> > +     .width = _width,                        \
> > +}
> > +
> > +/**
> > + * struct ccu_div - ccu clock divider
> > + *
> > + * @shift:           divider shift value
> > + * @width:           divider width value
> > + * @offset:          divider offset
> > + * @max:             maximum divider value
> > + */
> > +struct ccu_div {
> > +     u8 shift;
> > +     u8 width;
> > +     u32 offset;
> > +     u32 max;
> > +};
> > +
> > +#define _CCU_DIV(_shift, _width) {           \
> > +     .shift = _shift,                        \
> > +     .width = _width,                        \
> > +     .offset = 1,                            \
> > +     .max = 0,                               \
> > +}
> > +
> > +/**
> > + * struct ccu_clk_tree - ccu clock tree
> > + *
> > + * @parent:          parent clock tree
> > + * @type:            clock type
> > + * @off:             clock tree offset
> > + * @m:                       divider m
> > + * @p:                       divider p
> > + * @mux:             multiplexer mux
> > + * @post:            post divider value
> > + * @n:                       multiplier n
> > + * @k:                       multiplier k
> > + * @fixed_rate:              fixed rate
> > + * @flags:           clock tree flags
> > + */
> > +struct ccu_clk_tree {
> > +     const unsigned long *parent;
>
> Shouldn't that be called "parents" instead?
>
> > +     enum ccu_clk_type type;
> > +     u16 off;
> > +
> > +     struct ccu_div m;
> > +     struct ccu_div p;
> > +     struct ccu_mux mux;
> > +     unsigned int postdiv;
> > +
> > +     struct ccu_mult n;
> > +     struct ccu_mult k;
> > +
> > +     ulong fixed_rate;
> > +     enum ccu_clk_flags flags;
> > +};
> > +
> > +#define TREE(_parent, _type, _off,                           \
>
> Just a nit, but TREE is somewhat confusing here, as this just constructs
> a single entry in an array. The tree property is realised through the
> parent array, if I get this correctly.
> So should we name this ENTRY or CLK_ENTRY instead?
>
> > +          _m, _p,                                            \
> > +          _mux,                                              \
> > +          _postdiv,                                          \
> > +          _n, _k,                                            \
> > +          _fixed_rate,                                       \
> > +          _flags) {                                          \
> > +     .parent = _parent,                                      \
> > +     .type = _type,                                          \
> > +     .off = _off,                                            \
> > +     .m = _m,                                                \
> > +     .p = _p,                                                \
> > +     .mux = _mux,                                            \
> > +     .postdiv = _postdiv,                                    \
> > +     .n = _n,                                                \
> > +     .k = _k,                                                \
> > +     .fixed_rate = _fixed_rate,                              \
> > +     .flags = _flags,                                        \
> > +}
> > +
> > +#define MISC(_parent)                                                \
> > +     TREE(_parent, CCU_CLK_TYPE_MISC, 0,                     \
> > +          {0}, {0},                                          \
> > +          {0},                                               \
> > +          0,                                                 \
> > +          {0}, {0},                                          \
> > +          0,                                                 \
> > +          CCU_CLK_F_INIT_DONE)
>
> If MISC is really something like GATE or SIMPLE, would it be possible to
> construct the single element array here, so that the macro just takes
> the one parent clock ID here, instead of referring to an extra array?
>
> > +
> > +#define FIXED(_fixed_rate)                                   \
> > +     TREE(NULL, CCU_CLK_TYPE_FIXED, 0,                       \
> > +          {0}, {0},                                          \
> > +          {0},                                               \
> > +          0,                                                 \
> > +          {0}, {0},                                          \
> > +          _fixed_rate,                                       \
> > +          CCU_CLK_F_INIT_DONE)
> > +
> > +#define NK(_parent, _off,                                    \
> > +        _nshift, _nwidth,                                    \
> > +        _kshift, _kwidth, _kmin,                             \
> > +        _postdiv,                                            \
> > +        _flags)                                              \
> > +     TREE(_parent, CCU_CLK_TYPE_NK, _off,                    \
> > +          {0}, {0},                                          \
> > +          {0},                                               \
> > +          _postdiv,                                          \
> > +          _CCU_MULT(_nshift, _nwidth),                       \
> > +          _CCU_MULT_MIN(_kshift, _kwidth, _kmin),            \
> > +          0,                                                 \
> > +          CCU_CLK_F_INIT_DONE | _flags)
> > +
> > +#define MP(_parent, _off,                                    \
> > +        _mshift, _mwidth,                                    \
> > +        _pshift, _pwidth,                                    \
> > +        _muxshift, _muxwidth,                                \
> > +        _postdiv,                                            \
> > +        _flags)                                              \
> > +     TREE(_parent, CCU_CLK_TYPE_MP, _off,                    \
> > +          _CCU_DIV(_mshift, _mwidth),                        \
> > +          _CCU_DIV(_pshift, _pwidth),                        \
> > +          _CCU_MUX(_muxshift, _muxwidth),                    \
> > +          _postdiv,                                          \
> > +          {0}, {0},                                          \
> > +          0,                                                 \
> > +          CCU_CLK_F_INIT_DONE | _flags)
> > +
> >  /**
> >   * struct ccu_clk_gate - ccu clock gate
> >   * @off:     gate offset
> > @@ -59,6 +248,7 @@ struct ccu_reset {
> >   * @resets:  reset unit
> >   */
> >  struct ccu_desc {
> > +     const struct ccu_clk_tree *tree;
> >       const struct ccu_clk_gate *gates;
> >       const struct ccu_reset *resets;
> >  };
> > diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
> > index 162ec769d6..1d0cd98183 100644
> > --- a/drivers/clk/sunxi/clk_a64.c
> > +++ b/drivers/clk/sunxi/clk_a64.c
> > @@ -12,6 +12,45 @@
> >  #include <dt-bindings/clock/sun50i-a64-ccu.h>
> >  #include <dt-bindings/reset/sun50i-a64-ccu.h>
> >
> > +#define CLK_APB2                     26
> > +#define CLK_OSC_32K                  (CLK_GPU + 1)
> > +#define CLK_OSC_24M                  (CLK_OSC_32K + 1)
> > +
> > +static const unsigned long periph0_parents[] = {
>
> Why is this long? That's the DT clock index, which is 32 bit wide,
> right? Just unsigned int or uint32_t should be sufficient. long is quite
> a treacherous type to use, especially as we share code between 32 and
> 64-bit architectures.
>
> > +     CLK_OSC_24M,
> > +};
> > +
> > +static const unsigned long apb2_parents[] = {
> > +     CLK_OSC_32K,
> > +     CLK_OSC_24M,
> > +     CLK_PLL_PERIPH0,
> > +     CLK_PLL_PERIPH0,
> > +};
> > +
> > +static const unsigned long uart_parents[] = {
> > +     CLK_APB2,
> > +};
> > +
> > +static const struct ccu_clk_tree a64_tree[] = {
> > +     [CLK_OSC_32K]           = FIXED(OSC_32K_ULL),
> > +     [CLK_OSC_24M]           = FIXED(OSC_24M_ULL),
> > +
> > +     [CLK_PLL_PERIPH0]       = NK(periph0_parents, 0x028,
> > +                                  8, 5,      /* N */
> > +                                  4, 2, 2,   /* K */
> > +                                  2,         /* post-div */
> > +                                  CCU_CLK_F_POSTDIV),
> > +
> > +     [CLK_APB2]              = MP(apb2_parents, 0x058,
> > +                                  0, 5,      /* M */
> > +                                  16, 2,     /* P */
> > +                                  24, 2,     /* mux */
> > +                                  0,
> > +                                  0),
> > +
> > +     [CLK_BUS_UART0]         = MISC(uart_parents),
> > +};
> > +
> >  static const struct ccu_clk_gate a64_gates[] = {
> >       [CLK_BUS_OTG]           = GATE(0x060, BIT(23)),
> >       [CLK_BUS_EHCI0]         = GATE(0x060, BIT(24)),
> > @@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = {
> >  };
> >
> >  static const struct ccu_desc a64_ccu_desc = {
> > +     .tree = a64_tree,
> >       .gates = a64_gates,
> >       .resets = a64_resets,
> >  };
> > diff --git a/drivers/clk/sunxi/clk_sunxi.c b/drivers/clk/sunxi/clk_sunxi.c
> > index 345d706c2a..2aebd257d1 100644
> > --- a/drivers/clk/sunxi/clk_sunxi.c
> > +++ b/drivers/clk/sunxi/clk_sunxi.c
> > @@ -18,6 +18,187 @@ static const struct ccu_clk_gate *priv_to_gate(struct ccu_priv *priv,
> >       return &priv->desc->gates[id];
> >  }
> >
> > +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv *priv,
> > +                                            unsigned long id)
>
> Again, why long here? Especially as it's u32 in the function below.
>
> > +{
> > +     return &priv->desc->tree[id];
> > +}
> > +
> > +static int sunxi_get_parent_idx(const struct ccu_clk_tree *tree, void *base)
> > +{
> > +     u32 reg, idx;
> > +
> > +     reg = readl(base + tree->off);
> > +     idx = reg >> tree->mux.shift;
> > +     idx &= (1 << tree->mux.width) - 1;
> > +
> > +     return idx;
> > +}
> > +
> > +static ulong sunxi_fixed_get_rate(struct clk *clk, unsigned long id)
>
> Same "long" question for both the return type and the id.
> And for everything below.
>
> > +{
> > +     struct ccu_priv *priv = dev_get_priv(clk->dev);
> > +     const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> > +
> > +     if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> > +             printf("%s: (CLK#%ld) unhandled\n", __func__, clk->id);
> > +             return 0;
> > +     }
> > +
> > +     return tree->fixed_rate;
> > +}
> > +
>
> So why are there all those separate functions? Isn't that all the same
> algorithm: adjust the parent rate based on the clock type?
> I reworked this with recursive calls and it's MUCH less code:
>
> (fill the gaps, using your types for your convenience ;-)
>
> static ulong sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong
> parent_rate) { NK algorithm of sunxi_nk_get_rate }
> static ulong sunxi_apply_div(struct ccu_priv *priv, ulong id, ulong
> parent_rate) { MP algorithm of sunxi_mp_get_rate }
> static ulong sunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid)
> {
> ....
>         switch (tree->type) {
>         case CCU_CLK_TYPE_MISC:
>                 return sunxi_calc_clk_rate(priv, tree->parent[0]);
>         case CCU_CLK_TYPE_FIXED:
>                 return tree->fixed_rate;
>         case CCU_CLK_TYPE_NK:
>                 rate = sunxi_calc_clk_rate(priv,
>                         sunxi_get_parent_id(tree, priv->base));
>                 return sunxi_apply_pll(priv, clkid, rate);
>         (similar for _MP)
> ...
> }

Initially I would tried the recursive and yes code can reduce but
using recursive can leed more disadvantage in-terms of code tracing
during long run. Due to all these factors I used simple function
calls.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-07  1:03   ` André Przywara
  2019-01-07 13:01     ` Maxime Ripard
  2019-01-08 10:57     ` Jagan Teki
@ 2019-01-08 11:25     ` Jagan Teki
  2 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2019-01-08 11:25 UTC (permalink / raw)
  To: u-boot

On Mon, Jan 7, 2019 at 6:35 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 31/12/2018 16:59, Jagan Teki wrote:
> > Clock control unit comprises of parent clocks, gates, multiplexers,
> > dividers, multipliers, pre/post dividers and flags etc.
> >
> > So, the U-Boot implementation of ccu has divided into gates and tree.
> > gates are generic clock configuration of enable/disable bit management
> > which can be handle via ccu_clock_gate.
>
> So if I understand this correctly, you implement the gate functionality
> separately from the complex clock code, even if they are the same clock
> from the DT point of view? So if one wants to enable the MMC0 clock,
> which is a mux/divider clock, one needs to specify an extra entry in the
> gate array to describe the enable bit in this special clock register?
> Sounds a bit surprising, but is probably a neat trick to keep things
> simple. There should be a comment in the code to this regard then.
>
> > Tree clocks are parent clock type, fixed clocks, mp, nk, nkm, nkmp,
> > pre/post div, flags etc. which were managed via ccu_clock_tree.
>
> For a start, can we use more descriptive names than those very specific
> MP/NK names? DIV_MUX and PLL sound more descriptive to me. I understand
> that Linux uses those terms, but it would be great if uninitiated people
> have a chance to understand this as well.
>
> > This patch add support for MP, NK, MISC, FIXED clock types as part of
> > ccu clock tree with get_rate functionality this eventually used by
> > uart driver. and rest of the infrastructure will try to add while CLK
> > is being used on respective peripherals.
> >
> > Note that few of the tree type clock would require to enable gates on
> > their specific clock, in that case we need to add the gate details via
> > ccu_clock_gate, example: MP with gate so the gate offset, bit value
> > should add as part of ccu_clock_gate.
> >
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  arch/arm/include/asm/arch-sunxi/ccu.h | 192 +++++++++++++++++++++++++-
> >  drivers/clk/sunxi/clk_a64.c           |  40 ++++++
> >  drivers/clk/sunxi/clk_sunxi.c         | 182 ++++++++++++++++++++++++
> >  3 files changed, 413 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
> > index 3fdc26978d..61b8c36b3b 100644
> > --- a/arch/arm/include/asm/arch-sunxi/ccu.h
> > +++ b/arch/arm/include/asm/arch-sunxi/ccu.h
> > @@ -7,15 +7,204 @@
> >  #ifndef _ASM_ARCH_CCU_H
> >  #define _ASM_ARCH_CCU_H
> >
> > +#define OSC_32K_ULL          32000ULL
>
> 32768
>
> And why ULL? The whole Allwinner clock system works with 32-bit values,
> so just U would be totally sufficient. This avoid blowing this up to 64
> bit unnecessarily, which sounds painful for those poor ARMv7 parts.
>
> > +#define OSC_24M_ULL          24000000ULL
> > +
> > +/**
> > + * enum ccu_clk_type - ccu clock types
> > + *
> > + * @CCU_CLK_TYPE_MISC:                       misc clock type
>
> What is MISC, exactly? Seems like an artefact clock to me, some
> placeholder you need because gate clocks are handled separately in the
> gates struct. Should this be called something with SIMPLE instead, or GATE?
>
> > + * @CCU_CLK_TYPE_FIXED:                      fixed clock type
> > + * @CCU_CLK_TYPE_MP:                 mp clock type
> > + * @CCU_CLK_TYPE_NK:                 nk clock type
>
> What is the point of those comments, as you are basically repeating the
> enum name? What about:
>  * @CCU_CLK_TYPE_PLL:           PLL clock with two multiplier fields
>  * @CCU_CLK_TYPE_MUX_DIV:       multiple parents, two divider fields
>
> This gives more speaking names, plus some explanation.

My idea is to give generic name for a given clock type for example MP
clock has different varients like MP clock, MP with DIV, MP with
Postdiv, MP can be MMC etc. same like NK clock type as NK with
postdiv, NK can be PLL.

With this we can expose the base name to outside and keep fill the
require variants during macro initialization. This can avoid to many
names on the same clock based on the different variants.  Yes we can
add proper full detailed comments on the given type.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-08 10:57     ` Jagan Teki
@ 2019-01-08 11:39       ` Andre Przywara
  2019-01-08 19:12         ` Jagan Teki
  0 siblings, 1 reply; 49+ messages in thread
From: Andre Przywara @ 2019-01-08 11:39 UTC (permalink / raw)
  To: u-boot

On Tue, 8 Jan 2019 16:27:14 +0530
Jagan Teki <jagan@amarulasolutions.com> wrote:

Hi,

> On Mon, Jan 7, 2019 at 6:35 AM André Przywara
> <andre.przywara@arm.com> wrote:
> >
> > On 31/12/2018 16:59, Jagan Teki wrote:  
> > > Clock control unit comprises of parent clocks, gates,
> > > multiplexers, dividers, multipliers, pre/post dividers and flags
> > > etc.
> > >
> > > So, the U-Boot implementation of ccu has divided into gates and
> > > tree. gates are generic clock configuration of enable/disable bit
> > > management which can be handle via ccu_clock_gate.  
> >
> > So if I understand this correctly, you implement the gate
> > functionality separately from the complex clock code, even if they
> > are the same clock from the DT point of view? So if one wants to
> > enable the MMC0 clock, which is a mux/divider clock, one needs to
> > specify an extra entry in the gate array to describe the enable bit
> > in this special clock register? Sounds a bit surprising, but is
> > probably a neat trick to keep things simple. There should be a
> > comment in the code to this regard then.  
> 
> Exactly. Idea is to keep the macro's as simple as possible.
> 
> Adding gates clocks separately make easy and reasonable way to
> enable/disable clock operations. We even operate with single macro
> with all clock attributes along with gate(either another member or
> common structure like Linux does), but that seems not simple as per as
> my experince since there are many IP's like USB's just need
> enable/disable.
> 
> >  
> > > Tree clocks are parent clock type, fixed clocks, mp, nk, nkm,
> > > nkmp, pre/post div, flags etc. which were managed via
> > > ccu_clock_tree.  
> >
> > For a start, can we use more descriptive names than those very
> > specific MP/NK names? DIV_MUX and PLL sound more descriptive to me.
> > I understand that Linux uses those terms, but it would be great if
> > uninitiated people have a chance to understand this as well.
> >  
> > > This patch add support for MP, NK, MISC, FIXED clock types as
> > > part of ccu clock tree with get_rate functionality this
> > > eventually used by uart driver. and rest of the infrastructure
> > > will try to add while CLK is being used on respective peripherals.
> > >
> > > Note that few of the tree type clock would require to enable
> > > gates on their specific clock, in that case we need to add the
> > > gate details via ccu_clock_gate, example: MP with gate so the
> > > gate offset, bit value should add as part of ccu_clock_gate.
> > >
> > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > ---
> > >  arch/arm/include/asm/arch-sunxi/ccu.h | 192
> > > +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c
> > > |  40 ++++++ drivers/clk/sunxi/clk_sunxi.c         | 182
> > > ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1
> > > deletion(-)
> > >
> > > diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h
> > > b/arch/arm/include/asm/arch-sunxi/ccu.h index
> > > 3fdc26978d..61b8c36b3b 100644 ---
> > > a/arch/arm/include/asm/arch-sunxi/ccu.h +++
> > > b/arch/arm/include/asm/arch-sunxi/ccu.h @@ -7,15 +7,204 @@
> > >  #ifndef _ASM_ARCH_CCU_H
> > >  #define _ASM_ARCH_CCU_H
> > >
> > > +#define OSC_32K_ULL          32000ULL  
> >
> > 32768
> >
> > And why ULL? The whole Allwinner clock system works with 32-bit
> > values, so just U would be totally sufficient. This avoid blowing
> > this up to 64 bit unnecessarily, which sounds painful for those
> > poor ARMv7 parts. 
> > > +#define OSC_24M_ULL          24000000ULL
> > > +
> > > +/**
> > > + * enum ccu_clk_type - ccu clock types
> > > + *
> > > + * @CCU_CLK_TYPE_MISC:                       misc clock type  
> >
> > What is MISC, exactly? Seems like an artefact clock to me, some
> > placeholder you need because gate clocks are handled separately in
> > the gates struct. Should this be called something with SIMPLE
> > instead, or GATE?  
> 
> Unlike MP type in MMC, UART doesn't need any clock attributes like
> dividers, mux, etc, just have attached parent. I don't think UART
> clock is simple one It has parent, that indeed have another parents
> and so...on, ie reason I named as MISC.

Not really, as far as I can see the UART clock is a just a gate clock as
many others, with one parent (APB2).
The fact that APB2 in turn can have multiple parents doesn't affect the
UART clock itself, as you model this via the clock tree.

In fact we could have similar clocks in the tree structure for the
other gate clocks (USB, for instance), it's just that the UART is the
only user so far which actually queries the clock rate.

So MISC is way too generic, I would still prefer CCU_CLK_TYPE_GATE.

> > > + * @CCU_CLK_TYPE_FIXED:                      fixed clock type
> > > + * @CCU_CLK_TYPE_MP:                 mp clock type
> > > + * @CCU_CLK_TYPE_NK:                 nk clock type  
> >
> > What is the point of those comments, as you are basically repeating
> > the enum name? What about:
> >  * @CCU_CLK_TYPE_PLL:           PLL clock with two multiplier fields
> >  * @CCU_CLK_TYPE_MUX_DIV:       multiple parents, two divider fields
> >
> > This gives more speaking names, plus some explanation.
> >  
> > > + */
> > > +enum ccu_clk_type {
> > > +     CCU_CLK_TYPE_MISC               = 0,
> > > +     CCU_CLK_TYPE_FIXED              = 1,
> > > +     CCU_CLK_TYPE_MP                 = 2,
> > > +     CCU_CLK_TYPE_NK                 = 3,
> > > +};
> > > +
> > >  /**
> > >   * enum ccu_clk_flags - ccu clock flags
> > >   *
> > > - * @CCU_CLK_F_INIT_DONE:             clock gate init done check
> > > + * @CCU_CLK_F_INIT_DONE:             clock tree/gate init done
> > > check  
> >
> > Is this flag to tell implemented clocks apart from unimplemented
> > ones, which would be reset to all zeroes by the compiler? Then it
> > should be called something with VALID in it.  
> 
> Since the flags attached with real numeric initialized by macro itself
> rather than some other source like complier or any, so marked
> INIT_DONE seems to meaningful.

When I read INIT_DONE I understand some code has initialised this
clock at some point, which isn't true. I don't fight the flag itself,
just the name.

> and eventually the same verified in code whether the init done or not.
> 
> >  
> > > + * @CCU_CLK_F_POSTDIV:                       clock post divider
> > >   */
> > >  enum ccu_clk_flags {
> > >       CCU_CLK_F_INIT_DONE             = BIT(0),
> > > +     CCU_CLK_F_POSTDIV               = BIT(1),
> > >  };
> > >
> > > +/**
> > > + * struct ccu_mult - ccu clock multiplier
> > > + *
> > > + * @shift:           multiplier shift value
> > > + * @width:           multiplier width value
> > > + * @offset:          multiplier offset
> > > + * @min:             minimum multiplier
> > > + * @max:             maximum multiplier
> > > + */
> > > +struct ccu_mult {
> > > +     u8 shift;
> > > +     u8 width;
> > > +     u8 offset;
> > > +     u8 min;
> > > +     u8 max;
> > > +};
> > > +
> > > +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
> > > _offset,               \
> > > +                           _min, _max) {                     \
> > > +     .shift = _shift,                                        \
> > > +     .width = _width,                                        \
> > > +     .offset = _offset,                                      \
> > > +     .min = _min,                                            \
> > > +     .max = _max,                                            \
> > > +}
> > > +
> > > +#define _CCU_MULT_MIN(_shift, _width, _min)                  \
> > > +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0)
> > > +
> > > +#define _CCU_MULT(_shift, _width)                            \
> > > +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0)
> > > +
> > > +/**
> > > + * struct ccu_mux - ccu clock multiplexer
> > > + *
> > > + * @shift:           multiplexer shift value
> > > + * @width:           multiplexer width value
> > > + */
> > > +struct ccu_mux {
> > > +     u8 shift;
> > > +     u8 width;
> > > +};
> > > +
> > > +#define _CCU_MUX(_shift, _width) {           \
> > > +     .shift = _shift,                        \
> > > +     .width = _width,                        \
> > > +}
> > > +
> > > +/**
> > > + * struct ccu_div - ccu clock divider
> > > + *
> > > + * @shift:           divider shift value
> > > + * @width:           divider width value
> > > + * @offset:          divider offset
> > > + * @max:             maximum divider value
> > > + */
> > > +struct ccu_div {
> > > +     u8 shift;
> > > +     u8 width;
> > > +     u32 offset;
> > > +     u32 max;
> > > +};
> > > +
> > > +#define _CCU_DIV(_shift, _width) {           \
> > > +     .shift = _shift,                        \
> > > +     .width = _width,                        \
> > > +     .offset = 1,                            \
> > > +     .max = 0,                               \
> > > +}
> > > +
> > > +/**
> > > + * struct ccu_clk_tree - ccu clock tree
> > > + *
> > > + * @parent:          parent clock tree
> > > + * @type:            clock type
> > > + * @off:             clock tree offset
> > > + * @m:                       divider m
> > > + * @p:                       divider p
> > > + * @mux:             multiplexer mux
> > > + * @post:            post divider value
> > > + * @n:                       multiplier n
> > > + * @k:                       multiplier k
> > > + * @fixed_rate:              fixed rate
> > > + * @flags:           clock tree flags
> > > + */
> > > +struct ccu_clk_tree {
> > > +     const unsigned long *parent;  
> >
> > Shouldn't that be called "parents" instead?
> >  
> > > +     enum ccu_clk_type type;
> > > +     u16 off;
> > > +
> > > +     struct ccu_div m;
> > > +     struct ccu_div p;
> > > +     struct ccu_mux mux;
> > > +     unsigned int postdiv;
> > > +
> > > +     struct ccu_mult n;
> > > +     struct ccu_mult k;
> > > +
> > > +     ulong fixed_rate;
> > > +     enum ccu_clk_flags flags;
> > > +};
> > > +
> > > +#define TREE(_parent, _type, _off,                           \  
> >
> > Just a nit, but TREE is somewhat confusing here, as this just
> > constructs a single entry in an array. The tree property is
> > realised through the parent array, if I get this correctly.
> > So should we name this ENTRY or CLK_ENTRY instead?
> >  
> > > +          _m, _p,                                            \
> > > +          _mux,                                              \
> > > +          _postdiv,                                          \
> > > +          _n, _k,                                            \
> > > +          _fixed_rate,                                       \
> > > +          _flags) {                                          \
> > > +     .parent = _parent,                                      \
> > > +     .type = _type,                                          \
> > > +     .off = _off,                                            \
> > > +     .m = _m,                                                \
> > > +     .p = _p,                                                \
> > > +     .mux = _mux,                                            \
> > > +     .postdiv = _postdiv,                                    \
> > > +     .n = _n,                                                \
> > > +     .k = _k,                                                \
> > > +     .fixed_rate = _fixed_rate,                              \
> > > +     .flags = _flags,                                        \
> > > +}
> > > +
> > > +#define
> > > MISC(_parent)                                                \
> > > +     TREE(_parent, CCU_CLK_TYPE_MISC, 0,                     \
> > > +          {0}, {0},                                          \
> > > +          {0},                                               \
> > > +          0,                                                 \
> > > +          {0}, {0},                                          \
> > > +          0,                                                 \
> > > +          CCU_CLK_F_INIT_DONE)  
> >
> > If MISC is really something like GATE or SIMPLE, would it be
> > possible to construct the single element array here, so that the
> > macro just takes the one parent clock ID here, instead of referring
> > to an extra array? 
> > > +
> > > +#define FIXED(_fixed_rate)                                   \
> > > +     TREE(NULL, CCU_CLK_TYPE_FIXED, 0,                       \
> > > +          {0}, {0},                                          \
> > > +          {0},                                               \
> > > +          0,                                                 \
> > > +          {0}, {0},                                          \
> > > +          _fixed_rate,                                       \
> > > +          CCU_CLK_F_INIT_DONE)
> > > +
> > > +#define NK(_parent, _off,                                    \
> > > +        _nshift, _nwidth,                                    \
> > > +        _kshift, _kwidth, _kmin,                             \
> > > +        _postdiv,                                            \
> > > +        _flags)                                              \
> > > +     TREE(_parent, CCU_CLK_TYPE_NK, _off,                    \
> > > +          {0}, {0},                                          \
> > > +          {0},                                               \
> > > +          _postdiv,                                          \
> > > +          _CCU_MULT(_nshift, _nwidth),                       \
> > > +          _CCU_MULT_MIN(_kshift, _kwidth, _kmin),            \
> > > +          0,                                                 \
> > > +          CCU_CLK_F_INIT_DONE | _flags)
> > > +
> > > +#define MP(_parent, _off,                                    \
> > > +        _mshift, _mwidth,                                    \
> > > +        _pshift, _pwidth,                                    \
> > > +        _muxshift, _muxwidth,                                \
> > > +        _postdiv,                                            \
> > > +        _flags)                                              \
> > > +     TREE(_parent, CCU_CLK_TYPE_MP, _off,                    \
> > > +          _CCU_DIV(_mshift, _mwidth),                        \
> > > +          _CCU_DIV(_pshift, _pwidth),                        \
> > > +          _CCU_MUX(_muxshift, _muxwidth),                    \
> > > +          _postdiv,                                          \
> > > +          {0}, {0},                                          \
> > > +          0,                                                 \
> > > +          CCU_CLK_F_INIT_DONE | _flags)
> > > +
> > >  /**
> > >   * struct ccu_clk_gate - ccu clock gate
> > >   * @off:     gate offset
> > > @@ -59,6 +248,7 @@ struct ccu_reset {
> > >   * @resets:  reset unit
> > >   */
> > >  struct ccu_desc {
> > > +     const struct ccu_clk_tree *tree;
> > >       const struct ccu_clk_gate *gates;
> > >       const struct ccu_reset *resets;
> > >  };
> > > diff --git a/drivers/clk/sunxi/clk_a64.c
> > > b/drivers/clk/sunxi/clk_a64.c index 162ec769d6..1d0cd98183 100644
> > > --- a/drivers/clk/sunxi/clk_a64.c
> > > +++ b/drivers/clk/sunxi/clk_a64.c
> > > @@ -12,6 +12,45 @@
> > >  #include <dt-bindings/clock/sun50i-a64-ccu.h>
> > >  #include <dt-bindings/reset/sun50i-a64-ccu.h>
> > >
> > > +#define CLK_APB2                     26
> > > +#define CLK_OSC_32K                  (CLK_GPU + 1)
> > > +#define CLK_OSC_24M                  (CLK_OSC_32K + 1)
> > > +
> > > +static const unsigned long periph0_parents[] = {  
> >
> > Why is this long? That's the DT clock index, which is 32 bit wide,
> > right? Just unsigned int or uint32_t should be sufficient. long is
> > quite a treacherous type to use, especially as we share code
> > between 32 and 64-bit architectures.
> >  
> > > +     CLK_OSC_24M,
> > > +};
> > > +
> > > +static const unsigned long apb2_parents[] = {
> > > +     CLK_OSC_32K,
> > > +     CLK_OSC_24M,
> > > +     CLK_PLL_PERIPH0,
> > > +     CLK_PLL_PERIPH0,
> > > +};
> > > +
> > > +static const unsigned long uart_parents[] = {
> > > +     CLK_APB2,
> > > +};
> > > +
> > > +static const struct ccu_clk_tree a64_tree[] = {
> > > +     [CLK_OSC_32K]           = FIXED(OSC_32K_ULL),
> > > +     [CLK_OSC_24M]           = FIXED(OSC_24M_ULL),
> > > +
> > > +     [CLK_PLL_PERIPH0]       = NK(periph0_parents, 0x028,
> > > +                                  8, 5,      /* N */
> > > +                                  4, 2, 2,   /* K */
> > > +                                  2,         /* post-div */
> > > +                                  CCU_CLK_F_POSTDIV),
> > > +
> > > +     [CLK_APB2]              = MP(apb2_parents, 0x058,
> > > +                                  0, 5,      /* M */
> > > +                                  16, 2,     /* P */
> > > +                                  24, 2,     /* mux */
> > > +                                  0,
> > > +                                  0),
> > > +
> > > +     [CLK_BUS_UART0]         = MISC(uart_parents),
> > > +};
> > > +
> > >  static const struct ccu_clk_gate a64_gates[] = {
> > >       [CLK_BUS_OTG]           = GATE(0x060, BIT(23)),
> > >       [CLK_BUS_EHCI0]         = GATE(0x060, BIT(24)),
> > > @@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = {
> > >  };
> > >
> > >  static const struct ccu_desc a64_ccu_desc = {
> > > +     .tree = a64_tree,
> > >       .gates = a64_gates,
> > >       .resets = a64_resets,
> > >  };
> > > diff --git a/drivers/clk/sunxi/clk_sunxi.c
> > > b/drivers/clk/sunxi/clk_sunxi.c index 345d706c2a..2aebd257d1
> > > 100644 --- a/drivers/clk/sunxi/clk_sunxi.c
> > > +++ b/drivers/clk/sunxi/clk_sunxi.c
> > > @@ -18,6 +18,187 @@ static const struct ccu_clk_gate
> > > *priv_to_gate(struct ccu_priv *priv, return
> > > &priv->desc->gates[id]; }
> > >
> > > +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv
> > > *priv,
> > > +                                            unsigned long id)  
> >
> > Again, why long here? Especially as it's u32 in the function below.
> >  
> > > +{
> > > +     return &priv->desc->tree[id];
> > > +}
> > > +
> > > +static int sunxi_get_parent_idx(const struct ccu_clk_tree *tree,
> > > void *base) +{
> > > +     u32 reg, idx;
> > > +
> > > +     reg = readl(base + tree->off);
> > > +     idx = reg >> tree->mux.shift;
> > > +     idx &= (1 << tree->mux.width) - 1;
> > > +
> > > +     return idx;
> > > +}
> > > +
> > > +static ulong sunxi_fixed_get_rate(struct clk *clk, unsigned long
> > > id)  
> >
> > Same "long" question for both the return type and the id.
> > And for everything below.
> >  
> > > +{
> > > +     struct ccu_priv *priv = dev_get_priv(clk->dev);
> > > +     const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> > > +
> > > +     if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> > > +             printf("%s: (CLK#%ld) unhandled\n", __func__,
> > > clk->id);
> > > +             return 0;
> > > +     }
> > > +
> > > +     return tree->fixed_rate;
> > > +}
> > > +  
> >
> > So why are there all those separate functions? Isn't that all the
> > same algorithm: adjust the parent rate based on the clock type?
> > I reworked this with recursive calls and it's MUCH less code:
> >
> > (fill the gaps, using your types for your convenience ;-)
> >
> > static ulong sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong
> > parent_rate) { NK algorithm of sunxi_nk_get_rate }
> > static ulong sunxi_apply_div(struct ccu_priv *priv, ulong id, ulong
> > parent_rate) { MP algorithm of sunxi_mp_get_rate }
> > static ulong sunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid)
> > {
> > ....
> >         switch (tree->type) {
> >         case CCU_CLK_TYPE_MISC:
> >                 return sunxi_calc_clk_rate(priv, tree->parent[0]);
> >         case CCU_CLK_TYPE_FIXED:
> >                 return tree->fixed_rate;
> >         case CCU_CLK_TYPE_NK:
> >                 rate = sunxi_calc_clk_rate(priv,
> >                         sunxi_get_parent_id(tree, priv->base));
> >                 return sunxi_apply_pll(priv, clkid, rate);
> >         (similar for _MP)
> > ...
> > }  
> 
> Initially I would tried the recursive and yes code can reduce but
> using recursive can leed more disadvantage in-terms of code tracing
> during long run. Due to all these factors I used simple function
> calls.

But I find those extra functions much more confusing, due to the
similar names and their very similar functionality. Also it seems that
you just implemented what we need so far, so you will probably need to
extend those functions, making them even more similar and duplicating
more code. Basically you try to roll out the tree structure.

Since the clocks are organised in a tree-like structure, I believe this
recursive definition is a much better fit: A clock takes one of
possibly multiple input clocks and adjusts this rate. Full stop. The
rest is then just connecting them to other clocks.
The code looks much simpler and is much smaller this way:
https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112

Typically the recursion depth is just two or three levels, so I don't
buy the argument of code tracing.

Cheers,
Andre.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-08 11:39       ` Andre Przywara
@ 2019-01-08 19:12         ` Jagan Teki
  2019-01-10  0:50           ` André Przywara
  0 siblings, 1 reply; 49+ messages in thread
From: Jagan Teki @ 2019-01-08 19:12 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 8, 2019 at 5:09 PM Andre Przywara <andre.przywara@arm.com> wrote:
>
> On Tue, 8 Jan 2019 16:27:14 +0530
> Jagan Teki <jagan@amarulasolutions.com> wrote:
>
> Hi,
>
> > On Mon, Jan 7, 2019 at 6:35 AM André Przywara
> > <andre.przywara@arm.com> wrote:
> > >
> > > On 31/12/2018 16:59, Jagan Teki wrote:
> > > > Clock control unit comprises of parent clocks, gates,
> > > > multiplexers, dividers, multipliers, pre/post dividers and flags
> > > > etc.
> > > >
> > > > So, the U-Boot implementation of ccu has divided into gates and
> > > > tree. gates are generic clock configuration of enable/disable bit
> > > > management which can be handle via ccu_clock_gate.
> > >
> > > So if I understand this correctly, you implement the gate
> > > functionality separately from the complex clock code, even if they
> > > are the same clock from the DT point of view? So if one wants to
> > > enable the MMC0 clock, which is a mux/divider clock, one needs to
> > > specify an extra entry in the gate array to describe the enable bit
> > > in this special clock register? Sounds a bit surprising, but is
> > > probably a neat trick to keep things simple. There should be a
> > > comment in the code to this regard then.
> >
> > Exactly. Idea is to keep the macro's as simple as possible.
> >
> > Adding gates clocks separately make easy and reasonable way to
> > enable/disable clock operations. We even operate with single macro
> > with all clock attributes along with gate(either another member or
> > common structure like Linux does), but that seems not simple as per as
> > my experince since there are many IP's like USB's just need
> > enable/disable.
> >
> > >
> > > > Tree clocks are parent clock type, fixed clocks, mp, nk, nkm,
> > > > nkmp, pre/post div, flags etc. which were managed via
> > > > ccu_clock_tree.
> > >
> > > For a start, can we use more descriptive names than those very
> > > specific MP/NK names? DIV_MUX and PLL sound more descriptive to me.
> > > I understand that Linux uses those terms, but it would be great if
> > > uninitiated people have a chance to understand this as well.
> > >
> > > > This patch add support for MP, NK, MISC, FIXED clock types as
> > > > part of ccu clock tree with get_rate functionality this
> > > > eventually used by uart driver. and rest of the infrastructure
> > > > will try to add while CLK is being used on respective peripherals.
> > > >
> > > > Note that few of the tree type clock would require to enable
> > > > gates on their specific clock, in that case we need to add the
> > > > gate details via ccu_clock_gate, example: MP with gate so the
> > > > gate offset, bit value should add as part of ccu_clock_gate.
> > > >
> > > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > > ---
> > > >  arch/arm/include/asm/arch-sunxi/ccu.h | 192
> > > > +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c
> > > > |  40 ++++++ drivers/clk/sunxi/clk_sunxi.c         | 182
> > > > ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1
> > > > deletion(-)
> > > >
> > > > diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h
> > > > b/arch/arm/include/asm/arch-sunxi/ccu.h index
> > > > 3fdc26978d..61b8c36b3b 100644 ---
> > > > a/arch/arm/include/asm/arch-sunxi/ccu.h +++
> > > > b/arch/arm/include/asm/arch-sunxi/ccu.h @@ -7,15 +7,204 @@
> > > >  #ifndef _ASM_ARCH_CCU_H
> > > >  #define _ASM_ARCH_CCU_H
> > > >
> > > > +#define OSC_32K_ULL          32000ULL
> > >
> > > 32768
> > >
> > > And why ULL? The whole Allwinner clock system works with 32-bit
> > > values, so just U would be totally sufficient. This avoid blowing
> > > this up to 64 bit unnecessarily, which sounds painful for those
> > > poor ARMv7 parts.
> > > > +#define OSC_24M_ULL          24000000ULL
> > > > +
> > > > +/**
> > > > + * enum ccu_clk_type - ccu clock types
> > > > + *
> > > > + * @CCU_CLK_TYPE_MISC:                       misc clock type
> > >
> > > What is MISC, exactly? Seems like an artefact clock to me, some
> > > placeholder you need because gate clocks are handled separately in
> > > the gates struct. Should this be called something with SIMPLE
> > > instead, or GATE?
> >
> > Unlike MP type in MMC, UART doesn't need any clock attributes like
> > dividers, mux, etc, just have attached parent. I don't think UART
> > clock is simple one It has parent, that indeed have another parents
> > and so...on, ie reason I named as MISC.
>
> Not really, as far as I can see the UART clock is a just a gate clock as
> many others, with one parent (APB2).
> The fact that APB2 in turn can have multiple parents doesn't affect the
> UART clock itself, as you model this via the clock tree.
>
> In fact we could have similar clocks in the tree structure for the
> other gate clocks (USB, for instance), it's just that the UART is the
> only user so far which actually queries the clock rate.
>
> So MISC is way too generic, I would still prefer CCU_CLK_TYPE_GATE.

TYPE_GATE is more sense. fine for me.

>
> > > > + * @CCU_CLK_TYPE_FIXED:                      fixed clock type
> > > > + * @CCU_CLK_TYPE_MP:                 mp clock type
> > > > + * @CCU_CLK_TYPE_NK:                 nk clock type
> > >
> > > What is the point of those comments, as you are basically repeating
> > > the enum name? What about:
> > >  * @CCU_CLK_TYPE_PLL:           PLL clock with two multiplier fields
> > >  * @CCU_CLK_TYPE_MUX_DIV:       multiple parents, two divider fields
> > >
> > > This gives more speaking names, plus some explanation.
> > >
> > > > + */
> > > > +enum ccu_clk_type {
> > > > +     CCU_CLK_TYPE_MISC               = 0,
> > > > +     CCU_CLK_TYPE_FIXED              = 1,
> > > > +     CCU_CLK_TYPE_MP                 = 2,
> > > > +     CCU_CLK_TYPE_NK                 = 3,
> > > > +};
> > > > +
> > > >  /**
> > > >   * enum ccu_clk_flags - ccu clock flags
> > > >   *
> > > > - * @CCU_CLK_F_INIT_DONE:             clock gate init done check
> > > > + * @CCU_CLK_F_INIT_DONE:             clock tree/gate init done
> > > > check
> > >
> > > Is this flag to tell implemented clocks apart from unimplemented
> > > ones, which would be reset to all zeroes by the compiler? Then it
> > > should be called something with VALID in it.
> >
> > Since the flags attached with real numeric initialized by macro itself
> > rather than some other source like complier or any, so marked
> > INIT_DONE seems to meaningful.
>
> When I read INIT_DONE I understand some code has initialised this
> clock at some point, which isn't true. I don't fight the flag itself,
> just the name.

OK, I have updated INIT_DONE with IS_VALID and sent new version
changes based on this.

>
> > and eventually the same verified in code whether the init done or not.
> >
> > >
> > > > + * @CCU_CLK_F_POSTDIV:                       clock post divider
> > > >   */
> > > >  enum ccu_clk_flags {
> > > >       CCU_CLK_F_INIT_DONE             = BIT(0),
> > > > +     CCU_CLK_F_POSTDIV               = BIT(1),
> > > >  };
> > > >
> > > > +/**
> > > > + * struct ccu_mult - ccu clock multiplier
> > > > + *
> > > > + * @shift:           multiplier shift value
> > > > + * @width:           multiplier width value
> > > > + * @offset:          multiplier offset
> > > > + * @min:             minimum multiplier
> > > > + * @max:             maximum multiplier
> > > > + */
> > > > +struct ccu_mult {
> > > > +     u8 shift;
> > > > +     u8 width;
> > > > +     u8 offset;
> > > > +     u8 min;
> > > > +     u8 max;
> > > > +};
> > > > +
> > > > +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
> > > > _offset,               \
> > > > +                           _min, _max) {                     \
> > > > +     .shift = _shift,                                        \
> > > > +     .width = _width,                                        \
> > > > +     .offset = _offset,                                      \
> > > > +     .min = _min,                                            \
> > > > +     .max = _max,                                            \
> > > > +}
> > > > +
> > > > +#define _CCU_MULT_MIN(_shift, _width, _min)                  \
> > > > +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0)
> > > > +
> > > > +#define _CCU_MULT(_shift, _width)                            \
> > > > +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0)
> > > > +
> > > > +/**
> > > > + * struct ccu_mux - ccu clock multiplexer
> > > > + *
> > > > + * @shift:           multiplexer shift value
> > > > + * @width:           multiplexer width value
> > > > + */
> > > > +struct ccu_mux {
> > > > +     u8 shift;
> > > > +     u8 width;
> > > > +};
> > > > +
> > > > +#define _CCU_MUX(_shift, _width) {           \
> > > > +     .shift = _shift,                        \
> > > > +     .width = _width,                        \
> > > > +}
> > > > +
> > > > +/**
> > > > + * struct ccu_div - ccu clock divider
> > > > + *
> > > > + * @shift:           divider shift value
> > > > + * @width:           divider width value
> > > > + * @offset:          divider offset
> > > > + * @max:             maximum divider value
> > > > + */
> > > > +struct ccu_div {
> > > > +     u8 shift;
> > > > +     u8 width;
> > > > +     u32 offset;
> > > > +     u32 max;
> > > > +};
> > > > +
> > > > +#define _CCU_DIV(_shift, _width) {           \
> > > > +     .shift = _shift,                        \
> > > > +     .width = _width,                        \
> > > > +     .offset = 1,                            \
> > > > +     .max = 0,                               \
> > > > +}
> > > > +
> > > > +/**
> > > > + * struct ccu_clk_tree - ccu clock tree
> > > > + *
> > > > + * @parent:          parent clock tree
> > > > + * @type:            clock type
> > > > + * @off:             clock tree offset
> > > > + * @m:                       divider m
> > > > + * @p:                       divider p
> > > > + * @mux:             multiplexer mux
> > > > + * @post:            post divider value
> > > > + * @n:                       multiplier n
> > > > + * @k:                       multiplier k
> > > > + * @fixed_rate:              fixed rate
> > > > + * @flags:           clock tree flags
> > > > + */
> > > > +struct ccu_clk_tree {
> > > > +     const unsigned long *parent;
> > >
> > > Shouldn't that be called "parents" instead?
> > >
> > > > +     enum ccu_clk_type type;
> > > > +     u16 off;
> > > > +
> > > > +     struct ccu_div m;
> > > > +     struct ccu_div p;
> > > > +     struct ccu_mux mux;
> > > > +     unsigned int postdiv;
> > > > +
> > > > +     struct ccu_mult n;
> > > > +     struct ccu_mult k;
> > > > +
> > > > +     ulong fixed_rate;
> > > > +     enum ccu_clk_flags flags;
> > > > +};
> > > > +
> > > > +#define TREE(_parent, _type, _off,                           \
> > >
> > > Just a nit, but TREE is somewhat confusing here, as this just
> > > constructs a single entry in an array. The tree property is
> > > realised through the parent array, if I get this correctly.
> > > So should we name this ENTRY or CLK_ENTRY instead?
> > >
> > > > +          _m, _p,                                            \
> > > > +          _mux,                                              \
> > > > +          _postdiv,                                          \
> > > > +          _n, _k,                                            \
> > > > +          _fixed_rate,                                       \
> > > > +          _flags) {                                          \
> > > > +     .parent = _parent,                                      \
> > > > +     .type = _type,                                          \
> > > > +     .off = _off,                                            \
> > > > +     .m = _m,                                                \
> > > > +     .p = _p,                                                \
> > > > +     .mux = _mux,                                            \
> > > > +     .postdiv = _postdiv,                                    \
> > > > +     .n = _n,                                                \
> > > > +     .k = _k,                                                \
> > > > +     .fixed_rate = _fixed_rate,                              \
> > > > +     .flags = _flags,                                        \
> > > > +}
> > > > +
> > > > +#define
> > > > MISC(_parent)                                                \
> > > > +     TREE(_parent, CCU_CLK_TYPE_MISC, 0,                     \
> > > > +          {0}, {0},                                          \
> > > > +          {0},                                               \
> > > > +          0,                                                 \
> > > > +          {0}, {0},                                          \
> > > > +          0,                                                 \
> > > > +          CCU_CLK_F_INIT_DONE)
> > >
> > > If MISC is really something like GATE or SIMPLE, would it be
> > > possible to construct the single element array here, so that the
> > > macro just takes the one parent clock ID here, instead of referring
> > > to an extra array?
> > > > +
> > > > +#define FIXED(_fixed_rate)                                   \
> > > > +     TREE(NULL, CCU_CLK_TYPE_FIXED, 0,                       \
> > > > +          {0}, {0},                                          \
> > > > +          {0},                                               \
> > > > +          0,                                                 \
> > > > +          {0}, {0},                                          \
> > > > +          _fixed_rate,                                       \
> > > > +          CCU_CLK_F_INIT_DONE)
> > > > +
> > > > +#define NK(_parent, _off,                                    \
> > > > +        _nshift, _nwidth,                                    \
> > > > +        _kshift, _kwidth, _kmin,                             \
> > > > +        _postdiv,                                            \
> > > > +        _flags)                                              \
> > > > +     TREE(_parent, CCU_CLK_TYPE_NK, _off,                    \
> > > > +          {0}, {0},                                          \
> > > > +          {0},                                               \
> > > > +          _postdiv,                                          \
> > > > +          _CCU_MULT(_nshift, _nwidth),                       \
> > > > +          _CCU_MULT_MIN(_kshift, _kwidth, _kmin),            \
> > > > +          0,                                                 \
> > > > +          CCU_CLK_F_INIT_DONE | _flags)
> > > > +
> > > > +#define MP(_parent, _off,                                    \
> > > > +        _mshift, _mwidth,                                    \
> > > > +        _pshift, _pwidth,                                    \
> > > > +        _muxshift, _muxwidth,                                \
> > > > +        _postdiv,                                            \
> > > > +        _flags)                                              \
> > > > +     TREE(_parent, CCU_CLK_TYPE_MP, _off,                    \
> > > > +          _CCU_DIV(_mshift, _mwidth),                        \
> > > > +          _CCU_DIV(_pshift, _pwidth),                        \
> > > > +          _CCU_MUX(_muxshift, _muxwidth),                    \
> > > > +          _postdiv,                                          \
> > > > +          {0}, {0},                                          \
> > > > +          0,                                                 \
> > > > +          CCU_CLK_F_INIT_DONE | _flags)
> > > > +
> > > >  /**
> > > >   * struct ccu_clk_gate - ccu clock gate
> > > >   * @off:     gate offset
> > > > @@ -59,6 +248,7 @@ struct ccu_reset {
> > > >   * @resets:  reset unit
> > > >   */
> > > >  struct ccu_desc {
> > > > +     const struct ccu_clk_tree *tree;
> > > >       const struct ccu_clk_gate *gates;
> > > >       const struct ccu_reset *resets;
> > > >  };
> > > > diff --git a/drivers/clk/sunxi/clk_a64.c
> > > > b/drivers/clk/sunxi/clk_a64.c index 162ec769d6..1d0cd98183 100644
> > > > --- a/drivers/clk/sunxi/clk_a64.c
> > > > +++ b/drivers/clk/sunxi/clk_a64.c
> > > > @@ -12,6 +12,45 @@
> > > >  #include <dt-bindings/clock/sun50i-a64-ccu.h>
> > > >  #include <dt-bindings/reset/sun50i-a64-ccu.h>
> > > >
> > > > +#define CLK_APB2                     26
> > > > +#define CLK_OSC_32K                  (CLK_GPU + 1)
> > > > +#define CLK_OSC_24M                  (CLK_OSC_32K + 1)
> > > > +
> > > > +static const unsigned long periph0_parents[] = {
> > >
> > > Why is this long? That's the DT clock index, which is 32 bit wide,
> > > right? Just unsigned int or uint32_t should be sufficient. long is
> > > quite a treacherous type to use, especially as we share code
> > > between 32 and 64-bit architectures.
> > >
> > > > +     CLK_OSC_24M,
> > > > +};
> > > > +
> > > > +static const unsigned long apb2_parents[] = {
> > > > +     CLK_OSC_32K,
> > > > +     CLK_OSC_24M,
> > > > +     CLK_PLL_PERIPH0,
> > > > +     CLK_PLL_PERIPH0,
> > > > +};
> > > > +
> > > > +static const unsigned long uart_parents[] = {
> > > > +     CLK_APB2,
> > > > +};
> > > > +
> > > > +static const struct ccu_clk_tree a64_tree[] = {
> > > > +     [CLK_OSC_32K]           = FIXED(OSC_32K_ULL),
> > > > +     [CLK_OSC_24M]           = FIXED(OSC_24M_ULL),
> > > > +
> > > > +     [CLK_PLL_PERIPH0]       = NK(periph0_parents, 0x028,
> > > > +                                  8, 5,      /* N */
> > > > +                                  4, 2, 2,   /* K */
> > > > +                                  2,         /* post-div */
> > > > +                                  CCU_CLK_F_POSTDIV),
> > > > +
> > > > +     [CLK_APB2]              = MP(apb2_parents, 0x058,
> > > > +                                  0, 5,      /* M */
> > > > +                                  16, 2,     /* P */
> > > > +                                  24, 2,     /* mux */
> > > > +                                  0,
> > > > +                                  0),
> > > > +
> > > > +     [CLK_BUS_UART0]         = MISC(uart_parents),
> > > > +};
> > > > +
> > > >  static const struct ccu_clk_gate a64_gates[] = {
> > > >       [CLK_BUS_OTG]           = GATE(0x060, BIT(23)),
> > > >       [CLK_BUS_EHCI0]         = GATE(0x060, BIT(24)),
> > > > @@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = {
> > > >  };
> > > >
> > > >  static const struct ccu_desc a64_ccu_desc = {
> > > > +     .tree = a64_tree,
> > > >       .gates = a64_gates,
> > > >       .resets = a64_resets,
> > > >  };
> > > > diff --git a/drivers/clk/sunxi/clk_sunxi.c
> > > > b/drivers/clk/sunxi/clk_sunxi.c index 345d706c2a..2aebd257d1
> > > > 100644 --- a/drivers/clk/sunxi/clk_sunxi.c
> > > > +++ b/drivers/clk/sunxi/clk_sunxi.c
> > > > @@ -18,6 +18,187 @@ static const struct ccu_clk_gate
> > > > *priv_to_gate(struct ccu_priv *priv, return
> > > > &priv->desc->gates[id]; }
> > > >
> > > > +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv
> > > > *priv,
> > > > +                                            unsigned long id)
> > >
> > > Again, why long here? Especially as it's u32 in the function below.
> > >
> > > > +{
> > > > +     return &priv->desc->tree[id];
> > > > +}
> > > > +
> > > > +static int sunxi_get_parent_idx(const struct ccu_clk_tree *tree,
> > > > void *base) +{
> > > > +     u32 reg, idx;
> > > > +
> > > > +     reg = readl(base + tree->off);
> > > > +     idx = reg >> tree->mux.shift;
> > > > +     idx &= (1 << tree->mux.width) - 1;
> > > > +
> > > > +     return idx;
> > > > +}
> > > > +
> > > > +static ulong sunxi_fixed_get_rate(struct clk *clk, unsigned long
> > > > id)
> > >
> > > Same "long" question for both the return type and the id.
> > > And for everything below.
> > >
> > > > +{
> > > > +     struct ccu_priv *priv = dev_get_priv(clk->dev);
> > > > +     const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> > > > +
> > > > +     if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> > > > +             printf("%s: (CLK#%ld) unhandled\n", __func__,
> > > > clk->id);
> > > > +             return 0;
> > > > +     }
> > > > +
> > > > +     return tree->fixed_rate;
> > > > +}
> > > > +
> > >
> > > So why are there all those separate functions? Isn't that all the
> > > same algorithm: adjust the parent rate based on the clock type?
> > > I reworked this with recursive calls and it's MUCH less code:
> > >
> > > (fill the gaps, using your types for your convenience ;-)
> > >
> > > static ulong sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong
> > > parent_rate) { NK algorithm of sunxi_nk_get_rate }
> > > static ulong sunxi_apply_div(struct ccu_priv *priv, ulong id, ulong
> > > parent_rate) { MP algorithm of sunxi_mp_get_rate }
> > > static ulong sunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid)
> > > {
> > > ....
> > >         switch (tree->type) {
> > >         case CCU_CLK_TYPE_MISC:
> > >                 return sunxi_calc_clk_rate(priv, tree->parent[0]);
> > >         case CCU_CLK_TYPE_FIXED:
> > >                 return tree->fixed_rate;
> > >         case CCU_CLK_TYPE_NK:
> > >                 rate = sunxi_calc_clk_rate(priv,
> > >                         sunxi_get_parent_id(tree, priv->base));
> > >                 return sunxi_apply_pll(priv, clkid, rate);
> > >         (similar for _MP)
> > > ...
> > > }
> >
> > Initially I would tried the recursive and yes code can reduce but
> > using recursive can leed more disadvantage in-terms of code tracing
> > during long run. Due to all these factors I used simple function
> > calls.
>
> But I find those extra functions much more confusing, due to the
> similar names and their very similar functionality. Also it seems that
> you just implemented what we need so far, so you will probably need to
> extend those functions, making them even more similar and duplicating
> more code. Basically you try to roll out the tree structure.
>
> Since the clocks are organised in a tree-like structure, I believe this
> recursive definition is a much better fit: A clock takes one of
> possibly multiple input clocks and adjusts this rate. Full stop. The
> rest is then just connecting them to other clocks.
> The code looks much simpler and is much smaller this way:
> https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112
>
> Typically the recursion depth is just two or three levels, so I don't
> buy the argument of code tracing.

OK. agreed thanks.

I shall take this recursive and try to mark separate patch on behalf
of you if possible, will that be fine?

He is my next version TODO.
- Fixing clock types with meaning full values
- Adopt recursive function calls
- Try to add full MMC blot.

Let me know if you have any comments or question so-that we can
collaborate smooth to get CLK in as soon as possible.

Jagan.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-08 19:12         ` Jagan Teki
@ 2019-01-10  0:50           ` André Przywara
  2019-01-10 18:31             ` Jagan Teki
  0 siblings, 1 reply; 49+ messages in thread
From: André Przywara @ 2019-01-10  0:50 UTC (permalink / raw)
  To: u-boot

On 08/01/2019 19:12, Jagan Teki wrote:
> On Tue, Jan 8, 2019 at 5:09 PM Andre Przywara <andre.przywara@arm.com> wrote:
>>
>> On Tue, 8 Jan 2019 16:27:14 +0530
>> Jagan Teki <jagan@amarulasolutions.com> wrote:
>>
>> Hi,
>>
>>> On Mon, Jan 7, 2019 at 6:35 AM André Przywara
>>> <andre.przywara@arm.com> wrote:
>>>>
>>>> On 31/12/2018 16:59, Jagan Teki wrote:
>>>>> Clock control unit comprises of parent clocks, gates,
>>>>> multiplexers, dividers, multipliers, pre/post dividers and flags
>>>>> etc.
>>>>>
>>>>> So, the U-Boot implementation of ccu has divided into gates and
>>>>> tree. gates are generic clock configuration of enable/disable bit
>>>>> management which can be handle via ccu_clock_gate.
>>>>
>>>> So if I understand this correctly, you implement the gate
>>>> functionality separately from the complex clock code, even if they
>>>> are the same clock from the DT point of view? So if one wants to
>>>> enable the MMC0 clock, which is a mux/divider clock, one needs to
>>>> specify an extra entry in the gate array to describe the enable bit
>>>> in this special clock register? Sounds a bit surprising, but is
>>>> probably a neat trick to keep things simple. There should be a
>>>> comment in the code to this regard then.
>>>
>>> Exactly. Idea is to keep the macro's as simple as possible.
>>>
>>> Adding gates clocks separately make easy and reasonable way to
>>> enable/disable clock operations. We even operate with single macro
>>> with all clock attributes along with gate(either another member or
>>> common structure like Linux does), but that seems not simple as per as
>>> my experince since there are many IP's like USB's just need
>>> enable/disable.
>>>
>>>>
>>>>> Tree clocks are parent clock type, fixed clocks, mp, nk, nkm,
>>>>> nkmp, pre/post div, flags etc. which were managed via
>>>>> ccu_clock_tree.
>>>>
>>>> For a start, can we use more descriptive names than those very
>>>> specific MP/NK names? DIV_MUX and PLL sound more descriptive to me.
>>>> I understand that Linux uses those terms, but it would be great if
>>>> uninitiated people have a chance to understand this as well.
>>>>
>>>>> This patch add support for MP, NK, MISC, FIXED clock types as
>>>>> part of ccu clock tree with get_rate functionality this
>>>>> eventually used by uart driver. and rest of the infrastructure
>>>>> will try to add while CLK is being used on respective peripherals.
>>>>>
>>>>> Note that few of the tree type clock would require to enable
>>>>> gates on their specific clock, in that case we need to add the
>>>>> gate details via ccu_clock_gate, example: MP with gate so the
>>>>> gate offset, bit value should add as part of ccu_clock_gate.
>>>>>
>>>>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>>>>> ---
>>>>>  arch/arm/include/asm/arch-sunxi/ccu.h | 192
>>>>> +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c
>>>>> |  40 ++++++ drivers/clk/sunxi/clk_sunxi.c         | 182
>>>>> ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1
>>>>> deletion(-)
>>>>>
>>>>> diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h
>>>>> b/arch/arm/include/asm/arch-sunxi/ccu.h index
>>>>> 3fdc26978d..61b8c36b3b 100644 ---
>>>>> a/arch/arm/include/asm/arch-sunxi/ccu.h +++
>>>>> b/arch/arm/include/asm/arch-sunxi/ccu.h @@ -7,15 +7,204 @@
>>>>>  #ifndef _ASM_ARCH_CCU_H
>>>>>  #define _ASM_ARCH_CCU_H
>>>>>
>>>>> +#define OSC_32K_ULL          32000ULL
>>>>
>>>> 32768
>>>>
>>>> And why ULL? The whole Allwinner clock system works with 32-bit
>>>> values, so just U would be totally sufficient. This avoid blowing
>>>> this up to 64 bit unnecessarily, which sounds painful for those
>>>> poor ARMv7 parts.
>>>>> +#define OSC_24M_ULL          24000000ULL
>>>>> +
>>>>> +/**
>>>>> + * enum ccu_clk_type - ccu clock types
>>>>> + *
>>>>> + * @CCU_CLK_TYPE_MISC:                       misc clock type
>>>>
>>>> What is MISC, exactly? Seems like an artefact clock to me, some
>>>> placeholder you need because gate clocks are handled separately in
>>>> the gates struct. Should this be called something with SIMPLE
>>>> instead, or GATE?
>>>
>>> Unlike MP type in MMC, UART doesn't need any clock attributes like
>>> dividers, mux, etc, just have attached parent. I don't think UART
>>> clock is simple one It has parent, that indeed have another parents
>>> and so...on, ie reason I named as MISC.
>>
>> Not really, as far as I can see the UART clock is a just a gate clock as
>> many others, with one parent (APB2).
>> The fact that APB2 in turn can have multiple parents doesn't affect the
>> UART clock itself, as you model this via the clock tree.
>>
>> In fact we could have similar clocks in the tree structure for the
>> other gate clocks (USB, for instance), it's just that the UART is the
>> only user so far which actually queries the clock rate.
>>
>> So MISC is way too generic, I would still prefer CCU_CLK_TYPE_GATE.
> 
> TYPE_GATE is more sense. fine for me.
> 
>>
>>>>> + * @CCU_CLK_TYPE_FIXED:                      fixed clock type
>>>>> + * @CCU_CLK_TYPE_MP:                 mp clock type
>>>>> + * @CCU_CLK_TYPE_NK:                 nk clock type
>>>>
>>>> What is the point of those comments, as you are basically repeating
>>>> the enum name? What about:
>>>>  * @CCU_CLK_TYPE_PLL:           PLL clock with two multiplier fields
>>>>  * @CCU_CLK_TYPE_MUX_DIV:       multiple parents, two divider fields
>>>>
>>>> This gives more speaking names, plus some explanation.
>>>>
>>>>> + */
>>>>> +enum ccu_clk_type {
>>>>> +     CCU_CLK_TYPE_MISC               = 0,
>>>>> +     CCU_CLK_TYPE_FIXED              = 1,
>>>>> +     CCU_CLK_TYPE_MP                 = 2,
>>>>> +     CCU_CLK_TYPE_NK                 = 3,
>>>>> +};
>>>>> +
>>>>>  /**
>>>>>   * enum ccu_clk_flags - ccu clock flags
>>>>>   *
>>>>> - * @CCU_CLK_F_INIT_DONE:             clock gate init done check
>>>>> + * @CCU_CLK_F_INIT_DONE:             clock tree/gate init done
>>>>> check
>>>>
>>>> Is this flag to tell implemented clocks apart from unimplemented
>>>> ones, which would be reset to all zeroes by the compiler? Then it
>>>> should be called something with VALID in it.
>>>
>>> Since the flags attached with real numeric initialized by macro itself
>>> rather than some other source like complier or any, so marked
>>> INIT_DONE seems to meaningful.
>>
>> When I read INIT_DONE I understand some code has initialised this
>> clock at some point, which isn't true. I don't fight the flag itself,
>> just the name.
> 
> OK, I have updated INIT_DONE with IS_VALID and sent new version
> changes based on this.

Great, thanks!

>>> and eventually the same verified in code whether the init done or not.
>>>
>>>>
>>>>> + * @CCU_CLK_F_POSTDIV:                       clock post divider
>>>>>   */
>>>>>  enum ccu_clk_flags {
>>>>>       CCU_CLK_F_INIT_DONE             = BIT(0),
>>>>> +     CCU_CLK_F_POSTDIV               = BIT(1),
>>>>>  };
>>>>>
>>>>> +/**
>>>>> + * struct ccu_mult - ccu clock multiplier
>>>>> + *
>>>>> + * @shift:           multiplier shift value
>>>>> + * @width:           multiplier width value
>>>>> + * @offset:          multiplier offset
>>>>> + * @min:             minimum multiplier
>>>>> + * @max:             maximum multiplier
>>>>> + */
>>>>> +struct ccu_mult {
>>>>> +     u8 shift;
>>>>> +     u8 width;
>>>>> +     u8 offset;
>>>>> +     u8 min;
>>>>> +     u8 max;
>>>>> +};
>>>>> +
>>>>> +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
>>>>> _offset,               \
>>>>> +                           _min, _max) {                     \
>>>>> +     .shift = _shift,                                        \
>>>>> +     .width = _width,                                        \
>>>>> +     .offset = _offset,                                      \
>>>>> +     .min = _min,                                            \
>>>>> +     .max = _max,                                            \
>>>>> +}
>>>>> +
>>>>> +#define _CCU_MULT_MIN(_shift, _width, _min)                  \
>>>>> +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0)
>>>>> +
>>>>> +#define _CCU_MULT(_shift, _width)                            \
>>>>> +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0)
>>>>> +
>>>>> +/**
>>>>> + * struct ccu_mux - ccu clock multiplexer
>>>>> + *
>>>>> + * @shift:           multiplexer shift value
>>>>> + * @width:           multiplexer width value
>>>>> + */
>>>>> +struct ccu_mux {
>>>>> +     u8 shift;
>>>>> +     u8 width;
>>>>> +};
>>>>> +
>>>>> +#define _CCU_MUX(_shift, _width) {           \
>>>>> +     .shift = _shift,                        \
>>>>> +     .width = _width,                        \
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * struct ccu_div - ccu clock divider
>>>>> + *
>>>>> + * @shift:           divider shift value
>>>>> + * @width:           divider width value
>>>>> + * @offset:          divider offset
>>>>> + * @max:             maximum divider value
>>>>> + */
>>>>> +struct ccu_div {
>>>>> +     u8 shift;
>>>>> +     u8 width;
>>>>> +     u32 offset;
>>>>> +     u32 max;
>>>>> +};
>>>>> +
>>>>> +#define _CCU_DIV(_shift, _width) {           \
>>>>> +     .shift = _shift,                        \
>>>>> +     .width = _width,                        \
>>>>> +     .offset = 1,                            \
>>>>> +     .max = 0,                               \
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * struct ccu_clk_tree - ccu clock tree
>>>>> + *
>>>>> + * @parent:          parent clock tree
>>>>> + * @type:            clock type
>>>>> + * @off:             clock tree offset
>>>>> + * @m:                       divider m
>>>>> + * @p:                       divider p
>>>>> + * @mux:             multiplexer mux
>>>>> + * @post:            post divider value
>>>>> + * @n:                       multiplier n
>>>>> + * @k:                       multiplier k
>>>>> + * @fixed_rate:              fixed rate
>>>>> + * @flags:           clock tree flags
>>>>> + */
>>>>> +struct ccu_clk_tree {
>>>>> +     const unsigned long *parent;
>>>>
>>>> Shouldn't that be called "parents" instead?
>>>>
>>>>> +     enum ccu_clk_type type;
>>>>> +     u16 off;
>>>>> +
>>>>> +     struct ccu_div m;
>>>>> +     struct ccu_div p;
>>>>> +     struct ccu_mux mux;
>>>>> +     unsigned int postdiv;
>>>>> +
>>>>> +     struct ccu_mult n;
>>>>> +     struct ccu_mult k;
>>>>> +
>>>>> +     ulong fixed_rate;
>>>>> +     enum ccu_clk_flags flags;
>>>>> +};
>>>>> +
>>>>> +#define TREE(_parent, _type, _off,                           \
>>>>
>>>> Just a nit, but TREE is somewhat confusing here, as this just
>>>> constructs a single entry in an array. The tree property is
>>>> realised through the parent array, if I get this correctly.
>>>> So should we name this ENTRY or CLK_ENTRY instead?
>>>>
>>>>> +          _m, _p,                                            \
>>>>> +          _mux,                                              \
>>>>> +          _postdiv,                                          \
>>>>> +          _n, _k,                                            \
>>>>> +          _fixed_rate,                                       \
>>>>> +          _flags) {                                          \
>>>>> +     .parent = _parent,                                      \
>>>>> +     .type = _type,                                          \
>>>>> +     .off = _off,                                            \
>>>>> +     .m = _m,                                                \
>>>>> +     .p = _p,                                                \
>>>>> +     .mux = _mux,                                            \
>>>>> +     .postdiv = _postdiv,                                    \
>>>>> +     .n = _n,                                                \
>>>>> +     .k = _k,                                                \
>>>>> +     .fixed_rate = _fixed_rate,                              \
>>>>> +     .flags = _flags,                                        \
>>>>> +}
>>>>> +
>>>>> +#define
>>>>> MISC(_parent)                                                \
>>>>> +     TREE(_parent, CCU_CLK_TYPE_MISC, 0,                     \
>>>>> +          {0}, {0},                                          \
>>>>> +          {0},                                               \
>>>>> +          0,                                                 \
>>>>> +          {0}, {0},                                          \
>>>>> +          0,                                                 \
>>>>> +          CCU_CLK_F_INIT_DONE)
>>>>
>>>> If MISC is really something like GATE or SIMPLE, would it be
>>>> possible to construct the single element array here, so that the
>>>> macro just takes the one parent clock ID here, instead of referring
>>>> to an extra array?
>>>>> +
>>>>> +#define FIXED(_fixed_rate)                                   \
>>>>> +     TREE(NULL, CCU_CLK_TYPE_FIXED, 0,                       \
>>>>> +          {0}, {0},                                          \
>>>>> +          {0},                                               \
>>>>> +          0,                                                 \
>>>>> +          {0}, {0},                                          \
>>>>> +          _fixed_rate,                                       \
>>>>> +          CCU_CLK_F_INIT_DONE)
>>>>> +
>>>>> +#define NK(_parent, _off,                                    \
>>>>> +        _nshift, _nwidth,                                    \
>>>>> +        _kshift, _kwidth, _kmin,                             \
>>>>> +        _postdiv,                                            \
>>>>> +        _flags)                                              \
>>>>> +     TREE(_parent, CCU_CLK_TYPE_NK, _off,                    \
>>>>> +          {0}, {0},                                          \
>>>>> +          {0},                                               \
>>>>> +          _postdiv,                                          \
>>>>> +          _CCU_MULT(_nshift, _nwidth),                       \
>>>>> +          _CCU_MULT_MIN(_kshift, _kwidth, _kmin),            \
>>>>> +          0,                                                 \
>>>>> +          CCU_CLK_F_INIT_DONE | _flags)
>>>>> +
>>>>> +#define MP(_parent, _off,                                    \
>>>>> +        _mshift, _mwidth,                                    \
>>>>> +        _pshift, _pwidth,                                    \
>>>>> +        _muxshift, _muxwidth,                                \
>>>>> +        _postdiv,                                            \
>>>>> +        _flags)                                              \
>>>>> +     TREE(_parent, CCU_CLK_TYPE_MP, _off,                    \
>>>>> +          _CCU_DIV(_mshift, _mwidth),                        \
>>>>> +          _CCU_DIV(_pshift, _pwidth),                        \
>>>>> +          _CCU_MUX(_muxshift, _muxwidth),                    \
>>>>> +          _postdiv,                                          \
>>>>> +          {0}, {0},                                          \
>>>>> +          0,                                                 \
>>>>> +          CCU_CLK_F_INIT_DONE | _flags)
>>>>> +
>>>>>  /**
>>>>>   * struct ccu_clk_gate - ccu clock gate
>>>>>   * @off:     gate offset
>>>>> @@ -59,6 +248,7 @@ struct ccu_reset {
>>>>>   * @resets:  reset unit
>>>>>   */
>>>>>  struct ccu_desc {
>>>>> +     const struct ccu_clk_tree *tree;
>>>>>       const struct ccu_clk_gate *gates;
>>>>>       const struct ccu_reset *resets;
>>>>>  };
>>>>> diff --git a/drivers/clk/sunxi/clk_a64.c
>>>>> b/drivers/clk/sunxi/clk_a64.c index 162ec769d6..1d0cd98183 100644
>>>>> --- a/drivers/clk/sunxi/clk_a64.c
>>>>> +++ b/drivers/clk/sunxi/clk_a64.c
>>>>> @@ -12,6 +12,45 @@
>>>>>  #include <dt-bindings/clock/sun50i-a64-ccu.h>
>>>>>  #include <dt-bindings/reset/sun50i-a64-ccu.h>
>>>>>
>>>>> +#define CLK_APB2                     26
>>>>> +#define CLK_OSC_32K                  (CLK_GPU + 1)
>>>>> +#define CLK_OSC_24M                  (CLK_OSC_32K + 1)
>>>>> +
>>>>> +static const unsigned long periph0_parents[] = {
>>>>
>>>> Why is this long? That's the DT clock index, which is 32 bit wide,
>>>> right? Just unsigned int or uint32_t should be sufficient. long is
>>>> quite a treacherous type to use, especially as we share code
>>>> between 32 and 64-bit architectures.
>>>>
>>>>> +     CLK_OSC_24M,
>>>>> +};
>>>>> +
>>>>> +static const unsigned long apb2_parents[] = {
>>>>> +     CLK_OSC_32K,
>>>>> +     CLK_OSC_24M,
>>>>> +     CLK_PLL_PERIPH0,
>>>>> +     CLK_PLL_PERIPH0,
>>>>> +};
>>>>> +
>>>>> +static const unsigned long uart_parents[] = {
>>>>> +     CLK_APB2,
>>>>> +};
>>>>> +
>>>>> +static const struct ccu_clk_tree a64_tree[] = {
>>>>> +     [CLK_OSC_32K]           = FIXED(OSC_32K_ULL),
>>>>> +     [CLK_OSC_24M]           = FIXED(OSC_24M_ULL),
>>>>> +
>>>>> +     [CLK_PLL_PERIPH0]       = NK(periph0_parents, 0x028,
>>>>> +                                  8, 5,      /* N */
>>>>> +                                  4, 2, 2,   /* K */
>>>>> +                                  2,         /* post-div */
>>>>> +                                  CCU_CLK_F_POSTDIV),
>>>>> +
>>>>> +     [CLK_APB2]              = MP(apb2_parents, 0x058,
>>>>> +                                  0, 5,      /* M */
>>>>> +                                  16, 2,     /* P */
>>>>> +                                  24, 2,     /* mux */
>>>>> +                                  0,
>>>>> +                                  0),
>>>>> +
>>>>> +     [CLK_BUS_UART0]         = MISC(uart_parents),
>>>>> +};
>>>>> +
>>>>>  static const struct ccu_clk_gate a64_gates[] = {
>>>>>       [CLK_BUS_OTG]           = GATE(0x060, BIT(23)),
>>>>>       [CLK_BUS_EHCI0]         = GATE(0x060, BIT(24)),
>>>>> @@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = {
>>>>>  };
>>>>>
>>>>>  static const struct ccu_desc a64_ccu_desc = {
>>>>> +     .tree = a64_tree,
>>>>>       .gates = a64_gates,
>>>>>       .resets = a64_resets,
>>>>>  };
>>>>> diff --git a/drivers/clk/sunxi/clk_sunxi.c
>>>>> b/drivers/clk/sunxi/clk_sunxi.c index 345d706c2a..2aebd257d1
>>>>> 100644 --- a/drivers/clk/sunxi/clk_sunxi.c
>>>>> +++ b/drivers/clk/sunxi/clk_sunxi.c
>>>>> @@ -18,6 +18,187 @@ static const struct ccu_clk_gate
>>>>> *priv_to_gate(struct ccu_priv *priv, return
>>>>> &priv->desc->gates[id]; }
>>>>>
>>>>> +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv
>>>>> *priv,
>>>>> +                                            unsigned long id)
>>>>
>>>> Again, why long here? Especially as it's u32 in the function below.
>>>>
>>>>> +{
>>>>> +     return &priv->desc->tree[id];
>>>>> +}
>>>>> +
>>>>> +static int sunxi_get_parent_idx(const struct ccu_clk_tree *tree,
>>>>> void *base) +{
>>>>> +     u32 reg, idx;
>>>>> +
>>>>> +     reg = readl(base + tree->off);
>>>>> +     idx = reg >> tree->mux.shift;
>>>>> +     idx &= (1 << tree->mux.width) - 1;
>>>>> +
>>>>> +     return idx;
>>>>> +}
>>>>> +
>>>>> +static ulong sunxi_fixed_get_rate(struct clk *clk, unsigned long
>>>>> id)
>>>>
>>>> Same "long" question for both the return type and the id.
>>>> And for everything below.
>>>>
>>>>> +{
>>>>> +     struct ccu_priv *priv = dev_get_priv(clk->dev);
>>>>> +     const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
>>>>> +
>>>>> +     if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
>>>>> +             printf("%s: (CLK#%ld) unhandled\n", __func__,
>>>>> clk->id);
>>>>> +             return 0;
>>>>> +     }
>>>>> +
>>>>> +     return tree->fixed_rate;
>>>>> +}
>>>>> +
>>>>
>>>> So why are there all those separate functions? Isn't that all the
>>>> same algorithm: adjust the parent rate based on the clock type?
>>>> I reworked this with recursive calls and it's MUCH less code:
>>>>
>>>> (fill the gaps, using your types for your convenience ;-)
>>>>
>>>> static ulong sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong
>>>> parent_rate) { NK algorithm of sunxi_nk_get_rate }
>>>> static ulong sunxi_apply_div(struct ccu_priv *priv, ulong id, ulong
>>>> parent_rate) { MP algorithm of sunxi_mp_get_rate }
>>>> static ulong sunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid)
>>>> {
>>>> ....
>>>>         switch (tree->type) {
>>>>         case CCU_CLK_TYPE_MISC:
>>>>                 return sunxi_calc_clk_rate(priv, tree->parent[0]);
>>>>         case CCU_CLK_TYPE_FIXED:
>>>>                 return tree->fixed_rate;
>>>>         case CCU_CLK_TYPE_NK:
>>>>                 rate = sunxi_calc_clk_rate(priv,
>>>>                         sunxi_get_parent_id(tree, priv->base));
>>>>                 return sunxi_apply_pll(priv, clkid, rate);
>>>>         (similar for _MP)
>>>> ...
>>>> }
>>>
>>> Initially I would tried the recursive and yes code can reduce but
>>> using recursive can leed more disadvantage in-terms of code tracing
>>> during long run. Due to all these factors I used simple function
>>> calls.
>>
>> But I find those extra functions much more confusing, due to the
>> similar names and their very similar functionality. Also it seems that
>> you just implemented what we need so far, so you will probably need to
>> extend those functions, making them even more similar and duplicating
>> more code. Basically you try to roll out the tree structure.
>>
>> Since the clocks are organised in a tree-like structure, I believe this
>> recursive definition is a much better fit: A clock takes one of
>> possibly multiple input clocks and adjusts this rate. Full stop. The
>> rest is then just connecting them to other clocks.
>> The code looks much simpler and is much smaller this way:
>> https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112
>>
>> Typically the recursion depth is just two or three levels, so I don't
>> buy the argument of code tracing.
> 
> OK. agreed thanks.
> 
> I shall take this recursive and try to mark separate patch on behalf
> of you if possible, will that be fine?

No need, just rework this into this patch and keep your authorship. You
did the bulk of the work anyway. If someone complains about the code,
send them to me ;-)

> He is my next version TODO.
> - Fixing clock types with meaning full values
> - Adopt recursive function calls
> - Try to add full MMC blot.
> 
> Let me know if you have any comments or question so-that we can
> collaborate smooth to get CLK in as soon as possible.

Sure, lets nail this in the upcoming merge window.

Btw. I still get the warning for DM_USB, shouldn't this be fixed already
by this series?

Cheers,
Andre.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 02/26] reset: Add Allwinner RESET driver
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 02/26] reset: Add Allwinner RESET driver Jagan Teki
@ 2019-01-10  0:50   ` André Przywara
  0 siblings, 0 replies; 49+ messages in thread
From: André Przywara @ 2019-01-10  0:50 UTC (permalink / raw)
  To: u-boot

On 31/12/2018 16:59, Jagan Teki wrote:
> Add common reset driver for all Allwinner SoC's.
> 
> Since CLK and RESET share common DT compatible, it is CLK driver
> job is to bind the reset driver. So add CLK bind call on respective
> SoC driver by passing ccu map descriptor so-that reset deassert,
> deassert operations held based on ccu reset table defined from
> CLK driver.
> 
> Select DM_RESET via CLK_SUNXI, this make hidden section of RESET
> since CLK and RESET share common DT compatible and code.
> 
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
>  arch/arm/include/asm/arch-sunxi/ccu.h |  29 ++++++
>  drivers/clk/sunxi/Kconfig             |   1 +
>  drivers/clk/sunxi/clk_a64.c           |  20 +++++
>  drivers/reset/Kconfig                 |   8 ++
>  drivers/reset/Makefile                |   1 +
>  drivers/reset/reset-sunxi.c           | 125 ++++++++++++++++++++++++++
>  6 files changed, 184 insertions(+)
>  create mode 100644 drivers/reset/reset-sunxi.c
> 
> diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
> index db69c8f0d5..3fdc26978d 100644
> --- a/arch/arm/include/asm/arch-sunxi/ccu.h
> +++ b/arch/arm/include/asm/arch-sunxi/ccu.h
> @@ -34,13 +34,33 @@ struct ccu_clk_gate {
>  	.flags = CCU_CLK_F_INIT_DONE,		\
>  }
>  
> +/**
> + * struct ccu_reset - ccu reset
> + * @off:	reset offset
> + * @bit:	reset bit
> + * @flags:	reset flags
> + */
> +struct ccu_reset {
> +	u16 off;
> +	u32 bit;
> +	enum ccu_clk_flags flags;
> +};
> +
> +#define RESET(_off, _bit) {			\
> +	.off = _off,				\
> +	.bit = _bit,				\
> +	.flags = CCU_CLK_F_INIT_DONE,		\
> +}
> +
>  /**
>   * struct ccu_desc - clock control unit descriptor
>   *
>   * @gates:	clock gates
> + * @resets:	reset unit
>   */
>  struct ccu_desc {
>  	const struct ccu_clk_gate *gates;
> +	const struct ccu_reset *resets;
>  };
>  
>  /**
> @@ -62,4 +82,13 @@ int sunxi_clk_probe(struct udevice *dev);
>  
>  extern struct clk_ops sunxi_clk_ops;
>  
> +/**
> + * sunxi_reset_bind() - reset binding
> + *
> + * @dev:       reset device
> + * @count:     reset count
> + * @return 0 success, or error value
> + */
> +int sunxi_reset_bind(struct udevice *dev, ulong count);
> +
>  #endif /* _ASM_ARCH_CCU_H */
> diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig
> index bf5ecb3801..041d711e58 100644
> --- a/drivers/clk/sunxi/Kconfig
> +++ b/drivers/clk/sunxi/Kconfig
> @@ -1,6 +1,7 @@
>  config CLK_SUNXI
>  	bool "Clock support for Allwinner SoCs"
>  	depends on CLK && ARCH_SUNXI
> +	select DM_RESET
>  	default y
>  	help
>  	  This enables support for common clock driver API on Allwinner
> diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c
> index 803a2f711d..28bda1f497 100644
> --- a/drivers/clk/sunxi/clk_a64.c
> +++ b/drivers/clk/sunxi/clk_a64.c
> @@ -10,6 +10,7 @@
>  #include <errno.h>
>  #include <asm/arch/ccu.h>
>  #include <dt-bindings/clock/sun50i-a64-ccu.h>
> +#include <dt-bindings/reset/sun50i-a64-ccu.h>
>  
>  static const struct ccu_clk_gate a64_gates[] = {
>  	[CLK_BUS_OTG]		= GATE(0x060, BIT(23)),
> @@ -26,10 +27,28 @@ static const struct ccu_clk_gate a64_gates[] = {
>  	[CLK_USB_OHCI1]		= GATE(0x0cc, BIT(17)),
>  };
>  
> +static const struct ccu_reset a64_resets[] = {
> +	[RST_USB_PHY0]          = RESET(0x0cc, BIT(0)),
> +	[RST_USB_PHY1]          = RESET(0x0cc, BIT(1)),
> +	[RST_USB_HSIC]          = RESET(0x0cc, BIT(2)),
> +
> +	[RST_BUS_OTG]           = RESET(0x2c0, BIT(23)),
> +	[RST_BUS_EHCI0]         = RESET(0x2c0, BIT(24)),
> +	[RST_BUS_EHCI1]         = RESET(0x2c0, BIT(25)),
> +	[RST_BUS_OHCI0]         = RESET(0x2c0, BIT(28)),
> +	[RST_BUS_OHCI1]         = RESET(0x2c0, BIT(29)),
> +};
> +
>  static const struct ccu_desc a64_ccu_desc = {
>  	.gates = a64_gates,
> +	.resets = a64_resets,
>  };
>  
> +static int a64_clk_bind(struct udevice *dev)
> +{
> +	return sunxi_reset_bind(dev, 50);

The second parameter is count, so it should be 51. But this is wrong
either way, so just use ARRAY_SIZE(a64_reset), as this is what you are
after with the check later on.
Same for the other SoCs, of course.

> +}
> +
>  static const struct udevice_id a64_ccu_ids[] = {
>  	{ .compatible = "allwinner,sun50i-a64-ccu",
>  	  .data = (ulong)&a64_ccu_desc },
> @@ -43,4 +62,5 @@ U_BOOT_DRIVER(clk_sun50i_a64) = {
>  	.priv_auto_alloc_size	= sizeof(struct ccu_priv),
>  	.ops		= &sunxi_clk_ops,
>  	.probe		= sunxi_clk_probe,
> +	.bind		= a64_clk_bind,
>  };
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 9c5208b7da..b6b40b6ce9 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -106,4 +106,12 @@ config RESET_SOCFPGA
>  	help
>  	  Support for reset controller on SoCFPGA platform.
>  
> +config RESET_SUNXI
> +	bool "RESET support for Allwinner SoCs"
> +	depends on DM_RESET && ARCH_SUNXI
> +	default y
> +	help
> +	  This enables support for common reset driver for
> +	  Allwinner SoCs.
> +
>  endmenu
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index f4520878b7..377c038163 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -17,3 +17,4 @@ obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o
>  obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o
>  obj-$(CONFIG_RESET_MESON) += reset-meson.o
>  obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
> +obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
> diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
> new file mode 100644
> index 0000000000..af63cac64e
> --- /dev/null
> +++ b/drivers/reset/reset-sunxi.c
> @@ -0,0 +1,125 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> +/*
> + * Copyright (C) 2018 Amarula Solutions.
> + * Author: Jagan Teki <jagan@amarulasolutions.com>
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <errno.h>
> +#include <reset-uclass.h>
> +#include <asm/io.h>
> +#include <dm/lists.h>
> +#include <linux/log2.h>
> +#include <asm/arch/ccu.h>
> +
> +struct sunxi_reset_priv {
> +	void *base;
> +	ulong count;
> +	const struct ccu_desc *desc;
> +};
> +
> +static const struct ccu_reset *priv_to_reset(struct sunxi_reset_priv *priv,
> +					     unsigned long id)
> +{
> +	return	&priv->desc->resets[id];
> +}
> +
> +static int sunxi_reset_request(struct reset_ctl *reset_ctl)
> +{
> +	struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev);
> +
> +	debug("%s: (RST#%ld)\n", __func__, reset_ctl->id);
> +
> +	/* check dt-bindings/reset/sun8i-h3-ccu.h for max id */

File name should be generic, but the comment is not correct anyway,
since we are limited by the array size, not by the DT.
So please just remove this comment.

Cheers,
Andre.

> +	if (reset_ctl->id >= priv->count)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int sunxi_reset_free(struct reset_ctl *reset_ctl)
> +{
> +	debug("%s: (RST#%ld)\n", __func__, reset_ctl->id);
> +
> +	return 0;
> +}
> +
> +static int sunxi_set_reset(struct reset_ctl *reset_ctl, bool on)
> +{
> +	struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev);
> +	const struct ccu_reset *reset = priv_to_reset(priv, reset_ctl->id);
> +	u32 reg;
> +
> +	if (!(reset->flags & CCU_CLK_F_INIT_DONE)) {
> +		printf("%s: (RST#%ld) unhandled\n", __func__, reset_ctl->id);
> +		return 0;
> +	}
> +
> +	debug("%s: (RST#%ld) off#0x%x, BIT(%d)\n", __func__,
> +	      reset_ctl->id, reset->off, ilog2(reset->bit));
> +
> +	reg = readl(priv->base + reset->off);
> +	if (on)
> +		reg |= reset->bit;
> +	else
> +		reg &= ~reset->bit;
> +
> +	writel(reg, priv->base + reset->off);
> +
> +	return 0;
> +}
> +
> +static int sunxi_reset_assert(struct reset_ctl *reset_ctl)
> +{
> +	return sunxi_set_reset(reset_ctl, false);
> +}
> +
> +static int sunxi_reset_deassert(struct reset_ctl *reset_ctl)
> +{
> +	return sunxi_set_reset(reset_ctl, true);
> +}
> +
> +struct reset_ops sunxi_reset_ops = {
> +	.request = sunxi_reset_request,
> +	.free = sunxi_reset_free,
> +	.rst_assert = sunxi_reset_assert,
> +	.rst_deassert = sunxi_reset_deassert,
> +};
> +
> +static int sunxi_reset_probe(struct udevice *dev)
> +{
> +	struct sunxi_reset_priv *priv = dev_get_priv(dev);
> +
> +	priv->base = dev_read_addr_ptr(dev);
> +
> +	return 0;
> +}
> +
> +int sunxi_reset_bind(struct udevice *dev, ulong count)
> +{
> +	struct udevice *rst_dev;
> +	struct sunxi_reset_priv *priv;
> +	int ret;
> +
> +	ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset",
> +					 dev_ofnode(dev), &rst_dev);
> +	if (ret) {
> +		debug("failed to bind sunxi_reset driver (ret=%d)\n", ret);
> +		return ret;
> +	}
> +	priv = malloc(sizeof(struct sunxi_reset_priv));
> +	priv->count = count;
> +	priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev);
> +	rst_dev->priv = priv;
> +
> +	return 0;
> +}
> +
> +U_BOOT_DRIVER(sunxi_reset) = {
> +	.name		= "sunxi_reset",
> +	.id		= UCLASS_RESET,
> +	.ops		= &sunxi_reset_ops,
> +	.probe		= sunxi_reset_probe,
> +	.priv_auto_alloc_size = sizeof(struct sunxi_reset_priv),
> +};
> 

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support
  2019-01-10  0:50           ` André Przywara
@ 2019-01-10 18:31             ` Jagan Teki
  0 siblings, 0 replies; 49+ messages in thread
From: Jagan Teki @ 2019-01-10 18:31 UTC (permalink / raw)
  To: u-boot

On Thu, Jan 10, 2019 at 6:21 AM André Przywara <andre.przywara@arm.com> wrote:
>
> On 08/01/2019 19:12, Jagan Teki wrote:
> > On Tue, Jan 8, 2019 at 5:09 PM Andre Przywara <andre.przywara@arm.com> wrote:
> >>
> >> On Tue, 8 Jan 2019 16:27:14 +0530
> >> Jagan Teki <jagan@amarulasolutions.com> wrote:
> >>
> >> Hi,
> >>
> >>> On Mon, Jan 7, 2019 at 6:35 AM André Przywara
> >>> <andre.przywara@arm.com> wrote:
> >>>>
> >>>> On 31/12/2018 16:59, Jagan Teki wrote:
> >>>>> Clock control unit comprises of parent clocks, gates,
> >>>>> multiplexers, dividers, multipliers, pre/post dividers and flags
> >>>>> etc.
> >>>>>
> >>>>> So, the U-Boot implementation of ccu has divided into gates and
> >>>>> tree. gates are generic clock configuration of enable/disable bit
> >>>>> management which can be handle via ccu_clock_gate.
> >>>>
> >>>> So if I understand this correctly, you implement the gate
> >>>> functionality separately from the complex clock code, even if they
> >>>> are the same clock from the DT point of view? So if one wants to
> >>>> enable the MMC0 clock, which is a mux/divider clock, one needs to
> >>>> specify an extra entry in the gate array to describe the enable bit
> >>>> in this special clock register? Sounds a bit surprising, but is
> >>>> probably a neat trick to keep things simple. There should be a
> >>>> comment in the code to this regard then.
> >>>
> >>> Exactly. Idea is to keep the macro's as simple as possible.
> >>>
> >>> Adding gates clocks separately make easy and reasonable way to
> >>> enable/disable clock operations. We even operate with single macro
> >>> with all clock attributes along with gate(either another member or
> >>> common structure like Linux does), but that seems not simple as per as
> >>> my experince since there are many IP's like USB's just need
> >>> enable/disable.
> >>>
> >>>>
> >>>>> Tree clocks are parent clock type, fixed clocks, mp, nk, nkm,
> >>>>> nkmp, pre/post div, flags etc. which were managed via
> >>>>> ccu_clock_tree.
> >>>>
> >>>> For a start, can we use more descriptive names than those very
> >>>> specific MP/NK names? DIV_MUX and PLL sound more descriptive to me.
> >>>> I understand that Linux uses those terms, but it would be great if
> >>>> uninitiated people have a chance to understand this as well.
> >>>>
> >>>>> This patch add support for MP, NK, MISC, FIXED clock types as
> >>>>> part of ccu clock tree with get_rate functionality this
> >>>>> eventually used by uart driver. and rest of the infrastructure
> >>>>> will try to add while CLK is being used on respective peripherals.
> >>>>>
> >>>>> Note that few of the tree type clock would require to enable
> >>>>> gates on their specific clock, in that case we need to add the
> >>>>> gate details via ccu_clock_gate, example: MP with gate so the
> >>>>> gate offset, bit value should add as part of ccu_clock_gate.
> >>>>>
> >>>>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> >>>>> ---
> >>>>>  arch/arm/include/asm/arch-sunxi/ccu.h | 192
> >>>>> +++++++++++++++++++++++++- drivers/clk/sunxi/clk_a64.c
> >>>>> |  40 ++++++ drivers/clk/sunxi/clk_sunxi.c         | 182
> >>>>> ++++++++++++++++++++++++ 3 files changed, 413 insertions(+), 1
> >>>>> deletion(-)
> >>>>>
> >>>>> diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h
> >>>>> b/arch/arm/include/asm/arch-sunxi/ccu.h index
> >>>>> 3fdc26978d..61b8c36b3b 100644 ---
> >>>>> a/arch/arm/include/asm/arch-sunxi/ccu.h +++
> >>>>> b/arch/arm/include/asm/arch-sunxi/ccu.h @@ -7,15 +7,204 @@
> >>>>>  #ifndef _ASM_ARCH_CCU_H
> >>>>>  #define _ASM_ARCH_CCU_H
> >>>>>
> >>>>> +#define OSC_32K_ULL          32000ULL
> >>>>
> >>>> 32768
> >>>>
> >>>> And why ULL? The whole Allwinner clock system works with 32-bit
> >>>> values, so just U would be totally sufficient. This avoid blowing
> >>>> this up to 64 bit unnecessarily, which sounds painful for those
> >>>> poor ARMv7 parts.
> >>>>> +#define OSC_24M_ULL          24000000ULL
> >>>>> +
> >>>>> +/**
> >>>>> + * enum ccu_clk_type - ccu clock types
> >>>>> + *
> >>>>> + * @CCU_CLK_TYPE_MISC:                       misc clock type
> >>>>
> >>>> What is MISC, exactly? Seems like an artefact clock to me, some
> >>>> placeholder you need because gate clocks are handled separately in
> >>>> the gates struct. Should this be called something with SIMPLE
> >>>> instead, or GATE?
> >>>
> >>> Unlike MP type in MMC, UART doesn't need any clock attributes like
> >>> dividers, mux, etc, just have attached parent. I don't think UART
> >>> clock is simple one It has parent, that indeed have another parents
> >>> and so...on, ie reason I named as MISC.
> >>
> >> Not really, as far as I can see the UART clock is a just a gate clock as
> >> many others, with one parent (APB2).
> >> The fact that APB2 in turn can have multiple parents doesn't affect the
> >> UART clock itself, as you model this via the clock tree.
> >>
> >> In fact we could have similar clocks in the tree structure for the
> >> other gate clocks (USB, for instance), it's just that the UART is the
> >> only user so far which actually queries the clock rate.
> >>
> >> So MISC is way too generic, I would still prefer CCU_CLK_TYPE_GATE.
> >
> > TYPE_GATE is more sense. fine for me.
> >
> >>
> >>>>> + * @CCU_CLK_TYPE_FIXED:                      fixed clock type
> >>>>> + * @CCU_CLK_TYPE_MP:                 mp clock type
> >>>>> + * @CCU_CLK_TYPE_NK:                 nk clock type
> >>>>
> >>>> What is the point of those comments, as you are basically repeating
> >>>> the enum name? What about:
> >>>>  * @CCU_CLK_TYPE_PLL:           PLL clock with two multiplier fields
> >>>>  * @CCU_CLK_TYPE_MUX_DIV:       multiple parents, two divider fields
> >>>>
> >>>> This gives more speaking names, plus some explanation.
> >>>>
> >>>>> + */
> >>>>> +enum ccu_clk_type {
> >>>>> +     CCU_CLK_TYPE_MISC               = 0,
> >>>>> +     CCU_CLK_TYPE_FIXED              = 1,
> >>>>> +     CCU_CLK_TYPE_MP                 = 2,
> >>>>> +     CCU_CLK_TYPE_NK                 = 3,
> >>>>> +};
> >>>>> +
> >>>>>  /**
> >>>>>   * enum ccu_clk_flags - ccu clock flags
> >>>>>   *
> >>>>> - * @CCU_CLK_F_INIT_DONE:             clock gate init done check
> >>>>> + * @CCU_CLK_F_INIT_DONE:             clock tree/gate init done
> >>>>> check
> >>>>
> >>>> Is this flag to tell implemented clocks apart from unimplemented
> >>>> ones, which would be reset to all zeroes by the compiler? Then it
> >>>> should be called something with VALID in it.
> >>>
> >>> Since the flags attached with real numeric initialized by macro itself
> >>> rather than some other source like complier or any, so marked
> >>> INIT_DONE seems to meaningful.
> >>
> >> When I read INIT_DONE I understand some code has initialised this
> >> clock at some point, which isn't true. I don't fight the flag itself,
> >> just the name.
> >
> > OK, I have updated INIT_DONE with IS_VALID and sent new version
> > changes based on this.
>
> Great, thanks!
>
> >>> and eventually the same verified in code whether the init done or not.
> >>>
> >>>>
> >>>>> + * @CCU_CLK_F_POSTDIV:                       clock post divider
> >>>>>   */
> >>>>>  enum ccu_clk_flags {
> >>>>>       CCU_CLK_F_INIT_DONE             = BIT(0),
> >>>>> +     CCU_CLK_F_POSTDIV               = BIT(1),
> >>>>>  };
> >>>>>
> >>>>> +/**
> >>>>> + * struct ccu_mult - ccu clock multiplier
> >>>>> + *
> >>>>> + * @shift:           multiplier shift value
> >>>>> + * @width:           multiplier width value
> >>>>> + * @offset:          multiplier offset
> >>>>> + * @min:             minimum multiplier
> >>>>> + * @max:             maximum multiplier
> >>>>> + */
> >>>>> +struct ccu_mult {
> >>>>> +     u8 shift;
> >>>>> +     u8 width;
> >>>>> +     u8 offset;
> >>>>> +     u8 min;
> >>>>> +     u8 max;
> >>>>> +};
> >>>>> +
> >>>>> +#define _CCU_MULT_OFF_MIN_MAX(_shift, _width,
> >>>>> _offset,               \
> >>>>> +                           _min, _max) {                     \
> >>>>> +     .shift = _shift,                                        \
> >>>>> +     .width = _width,                                        \
> >>>>> +     .offset = _offset,                                      \
> >>>>> +     .min = _min,                                            \
> >>>>> +     .max = _max,                                            \
> >>>>> +}
> >>>>> +
> >>>>> +#define _CCU_MULT_MIN(_shift, _width, _min)                  \
> >>>>> +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, _min, 0)
> >>>>> +
> >>>>> +#define _CCU_MULT(_shift, _width)                            \
> >>>>> +     _CCU_MULT_OFF_MIN_MAX(_shift, _width, 1, 1, 0)
> >>>>> +
> >>>>> +/**
> >>>>> + * struct ccu_mux - ccu clock multiplexer
> >>>>> + *
> >>>>> + * @shift:           multiplexer shift value
> >>>>> + * @width:           multiplexer width value
> >>>>> + */
> >>>>> +struct ccu_mux {
> >>>>> +     u8 shift;
> >>>>> +     u8 width;
> >>>>> +};
> >>>>> +
> >>>>> +#define _CCU_MUX(_shift, _width) {           \
> >>>>> +     .shift = _shift,                        \
> >>>>> +     .width = _width,                        \
> >>>>> +}
> >>>>> +
> >>>>> +/**
> >>>>> + * struct ccu_div - ccu clock divider
> >>>>> + *
> >>>>> + * @shift:           divider shift value
> >>>>> + * @width:           divider width value
> >>>>> + * @offset:          divider offset
> >>>>> + * @max:             maximum divider value
> >>>>> + */
> >>>>> +struct ccu_div {
> >>>>> +     u8 shift;
> >>>>> +     u8 width;
> >>>>> +     u32 offset;
> >>>>> +     u32 max;
> >>>>> +};
> >>>>> +
> >>>>> +#define _CCU_DIV(_shift, _width) {           \
> >>>>> +     .shift = _shift,                        \
> >>>>> +     .width = _width,                        \
> >>>>> +     .offset = 1,                            \
> >>>>> +     .max = 0,                               \
> >>>>> +}
> >>>>> +
> >>>>> +/**
> >>>>> + * struct ccu_clk_tree - ccu clock tree
> >>>>> + *
> >>>>> + * @parent:          parent clock tree
> >>>>> + * @type:            clock type
> >>>>> + * @off:             clock tree offset
> >>>>> + * @m:                       divider m
> >>>>> + * @p:                       divider p
> >>>>> + * @mux:             multiplexer mux
> >>>>> + * @post:            post divider value
> >>>>> + * @n:                       multiplier n
> >>>>> + * @k:                       multiplier k
> >>>>> + * @fixed_rate:              fixed rate
> >>>>> + * @flags:           clock tree flags
> >>>>> + */
> >>>>> +struct ccu_clk_tree {
> >>>>> +     const unsigned long *parent;
> >>>>
> >>>> Shouldn't that be called "parents" instead?
> >>>>
> >>>>> +     enum ccu_clk_type type;
> >>>>> +     u16 off;
> >>>>> +
> >>>>> +     struct ccu_div m;
> >>>>> +     struct ccu_div p;
> >>>>> +     struct ccu_mux mux;
> >>>>> +     unsigned int postdiv;
> >>>>> +
> >>>>> +     struct ccu_mult n;
> >>>>> +     struct ccu_mult k;
> >>>>> +
> >>>>> +     ulong fixed_rate;
> >>>>> +     enum ccu_clk_flags flags;
> >>>>> +};
> >>>>> +
> >>>>> +#define TREE(_parent, _type, _off,                           \
> >>>>
> >>>> Just a nit, but TREE is somewhat confusing here, as this just
> >>>> constructs a single entry in an array. The tree property is
> >>>> realised through the parent array, if I get this correctly.
> >>>> So should we name this ENTRY or CLK_ENTRY instead?
> >>>>
> >>>>> +          _m, _p,                                            \
> >>>>> +          _mux,                                              \
> >>>>> +          _postdiv,                                          \
> >>>>> +          _n, _k,                                            \
> >>>>> +          _fixed_rate,                                       \
> >>>>> +          _flags) {                                          \
> >>>>> +     .parent = _parent,                                      \
> >>>>> +     .type = _type,                                          \
> >>>>> +     .off = _off,                                            \
> >>>>> +     .m = _m,                                                \
> >>>>> +     .p = _p,                                                \
> >>>>> +     .mux = _mux,                                            \
> >>>>> +     .postdiv = _postdiv,                                    \
> >>>>> +     .n = _n,                                                \
> >>>>> +     .k = _k,                                                \
> >>>>> +     .fixed_rate = _fixed_rate,                              \
> >>>>> +     .flags = _flags,                                        \
> >>>>> +}
> >>>>> +
> >>>>> +#define
> >>>>> MISC(_parent)                                                \
> >>>>> +     TREE(_parent, CCU_CLK_TYPE_MISC, 0,                     \
> >>>>> +          {0}, {0},                                          \
> >>>>> +          {0},                                               \
> >>>>> +          0,                                                 \
> >>>>> +          {0}, {0},                                          \
> >>>>> +          0,                                                 \
> >>>>> +          CCU_CLK_F_INIT_DONE)
> >>>>
> >>>> If MISC is really something like GATE or SIMPLE, would it be
> >>>> possible to construct the single element array here, so that the
> >>>> macro just takes the one parent clock ID here, instead of referring
> >>>> to an extra array?
> >>>>> +
> >>>>> +#define FIXED(_fixed_rate)                                   \
> >>>>> +     TREE(NULL, CCU_CLK_TYPE_FIXED, 0,                       \
> >>>>> +          {0}, {0},                                          \
> >>>>> +          {0},                                               \
> >>>>> +          0,                                                 \
> >>>>> +          {0}, {0},                                          \
> >>>>> +          _fixed_rate,                                       \
> >>>>> +          CCU_CLK_F_INIT_DONE)
> >>>>> +
> >>>>> +#define NK(_parent, _off,                                    \
> >>>>> +        _nshift, _nwidth,                                    \
> >>>>> +        _kshift, _kwidth, _kmin,                             \
> >>>>> +        _postdiv,                                            \
> >>>>> +        _flags)                                              \
> >>>>> +     TREE(_parent, CCU_CLK_TYPE_NK, _off,                    \
> >>>>> +          {0}, {0},                                          \
> >>>>> +          {0},                                               \
> >>>>> +          _postdiv,                                          \
> >>>>> +          _CCU_MULT(_nshift, _nwidth),                       \
> >>>>> +          _CCU_MULT_MIN(_kshift, _kwidth, _kmin),            \
> >>>>> +          0,                                                 \
> >>>>> +          CCU_CLK_F_INIT_DONE | _flags)
> >>>>> +
> >>>>> +#define MP(_parent, _off,                                    \
> >>>>> +        _mshift, _mwidth,                                    \
> >>>>> +        _pshift, _pwidth,                                    \
> >>>>> +        _muxshift, _muxwidth,                                \
> >>>>> +        _postdiv,                                            \
> >>>>> +        _flags)                                              \
> >>>>> +     TREE(_parent, CCU_CLK_TYPE_MP, _off,                    \
> >>>>> +          _CCU_DIV(_mshift, _mwidth),                        \
> >>>>> +          _CCU_DIV(_pshift, _pwidth),                        \
> >>>>> +          _CCU_MUX(_muxshift, _muxwidth),                    \
> >>>>> +          _postdiv,                                          \
> >>>>> +          {0}, {0},                                          \
> >>>>> +          0,                                                 \
> >>>>> +          CCU_CLK_F_INIT_DONE | _flags)
> >>>>> +
> >>>>>  /**
> >>>>>   * struct ccu_clk_gate - ccu clock gate
> >>>>>   * @off:     gate offset
> >>>>> @@ -59,6 +248,7 @@ struct ccu_reset {
> >>>>>   * @resets:  reset unit
> >>>>>   */
> >>>>>  struct ccu_desc {
> >>>>> +     const struct ccu_clk_tree *tree;
> >>>>>       const struct ccu_clk_gate *gates;
> >>>>>       const struct ccu_reset *resets;
> >>>>>  };
> >>>>> diff --git a/drivers/clk/sunxi/clk_a64.c
> >>>>> b/drivers/clk/sunxi/clk_a64.c index 162ec769d6..1d0cd98183 100644
> >>>>> --- a/drivers/clk/sunxi/clk_a64.c
> >>>>> +++ b/drivers/clk/sunxi/clk_a64.c
> >>>>> @@ -12,6 +12,45 @@
> >>>>>  #include <dt-bindings/clock/sun50i-a64-ccu.h>
> >>>>>  #include <dt-bindings/reset/sun50i-a64-ccu.h>
> >>>>>
> >>>>> +#define CLK_APB2                     26
> >>>>> +#define CLK_OSC_32K                  (CLK_GPU + 1)
> >>>>> +#define CLK_OSC_24M                  (CLK_OSC_32K + 1)
> >>>>> +
> >>>>> +static const unsigned long periph0_parents[] = {
> >>>>
> >>>> Why is this long? That's the DT clock index, which is 32 bit wide,
> >>>> right? Just unsigned int or uint32_t should be sufficient. long is
> >>>> quite a treacherous type to use, especially as we share code
> >>>> between 32 and 64-bit architectures.
> >>>>
> >>>>> +     CLK_OSC_24M,
> >>>>> +};
> >>>>> +
> >>>>> +static const unsigned long apb2_parents[] = {
> >>>>> +     CLK_OSC_32K,
> >>>>> +     CLK_OSC_24M,
> >>>>> +     CLK_PLL_PERIPH0,
> >>>>> +     CLK_PLL_PERIPH0,
> >>>>> +};
> >>>>> +
> >>>>> +static const unsigned long uart_parents[] = {
> >>>>> +     CLK_APB2,
> >>>>> +};
> >>>>> +
> >>>>> +static const struct ccu_clk_tree a64_tree[] = {
> >>>>> +     [CLK_OSC_32K]           = FIXED(OSC_32K_ULL),
> >>>>> +     [CLK_OSC_24M]           = FIXED(OSC_24M_ULL),
> >>>>> +
> >>>>> +     [CLK_PLL_PERIPH0]       = NK(periph0_parents, 0x028,
> >>>>> +                                  8, 5,      /* N */
> >>>>> +                                  4, 2, 2,   /* K */
> >>>>> +                                  2,         /* post-div */
> >>>>> +                                  CCU_CLK_F_POSTDIV),
> >>>>> +
> >>>>> +     [CLK_APB2]              = MP(apb2_parents, 0x058,
> >>>>> +                                  0, 5,      /* M */
> >>>>> +                                  16, 2,     /* P */
> >>>>> +                                  24, 2,     /* mux */
> >>>>> +                                  0,
> >>>>> +                                  0),
> >>>>> +
> >>>>> +     [CLK_BUS_UART0]         = MISC(uart_parents),
> >>>>> +};
> >>>>> +
> >>>>>  static const struct ccu_clk_gate a64_gates[] = {
> >>>>>       [CLK_BUS_OTG]           = GATE(0x060, BIT(23)),
> >>>>>       [CLK_BUS_EHCI0]         = GATE(0x060, BIT(24)),
> >>>>> @@ -52,6 +91,7 @@ static const struct ccu_reset a64_resets[] = {
> >>>>>  };
> >>>>>
> >>>>>  static const struct ccu_desc a64_ccu_desc = {
> >>>>> +     .tree = a64_tree,
> >>>>>       .gates = a64_gates,
> >>>>>       .resets = a64_resets,
> >>>>>  };
> >>>>> diff --git a/drivers/clk/sunxi/clk_sunxi.c
> >>>>> b/drivers/clk/sunxi/clk_sunxi.c index 345d706c2a..2aebd257d1
> >>>>> 100644 --- a/drivers/clk/sunxi/clk_sunxi.c
> >>>>> +++ b/drivers/clk/sunxi/clk_sunxi.c
> >>>>> @@ -18,6 +18,187 @@ static const struct ccu_clk_gate
> >>>>> *priv_to_gate(struct ccu_priv *priv, return
> >>>>> &priv->desc->gates[id]; }
> >>>>>
> >>>>> +static const struct ccu_clk_tree *priv_to_tree(struct ccu_priv
> >>>>> *priv,
> >>>>> +                                            unsigned long id)
> >>>>
> >>>> Again, why long here? Especially as it's u32 in the function below.
> >>>>
> >>>>> +{
> >>>>> +     return &priv->desc->tree[id];
> >>>>> +}
> >>>>> +
> >>>>> +static int sunxi_get_parent_idx(const struct ccu_clk_tree *tree,
> >>>>> void *base) +{
> >>>>> +     u32 reg, idx;
> >>>>> +
> >>>>> +     reg = readl(base + tree->off);
> >>>>> +     idx = reg >> tree->mux.shift;
> >>>>> +     idx &= (1 << tree->mux.width) - 1;
> >>>>> +
> >>>>> +     return idx;
> >>>>> +}
> >>>>> +
> >>>>> +static ulong sunxi_fixed_get_rate(struct clk *clk, unsigned long
> >>>>> id)
> >>>>
> >>>> Same "long" question for both the return type and the id.
> >>>> And for everything below.
> >>>>
> >>>>> +{
> >>>>> +     struct ccu_priv *priv = dev_get_priv(clk->dev);
> >>>>> +     const struct ccu_clk_tree *tree = priv_to_tree(priv, id);
> >>>>> +
> >>>>> +     if (!(tree->flags & CCU_CLK_F_INIT_DONE)) {
> >>>>> +             printf("%s: (CLK#%ld) unhandled\n", __func__,
> >>>>> clk->id);
> >>>>> +             return 0;
> >>>>> +     }
> >>>>> +
> >>>>> +     return tree->fixed_rate;
> >>>>> +}
> >>>>> +
> >>>>
> >>>> So why are there all those separate functions? Isn't that all the
> >>>> same algorithm: adjust the parent rate based on the clock type?
> >>>> I reworked this with recursive calls and it's MUCH less code:
> >>>>
> >>>> (fill the gaps, using your types for your convenience ;-)
> >>>>
> >>>> static ulong sunxi_apply_pll(struct ccu_priv *priv, ulong id, ulong
> >>>> parent_rate) { NK algorithm of sunxi_nk_get_rate }
> >>>> static ulong sunxi_apply_div(struct ccu_priv *priv, ulong id, ulong
> >>>> parent_rate) { MP algorithm of sunxi_mp_get_rate }
> >>>> static ulong sunxi_calc_clk_rate(struct ccu_priv *priv, ulong clkid)
> >>>> {
> >>>> ....
> >>>>         switch (tree->type) {
> >>>>         case CCU_CLK_TYPE_MISC:
> >>>>                 return sunxi_calc_clk_rate(priv, tree->parent[0]);
> >>>>         case CCU_CLK_TYPE_FIXED:
> >>>>                 return tree->fixed_rate;
> >>>>         case CCU_CLK_TYPE_NK:
> >>>>                 rate = sunxi_calc_clk_rate(priv,
> >>>>                         sunxi_get_parent_id(tree, priv->base));
> >>>>                 return sunxi_apply_pll(priv, clkid, rate);
> >>>>         (similar for _MP)
> >>>> ...
> >>>> }
> >>>
> >>> Initially I would tried the recursive and yes code can reduce but
> >>> using recursive can leed more disadvantage in-terms of code tracing
> >>> during long run. Due to all these factors I used simple function
> >>> calls.
> >>
> >> But I find those extra functions much more confusing, due to the
> >> similar names and their very similar functionality. Also it seems that
> >> you just implemented what we need so far, so you will probably need to
> >> extend those functions, making them even more similar and duplicating
> >> more code. Basically you try to roll out the tree structure.
> >>
> >> Since the clocks are organised in a tree-like structure, I believe this
> >> recursive definition is a much better fit: A clock takes one of
> >> possibly multiple input clocks and adjusts this rate. Full stop. The
> >> rest is then just connecting them to other clocks.
> >> The code looks much simpler and is much smaller this way:
> >> https://gist.github.com/apritzel/db93dd06b4defb46504bccbfe4fc2c20#file-sunxi_clk-c-L86-L112
> >>
> >> Typically the recursion depth is just two or three levels, so I don't
> >> buy the argument of code tracing.
> >
> > OK. agreed thanks.
> >
> > I shall take this recursive and try to mark separate patch on behalf
> > of you if possible, will that be fine?
>
> No need, just rework this into this patch and keep your authorship. You
> did the bulk of the work anyway. If someone complains about the code,
> send them to me ;-)
>
> > He is my next version TODO.
> > - Fixing clock types with meaning full values
> > - Adopt recursive function calls
> > - Try to add full MMC blot.
> >
> > Let me know if you have any comments or question so-that we can
> > collaborate smooth to get CLK in as soon as possible.
>
> Sure, lets nail this in the upcoming merge window.
>
> Btw. I still get the warning for DM_USB, shouldn't this be fixed already
> by this series?

We already have DM_USB enabled, since the check will also look for BLK
it's still showing the warning. Once we move DM_MMC it will gone.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH
  2018-12-31 16:59 ` [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
  2019-01-07 13:04   ` Maxime Ripard
@ 2019-01-22 16:32   ` Alexander Graf
  2019-01-22 16:40     ` Andre Przywara
  1 sibling, 1 reply; 49+ messages in thread
From: Alexander Graf @ 2019-01-22 16:32 UTC (permalink / raw)
  To: u-boot



On 31.12.18 17:59, Jagan Teki wrote:
> Sopine has Winbond SPI flash, so enable the same to use
> flash on Sopine board.
> 
> Cc: TL Lim <tllim@pine64.org>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> ---
>  .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi  | 16 ++++++++++++++++
>  configs/sopine_baseboard_defconfig               |  7 +++++++
>  2 files changed, 23 insertions(+)
>  create mode 100644 arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> 
> diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> new file mode 100644
> index 0000000000..9661b95d15
> --- /dev/null
> +++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi

Where does this dtsi get included?


Alex

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH
  2019-01-22 16:32   ` Alexander Graf
@ 2019-01-22 16:40     ` Andre Przywara
  2019-01-22 16:47       ` Tom Rini
  0 siblings, 1 reply; 49+ messages in thread
From: Andre Przywara @ 2019-01-22 16:40 UTC (permalink / raw)
  To: u-boot

On Tue, 22 Jan 2019 17:32:27 +0100
Alexander Graf <agraf@suse.de> wrote:

> On 31.12.18 17:59, Jagan Teki wrote:
> > Sopine has Winbond SPI flash, so enable the same to use
> > flash on Sopine board.
> > 
> > Cc: TL Lim <tllim@pine64.org>
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > ---
> >  .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi  | 16
> > ++++++++++++++++ configs/sopine_baseboard_defconfig
> > |  7 +++++++ 2 files changed, 23 insertions(+)
> >  create mode 100644
> > arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> > 
> > diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> > b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi new file
> > mode 100644 index 0000000000..9661b95d15
> > --- /dev/null
> > +++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi  
> 
> Where does this dtsi get included?

This is some U-Boot build system magic, more precisely by binman:
http://git.denx.de/?p=u-boot.git;a=blob;f=tools/binman/README;hb=HEAD#l564

Cheers,
Andre.

^ permalink raw reply	[flat|nested] 49+ messages in thread

* [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH
  2019-01-22 16:40     ` Andre Przywara
@ 2019-01-22 16:47       ` Tom Rini
  0 siblings, 0 replies; 49+ messages in thread
From: Tom Rini @ 2019-01-22 16:47 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 22, 2019 at 04:40:19PM +0000, Andre Przywara wrote:
> On Tue, 22 Jan 2019 17:32:27 +0100
> Alexander Graf <agraf@suse.de> wrote:
> 
> > On 31.12.18 17:59, Jagan Teki wrote:
> > > Sopine has Winbond SPI flash, so enable the same to use
> > > flash on Sopine board.
> > > 
> > > Cc: TL Lim <tllim@pine64.org>
> > > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > > ---
> > >  .../dts/sun50i-a64-sopine-baseboard-u-boot.dtsi  | 16
> > > ++++++++++++++++ configs/sopine_baseboard_defconfig
> > > |  7 +++++++ 2 files changed, 23 insertions(+)
> > >  create mode 100644
> > > arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> > > 
> > > diff --git a/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi
> > > b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi new file
> > > mode 100644 index 0000000000..9661b95d15
> > > --- /dev/null
> > > +++ b/arch/arm/dts/sun50i-a64-sopine-baseboard-u-boot.dtsi  
> > 
> > Where does this dtsi get included?
> 
> This is some U-Boot build system magic, more precisely by binman:
> http://git.denx.de/?p=u-boot.git;a=blob;f=tools/binman/README;hb=HEAD#l564

Well, scripts/Makefile.lib has the logic for searching for the most
appropriate -u-boot.dtsi file.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190122/bf5be876/attachment.sig>

^ permalink raw reply	[flat|nested] 49+ messages in thread

end of thread, other threads:[~2019-01-22 16:47 UTC | newest]

Thread overview: 49+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-12-31 16:59 [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 01/26] clk: Add Allwinner A64 CLK driver Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 02/26] reset: Add Allwinner RESET driver Jagan Teki
2019-01-10  0:50   ` André Przywara
2018-12-31 16:59 ` [U-Boot] [PATCH v5 03/26] clk: sunxi: Add Allwinner H3/H5 CLK driver Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 04/26] clk: sunxi: Add Allwinner A10/A20 " Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 05/26] clk: sunxi: Add Allwinner A10s/A13 " Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 06/26] clk: sunxi: Add Allwinner A31 " Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 07/26] clk: sunxi: Add Allwinner A23/A33 " Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 08/26] clk: sunxi: Add Allwinner A83T " Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 09/26] clk: sunxi: Add Allwinner R40 " Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 10/26] clk: sunxi: Add Allwinner V3S " Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 11/26] clk: sunxi: Implement UART clocks Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 12/26] clk: sunxi: Implement UART resets Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 13/26] clk: sunxi: Add Allwinner H6 CLK driver Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 14/26] sunxi: A64: Update sun50i-a64-ccu.h Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 15/26] clk: sunxi: Add ccu clock tree support Jagan Teki
2019-01-07  1:03   ` André Przywara
2019-01-07 13:01     ` Maxime Ripard
2019-01-07 14:09       ` Andre Przywara
2019-01-07 18:25         ` Maxime Ripard
2019-01-08 10:57     ` Jagan Teki
2019-01-08 11:39       ` Andre Przywara
2019-01-08 19:12         ` Jagan Teki
2019-01-10  0:50           ` André Przywara
2019-01-10 18:31             ` Jagan Teki
2019-01-08 11:25     ` Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 16/26] sunxi: Enable CLK Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 17/26] phy: sun4i-usb: Use CLK and RESET support Jagan Teki
2018-12-31 18:29   ` Marek Vasut
2018-12-31 18:38     ` Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 18/26] reset: Add reset valid Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 19/26] musb-new: sunxi: Use CLK and RESET support Jagan Teki
2018-12-31 18:30   ` Marek Vasut
2018-12-31 16:59 ` [U-Boot] [PATCH v5 20/26] sunxi: usb: Switch to Generic host controllers Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 21/26] usb: host: Drop [e-o]hci-sunxi drivers Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 22/26] clk: sunxi: Implement SPI clocks Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 23/26] spi: sun4i: Add CLK support Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 24/26] clk: sunxi: Implement A64 SPI clocks, resets Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 25/26] spi: Add Allwinner A31 SPI driver Jagan Teki
2018-12-31 16:59 ` [U-Boot] [PATCH v5 26/26] board: sopine: Enable SPI/SPI-FLASH Jagan Teki
2019-01-07 13:04   ` Maxime Ripard
2019-01-22 16:32   ` Alexander Graf
2019-01-22 16:40     ` Andre Przywara
2019-01-22 16:47       ` Tom Rini
2019-01-06  9:39 ` [U-Boot] [PATCH v5 00/26] clk: Add Allwinner CLK, RESET support Jagan Teki
2019-01-06 13:17 ` André Przywara
2019-01-06 19:22   ` Jagan Teki
2019-01-07  1:21     ` André Przywara

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.