* [PATCH v9 4/6] clk: Ingenic: Add CGU driver for X1830.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-24 15:47 UTC (permalink / raw)
To: linux-clk
Cc: linux-kernel, devicetree, sboyd, mturquette, robh+dt,
dongsheng.qiu, aric.pzqi, sernia.zhou, zhenwenjin, paul
In-Reply-To: <20200524154729.30958-1-zhouyanjie@wanyeetech.com>
Add support for the clocks provided by the CGU in the Ingenic X1830
SoC, making use of the cgu code to do the heavy lifting.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
---
Notes:
v1->v2:
1.Use two fields (pll_reg & bypass_reg) instead of the 2-values
array (reg[2]).
2.Remove the "pll_info->version" and add a "pll_info->rate_multiplier".
3.Change my Signed-off-by from "Zhou Yanjie <zhouyanjie@zoho.com>"
to "周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>" because
the old mailbox is in an unstable state.
v2->v3:
Adjust order from [4/5] in v2 to [5/5] in v3.
v3->v4:
Adjust order from [5/5] in v3 to [4/4] in v4.
v4->v5:
Rebase on top of kernel 5.6-rc1.
v5->v6:
Add missing part of X1830's CGU.
v6->v7:
1.Adjust includes, add blank line as Paul Cercueil's suggest.
2.Move "*cgu" into x1830_cgu_init() as a local variable.
v7->v8:
No change.
v8->v9:
Add Paul Cercueil's Reviewed-by, somehow his emails are not displayed
on the mailing list and patchwork of clock framework subsystem.
drivers/clk/ingenic/Kconfig | 10 +
drivers/clk/ingenic/Makefile | 1 +
drivers/clk/ingenic/x1830-cgu.c | 436 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 447 insertions(+)
create mode 100644 drivers/clk/ingenic/x1830-cgu.c
diff --git a/drivers/clk/ingenic/Kconfig b/drivers/clk/ingenic/Kconfig
index b4555b465ea6..580b0cf69ed5 100644
--- a/drivers/clk/ingenic/Kconfig
+++ b/drivers/clk/ingenic/Kconfig
@@ -55,6 +55,16 @@ config INGENIC_CGU_X1000
If building for a X1000 SoC, you want to say Y here.
+config INGENIC_CGU_X1830
+ bool "Ingenic X1830 CGU driver"
+ default MACH_X1830
+ select INGENIC_CGU_COMMON
+ help
+ Support the clocks provided by the CGU hardware on Ingenic X1830
+ and compatible SoCs.
+
+ If building for a X1830 SoC, you want to say Y here.
+
config INGENIC_TCU_CLK
bool "Ingenic JZ47xx TCU clocks driver"
default MACH_INGENIC
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index 8b1dad9b74a7..aaa4bffe03c6 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o
obj-$(CONFIG_INGENIC_CGU_X1000) += x1000-cgu.o
+obj-$(CONFIG_INGENIC_CGU_X1830) += x1830-cgu.o
obj-$(CONFIG_INGENIC_TCU_CLK) += tcu.o
diff --git a/drivers/clk/ingenic/x1830-cgu.c b/drivers/clk/ingenic/x1830-cgu.c
new file mode 100644
index 000000000000..8989dbe6ee61
--- /dev/null
+++ b/drivers/clk/ingenic/x1830-cgu.c
@@ -0,0 +1,436 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * X1830 SoC CGU driver
+ * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#include <dt-bindings/clock/x1830-cgu.h>
+
+#include "cgu.h"
+#include "pm.h"
+
+/* CGU register offsets */
+#define CGU_REG_CPCCR 0x00
+#define CGU_REG_CPPCR 0x0c
+#define CGU_REG_APLL 0x10
+#define CGU_REG_MPLL 0x14
+#define CGU_REG_CLKGR0 0x20
+#define CGU_REG_OPCR 0x24
+#define CGU_REG_CLKGR1 0x28
+#define CGU_REG_DDRCDR 0x2c
+#define CGU_REG_USBPCR 0x3c
+#define CGU_REG_USBRDT 0x40
+#define CGU_REG_USBVBFIL 0x44
+#define CGU_REG_USBPCR1 0x48
+#define CGU_REG_MACCDR 0x54
+#define CGU_REG_EPLL 0x58
+#define CGU_REG_I2SCDR 0x60
+#define CGU_REG_LPCDR 0x64
+#define CGU_REG_MSC0CDR 0x68
+#define CGU_REG_I2SCDR1 0x70
+#define CGU_REG_SSICDR 0x74
+#define CGU_REG_CIMCDR 0x7c
+#define CGU_REG_MSC1CDR 0xa4
+#define CGU_REG_CMP_INTR 0xb0
+#define CGU_REG_CMP_INTRE 0xb4
+#define CGU_REG_DRCG 0xd0
+#define CGU_REG_CPCSR 0xd4
+#define CGU_REG_VPLL 0xe0
+#define CGU_REG_MACPHYC 0xe8
+
+/* bits within the OPCR register */
+#define OPCR_SPENDN0 BIT(7)
+#define OPCR_SPENDN1 BIT(6)
+
+/* bits within the USBPCR register */
+#define USBPCR_SIDDQ BIT(21)
+#define USBPCR_OTG_DISABLE BIT(20)
+
+static struct ingenic_cgu *cgu;
+
+static int x1830_usb_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
+
+ writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
+ writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
+ return 0;
+}
+
+static void x1830_usb_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
+ writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
+}
+
+static int x1830_usb_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
+
+ return (readl(reg_opcr) & OPCR_SPENDN0) &&
+ !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
+ !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
+}
+
+static const struct clk_ops x1830_otg_phy_ops = {
+ .enable = x1830_usb_phy_enable,
+ .disable = x1830_usb_phy_disable,
+ .is_enabled = x1830_usb_phy_is_enabled,
+};
+
+static const s8 pll_od_encoding[64] = {
+ 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
+ -1, -1, -1, -1, -1, -1, -1, 0x4,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 0x5,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 0x6,
+};
+
+static const struct ingenic_cgu_clk_info x1830_cgu_clocks[] = {
+
+ /* External clocks */
+
+ [X1830_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
+ [X1830_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
+
+ /* PLLs */
+
+ [X1830_CLK_APLL] = {
+ "apll", CGU_CLK_PLL,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .pll = {
+ .reg = CGU_REG_APLL,
+ .rate_multiplier = 2,
+ .m_shift = 20,
+ .m_bits = 9,
+ .m_offset = 1,
+ .n_shift = 14,
+ .n_bits = 6,
+ .n_offset = 1,
+ .od_shift = 11,
+ .od_bits = 3,
+ .od_max = 64,
+ .od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_CPPCR,
+ .bypass_bit = 30,
+ .enable_bit = 0,
+ .stable_bit = 3,
+ },
+ },
+
+ [X1830_CLK_MPLL] = {
+ "mpll", CGU_CLK_PLL,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .pll = {
+ .reg = CGU_REG_MPLL,
+ .rate_multiplier = 2,
+ .m_shift = 20,
+ .m_bits = 9,
+ .m_offset = 1,
+ .n_shift = 14,
+ .n_bits = 6,
+ .n_offset = 1,
+ .od_shift = 11,
+ .od_bits = 3,
+ .od_max = 64,
+ .od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_CPPCR,
+ .bypass_bit = 28,
+ .enable_bit = 0,
+ .stable_bit = 3,
+ },
+ },
+
+ [X1830_CLK_EPLL] = {
+ "epll", CGU_CLK_PLL,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .pll = {
+ .reg = CGU_REG_EPLL,
+ .rate_multiplier = 2,
+ .m_shift = 20,
+ .m_bits = 9,
+ .m_offset = 1,
+ .n_shift = 14,
+ .n_bits = 6,
+ .n_offset = 1,
+ .od_shift = 11,
+ .od_bits = 3,
+ .od_max = 64,
+ .od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_CPPCR,
+ .bypass_bit = 24,
+ .enable_bit = 0,
+ .stable_bit = 3,
+ },
+ },
+
+ [X1830_CLK_VPLL] = {
+ "vpll", CGU_CLK_PLL,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .pll = {
+ .reg = CGU_REG_VPLL,
+ .rate_multiplier = 2,
+ .m_shift = 20,
+ .m_bits = 9,
+ .m_offset = 1,
+ .n_shift = 14,
+ .n_bits = 6,
+ .n_offset = 1,
+ .od_shift = 11,
+ .od_bits = 3,
+ .od_max = 64,
+ .od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_CPPCR,
+ .bypass_bit = 26,
+ .enable_bit = 0,
+ .stable_bit = 3,
+ },
+ },
+
+ /* Custom (SoC-specific) OTG PHY */
+
+ [X1830_CLK_OTGPHY] = {
+ "otg_phy", CGU_CLK_CUSTOM,
+ .parents = { X1830_CLK_EXCLK },
+ .custom = { &x1830_otg_phy_ops },
+ },
+
+ /* Muxes & dividers */
+
+ [X1830_CLK_SCLKA] = {
+ "sclk_a", CGU_CLK_MUX,
+ .parents = { -1, X1830_CLK_EXCLK, X1830_CLK_APLL, -1 },
+ .mux = { CGU_REG_CPCCR, 30, 2 },
+ },
+
+ [X1830_CLK_CPUMUX] = {
+ "cpu_mux", CGU_CLK_MUX,
+ .parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
+ .mux = { CGU_REG_CPCCR, 28, 2 },
+ },
+
+ [X1830_CLK_CPU] = {
+ "cpu", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
+ .div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 15 },
+ },
+
+ [X1830_CLK_L2CACHE] = {
+ "l2cache", CGU_CLK_DIV,
+ .parents = { X1830_CLK_CPUMUX, -1, -1, -1 },
+ .div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
+ },
+
+ [X1830_CLK_AHB0] = {
+ "ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
+ .parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
+ .mux = { CGU_REG_CPCCR, 26, 2 },
+ .div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
+ },
+
+ [X1830_CLK_AHB2PMUX] = {
+ "ahb2_apb_mux", CGU_CLK_MUX,
+ .parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
+ .mux = { CGU_REG_CPCCR, 24, 2 },
+ },
+
+ [X1830_CLK_AHB2] = {
+ "ahb2", CGU_CLK_DIV,
+ .parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
+ .div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
+ },
+
+ [X1830_CLK_PCLK] = {
+ "pclk", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { X1830_CLK_AHB2PMUX, -1, -1, -1 },
+ .div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 14 },
+ },
+
+ [X1830_CLK_DDR] = {
+ "ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { -1, X1830_CLK_SCLKA, X1830_CLK_MPLL, -1 },
+ .mux = { CGU_REG_DDRCDR, 30, 2 },
+ .div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
+ .gate = { CGU_REG_CLKGR0, 31 },
+ },
+
+ [X1830_CLK_MAC] = {
+ "mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
+ X1830_CLK_VPLL, X1830_CLK_EPLL },
+ .mux = { CGU_REG_MACCDR, 30, 2 },
+ .div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
+ .gate = { CGU_REG_CLKGR1, 4 },
+ },
+
+ [X1830_CLK_LCD] = {
+ "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
+ X1830_CLK_VPLL, X1830_CLK_EPLL },
+ .mux = { CGU_REG_LPCDR, 30, 2 },
+ .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
+ .gate = { CGU_REG_CLKGR1, 9 },
+ },
+
+ [X1830_CLK_MSCMUX] = {
+ "msc_mux", CGU_CLK_MUX,
+ .parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
+ X1830_CLK_VPLL, X1830_CLK_EPLL },
+ .mux = { CGU_REG_MSC0CDR, 30, 2 },
+ },
+
+ [X1830_CLK_MSC0] = {
+ "msc0", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
+ .div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
+ .gate = { CGU_REG_CLKGR0, 4 },
+ },
+
+ [X1830_CLK_MSC1] = {
+ "msc1", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { X1830_CLK_MSCMUX, -1, -1, -1 },
+ .div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
+ .gate = { CGU_REG_CLKGR0, 5 },
+ },
+
+ [X1830_CLK_SSIPLL] = {
+ "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
+ .parents = { X1830_CLK_SCLKA, X1830_CLK_MPLL,
+ X1830_CLK_VPLL, X1830_CLK_EPLL },
+ .mux = { CGU_REG_SSICDR, 30, 2 },
+ .div = { CGU_REG_SSICDR, 0, 1, 8, 28, 27, 26 },
+ },
+
+ [X1830_CLK_SSIPLL_DIV2] = {
+ "ssi_pll_div2", CGU_CLK_FIXDIV,
+ .parents = { X1830_CLK_SSIPLL },
+ .fixdiv = { 2 },
+ },
+
+ [X1830_CLK_SSIMUX] = {
+ "ssi_mux", CGU_CLK_MUX,
+ .parents = { X1830_CLK_EXCLK, X1830_CLK_SSIPLL_DIV2, -1, -1 },
+ .mux = { CGU_REG_SSICDR, 29, 1 },
+ },
+
+ /* Gate-only clocks */
+
+ [X1830_CLK_EMC] = {
+ "emc", CGU_CLK_GATE,
+ .parents = { X1830_CLK_AHB2, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 0 },
+ },
+
+ [X1830_CLK_EFUSE] = {
+ "efuse", CGU_CLK_GATE,
+ .parents = { X1830_CLK_AHB2, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 1 },
+ },
+
+ [X1830_CLK_OTG] = {
+ "otg", CGU_CLK_GATE,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 3 },
+ },
+
+ [X1830_CLK_SSI0] = {
+ "ssi0", CGU_CLK_GATE,
+ .parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 6 },
+ },
+
+ [X1830_CLK_SMB0] = {
+ "smb0", CGU_CLK_GATE,
+ .parents = { X1830_CLK_PCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 7 },
+ },
+
+ [X1830_CLK_SMB1] = {
+ "smb1", CGU_CLK_GATE,
+ .parents = { X1830_CLK_PCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 8 },
+ },
+
+ [X1830_CLK_SMB2] = {
+ "smb2", CGU_CLK_GATE,
+ .parents = { X1830_CLK_PCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 9 },
+ },
+
+ [X1830_CLK_UART0] = {
+ "uart0", CGU_CLK_GATE,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 14 },
+ },
+
+ [X1830_CLK_UART1] = {
+ "uart1", CGU_CLK_GATE,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 15 },
+ },
+
+ [X1830_CLK_SSI1] = {
+ "ssi1", CGU_CLK_GATE,
+ .parents = { X1830_CLK_SSIMUX, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 19 },
+ },
+
+ [X1830_CLK_SFC] = {
+ "sfc", CGU_CLK_GATE,
+ .parents = { X1830_CLK_SSIPLL, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 20 },
+ },
+
+ [X1830_CLK_PDMA] = {
+ "pdma", CGU_CLK_GATE,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR0, 21 },
+ },
+
+ [X1830_CLK_DTRNG] = {
+ "dtrng", CGU_CLK_GATE,
+ .parents = { X1830_CLK_PCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 1 },
+ },
+
+ [X1830_CLK_OST] = {
+ "ost", CGU_CLK_GATE,
+ .parents = { X1830_CLK_EXCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR1, 11 },
+ },
+};
+
+static void __init x1830_cgu_init(struct device_node *np)
+{
+ int retval;
+
+ cgu = ingenic_cgu_new(x1830_cgu_clocks,
+ ARRAY_SIZE(x1830_cgu_clocks), np);
+ if (!cgu) {
+ pr_err("%s: failed to initialise CGU\n", __func__);
+ return;
+ }
+
+ retval = ingenic_cgu_register_clocks(cgu);
+ if (retval) {
+ pr_err("%s: failed to register CGU Clocks\n", __func__);
+ return;
+ }
+
+ ingenic_cgu_register_syscore_ops(cgu);
+}
+CLK_OF_DECLARE_DRIVER(x1830_cgu, "ingenic,x1830-cgu", x1830_cgu_init);
--
2.11.0
^ permalink raw reply related
* [PATCH v9 6/6] clk: X1000: Add FIXDIV for SSI clock of X1000.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-24 15:47 UTC (permalink / raw)
To: linux-clk
Cc: linux-kernel, devicetree, sboyd, mturquette, robh+dt,
dongsheng.qiu, aric.pzqi, sernia.zhou, zhenwenjin, paul
In-Reply-To: <20200524154729.30958-1-zhouyanjie@wanyeetech.com>
1.The SSI clock of X1000 not like JZ4770 and JZ4780, they are not
directly derived from the output of SSIPLL, but from the clock
obtained by dividing the frequency by 2. "X1000_CLK_SSIPLL_DIV2"
is added for this purpose, and ensure that it initialized before
"X1000_CLK_SSIMUX" when initializing the clocks.
2.Clocks of LCD, OTG, EMC, EFUSE, OST, and gates of CPU, PCLK
are also added.
3.Use "CLK_OF_DECLARE_DRIVER" like the other CGU drivers.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
---
Notes:
v5:
New patch.
V5->v6:
Add missing part of X1000's CGU.
v6->v7:
Update commit message.
v7->v8:
No change.
v8->v9:
Add Paul Cercueil's Reviewed-by, somehow his emails are not displayed
on the mailing list and patchwork of clock framework subsystem.
drivers/clk/ingenic/x1000-cgu.c | 112 +++++++++++++++++++++++++++++++++++++---
1 file changed, 105 insertions(+), 7 deletions(-)
diff --git a/drivers/clk/ingenic/x1000-cgu.c b/drivers/clk/ingenic/x1000-cgu.c
index c33934d8ac14..a4110cf96a8a 100644
--- a/drivers/clk/ingenic/x1000-cgu.c
+++ b/drivers/clk/ingenic/x1000-cgu.c
@@ -1,15 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
/*
* X1000 SoC CGU driver
- * Copyright (c) 2019 Zhou Yanjie <zhouyanjie@zoho.com>
+ * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/of.h>
-
#include <dt-bindings/clock/x1000-cgu.h>
-
#include "cgu.h"
#include "pm.h"
@@ -20,6 +18,9 @@
#define CGU_REG_CLKGR 0x20
#define CGU_REG_OPCR 0x24
#define CGU_REG_DDRCDR 0x2c
+#define CGU_REG_USBPCR 0x3c
+#define CGU_REG_USBPCR1 0x48
+#define CGU_REG_USBCDR 0x50
#define CGU_REG_MACCDR 0x54
#define CGU_REG_I2SCDR 0x60
#define CGU_REG_LPCDR 0x64
@@ -40,8 +41,47 @@
#define OPCR_SPENDN0 BIT(7)
#define OPCR_SPENDN1 BIT(6)
+/* bits within the USBPCR register */
+#define USBPCR_SIDDQ BIT(21)
+#define USBPCR_OTG_DISABLE BIT(20)
+
static struct ingenic_cgu *cgu;
+static int x1000_usb_phy_enable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
+
+ writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
+ writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
+ return 0;
+}
+
+static void x1000_usb_phy_disable(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
+
+ writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
+ writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
+}
+
+static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
+{
+ void __iomem *reg_opcr = cgu->base + CGU_REG_OPCR;
+ void __iomem *reg_usbpcr = cgu->base + CGU_REG_USBPCR;
+
+ return (readl(reg_opcr) & OPCR_SPENDN0) &&
+ !(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
+ !(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
+}
+
+static const struct clk_ops x1000_otg_phy_ops = {
+ .enable = x1000_usb_phy_enable,
+ .disable = x1000_usb_phy_disable,
+ .is_enabled = x1000_usb_phy_is_enabled,
+};
+
static const s8 pll_od_encoding[8] = {
0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
};
@@ -101,6 +141,15 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
},
},
+
+ /* Custom (SoC-specific) OTG PHY */
+
+ [X1000_CLK_OTGPHY] = {
+ "otg_phy", CGU_CLK_CUSTOM,
+ .parents = { -1, -1, X1000_CLK_EXCLK, -1 },
+ .custom = { &x1000_otg_phy_ops },
+ },
+
/* Muxes & dividers */
[X1000_CLK_SCLKA] = {
@@ -116,9 +165,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
},
[X1000_CLK_CPU] = {
- "cpu", CGU_CLK_DIV,
+ "cpu", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 30 },
},
[X1000_CLK_L2CACHE] = {
@@ -147,9 +197,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
},
[X1000_CLK_PCLK] = {
- "pclk", CGU_CLK_DIV,
+ "pclk", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 28 },
},
[X1000_CLK_DDR] = {
@@ -162,12 +213,20 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_MAC] = {
"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
- .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
+ .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
.mux = { CGU_REG_MACCDR, 31, 1 },
.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR, 25 },
},
+ [X1000_CLK_LCD] = {
+ "lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
+ .mux = { CGU_REG_LPCDR, 31, 1 },
+ .div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
+ .gate = { CGU_REG_CLKGR, 23 },
+ },
+
[X1000_CLK_MSCMUX] = {
"msc_mux", CGU_CLK_MUX,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
@@ -188,6 +247,15 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.gate = { CGU_REG_CLKGR, 5 },
},
+ [X1000_CLK_OTG] = {
+ "otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
+ .parents = { X1000_CLK_EXCLK, -1,
+ X1000_CLK_APLL, X1000_CLK_MPLL },
+ .mux = { CGU_REG_USBCDR, 30, 2 },
+ .div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
+ .gate = { CGU_REG_CLKGR, 3 },
+ },
+
[X1000_CLK_SSIPLL] = {
"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
@@ -195,14 +263,32 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
},
+ [X1000_CLK_SSIPLL_DIV2] = {
+ "ssi_pll_div2", CGU_CLK_FIXDIV,
+ .parents = { X1000_CLK_SSIPLL },
+ .fixdiv = { 2 },
+ },
+
[X1000_CLK_SSIMUX] = {
"ssi_mux", CGU_CLK_MUX,
- .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL, -1, -1 },
+ .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 },
.mux = { CGU_REG_SSICDR, 30, 1 },
},
/* Gate-only clocks */
+ [X1000_CLK_EMC] = {
+ "emc", CGU_CLK_GATE,
+ .parents = { X1000_CLK_AHB2, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 0 },
+ },
+
+ [X1000_CLK_EFUSE] = {
+ "efuse", CGU_CLK_GATE,
+ .parents = { X1000_CLK_AHB2, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 1 },
+ },
+
[X1000_CLK_SFC] = {
"sfc", CGU_CLK_GATE,
.parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
@@ -245,12 +331,24 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.gate = { CGU_REG_CLKGR, 16 },
},
+ [X1000_CLK_TCU] = {
+ "tcu", CGU_CLK_GATE,
+ .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 18 },
+ },
+
[X1000_CLK_SSI] = {
"ssi", CGU_CLK_GATE,
.parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 19 },
},
+ [X1000_CLK_OST] = {
+ "ost", CGU_CLK_GATE,
+ .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 20 },
+ },
+
[X1000_CLK_PDMA] = {
"pdma", CGU_CLK_GATE,
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
--
2.11.0
^ permalink raw reply related
* [PATCH v9 2/6] clk: Ingenic: Adjust cgu code to make it compatible with X1830.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-24 15:47 UTC (permalink / raw)
To: linux-clk
Cc: linux-kernel, devicetree, sboyd, mturquette, robh+dt,
dongsheng.qiu, aric.pzqi, sernia.zhou, zhenwenjin, paul
In-Reply-To: <20200524154729.30958-1-zhouyanjie@wanyeetech.com>
The PLL of X1830 Soc from Ingenic has been greatly changed,
the bypass control is placed in another register, so now two
registers may needed to control the PLL. To this end, a new
"bypass_reg" was introduced. In addition, when calculating
rate, the PLL of X1830 introduced an extra 2x multiplier,
so a new "rate_multiplier" was introduced. And adjust the
code in jz47xx-cgu.c and x1000-cgu.c, make it to be
compatible with the new cgu code.
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
---
Notes:
v2->v3:
Adjust order from [1/5] in v2 to [2/5] in v3.
v3->v4:
Merge [3/5] in v3 into this patch.
v4->v5:
Rebase on top of kernel 5.6-rc1.
v5->v6:
Revert "pll_reg" to "reg" to minimize patch as Paul Cercueil's suggest.
v6->v7:
Update commit message.
v7->v8:
No change.
v8->v9:
No change.
drivers/clk/ingenic/cgu.c | 16 +++++++++++++---
drivers/clk/ingenic/cgu.h | 4 ++++
drivers/clk/ingenic/jz4725b-cgu.c | 4 ++++
drivers/clk/ingenic/jz4740-cgu.c | 4 ++++
drivers/clk/ingenic/jz4770-cgu.c | 8 +++++++-
drivers/clk/ingenic/jz4780-cgu.c | 3 +++
drivers/clk/ingenic/x1000-cgu.c | 6 ++++++
7 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index ab1302ad1450..d7981b670221 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -90,6 +90,9 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
n += pll_info->n_offset;
od_enc = ctl >> pll_info->od_shift;
od_enc &= GENMASK(pll_info->od_bits - 1, 0);
+
+ ctl = readl(cgu->base + pll_info->bypass_reg);
+
bypass = !pll_info->no_bypass_bit &&
!!(ctl & BIT(pll_info->bypass_bit));
@@ -103,7 +106,8 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
BUG_ON(od == pll_info->od_max);
od++;
- return div_u64((u64)parent_rate * m, n * od);
+ return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
+ n * od);
}
static unsigned long
@@ -136,7 +140,8 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
if (pod)
*pod = od;
- return div_u64((u64)parent_rate * m, n * od);
+ return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
+ n * od);
}
static inline const struct ingenic_cgu_clk_info *to_clk_info(
@@ -209,9 +214,14 @@ static int ingenic_pll_enable(struct clk_hw *hw)
u32 ctl;
spin_lock_irqsave(&cgu->lock, flags);
- ctl = readl(cgu->base + pll_info->reg);
+ ctl = readl(cgu->base + pll_info->bypass_reg);
ctl &= ~BIT(pll_info->bypass_bit);
+
+ writel(ctl, cgu->base + pll_info->bypass_reg);
+
+ ctl = readl(cgu->base + pll_info->reg);
+
ctl |= BIT(pll_info->enable_bit);
writel(ctl, cgu->base + pll_info->reg);
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index 0dc8004079ee..2c75ef4a36f5 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -17,6 +17,7 @@
/**
* struct ingenic_cgu_pll_info - information about a PLL
* @reg: the offset of the PLL's control register within the CGU
+ * @rate_multiplier: the multiplier needed by pll rate calculation
* @m_shift: the number of bits to shift the multiplier value by (ie. the
* index of the lowest bit of the multiplier value in the PLL's
* control register)
@@ -37,6 +38,7 @@
* @od_encoding: a pointer to an array mapping post-VCO divider values to
* their encoded values in the PLL control register, or -1 for
* unsupported values
+ * @bypass_reg: the offset of the bypass control register within the CGU
* @bypass_bit: the index of the bypass bit in the PLL control register
* @enable_bit: the index of the enable bit in the PLL control register
* @stable_bit: the index of the stable bit in the PLL control register
@@ -44,10 +46,12 @@
*/
struct ingenic_cgu_pll_info {
unsigned reg;
+ unsigned rate_multiplier;
const s8 *od_encoding;
u8 m_shift, m_bits, m_offset;
u8 n_shift, n_bits, n_offset;
u8 od_shift, od_bits, od_max;
+ unsigned bypass_reg;
u8 bypass_bit;
u8 enable_bit;
u8 stable_bit;
diff --git a/drivers/clk/ingenic/jz4725b-cgu.c b/drivers/clk/ingenic/jz4725b-cgu.c
index a3b4635f6278..8c38e72d14a7 100644
--- a/drivers/clk/ingenic/jz4725b-cgu.c
+++ b/drivers/clk/ingenic/jz4725b-cgu.c
@@ -9,7 +9,9 @@
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/of.h>
+
#include <dt-bindings/clock/jz4725b-cgu.h>
+
#include "cgu.h"
#include "pm.h"
@@ -54,6 +56,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.pll = {
.reg = CGU_REG_CPPCR,
+ .rate_multiplier = 1,
.m_shift = 23,
.m_bits = 9,
.m_offset = 2,
@@ -65,6 +68,7 @@ static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
.od_max = 4,
.od_encoding = pll_od_encoding,
.stable_bit = 10,
+ .bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 9,
.enable_bit = 8,
},
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
index 4f0e92c877d6..c0ac9196a581 100644
--- a/drivers/clk/ingenic/jz4740-cgu.c
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -10,7 +10,9 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
+
#include <dt-bindings/clock/jz4740-cgu.h>
+
#include "cgu.h"
#include "pm.h"
@@ -69,6 +71,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
.parents = { JZ4740_CLK_EXT, -1, -1, -1 },
.pll = {
.reg = CGU_REG_CPPCR,
+ .rate_multiplier = 1,
.m_shift = 23,
.m_bits = 9,
.m_offset = 2,
@@ -80,6 +83,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
.od_max = 4,
.od_encoding = pll_od_encoding,
.stable_bit = 10,
+ .bypass_reg = CGU_REG_CPPCR,
.bypass_bit = 9,
.enable_bit = 8,
},
diff --git a/drivers/clk/ingenic/jz4770-cgu.c b/drivers/clk/ingenic/jz4770-cgu.c
index c051ecba5cf8..9ea4490ecb7f 100644
--- a/drivers/clk/ingenic/jz4770-cgu.c
+++ b/drivers/clk/ingenic/jz4770-cgu.c
@@ -9,7 +9,9 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
+
#include <dt-bindings/clock/jz4770-cgu.h>
+
#include "cgu.h"
#include "pm.h"
@@ -102,6 +104,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.parents = { JZ4770_CLK_EXT },
.pll = {
.reg = CGU_REG_CPPCR0,
+ .rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -112,6 +115,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_CPPCR0,
.bypass_bit = 9,
.enable_bit = 8,
.stable_bit = 10,
@@ -124,6 +128,7 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.parents = { JZ4770_CLK_EXT },
.pll = {
.reg = CGU_REG_CPPCR1,
+ .rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -134,9 +139,10 @@ static const struct ingenic_cgu_clk_info jz4770_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_CPPCR1,
+ .no_bypass_bit = true,
.enable_bit = 7,
.stable_bit = 6,
- .no_bypass_bit = true,
},
},
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
index c758f1643067..6c5b8029cc8a 100644
--- a/drivers/clk/ingenic/jz4780-cgu.c
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -13,6 +13,7 @@
#include <linux/of.h>
#include <dt-bindings/clock/jz4780-cgu.h>
+
#include "cgu.h"
#include "pm.h"
@@ -266,6 +267,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
#define DEF_PLL(name) { \
.reg = CGU_REG_ ## name, \
+ .rate_multiplier = 1, \
.m_shift = 19, \
.m_bits = 13, \
.m_offset = 1, \
@@ -277,6 +279,7 @@ static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
.od_max = 16, \
.od_encoding = pll_od_encoding, \
.stable_bit = 6, \
+ .bypass_reg = CGU_REG_ ## name, \
.bypass_bit = 1, \
.enable_bit = 0, \
}
diff --git a/drivers/clk/ingenic/x1000-cgu.c b/drivers/clk/ingenic/x1000-cgu.c
index b22d87b3f555..c33934d8ac14 100644
--- a/drivers/clk/ingenic/x1000-cgu.c
+++ b/drivers/clk/ingenic/x1000-cgu.c
@@ -7,7 +7,9 @@
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/of.h>
+
#include <dt-bindings/clock/x1000-cgu.h>
+
#include "cgu.h"
#include "pm.h"
@@ -58,6 +60,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_APLL,
+ .rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -68,6 +71,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_APLL,
.bypass_bit = 9,
.enable_bit = 8,
.stable_bit = 10,
@@ -79,6 +83,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
.pll = {
.reg = CGU_REG_MPLL,
+ .rate_multiplier = 1,
.m_shift = 24,
.m_bits = 7,
.m_offset = 1,
@@ -89,6 +94,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.od_bits = 2,
.od_max = 8,
.od_encoding = pll_od_encoding,
+ .bypass_reg = CGU_REG_MPLL,
.bypass_bit = 6,
.enable_bit = 7,
.stable_bit = 0,
--
2.11.0
^ permalink raw reply related
* [PATCH v9 1/6] clk: Ingenic: Remove unnecessary spinlock when reading registers.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-24 15:47 UTC (permalink / raw)
To: linux-clk
Cc: linux-kernel, devicetree, sboyd, mturquette, robh+dt,
dongsheng.qiu, aric.pzqi, sernia.zhou, zhenwenjin, paul
In-Reply-To: <20200524154729.30958-1-zhouyanjie@wanyeetech.com>
It is not necessary to use spinlock when reading registers,
so remove it from cgu.c.
Suggested-by: Paul Cercueil <paul@crapouillou.net>
Suggested-by: Paul Burton <paulburton@kernel.org>
Signed-off-by: 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
Reviewed-by: Paul Cercueil <paul@crapouillou.net>
---
Notes:
v2:
New patch.
v2->v3:
Adjust order from [5/5] in v2 to [1/5] in v3.
v3->v4:
Remove the spinlock around ingenic_cgu_gate_get().
v4->v5:
Rebase on top of kernel 5.6-rc1.
v5->v6:
No change.
v6->v7:
No change.
v7->v8:
No change.
v8->v9:
No change.
drivers/clk/ingenic/cgu.c | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 6e963031cd87..ab1302ad1450 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -76,16 +76,13 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
const struct ingenic_cgu_pll_info *pll_info;
unsigned m, n, od_enc, od;
bool bypass;
- unsigned long flags;
u32 ctl;
clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);
pll_info = &clk_info->pll;
- spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
- spin_unlock_irqrestore(&cgu->lock, flags);
m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0);
m += pll_info->m_offset;
@@ -259,12 +256,9 @@ static int ingenic_pll_is_enabled(struct clk_hw *hw)
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
- unsigned long flags;
u32 ctl;
- spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
- spin_unlock_irqrestore(&cgu->lock, flags);
return !!(ctl & BIT(pll_info->enable_bit));
}
@@ -562,16 +556,12 @@ static int ingenic_clk_is_enabled(struct clk_hw *hw)
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
- unsigned long flags;
int enabled = 1;
clk_info = &cgu->clock_info[ingenic_clk->idx];
- if (clk_info->type & CGU_CLK_GATE) {
- spin_lock_irqsave(&cgu->lock, flags);
+ if (clk_info->type & CGU_CLK_GATE)
enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
- spin_unlock_irqrestore(&cgu->lock, flags);
- }
return enabled;
}
--
2.11.0
^ permalink raw reply related
* Add support for the X1830 and fix bugs for X1000 v9.
From: 周琰杰 (Zhou Yanjie) @ 2020-05-24 15:47 UTC (permalink / raw)
To: linux-clk
Cc: linux-kernel, devicetree, sboyd, mturquette, robh+dt,
dongsheng.qiu, aric.pzqi, sernia.zhou, zhenwenjin, paul
v8->v9:
Add Paul Cercueil's Reviewed-by, somehow his emails are not displayed
on the mailing list and patchwork of clock framework subsystem.
^ permalink raw reply
* [PATCH v9 0/6] Add support for the X1830 and fix bugs for X1000
From: 周琰杰 (Zhou Yanjie) @ 2020-05-24 15:47 UTC (permalink / raw)
To: linux-clk
Cc: linux-kernel, devicetree, sboyd, mturquette, robh+dt,
dongsheng.qiu, aric.pzqi, sernia.zhou, zhenwenjin, paul
In-Reply-To: <20200524154729.30958-1-zhouyanjie@wanyeetech.com>
v8->v9:
Add Paul Cercueil's Reviewed-by, somehow his emails are not displayed
on the mailing list and patchwork of clock framework subsystem.
周琰杰 (Zhou Yanjie) (6):
clk: Ingenic: Remove unnecessary spinlock when reading registers.
clk: Ingenic: Adjust cgu code to make it compatible with X1830.
dt-bindings: clock: Add X1830 bindings.
clk: Ingenic: Add CGU driver for X1830.
dt-bindings: clock: Add and reorder ABI for X1000.
clk: X1000: Add FIXDIV for SSI clock of X1000.
.../devicetree/bindings/clock/ingenic,cgu.yaml | 2 +
drivers/clk/ingenic/Kconfig | 10 +
drivers/clk/ingenic/Makefile | 1 +
drivers/clk/ingenic/cgu.c | 28 +-
drivers/clk/ingenic/cgu.h | 4 +
drivers/clk/ingenic/jz4725b-cgu.c | 4 +
drivers/clk/ingenic/jz4740-cgu.c | 4 +
drivers/clk/ingenic/jz4770-cgu.c | 8 +-
drivers/clk/ingenic/jz4780-cgu.c | 3 +
drivers/clk/ingenic/x1000-cgu.c | 114 +++++-
drivers/clk/ingenic/x1830-cgu.c | 436 +++++++++++++++++++++
include/dt-bindings/clock/x1000-cgu.h | 64 +--
include/dt-bindings/clock/x1830-cgu.h | 54 +++
13 files changed, 684 insertions(+), 48 deletions(-)
create mode 100644 drivers/clk/ingenic/x1830-cgu.c
create mode 100644 include/dt-bindings/clock/x1830-cgu.h
--
2.11.0
^ permalink raw reply
* Re: [PATCH v5 5/5] counter: Add microchip TCB capture counter
From: William Breathitt Gray @ 2020-05-24 15:35 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Kamel Bouhara, Rob Herring, Mark Rutland, Nicolas Ferre,
Alexandre Belloni, Ludovic Desroches, linux-arm-kernel,
Thomas Petazzoni, linux-input, devicetree, linux-iio
In-Reply-To: <20200524161624.2c932a30@archlinux>
[-- Attachment #1: Type: text/plain, Size: 1396 bytes --]
On Sun, May 24, 2020 at 04:16:24PM +0100, Jonathan Cameron wrote:
> On Tue, 19 May 2020 10:37:16 +0200
> Kamel Bouhara <kamel.bouhara@bootlin.com> wrote:
>
> > This drivers allows to use the capture mode of the Timer Counter Block
> > hardware block available in Microchip SoCs through the counter subsystem.
> >
> > Two functions of the counter are supported for the moment: period
> > capture and quadrature decoder. The latter is only supported by the
> > SAMA5 series of SoCs.
> >
> > For the period capture mode a basic setup has been chosen that will
> > reset the counter each time the period is actually reached. Of course
> > the device offers much more possibilities.
> >
> > For quadrature mode, both channel 0 and 1 must be configured even if we
> > only capture the position (no revolution/rotation).
> >
> > Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
>
> Looks good to me. After reviews from William, DT and maybe
> something from SoC side if intent is I'm taking this.
>
> Jonathan
I'll defer to the DT maintainers for the dt-binding changes. Regarding
this counter driver, I believe there have been no changes since I
signed-off for it in the v3 patchset thread. If that's true, I haven't
changed my mind -- I'm still statisfied with this particular version and
have no objections if it's merged. ;-)
William Breathitt Gray
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH] dt/platform: Fix comment in of_dev_lookup()
From: Qi Zheng @ 2020-05-24 15:26 UTC (permalink / raw)
To: robh+dt, robh, frowand.list; +Cc: devicetree, linux-kernel, Qi Zheng
The code is using of_dev_lookup() rather than of_devname_lookup().
Signed-off-by: Qi Zheng <arch0.zheng@gmail.com>
---
drivers/of/platform.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 3371e4a06248..3627fee60215 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -291,7 +291,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
#endif /* CONFIG_ARM_AMBA */
/**
- * of_devname_lookup() - Given a device node, lookup the preferred Linux name
+ * of_dev_lookup() - Given a device node, lookup the preferred Linux name
*/
static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
struct device_node *np)
--
2.25.1
^ permalink raw reply related
* Re: [PATCH v5 5/5] counter: Add microchip TCB capture counter
From: Jonathan Cameron @ 2020-05-24 15:16 UTC (permalink / raw)
To: Kamel Bouhara
Cc: William Breathitt Gray, Rob Herring, Mark Rutland, Nicolas Ferre,
Alexandre Belloni, Ludovic Desroches, linux-arm-kernel,
Thomas Petazzoni, linux-input, devicetree, linux-iio
In-Reply-To: <20200519083716.938384-6-kamel.bouhara@bootlin.com>
On Tue, 19 May 2020 10:37:16 +0200
Kamel Bouhara <kamel.bouhara@bootlin.com> wrote:
> This drivers allows to use the capture mode of the Timer Counter Block
> hardware block available in Microchip SoCs through the counter subsystem.
>
> Two functions of the counter are supported for the moment: period
> capture and quadrature decoder. The latter is only supported by the
> SAMA5 series of SoCs.
>
> For the period capture mode a basic setup has been chosen that will
> reset the counter each time the period is actually reached. Of course
> the device offers much more possibilities.
>
> For quadrature mode, both channel 0 and 1 must be configured even if we
> only capture the position (no revolution/rotation).
>
> Signed-off-by: Kamel Bouhara <kamel.bouhara@bootlin.com>
Looks good to me. After reviews from William, DT and maybe
something from SoC side if intent is I'm taking this.
Jonathan
> ---
> drivers/counter/Kconfig | 11 +
> drivers/counter/Makefile | 1 +
> drivers/counter/microchip-tcb-capture.c | 397 ++++++++++++++++++++++++
> 3 files changed, 409 insertions(+)
> create mode 100644 drivers/counter/microchip-tcb-capture.c
>
> diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
> index c80fa76bb531..2de53ab0dd25 100644
> --- a/drivers/counter/Kconfig
> +++ b/drivers/counter/Kconfig
> @@ -70,4 +70,15 @@ config FTM_QUADDEC
> To compile this driver as a module, choose M here: the
> module will be called ftm-quaddec.
>
> +config MICROCHIP_TCB_CAPTURE
> + tristate "Microchip Timer Counter Capture driver"
> + depends on HAS_IOMEM && OF
> + select REGMAP_MMIO
> + help
> + Select this option to enable the Microchip Timer Counter Block
> + capture driver.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called microchip-tcb-capture.
> +
> endif # COUNTER
> diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
> index 55142d1f4c43..0a393f71e481 100644
> --- a/drivers/counter/Makefile
> +++ b/drivers/counter/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_STM32_TIMER_CNT) += stm32-timer-cnt.o
> obj-$(CONFIG_STM32_LPTIMER_CNT) += stm32-lptimer-cnt.o
> obj-$(CONFIG_TI_EQEP) += ti-eqep.o
> obj-$(CONFIG_FTM_QUADDEC) += ftm-quaddec.o
> +obj-$(CONFIG_MICROCHIP_TCB_CAPTURE) += microchip-tcb-capture.o
> diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
> new file mode 100644
> index 000000000000..f7b7743ddb94
> --- /dev/null
> +++ b/drivers/counter/microchip-tcb-capture.c
> @@ -0,0 +1,397 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/**
> + * Copyright (C) 2020 Microchip
> + *
> + * Author: Kamel Bouhara <kamel.bouhara@bootlin.com>
> + */
> +#include <linux/clk.h>
> +#include <linux/counter.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <soc/at91/atmel_tcb.h>
> +
> +#define ATMEL_TC_CMR_MASK (ATMEL_TC_LDRA_RISING | ATMEL_TC_LDRB_FALLING | \
> + ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_LDBDIS | \
> + ATMEL_TC_LDBSTOP)
> +
> +#define ATMEL_TC_QDEN BIT(8)
> +#define ATMEL_TC_POSEN BIT(9)
> +
> +struct mchp_tc_data {
> + const struct atmel_tcb_config *tc_cfg;
> + struct counter_device counter;
> + struct regmap *regmap;
> + int qdec_mode;
> + int num_channels;
> + int channel[2];
> + bool trig_inverted;
> +};
> +
> +enum mchp_tc_count_function {
> + MCHP_TC_FUNCTION_INCREASE,
> + MCHP_TC_FUNCTION_QUADRATURE,
> +};
> +
> +static enum counter_count_function mchp_tc_count_functions[] = {
> + [MCHP_TC_FUNCTION_INCREASE] = COUNTER_COUNT_FUNCTION_INCREASE,
> + [MCHP_TC_FUNCTION_QUADRATURE] = COUNTER_COUNT_FUNCTION_QUADRATURE_X4,
> +};
> +
> +enum mchp_tc_synapse_action {
> + MCHP_TC_SYNAPSE_ACTION_NONE = 0,
> + MCHP_TC_SYNAPSE_ACTION_RISING_EDGE,
> + MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE,
> + MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE
> +};
> +
> +static enum counter_synapse_action mchp_tc_synapse_actions[] = {
> + [MCHP_TC_SYNAPSE_ACTION_NONE] = COUNTER_SYNAPSE_ACTION_NONE,
> + [MCHP_TC_SYNAPSE_ACTION_RISING_EDGE] = COUNTER_SYNAPSE_ACTION_RISING_EDGE,
> + [MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE] = COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
> + [MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE] = COUNTER_SYNAPSE_ACTION_BOTH_EDGES,
> +};
> +
> +static struct counter_signal mchp_tc_count_signals[] = {
> + {
> + .id = 0,
> + .name = "Channel A",
> + },
> + {
> + .id = 1,
> + .name = "Channel B",
> + }
> +};
> +
> +static struct counter_synapse mchp_tc_count_synapses[] = {
> + {
> + .actions_list = mchp_tc_synapse_actions,
> + .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
> + .signal = &mchp_tc_count_signals[0]
> + },
> + {
> + .actions_list = mchp_tc_synapse_actions,
> + .num_actions = ARRAY_SIZE(mchp_tc_synapse_actions),
> + .signal = &mchp_tc_count_signals[1]
> + }
> +};
> +
> +static int mchp_tc_count_function_get(struct counter_device *counter,
> + struct counter_count *count,
> + size_t *function)
> +{
> + struct mchp_tc_data *const priv = counter->priv;
> +
> + if (priv->qdec_mode)
> + *function = MCHP_TC_FUNCTION_QUADRATURE;
> + else
> + *function = MCHP_TC_FUNCTION_INCREASE;
> +
> + return 0;
> +}
> +
> +static int mchp_tc_count_function_set(struct counter_device *counter,
> + struct counter_count *count,
> + size_t function)
> +{
> + struct mchp_tc_data *const priv = counter->priv;
> + u32 bmr, cmr;
> +
> + regmap_read(priv->regmap, ATMEL_TC_BMR, &bmr);
> + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
> +
> + /* Set capture mode */
> + cmr &= ~ATMEL_TC_WAVE;
> +
> + switch (function) {
> + case MCHP_TC_FUNCTION_INCREASE:
> + priv->qdec_mode = 0;
> + /* Set highest rate based on whether soc has gclk or not */
> + bmr &= ~(ATMEL_TC_QDEN | ATMEL_TC_POSEN);
> + if (priv->tc_cfg->has_gclk)
> + cmr |= ATMEL_TC_TIMER_CLOCK2;
> + else
> + cmr |= ATMEL_TC_TIMER_CLOCK1;
> + /* Setup the period capture mode */
> + cmr |= ATMEL_TC_CMR_MASK;
> + cmr &= ~(ATMEL_TC_ABETRG | ATMEL_TC_XC0);
> + break;
> + case MCHP_TC_FUNCTION_QUADRATURE:
> + if (!priv->tc_cfg->has_qdec)
> + return -EINVAL;
> + /* In QDEC mode settings both channels 0 and 1 are required */
> + if (priv->num_channels < 2 || priv->channel[0] != 0 ||
> + priv->channel[1] != 1) {
> + pr_err("Invalid channels number or id for quadrature mode\n");
> + return -EINVAL;
> + }
> + priv->qdec_mode = 1;
> + bmr |= ATMEL_TC_QDEN | ATMEL_TC_POSEN;
> + cmr |= ATMEL_TC_ETRGEDG_RISING | ATMEL_TC_ABETRG | ATMEL_TC_XC0;
> + break;
> + }
> +
> + regmap_write(priv->regmap, ATMEL_TC_BMR, bmr);
> + regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), cmr);
> +
> + /* Enable clock and trigger counter */
> + regmap_write(priv->regmap, ATMEL_TC_REG(priv->channel[0], CCR),
> + ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
> +
> + if (priv->qdec_mode) {
> + regmap_write(priv->regmap,
> + ATMEL_TC_REG(priv->channel[1], CMR), cmr);
> + regmap_write(priv->regmap,
> + ATMEL_TC_REG(priv->channel[1], CCR),
> + ATMEL_TC_CLKEN | ATMEL_TC_SWTRG);
> + }
> +
> + return 0;
> +}
> +
> +static int mchp_tc_count_signal_read(struct counter_device *counter,
> + struct counter_signal *signal,
> + enum counter_signal_value *val)
> +{
> + struct mchp_tc_data *const priv = counter->priv;
> + bool sigstatus;
> + u32 sr;
> +
> + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], SR), &sr);
> +
> + if (priv->trig_inverted)
> + sigstatus = (sr & ATMEL_TC_MTIOB);
> + else
> + sigstatus = (sr & ATMEL_TC_MTIOA);
> +
> + *val = sigstatus ? COUNTER_SIGNAL_HIGH : COUNTER_SIGNAL_LOW;
> +
> + return 0;
> +}
> +
> +static int mchp_tc_count_action_get(struct counter_device *counter,
> + struct counter_count *count,
> + struct counter_synapse *synapse,
> + size_t *action)
> +{
> + struct mchp_tc_data *const priv = counter->priv;
> + u32 cmr;
> +
> + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CMR), &cmr);
> +
> + *action = MCHP_TC_SYNAPSE_ACTION_NONE;
> +
> + if (cmr & ATMEL_TC_ETRGEDG_NONE)
> + *action = MCHP_TC_SYNAPSE_ACTION_NONE;
> + else if (cmr & ATMEL_TC_ETRGEDG_RISING)
> + *action = MCHP_TC_SYNAPSE_ACTION_RISING_EDGE;
> + else if (cmr & ATMEL_TC_ETRGEDG_FALLING)
> + *action = MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE;
> + else if (cmr & ATMEL_TC_ETRGEDG_BOTH)
> + *action = MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE;
> +
> + return 0;
> +}
> +
> +static int mchp_tc_count_action_set(struct counter_device *counter,
> + struct counter_count *count,
> + struct counter_synapse *synapse,
> + size_t action)
> +{
> + struct mchp_tc_data *const priv = counter->priv;
> + u32 edge = ATMEL_TC_ETRGEDG_NONE;
> +
> + /* QDEC mode is rising edge only */
> + if (priv->qdec_mode)
> + return -EINVAL;
> +
> + switch (action) {
> + case MCHP_TC_SYNAPSE_ACTION_NONE:
> + edge = ATMEL_TC_ETRGEDG_NONE;
> + break;
> + case MCHP_TC_SYNAPSE_ACTION_RISING_EDGE:
> + edge = ATMEL_TC_ETRGEDG_RISING;
> + break;
> + case MCHP_TC_SYNAPSE_ACTION_FALLING_EDGE:
> + edge = ATMEL_TC_ETRGEDG_FALLING;
> + break;
> + case MCHP_TC_SYNAPSE_ACTION_BOTH_EDGE:
> + edge = ATMEL_TC_ETRGEDG_BOTH;
> + break;
> + }
> +
> + return regmap_write_bits(priv->regmap,
> + ATMEL_TC_REG(priv->channel[0], CMR),
> + ATMEL_TC_ETRGEDG, edge);
> +}
> +
> +static int mchp_tc_count_read(struct counter_device *counter,
> + struct counter_count *count,
> + unsigned long *val)
> +{
> + struct mchp_tc_data *const priv = counter->priv;
> + u32 cnt;
> +
> + regmap_read(priv->regmap, ATMEL_TC_REG(priv->channel[0], CV), &cnt);
> + *val = cnt;
> +
> + return 0;
> +}
> +
> +static struct counter_count mchp_tc_counts[] = {
> + {
> + .id = 0,
> + .name = "Timer Counter",
> + .functions_list = mchp_tc_count_functions,
> + .num_functions = ARRAY_SIZE(mchp_tc_count_functions),
> + .synapses = mchp_tc_count_synapses,
> + .num_synapses = ARRAY_SIZE(mchp_tc_count_synapses),
> + },
> +};
> +
> +static struct counter_ops mchp_tc_ops = {
> + .signal_read = mchp_tc_count_signal_read,
> + .count_read = mchp_tc_count_read,
> + .function_get = mchp_tc_count_function_get,
> + .function_set = mchp_tc_count_function_set,
> + .action_get = mchp_tc_count_action_get,
> + .action_set = mchp_tc_count_action_set
> +};
> +
> +static const struct atmel_tcb_config tcb_rm9200_config = {
> + .counter_width = 16,
> +};
> +
> +static const struct atmel_tcb_config tcb_sam9x5_config = {
> + .counter_width = 32,
> +};
> +
> +static const struct atmel_tcb_config tcb_sama5d2_config = {
> + .counter_width = 32,
> + .has_gclk = true,
> + .has_qdec = true,
> +};
> +
> +static const struct atmel_tcb_config tcb_sama5d3_config = {
> + .counter_width = 32,
> + .has_qdec = true,
> +};
> +
> +static const struct of_device_id atmel_tc_of_match[] = {
> + { .compatible = "atmel,at91rm9200-tcb", .data = &tcb_rm9200_config, },
> + { .compatible = "atmel,at91sam9x5-tcb", .data = &tcb_sam9x5_config, },
> + { .compatible = "atmel,sama5d2-tcb", .data = &tcb_sama5d2_config, },
> + { .compatible = "atmel,sama5d3-tcb", .data = &tcb_sama5d3_config, },
> + { /* sentinel */ }
> +};
> +
> +static void mchp_tc_clk_remove(void *ptr)
> +{
> + clk_disable_unprepare((struct clk *)ptr);
> +}
> +
> +static int mchp_tc_probe(struct platform_device *pdev)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + const struct atmel_tcb_config *tcb_config;
> + const struct of_device_id *match;
> + struct mchp_tc_data *priv;
> + char clk_name[7];
> + struct regmap *regmap;
> + struct clk *clk[3];
> + int channel;
> + int ret, i;
> +
> + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + match = of_match_node(atmel_tc_of_match, np->parent);
> + tcb_config = match->data;
> + if (!tcb_config) {
> + dev_err(&pdev->dev, "No matching parent node found\n");
> + return -ENODEV;
> + }
> +
> + regmap = syscon_node_to_regmap(np->parent);
> + if (IS_ERR(priv->regmap))
> + return PTR_ERR(priv->regmap);
> +
> + /* max. channels number is 2 when in QDEC mode */
> + priv->num_channels = of_property_count_u32_elems(np, "reg");
> + if (priv->num_channels < 0) {
> + dev_err(&pdev->dev, "Invalid or missing channel\n");
> + return -EINVAL;
> + }
> +
> + /* Register channels and initialize clocks */
> + for (i = 0; i < priv->num_channels; i++) {
> + ret = of_property_read_u32_index(np, "reg", i, &channel);
> + if (ret < 0 || channel > 2)
> + return -ENODEV;
> +
> + priv->channel[i] = channel;
> +
> + snprintf(clk_name, sizeof(clk_name), "t%d_clk", channel);
> +
> + clk[i] = of_clk_get_by_name(np->parent, clk_name);
> + if (IS_ERR(clk[i])) {
> + /* Fallback to t0_clk */
> + clk[i] = of_clk_get_by_name(np->parent, "t0_clk");
> + if (IS_ERR(clk[i]))
> + return PTR_ERR(clk[i]);
> + }
> +
> + ret = clk_prepare_enable(clk[i]);
> + if (ret)
> + return ret;
> +
> + ret = devm_add_action_or_reset(&pdev->dev,
> + mchp_tc_clk_remove,
> + clk[i]);
> + if (ret)
> + return ret;
> +
> + dev_dbg(&pdev->dev,
> + "Initialized capture mode on channel %d\n",
> + channel);
> + }
> +
> + priv->tc_cfg = tcb_config;
> + priv->regmap = regmap;
> + priv->counter.name = dev_name(&pdev->dev);
> + priv->counter.parent = &pdev->dev;
> + priv->counter.ops = &mchp_tc_ops;
> + priv->counter.num_counts = ARRAY_SIZE(mchp_tc_counts);
> + priv->counter.counts = mchp_tc_counts;
> + priv->counter.num_signals = ARRAY_SIZE(mchp_tc_count_signals);
> + priv->counter.signals = mchp_tc_count_signals;
> + priv->counter.priv = priv;
> +
> + return devm_counter_register(&pdev->dev, &priv->counter);
> +}
> +
> +static const struct of_device_id mchp_tc_dt_ids[] = {
> + { .compatible = "microchip,tcb-capture", },
> + { /* sentinel */ },
> +};
> +MODULE_DEVICE_TABLE(of, mchp_tc_dt_ids);
> +
> +static struct platform_driver mchp_tc_driver = {
> + .probe = mchp_tc_probe,
> + .driver = {
> + .name = "microchip-tcb-capture",
> + .of_match_table = mchp_tc_dt_ids,
> + },
> +};
> +module_platform_driver(mchp_tc_driver);
> +
> +MODULE_AUTHOR("Kamel Bouhara <kamel.bouhara@bootlin.com>");
> +MODULE_DESCRIPTION("Microchip TCB Capture driver");
> +MODULE_LICENSE("GPL v2");
^ permalink raw reply
* Re: [PATCH v5 4/4] iio: magnetometer: ak8975: Add gpio reset support
From: Jonathan Cameron @ 2020-05-24 14:59 UTC (permalink / raw)
To: Jonathan Albrieux
Cc: linux-kernel, ~postmarketos/upstreaming, Andy Shevchenko,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Greg Kroah-Hartman, Hartmut Knaack, Jilayne Lovejoy,
Jonathan Cameron, Kate Stewart, Lars-Peter Clausen, Linus Walleij,
open list:IIO SUBSYSTEM AND DRIVERS, Peter Meerwald-Stadler,
Steve Winslow, Thomas Gleixner
In-Reply-To: <20200520163417.27805-5-jonathan.albrieux@gmail.com>
On Wed, 20 May 2020 18:34:09 +0200
Jonathan Albrieux <jonathan.albrieux@gmail.com> wrote:
> According to AK09911 datasheet, if reset gpio is provided then
> deassert reset on ak8975_power_on() and assert reset on ak8975_power_off().
>
> Without reset's deassertion during ak8975_power_on(), driver's probe fails
> on ak8975_who_i_am() while checking for device identity for AK09911 chip.
>
> AK09911 has an active low reset gpio to handle register's reset.
> AK09911 datasheet says that, if not used, reset pin should be connected
> to VID. This patch emulates this situation.
>
> Signed-off-by: Jonathan Albrieux <jonathan.albrieux@gmail.com>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> Reviewed-by: Stephan Gerhold <stephan@gerhold.net>
Looks good to me. Just the minor stuff with the binding plus
giving time for a binding review to go.
Thanks,
Jonathan
> ---
> drivers/iio/magnetometer/ak8975.c | 18 ++++++++++++++++++
> 1 file changed, 18 insertions(+)
>
> diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
> index fd368455cd7b..a23422aad97d 100644
> --- a/drivers/iio/magnetometer/ak8975.c
> +++ b/drivers/iio/magnetometer/ak8975.c
> @@ -358,6 +358,7 @@ struct ak8975_data {
> u8 asa[3];
> long raw_to_gauss[3];
> struct gpio_desc *eoc_gpiod;
> + struct gpio_desc *reset_gpiod;
> int eoc_irq;
> wait_queue_head_t data_ready_queue;
> unsigned long flags;
> @@ -384,6 +385,9 @@ static int ak8975_power_on(const struct ak8975_data *data)
> "Failed to enable specified Vid supply\n");
> return ret;
> }
> +
> + gpiod_set_value_cansleep(data->reset_gpiod, 0);
> +
> /*
> * According to the datasheet the power supply rise time is 200us
> * and the minimum wait time before mode setting is 100us, in
> @@ -396,6 +400,8 @@ static int ak8975_power_on(const struct ak8975_data *data)
> /* Disable attached power regulator if any. */
> static void ak8975_power_off(const struct ak8975_data *data)
> {
> + gpiod_set_value_cansleep(data->reset_gpiod, 1);
> +
> regulator_disable(data->vid);
> regulator_disable(data->vdd);
> }
> @@ -839,6 +845,7 @@ static int ak8975_probe(struct i2c_client *client,
> struct ak8975_data *data;
> struct iio_dev *indio_dev;
> struct gpio_desc *eoc_gpiod;
> + struct gpio_desc *reset_gpiod;
> const void *match;
> unsigned int i;
> int err;
> @@ -856,6 +863,16 @@ static int ak8975_probe(struct i2c_client *client,
> if (eoc_gpiod)
> gpiod_set_consumer_name(eoc_gpiod, "ak_8975");
>
> + /*
> + * According to AK09911 datasheet, if reset GPIO is provided then
> + * deassert reset on ak8975_power_on() and assert reset on
> + * ak8975_power_off().
> + */
> + reset_gpiod = devm_gpiod_get_optional(&client->dev,
> + "reset", GPIOD_OUT_HIGH);
> + if (IS_ERR(reset_gpiod))
> + return PTR_ERR(reset_gpiod);
> +
> /* Register with IIO */
> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> if (indio_dev == NULL)
> @@ -866,6 +883,7 @@ static int ak8975_probe(struct i2c_client *client,
>
> data->client = client;
> data->eoc_gpiod = eoc_gpiod;
> + data->reset_gpiod = reset_gpiod;
> data->eoc_irq = 0;
>
> err = iio_read_mount_matrix(&client->dev, "mount-matrix", &data->orientation);
^ permalink raw reply
* Re: [PATCH v5 1/4] dt-bindings: iio: magnetometer: ak8975: convert format to yaml, add maintainer
From: Jonathan Cameron @ 2020-05-24 14:57 UTC (permalink / raw)
To: Jonathan Albrieux
Cc: linux-kernel, ~postmarketos/upstreaming, Andy Shevchenko,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Greg Kroah-Hartman, Hartmut Knaack, Jilayne Lovejoy,
Jonathan Cameron, Kate Stewart, Lars-Peter Clausen, Linus Walleij,
open list:IIO SUBSYSTEM AND DRIVERS, Peter Meerwald-Stadler,
Steve Winslow, Thomas Gleixner, Rob Herring
In-Reply-To: <20200520163417.27805-2-jonathan.albrieux@gmail.com>
On Wed, 20 May 2020 18:34:06 +0200
Jonathan Albrieux <jonathan.albrieux@gmail.com> wrote:
> Converts documentation from txt format to yaml.
>
> Signed-off-by: Jonathan Albrieux <jonathan.albrieux@gmail.com>
An additional request inline. Doesn't effect this patch 'as such'.
Also the file name thing just below here.
> ---
> .../bindings/iio/magnetometer/ak8975.txt | 30 --------
> .../bindings/iio/magnetometer/ak8975.yaml | 71 +++++++++++++++++++
File naming should match the compatible.
ashahi-kasei,ak8975.yaml
> 2 files changed, 71 insertions(+), 30 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt
> create mode 100644 Documentation/devicetree/bindings/iio/magnetometer/ak8975.yaml
>
> diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt
> deleted file mode 100644
> index aa67ceb0d4e0..000000000000
> --- a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.txt
> +++ /dev/null
> @@ -1,30 +0,0 @@
> -* AsahiKASEI AK8975 magnetometer sensor
> -
> -Required properties:
> -
> - - compatible : should be "asahi-kasei,ak8975"
> - - reg : the I2C address of the magnetometer
> -
> -Optional properties:
> -
> - - gpios : should be device tree identifier of the magnetometer DRDY pin
> - - vdd-supply: an optional regulator that needs to be on to provide VDD
> - - mount-matrix: an optional 3x3 mounting rotation matrix
> -
> -Example:
> -
> -ak8975@c {
> - compatible = "asahi-kasei,ak8975";
> - reg = <0x0c>;
> - gpios = <&gpj0 7 0>;
> - vdd-supply = <&ldo_3v3_gnss>;
> - mount-matrix = "-0.984807753012208", /* x0 */
> - "0", /* y0 */
> - "-0.173648177666930", /* z0 */
> - "0", /* x1 */
> - "-1", /* y1 */
> - "0", /* z1 */
> - "-0.173648177666930", /* x2 */
> - "0", /* y2 */
> - "0.984807753012208"; /* z2 */
> -};
> diff --git a/Documentation/devicetree/bindings/iio/magnetometer/ak8975.yaml b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.yaml
> new file mode 100644
> index 000000000000..8bde423a2ffa
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/magnetometer/ak8975.yaml
> @@ -0,0 +1,71 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/iio/magnetometer/ak8975.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: AsahiKASEI AK8975 magnetometer sensor
> +
> +maintainers:
> + - Jonathan Albrieux <jonathan.albrieux@gmail.com>
> +
> +properties:
> + compatible:
> + oneOf:
> + - const: asahi-kasei,ak8975
> + - const: asahi-kasei,ak8963
> + - const: asahi-kasei,ak09911
> + - const: asahi-kasei,ak09912
> + - const: ak8975
> + deprecated: true
> + - const: ak8963
> + deprecated: true
> + - const: ak09911
> + deprecated: true
> + - const: ak09912
> + deprecated: true
> +
> + reg:
> + maxItems: 1
> + description: the I2C address of the magnetometer
> +
> + gpios:
> + description: should be device tree identifier of the magnetometer DRDY pin
Nothing to do with your patch obviously but this is horrible...
+ the driver will quite happily take an interrupt instead.
Do you mind documenting the interrupt here as well?
Should be a separate patch though. So a follow up one to
this one. The
arch/arm/boot/dts/motorola-mapphone-common.dtsi
does it that way, unlike the samsung s3 which uses the gpio
binding (I think it's the only one against quite a few
using interrupts).
Also switch the example to an interrupts one so we don't
encourage anyone to go the gpios route.
Note can be a follow up if this series is otherwise ready to go.
> +
> + vdd-supply:
> + maxItems: 1
> + description: |
> + an optional regulator that needs to be on to provide VDD power to
> + the sensor.
> +
> + mount-matrix:
> + description: an optional 3x3 mounting rotation matrix
> +
> +required:
> + - compatible
> + - reg
> +
> +examples:
> + - |
> + #include <dt-bindings/gpio/gpio.h>
> + i2c@78b7000 {
> + reg = <0x78b6000 0x600>;
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + magnetometer@c {
> + compatible = "asahi-kasei,ak8975";
> + reg = <0x0c>;
> + gpios = <&gpj0 7 GPIO_ACTIVE_HIGH>;
> + vdd-supply = <&ldo_3v3_gnss>;
> + mount-matrix = "-0.984807753012208", /* x0 */
> + "0", /* y0 */
> + "-0.173648177666930", /* z0 */
> + "0", /* x1 */
> + "-1", /* y1 */
> + "0", /* z1 */
> + "-0.173648177666930", /* x2 */
> + "0", /* y2 */
> + "0.984807753012208"; /* z2 */
> + };
> + };
^ permalink raw reply
* Re: [PATCH v13 2/3] i2c: npcm7xx: Add Nuvoton NPCM I2C controller driver
From: kbuild test robot @ 2020-05-24 12:20 UTC (permalink / raw)
To: Tali Perry, ofery, brendanhiggins, avifishman70, tmaimon77,
kfting, venture, yuenn, benjaminfair, robh+dt, wsa,
andriy.shevchenko
Cc: kbuild-all, clang-built-linux, devicetree, openbmc, linux-kernel,
Tali Perry, linux-i2c, linux-arm-kernel
In-Reply-To: <20200522113312.181413-3-tali.perry1@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 4933 bytes --]
Hi Tali,
I love your patch! Yet something to improve:
[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v5.7-rc6 next-20200522]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]
url: https://github.com/0day-ci/linux/commits/Tali-Perry/i2c-npcm7xx-add-NPCM-i2c-controller-driver/20200522-193916
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
config: x86_64-allmodconfig (attached as .config)
compiler: clang version 11.0.0 (https://github.com/llvm/llvm-project 3393cc4cebf9969db94dc424b7a2b6195589c33b)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install x86_64 cross compiling tool for clang build
# apt-get install binutils-x86-64-linux-gnu
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64
If you fix the issue, kindly add following tag as appropriate
Reported-by: kbuild test robot <lkp@intel.com>
All errors (new ones prefixed by >>, old ones prefixed by <<):
>> drivers/i2c/busses/i2c-npcm7xx.c:1797:1: error: redefinition of '__inittest'
module_init(npcm_i2c_init);
^
include/linux/module.h:131:42: note: expanded from macro 'module_init'
static inline initcall_t __maybe_unused __inittest(void) ^
drivers/i2c/busses/i2c-npcm7xx.c:1778:1: note: previous definition is here
module_platform_driver(npcm_i2c_bus_driver);
^
include/linux/platform_device.h:247:2: note: expanded from macro 'module_platform_driver'
module_driver(__platform_driver, platform_driver_register, ^
include/linux/device/driver.h:262:3: note: expanded from macro 'module_driver'
} ^
include/linux/module.h:131:42: note: expanded from macro ' module_init'
static inline initcall_t __maybe_unused __inittest(void) ^
>> drivers/i2c/busses/i2c-npcm7xx.c:1797:1: error: redefinition of 'init_module'
module_init(npcm_i2c_init);
^
include/linux/module.h:133:6: note: expanded from macro 'module_init'
int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
^
drivers/i2c/busses/i2c-npcm7xx.c:1778:1: note: previous definition is here
module_platform_driver(npcm_i2c_bus_driver);
^
include/linux/platform_device.h:247:2: note: expanded from macro 'module_platform_driver'
module_driver(__platform_driver, platform_driver_register, ^
include/linux/device/driver.h:262:3: note: expanded from macro 'module_driver'
} ^
include/linux/module.h:133:6: note: expanded from macro ' module_init'
int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
^
>> drivers/i2c/busses/i2c-npcm7xx.c:1798:1: error: redefinition of '__exittest'
module_exit(npcm_i2c_exit);
^
include/linux/module.h:137:42: note: expanded from macro 'module_exit'
static inline exitcall_t __maybe_unused __exittest(void) ^
drivers/i2c/busses/i2c-npcm7xx.c:1778:1: note: previous definition is here
module_platform_driver(npcm_i2c_bus_driver);
^
include/linux/platform_device.h:247:2: note: expanded from macro 'module_platform_driver'
module_driver(__platform_driver, platform_driver_register, ^
include/linux/device/driver.h:267:3: note: expanded from macro 'module_driver'
} ^
include/linux/module.h:137:42: note: expanded from macro ' module_exit'
static inline exitcall_t __maybe_unused __exittest(void) ^
>> drivers/i2c/busses/i2c-npcm7xx.c:1798:1: error: redefinition of 'cleanup_module'
module_exit(npcm_i2c_exit);
^
include/linux/module.h:139:7: note: expanded from macro 'module_exit'
void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
^
drivers/i2c/busses/i2c-npcm7xx.c:1778:1: note: previous definition is here
module_platform_driver(npcm_i2c_bus_driver);
^
include/linux/platform_device.h:247:2: note: expanded from macro 'module_platform_driver'
module_driver(__platform_driver, platform_driver_register, ^
include/linux/device/driver.h:267:3: note: expanded from macro 'module_driver'
} ^
include/linux/module.h:139:7: note: expanded from macro ' module_exit'
void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
^
4 errors generated.
vim +/__inittest +1797 drivers/i2c/busses/i2c-npcm7xx.c
1796
> 1797 module_init(npcm_i2c_init);
> 1798 module_exit(npcm_i2c_exit);
1799
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 74080 bytes --]
^ permalink raw reply
* Re: [PATCH V5 5/5] iio: adc: Clean up ADC code common to PMIC5 and PMIC7
From: Jonathan Cameron @ 2020-05-24 12:04 UTC (permalink / raw)
To: Jishnu Prakash
Cc: agross, bjorn.andersson, devicetree, linux-kernel, mka,
linus.walleij, Jonathan.Cameron, andy.shevchenko, amit.kucheria,
smohanad, kgunda, aghayal, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, linux-arm-msm, linux-iio,
linux-arm-msm-owner
In-Reply-To: <1590157452-27179-6-git-send-email-jprakash@codeaurora.org>
On Fri, 22 May 2020 19:54:12 +0530
Jishnu Prakash <jprakash@codeaurora.org> wrote:
> This commit includes the following changes:
>
> Add a common function used for read_raw callback for both PMIC5
> and PMIC7 ADCs.
>
> Add exit function for ADC.
Hi Jishnu,
I don't understand why one is needed, and if it is you can't do
what you have here without introducing some nasty races.
So if you need it clearly explain why in comments in the code
and also consider how it may race with new requests coming in etc
as the userspace interfaces are still visible.
Move the eoc_irq addition to the structure here as well as makes
no sense in earlier patch.
Thanks,
Jonathan
>
> Add info_property under adc_data to more efficiently distinguish
> PMIC5 and PMIC7 ADCs.
>
> Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
> ---
> drivers/iio/adc/qcom-spmi-adc5.c | 81 +++++++++++++++++++++-----------------
> drivers/iio/adc/qcom-vadc-common.h | 1 +
> 2 files changed, 46 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
> index 11eb97c..0208da3 100644
> --- a/drivers/iio/adc/qcom-spmi-adc5.c
> +++ b/drivers/iio/adc/qcom-spmi-adc5.c
> @@ -167,8 +167,6 @@ static const struct vadc_prescale_ratio adc5_prescale_ratios[] = {
> {.num = 1, .den = 16}
> };
>
> -static const struct adc5_data adc7_data_pmic;
> -
> static int adc5_read(struct adc5_chip *adc, u16 offset, u8 *data, int len)
> {
> return regmap_bulk_read(adc->regmap, adc->base + offset, data, len);
> @@ -452,6 +450,13 @@ static int adc7_do_conversion(struct adc5_chip *adc,
> return ret;
> }
>
> +struct adc_do_conversion {
> + int (*adc_do_conversion)(struct adc5_chip *adc,
> + struct adc5_channel_prop *prop,
> + struct iio_chan_spec const *chan,
> + u16 *data_volt, u16 *data_cur);
> +};
> +
> static irqreturn_t adc5_isr(int irq, void *dev_id)
> {
> struct adc5_chip *adc = dev_id;
> @@ -490,9 +495,9 @@ static int adc7_of_xlate(struct iio_dev *indio_dev,
> return -EINVAL;
> }
>
> -static int adc5_read_raw(struct iio_dev *indio_dev,
> +static int adc_read_raw_common(struct iio_dev *indio_dev,
> struct iio_chan_spec const *chan, int *val, int *val2,
> - long mask)
> + long mask, struct adc_do_conversion do_conv)
> {
> struct adc5_chip *adc = iio_priv(indio_dev);
> struct adc5_channel_prop *prop;
> @@ -503,8 +508,8 @@ static int adc5_read_raw(struct iio_dev *indio_dev,
>
> switch (mask) {
> case IIO_CHAN_INFO_PROCESSED:
> - ret = adc5_do_conversion(adc, prop, chan,
> - &adc_code_volt, &adc_code_cur);
> + ret = do_conv.adc_do_conversion(adc, prop, chan,
> + &adc_code_volt, &adc_code_cur);
> if (ret)
> return ret;
>
> @@ -521,36 +526,26 @@ static int adc5_read_raw(struct iio_dev *indio_dev,
> }
> }
>
> -static int adc7_read_raw(struct iio_dev *indio_dev,
> +static int adc5_read_raw(struct iio_dev *indio_dev,
> struct iio_chan_spec const *chan, int *val, int *val2,
> long mask)
> {
> - struct adc5_chip *adc = iio_priv(indio_dev);
> - struct adc5_channel_prop *prop;
> - u16 adc_code_volt, adc_code_cur;
> - int ret;
> -
> - prop = &adc->chan_props[chan->address];
> + struct adc_do_conversion do_conv;
>
> - switch (mask) {
> - case IIO_CHAN_INFO_PROCESSED:
> - ret = adc7_do_conversion(adc, prop, chan,
> - &adc_code_volt, &adc_code_cur);
> - if (ret)
> - return ret;
> -
> - ret = qcom_adc5_hw_scale(prop->scale_fn_type,
> - &adc5_prescale_ratios[prop->prescale],
> - adc->data,
> - adc_code_volt, val);
> + do_conv.adc_do_conversion = adc5_do_conversion;
> + return adc_read_raw_common(indio_dev, chan, val, val2,
> + mask, do_conv);
> +}
>
> - if (ret)
> - return ret;
> +static int adc7_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan, int *val, int *val2,
> + long mask)
> +{
> + struct adc_do_conversion do_conv;
>
> - return IIO_VAL_INT;
> - default:
> - return -EINVAL;
> - }
> + do_conv.adc_do_conversion = adc7_do_conversion;
> + return adc_read_raw_common(indio_dev, chan, val, val2,
> + mask, do_conv);
> }
>
> static const struct iio_info adc5_info = {
> @@ -706,7 +701,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
>
> /* virtual channel number = sid << 8 | channel number */
>
> - if (adc->data == &adc7_data_pmic) {
> + if (adc->data->info == &adc7_info) {
> sid = chan >> ADC_CHANNEL_OFFSET;
> chan = chan & ADC_CHANNEL_MASK;
> }
> @@ -772,7 +767,7 @@ static int adc5_get_dt_channel_data(struct adc5_chip *adc,
> /* Digital controller >= 5.3 have hw_settle_2 option */
> if ((dig_version[0] >= ADC5_HW_SETTLE_DIFF_MINOR &&
> dig_version[1] >= ADC5_HW_SETTLE_DIFF_MAJOR) ||
> - adc->data == &adc7_data_pmic)
> + adc->data->info == &adc7_info)
> ret = adc5_hw_settle_time_from_dt(value,
> data->hw_settle_2);
> else
> @@ -822,6 +817,7 @@ static const struct adc5_data adc5_data_pmic = {
> .full_scale_code_volt = 0x70e4,
> .full_scale_code_cur = 0x2710,
> .adc_chans = adc5_chans_pmic,
> + .info = &adc5_info,
> .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
> {250, 420, 840},
> .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
> @@ -835,6 +831,7 @@ static const struct adc5_data adc5_data_pmic = {
> static const struct adc5_data adc7_data_pmic = {
> .full_scale_code_volt = 0x70e4,
> .adc_chans = adc7_chans_pmic,
> + .info = &adc7_info,
> .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
> {85, 340, 1360},
> .hw_settle_2 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
> @@ -847,6 +844,7 @@ static const struct adc5_data adc5_data_pmic_rev2 = {
> .full_scale_code_volt = 0x4000,
> .full_scale_code_cur = 0x1800,
> .adc_chans = adc5_chans_rev2,
> + .info = &adc5_info,
> .decimation = (unsigned int [ADC5_DECIMATION_SAMPLES_MAX])
> {256, 512, 1024},
> .hw_settle_1 = (unsigned int [VADC_HW_SETTLE_SAMPLES_MAX])
> @@ -961,10 +959,7 @@ static int adc5_probe(struct platform_device *pdev)
> adc->dev = dev;
> adc->base = reg;
>
> - if (of_device_is_compatible(node, "qcom,spmi-adc7"))
> - indio_dev->info = &adc7_info;
> - else
> - indio_dev->info = &adc5_info;
> + platform_set_drvdata(pdev, adc);
>
> init_completion(&adc->complete);
> mutex_init(&adc->lock);
> @@ -975,6 +970,8 @@ static int adc5_probe(struct platform_device *pdev)
> return ret;
> }
>
> + indio_dev->info = adc->data->info;
> +
> irq_eoc = platform_get_irq(pdev, 0);
> if (irq_eoc < 0) {
> if (irq_eoc == -EPROBE_DEFER || irq_eoc == -EINVAL)
> @@ -987,6 +984,8 @@ static int adc5_probe(struct platform_device *pdev)
> return ret;
> }
>
> + adc->irq_eoc = irq_eoc;
> +
> indio_dev->dev.parent = dev;
> indio_dev->dev.of_node = node;
> indio_dev->name = pdev->name;
> @@ -997,12 +996,22 @@ static int adc5_probe(struct platform_device *pdev)
> return devm_iio_device_register(dev, indio_dev);
> }
>
> +static int adc5_exit(struct platform_device *pdev)
> +{
> + struct adc5_chip *adc = platform_get_drvdata(pdev);
> +
> + if (adc->irq_eoc >= 0)
> + disable_irq(adc->irq_eoc);
So here you are disabling an irq? Why. We should be removing it
cleanly in the managed flow shortly anyway. If you did do this
here for some reason I'm not thinking of then you would have
a race against the userspace being removed on the unwind
of the iio device register.
> + return 0;
> +}
> +
> static struct platform_driver adc5_driver = {
> .driver = {
> .name = "qcom-spmi-adc5.c",
> .of_match_table = adc5_match_table,
> },
> .probe = adc5_probe,
> + .remove = adc5_exit,
> };
> module_platform_driver(adc5_driver);
>
> diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h
> index f10250b..17b2fc4 100644
> --- a/drivers/iio/adc/qcom-vadc-common.h
> +++ b/drivers/iio/adc/qcom-vadc-common.h
> @@ -150,6 +150,7 @@ struct adc5_data {
> const u32 full_scale_code_volt;
> const u32 full_scale_code_cur;
> const struct adc5_channels *adc_chans;
> + const struct iio_info *info;
> unsigned int *decimation;
> unsigned int *hw_settle_1;
> unsigned int *hw_settle_2;
^ permalink raw reply
* Re: [PATCH V5 3/5] iio: adc: Add support for PMIC7 ADC
From: Jonathan Cameron @ 2020-05-24 11:59 UTC (permalink / raw)
To: Jishnu Prakash
Cc: agross, bjorn.andersson, devicetree, linux-kernel, mka,
linus.walleij, Jonathan.Cameron, andy.shevchenko, amit.kucheria,
smohanad, kgunda, aghayal, Hartmut Knaack, Lars-Peter Clausen,
Peter Meerwald-Stadler, linux-arm-msm, linux-iio,
linux-arm-msm-owner
In-Reply-To: <1590157452-27179-4-git-send-email-jprakash@codeaurora.org>
On Fri, 22 May 2020 19:54:10 +0530
Jishnu Prakash <jprakash@codeaurora.org> wrote:
> The ADC architecture on PMIC7 is changed as compared to PMIC5. The
> major change from PMIC5 is that all SW communication to ADC goes through
> PMK8350, which communicates with other PMICs through PBS when the ADC
> on PMK8350 works in master mode. The SID register is used to identify the
> PMICs with which the PBS needs to communicate. Add support for the same.
>
> Signed-off-by: Jishnu Prakash <jprakash@codeaurora.org>
> ---
> drivers/iio/adc/qcom-spmi-adc5.c | 231 ++++++++++++++++++++++++++++++--
> drivers/iio/adc/qcom-vadc-common.c | 260 +++++++++++++++++++++++++++++++++++++
> drivers/iio/adc/qcom-vadc-common.h | 14 ++
> 3 files changed, 496 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
> index 21fdcde..e1482fd 100644
> --- a/drivers/iio/adc/qcom-spmi-adc5.c
> +++ b/drivers/iio/adc/qcom-spmi-adc5.c
> @@ -1,6 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
> /*
> - * Copyright (c) 2018, The Linux Foundation. All rights reserved.
> + * Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
...
> @@ -110,6 +120,7 @@ struct adc5_channel_prop {
> enum adc5_cal_method cal_method;
> enum adc5_cal_val cal_val;
> unsigned int decimation;
> + unsigned int sid;
> unsigned int prescale;
> unsigned int hw_settle_time;
> unsigned int avg_samples;
> @@ -140,6 +151,7 @@ struct adc5_chip {
> bool poll_eoc;
> struct completion complete;
> struct mutex lock;
> + int irq_eoc;
This is introduced but doesn't seem to be used...
> const struct adc5_data *data;
> };
>
> @@ -155,6 +167,8 @@ static const struct vadc_prescale_ratio adc5_prescale_ratios[] = {
> {.num = 1, .den = 16}
> };
>
...
> static int adc5_prescaling_from_dt(u32 num, u32 den)
> {
> unsigned int pre;
> @@ -285,7 +304,7 @@ static int adc5_configure(struct adc5_chip *adc,
>
> /* Read registers 0x42 through 0x46 */
> ret = adc5_read(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
> - if (ret < 0)
> + if (ret)
> return ret;
As Andy mentioned, this is better in a separate patch. It's just adding
noise to this patch which is actually doing things...
>
> /* Digital param selection */
> @@ -314,6 +333,47 @@ static int adc5_configure(struct adc5_chip *adc,
> return adc5_write(adc, ADC5_USR_DIG_PARAM, buf, sizeof(buf));
> }
>
Thanks,
Jonathan
^ permalink raw reply
* Re: [PATCH v3 5/5] iio: imu: bmi160: added mount-matrix support
From: Jonathan Cameron @ 2020-05-24 11:43 UTC (permalink / raw)
To: Jonathan Albrieux
Cc: linux-kernel, ~postmarketos/upstreaming, daniel.baluta,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Hartmut Knaack, Lars-Peter Clausen,
open list:IIO SUBSYSTEM AND DRIVERS, Peter Meerwald-Stadler
In-Reply-To: <20200520194656.16218-6-jonathan.albrieux@gmail.com>
On Wed, 20 May 2020 21:46:44 +0200
Jonathan Albrieux <jonathan.albrieux@gmail.com> wrote:
> Add mount-matrix binding support. As chip could have different orientations
> a mount matrix support is needed to correctly translate these differences.
>
> Signed-off-by: Jonathan Albrieux <jonathan.albrieux@gmail.com>
Other than those bits for the binding doc, the rest of the series
looks good to me. Given timing this will only go into mainline in the
next cycle now anyway so we have plenty of time to tidy up the corners.
Thanks,
Jonathan
> ---
> drivers/iio/imu/bmi160/bmi160.h | 1 +
> drivers/iio/imu/bmi160/bmi160_core.c | 20 ++++++++++++++++++++
> 2 files changed, 21 insertions(+)
>
> diff --git a/drivers/iio/imu/bmi160/bmi160.h b/drivers/iio/imu/bmi160/bmi160.h
> index 923c3b274fde..a82e040bd109 100644
> --- a/drivers/iio/imu/bmi160/bmi160.h
> +++ b/drivers/iio/imu/bmi160/bmi160.h
> @@ -9,6 +9,7 @@ struct bmi160_data {
> struct regmap *regmap;
> struct iio_trigger *trig;
> struct regulator_bulk_data supplies[2];
> + struct iio_mount_matrix orientation;
> };
>
> extern const struct regmap_config bmi160_regmap_config;
> diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
> index d3316ca02fbd..26d586daee26 100644
> --- a/drivers/iio/imu/bmi160/bmi160_core.c
> +++ b/drivers/iio/imu/bmi160/bmi160_core.c
> @@ -110,6 +110,7 @@
> .storagebits = 16, \
> .endianness = IIO_LE, \
> }, \
> + .ext_info = bmi160_ext_info, \
> }
>
> /* scan indexes follow DATA register order */
> @@ -265,6 +266,20 @@ static const struct bmi160_odr_item bmi160_odr_table[] = {
> },
> };
>
> +static const struct iio_mount_matrix *
> +bmi160_get_mount_matrix(const struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan)
> +{
> + struct bmi160_data *data = iio_priv(indio_dev);
> +
> + return &data->orientation;
> +}
> +
> +static const struct iio_chan_spec_ext_info bmi160_ext_info[] = {
> + IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bmi160_get_mount_matrix),
> + { }
> +};
> +
> static const struct iio_chan_spec bmi160_channels[] = {
> BMI160_CHANNEL(IIO_ACCEL, X, BMI160_SCAN_ACCEL_X),
> BMI160_CHANNEL(IIO_ACCEL, Y, BMI160_SCAN_ACCEL_Y),
> @@ -839,6 +854,11 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
> return ret;
> }
>
> + ret = iio_read_mount_matrix(dev, "mount-matrix",
> + &data->orientation);
> + if (ret)
> + return ret;
> +
> ret = bmi160_chip_init(data, use_spi);
> if (ret)
> return ret;
^ permalink raw reply
* Re: [PATCH v3 1/5] dt-bindings: iio: imu: bmi160: convert txt format to yaml
From: Jonathan Cameron @ 2020-05-24 11:41 UTC (permalink / raw)
To: Jonathan Albrieux
Cc: linux-kernel, ~postmarketos/upstreaming, daniel.baluta,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Hartmut Knaack, Lars-Peter Clausen,
open list:IIO SUBSYSTEM AND DRIVERS, Peter Meerwald-Stadler,
Rob Herring
In-Reply-To: <20200520194656.16218-2-jonathan.albrieux@gmail.com>
On Wed, 20 May 2020 21:46:40 +0200
Jonathan Albrieux <jonathan.albrieux@gmail.com> wrote:
> Converts documentation from txt format to yaml.
>
> Signed-off-by: Jonathan Albrieux <jonathan.albrieux@gmail.com>
A reminder on the maintainer bit as that thread crossed with
this one. Also, drop the spi-max-frequency as we don't need
to mention it explicitly for this device.
Thanks,
Jonathan
> ---
> .../devicetree/bindings/iio/imu/bmi160.txt | 37 ---------
> .../bindings/iio/imu/bosch,bmi160.yaml | 76 +++++++++++++++++++
> 2 files changed, 76 insertions(+), 37 deletions(-)
> delete mode 100644 Documentation/devicetree/bindings/iio/imu/bmi160.txt
> create mode 100644 Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml
>
> diff --git a/Documentation/devicetree/bindings/iio/imu/bmi160.txt b/Documentation/devicetree/bindings/iio/imu/bmi160.txt
> deleted file mode 100644
> index 900c169de00f..000000000000
> --- a/Documentation/devicetree/bindings/iio/imu/bmi160.txt
> +++ /dev/null
> @@ -1,37 +0,0 @@
> -Bosch BMI160 - Inertial Measurement Unit with Accelerometer, Gyroscope
> -and externally connectable Magnetometer
> -
> -https://www.bosch-sensortec.com/bst/products/all_products/bmi160
> -
> -Required properties:
> - - compatible : should be "bosch,bmi160"
> - - reg : the I2C address or SPI chip select number of the sensor
> - - spi-max-frequency : set maximum clock frequency (only for SPI)
> -
> -Optional properties:
> - - interrupts : interrupt mapping for IRQ
> - - interrupt-names : set to "INT1" if INT1 pin should be used as interrupt
> - input, set to "INT2" if INT2 pin should be used instead
> - - drive-open-drain : set if the specified interrupt pin should be configured as
> - open drain. If not set, defaults to push-pull.
> -
> -Examples:
> -
> -bmi160@68 {
> - compatible = "bosch,bmi160";
> - reg = <0x68>;
> -
> - interrupt-parent = <&gpio4>;
> - interrupts = <12 IRQ_TYPE_EDGE_RISING>;
> - interrupt-names = "INT1";
> -};
> -
> -bmi160@0 {
> - compatible = "bosch,bmi160";
> - reg = <0>;
> - spi-max-frequency = <10000000>;
> -
> - interrupt-parent = <&gpio2>;
> - interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
> - interrupt-names = "INT2";
> -};
> diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml
> new file mode 100644
> index 000000000000..46cb4fde1165
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/imu/bosch,bmi160.yaml
> @@ -0,0 +1,76 @@
> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/iio/imu/bosch,bmi160.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Bosch BMI160
> +
> +maintainers:
> + - Daniel Baluta <daniel.baluta@nxp.com> (?)
Daniel's reply crossed with this. Given he's moved on to other things
he's not happy to be listed as maintainer here.
Given other threads, either put yourself here if you are happy to maintain
the binding, or fall back to me but use my kernel.org address.
Jonathan Cameron <jic23@kernel.org>
I don't mind either way.
> +
> +description: |
> + Inertial Measurement Unit with Accelerometer, Gyroscope and externally
> + connectable Magnetometer
> + https://www.bosch-sensortec.com/bst/products/all_products/bmi160
> +
> +properties:
> + compatible:
> + const: bosch,bmi160
> +
> + reg:
> + maxItems: 1
> +
> + spi-max-frequency:
> + maxItems: 1
spi-max-frequency doesn't need to be here at all. We aren't trying to list
all of the properties that might be present - but rather those that
are either required or that are part of the description of the device.
This one is a generic spi binding that may or may not be present.
> +
> + interrupts:
> + maxItems: 1
> +
> + interrupt-names:
> + enum:
> + - INT1
> + - INT2
> + description: |
> + set to "INT1" if INT1 pin should be used as interrupt input, set
> + to "INT2" if INT2 pin should be used instead
> +
> + drive-open-drain:
> + description: |
> + set if the specified interrupt pin should be configured as
> + open drain. If not set, defaults to push-pull.
> +
> +required:
> + - compatible
> + - reg
> +
> +examples:
> + - |
> + // Example for I2C
> + i2c {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + bmi160@68 {
> + compatible = "bosch,bmi160";
> + reg = <0x68>;
> + interrupt-parent = <&gpio4>;
> + interrupts = <12 1>;
> + interrupt-names = "INT1";
> + };
> + };
> + - |
> + // Example for SPI
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + bmi160@0 {
> + compatible = "bosch,bmi160";
> + reg = <0>;
> + spi-max-frequency = <10000000>;
> + interrupt-parent = <&gpio2>;
> + interrupts = <12 1>;
> + interrupt-names = "INT2";
> + };
> + };
^ permalink raw reply
* [PATCH V5 1/8] dt-bindings: mailbox: Add YAML schemas for QCOM APCS global block
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
Qualcomm APCS global block provides a bunch of generic properties which
are required in a device tree. Add YAML schema for these properties.
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
.../bindings/mailbox/qcom,apcs-kpss-global.txt | 88 ----------------------
.../bindings/mailbox/qcom,apcs-kpss-global.yaml | 86 +++++++++++++++++++++
2 files changed, 86 insertions(+), 88 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
create mode 100644 Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
deleted file mode 100644
index beec612..0000000
--- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-Binding for the Qualcomm APCS global block
-==========================================
-
-This binding describes the APCS "global" block found in various Qualcomm
-platforms.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be one of:
- "qcom,msm8916-apcs-kpss-global",
- "qcom,msm8996-apcs-hmss-global"
- "qcom,msm8998-apcs-hmss-global"
- "qcom,qcs404-apcs-apps-global"
- "qcom,sc7180-apss-shared"
- "qcom,sdm845-apss-shared"
- "qcom,sm8150-apss-shared"
- "qcom,ipq8074-apcs-apps-global"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: must specify the base address and size of the global block
-
-- clocks:
- Usage: required if #clock-names property is present
- Value type: <phandle array>
- Definition: phandles to the two parent clocks of the clock driver.
-
-- #mbox-cells:
- Usage: required
- Value type: <u32>
- Definition: as described in mailbox.txt, must be 1
-
-- #clock-cells:
- Usage: optional
- Value type: <u32>
- Definition: as described in clock.txt, must be 0
-
-- clock-names:
- Usage: required if the platform data based clock driver needs to
- retrieve the parent clock names from device tree.
- This will requires two mandatory clocks to be defined.
- Value type: <string-array>
- Definition: must be "pll" and "aux"
-
-= EXAMPLE
-The following example describes the APCS HMSS found in MSM8996 and part of the
-GLINK RPM referencing the "rpm_hlos" doorbell therein.
-
- apcs_glb: mailbox@9820000 {
- compatible = "qcom,msm8996-apcs-hmss-global";
- reg = <0x9820000 0x1000>;
-
- #mbox-cells = <1>;
- };
-
- rpm-glink {
- compatible = "qcom,glink-rpm";
-
- interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
-
- qcom,rpm-msg-ram = <&rpm_msg_ram>;
-
- mboxes = <&apcs_glb 0>;
- mbox-names = "rpm_hlos";
- };
-
-Below is another example of the APCS binding on MSM8916 platforms:
-
- apcs: mailbox@b011000 {
- compatible = "qcom,msm8916-apcs-kpss-global";
- reg = <0xb011000 0x1000>;
- #mbox-cells = <1>;
- clocks = <&a53pll>;
- #clock-cells = <0>;
- };
-
-Below is another example of the APCS binding on QCS404 platforms:
-
- apcs_glb: mailbox@b011000 {
- compatible = "qcom,qcs404-apcs-apps-global", "syscon";
- reg = <0x0b011000 0x1000>;
- #mbox-cells = <1>;
- clocks = <&apcs_hfpll>, <&gcc GCC_GPLL0_AO_OUT_MAIN>;
- clock-names = "pll", "aux";
- #clock-cells = <0>;
- };
diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
new file mode 100644
index 0000000..12eff94
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/mailbox/qcom,apcs-kpss-global.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm APCS global block bindings
+
+description:
+ This binding describes the APCS "global" block found in various Qualcomm
+ platforms.
+
+maintainers:
+ - Sivaprakash Murugesan <sivaprak@codeaurora.org>
+
+properties:
+ compatible:
+ enum:
+ - qcom,ipq8074-apcs-apps-global
+ - qcom,msm8916-apcs-kpss-global
+ - qcom,msm8996-apcs-hmss-global
+ - qcom,msm8998-apcs-hmss-global
+ - qcom,qcs404-apcs-apps-global
+ - qcom,sc7180-apss-shared
+ - qcom,sdm845-apss-shared
+ - qcom,sm8150-apss-shared
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: phandles to the parent clocks of the clock driver
+ items:
+ - description: primary pll parent of the clock driver
+ - description: auxiliary parent
+
+ '#mbox-cells':
+ const: 1
+
+ '#clock-cells':
+ const: 0
+
+ clock-names:
+ items:
+ - const: pll
+ - const: aux
+
+required:
+ - compatible
+ - reg
+ - '#mbox-cells'
+
+additionalProperties: false
+
+examples:
+
+ # Example apcs with msm8996
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ apcs_glb: mailbox@9820000 {
+ compatible = "qcom,msm8996-apcs-hmss-global";
+ reg = <0x9820000 0x1000>;
+
+ #mbox-cells = <1>;
+ };
+
+ rpm-glink {
+ compatible = "qcom,glink-rpm";
+ interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+ mboxes = <&apcs_glb 0>;
+ mbox-names = "rpm_hlos";
+ };
+
+ # Example apcs with qcs404
+ - |
+ #define GCC_APSS_AHB_CLK_SRC 1
+ #define GCC_GPLL0_AO_OUT_MAIN 123
+ apcs: mailbox@b011000 {
+ compatible = "qcom,qcs404-apcs-apps-global";
+ reg = <0x0b011000 0x1000>;
+ #mbox-cells = <1>;
+ clocks = <&apcs_hfpll>, <&gcc GCC_GPLL0_AO_OUT_MAIN>;
+ clock-names = "pll", "aux";
+ #clock-cells = <0>;
+ };
--
2.7.4
^ permalink raw reply related
* [PATCH V5 2/8] dt-bindings: clock: add ipq6018 a53 pll compatible
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
cpus on ipq6018 are clocked by a53 pll, add device compatible for a53
pll found on ipq6018 devices.
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
[V5]
* Addressed Bjorn's review comment.
now the a53 dt-binding represents ipq a53 pll as well.
.../devicetree/bindings/clock/qcom,a53pll.yaml | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
index 20d2638..972db15 100644
--- a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
@@ -16,6 +16,7 @@ description:
properties:
compatible:
const: qcom,msm8916-a53pll
+ const: qcom,ipq6018-a53pll
reg:
maxItems: 1
@@ -23,6 +24,14 @@ properties:
'#clock-cells':
const: 0
+ clocks:
+ items:
+ - description: board XO clock
+
+ clock-names:
+ items:
+ - const: xo
+
required:
- compatible
- reg
@@ -38,3 +47,12 @@ examples:
reg = <0xb016000 0x40>;
#clock-cells = <0>;
};
+ #Example 2 - A53 PLL found on IPQ6018 devices
+ - |
+ a53pll_ipq: clock@b116000 {
+ compatible = "qcom,ipq6018-a53pll";
+ reg = <0x0b116000 0x40>;
+ #clock-cells = <0>;
+ clocks = <&xo>;
+ clock-names = "xo";
+ };
--
2.7.4
^ permalink raw reply related
* [PATCH V5 3/8] clk: qcom: Add ipq apss pll driver
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
The CPUs on Qualcomm ipq based devices are clocked by an alpha PLL.
Add support for the apss pll found on ipq based devices which can
support CPU frequencies above 1Ghz.
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
drivers/clk/qcom/Kconfig | 8 ++++
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/apss-ipq-pll.c | 97 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 106 insertions(+)
create mode 100644 drivers/clk/qcom/apss-ipq-pll.c
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 11ec6f4..e70aa01 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -89,6 +89,14 @@ config APQ_MMCC_8084
Say Y if you want to support multimedia devices such as display,
graphics, video encode/decode, camera, etc.
+config IPQ_APSS_PLL
+ tristate "IPQ APSS PLL"
+ help
+ Support for APSS PLL on ipq devices. The APSS PLL is the main
+ clock that feeds the CPUs on ipq based devices.
+ Say Y if you want to support CPU frequency scaling on ipq based
+ devices.
+
config IPQ_GCC_4019
tristate "IPQ4019 Global Clock Controller"
help
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 691efbf..b4a6ba1 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -19,6 +19,7 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
# Keep alphabetically sorted by config
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
+obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
diff --git a/drivers/clk/qcom/apss-ipq-pll.c b/drivers/clk/qcom/apss-ipq-pll.c
new file mode 100644
index 0000000..aafdaa7
--- /dev/null
+++ b/drivers/clk/qcom/apss-ipq-pll.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+
+#include "clk-alpha-pll.h"
+
+static const u8 ipq_pll_offsets[] = {
+ [PLL_OFF_L_VAL] = 0x08,
+ [PLL_OFF_ALPHA_VAL] = 0x10,
+ [PLL_OFF_USER_CTL] = 0x18,
+ [PLL_OFF_CONFIG_CTL] = 0x20,
+ [PLL_OFF_CONFIG_CTL_U] = 0x24,
+ [PLL_OFF_STATUS] = 0x28,
+ [PLL_OFF_TEST_CTL] = 0x30,
+ [PLL_OFF_TEST_CTL_U] = 0x34,
+};
+
+static struct clk_alpha_pll ipq_pll = {
+ .offset = 0x0,
+ .regs = ipq_pll_offsets,
+ .flags = SUPPORTS_DYNAMIC_UPDATE,
+ .clkr = {
+ .enable_reg = 0x0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "a53pll",
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_huayra_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config ipq_pll_config = {
+ .l = 0x37,
+ .config_ctl_val = 0x04141200,
+ .config_ctl_hi_val = 0x0,
+ .early_output_mask = BIT(3),
+ .main_output_mask = BIT(0),
+};
+
+static const struct regmap_config ipq_pll_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x40,
+ .fast_io = true,
+};
+
+static int apss_ipq_pll_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ struct resource *res;
+ void __iomem *base;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &ipq_pll_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_alpha_pll_configure(&ipq_pll, regmap, &ipq_pll_config);
+
+ ret = devm_clk_register_regmap(dev, &ipq_pll.clkr);
+ if (ret)
+ return ret;
+
+ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+ &ipq_pll.clkr.hw);
+}
+
+static const struct of_device_id apss_ipq_pll_match_table[] = {
+ { .compatible = "qcom,ipq6018-a53pll" },
+ { }
+};
+
+static struct platform_driver apss_ipq_pll_driver = {
+ .probe = apss_ipq_pll_probe,
+ .driver = {
+ .name = "qcom-ipq-apss-pll",
+ .of_match_table = apss_ipq_pll_match_table,
+ },
+};
+module_platform_driver(apss_ipq_pll_driver);
+
+MODULE_DESCRIPTION("Qualcomm technology Inc APSS ALPHA PLL Driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH V5 4/8] clk: qcom: Add DT bindings for ipq6018 apss clock controller
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
add dt-binding for ipq6018 apss clock controller
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
include/dt-bindings/clock/qcom,apss-ipq.h | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 include/dt-bindings/clock/qcom,apss-ipq.h
diff --git a/include/dt-bindings/clock/qcom,apss-ipq.h b/include/dt-bindings/clock/qcom,apss-ipq.h
new file mode 100644
index 0000000..77b6e05
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,apss-ipq.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_QCA_APSS_IPQ6018_H
+#define _DT_BINDINGS_CLOCK_QCA_APSS_IPQ6018_H
+
+#define APCS_ALIAS0_CLK_SRC 0
+#define APCS_ALIAS0_CORE_CLK 1
+
+#endif
--
2.7.4
^ permalink raw reply related
* [PATCH V5 7/8] mailbox: qcom: Add ipq6018 apcs compatible
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
The Qualcomm ipq6018 has apcs block, add compatible for the same.
Also, the apcs provides a clock controller functionality similar
to msm8916 but the clock driver is different.
Create a child platform device based on the apcs compatible for the
clock controller functionality.
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
[V5]
* Addressed Bjorn's review comments
drivers/mailbox/qcom-apcs-ipc-mailbox.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
index eeebafd..db3f9518 100644
--- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c
+++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c
@@ -45,6 +45,13 @@ static const struct mbox_chan_ops qcom_apcs_ipc_ops = {
.send_data = qcom_apcs_ipc_send_data,
};
+static const struct of_device_id apcs_clk_match_table[] = {
+ { .compatible = "qcom,ipq6018-apcs-apps-global", .data = "qcom,apss-ipq6018-clk", },
+ { .compatible = "qcom,msm8916-apcs-kpss-global", .data = "qcom-apcs-msm8916-clk", },
+ { .compatible = "qcom,qcs404-apcs-apps-global", .data = "qcom-apcs-msm8916-clk", },
+ {}
+};
+
static int qcom_apcs_ipc_probe(struct platform_device *pdev)
{
struct qcom_apcs_ipc *apcs;
@@ -54,11 +61,7 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
void __iomem *base;
unsigned long i;
int ret;
- const struct of_device_id apcs_clk_match_table[] = {
- { .compatible = "qcom,msm8916-apcs-kpss-global", },
- { .compatible = "qcom,qcs404-apcs-apps-global", },
- {}
- };
+ const struct of_device_id *clk_device;
apcs = devm_kzalloc(&pdev->dev, sizeof(*apcs), GFP_KERNEL);
if (!apcs)
@@ -93,11 +96,12 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev)
return ret;
}
- if (of_match_device(apcs_clk_match_table, &pdev->dev)) {
+ clk_device = of_match_device(apcs_clk_match_table, &pdev->dev);
+ if (clk_device) {
apcs->clk = platform_device_register_data(&pdev->dev,
- "qcom-apcs-msm8916-clk",
- PLATFORM_DEVID_NONE,
- NULL, 0);
+ clk_device->data,
+ PLATFORM_DEVID_NONE,
+ NULL, 0);
if (IS_ERR(apcs->clk))
dev_err(&pdev->dev, "failed to register APCS clk\n");
}
@@ -126,6 +130,7 @@ static const struct of_device_id qcom_apcs_ipc_of_match[] = {
{ .compatible = "qcom,sc7180-apss-shared", .data = (void *)12 },
{ .compatible = "qcom,sdm845-apss-shared", .data = (void *)12 },
{ .compatible = "qcom,sm8150-apss-shared", .data = (void *)12 },
+ { .compatible = "qcom,ipq6018-apcs-apps-global", .data = (void *)8 },
{ .compatible = "qcom,ipq8074-apcs-apps-global", .data = (void *)8 },
{}
};
--
2.7.4
^ permalink raw reply related
* [PATCH V5 8/8] arm64: dts: ipq6018: Add a53 pll and apcs clock
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
add support for apps pll and apcs clock.
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
[V5]
* changed compatible to match the bindings
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
index 1aa8d85..8d60f6f 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -294,12 +294,22 @@
};
apcs_glb: mailbox@b111000 {
- compatible = "qcom,ipq8074-apcs-apps-global";
- reg = <0x0b111000 0xc>;
-
+ compatible = "qcom,ipq6018-apcs-apps-global";
+ reg = <0x0b111000 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&apsspll>, <&xo>;
+ clock-names = "pll", "xo";
#mbox-cells = <1>;
};
+ apsspll: clock@b116000 {
+ compatible = "qcom,ipq6018-a53pll";
+ reg = <0x0b116000 0x40>;
+ #clock-cells = <0>;
+ clocks = <&xo>;
+ clock-names = "xo";
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
--
2.7.4
^ permalink raw reply related
* [PATCH V5 5/8] clk: qcom: Add ipq6018 apss clock controller
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
The CPU on Qualcomm ipq6018 devices are clocked primarily by a aplha PLL
and xo which are connected to a mux and enable block.
Add support for the mux and enable block which feeds the CPU on ipq6018
devices.
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
[V5]
* Addressed Bjorn's review comments, changed apss clock driver more specific
to the ipq6018 devices.
drivers/clk/qcom/Kconfig | 11 +++++
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/apss-ipq6018.c | 106 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 118 insertions(+)
create mode 100644 drivers/clk/qcom/apss-ipq6018.c
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index e70aa01..b543e63 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -97,6 +97,17 @@ config IPQ_APSS_PLL
Say Y if you want to support CPU frequency scaling on ipq based
devices.
+config IPQ_APSS_6018
+ tristate "IPQ APSS Clock Controller"
+ select IPQ_APSS_PLL
+ depends on QCOM_APCS_IPC || COMPILE_TEST
+ help
+ Support for APSS clock controller on IPQ platforms. The
+ APSS clock controller manages the Mux and enable block that feeds the
+ CPUs.
+ Say Y if you want to support CPU frequency scaling on
+ ipq based devices.
+
config IPQ_GCC_4019
tristate "IPQ4019 Global Clock Controller"
help
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index b4a6ba1..3accea1 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -20,6 +20,7 @@ clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
+obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
obj-$(CONFIG_IPQ_GCC_6018) += gcc-ipq6018.o
obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c
new file mode 100644
index 0000000..004f7e1
--- /dev/null
+++ b/drivers/clk/qcom/apss-ipq6018.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+
+#include <dt-bindings/clock/qcom,apss-ipq.h>
+
+#include "common.h"
+#include "clk-regmap.h"
+#include "clk-branch.h"
+#include "clk-alpha-pll.h"
+#include "clk-regmap-mux.h"
+
+enum {
+ P_XO,
+ P_APSS_PLL_EARLY,
+};
+
+static const struct clk_parent_data parents_apcs_alias0_clk_src[] = {
+ { .fw_name = "xo" },
+ { .fw_name = "pll" },
+};
+
+static const struct parent_map parents_apcs_alias0_clk_src_map[] = {
+ { P_XO, 0 },
+ { P_APSS_PLL_EARLY, 5 },
+};
+
+static struct clk_regmap_mux apcs_alias0_clk_src = {
+ .reg = 0x0050,
+ .width = 3,
+ .shift = 7,
+ .parent_map = parents_apcs_alias0_clk_src_map,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "apcs_alias0_clk_src",
+ .parent_data = parents_apcs_alias0_clk_src,
+ .num_parents = 2,
+ .ops = &clk_regmap_mux_closest_ops,
+ .flags = CLK_SET_RATE_PARENT,
+ },
+};
+
+static struct clk_branch apcs_alias0_core_clk = {
+ .halt_reg = 0x0058,
+ .clkr = {
+ .enable_reg = 0x0058,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "apcs_alias0_core_clk",
+ .parent_hws = (const struct clk_hw *[]){
+ &apcs_alias0_clk_src.clkr.hw },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static const struct regmap_config apss_ipq6018_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1000,
+ .fast_io = true,
+};
+
+static struct clk_regmap *apss_ipq6018_clks[] = {
+ [APCS_ALIAS0_CLK_SRC] = &apcs_alias0_clk_src.clkr,
+ [APCS_ALIAS0_CORE_CLK] = &apcs_alias0_core_clk.clkr,
+};
+
+static const struct qcom_cc_desc apss_ipq6018_desc = {
+ .config = &apss_ipq6018_regmap_config,
+ .clks = apss_ipq6018_clks,
+ .num_clks = ARRAY_SIZE(apss_ipq6018_clks),
+};
+
+static int apss_ipq6018_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap);
+}
+
+static struct platform_driver apss_ipq6018_driver = {
+ .probe = apss_ipq6018_probe,
+ .driver = {
+ .name = "qcom,apss-ipq6018-clk",
+ },
+};
+
+module_platform_driver(apss_ipq6018_driver);
+
+MODULE_DESCRIPTION("QCOM APSS IPQ 6018 CLK Driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH V5 6/8] dt-bindings: mailbox: Add dt-bindings for ipq6018 apcs global block
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
In-Reply-To: <1590314686-11749-1-git-send-email-sivaprak@codeaurora.org>
Add dt-bindings for ipq6018 mailbox driver
Reviewed-by: Rob Herring <robh@kernel.org>
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
---
.../bindings/mailbox/qcom,apcs-kpss-global.yaml | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
index 12eff94..e05bff4 100644
--- a/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
+++ b/Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
@@ -16,6 +16,7 @@ maintainers:
properties:
compatible:
enum:
+ - qcom,ipq6018-apcs-apps-global
- qcom,ipq8074-apcs-apps-global
- qcom,msm8916-apcs-kpss-global
- qcom,msm8996-apcs-hmss-global
@@ -38,12 +39,12 @@ properties:
const: 1
'#clock-cells':
- const: 0
+ enum: [ 0, 1 ]
clock-names:
items:
- const: pll
- - const: aux
+ - enum: [ aux, xo ]
required:
- compatible
@@ -84,3 +85,15 @@ examples:
clock-names = "pll", "aux";
#clock-cells = <0>;
};
+
+ # Example apcs with ipq6018
+ - |
+ #include "dt-bindings/clock/qcom,apss-ipq.h"
+ apcs_ipq: mailbox@b111000 {
+ compatible = "qcom,ipq6018-apcs-apps-global";
+ reg = <0x0b111000 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&a53pll>, <&xo>;
+ clock-names = "pll", "xo";
+ #mbox-cells = <1>;
+ };
--
2.7.4
^ permalink raw reply related
* [PATCH V5 0/8] Add APSS clock controller support for IPQ6018
From: Sivaprakash Murugesan @ 2020-05-24 10:04 UTC (permalink / raw)
To: agross, bjorn.andersson, mturquette, sboyd, robh+dt,
jassisinghbrar, linux-arm-msm, linux-clk, devicetree,
linux-kernel
Cc: Sivaprakash Murugesan
The CPU on Qualcomm's IPQ6018 devices are primarily fed by APSS PLL and XO,
these are connected to a clock mux and enable block.
This patch series adds support for these clocks and inturn enables clocks
required for CPU freq.
[V5]
* Addressed Bjorn comments on apss clk and dt-bindings
* Patch 2 depends on a53 pll dt-bindings
https://www.spinics.net/lists/linux-clk/msg48358.html
[V4]
* Re-written PLL found on IPQ platforms as a separate driver
* Addressed stephen's comments on apss clock controller and pll
* Addressed Rob's review comments on bindings
* moved a53 pll binding from this series as it is not applicable, will send
it separately.
[V3]
* Fixed dt binding check error in patch2
dt-bindings: clock: Add YAML schemas for QCOM A53 PLL
[V2]
* Restructred the patch series as there are two different HW blocks,
the mux and enable belongs to the apcs block and PLL has a separate HW
block.
* Converted qcom mailbox and qcom a53 pll documentation to yaml.
* Addressed review comments from Stephen, Rob and Sibi where it is applicable.
* Changed this cover letter to state the purpose of this patch series
Sivaprakash Murugesan (8):
dt-bindings: mailbox: Add YAML schemas for QCOM APCS global block
dt-bindings: clock: add ipq6018 a53 pll compatible
clk: qcom: Add ipq apss pll driver
clk: qcom: Add DT bindings for ipq6018 apss clock controller
clk: qcom: Add ipq6018 apss clock controller
dt-bindings: mailbox: Add dt-bindings for ipq6018 apcs global block
mailbox: qcom: Add ipq6018 apcs compatible
arm64: dts: ipq6018: Add a53 pll and apcs clock
.../devicetree/bindings/clock/qcom,a53pll.yaml | 18 ++++
.../bindings/mailbox/qcom,apcs-kpss-global.txt | 88 -----------------
.../bindings/mailbox/qcom,apcs-kpss-global.yaml | 99 +++++++++++++++++++
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 16 +++-
drivers/clk/qcom/Kconfig | 19 ++++
drivers/clk/qcom/Makefile | 2 +
drivers/clk/qcom/apss-ipq-pll.c | 97 +++++++++++++++++++
drivers/clk/qcom/apss-ipq6018.c | 106 +++++++++++++++++++++
drivers/mailbox/qcom-apcs-ipc-mailbox.c | 23 +++--
include/dt-bindings/clock/qcom,apss-ipq.h | 12 +++
10 files changed, 380 insertions(+), 100 deletions(-)
delete mode 100644 Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.txt
create mode 100644 Documentation/devicetree/bindings/mailbox/qcom,apcs-kpss-global.yaml
create mode 100644 drivers/clk/qcom/apss-ipq-pll.c
create mode 100644 drivers/clk/qcom/apss-ipq6018.c
create mode 100644 include/dt-bindings/clock/qcom,apss-ipq.h
--
2.7.4
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox