Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v4 0/4] meson-ee-pwrc: support for Meson8/8b/8m2 and GX
From: Kevin Hilman @ 2020-05-19 23:07 UTC (permalink / raw)
  To: Martin Blumenstingl, linux-amlogic
  Cc: robh+dt, narmstrong, devicetree, linux-arm-kernel, linux-kernel,
	Martin Blumenstingl
In-Reply-To: <20200515204709.1505498-1-martin.blumenstingl@googlemail.com>

Martin Blumenstingl <martin.blumenstingl@googlemail.com> writes:

> This series adds support for all "older" SoCs to the meson-ee-pwrc
> driver. I wanted to compare as much as I could between my Meson8b EC-100
> (Endless Mini) and the Le Potato board so I added support for GXBB, GXL
> and GXM as well as for the SoCs that I'm actually working on. I will
> send the ARM64 dts patches once all of this is reviewed and merged.
>
> I successfully tested the Meson8b part on EC-100 where u-boot does not
> initialize the VPU controller. So this the board where I have been
> struggling most.
>
> Kevin, I'm not sure if this can still make it into v5.8. If the
> series as a whole can't make it for some reason then I'd appreciate if
> patches #1 and #2 could end in v5.8 so I can push the .dts patches for
> v5.9.

Queuing for v5.8,

Thanks Martin!

Kevin

^ permalink raw reply

* Re: [PATCH 2/4] dt-bindings: sram: add documentation for reserved-only flag
From: Rob Herring @ 2020-05-19 23:03 UTC (permalink / raw)
  To: Stephen Warren
  Cc: Mian Yousaf Kaukab, robin.murphy, devicetree, talho,
	thierry.reding, jonathanh, linux-tegra, linux-kernel,
	linux-arm-kernel, afaerber, arnd, gregkh
In-Reply-To: <efcc6b5e-423c-8ae1-8a46-d6a06c1a1bab@wwwdotorg.org>

On Tue, May 19, 2020 at 10:16:43AM -0600, Stephen Warren wrote:
> On 5/13/20 4:41 AM, Mian Yousaf Kaukab wrote:
> > On Tue, May 12, 2020 at 01:45:28PM -0600, Stephen Warren wrote:
> >> On 5/12/20 8:48 AM, Mian Yousaf Kaukab wrote:
> >>> Add documentation for the new optional flag added for SRAM driver.
> >>
> >>> diff --git a/Documentation/devicetree/bindings/sram/sram.yaml b/Documentation/devicetree/bindings/sram/sram.yaml
> >>
> >>> +  reserved-only:
> >>> +    description:
> >>> +      The flag indicating, that only SRAM reserved regions have to be remapped.
> >>> +      remapping type is selected depending upon no-memory-wc as usual.
> >>> +    type: boolean
> >>
> >> This feels a bit like a SW flag rather than a HW description, so I'm not
> >> sure it's appropriate to put it into DT.
> > 
> > Reserved regions themselves are software descriptions, no? Then we have 'pool'
> > flag which is again a software flag and so on. This flag falls into same
> > category and nothing out of ordinary.
> 
> I suppose that's true to some extent. This is indeed a description of
> the system environment presented to the SW that consumes the DT, which
> is a bit more than pure HW description but still a description of
> something imposed externally rather than describing something that's up
> to the discretion of the consuming SW. So, go ahead.
> 
> >> Are there any cases where the SW should map all of the SRAM, i.e. where
> >> we wouldn't expect to set reserved-only? [...]
> > 
> > Yes, here are a few examples:
> > arch/arm/boot/dts/aspeed-g*.dtsi
> > arch/arm/boot/dts/at91*.dtsi
> > arch/arm/boot/dts/bcm7445.dtsi
> > Then arch/arm/boot/dts/dra7.dtsi is an example where we should map everything
> > except the reserved region.
> > 
> >> [...] I'd expect reserved-only to be
> >> the default, and perhaps only, mode of operation for the SRAM driver.
> > 
> > It will break compatibility with existing dtbs.
> > 
> >> If we can't do that because some SW currently expects to be able to map
> >> arbitrary portions of the SRAM, shouldn't that SW be fixed to tell the
> >> SRAM driver which parts it's using, hence still allowing the driver to
> >> only map in-use portions?
> > 
> > User doesn’t need sram driver in that case. It can use genalloc api directly.
> 
> This sounds a bit odd. Without a driver for the reserved region, nothing
> should be touching it, since otherwise there's no code that owns an
> manages the region. If any code needs to consume the region, it should
> obtain info about the region from some form of provider code that can
> handle both the allocation and mapping. Anything else sounds like some
> consumer code directly making use of DT nodes it doesn't own. But since
> I'm not familiar enough with the SRAM driver and genalloc code that you
> mention to fully understand the allocation paths I guess I won't object
> for now, although it does still sound fishy.

I'm fine with the concept, but I don't think a single flag is adequate. 
If there are reserved regions within the SRAM, then define child nodes 
to mark those regions reserved. I don't think you need a new flag. Just 
a 'reg' property and nothing else.

Rob

^ permalink raw reply

* Re: [PATCH v8 7/8] tpm: Add YAML schema for TPM TIS I2C options
From: Rob Herring @ 2020-05-19 22:44 UTC (permalink / raw)
  To: amirmizi6
  Cc: Eyal.Cohen, jarkko.sakkinen, oshrialkoby85, alexander.steffen,
	peterhuewe, christophe-h.richard, jgg, arnd, gregkh, devicetree,
	linux-kernel, linux-integrity, oshri.alkoby, tmaimon77, gcwilson,
	kgoldman, Dan.Morav, oren.tanami, shmulik.hager, amir.mizinski
In-Reply-To: <20200512141431.83833-8-amirmizi6@gmail.com>

On Tue, May 12, 2020 at 05:14:30PM +0300, amirmizi6@gmail.com wrote:
> From: Amir Mizinski <amirmizi6@gmail.com>
> 
> Added a YAML schema to support tpm tis i2c related dt-bindings for the I2c
> PTP based physical layer.
> 
> This patch adds the documentation for corresponding device tree bindings of
> I2C based Physical TPM.
> Refer to the 'I2C Interface Definition' section in
> 'TCG PC Client PlatformTPMProfile(PTP) Specification' publication
> for specification.
> 
> Signed-off-by: Amir Mizinski <amirmizi6@gmail.com>
> ---
>  .../bindings/security/tpm/tpm-tis-i2c.yaml         | 51 ++++++++++++++++++++++
>  1 file changed, 51 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml
> 
> diff --git a/Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml b/Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml
> new file mode 100644
> index 0000000..628c8f3
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/security/tpm/tpm-tis-i2c.yaml
> @@ -0,0 +1,51 @@
> +# SPDX-License-Identifier: GPL-2.0

Dual license new bindings please:

(GPL-2.0-only OR BSD-2-Clause)

> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/security/tpm/tpm-tis-i2c.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: I2C PTP based TPM Device Tree Bindings
> +
> +maintainers:
> +  - Amir Mizinski <amirmizi6@gmail.com>
> +
> +description:
> +  Device Tree Bindings for I2C based Trusted Platform Module(TPM).
> +
> +properties:
> +  compatible:
> +    oneOf:
> +      - items:

You don't need 'oneOf'.

> +          - enum:
> +              # Nuvoton's Trusted Platform Module (TPM) (NPCT75x)
> +              - nuvoton,npct75x
> +          - const: tcg,tpm-tis-i2c
> +
> +  reg:
> +    maxItems: 1
> +
> +  interrupt:
> +    maxItems: 1
> +
> +  crc-checksum:
> +    $ref: /schemas/types.yaml#/definitions/flag
> +    description:
> +      Set this flag to enable CRC checksum.
> +
> +required:
> +  - compatible
> +  - reg
> +
> +examples:
> +  - |
> +    i2c {
> +      #address-cells = <1>;
> +      #size-cells = <0>;
> +
> +      tpm_tis@2e {

tpm@2e

> +        compatible = "nuvoton,npct75x", "tcg,tpm-tis-i2c";
> +        reg = <0x2e>;
> +        crc-checksum;
> +      };
> +    };
> +...
> -- 
> 2.7.4
> 

^ permalink raw reply

* [PATCH v3 05/13] clk: mmp2: Move thermal register defines up a bit
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

A trivial change to keep the sorting sane. The APBC registers are happier
when they are grouped together, instead of mixed with the APMU ones.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
 drivers/clk/mmp/clk-of-mmp2.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 52dc8b43acd9..524574187c17 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -45,6 +45,10 @@
 #define APBC_SSP1	0x54
 #define APBC_SSP2	0x58
 #define APBC_SSP3	0x5c
+#define APBC_THERMAL0	0x90
+#define APBC_THERMAL1	0x98
+#define APBC_THERMAL2	0x9c
+#define APBC_THERMAL3	0xa0
 #define APMU_SDH0	0x54
 #define APMU_SDH1	0x58
 #define APMU_SDH2	0xe8
@@ -55,10 +59,6 @@
 #define APMU_DISP1	0x110
 #define APMU_CCIC0	0x50
 #define APMU_CCIC1	0xf4
-#define APBC_THERMAL0	0x90
-#define APBC_THERMAL1	0x98
-#define APBC_THERMAL2	0x9c
-#define APBC_THERMAL3	0xa0
 #define APMU_USBHSIC0	0xf8
 #define APMU_USBHSIC1	0xfc
 #define APMU_GPU	0xcc
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 07/13] clk: mmp2: Add the I2S clocks
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

A pair of fractional clock sources for PLLs and gates.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>

---
Changes since v2:
- s/I2C/I2S/

 drivers/clk/mmp/clk-of-mmp2.c | 46 +++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index ac88ea99b7c6..dcdff06a698a 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -67,6 +67,9 @@
 #define MPMU_POSR		0x10
 #define MPMU_UART_PLL		0x14
 #define MPMU_PLL2_CR		0x34
+#define MPMU_I2S0_PLL		0x40
+#define MPMU_I2S1_PLL		0x44
+#define MPMU_ACGR		0x1024
 /* MMP3 specific below */
 #define MPMU_PLL3_CR		0x50
 #define MPMU_PLL3_CTRL1		0x58
@@ -91,6 +94,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
 	{MMP2_CLK_CLK32, "clk32", NULL, 0, 32768},
 	{MMP2_CLK_VCTCXO, "vctcxo", NULL, 0, 26000000},
 	{MMP2_CLK_USB_PLL, "usb_pll", NULL, 0, 480000000},
+	{0, "i2s_pll", NULL, 0, 99666667},
 };
 
 static struct mmp_param_pll_clk pll_clks[] = {
@@ -139,6 +143,34 @@ static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
 	{.num = 3521, .den = 689},	/*19.23MHZ */
 };
 
+static struct mmp_clk_factor_masks i2s_factor_masks = {
+	.factor = 2,
+	.num_mask = 0x7fff,
+	.den_mask = 0x1fff,
+	.num_shift = 0,
+	.den_shift = 15,
+	.enable_mask = 0xd0000000,
+};
+
+static struct mmp_clk_factor_tbl i2s_factor_tbl[] = {
+	{.num = 24868, .den =  511},	/*  2.0480 MHz */
+	{.num = 28003, .den =  793},	/*  2.8224 MHz */
+	{.num = 24941, .den = 1025},	/*  4.0960 MHz */
+	{.num = 28003, .den = 1586},	/*  5.6448 MHz */
+	{.num = 31158, .den = 2561},	/*  8.1920 MHz */
+	{.num = 16288, .den = 1845},	/* 11.2896 MHz */
+	{.num = 20772, .den = 2561},	/* 12.2880 MHz */
+	{.num =  8144, .den = 1845},	/* 22.5792 MHz */
+	{.num = 10386, .den = 2561},	/* 24.5760 MHz */
+};
+
+static DEFINE_SPINLOCK(acgr_lock);
+
+static struct mmp_param_gate_clk mpmu_gate_clks[] = {
+	{MMP2_CLK_I2S0, "i2s0_clk", "i2s0_pll", CLK_SET_RATE_PARENT, MPMU_ACGR, 0x200000, 0x200000, 0x0, 0, &acgr_lock},
+	{MMP2_CLK_I2S1, "i2s1_clk", "i2s1_pll", CLK_SET_RATE_PARENT, MPMU_ACGR, 0x100000, 0x100000, 0x0, 0, &acgr_lock},
+};
+
 static void mmp2_main_clk_init(struct mmp2_clk_unit *pxa_unit)
 {
 	struct clk *clk;
@@ -166,6 +198,20 @@ static void mmp2_main_clk_init(struct mmp2_clk_unit *pxa_unit)
 				&uart_factor_masks, uart_factor_tbl,
 				ARRAY_SIZE(uart_factor_tbl), NULL);
 	mmp_clk_add(unit, MMP2_CLK_UART_PLL, clk);
+
+	mmp_clk_register_factor("i2s0_pll", "pll1_4",
+				CLK_SET_RATE_PARENT,
+				pxa_unit->mpmu_base + MPMU_I2S0_PLL,
+				&i2s_factor_masks, i2s_factor_tbl,
+				ARRAY_SIZE(i2s_factor_tbl), NULL);
+	mmp_clk_register_factor("i2s1_pll", "pll1_4",
+				CLK_SET_RATE_PARENT,
+				pxa_unit->mpmu_base + MPMU_I2S1_PLL,
+				&i2s_factor_masks, i2s_factor_tbl,
+				ARRAY_SIZE(i2s_factor_tbl), NULL);
+
+	mmp_register_gate_clks(unit, mpmu_gate_clks, pxa_unit->mpmu_base,
+				ARRAY_SIZE(mpmu_gate_clks));
 }
 
 static DEFINE_SPINLOCK(uart0_lock);
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 11/13] clk: mmp2: Add support for power islands
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

Apart from the clocks and resets, the PMU hardware also controls power
to peripherals that are on separate power islands. On MMP2, that's the
GC860 GPU and the SSPA audio interface, while on MMP3 also the camera
interface is on a separate island, along with the pair of GC2000 and GC300
GPUs and the SSPA.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>

---
Changes since v2:
- Use lowercase names for power domain names
- Fix the audio domain reset mask

 arch/arm/mach-mmp/Kconfig     |   2 +
 drivers/clk/mmp/Makefile      |   2 +-
 drivers/clk/mmp/clk-of-mmp2.c |  42 +++++++++++++
 drivers/clk/mmp/clk.h         |  10 +++
 drivers/clk/mmp/pwr-island.c  | 115 ++++++++++++++++++++++++++++++++++
 5 files changed, 170 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/pwr-island.c

diff --git a/arch/arm/mach-mmp/Kconfig b/arch/arm/mach-mmp/Kconfig
index 6fe1550f43ec..0dd999212944 100644
--- a/arch/arm/mach-mmp/Kconfig
+++ b/arch/arm/mach-mmp/Kconfig
@@ -124,6 +124,8 @@ config MACH_MMP2_DT
 	select PINCTRL_SINGLE
 	select ARCH_HAS_RESET_CONTROLLER
 	select CPU_PJ4
+	select PM_GENERIC_DOMAINS if PM
+	select PM_GENERIC_DOMAINS_OF if PM && OF
 	help
 	  Include support for Marvell MMP2 based platforms using
 	  the device tree.
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 14dc8a8a9d08..f9fab883a13b 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -8,7 +8,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 
 obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
-obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o
+obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index c686c16fca82..67208aea94c5 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -17,8 +17,10 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 
 #include <dt-bindings/clock/marvell,mmp2.h>
+#include <dt-bindings/power/marvell,mmp2.h>
 
 #include "clk.h"
 #include "reset.h"
@@ -63,6 +65,7 @@
 #define APMU_USBHSIC1	0xfc
 #define APMU_GPU	0xcc
 #define APMU_AUDIO	0x10c
+#define APMU_CAMERA	0x1fc
 
 #define MPMU_FCCR		0x8
 #define MPMU_POSR		0x10
@@ -86,6 +89,8 @@ enum mmp2_clk_model {
 struct mmp2_clk_unit {
 	struct mmp_clk_unit unit;
 	enum mmp2_clk_model model;
+	struct genpd_onecell_data pd_data;
+	struct generic_pm_domain *pm_domains[MMP2_NR_POWER_DOMAINS];
 	void __iomem *mpmu_base;
 	void __iomem *apmu_base;
 	void __iomem *apbc_base;
@@ -473,6 +478,41 @@ static void mmp2_clk_reset_init(struct device_node *np,
 	mmp_clk_reset_register(np, cells, nr_resets);
 }
 
+static void mmp2_pm_domain_init(struct device_node *np,
+				struct mmp2_clk_unit *pxa_unit)
+{
+	if (pxa_unit->model == CLK_MODEL_MMP3) {
+		pxa_unit->pm_domains[MMP2_POWER_DOMAIN_GPU]
+			= mmp_pm_domain_register("gpu",
+				pxa_unit->apmu_base + APMU_GPU,
+				0x0600, 0x40003, 0x18000c, 0, &gpu_lock);
+	} else {
+		pxa_unit->pm_domains[MMP2_POWER_DOMAIN_GPU]
+			= mmp_pm_domain_register("gpu",
+				pxa_unit->apmu_base + APMU_GPU,
+				0x8600, 0x00003, 0x00000c,
+				MMP_PM_DOMAIN_NO_DISABLE, &gpu_lock);
+	}
+	pxa_unit->pd_data.num_domains++;
+
+	pxa_unit->pm_domains[MMP2_POWER_DOMAIN_AUDIO]
+		= mmp_pm_domain_register("audio",
+			pxa_unit->apmu_base + APMU_AUDIO,
+			0x600, 0x2, 0, 0, &audio_lock);
+	pxa_unit->pd_data.num_domains++;
+
+	if (pxa_unit->model == CLK_MODEL_MMP3) {
+		pxa_unit->pm_domains[MMP3_POWER_DOMAIN_CAMERA]
+			= mmp_pm_domain_register("camera",
+				pxa_unit->apmu_base + APMU_CAMERA,
+				0x600, 0, 0, 0, NULL);
+		pxa_unit->pd_data.num_domains++;
+	}
+
+	pxa_unit->pd_data.domains = pxa_unit->pm_domains;
+	of_genpd_add_provider_onecell(np, &pxa_unit->pd_data);
+}
+
 static void __init mmp2_clk_init(struct device_node *np)
 {
 	struct mmp2_clk_unit *pxa_unit;
@@ -504,6 +544,8 @@ static void __init mmp2_clk_init(struct device_node *np)
 		goto unmap_apmu_region;
 	}
 
+	mmp2_pm_domain_init(np, pxa_unit);
+
 	mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS);
 
 	mmp2_main_clk_init(pxa_unit);
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 369a09256e2f..55ac05379781 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -3,6 +3,7 @@
 #define __MACH_MMP_CLK_H
 
 #include <linux/clk-provider.h>
+#include <linux/pm_domain.h>
 #include <linux/clkdev.h>
 
 #define APBC_NO_BUS_CTRL	BIT(0)
@@ -252,4 +253,13 @@ void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
 		int nr_clks);
 void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
 		struct clk *clk);
+
+/* Power islands */
+#define MMP_PM_DOMAIN_NO_DISABLE		BIT(0)
+
+struct generic_pm_domain *mmp_pm_domain_register(const char *name,
+		void __iomem *reg,
+		u32 power_on, u32 reset, u32 clock_enable,
+		unsigned int flags, spinlock_t *lock);
+
 #endif
diff --git a/drivers/clk/mmp/pwr-island.c b/drivers/clk/mmp/pwr-island.c
new file mode 100644
index 000000000000..ab57c0e995c1
--- /dev/null
+++ b/drivers/clk/mmp/pwr-island.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MMP PMU power island support
+ *
+ * Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
+ */
+
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include "clk.h"
+
+#define to_mmp_pm_domain(genpd) container_of(genpd, struct mmp_pm_domain, genpd)
+
+struct mmp_pm_domain {
+	struct generic_pm_domain genpd;
+	void __iomem *reg;
+	spinlock_t *lock;
+	u32 power_on;
+	u32 reset;
+	u32 clock_enable;
+	unsigned int flags;
+};
+
+static int mmp_pm_domain_power_on(struct generic_pm_domain *genpd)
+{
+	struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);
+	unsigned long flags = 0;
+	u32 val;
+
+	if (pm_domain->lock)
+		spin_lock_irqsave(pm_domain->lock, flags);
+
+	val = readl(pm_domain->reg);
+
+	/* Turn on the power island */
+	val |= pm_domain->power_on;
+	writel(val, pm_domain->reg);
+
+	/* Disable isolation */
+	val |= 0x100;
+	writel(val, pm_domain->reg);
+
+	/* Some blocks need to be reset after a power up */
+	if (pm_domain->reset || pm_domain->clock_enable) {
+		u32 after_power_on = val;
+
+		val &= ~pm_domain->reset;
+		writel(val, pm_domain->reg);
+
+		val |= pm_domain->clock_enable;
+		writel(val, pm_domain->reg);
+
+		val |= pm_domain->reset;
+		writel(val, pm_domain->reg);
+
+		writel(after_power_on, pm_domain->reg);
+	}
+
+	if (pm_domain->lock)
+		spin_unlock_irqrestore(pm_domain->lock, flags);
+
+	return 0;
+}
+
+static int mmp_pm_domain_power_off(struct generic_pm_domain *genpd)
+{
+	struct mmp_pm_domain *pm_domain = to_mmp_pm_domain(genpd);
+	unsigned long flags = 0;
+	u32 val;
+
+	if (pm_domain->flags & MMP_PM_DOMAIN_NO_DISABLE)
+		return 0;
+
+	if (pm_domain->lock)
+		spin_lock_irqsave(pm_domain->lock, flags);
+
+	/* Turn off and isolate the the power island. */
+	val = readl(pm_domain->reg);
+	val &= ~pm_domain->power_on;
+	val &= ~0x100;
+	writel(val, pm_domain->reg);
+
+	if (pm_domain->lock)
+		spin_unlock_irqrestore(pm_domain->lock, flags);
+
+	return 0;
+}
+
+struct generic_pm_domain *mmp_pm_domain_register(const char *name,
+		void __iomem *reg,
+		u32 power_on, u32 reset, u32 clock_enable,
+		unsigned int flags, spinlock_t *lock)
+{
+	struct mmp_pm_domain *pm_domain;
+
+	pm_domain = kzalloc(sizeof(*pm_domain), GFP_KERNEL);
+	if (!pm_domain)
+		return ERR_PTR(-ENOMEM);
+
+	pm_domain->reg = reg;
+	pm_domain->power_on = power_on;
+	pm_domain->reset = reset;
+	pm_domain->clock_enable = clock_enable;
+	pm_domain->flags = flags;
+	pm_domain->lock = lock;
+
+	pm_genpd_init(&pm_domain->genpd, NULL, true);
+	pm_domain->genpd.name = name;
+	pm_domain->genpd.power_on = mmp_pm_domain_power_on;
+	pm_domain->genpd.power_off = mmp_pm_domain_power_off;
+
+	return &pm_domain->genpd;
+}
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 00/13] MMP2 Clock Updates (GPU, Audio, Power Islands)
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel

Hi,

please consider applying this patch set. It contains patches that were
previously sent in two separate series ("clk: mmp2: Enable Audio and GPU
on MMP2 and MMP3" and "MMP2 Audio clock controller driver") but given
there are some dependencies, it seems more practical to merge them into
one.

The ultimate goal it so make GPU and Audio clocks work on MMP2 and
MMP3-based machines.

This patch set aims to address issues pointed out in review of v1 of the
clock controller set.

Ther first few patches add the clocks for the audio block, setting a few
things beforehands:

  [01/13] clk: mmp: frac: Do not lose last 4 digits of precision
  [02/13] clk: mmp: frac: Allow setting bits other than the
  [03/13] dt-bindings: marvell,mmp2: Add clock id for the I2S
  [04/13] dt-bindings: marvell,mmp2: Add clock id for the Audio
  [05/13] clk: mmp2: Move thermal register defines up a bit
  [06/13] clk: mmp2: Rename mmp2_pll_init() to
  [07/13] clk: mmp2: Add the I2S clocks
  [08/13] clk: mmp2: Add the audio clock

Then the support for controlling the power to Audio, GPU and (on a MMP3)
Camera blocks is added. The power is controlled by the same hardware
(the PMUs) as one that drives the clocks:

  [09/13] dt-bindings: clock: Make marvell,mmp2-clock a power
  [10/13] dt-bindings: marvell,mmp2: Add ids for the power
  [11/13] clk: mmp2: Add support for power islands

Finally a driver for the clocks used by I2S is added. The controller is
separate from a PMUs and lives in the audio block along with a pair of
I2S controllers:

  [12/13] dt-bindings: clock: Add Marvell MMP Audio Clock
  [13/13] clk: mmp2: Add audio clock controller driver

Tested the GPU and Audio on an OLPC XO-1.75 laptop (MMP2).

Thanks,
Lubo



^ permalink raw reply

* [PATCH v3 10/13] dt-bindings: marvell,mmp2: Add ids for the power domains
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel, Rob Herring
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

On MMP2 the audio and GPU blocks are on separate power islands. On MMP3
the camera block's power is also controlled separately.

Add the numbers that we could use to refer to the power domains for
respective power islands from the device tree.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Acked-by: Rob Herring <robh@kernel.org>

---
Changes since v1:
- Rob's ack

 include/dt-bindings/power/marvell,mmp2.h | 11 +++++++++++
 1 file changed, 11 insertions(+)
 create mode 100644 include/dt-bindings/power/marvell,mmp2.h

diff --git a/include/dt-bindings/power/marvell,mmp2.h b/include/dt-bindings/power/marvell,mmp2.h
new file mode 100644
index 000000000000..c53d2b3e1057
--- /dev/null
+++ b/include/dt-bindings/power/marvell,mmp2.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DTS_MARVELL_MMP2_POWER_H
+#define __DTS_MARVELL_MMP2_POWER_H
+
+#define MMP2_POWER_DOMAIN_GPU		0
+#define MMP2_POWER_DOMAIN_AUDIO		1
+#define MMP3_POWER_DOMAIN_CAMERA	2
+
+#define MMP2_NR_POWER_DOMAINS		3
+
+#endif
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 03/13] dt-bindings: marvell,mmp2: Add clock id for the I2S clocks
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel, Rob Herring
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

There are two of these on a MMP2.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Acked-by: Rob Herring <robh@kernel.org>

---
Changes since v1:
- Rob's ack

 include/dt-bindings/clock/marvell,mmp2.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/dt-bindings/clock/marvell,mmp2.h b/include/dt-bindings/clock/marvell,mmp2.h
index 06bb7fe4c62f..5b083f42811e 100644
--- a/include/dt-bindings/clock/marvell,mmp2.h
+++ b/include/dt-bindings/clock/marvell,mmp2.h
@@ -29,6 +29,8 @@
 #define MMP3_CLK_PLL1_P			28
 #define MMP3_CLK_PLL2_P			29
 #define MMP3_CLK_PLL3			30
+#define MMP2_CLK_I2S0			31
+#define MMP2_CLK_I2S1			32
 
 /* apb periphrals */
 #define MMP2_CLK_TWSI0			60
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 12/13] dt-bindings: clock: Add Marvell MMP Audio Clock Controller binding
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

This describes the bindings for a controller that generates master and bit
clocks for the I2S interface.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>

---
Changes since v1:
- Fix commit message wording
- Define MMP2_CLK_AUDIO_NR_CLKS
- Make clock ids start at 0, not 1
- Fix dt-bindings/clock/marvell,mmp2-audio.h file name
- Rename node from "clocks" to "clock-controller"

 .../clock/marvell,mmp2-audio-clock.yaml       | 74 +++++++++++++++++++
 .../dt-bindings/clock/marvell,mmp2-audio.h    | 10 +++
 2 files changed, 84 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,mmp2-audio-clock.yaml
 create mode 100644 include/dt-bindings/clock/marvell,mmp2-audio.h

diff --git a/Documentation/devicetree/bindings/clock/marvell,mmp2-audio-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,mmp2-audio-clock.yaml
new file mode 100644
index 000000000000..ab6e82d1d3a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,mmp2-audio-clock.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/marvell,mmp2-audio-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Marvell MMP2 Audio Clock Controller
+
+maintainers:
+  - Lubomir Rintel <lkundrak@v3.sk>
+
+description: |
+  The audio clock controller generates and supplies the clocks to the audio
+  codec.
+
+  Each clock is assigned an identifier and client nodes use this identifier
+  to specify the clock which they consume.
+
+  All these identifiers could be found in
+  <dt-bindings/clock/marvell,mmp2-audio.h>.
+
+properties:
+  compatible:
+    enum:
+      - marvell,mmp2-audio-clock
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    items:
+      - description: Audio subsystem clock
+      - description: The crystal oscillator clock
+      - description: First I2S clock
+      - description: Second I2S clock
+
+  clock-names:
+    items:
+      - const: audio
+      - const: vctcxo
+      - const: i2s0
+      - const: i2s1
+
+  '#clock-cells':
+    const: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/marvell,mmp2-audio.h>
+    #include <dt-bindings/power/marvell,mmp2.h>
+
+    clock-controller@d42a0c30 {
+      compatible = "marvell,mmp2-audio-clock";
+      reg = <0xd42a0c30 0x10>;
+      clock-names = "audio", "vctcxo", "i2s0", "i2s1";
+      clocks = <&soc_clocks MMP2_CLK_AUDIO>,
+               <&soc_clocks MMP2_CLK_VCTCXO>,
+               <&soc_clocks MMP2_CLK_I2S0>,
+               <&soc_clocks MMP2_CLK_I2S1>;
+      power-domains = <&soc_clocks MMP2_POWER_DOMAIN_AUDIO>;
+      #clock-cells = <1>;
+    };
diff --git a/include/dt-bindings/clock/marvell,mmp2-audio.h b/include/dt-bindings/clock/marvell,mmp2-audio.h
new file mode 100644
index 000000000000..20664776f497
--- /dev/null
+++ b/include/dt-bindings/clock/marvell,mmp2-audio.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) */
+#ifndef __DT_BINDINGS_CLOCK_MARVELL_MMP2_AUDIO_H
+#define __DT_BINDINGS_CLOCK_MARVELL_MMP2_AUDIO_H
+
+#define MMP2_CLK_AUDIO_SYSCLK		0
+#define MMP2_CLK_AUDIO_SSPA0		1
+#define MMP2_CLK_AUDIO_SSPA1		2
+
+#define MMP2_CLK_AUDIO_NR_CLKS		3
+#endif
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 04/13] dt-bindings: marvell,mmp2: Add clock id for the Audio clock
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel, Rob Herring
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

This clocks the Audio block.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
Acked-by: Rob Herring <robh@kernel.org>

---
Changes since v1:
- Rob's ack

 include/dt-bindings/clock/marvell,mmp2.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/dt-bindings/clock/marvell,mmp2.h b/include/dt-bindings/clock/marvell,mmp2.h
index 5b083f42811e..87f5ad5df72f 100644
--- a/include/dt-bindings/clock/marvell,mmp2.h
+++ b/include/dt-bindings/clock/marvell,mmp2.h
@@ -89,6 +89,7 @@
 #define MMP3_CLK_GPU_3D			MMP2_CLK_GPU_3D
 #define MMP3_CLK_GPU_2D			125
 #define MMP3_CLK_SDH4			126
+#define MMP2_CLK_AUDIO			127
 
 #define MMP2_NR_CLKS			200
 #endif
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 06/13] clk: mmp2: Rename mmp2_pll_init() to mmp2_main_clk_init()
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

This is a trivial rename for a routine that registers more clock sources
than the PLLs -- there's also a XO.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
 drivers/clk/mmp/clk-of-mmp2.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 524574187c17..ac88ea99b7c6 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -139,7 +139,7 @@ static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
 	{.num = 3521, .den = 689},	/*19.23MHZ */
 };
 
-static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
+static void mmp2_main_clk_init(struct mmp2_clk_unit *pxa_unit)
 {
 	struct clk *clk;
 	struct mmp_clk_unit *unit = &pxa_unit->unit;
@@ -456,7 +456,7 @@ static void __init mmp2_clk_init(struct device_node *np)
 
 	mmp_clk_init(np, &pxa_unit->unit, MMP2_NR_CLKS);
 
-	mmp2_pll_init(pxa_unit);
+	mmp2_main_clk_init(pxa_unit);
 
 	mmp2_apb_periph_clk_init(pxa_unit);
 
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 02/13] clk: mmp: frac: Allow setting bits other than the numerator/denominator
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

For the I2S fractional clocks, there are more bits that need to be set
for the clock to run. Their actual meaning is unknown.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
 drivers/clk/mmp/clk-frac.c | 3 +++
 drivers/clk/mmp/clk.h      | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index ed9928f5bdc7..48f592bd633d 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -148,7 +148,10 @@ static int clk_factor_init(struct clk_hw *hw)
 		val &= ~(masks->den_mask << masks->den_shift);
 		val |= (factor->ftbl[0].den & masks->den_mask) <<
 			masks->den_shift;
+	}
 
+	if (!(val & masks->enable_mask) || i >= factor->ftbl_cnt) {
+		val |= masks->enable_mask;
 		writel(val, factor->base);
 	}
 
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 20dc1e5dd756..369a09256e2f 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -16,6 +16,7 @@ struct mmp_clk_factor_masks {
 	unsigned int den_mask;
 	unsigned int num_shift;
 	unsigned int den_shift;
+	unsigned int enable_mask;
 };
 
 struct mmp_clk_factor_tbl {
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 13/13] clk: mmp2: Add audio clock controller driver
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

This is a driver for a block that generates master and bit clocks for
the I2S interface. It's separate from the PMUs that generate clocks for
the peripherals.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>

---
Changes since v1:
- Utilize runtime PM along with pm_clk to enable/disable clocks
- Rework the driver to use regular clk_mux, clk_div and clk_gate;
  save/restore the registers on PM suspend/resume
- Use #defines for regiser offsets instead of an enum
- Constify some structs
- Remove an extra comma afer a sentinel
- Remove an line break before module_platform_driver()
- Replace __raw_readl()/__raw_writel() with readl()/writel()
- Use clk_add_hw_provider() instead of clk_add_provider()
- Utilize clk_parent_data[] with .fw_name instead of clk_hw[] with
  __clk_get_hw(devm_clk_get()) to refer to parent clocks from outside the
  audio clock controller

 drivers/clk/Kconfig         |   6 +
 drivers/clk/mmp/Makefile    |   1 +
 drivers/clk/mmp/clk-audio.c | 443 ++++++++++++++++++++++++++++++++++++
 3 files changed, 450 insertions(+)
 create mode 100644 drivers/clk/mmp/clk-audio.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 5401d4a00eba..f0a01c439789 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -341,6 +341,12 @@ config COMMON_CLK_MMP2
 	help
 	  Support for Marvell MMP2 and MMP3 SoC clocks
 
+config COMMON_CLK_MMP2_AUDIO
+        tristate "Clock driver for MMP2 Audio subsystem"
+        depends on COMMON_CLK_MMP2 || COMPILE_TEST
+        help
+          This driver supports clocks for Audio subsystem on MMP2 SoC.
+
 config COMMON_CLK_BD718XX
 	tristate "Clock driver for 32K clk gates on ROHM PMICs"
 	depends on MFD_ROHM_BD718XX || MFD_ROHM_BD70528 || MFD_ROHM_BD71828
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index f9fab883a13b..cbcc2f8430a2 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 
 obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
 obj-$(CONFIG_COMMON_CLK_MMP2) += clk-of-mmp2.o clk-pll.o pwr-island.o
+obj-$(CONFIG_COMMON_CLK_MMP2_AUDIO) += clk-audio.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-audio.c b/drivers/clk/mmp/clk-audio.c
new file mode 100644
index 000000000000..eea69d498bd2
--- /dev/null
+++ b/drivers/clk/mmp/clk-audio.c
@@ -0,0 +1,443 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * MMP Audio Clock Controller driver
+ *
+ * Copyright (C) 2020 Lubomir Rintel <lkundrak@v3.sk>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <dt-bindings/clock/marvell,mmp2-audio.h>
+
+/* Audio Controller Registers */
+#define SSPA_AUD_CTRL				0x04
+#define SSPA_AUD_PLL_CTRL0			0x08
+#define SSPA_AUD_PLL_CTRL1			0x0c
+
+/* SSPA Audio Control Register */
+#define SSPA_AUD_CTRL_SYSCLK_SHIFT		0
+#define SSPA_AUD_CTRL_SYSCLK_DIV_SHIFT		1
+#define SSPA_AUD_CTRL_SSPA0_MUX_SHIFT		7
+#define SSPA_AUD_CTRL_SSPA0_SHIFT		8
+#define SSPA_AUD_CTRL_SSPA0_DIV_SHIFT		9
+#define SSPA_AUD_CTRL_SSPA1_SHIFT		16
+#define SSPA_AUD_CTRL_SSPA1_DIV_SHIFT		17
+#define SSPA_AUD_CTRL_SSPA1_MUX_SHIFT		23
+#define SSPA_AUD_CTRL_DIV_MASK			0x7e
+
+/* SSPA Audio PLL Control 0 Register */
+#define SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO_MASK (0x7 << 28)
+#define SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(x)	((x) << 28)
+#define SSPA_AUD_PLL_CTRL0_FRACT_MASK		(0xfffff << 8)
+#define SSPA_AUD_PLL_CTRL0_FRACT(x)		((x) << 8)
+#define SSPA_AUD_PLL_CTRL0_ENA_DITHER		(1 << 7)
+#define SSPA_AUD_PLL_CTRL0_ICP_2UA		(0 << 5)
+#define SSPA_AUD_PLL_CTRL0_ICP_5UA		(1 << 5)
+#define SSPA_AUD_PLL_CTRL0_ICP_7UA		(2 << 5)
+#define SSPA_AUD_PLL_CTRL0_ICP_10UA		(3 << 5)
+#define SSPA_AUD_PLL_CTRL0_DIV_FBCCLK_MASK	(0x3 << 3)
+#define SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(x)	((x) << 3)
+#define SSPA_AUD_PLL_CTRL0_DIV_MCLK_MASK	(0x1 << 2)
+#define SSPA_AUD_PLL_CTRL0_DIV_MCLK(x)		((x) << 2)
+#define SSPA_AUD_PLL_CTRL0_PD_OVPROT_DIS	(1 << 1)
+#define SSPA_AUD_PLL_CTRL0_PU			(1 << 0)
+
+/* SSPA Audio PLL Control 1 Register */
+#define SSPA_AUD_PLL_CTRL1_SEL_FAST_CLK		(1 << 24)
+#define SSPA_AUD_PLL_CTRL1_CLK_SEL_MASK		(1 << 11)
+#define SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL	(1 << 11)
+#define SSPA_AUD_PLL_CTRL1_CLK_SEL_VCXO		(0 << 11)
+#define SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN_MASK (0x7ff << 0)
+#define SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(x)	((x) << 0)
+
+struct mmp2_audio_clk {
+	void __iomem *mmio_base;
+
+	struct clk_hw audio_pll_hw;
+	struct clk_mux sspa_mux;
+	struct clk_mux sspa1_mux;
+	struct clk_divider sysclk_div;
+	struct clk_divider sspa0_div;
+	struct clk_divider sspa1_div;
+	struct clk_gate sysclk_gate;
+	struct clk_gate sspa0_gate;
+	struct clk_gate sspa1_gate;
+
+	u32 aud_ctrl;
+	u32 aud_pll_ctrl0;
+	u32 aud_pll_ctrl1;
+
+	spinlock_t lock;
+
+	/* Must be last */
+	struct clk_hw_onecell_data clk_data;
+};
+
+static const struct {
+	unsigned long parent_rate;
+	unsigned long freq_vco;
+	unsigned char mclk;
+	unsigned char fbcclk;
+	unsigned short fract;
+} predivs[] = {
+	{ 26000000, 135475200, 0, 0, 0x8a18 },
+	{ 26000000, 147456000, 0, 1, 0x0da1 },
+	{ 38400000, 135475200, 1, 2, 0x8208 },
+	{ 38400000, 147456000, 1, 3, 0xaaaa },
+};
+
+static const struct {
+	unsigned char divisor;
+	unsigned char modulo;
+	unsigned char pattern;
+} postdivs[] = {
+	{   1,	3,  0, },
+	{   2,	5,  0, },
+	{   4,	0,  0, },
+	{   6,	1,  1, },
+	{   8,	1,  0, },
+	{   9,	1,  2, },
+	{  12,	2,  1, },
+	{  16,	2,  0, },
+	{  18,	2,  2, },
+	{  24,	4,  1, },
+	{  36,	4,  2, },
+	{  48,	6,  1, },
+	{  72,	6,  2, },
+};
+
+static unsigned long audio_pll_recalc_rate(struct clk_hw *hw,
+					   unsigned long parent_rate)
+{
+	struct mmp2_audio_clk *priv = container_of(hw, struct mmp2_audio_clk, audio_pll_hw);
+	unsigned int prediv;
+	unsigned int postdiv;
+	u32 aud_pll_ctrl0;
+	u32 aud_pll_ctrl1;
+
+	aud_pll_ctrl0 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL0);
+	aud_pll_ctrl0 &= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO_MASK |
+			 SSPA_AUD_PLL_CTRL0_FRACT_MASK |
+			 SSPA_AUD_PLL_CTRL0_ENA_DITHER |
+			 SSPA_AUD_PLL_CTRL0_DIV_FBCCLK_MASK |
+			 SSPA_AUD_PLL_CTRL0_DIV_MCLK_MASK |
+			 SSPA_AUD_PLL_CTRL0_PU;
+
+	aud_pll_ctrl1 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL1);
+	aud_pll_ctrl1 &= SSPA_AUD_PLL_CTRL1_CLK_SEL_MASK |
+			 SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN_MASK;
+
+	for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
+		if (predivs[prediv].parent_rate != parent_rate)
+			continue;
+		for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
+			unsigned long freq;
+			u32 val;
+
+			val = SSPA_AUD_PLL_CTRL0_ENA_DITHER;
+			val |= SSPA_AUD_PLL_CTRL0_PU;
+			val |= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(postdivs[postdiv].modulo);
+			val |= SSPA_AUD_PLL_CTRL0_FRACT(predivs[prediv].fract);
+			val |= SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(predivs[prediv].fbcclk);
+			val |= SSPA_AUD_PLL_CTRL0_DIV_MCLK(predivs[prediv].mclk);
+			if (val != aud_pll_ctrl0)
+				continue;
+
+			val = SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL;
+			val |= SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(postdivs[postdiv].pattern);
+			if (val != aud_pll_ctrl1)
+				continue;
+
+			freq = predivs[prediv].freq_vco;
+			freq /= postdivs[postdiv].divisor;
+			return freq;
+		}
+	}
+
+	return 0;
+}
+
+static long audio_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long *parent_rate)
+{
+	unsigned int prediv;
+	unsigned int postdiv;
+	long rounded = 0;
+
+	for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
+		if (predivs[prediv].parent_rate != *parent_rate)
+			continue;
+		for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
+			long freq = predivs[prediv].freq_vco;
+
+			freq /= postdivs[postdiv].divisor;
+			if (freq == rate)
+				return rate;
+			if (freq < rate)
+				continue;
+			if (rounded && freq > rounded)
+				continue;
+			rounded = freq;
+		}
+	}
+
+	return rounded;
+}
+
+static int audio_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long parent_rate)
+{
+	struct mmp2_audio_clk *priv = container_of(hw, struct mmp2_audio_clk, audio_pll_hw);
+	unsigned int prediv;
+	unsigned int postdiv;
+	unsigned long val;
+
+	for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
+		if (predivs[prediv].parent_rate != parent_rate)
+			continue;
+
+		for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
+			if (rate * postdivs[postdiv].divisor != predivs[prediv].freq_vco)
+				continue;
+
+			val = SSPA_AUD_PLL_CTRL0_ENA_DITHER;
+			val |= SSPA_AUD_PLL_CTRL0_PU;
+			val |= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(postdivs[postdiv].modulo);
+			val |= SSPA_AUD_PLL_CTRL0_FRACT(predivs[prediv].fract);
+			val |= SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(predivs[prediv].fbcclk);
+			val |= SSPA_AUD_PLL_CTRL0_DIV_MCLK(predivs[prediv].mclk);
+			writel(val, priv->mmio_base + SSPA_AUD_PLL_CTRL0);
+
+			val = SSPA_AUD_PLL_CTRL1_CLK_SEL_AUDIO_PLL;
+			val |= SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN(postdivs[postdiv].pattern);
+			writel(val, priv->mmio_base + SSPA_AUD_PLL_CTRL1);
+
+			return 0;
+		}
+	}
+
+	return -ERANGE;
+}
+
+static const struct clk_ops audio_pll_ops = {
+	.recalc_rate = audio_pll_recalc_rate,
+	.round_rate = audio_pll_round_rate,
+	.set_rate = audio_pll_set_rate,
+};
+
+static int register_clocks(struct mmp2_audio_clk *priv, struct device *dev)
+{
+	const struct clk_parent_data sspa_mux_parents[] = {
+		{ .hw = &priv->audio_pll_hw },
+		{ .fw_name = "i2s0" },
+	};
+	const struct clk_parent_data sspa1_mux_parents[] = {
+		{ .hw = &priv->audio_pll_hw },
+		{ .fw_name = "i2s1" },
+	};
+	int ret;
+
+	priv->audio_pll_hw.init = CLK_HW_INIT_FW_NAME("audio_pll",
+				"vctcxo", &audio_pll_ops,
+				CLK_SET_RATE_PARENT);
+	ret = devm_clk_hw_register(dev, &priv->audio_pll_hw);
+	if (ret)
+		return ret;
+
+	priv->sspa_mux.hw.init = CLK_HW_INIT_PARENTS_DATA("sspa_mux",
+				sspa_mux_parents, &clk_mux_ops,
+				CLK_SET_RATE_PARENT);
+	priv->sspa_mux.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sspa_mux.mask = 1;
+	priv->sspa_mux.shift = SSPA_AUD_CTRL_SSPA0_MUX_SHIFT;
+	ret = devm_clk_hw_register(dev, &priv->sspa_mux.hw);
+	if (ret)
+		return ret;
+
+	priv->sysclk_div.hw.init = CLK_HW_INIT_HW("sys_div",
+				&priv->sspa_mux.hw, &clk_divider_ops,
+				CLK_SET_RATE_PARENT);
+	priv->sysclk_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sysclk_div.shift = SSPA_AUD_CTRL_SYSCLK_DIV_SHIFT;
+	priv->sysclk_div.width = 6;
+	priv->sysclk_div.flags = CLK_DIVIDER_ONE_BASED;
+	priv->sysclk_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
+	priv->sysclk_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
+	ret = devm_clk_hw_register(dev, &priv->sysclk_div.hw);
+	if (ret)
+		return ret;
+
+	priv->sysclk_gate.hw.init = CLK_HW_INIT_HW("sys_clk",
+				&priv->sysclk_div.hw, &clk_gate_ops,
+				CLK_SET_RATE_PARENT);
+	priv->sysclk_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sysclk_gate.bit_idx = SSPA_AUD_CTRL_SYSCLK_SHIFT;
+	ret = devm_clk_hw_register(dev, &priv->sysclk_gate.hw);
+	if (ret)
+		return ret;
+
+	priv->sspa0_div.hw.init = CLK_HW_INIT_HW("sspa0_div",
+				&priv->sspa_mux.hw, &clk_divider_ops, 0);
+	priv->sspa0_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sspa0_div.shift = SSPA_AUD_CTRL_SSPA0_DIV_SHIFT;
+	priv->sspa0_div.width = 6;
+	priv->sspa0_div.flags = CLK_DIVIDER_ONE_BASED;
+	priv->sspa0_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
+	priv->sspa0_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
+	ret = devm_clk_hw_register(dev, &priv->sspa0_div.hw);
+	if (ret)
+		return ret;
+
+	priv->sspa0_gate.hw.init = CLK_HW_INIT_HW("sspa0_clk",
+				&priv->sspa0_div.hw, &clk_gate_ops,
+				CLK_SET_RATE_PARENT);
+	priv->sspa0_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sspa0_gate.bit_idx = SSPA_AUD_CTRL_SSPA0_SHIFT;
+	ret = devm_clk_hw_register(dev, &priv->sspa0_gate.hw);
+	if (ret)
+		return ret;
+
+	priv->sspa1_mux.hw.init = CLK_HW_INIT_PARENTS_DATA("sspa1_mux",
+				sspa1_mux_parents, &clk_mux_ops,
+				CLK_SET_RATE_PARENT);
+	priv->sspa1_mux.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sspa1_mux.mask = 1;
+	priv->sspa1_mux.shift = SSPA_AUD_CTRL_SSPA1_MUX_SHIFT;
+	ret = devm_clk_hw_register(dev, &priv->sspa1_mux.hw);
+	if (ret)
+		return ret;
+
+	priv->sspa1_div.hw.init = CLK_HW_INIT_HW("sspa1_div",
+				&priv->sspa1_mux.hw, &clk_divider_ops, 0);
+	priv->sspa1_div.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sspa1_div.shift = SSPA_AUD_CTRL_SSPA1_DIV_SHIFT;
+	priv->sspa1_div.width = 6;
+	priv->sspa1_div.flags = CLK_DIVIDER_ONE_BASED;
+	priv->sspa1_div.flags |= CLK_DIVIDER_ROUND_CLOSEST;
+	priv->sspa1_div.flags |= CLK_DIVIDER_ALLOW_ZERO;
+	ret = devm_clk_hw_register(dev, &priv->sspa1_div.hw);
+	if (ret)
+		return ret;
+
+	priv->sspa1_gate.hw.init = CLK_HW_INIT_HW("sspa1_clk",
+				&priv->sspa1_div.hw, &clk_gate_ops,
+				CLK_SET_RATE_PARENT);
+	priv->sspa1_gate.reg = priv->mmio_base + SSPA_AUD_CTRL;
+	priv->sspa1_gate.bit_idx = SSPA_AUD_CTRL_SSPA1_SHIFT;
+	ret = devm_clk_hw_register(dev, &priv->sspa1_gate.hw);
+	if (ret)
+		return ret;
+
+	priv->clk_data.hws[MMP2_CLK_AUDIO_SYSCLK] = &priv->sysclk_gate.hw;
+	priv->clk_data.hws[MMP2_CLK_AUDIO_SSPA0] = &priv->sspa0_gate.hw;
+	priv->clk_data.hws[MMP2_CLK_AUDIO_SSPA1] = &priv->sspa1_gate.hw;
+	priv->clk_data.num = MMP2_CLK_AUDIO_NR_CLKS;
+
+	return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+				      &priv->clk_data);
+}
+
+static int mmp2_audio_clk_probe(struct platform_device *pdev)
+{
+	struct mmp2_audio_clk *priv;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev,
+			    struct_size(priv, clk_data.hws,
+					MMP2_CLK_AUDIO_NR_CLKS),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	spin_lock_init(&priv->lock);
+	platform_set_drvdata(pdev, priv);
+
+	priv->mmio_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->mmio_base))
+		return PTR_ERR(priv->mmio_base);
+
+	pm_runtime_enable(&pdev->dev);
+	ret = pm_clk_create(&pdev->dev);
+	if (ret)
+		goto disable_pm_runtime;
+
+	ret = pm_clk_add(&pdev->dev, "audio");
+	if (ret)
+		goto destroy_pm_clk;
+
+	ret = register_clocks(priv, &pdev->dev);
+	if (ret)
+		goto destroy_pm_clk;
+
+	return 0;
+
+destroy_pm_clk:
+	pm_clk_destroy(&pdev->dev);
+disable_pm_runtime:
+	pm_runtime_disable(&pdev->dev);
+
+	return ret;
+}
+
+static int mmp2_audio_clk_remove(struct platform_device *pdev)
+{
+	pm_clk_destroy(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static int __maybe_unused mmp2_audio_clk_suspend(struct device *dev)
+{
+	struct mmp2_audio_clk *priv = dev_get_drvdata(dev);
+
+	priv->aud_ctrl = readl(priv->mmio_base + SSPA_AUD_CTRL);
+	priv->aud_pll_ctrl0 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL0);
+	priv->aud_pll_ctrl1 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL1);
+	pm_clk_suspend(dev);
+
+	return 0;
+}
+
+static int __maybe_unused mmp2_audio_clk_resume(struct device *dev)
+{
+	struct mmp2_audio_clk *priv = dev_get_drvdata(dev);
+
+	pm_clk_resume(dev);
+	writel(priv->aud_ctrl, priv->mmio_base + SSPA_AUD_CTRL);
+	writel(priv->aud_pll_ctrl0, priv->mmio_base + SSPA_AUD_PLL_CTRL0);
+	writel(priv->aud_pll_ctrl1, priv->mmio_base + SSPA_AUD_PLL_CTRL1);
+
+	return 0;
+}
+
+static const struct dev_pm_ops mmp2_audio_clk_pm_ops = {
+	SET_RUNTIME_PM_OPS(mmp2_audio_clk_suspend, mmp2_audio_clk_resume, NULL)
+};
+
+static const struct of_device_id mmp2_audio_clk_of_match[] = {
+	{ .compatible = "marvell,mmp2-audio-clock" },
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, mmp2_audio_clk_of_match);
+
+static struct platform_driver mmp2_audio_clk_driver = {
+	.driver = {
+		.name = "mmp2-audio-clock",
+		.of_match_table = of_match_ptr(mmp2_audio_clk_of_match),
+		.pm = &mmp2_audio_clk_pm_ops,
+	},
+	.probe = mmp2_audio_clk_probe,
+	.remove = mmp2_audio_clk_remove,
+};
+module_platform_driver(mmp2_audio_clk_driver);
+
+MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");
+MODULE_DESCRIPTION("Clock driver for MMP2 Audio subsystem");
+MODULE_LICENSE("GPL");
-- 
2.26.2


^ permalink raw reply related

* Re: [PATCH v2 2/3] bindings: sound: Add documentation for TI j721e EVM (CPB and IVI)
From: Rob Herring @ 2020-05-19 22:42 UTC (permalink / raw)
  To: Peter Ujfalusi; +Cc: broonie, lgirdwood, alsa-devel, devicetree, linux-kernel
In-Reply-To: <20200512131633.32668-3-peter.ujfalusi@ti.com>

On Tue, May 12, 2020 at 04:16:32PM +0300, Peter Ujfalusi wrote:
> The audio support on the Common Processor Board board is using
> pcm3168a codec connected to McASP10 serializers in parallel setup.
> 
> The Infotainment board plugs into the Common Processor Board, the support
> of the extension board is extending the CPB audio support by adding
> the two codecs on the expansion board.
> 
> The audio support on the Infotainment Expansion Board consists of McASP0
> connected to two pcm3168a codecs with dedicated set of serializers to each.
> The SCKI for pcm3168a is sourced from j721e AUDIO_REFCLK0 pin.

Would the audio graph card work for you on this? 

^ permalink raw reply

* [PATCH v3 09/13] dt-bindings: clock: Make marvell,mmp2-clock a power controller
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

This is a binding for the MMP2 power management units. As such apart from
providing the clocks, they also manage the power islands.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>

---
Changes since v2:
- Added this patch

 .../devicetree/bindings/clock/marvell,mmp2-clock.yaml        | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/clock/marvell,mmp2-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,mmp2-clock.yaml
index e2b6ac96bbcb..d68f0d196e7d 100644
--- a/Documentation/devicetree/bindings/clock/marvell,mmp2-clock.yaml
+++ b/Documentation/devicetree/bindings/clock/marvell,mmp2-clock.yaml
@@ -42,12 +42,16 @@ properties:
   '#reset-cells':
     const: 1
 
+  '#power-domain-cells':
+    const: 1
+
 required:
   - compatible
   - reg
   - reg-names
   - '#clock-cells'
   - '#reset-cells'
+  - '#power-domain-cells'
 
 additionalProperties: false
 
@@ -61,4 +65,5 @@ examples:
       reg-names = "mpmu", "apmu", "apbc";
       #clock-cells = <1>;
       #reset-cells = <1>;
+      #power-domain-cells = <1>;
     };
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 08/13] clk: mmp2: Add the audio clock
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

This clocks the Audio block.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
 drivers/clk/mmp/clk-of-mmp2.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index dcdff06a698a..c686c16fca82 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -62,6 +62,7 @@
 #define APMU_USBHSIC0	0xf8
 #define APMU_USBHSIC1	0xfc
 #define APMU_GPU	0xcc
+#define APMU_AUDIO	0x10c
 
 #define MPMU_FCCR		0x8
 #define MPMU_POSR		0x10
@@ -317,6 +318,8 @@ static u32 mmp2_gpu_bus_parent_table[] =         { 0x0000,   0x0020,   0x0030,
 static const char * const mmp3_gpu_bus_parent_names[] = {"pll1_4", "pll1_6", "pll1_2", "pll2_2"};
 static const char * const mmp3_gpu_gc_parent_names[] =  {"pll1",   "pll2",   "pll1_p", "pll2_p"};
 
+static DEFINE_SPINLOCK(audio_lock);
+
 static struct mmp_clk_mix_config ccic0_mix_config = {
 	.reg_info = DEFINE_MIX_REG_INFO(4, 17, 2, 6, 32),
 };
@@ -372,6 +375,7 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
 	{MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
 	{MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
 	{MMP2_CLK_GPU_BUS, "gpu_bus_clk", "gpu_bus_mux", CLK_SET_RATE_PARENT, APMU_GPU, 0xa, 0xa, 0x0, MMP_CLK_GATE_NEED_DELAY, &gpu_lock},
+	{MMP2_CLK_AUDIO, "audio_clk", "audio_mix_clk", CLK_SET_RATE_PARENT, APMU_AUDIO, 0x12, 0x12, 0x0, 0, &audio_lock},
 };
 
 static struct mmp_param_gate_clk mmp2_apmu_gate_clks[] = {
-- 
2.26.2


^ permalink raw reply related

* [PATCH v3 01/13] clk: mmp: frac: Do not lose last 4 digits of precision
From: Lubomir Rintel @ 2020-05-19 22:41 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Rob Herring, linux-clk, devicetree,
	linux-kernel, linux-arm-kernel, Lubomir Rintel
In-Reply-To: <20200519224151.2074597-1-lkundrak@v3.sk>

While calculating the output rate of a fractional divider clock, the
value is divided and multipled by 10000, discarding the least
significant digits -- presumably to fit the intermediate value within 32
bits.

The precision we're losing is, however, not insignificant for things like
I2S clock. Maybe also elsewhere, now that since commit ea56ad60260e ("clk:
mmp2: Stop pretending PLL outputs are constant") the parent rates are more
precise and no longer rounded to 10000s.

Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
 drivers/clk/mmp/clk-frac.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index fabc09aca6c4..ed9928f5bdc7 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -28,13 +28,15 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
 		unsigned long *prate)
 {
 	struct mmp_clk_factor *factor = to_clk_factor(hw);
-	unsigned long rate = 0, prev_rate;
+	u64 rate = 0, prev_rate;
 	int i;
 
 	for (i = 0; i < factor->ftbl_cnt; i++) {
 		prev_rate = rate;
-		rate = (((*prate / 10000) * factor->ftbl[i].den) /
-			(factor->ftbl[i].num * factor->masks->factor)) * 10000;
+		rate = *prate;
+		rate *= factor->ftbl[i].den;
+		do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+
 		if (rate > drate)
 			break;
 	}
@@ -54,6 +56,7 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 	struct mmp_clk_factor *factor = to_clk_factor(hw);
 	struct mmp_clk_factor_masks *masks = factor->masks;
 	unsigned int val, num, den;
+	u64 rate;
 
 	val = readl_relaxed(factor->base);
 
@@ -66,8 +69,11 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 	if (!den)
 		return 0;
 
-	return (((parent_rate / 10000)  * den) /
-			(num * factor->masks->factor)) * 10000;
+	rate = parent_rate;
+	rate *= den;
+	do_div(rate, num * factor->masks->factor);
+
+	return rate;
 }
 
 /* Configures new clock rate*/
@@ -78,12 +84,14 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
 	struct mmp_clk_factor_masks *masks = factor->masks;
 	int i;
 	unsigned long val;
-	unsigned long rate = 0;
 	unsigned long flags = 0;
+	u64 rate = 0;
 
 	for (i = 0; i < factor->ftbl_cnt; i++) {
-		rate = (((prate / 10000) * factor->ftbl[i].den) /
-			(factor->ftbl[i].num * factor->masks->factor)) * 10000;
+		rate = prate;
+		rate *= factor->ftbl[i].den;
+		do_div(rate, factor->ftbl[i].num * factor->masks->factor);
+
 		if (rate > drate)
 			break;
 	}
-- 
2.26.2


^ permalink raw reply related

* Re: [PATCH 1/2] dt-bindings: sound: Add Marvell MMP Audio Clock Controller binding
From: Lubomir Rintel @ 2020-05-19 22:21 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Michael Turquette, Liam Girdwood, Mark Brown, Rob Herring,
	linux-clk, devicetree, linux-kernel, linux-media
In-Reply-To: <158949036750.215346.11234071140104055350@swboyd.mtv.corp.google.com>

On Thu, May 14, 2020 at 02:06:07PM -0700, Stephen Boyd wrote:
> Quoting Lubomir Rintel (2020-05-11 12:55:33)
> > diff --git a/Documentation/devicetree/bindings/clock/marvell,mmp2-audio-clock.yaml b/Documentation/devicetree/bindings/clock/marvell,mmp2-audio-clock.yaml
> > new file mode 100644
> > index 000000000000..b86e9fbfa56d
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/clock/marvell,mmp2-audio-clock.yaml
> > @@ -0,0 +1,73 @@
> > +# SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/clock/marvell,mmp2-audio-clock.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: Marvell MMP2 Audio Clock Controller
> > +
> > +maintainers:
> > +  - Lubomir Rintel <lkundrak@v3.sk>
> > +
> > +description: |
> > +  The audio clock controller generates and supplies the clocks to the audio
> > +  codec.
> > +
> > +  Each clock is assigned an identifier and client nodes use this identifier
> > +  to specify the clock which they consume.
> > +
> > +  All these identifiers could be found in <dt-bindings/clock/marvell,mmp2.h>.
> 
> Is this right? The patch puts them in mmp2-audio.h
> 
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - marvell,mmp2-audio-clock
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  clocks:
> > +    items:
> > +      - description: Audio subsystem clock
> > +      - description: The crystal oscillator clock
> > +      - description: First I2S clock
> > +      - description: Second I2S clock
> > +
> > +  clock-names:
> > +    items:
> > +      - const: audio
> > +      - const: vctcxo
> > +      - const: i2s0
> > +      - const: i2s1
> > +
> > +  '#clock-cells':
> > +    const: 1
> > +
> > +  power-domains:
> > +    maxItems: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - clocks
> > +  - clock-names
> > +  - '#clock-cells'
> > +
> > +additionalProperties: false
> > +
> > +examples:
> > +  - |
> > +    #include <dt-bindings/clock/marvell,mmp2.h>
> > +    #include <dt-bindings/power/marvell,mmp2.h>
> > +
> > +    clocks@d42a0c30 {
> 
> clock-controller@d42a0c30
> 
> > +      compatible = "marvell,mmp2-audio-clock";
> > +      reg = <0xd42a0c30 0x10>;
> 
> That is a very specific and tiny region. Presumably this is part of a
> larger hardware block and thus shouldn't be described in DT this way.
> Instead there should be one clock-controller node and a driver that
> controls all the clks that it wants to inside that hardware block.

This resides in a block that's entirely separate from SoC's main clock
controllers ("power management units"). It is inside the audio block,
separate power island along with two I2S ("SSPA") controllers. The
addresses are weirdly interleaved, with the clock controller being
mapped between the two channels of the first SSPA:

  0xd42a0c00 - 0xd42a0c30 SSPA1 RX
  0xd42a0c30 - 0xd42a0c40 Clock Control
  0xd42a0c80 - 0xd42a0cb0 SSPA1 TX
  0xd42a0d00 - 0xd42a0d30 SSPA2 RX
  0xd42a0d80 - 0xd42a0cb0 SSPA2 TX

Despite the addresses being interwoven in this way, the Clock Controller
is pretty much independent of the SSPAs and deserves a separate device
node, regardless of how tiny its range is.

> > +      clock-names = "audio", "vctcxo", "i2s0", "i2s1";
> > +      clocks = <&soc_clocks MMP2_CLK_AUDIO>,
> > +               <&soc_clocks MMP2_CLK_VCTCXO>,
> > +               <&soc_clocks MMP2_CLK_I2S0>,
> > +               <&soc_clocks MMP2_CLK_I2S1>;
> > +      power-domains = <&soc_clocks MMP2_POWER_DOMAIN_AUDIO>;
> > +      #clock-cells = <1>;
> > +    };
> > diff --git a/include/dt-bindings/clock/marvell,mmp2-audio.h b/include/dt-bindings/clock/marvell,mmp2-audio.h
> > new file mode 100644
> > index 000000000000..127b48ec0f0a
> > --- /dev/null
> > +++ b/include/dt-bindings/clock/marvell,mmp2-audio.h
> > @@ -0,0 +1,8 @@
> > +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-2-Clause) */
> > +#ifndef __DT_BINDINGS_CLOCK_MARVELL_MMP2_AUDIO_H
> > +#define __DT_BINDINGS_CLOCK_MARVELL_MMP2_AUDIO_H
> > +
> > +#define MMP2_CLK_AUDIO_SYSCLK          1
> 
> Any reason to start at 1 vs. 0?
> 
> > +#define MMP2_CLK_AUDIO_SSPA0           2
> > +#define MMP2_CLK_AUDIO_SSPA1           3
> > +#endif
> > -- 
> > 2.26.2
> >

^ permalink raw reply

* Re: [PATCH v2 2/3] bindings: sound: Add documentation for TI j721e EVM (CPB and IVI)
From: Rob Herring @ 2020-05-19 22:21 UTC (permalink / raw)
  To: Peter Ujfalusi; +Cc: broonie, lgirdwood, alsa-devel, devicetree, linux-kernel
In-Reply-To: <20200512131633.32668-3-peter.ujfalusi@ti.com>

On Tue, May 12, 2020 at 04:16:32PM +0300, Peter Ujfalusi wrote:
> The audio support on the Common Processor Board board is using
> pcm3168a codec connected to McASP10 serializers in parallel setup.
> 
> The Infotainment board plugs into the Common Processor Board, the support
> of the extension board is extending the CPB audio support by adding
> the two codecs on the expansion board.
> 
> The audio support on the Infotainment Expansion Board consists of McASP0
> connected to two pcm3168a codecs with dedicated set of serializers to each.
> The SCKI for pcm3168a is sourced from j721e AUDIO_REFCLK0 pin.
> 
> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
> ---
>  .../bindings/sound/ti,j721e-cpb-audio.yaml    |  93 ++++++++++++
>  .../sound/ti,j721e-cpb-ivi-audio.yaml         | 142 ++++++++++++++++++
>  2 files changed, 235 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml
>  create mode 100644 Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml
> 
> diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml
> new file mode 100644
> index 000000000000..0355ffc2b01b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-audio.yaml
> @@ -0,0 +1,93 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/ti,j721e-cpb-audio.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Texas Instruments J721e Common Processor Board Audio Support
> +
> +maintainers:
> +  - Peter Ujfalusi <peter.ujfalusi@ti.com>
> +
> +description: |
> +  The audio support on the board is using pcm3168a codec connected to McASP10
> +  serializers in parallel setup.
> +  The pcm3168a SCKI clock is sourced from j721e AUDIO_REFCLK2 pin.
> +  In order to support 48KHz and 44.1KHz family of sampling rates the parent
> +  clock for AUDIO_REFCLK2 needs to be changed between PLL4 (for 48KHz) and
> +  PLL15 (for 44.1KHz). The same PLLs are used for McASP10's AUXCLK clock via
> +  different HSDIVIDER.
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: ti,j721e-cpb-audio
> +
> +  model:
> +    $ref: /schemas/types.yaml#/definitions/string
> +    description: User specified audio sound card name
> +
> +  ti,cpb-mcasp:
> +    description: phandle to McASP10
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  ti,cpb-codec:
> +    description: phandle to the pcm3168a codec used on the CPB
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  clocks:
> +    items:
> +      - description: PLL4 clock
> +      - description: PLL15 clock
> +      - description: McASP10 auxclk clock
> +      - description: PLL4_HSDIV0 parent for McASP10 auxclk (for 48KHz)
> +      - description: PLL15_HSDIV0 parent for McASP10 auxclk (for 44.1KHz)
> +      - description: AUDIO_REFCLK2 clock
> +      - description: PLL4_HSDIV2 parent for AUDIO_REFCLK2 clock (for 48KHz)
> +      - description: PLL15_HSDIV2 parent for AUDIO_REFCLK2 clock (for 44.1KHz)

What h/w are these connected to? You have no control interface here, so 
how do you have clocks?

Defining parent clocks seems wrong, too. This seems to just be a 
collection of clocks a driver happens to need. Really, you should be 
able query possible parents and select one with the right frequency 
multiple.

> +
> +  clock-names:
> +    items:
> +      - const: pll4
> +      - const: pll15
> +      - const: cpb-mcasp
> +      - const: cpb-mcasp-48000
> +      - const: cpb-mcasp-44100
> +      - const: audio-refclk2
> +      - const: audio-refclk2-48000
> +      - const: audio-refclk2-44100
> +
> +required:
> +  - compatible
> +  - model
> +  - ti,cpb-mcasp
> +  - ti,cpb-codec
> +  - clocks
> +  - clock-names
> +
> +additionalProperties: false
> +
> +examples:
> +  - |+
> +    sound {
> +        compatible = "ti,j721e-cpb-audio";
> +        model = "j721e-cpb";
> +
> +        status = "okay";

Don't show status in examples.

> +
> +        ti,cpb-mcasp = <&mcasp10>;
> +        ti,cpb-codec = <&pcm3168a_1>;
> +
> +        clocks = <&pll4>, <&pll15>,
> +                 <&k3_clks 184 1>,
> +                 <&k3_clks 184 2>, <&k3_clks 184 4>,
> +                 <&k3_clks 157 371>,
> +                 <&k3_clks 157 400>, <&k3_clks 157 401>;
> +        clock-names = "pll4", "pll15",
> +                      "cpb-mcasp",
> +                      "cpb-mcasp-48000", "cpb-mcasp-44100",
> +                      "audio-refclk2",
> +                      "audio-refclk2-48000", "audio-refclk2-44100";
> +    };
> diff --git a/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml
> new file mode 100644
> index 000000000000..3951c1320fae
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/sound/ti,j721e-cpb-ivi-audio.yaml
> @@ -0,0 +1,142 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/sound/ti,j721e-cpb-ivi-audio.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Texas Instruments J721e Common Processor Board Audio Support
> +
> +maintainers:
> +  - Peter Ujfalusi <peter.ujfalusi@ti.com>
> +
> +description: |
> +  The Infotainment board plugs into the Common Processor Board, the support of the
> +  extension board is extending the CPB audio support, decribed in:
> +  sound/ti,j721e-cpb-audio.txt
> +
> +  The audio support on the Infotainment Expansion Board consists of McASP0
> +  connected to two pcm3168a codecs with dedicated set of serializers to each.
> +  The SCKI for pcm3168a is sourced from j721e AUDIO_REFCLK0 pin.
> +
> +  In order to support 48KHz and 44.1KHz family of sampling rates the parent clock
> +  for AUDIO_REFCLK0 needs to be changed between PLL4 (for 48KHz) and PLL15 (for
> +  44.1KHz). The same PLLs are used for McASP0's AUXCLK clock via different
> +  HSDIVIDER.
> +
> +  Note: the same PLL4 and PLL15 is used by the audio support on the CPB!
> +
> +properties:
> +  compatible:
> +    items:
> +      - const: ti,j721e-cpb-ivi-audio
> +
> +  model:
> +    $ref: /schemas/types.yaml#/definitions/string
> +    description: User specified audio sound card name
> +
> +  ti,cpb-mcasp:
> +    description: phandle to McASP10
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  ti,cpb-codec:
> +    description: phandle to the pcm3168a codec used on the CPB
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  ti,ivi-mcasp:
> +    description: phandle to McASP9
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  ti,ivi-codec-a:
> +    description: phandle to the pcm3168a-A codec on the expansion board
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  ti,ivi-codec-b:
> +    description: phandle to the pcm3168a-B codec on the expansion board
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/phandle
> +
> +  clocks:
> +    items:
> +      - description: PLL4 clock
> +      - description: PLL15 clock
> +      - description: McASP10 auxclk clock
> +      - description: PLL4_HSDIV0 parent for McASP10 auxclk (for 48KHz)
> +      - description: PLL15_HSDIV0 parent for McASP10 auxclk (for 44.1KHz)
> +      - description: AUDIO_REFCLK2 clock
> +      - description: PLL4_HSDIV2 parent for AUDIO_REFCLK2 clock (for 48KHz)
> +      - description: PLL15_HSDIV2 parent for AUDIO_REFCLK2 clock (for 44.1KHz)
> +      - description: McASP0 auxclk clock
> +      - description: PLL4_HSDIV0 parent for McASP0 auxclk (for 48KHz)
> +      - description: PLL15_HSDIV0 parent for McASP0 auxclk (for 44.1KHz)
> +      - description: AUDIO_REFCLK0 clock
> +      - description: PLL4_HSDIV2 parent for AUDIO_REFCLK0 clock (for 48KHz)
> +      - description: PLL15_HSDIV2 parent for AUDIO_REFCLK0 clock (for 44.1KHz)
> +
> +  clock-names:
> +    items:
> +      - const: pll4
> +      - const: pll15
> +      - const: cpb-mcasp
> +      - const: cpb-mcasp-48000
> +      - const: cpb-mcasp-44100
> +      - const: audio-refclk2
> +      - const: audio-refclk2-48000
> +      - const: audio-refclk2-44100
> +      - const: ivi-mcasp
> +      - const: ivi-mcasp-48000
> +      - const: ivi-mcasp-44100
> +      - const: audio-refclk0
> +      - const: audio-refclk0-48000
> +      - const: audio-refclk0-44100
> +
> +required:
> +  - compatible
> +  - model
> +  - ti,cpb-mcasp
> +  - ti,cpb-codec
> +  - ti,ivi-mcasp
> +  - ti,ivi-codec-a
> +  - ti,ivi-codec-b
> +  - clocks
> +  - clock-names
> +
> +additionalProperties: false
> +
> +examples:
> +  - |+
> +    sound {
> +        compatible = "ti,j721e-cpb-ivi-audio";
> +        model = "j721e-cpb-ivi";
> +
> +        status = "okay";
> +
> +        ti,cpb-mcasp = <&mcasp10>;
> +        ti,cpb-codec = <&pcm3168a_1>;
> +
> +        ti,ivi-mcasp = <&mcasp0>;
> +        ti,ivi-codec-a = <&pcm3168a_a>;
> +        ti,ivi-codec-b = <&pcm3168a_b>;
> +
> +        clocks = <&pll4>, <&pll15>,
> +                 <&k3_clks 184 1>,
> +                 <&k3_clks 184 2>, <&k3_clks 184 4>,
> +                 <&k3_clks 157 371>,
> +                 <&k3_clks 157 400>, <&k3_clks 157 401>,
> +                 <&k3_clks 174 1>,
> +                 <&k3_clks 174 2>, <&k3_clks 174 4>,
> +                 <&k3_clks 157 301>,
> +                 <&k3_clks 157 330>, <&k3_clks 157 331>;
> +        clock-names = "pll4", "pll15",
> +                      "cpb-mcasp",
> +                      "cpb-mcasp-48000", "cpb-mcasp-44100",
> +                      "audio-refclk2",
> +                      "audio-refclk2-48000", "audio-refclk2-44100",
> +                      "ivi-mcasp",
> +                      "ivi-mcasp-48000", "ivi-mcasp-44100",
> +                      "audio-refclk0",
> +                      "audio-refclk0-48000", "audio-refclk0-44100";
> +    };
> -- 
> Peter
> 
> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
> Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
> 

^ permalink raw reply

* [PATCH v3 2/2] platform/chrome: typec: Register Type C switches
From: Prashant Malani @ 2020-05-19 21:46 UTC (permalink / raw)
  To: linux-kernel, robh+dt
  Cc: heikki.krogerus, Prashant Malani, Enric Balletbo i Serra,
	Benson Leung,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Guenter Roeck
In-Reply-To: <20200519214604.180036-1-pmalani@chromium.org>

Register Type C mux and switch handles, when provided via firmware
bindings. These will allow the cros-ec-typec driver, and also alternate
mode drivers to configure connected Muxes correctly, according to PD
information retrieved from the Chrome OS EC.

Signed-off-by: Prashant Malani <pmalani@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Acked-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---

Changes in v3:
- Added Acked-by tag.
- Fixed Heikki's email address in Reviewed-by tag.

Changes in v2:
- Changed dev_info prints to dev_dbg.

 drivers/platform/chrome/cros_ec_typec.c | 47 +++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 66b8d21092af..6e79f917314b 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -14,6 +14,8 @@
 #include <linux/platform_data/cros_usbpd_notify.h>
 #include <linux/platform_device.h>
 #include <linux/usb/typec.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/role.h>
 
 #define DRV_NAME "cros-ec-typec"
 
@@ -25,6 +27,9 @@ struct cros_typec_port {
 	struct typec_partner *partner;
 	/* Port partner PD identity info. */
 	struct usb_pd_identity p_identity;
+	struct typec_switch *ori_sw;
+	struct typec_mux *mux;
+	struct usb_role_switch *role_sw;
 };
 
 /* Platform-specific data for the Chrome OS EC Type C controller. */
@@ -84,6 +89,40 @@ static int cros_typec_parse_port_props(struct typec_capability *cap,
 	return 0;
 }
 
+static int cros_typec_get_switch_handles(struct cros_typec_port *port,
+					 struct fwnode_handle *fwnode,
+					 struct device *dev)
+{
+	port->mux = fwnode_typec_mux_get(fwnode, NULL);
+	if (IS_ERR(port->mux)) {
+		dev_dbg(dev, "Mux handle not found.\n");
+		goto mux_err;
+	}
+
+	port->ori_sw = fwnode_typec_switch_get(fwnode);
+	if (IS_ERR(port->ori_sw)) {
+		dev_dbg(dev, "Orientation switch handle not found.\n");
+		goto ori_sw_err;
+	}
+
+	port->role_sw = fwnode_usb_role_switch_get(fwnode);
+	if (IS_ERR(port->role_sw)) {
+		dev_dbg(dev, "USB role switch handle not found.\n");
+		goto role_sw_err;
+	}
+
+	return 0;
+
+role_sw_err:
+	usb_role_switch_put(port->role_sw);
+ori_sw_err:
+	typec_switch_put(port->ori_sw);
+mux_err:
+	typec_mux_put(port->mux);
+
+	return -ENODEV;
+}
+
 static void cros_unregister_ports(struct cros_typec_data *typec)
 {
 	int i;
@@ -91,6 +130,9 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
 	for (i = 0; i < typec->num_ports; i++) {
 		if (!typec->ports[i])
 			continue;
+		usb_role_switch_put(typec->ports[i]->role_sw);
+		typec_switch_put(typec->ports[i]->ori_sw);
+		typec_mux_put(typec->ports[i]->mux);
 		typec_unregister_port(typec->ports[i]->port);
 	}
 }
@@ -153,6 +195,11 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
 			ret = PTR_ERR(cros_port->port);
 			goto unregister_ports;
 		}
+
+		ret = cros_typec_get_switch_handles(cros_port, fwnode, dev);
+		if (ret)
+			dev_dbg(dev, "No switch control for port %d\n",
+				port_num);
 	}
 
 	return 0;
-- 
2.26.2.761.g0e0b3e54be-goog


^ permalink raw reply related

* [PATCH v3 1/2] dt-bindings: chrome: Add cros-ec-typec mux props
From: Prashant Malani @ 2020-05-19 21:46 UTC (permalink / raw)
  To: linux-kernel, robh+dt
  Cc: heikki.krogerus, Prashant Malani, Benson Leung,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Enric Balletbo i Serra, Guenter Roeck

Add properties for mode, orientation and USB data role switches for
Type C connectors. When available, these will allow the Type C connector
class port driver to configure the various switches according to USB PD
information (like orientation, alt mode etc.) provided by the Chrome OS
EC controller.

Signed-off-by: Prashant Malani <pmalani@chromium.org>
Acked-by: Benson Leung <bleung@chromium.org>
---

Changes in v3:
- Fixed Acked-by tag typo.

Changes in v2:
- Added more text to the switch descriptions, explaining their purpose,
  and relation to the Type C connector class framework.

 .../bindings/chrome/google,cros-ec-typec.yaml | 40 ++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml b/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
index 6d7396ab8bee..800c005a0e44 100644
--- a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
+++ b/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
@@ -21,7 +21,34 @@ properties:
     const: google,cros-ec-typec
 
   connector:
-    $ref: /schemas/connector/usb-connector.yaml#
+    allOf:
+      - $ref: /schemas/connector/usb-connector.yaml#
+      - type: object
+        properties:
+          mode-switch:
+            description: Reference to a DT node for the USB Type C Multiplexer
+              for this connector. This switch controls the data lines routing
+              for this connector for various operation modes, including
+              Alternate Modes. This switch is assumed registered with the Type C
+              connector class framework by its driver. The Type C connector
+              class framework assumes that the mode switch property uses this
+              name.
+
+          orientation-switch:
+            description: Reference to a DT node for the USB Type C orientation
+              switch for this connector. This switch controls routing the
+              correct data pairs depending on the cable plug orientation from
+              this connector to the USB / Alternate Mode controllers. This
+              switch is assumed registered with the Type C connector class
+              framework by its driver. The Type C connector class framework
+              assumes that the orientation switch property uses this name.
+
+          usb-role-switch:
+            description: Reference to a DT node for the USB Data role switch
+              for this connector. This switch is assumed registered with the
+              Type C connector class framework by its driver. The Type C
+              connector class framework assumes that the USB role switch
+              property uses this name.
 
 required:
   - compatible
@@ -49,6 +76,17 @@ examples:
             data-role = "dual";
             try-power-role = "source";
           };
+
+          connector@1 {
+            compatible = "usb-c-connector";
+            reg = <1>;
+            power-role = "dual";
+            data-role = "host";
+            try-power-role = "source";
+            mode-switch = <&typec_mux>;
+            orientation-switch = <&typec_orientation_switch>;
+            usb-role-switch = <&typec_mux>;
+          };
         };
       };
     };
-- 
2.26.2.761.g0e0b3e54be-goog


^ permalink raw reply related

* Re: [PATCH 3/4] clk/soc: mediatek: mt6779: Bind clock driver from platform device
From: Matthias Brugger @ 2020-05-19 21:26 UTC (permalink / raw)
  To: Chun-Kuang Hu, matthias.bgg
  Cc: Rob Herring, Matthias Brugger, Michael Turquette, Stephen Boyd,
	Kate Stewart, devicetree, Greg Kroah-Hartman, linux-kernel,
	moderated list:ARM/Mediatek SoC support, Linux ARM, mtk01761,
	Thomas Gleixner, linux-clk, Allison Randal
In-Reply-To: <CAAOTY_80D6ZMM5_nEyf_XDjOLaWCOyi3mn9ibWhNX8_ozPK1BQ@mail.gmail.com>



On 19/05/2020 17:10, Chun-Kuang Hu wrote:
> Hi, Matthias:
> 
> <matthias.bgg@kernel.org> 於 2020年5月18日 週一 下午7:33寫道:
>>
>> From: Matthias Brugger <matthias.bgg@gmail.com>
>>
>> The mmsys driver is now the top level entry point for the multimedia
>> system (mmsys), we bind the clock driver by creating a platform device.
>> We also bind the MediaTek DRM driver which is not yet implement and
>> therefor will errror out for now.
>>
>> Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
>> ---
>>
>>  drivers/clk/mediatek/clk-mt6779-mm.c | 9 ++-------
>>  drivers/soc/mediatek/mtk-mmsys.c     | 8 ++++++++
>>  2 files changed, 10 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/clk/mediatek/clk-mt6779-mm.c b/drivers/clk/mediatek/clk-mt6779-mm.c
>> index fb5fbb8e3e41..059c1a41ac7a 100644
>> --- a/drivers/clk/mediatek/clk-mt6779-mm.c
>> +++ b/drivers/clk/mediatek/clk-mt6779-mm.c
>> @@ -84,15 +84,11 @@ static const struct mtk_gate mm_clks[] = {
>>         GATE_MM1(CLK_MM_DISP_OVL_FBDC, "mm_disp_ovl_fbdc", "mm_sel", 16),
>>  };
>>
>> -static const struct of_device_id of_match_clk_mt6779_mm[] = {
>> -       { .compatible = "mediatek,mt6779-mmsys", },
>> -       {}
>> -};
>> -
>>  static int clk_mt6779_mm_probe(struct platform_device *pdev)
>>  {
>> +       struct device *dev = &pdev->dev;
>> +       struct device_node *node = dev->parent->of_node;
>>         struct clk_onecell_data *clk_data;
>> -       struct device_node *node = pdev->dev.of_node;
>>
>>         clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
>>
>> @@ -106,7 +102,6 @@ static struct platform_driver clk_mt6779_mm_drv = {
>>         .probe = clk_mt6779_mm_probe,
>>         .driver = {
>>                 .name = "clk-mt6779-mm",
>> -               .of_match_table = of_match_clk_mt6779_mm,
>>         },
>>  };
>>
>> diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c
>> index fee64c8d3020..dc15808cf3a3 100644
>> --- a/drivers/soc/mediatek/mtk-mmsys.c
>> +++ b/drivers/soc/mediatek/mtk-mmsys.c
>> @@ -88,6 +88,10 @@ static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = {
>>         .clk_driver = "clk-mt2712-mm",
>>  };
>>
>> +static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = {
>> +       .clk_driver = "clk-mt6779-mm",
> 
> This patch looks good to me, but I've one question: why drm driver
> just use single "mediatek-drm" for sub driver name, but clock driver
> has different name for each SoC?
> Could we just use single name for clock driver such as "mediatek-clk-mm"?

Because the DRM for all SoCs are handled in the same driver, while we have a
different clock drivers for each SoC. So we need to specify which clock driver
we want to load.

If we want to change that, we would need to refactor heavily the clock drivers
for all MediaTek SoCs. I don't think it's worth the effort.

Regards,
Matthias

> 
> Regards,
> Chun-Kuang.
> 
>> +};
>> +
>>  static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = {
>>         .clk_driver = "clk-mt6797-mm",
>>  };
>> @@ -343,6 +347,10 @@ static const struct of_device_id of_match_mtk_mmsys[] = {
>>                 .compatible = "mediatek,mt2712-mmsys",
>>                 .data = &mt2712_mmsys_driver_data,
>>         },
>> +       {
>> +               .compatible = "mediatek,mt6779-mmsys",
>> +               .data = &mt6779_mmsys_driver_data,
>> +       },
>>         {
>>                 .compatible = "mediatek,mt6797-mmsys",
>>                 .data = &mt6797_mmsys_driver_data,
>> --
>> 2.26.2
>>
>>
>> _______________________________________________
>> Linux-mediatek mailing list
>> Linux-mediatek@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply

* Re: [PATCH v2 2/2] platform/chrome: typec: Register Type C switches
From: Enric Balletbo i Serra @ 2020-05-19 21:24 UTC (permalink / raw)
  To: Prashant Malani, linux-kernel
  Cc: heikki.krogerus, Heikki Krogerus, Benson Leung,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Guenter Roeck, Rob Herring
In-Reply-To: <20200518071707.161843-2-pmalani@chromium.org>

Hi Prashant,

Thank you for the patch.

On 18/5/20 9:17, Prashant Malani wrote:
> Register Type C mux and switch handles, when provided via firmware
> bindings. These will allow the cros-ec-typec driver, and also alternate
> mode drivers to configure connected Muxes correctly, according to PD
> information retrieved from the Chrome OS EC.
> 
> Signed-off-by: Prashant Malani <pmalani@chromium.org>
> Reviewed-by: Heikki Krogerus <heikki.krogerus@intel.linux.com>

For my own reference:

Acked-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>

Patch 1/2 still needs a review from Rob, I'll wait for that before queue the
patches.

Thanks,
 Enric

> ---
> 
> Changes in v2:
> - Changed dev_info prints to dev_dbg.
> 
>  drivers/platform/chrome/cros_ec_typec.c | 47 +++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
> 
> diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
> index 66b8d21092af..6e79f917314b 100644
> --- a/drivers/platform/chrome/cros_ec_typec.c
> +++ b/drivers/platform/chrome/cros_ec_typec.c
> @@ -14,6 +14,8 @@
>  #include <linux/platform_data/cros_usbpd_notify.h>
>  #include <linux/platform_device.h>
>  #include <linux/usb/typec.h>
> +#include <linux/usb/typec_mux.h>
> +#include <linux/usb/role.h>
>  
>  #define DRV_NAME "cros-ec-typec"
>  
> @@ -25,6 +27,9 @@ struct cros_typec_port {
>  	struct typec_partner *partner;
>  	/* Port partner PD identity info. */
>  	struct usb_pd_identity p_identity;
> +	struct typec_switch *ori_sw;
> +	struct typec_mux *mux;
> +	struct usb_role_switch *role_sw;
>  };
>  
>  /* Platform-specific data for the Chrome OS EC Type C controller. */
> @@ -84,6 +89,40 @@ static int cros_typec_parse_port_props(struct typec_capability *cap,
>  	return 0;
>  }
>  
> +static int cros_typec_get_switch_handles(struct cros_typec_port *port,
> +					 struct fwnode_handle *fwnode,
> +					 struct device *dev)
> +{
> +	port->mux = fwnode_typec_mux_get(fwnode, NULL);
> +	if (IS_ERR(port->mux)) {
> +		dev_dbg(dev, "Mux handle not found.\n");
> +		goto mux_err;
> +	}
> +
> +	port->ori_sw = fwnode_typec_switch_get(fwnode);
> +	if (IS_ERR(port->ori_sw)) {
> +		dev_dbg(dev, "Orientation switch handle not found.\n");
> +		goto ori_sw_err;
> +	}
> +
> +	port->role_sw = fwnode_usb_role_switch_get(fwnode);
> +	if (IS_ERR(port->role_sw)) {
> +		dev_dbg(dev, "USB role switch handle not found.\n");
> +		goto role_sw_err;
> +	}
> +
> +	return 0;
> +
> +role_sw_err:
> +	usb_role_switch_put(port->role_sw);
> +ori_sw_err:
> +	typec_switch_put(port->ori_sw);
> +mux_err:
> +	typec_mux_put(port->mux);
> +
> +	return -ENODEV;
> +}
> +
>  static void cros_unregister_ports(struct cros_typec_data *typec)
>  {
>  	int i;
> @@ -91,6 +130,9 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
>  	for (i = 0; i < typec->num_ports; i++) {
>  		if (!typec->ports[i])
>  			continue;
> +		usb_role_switch_put(typec->ports[i]->role_sw);
> +		typec_switch_put(typec->ports[i]->ori_sw);
> +		typec_mux_put(typec->ports[i]->mux);
>  		typec_unregister_port(typec->ports[i]->port);
>  	}
>  }
> @@ -153,6 +195,11 @@ static int cros_typec_init_ports(struct cros_typec_data *typec)
>  			ret = PTR_ERR(cros_port->port);
>  			goto unregister_ports;
>  		}
> +
> +		ret = cros_typec_get_switch_handles(cros_port, fwnode, dev);
> +		if (ret)
> +			dev_dbg(dev, "No switch control for port %d\n",
> +				port_num);
>  	}
>  
>  	return 0;
> 

^ permalink raw reply

* Re: [PATCH v7 7/7] input: joystick: Add ADC attached joystick driver.
From: Paul Cercueil @ 2020-05-19 21:02 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Artur Rojek, Dmitry Torokhov, Rob Herring, Mark Rutland,
	Jonathan Cameron, Heiko Stuebner, Ezequiel Garcia, linux-input,
	devicetree, linux-iio, Linux Kernel Mailing List
In-Reply-To: <CAHp75VcChHOrxrqBM==-_SaTL4vSojKmRWvkNn-CHLH99pcAuQ@mail.gmail.com>

Hi Andy,

Le mar. 19 mai 2020 à 23:43, Andy Shevchenko 
<andy.shevchenko@gmail.com> a écrit :
> On Sun, May 17, 2020 at 10:49 PM Artur Rojek <contact@artur-rojek.eu> 
> wrote:
>> 
>>  Add a driver for joystick devices connected to ADC controllers
>>  supporting the Industrial I/O subsystem.
> 
> ...
> 
>>  +static int adc_joystick_handle(const void *data, void *private)
>>  +{
>>  +       struct adc_joystick *joy = private;
>>  +       enum iio_endian endianness;
>>  +       int bytes, msb, val, i;
>>  +       bool sign;
>>  +
>>  +       bytes = joy->chans[0].channel->scan_type.storagebits >> 3;
>>  +
>>  +       for (i = 0; i < joy->num_chans; ++i) {
>>  +               endianness = 
>> joy->chans[i].channel->scan_type.endianness;
>>  +               msb = joy->chans[i].channel->scan_type.realbits - 1;
> 
>>  +               sign = 
>> (tolower(joy->chans[i].channel->scan_type.sign) == 's');
> 
> Do we need tolower()?

I'll answer this one:

The sign can be uppercase to specify that the value is sign-extended in 
all the storage bits.

-Paul

>>  +
>>  +               switch (bytes) {
>>  +               case 1:
>>  +                       val = ((const u8 *)data)[i];
>>  +                       break;
>>  +               case 2:
>>  +                       if (endianness == IIO_BE)
> 
>>  +                               val = be16_to_cpu(((const u16 
>> *)data)[i]);
> 
> Yeah, you have to provide bitwise types to satisfy sparse.
> Maybe using *_to_cpup() will cure this.
> 
>>  +                       else if (endianness == IIO_LE)
>>  +                               val = le16_to_cpu(((const u16 
>> *)data)[i]);
>>  +                       else /* IIO_CPU */
>>  +                               val = ((const u16 *)data)[i];
>>  +                       break;
>>  +               default:
>>  +                       return -EINVAL;
>>  +               }
>>  +
>>  +               val >>= joy->chans[i].channel->scan_type.shift;
>>  +               if (sign)
>>  +                       val = sign_extend32(val, msb);
>>  +               else
>>  +                       val &= GENMASK(msb, 0);
>>  +               input_report_abs(joy->input, joy->axes[i].code, 
>> val);
>>  +       }
>>  +
>>  +       input_sync(joy->input);
>>  +
>>  +       return 0;
>>  +}
> 
> ...
> 
>>  +       /* Count how many channels we got. NULL terminated. */
>>  +       while (joy->chans[joy->num_chans].indio_dev)
>>  +               joy->num_chans++;
> 
> I don't see how useful this is. Why not simple do below...
> 
>>  +       bits = joy->chans[0].channel->scan_type.storagebits;
>>  +       if (!bits || (bits > 16)) {
>>  +               dev_err(dev, "Unsupported channel storage size");
>>  +               return -EINVAL;
>>  +       }
>>  +       for (i = 1; i < joy->num_chans; ++i)
>>  +               if (joy->chans[i].channel->scan_type.storagebits != 
>> bits) {
>>  +                       dev_err(dev, "Channels must have equal 
>> storage size");
>>  +                       return -EINVAL;
>>  +               }
> 
> ...something like
> 
>   for (i = 0; joy->chans[i].indio_dev; i++) {
>     bits = joy->chans[i].channel->scan_type.storagebits;
>     if (bits ...) {
>       ...error handling...
>     }
>     if (bits != joy->chans[0].channel->scan_type.storagebits) {
>       ...second level of error handling...
>     }
>  }
> 
> ...
> 
>>  +static const struct of_device_id adc_joystick_of_match[] = {
>>  +       { .compatible = "adc-joystick", },
> 
>>  +       { },
> 
> No need comma.
> 
>>  +};
> 
> --
> With Best Regards,
> Andy Shevchenko



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox