From 9357b04624013294e4204b1a837d0a611b9048c3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 27 May 2020 17:47:31 +0200 Subject: [PATCH 01/94] reset: Move reset-simple header out of drivers/reset The reset-simple code can be useful for drivers outside of drivers/reset that have a few reset controls as part of their features. Let's move it to include/linux/reset. Reviewed-by: Philipp Zabel Signed-off-by: Maxime Ripard Signed-off-by: Philipp Zabel --- drivers/reset/reset-simple.c | 3 +-- drivers/reset/reset-socfpga.c | 3 +-- drivers/reset/reset-sunxi.c | 3 +-- drivers/reset/reset-uniphier-glue.c | 3 +-- {drivers => include/linux}/reset/reset-simple.h | 0 5 files changed, 4 insertions(+), 8 deletions(-) rename {drivers => include/linux}/reset/reset-simple.h (100%) diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c index 067e7e7b34f1..c854aa351640 100644 --- a/drivers/reset/reset-simple.c +++ b/drivers/reset/reset-simple.c @@ -18,10 +18,9 @@ #include #include #include +#include #include -#include "reset-simple.h" - static inline struct reset_simple_data * to_reset_simple_data(struct reset_controller_dev *rcdev) { diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index 96953992c2bb..bdd984296196 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -11,13 +11,12 @@ #include #include #include +#include #include #include #include #include -#include "reset-simple.h" - #define SOCFPGA_NR_BANKS 8 static int a10_reset_init(struct device_node *np) diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c index e7f169e57bcf..e752594b6971 100644 --- a/drivers/reset/reset-sunxi.c +++ b/drivers/reset/reset-sunxi.c @@ -14,13 +14,12 @@ #include #include #include +#include #include #include #include #include -#include "reset-simple.h" - static int sunxi_reset_init(struct device_node *np) { struct reset_simple_data *data; diff --git a/drivers/reset/reset-uniphier-glue.c b/drivers/reset/reset-uniphier-glue.c index 2b188b3bb69a..027990b79f61 100644 --- a/drivers/reset/reset-uniphier-glue.c +++ b/drivers/reset/reset-uniphier-glue.c @@ -9,8 +9,7 @@ #include #include #include - -#include "reset-simple.h" +#include #define MAX_CLKS 2 #define MAX_RSTS 2 diff --git a/drivers/reset/reset-simple.h b/include/linux/reset/reset-simple.h similarity index 100% rename from drivers/reset/reset-simple.h rename to include/linux/reset/reset-simple.h From a9701376ed0fb61a5be4bb438daf26bd9cfa24b5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 27 May 2020 17:47:32 +0200 Subject: [PATCH 02/94] reset: simple: Add reset callback The reset-simple code lacks a reset callback that is still pretty easy to implement. The only real thing to consider is the delay needed for a device to be reset, so let's expose that as part of the reset-simple driver data. Reviewed-by: Philipp Zabel Signed-off-by: Maxime Ripard Signed-off-by: Philipp Zabel --- drivers/reset/reset-simple.c | 20 ++++++++++++++++++++ include/linux/reset/reset-simple.h | 7 +++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c index c854aa351640..e066614818a3 100644 --- a/drivers/reset/reset-simple.c +++ b/drivers/reset/reset-simple.c @@ -11,6 +11,7 @@ * Maxime Ripard */ +#include #include #include #include @@ -63,6 +64,24 @@ static int reset_simple_deassert(struct reset_controller_dev *rcdev, return reset_simple_update(rcdev, id, false); } +static int reset_simple_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + struct reset_simple_data *data = to_reset_simple_data(rcdev); + int ret; + + if (!data->reset_us) + return -ENOTSUPP; + + ret = reset_simple_assert(rcdev, id); + if (ret) + return ret; + + usleep_range(data->reset_us, data->reset_us * 2); + + return reset_simple_deassert(rcdev, id); +} + static int reset_simple_status(struct reset_controller_dev *rcdev, unsigned long id) { @@ -80,6 +99,7 @@ static int reset_simple_status(struct reset_controller_dev *rcdev, const struct reset_control_ops reset_simple_ops = { .assert = reset_simple_assert, .deassert = reset_simple_deassert, + .reset = reset_simple_reset, .status = reset_simple_status, }; EXPORT_SYMBOL_GPL(reset_simple_ops); diff --git a/include/linux/reset/reset-simple.h b/include/linux/reset/reset-simple.h index 08ccb25a55e6..c3e44f45b0f7 100644 --- a/include/linux/reset/reset-simple.h +++ b/include/linux/reset/reset-simple.h @@ -27,6 +27,12 @@ * @status_active_low: if true, bits read back as cleared while the reset is * asserted. Otherwise, bits read back as set while the * reset is asserted. + * @reset_us: Minimum delay in microseconds needed that needs to be + * waited for between an assert and a deassert to reset the + * device. If multiple consumers with different delay + * requirements are connected to this controller, it must + * be the largest minimum delay. 0 means that such a delay is + * unknown and the reset operation is unsupported. */ struct reset_simple_data { spinlock_t lock; @@ -34,6 +40,7 @@ struct reset_simple_data { struct reset_controller_dev rcdev; bool active_low; bool status_active_low; + unsigned int reset_us; }; extern const struct reset_control_ops reset_simple_ops; From cf8030d7035bd3e89c9e66f7193a7fc8057a9b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Tue, 9 Jun 2020 13:08:46 +0200 Subject: [PATCH 03/94] clk: bcm63xx-gate: fix last clock availability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to make the last clock available, maxbit has to be set to the highest bit value plus 1. Fixes: 1c099779c1e2 ("clk: add BCM63XX gated clock controller driver") Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200609110846.4029620-1-noltari@gmail.com Reviewed-by: Florian Fainelli Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm63xx-gate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/bcm/clk-bcm63xx-gate.c b/drivers/clk/bcm/clk-bcm63xx-gate.c index 98e884957db8..911a29bd744e 100644 --- a/drivers/clk/bcm/clk-bcm63xx-gate.c +++ b/drivers/clk/bcm/clk-bcm63xx-gate.c @@ -155,6 +155,7 @@ static int clk_bcm63xx_probe(struct platform_device *pdev) for (entry = table; entry->name; entry++) maxbit = max_t(u8, maxbit, entry->bit); + maxbit++; hw = devm_kzalloc(&pdev->dev, struct_size(hw, data.hws, maxbit), GFP_KERNEL); From 8fc4f427b84b3949db0be2f66955f91a0c29ba66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Wed, 10 Jun 2020 16:08:57 +0200 Subject: [PATCH 04/94] dt-bindings: clock: bcm63xx: add 6318 gated clock bindings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add BCM6318 to the binding documentation for the gated clock controllers found on BCM63xx SoCs. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20200610140858.207329-2-noltari@gmail.com Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt b/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt index 3041657e2f96..3e7ca5530775 100644 --- a/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt +++ b/Documentation/devicetree/bindings/clock/brcm,bcm63xx-clocks.txt @@ -3,6 +3,8 @@ Gated Clock Controller Bindings for MIPS based BCM63XX SoCs Required properties: - compatible: must be one of: "brcm,bcm3368-clocks" + "brcm,bcm6318-clocks" + "brcm,bcm6318-ubus-clocks" "brcm,bcm6328-clocks" "brcm,bcm6358-clocks" "brcm,bcm6362-clocks" From 90741a7268dfe4d4f159c8e10a1c1cb9d4e31dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Wed, 10 Jun 2020 16:08:58 +0200 Subject: [PATCH 05/94] clk: bcm63xx-gate: add BCM6318 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for the gated clock controllers found on the BCM6318. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Florian Fainelli Link: https://lore.kernel.org/r/20200610140858.207329-3-noltari@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm63xx-gate.c | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm63xx-gate.c b/drivers/clk/bcm/clk-bcm63xx-gate.c index 911a29bd744e..43853add44cb 100644 --- a/drivers/clk/bcm/clk-bcm63xx-gate.c +++ b/drivers/clk/bcm/clk-bcm63xx-gate.c @@ -40,6 +40,48 @@ static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = { { }, }; +static const struct clk_bcm63xx_table_entry bcm6318_clocks[] = { + { .name = "adsl_asb", .bit = 0, }, + { .name = "usb_asb", .bit = 1, }, + { .name = "mips_asb", .bit = 2, }, + { .name = "pcie_asb", .bit = 3, }, + { .name = "phymips_asb", .bit = 4, }, + { .name = "robosw_asb", .bit = 5, }, + { .name = "sar_asb", .bit = 6, }, + { .name = "sdr_asb", .bit = 7, }, + { .name = "swreg_asb", .bit = 8, }, + { .name = "periph_asb", .bit = 9, }, + { .name = "cpubus160", .bit = 10, }, + { .name = "adsl", .bit = 11, }, + { .name = "sar125", .bit = 12, }, + { .name = "mips", .bit = 13, .flags = CLK_IS_CRITICAL, }, + { .name = "pcie", .bit = 14, }, + { .name = "robosw250", .bit = 16, }, + { .name = "robosw025", .bit = 17, }, + { .name = "sdr", .bit = 19, .flags = CLK_IS_CRITICAL, }, + { .name = "usbd", .bit = 20, }, + { .name = "hsspi", .bit = 25, }, + { .name = "pcie25", .bit = 27, }, + { .name = "phymips", .bit = 28, }, + { .name = "afe", .bit = 29, }, + { .name = "qproc", .bit = 30, }, + { }, +}; + +static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks[] = { + { .name = "adsl-ubus", .bit = 0, }, + { .name = "arb-ubus", .bit = 1, .flags = CLK_IS_CRITICAL, }, + { .name = "mips-ubus", .bit = 2, .flags = CLK_IS_CRITICAL, }, + { .name = "pcie-ubus", .bit = 3, }, + { .name = "periph-ubus", .bit = 4, .flags = CLK_IS_CRITICAL, }, + { .name = "phymips-ubus", .bit = 5, }, + { .name = "robosw-ubus", .bit = 6, }, + { .name = "sar-ubus", .bit = 7, }, + { .name = "sdr-ubus", .bit = 8, }, + { .name = "usb-ubus", .bit = 9, }, + { }, +}; + static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = { { .name = "phy_mips", .bit = 0, }, { .name = "adsl_qproc", .bit = 1, }, @@ -218,6 +260,8 @@ static int clk_bcm63xx_remove(struct platform_device *pdev) static const struct of_device_id clk_bcm63xx_dt_ids[] = { { .compatible = "brcm,bcm3368-clocks", .data = &bcm3368_clocks, }, + { .compatible = "brcm,bcm6318-clocks", .data = &bcm6318_clocks, }, + { .compatible = "brcm,bcm6318-ubus-clocks", .data = &bcm6318_ubus_clocks, }, { .compatible = "brcm,bcm6328-clocks", .data = &bcm6328_clocks, }, { .compatible = "brcm,bcm6358-clocks", .data = &bcm6358_clocks, }, { .compatible = "brcm,bcm6362-clocks", .data = &bcm6362_clocks, }, From c7f03eea07682639ef320aab348b706c330941dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:24 +0200 Subject: [PATCH 06/94] mips: bmips: add BCM3368 clock definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add header with BCM3368 definitions in order to be able to include it from device tree files. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-2-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/bcm3368-clock.h | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 include/dt-bindings/clock/bcm3368-clock.h diff --git a/include/dt-bindings/clock/bcm3368-clock.h b/include/dt-bindings/clock/bcm3368-clock.h new file mode 100644 index 000000000000..74a7382f77b8 --- /dev/null +++ b/include/dt-bindings/clock/bcm3368-clock.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_CLOCK_BCM3368_H +#define __DT_BINDINGS_CLOCK_BCM3368_H + +#define BCM3368_CLK_MAC 3 +#define BCM3368_CLK_TC 5 +#define BCM3368_CLK_US_TOP 6 +#define BCM3368_CLK_DS_TOP 7 +#define BCM3368_CLK_ACM 8 +#define BCM3368_CLK_SPI 9 +#define BCM3368_CLK_USBS 10 +#define BCM3368_CLK_BMU 11 +#define BCM3368_CLK_PCM 12 +#define BCM3368_CLK_NTP 13 +#define BCM3368_CLK_ACP_B 14 +#define BCM3368_CLK_ACP_A 15 +#define BCM3368_CLK_EMUSB 17 +#define BCM3368_CLK_ENET0 18 +#define BCM3368_CLK_ENET1 19 +#define BCM3368_CLK_USBSU 20 +#define BCM3368_CLK_EPHY 21 + +#endif /* __DT_BINDINGS_CLOCK_BCM3368_H */ From 020c89c5a981cb6d0424aadab8ae067a3b6bd8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:25 +0200 Subject: [PATCH 07/94] mips: bmips: add BCM6318 clock definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add header with BCM6318 definitions in order to be able to include it from device tree files. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-3-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/bcm6318-clock.h | 42 +++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 include/dt-bindings/clock/bcm6318-clock.h diff --git a/include/dt-bindings/clock/bcm6318-clock.h b/include/dt-bindings/clock/bcm6318-clock.h new file mode 100644 index 000000000000..c4417f8983ab --- /dev/null +++ b/include/dt-bindings/clock/bcm6318-clock.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_CLOCK_BCM6318_H +#define __DT_BINDINGS_CLOCK_BCM6318_H + +#define BCM6318_CLK_ADSL_ASB 0 +#define BCM6318_CLK_USB_ASB 1 +#define BCM6318_CLK_MIPS_ASB 2 +#define BCM6318_CLK_PCIE_ASB 3 +#define BCM6318_CLK_PHYMIPS_ASB 4 +#define BCM6318_CLK_ROBOSW_ASB 5 +#define BCM6318_CLK_SAR_ASB 6 +#define BCM6318_CLK_SDR_ASB 7 +#define BCM6318_CLK_SWREG_ASB 8 +#define BCM6318_CLK_PERIPH_ASB 9 +#define BCM6318_CLK_CPUBUS160 10 +#define BCM6318_CLK_ADSL 11 +#define BCM6318_CLK_SAR125 12 +#define BCM6318_CLK_MIPS 13 +#define BCM6318_CLK_PCIE 14 +#define BCM6318_CLK_ROBOSW250 16 +#define BCM6318_CLK_ROBOSW025 17 +#define BCM6318_CLK_SDR 19 +#define BCM6318_CLK_USBD 20 +#define BCM6318_CLK_HSSPI 25 +#define BCM6318_CLK_PCIE25 27 +#define BCM6318_CLK_PHYMIPS 28 +#define BCM6318_CLK_AFE 29 +#define BCM6318_CLK_QPROC 30 + +#define BCM6318_UCLK_ADSL 0 +#define BCM6318_UCLK_ARB 1 +#define BCM6318_UCLK_MIPS 2 +#define BCM6318_UCLK_PCIE 3 +#define BCM6318_UCLK_PERIPH 4 +#define BCM6318_UCLK_PHYMIPS 5 +#define BCM6318_UCLK_ROBOSW 6 +#define BCM6318_UCLK_SAR 7 +#define BCM6318_UCLK_SDR 8 +#define BCM6318_UCLK_USB 9 + +#endif /* __DT_BINDINGS_CLOCK_BCM6318_H */ From 92cd8bb27a692d93ba7442ec123e96528f5e992c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:26 +0200 Subject: [PATCH 08/94] mips: bmips: add BCM6328 clock definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add header with BCM6328 definitions in order to be able to include it from device tree files. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-4-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/bcm6328-clock.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 include/dt-bindings/clock/bcm6328-clock.h diff --git a/include/dt-bindings/clock/bcm6328-clock.h b/include/dt-bindings/clock/bcm6328-clock.h new file mode 100644 index 000000000000..1f6a3103f3dc --- /dev/null +++ b/include/dt-bindings/clock/bcm6328-clock.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_CLOCK_BCM6328_H +#define __DT_BINDINGS_CLOCK_BCM6328_H + +#define BCM6328_CLK_PHYMIPS 0 +#define BCM6328_CLK_ADSL_QPROC 1 +#define BCM6328_CLK_ADSL_AFE 2 +#define BCM6328_CLK_ADSL 3 +#define BCM6328_CLK_MIPS 4 +#define BCM6328_CLK_SAR 5 +#define BCM6328_CLK_PCM 6 +#define BCM6328_CLK_USBD 7 +#define BCM6328_CLK_USBH 8 +#define BCM6328_CLK_HSSPI 9 +#define BCM6328_CLK_PCIE 10 +#define BCM6328_CLK_ROBOSW 11 + +#endif /* __DT_BINDINGS_CLOCK_BCM6328_H */ From d3499bda4e176de6853c24e5243f3906d9390d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:27 +0200 Subject: [PATCH 09/94] mips: bmips: add BCM6358 clock definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add header with BCM6358 definitions in order to be able to include it from device tree files. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-5-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/bcm6358-clock.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 include/dt-bindings/clock/bcm6358-clock.h diff --git a/include/dt-bindings/clock/bcm6358-clock.h b/include/dt-bindings/clock/bcm6358-clock.h new file mode 100644 index 000000000000..980c9cac4765 --- /dev/null +++ b/include/dt-bindings/clock/bcm6358-clock.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_CLOCK_BCM6358_H +#define __DT_BINDINGS_CLOCK_BCM6358_H + +#define BCM6358_CLK_ENET 4 +#define BCM6358_CLK_ADSLPHY 5 +#define BCM6358_CLK_PCM 8 +#define BCM6358_CLK_SPI 9 +#define BCM6358_CLK_USBS 10 +#define BCM6358_CLK_SAR 11 +#define BCM6358_CLK_EMUSB 17 +#define BCM6358_CLK_ENET0 18 +#define BCM6358_CLK_ENET1 19 +#define BCM6358_CLK_USBSU 20 +#define BCM6358_CLK_EPHY 21 + +#endif /* __DT_BINDINGS_CLOCK_BCM6358_H */ From fb8fb3f13f86fda0af72c02691333fdba5164c20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:28 +0200 Subject: [PATCH 10/94] mips: bmips: add BCM6362 clock definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add header with BCM6362 definitions in order to be able to include it from device tree files. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-6-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/bcm6362-clock.h | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 include/dt-bindings/clock/bcm6362-clock.h diff --git a/include/dt-bindings/clock/bcm6362-clock.h b/include/dt-bindings/clock/bcm6362-clock.h new file mode 100644 index 000000000000..17655cd5bf25 --- /dev/null +++ b/include/dt-bindings/clock/bcm6362-clock.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_CLOCK_BCM6362_H +#define __DT_BINDINGS_CLOCK_BCM6362_H + +#define BCM6362_CLK_ADSL_QPROC 1 +#define BCM6362_CLK_ADSL_AFE 2 +#define BCM6362_CLK_ADSL 3 +#define BCM6362_CLK_MIPS 4 +#define BCM6362_CLK_WLAN_OCP 5 +#define BCM6362_CLK_SWPKT_USB 7 +#define BCM6362_CLK_SWPKT_SAR 8 +#define BCM6362_CLK_SAR 9 +#define BCM6362_CLK_ROBOSW 10 +#define BCM6362_CLK_PCM 11 +#define BCM6362_CLK_USBD 12 +#define BCM6362_CLK_USBH 13 +#define BCM6362_CLK_IPSEC 14 +#define BCM6362_CLK_SPI 15 +#define BCM6362_CLK_HSSPI 16 +#define BCM6362_CLK_PCIE 17 +#define BCM6362_CLK_FAP 18 +#define BCM6362_CLK_PHYMIPS 19 +#define BCM6362_CLK_NAND 20 + +#endif /* __DT_BINDINGS_CLOCK_BCM6362_H */ From ad31e793f246d5276bc24829cb3d1ca95c3c92ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:29 +0200 Subject: [PATCH 11/94] mips: bmips: add BCM6368 clock definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add header with BCM6368 definitions in order to be able to include it from device tree files. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-7-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/bcm6368-clock.h | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 include/dt-bindings/clock/bcm6368-clock.h diff --git a/include/dt-bindings/clock/bcm6368-clock.h b/include/dt-bindings/clock/bcm6368-clock.h new file mode 100644 index 000000000000..f161d5333883 --- /dev/null +++ b/include/dt-bindings/clock/bcm6368-clock.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_CLOCK_BCM6368_H +#define __DT_BINDINGS_CLOCK_BCM6368_H + +#define BCM6368_CLK_VDSL_QPROC 2 +#define BCM6368_CLK_VDSL_AFE 3 +#define BCM6368_CLK_VDSL_BONDING 4 +#define BCM6368_CLK_VDSL 5 +#define BCM6368_CLK_PHYMIPS 6 +#define BCM6368_CLK_SWPKT_USB 7 +#define BCM6368_CLK_SWPKT_SAR 8 +#define BCM6368_CLK_SPI 9 +#define BCM6368_CLK_USBD 10 +#define BCM6368_CLK_SAR 11 +#define BCM6368_CLK_ROBOSW 12 +#define BCM6368_CLK_UTOPIA 13 +#define BCM6368_CLK_PCM 14 +#define BCM6368_CLK_USBH 15 +#define BCM6368_CLK_DIS_GLESS 16 +#define BCM6368_CLK_NAND 17 +#define BCM6368_CLK_IPSEC 18 + +#endif /* __DT_BINDINGS_CLOCK_BCM6368_H */ From f3cd8c96a97ca970a116af092555778f792d0abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:30 +0200 Subject: [PATCH 12/94] mips: bmips: add BCM63268 clock definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add header with BCM63268 definitions in order to be able to include it from device tree files. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-8-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/bcm63268-clock.h | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 include/dt-bindings/clock/bcm63268-clock.h diff --git a/include/dt-bindings/clock/bcm63268-clock.h b/include/dt-bindings/clock/bcm63268-clock.h new file mode 100644 index 000000000000..da23e691d359 --- /dev/null +++ b/include/dt-bindings/clock/bcm63268-clock.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#ifndef __DT_BINDINGS_CLOCK_BCM63268_H +#define __DT_BINDINGS_CLOCK_BCM63268_H + +#define BCM63268_CLK_DIS_GLESS 0 +#define BCM63268_CLK_VDSL_QPROC 1 +#define BCM63268_CLK_VDSL_AFE 2 +#define BCM63268_CLK_VDSL 3 +#define BCM63268_CLK_MIPS 4 +#define BCM63268_CLK_WLAN_OCP 5 +#define BCM63268_CLK_DECT 6 +#define BCM63268_CLK_FAP0 7 +#define BCM63268_CLK_FAP1 8 +#define BCM63268_CLK_SAR 9 +#define BCM63268_CLK_ROBOSW 10 +#define BCM63268_CLK_PCM 11 +#define BCM63268_CLK_USBD 12 +#define BCM63268_CLK_USBH 13 +#define BCM63268_CLK_IPSEC 14 +#define BCM63268_CLK_SPI 15 +#define BCM63268_CLK_HSSPI 16 +#define BCM63268_CLK_PCIE 17 +#define BCM63268_CLK_PHYMIPS 18 +#define BCM63268_CLK_GMAC 19 +#define BCM63268_CLK_NAND 20 +#define BCM63268_CLK_TBUS 27 +#define BCM63268_CLK_ROBOSW250 31 + +#endif /* __DT_BINDINGS_CLOCK_BCM63268_H */ From e244d2058dcdff6c7ac21efefed75eba43525140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= Date: Mon, 15 Jun 2020 11:02:31 +0200 Subject: [PATCH 13/94] clk: bcm63xx-gate: switch to dt-bindings definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that there are header files for each SoC, let's use them in the bcm63xx-gate controller driver. Signed-off-by: Álvaro Fernández Rojas Link: https://lore.kernel.org/r/20200615090231.2932696-9-noltari@gmail.com Acked-by: Florian Fainelli Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm63xx-gate.c | 580 ++++++++++++++++++++++------- 1 file changed, 439 insertions(+), 141 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm63xx-gate.c b/drivers/clk/bcm/clk-bcm63xx-gate.c index 43853add44cb..89297c57881e 100644 --- a/drivers/clk/bcm/clk-bcm63xx-gate.c +++ b/drivers/clk/bcm/clk-bcm63xx-gate.c @@ -6,6 +6,14 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + struct clk_bcm63xx_table_entry { const char * const name; u8 bit; @@ -20,168 +28,458 @@ struct clk_bcm63xx_hw { }; static const struct clk_bcm63xx_table_entry bcm3368_clocks[] = { - { .name = "mac", .bit = 3, }, - { .name = "tc", .bit = 5, }, - { .name = "us_top", .bit = 6, }, - { .name = "ds_top", .bit = 7, }, - { .name = "acm", .bit = 8, }, - { .name = "spi", .bit = 9, }, - { .name = "usbs", .bit = 10, }, - { .name = "bmu", .bit = 11, }, - { .name = "pcm", .bit = 12, }, - { .name = "ntp", .bit = 13, }, - { .name = "acp_b", .bit = 14, }, - { .name = "acp_a", .bit = 15, }, - { .name = "emusb", .bit = 17, }, - { .name = "enet0", .bit = 18, }, - { .name = "enet1", .bit = 19, }, - { .name = "usbsu", .bit = 20, }, - { .name = "ephy", .bit = 21, }, - { }, + { + .name = "mac", + .bit = BCM3368_CLK_MAC, + }, { + .name = "tc", + .bit = BCM3368_CLK_TC, + }, { + .name = "us_top", + .bit = BCM3368_CLK_US_TOP, + }, { + .name = "ds_top", + .bit = BCM3368_CLK_DS_TOP, + }, { + .name = "acm", + .bit = BCM3368_CLK_ACM, + }, { + .name = "spi", + .bit = BCM3368_CLK_SPI, + }, { + .name = "usbs", + .bit = BCM3368_CLK_USBS, + }, { + .name = "bmu", + .bit = BCM3368_CLK_BMU, + }, { + .name = "pcm", + .bit = BCM3368_CLK_PCM, + }, { + .name = "ntp", + .bit = BCM3368_CLK_NTP, + }, { + .name = "acp_b", + .bit = BCM3368_CLK_ACP_B, + }, { + .name = "acp_a", + .bit = BCM3368_CLK_ACP_A, + }, { + .name = "emusb", + .bit = BCM3368_CLK_EMUSB, + }, { + .name = "enet0", + .bit = BCM3368_CLK_ENET0, + }, { + .name = "enet1", + .bit = BCM3368_CLK_ENET1, + }, { + .name = "usbsu", + .bit = BCM3368_CLK_USBSU, + }, { + .name = "ephy", + .bit = BCM3368_CLK_EPHY, + }, { + /* sentinel */ + }, }; static const struct clk_bcm63xx_table_entry bcm6318_clocks[] = { - { .name = "adsl_asb", .bit = 0, }, - { .name = "usb_asb", .bit = 1, }, - { .name = "mips_asb", .bit = 2, }, - { .name = "pcie_asb", .bit = 3, }, - { .name = "phymips_asb", .bit = 4, }, - { .name = "robosw_asb", .bit = 5, }, - { .name = "sar_asb", .bit = 6, }, - { .name = "sdr_asb", .bit = 7, }, - { .name = "swreg_asb", .bit = 8, }, - { .name = "periph_asb", .bit = 9, }, - { .name = "cpubus160", .bit = 10, }, - { .name = "adsl", .bit = 11, }, - { .name = "sar125", .bit = 12, }, - { .name = "mips", .bit = 13, .flags = CLK_IS_CRITICAL, }, - { .name = "pcie", .bit = 14, }, - { .name = "robosw250", .bit = 16, }, - { .name = "robosw025", .bit = 17, }, - { .name = "sdr", .bit = 19, .flags = CLK_IS_CRITICAL, }, - { .name = "usbd", .bit = 20, }, - { .name = "hsspi", .bit = 25, }, - { .name = "pcie25", .bit = 27, }, - { .name = "phymips", .bit = 28, }, - { .name = "afe", .bit = 29, }, - { .name = "qproc", .bit = 30, }, - { }, + { + .name = "adsl_asb", + .bit = BCM6318_CLK_ADSL_ASB, + }, { + .name = "usb_asb", + .bit = BCM6318_CLK_USB_ASB, + }, { + .name = "mips_asb", + .bit = BCM6318_CLK_MIPS_ASB, + }, { + .name = "pcie_asb", + .bit = BCM6318_CLK_PCIE_ASB, + }, { + .name = "phymips_asb", + .bit = BCM6318_CLK_PHYMIPS_ASB, + }, { + .name = "robosw_asb", + .bit = BCM6318_CLK_ROBOSW_ASB, + }, { + .name = "sar_asb", + .bit = BCM6318_CLK_SAR_ASB, + }, { + .name = "sdr_asb", + .bit = BCM6318_CLK_SDR_ASB, + }, { + .name = "swreg_asb", + .bit = BCM6318_CLK_SWREG_ASB, + }, { + .name = "periph_asb", + .bit = BCM6318_CLK_PERIPH_ASB, + }, { + .name = "cpubus160", + .bit = BCM6318_CLK_CPUBUS160, + }, { + .name = "adsl", + .bit = BCM6318_CLK_ADSL, + }, { + .name = "sar125", + .bit = BCM6318_CLK_SAR125, + }, { + .name = "mips", + .bit = BCM6318_CLK_MIPS, + .flags = CLK_IS_CRITICAL, + }, { + .name = "pcie", + .bit = BCM6318_CLK_PCIE, + }, { + .name = "robosw250", + .bit = BCM6318_CLK_ROBOSW250, + }, { + .name = "robosw025", + .bit = BCM6318_CLK_ROBOSW025, + }, { + .name = "sdr", + .bit = BCM6318_CLK_SDR, + .flags = CLK_IS_CRITICAL, + }, { + .name = "usbd", + .bit = BCM6318_CLK_USBD, + }, { + .name = "hsspi", + .bit = BCM6318_CLK_HSSPI, + }, { + .name = "pcie25", + .bit = BCM6318_CLK_PCIE25, + }, { + .name = "phymips", + .bit = BCM6318_CLK_PHYMIPS, + }, { + .name = "afe", + .bit = BCM6318_CLK_AFE, + }, { + .name = "qproc", + .bit = BCM6318_CLK_QPROC, + }, { + /* sentinel */ + }, }; static const struct clk_bcm63xx_table_entry bcm6318_ubus_clocks[] = { - { .name = "adsl-ubus", .bit = 0, }, - { .name = "arb-ubus", .bit = 1, .flags = CLK_IS_CRITICAL, }, - { .name = "mips-ubus", .bit = 2, .flags = CLK_IS_CRITICAL, }, - { .name = "pcie-ubus", .bit = 3, }, - { .name = "periph-ubus", .bit = 4, .flags = CLK_IS_CRITICAL, }, - { .name = "phymips-ubus", .bit = 5, }, - { .name = "robosw-ubus", .bit = 6, }, - { .name = "sar-ubus", .bit = 7, }, - { .name = "sdr-ubus", .bit = 8, }, - { .name = "usb-ubus", .bit = 9, }, - { }, + { + .name = "adsl-ubus", + .bit = BCM6318_UCLK_ADSL, + }, { + .name = "arb-ubus", + .bit = BCM6318_UCLK_ARB, + .flags = CLK_IS_CRITICAL, + }, { + .name = "mips-ubus", + .bit = BCM6318_UCLK_MIPS, + .flags = CLK_IS_CRITICAL, + }, { + .name = "pcie-ubus", + .bit = BCM6318_UCLK_PCIE, + }, { + .name = "periph-ubus", + .bit = BCM6318_UCLK_PERIPH, + .flags = CLK_IS_CRITICAL, + }, { + .name = "phymips-ubus", + .bit = BCM6318_UCLK_PHYMIPS, + }, { + .name = "robosw-ubus", + .bit = BCM6318_UCLK_ROBOSW, + }, { + .name = "sar-ubus", + .bit = BCM6318_UCLK_SAR, + }, { + .name = "sdr-ubus", + .bit = BCM6318_UCLK_SDR, + }, { + .name = "usb-ubus", + .bit = BCM6318_UCLK_USB, + }, { + /* sentinel */ + }, }; static const struct clk_bcm63xx_table_entry bcm6328_clocks[] = { - { .name = "phy_mips", .bit = 0, }, - { .name = "adsl_qproc", .bit = 1, }, - { .name = "adsl_afe", .bit = 2, }, - { .name = "adsl", .bit = 3, }, - { .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, }, - { .name = "sar", .bit = 5, }, - { .name = "pcm", .bit = 6, }, - { .name = "usbd", .bit = 7, }, - { .name = "usbh", .bit = 8, }, - { .name = "hsspi", .bit = 9, }, - { .name = "pcie", .bit = 10, }, - { .name = "robosw", .bit = 11, }, - { }, + { + .name = "phy_mips", + .bit = BCM6328_CLK_PHYMIPS, + }, { + .name = "adsl_qproc", + .bit = BCM6328_CLK_ADSL_QPROC, + }, { + .name = "adsl_afe", + .bit = BCM6328_CLK_ADSL_AFE, + }, { + .name = "adsl", + .bit = BCM6328_CLK_ADSL, + }, { + .name = "mips", + .bit = BCM6328_CLK_MIPS, + .flags = CLK_IS_CRITICAL, + }, { + .name = "sar", + .bit = BCM6328_CLK_SAR, + }, { + .name = "pcm", + .bit = BCM6328_CLK_PCM, + }, { + .name = "usbd", + .bit = BCM6328_CLK_USBD, + }, { + .name = "usbh", + .bit = BCM6328_CLK_USBH, + }, { + .name = "hsspi", + .bit = BCM6328_CLK_HSSPI, + }, { + .name = "pcie", + .bit = BCM6328_CLK_PCIE, + }, { + .name = "robosw", + .bit = BCM6328_CLK_ROBOSW, + }, { + /* sentinel */ + }, }; static const struct clk_bcm63xx_table_entry bcm6358_clocks[] = { - { .name = "enet", .bit = 4, }, - { .name = "adslphy", .bit = 5, }, - { .name = "pcm", .bit = 8, }, - { .name = "spi", .bit = 9, }, - { .name = "usbs", .bit = 10, }, - { .name = "sar", .bit = 11, }, - { .name = "emusb", .bit = 17, }, - { .name = "enet0", .bit = 18, }, - { .name = "enet1", .bit = 19, }, - { .name = "usbsu", .bit = 20, }, - { .name = "ephy", .bit = 21, }, - { }, + { + .name = "enet", + .bit = BCM6358_CLK_ENET, + }, { + .name = "adslphy", + .bit = BCM6358_CLK_ADSLPHY, + }, { + .name = "pcm", + .bit = BCM6358_CLK_PCM, + }, { + .name = "spi", + .bit = BCM6358_CLK_SPI, + }, { + .name = "usbs", + .bit = BCM6358_CLK_USBS, + }, { + .name = "sar", + .bit = BCM6358_CLK_SAR, + }, { + .name = "emusb", + .bit = BCM6358_CLK_EMUSB, + }, { + .name = "enet0", + .bit = BCM6358_CLK_ENET0, + }, { + .name = "enet1", + .bit = BCM6358_CLK_ENET1, + }, { + .name = "usbsu", + .bit = BCM6358_CLK_USBSU, + }, { + .name = "ephy", + .bit = BCM6358_CLK_EPHY, + }, { + /* sentinel */ + }, }; static const struct clk_bcm63xx_table_entry bcm6362_clocks[] = { - { .name = "adsl_qproc", .bit = 1, }, - { .name = "adsl_afe", .bit = 2, }, - { .name = "adsl", .bit = 3, }, - { .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, }, - { .name = "wlan_ocp", .bit = 5, }, - { .name = "swpkt_usb", .bit = 7, }, - { .name = "swpkt_sar", .bit = 8, }, - { .name = "sar", .bit = 9, }, - { .name = "robosw", .bit = 10, }, - { .name = "pcm", .bit = 11, }, - { .name = "usbd", .bit = 12, }, - { .name = "usbh", .bit = 13, }, - { .name = "ipsec", .bit = 14, }, - { .name = "spi", .bit = 15, }, - { .name = "hsspi", .bit = 16, }, - { .name = "pcie", .bit = 17, }, - { .name = "fap", .bit = 18, }, - { .name = "phymips", .bit = 19, }, - { .name = "nand", .bit = 20, }, - { }, + { + .name = "adsl_qproc", + .bit = BCM6362_CLK_ADSL_QPROC, + }, { + .name = "adsl_afe", + .bit = BCM6362_CLK_ADSL_AFE, + }, { + .name = "adsl", + .bit = BCM6362_CLK_ADSL, + }, { + .name = "mips", + .bit = BCM6362_CLK_MIPS, + .flags = CLK_IS_CRITICAL, + }, { + .name = "wlan_ocp", + .bit = BCM6362_CLK_WLAN_OCP, + }, { + .name = "swpkt_usb", + .bit = BCM6362_CLK_SWPKT_USB, + }, { + .name = "swpkt_sar", + .bit = BCM6362_CLK_SWPKT_SAR, + }, { + .name = "sar", + .bit = BCM6362_CLK_SAR, + }, { + .name = "robosw", + .bit = BCM6362_CLK_ROBOSW, + }, { + .name = "pcm", + .bit = BCM6362_CLK_PCM, + }, { + .name = "usbd", + .bit = BCM6362_CLK_USBD, + }, { + .name = "usbh", + .bit = BCM6362_CLK_USBH, + }, { + .name = "ipsec", + .bit = BCM6362_CLK_IPSEC, + }, { + .name = "spi", + .bit = BCM6362_CLK_SPI, + }, { + .name = "hsspi", + .bit = BCM6362_CLK_HSSPI, + }, { + .name = "pcie", + .bit = BCM6362_CLK_PCIE, + }, { + .name = "fap", + .bit = BCM6362_CLK_FAP, + }, { + .name = "phymips", + .bit = BCM6362_CLK_PHYMIPS, + }, { + .name = "nand", + .bit = BCM6362_CLK_NAND, + }, { + /* sentinel */ + }, }; static const struct clk_bcm63xx_table_entry bcm6368_clocks[] = { - { .name = "vdsl_qproc", .bit = 2, }, - { .name = "vdsl_afe", .bit = 3, }, - { .name = "vdsl_bonding", .bit = 4, }, - { .name = "vdsl", .bit = 5, }, - { .name = "phymips", .bit = 6, }, - { .name = "swpkt_usb", .bit = 7, }, - { .name = "swpkt_sar", .bit = 8, }, - { .name = "spi", .bit = 9, }, - { .name = "usbd", .bit = 10, }, - { .name = "sar", .bit = 11, }, - { .name = "robosw", .bit = 12, }, - { .name = "utopia", .bit = 13, }, - { .name = "pcm", .bit = 14, }, - { .name = "usbh", .bit = 15, }, - { .name = "disable_gless", .bit = 16, }, - { .name = "nand", .bit = 17, }, - { .name = "ipsec", .bit = 18, }, - { }, + { + .name = "vdsl_qproc", + .bit = BCM6368_CLK_VDSL_QPROC, + }, { + .name = "vdsl_afe", + .bit = BCM6368_CLK_VDSL_AFE, + }, { + .name = "vdsl_bonding", + .bit = BCM6368_CLK_VDSL_BONDING, + }, { + .name = "vdsl", + .bit = BCM6368_CLK_VDSL, + }, { + .name = "phymips", + .bit = BCM6368_CLK_PHYMIPS, + }, { + .name = "swpkt_usb", + .bit = BCM6368_CLK_SWPKT_USB, + }, { + .name = "swpkt_sar", + .bit = BCM6368_CLK_SWPKT_SAR, + }, { + .name = "spi", + .bit = BCM6368_CLK_SPI, + }, { + .name = "usbd", + .bit = BCM6368_CLK_USBD, + }, { + .name = "sar", + .bit = BCM6368_CLK_SAR, + }, { + .name = "robosw", + .bit = BCM6368_CLK_ROBOSW, + }, { + .name = "utopia", + .bit = BCM6368_CLK_UTOPIA, + }, { + .name = "pcm", + .bit = BCM6368_CLK_PCM, + }, { + .name = "usbh", + .bit = BCM6368_CLK_USBH, + }, { + .name = "disable_gless", + .bit = BCM6368_CLK_DIS_GLESS, + }, { + .name = "nand", + .bit = BCM6368_CLK_NAND, + }, { + .name = "ipsec", + .bit = BCM6368_CLK_IPSEC, + }, { + /* sentinel */ + }, }; static const struct clk_bcm63xx_table_entry bcm63268_clocks[] = { - { .name = "disable_gless", .bit = 0, }, - { .name = "vdsl_qproc", .bit = 1, }, - { .name = "vdsl_afe", .bit = 2, }, - { .name = "vdsl", .bit = 3, }, - { .name = "mips", .bit = 4, .flags = CLK_IS_CRITICAL, }, - { .name = "wlan_ocp", .bit = 5, }, - { .name = "dect", .bit = 6, }, - { .name = "fap0", .bit = 7, }, - { .name = "fap1", .bit = 8, }, - { .name = "sar", .bit = 9, }, - { .name = "robosw", .bit = 10, }, - { .name = "pcm", .bit = 11, }, - { .name = "usbd", .bit = 12, }, - { .name = "usbh", .bit = 13, }, - { .name = "ipsec", .bit = 14, }, - { .name = "spi", .bit = 15, }, - { .name = "hsspi", .bit = 16, }, - { .name = "pcie", .bit = 17, }, - { .name = "phymips", .bit = 18, }, - { .name = "gmac", .bit = 19, }, - { .name = "nand", .bit = 20, }, - { .name = "tbus", .bit = 27, }, - { .name = "robosw250", .bit = 31, }, - { }, + { + .name = "disable_gless", + .bit = BCM63268_CLK_DIS_GLESS, + }, { + .name = "vdsl_qproc", + .bit = BCM63268_CLK_VDSL_QPROC, + }, { + .name = "vdsl_afe", + .bit = BCM63268_CLK_VDSL_AFE, + }, { + .name = "vdsl", + .bit = BCM63268_CLK_VDSL, + }, { + .name = "mips", + .bit = BCM63268_CLK_MIPS, + .flags = CLK_IS_CRITICAL, + }, { + .name = "wlan_ocp", + .bit = BCM63268_CLK_WLAN_OCP, + }, { + .name = "dect", + .bit = BCM63268_CLK_DECT, + }, { + .name = "fap0", + .bit = BCM63268_CLK_FAP0, + }, { + .name = "fap1", + .bit = BCM63268_CLK_FAP1, + }, { + .name = "sar", + .bit = BCM63268_CLK_SAR, + }, { + .name = "robosw", + .bit = BCM63268_CLK_ROBOSW, + }, { + .name = "pcm", + .bit = BCM63268_CLK_PCM, + }, { + .name = "usbd", + .bit = BCM63268_CLK_USBD, + }, { + .name = "usbh", + .bit = BCM63268_CLK_USBH, + }, { + .name = "ipsec", + .bit = BCM63268_CLK_IPSEC, + }, { + .name = "spi", + .bit = BCM63268_CLK_SPI, + }, { + .name = "hsspi", + .bit = BCM63268_CLK_HSSPI, + }, { + .name = "pcie", + .bit = BCM63268_CLK_PCIE, + }, { + .name = "phymips", + .bit = BCM63268_CLK_PHYMIPS, + }, { + .name = "gmac", + .bit = BCM63268_CLK_GMAC, + }, { + .name = "nand", + .bit = BCM63268_CLK_NAND, + }, { + .name = "tbus", + .bit = BCM63268_CLK_TBUS, + }, { + .name = "robosw250", + .bit = BCM63268_CLK_ROBOSW250, + }, { + /* sentinel */ + }, }; static int clk_bcm63xx_probe(struct platform_device *pdev) From 8dda00049093786c9ff8cf9474b96aa60ed961cd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 11 Jun 2020 11:23:15 +0200 Subject: [PATCH 14/94] dt-bindings: clock: Add BCM2711 DVP binding The BCM2711 has a unit controlling the HDMI0 and HDMI1 clock and reset signals. Let's add a binding for it. Cc: Philipp Zabel Cc: Rob Herring Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/0b8f09baff1ff3c471631e6f523e2b2cd773ec47.1591867332.git-series.maxime@cerno.tech Acked-by: Stefan Wahren Signed-off-by: Stephen Boyd --- .../bindings/clock/brcm,bcm2711-dvp.yaml | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/brcm,bcm2711-dvp.yaml diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm2711-dvp.yaml b/Documentation/devicetree/bindings/clock/brcm,bcm2711-dvp.yaml new file mode 100644 index 000000000000..08543ecbe35b --- /dev/null +++ b/Documentation/devicetree/bindings/clock/brcm,bcm2711-dvp.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/brcm,bcm2711-dvp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom BCM2711 HDMI DVP Device Tree Bindings + +maintainers: + - Maxime Ripard + +properties: + "#clock-cells": + const: 1 + + "#reset-cells": + const: 1 + + compatible: + const: brcm,brcm2711-dvp + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + +required: + - "#clock-cells" + - "#reset-cells" + - compatible + - reg + - clocks + +additionalProperties: false + +examples: + - | + dvp: clock@7ef00000 { + compatible = "brcm,brcm2711-dvp"; + reg = <0x7ef00000 0x10>; + clocks = <&clk_108MHz>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + +... From 1bc95972715ab81fd3fa9f5b45ace5bb607af1b5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 11 Jun 2020 11:23:16 +0200 Subject: [PATCH 15/94] clk: bcm: Add BCM2711 DVP driver The HDMI block has a block that controls clocks and reset signals to the HDMI0 and HDMI1 controllers. Let's expose that through a clock driver implementing a clock and reset provider. Cc: Michael Turquette Cc: Stephen Boyd Cc: Rob Herring Cc: linux-clk@vger.kernel.org Cc: devicetree@vger.kernel.org Reviewed-by: Stephen Boyd Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/bb60d97fc76b61c2eabef5a02ebd664c0f57ede0.1591867332.git-series.maxime@cerno.tech Acked-by: Stefan Wahren Reviewed-by: Nicolas Saenz Julienne Signed-off-by: Stephen Boyd --- drivers/clk/bcm/Kconfig | 11 +++ drivers/clk/bcm/Makefile | 1 + drivers/clk/bcm/clk-bcm2711-dvp.c | 120 ++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 drivers/clk/bcm/clk-bcm2711-dvp.c diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig index 8c83977a7dc4..784f12c72365 100644 --- a/drivers/clk/bcm/Kconfig +++ b/drivers/clk/bcm/Kconfig @@ -1,4 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only + +config CLK_BCM2711_DVP + tristate "Broadcom BCM2711 DVP support" + depends on ARCH_BCM2835 ||COMPILE_TEST + depends on COMMON_CLK + default ARCH_BCM2835 + select RESET_SIMPLE + help + Enable common clock framework support for the Broadcom BCM2711 + DVP Controller. + config CLK_BCM2835 bool "Broadcom BCM2835 clock support" depends on ARCH_BCM2835 || ARCH_BRCMSTB || COMPILE_TEST diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile index 0070ddf6cdd2..edb66b44cb27 100644 --- a/drivers/clk/bcm/Makefile +++ b/drivers/clk/bcm/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o +obj-$(CONFIG_CLK_BCM2711_DVP) += clk-bcm2711-dvp.o obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835.o obj-$(CONFIG_CLK_BCM2835) += clk-bcm2835-aux.o obj-$(CONFIG_CLK_RASPBERRYPI) += clk-raspberrypi.o diff --git a/drivers/clk/bcm/clk-bcm2711-dvp.c b/drivers/clk/bcm/clk-bcm2711-dvp.c new file mode 100644 index 000000000000..84dbc886e303 --- /dev/null +++ b/drivers/clk/bcm/clk-bcm2711-dvp.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// Copyright 2020 Cerno + +#include +#include +#include +#include +#include + +#define DVP_HT_RPI_SW_INIT 0x04 +#define DVP_HT_RPI_MISC_CONFIG 0x08 + +#define NR_CLOCKS 2 +#define NR_RESETS 6 + +struct clk_dvp { + struct clk_hw_onecell_data *data; + struct reset_simple_data reset; +}; + +static const struct clk_parent_data clk_dvp_parent = { + .index = 0, +}; + +static int clk_dvp_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *data; + struct resource *res; + struct clk_dvp *dvp; + void __iomem *base; + int ret; + + dvp = devm_kzalloc(&pdev->dev, sizeof(*dvp), GFP_KERNEL); + if (!dvp) + return -ENOMEM; + platform_set_drvdata(pdev, dvp); + + dvp->data = devm_kzalloc(&pdev->dev, + struct_size(dvp->data, hws, NR_CLOCKS), + GFP_KERNEL); + if (!dvp->data) + return -ENOMEM; + data = dvp->data; + + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); + if (IS_ERR(base)) + return PTR_ERR(base); + + dvp->reset.rcdev.owner = THIS_MODULE; + dvp->reset.rcdev.nr_resets = NR_RESETS; + dvp->reset.rcdev.ops = &reset_simple_ops; + dvp->reset.rcdev.of_node = pdev->dev.of_node; + dvp->reset.membase = base + DVP_HT_RPI_SW_INIT; + spin_lock_init(&dvp->reset.lock); + + ret = devm_reset_controller_register(&pdev->dev, &dvp->reset.rcdev); + if (ret) + return ret; + + data->hws[0] = clk_hw_register_gate_parent_data(&pdev->dev, + "hdmi0-108MHz", + &clk_dvp_parent, 0, + base + DVP_HT_RPI_MISC_CONFIG, 3, + CLK_GATE_SET_TO_DISABLE, + &dvp->reset.lock); + if (IS_ERR(data->hws[0])) + return PTR_ERR(data->hws[0]); + + data->hws[1] = clk_hw_register_gate_parent_data(&pdev->dev, + "hdmi1-108MHz", + &clk_dvp_parent, 0, + base + DVP_HT_RPI_MISC_CONFIG, 4, + CLK_GATE_SET_TO_DISABLE, + &dvp->reset.lock); + if (IS_ERR(data->hws[1])) { + ret = PTR_ERR(data->hws[1]); + goto unregister_clk0; + } + + data->num = NR_CLOCKS; + ret = of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_onecell_get, + data); + if (ret) + goto unregister_clk1; + + return 0; + +unregister_clk1: + clk_hw_unregister_gate(data->hws[1]); + +unregister_clk0: + clk_hw_unregister_gate(data->hws[0]); + return ret; +}; + +static int clk_dvp_remove(struct platform_device *pdev) +{ + struct clk_dvp *dvp = platform_get_drvdata(pdev); + struct clk_hw_onecell_data *data = dvp->data; + + clk_hw_unregister_gate(data->hws[1]); + clk_hw_unregister_gate(data->hws[0]); + + return 0; +} + +static const struct of_device_id clk_dvp_dt_ids[] = { + { .compatible = "brcm,brcm2711-dvp", }, + { /* sentinel */ } +}; + +static struct platform_driver clk_dvp_driver = { + .probe = clk_dvp_probe, + .remove = clk_dvp_remove, + .driver = { + .name = "brcm2711-dvp", + .of_match_table = clk_dvp_dt_ids, + }, +}; +module_platform_driver(clk_dvp_driver); From d4c708c032df3d95de297232e20041737e99d126 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 15 Jun 2020 10:40:41 +0200 Subject: [PATCH 16/94] dt-bindings: arm: bcm: Convert BCM2835 firmware binding to YAML Convert the Raspberry Pi BCM2835 firmware binding document to YAML. Verified with dt_binding_check and dtbs_check. Signed-off-by: Florian Fainelli Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/5bc0b9be8544b07300fccab4d4f26e5e5d8e62b2.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- .../arm/bcm/raspberrypi,bcm2835-firmware.txt | 14 -------- .../arm/bcm/raspberrypi,bcm2835-firmware.yaml | 35 +++++++++++++++++++ 2 files changed, 35 insertions(+), 14 deletions(-) delete mode 100644 Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.txt create mode 100644 Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.txt b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.txt deleted file mode 100644 index 6824b3180ffb..000000000000 --- a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.txt +++ /dev/null @@ -1,14 +0,0 @@ -Raspberry Pi VideoCore firmware driver - -Required properties: - -- compatible: Should be "raspberrypi,bcm2835-firmware" -- mboxes: Phandle to the firmware device's Mailbox. - (See: ../mailbox/mailbox.txt for more information) - -Example: - -firmware { - compatible = "raspberrypi,bcm2835-firmware"; - mboxes = <&mailbox>; -}; diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml new file mode 100644 index 000000000000..cec540c052b6 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/bcm/raspberrypi,bcm2835-firmware.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Raspberry Pi VideoCore firmware driver + +maintainers: + - Eric Anholt + - Stefan Wahren + +properties: + compatible: + items: + - const: raspberrypi,bcm2835-firmware + - const: simple-bus + + mboxes: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: | + Phandle to the firmware device's Mailbox. + (See: ../mailbox/mailbox.txt for more information) + +required: + - compatible + - mboxes + +examples: + - | + firmware { + compatible = "raspberrypi,bcm2835-firmware", "simple-bus"; + mboxes = <&mailbox>; + }; +... From 74a0caa5ef1c25905c4409b350ed9a8e0d9a3b74 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:42 +0200 Subject: [PATCH 17/94] dt-bindings: clock: Add a binding for the RPi Firmware clocks The firmware running on the RPi VideoCore can be used to discover and change the various clocks running in the BCM2711. Since devices will need to use them through the DT, let's add a pretty simple binding. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Cc: devicetree@vger.kernel.org Reviewed-by: Stephen Boyd Reviewed-by: Rob Herring Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/f6105207e7ef5a5ea8d7a1774faf989d341a25f5.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- .../arm/bcm/raspberrypi,bcm2835-firmware.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml index cec540c052b6..b48ed875eb8e 100644 --- a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml +++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml @@ -22,6 +22,25 @@ properties: Phandle to the firmware device's Mailbox. (See: ../mailbox/mailbox.txt for more information) + clocks: + type: object + + properties: + compatible: + const: raspberrypi,firmware-clocks + + "#clock-cells": + const: 1 + description: > + The argument is the ID of the clocks contained by the + firmware messages. + + required: + - compatible + - "#clock-cells" + + additionalProperties: false + required: - compatible - mboxes @@ -31,5 +50,10 @@ examples: firmware { compatible = "raspberrypi,bcm2835-firmware", "simple-bus"; mboxes = <&mailbox>; + + firmware_clocks: clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <1>; + }; }; ... From 511aba099cd4c44cb8ad4ca7e2d6ffc034eed743 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:43 +0200 Subject: [PATCH 18/94] firmware: rpi: Only create clocks device if we don't have a node for it The firmware clocks driver was previously probed through a platform_device created by the firmware driver. Since we will now have a node for that clocks driver, we need to create the device only in the case where there's no node for it already. Reviewed-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/72114c4287ebda2dbd952ea238d4489d359897e5.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/firmware/raspberrypi.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c index ef8098856a47..b25901a77c09 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c @@ -208,6 +208,20 @@ rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw) static void rpi_register_clk_driver(struct device *dev) { + struct device_node *firmware; + + /* + * Earlier DTs don't have a node for the firmware clocks but + * rely on us creating a platform device by hand. If we do + * have a node for the firmware clocks, just bail out here. + */ + firmware = of_get_compatible_child(dev->of_node, + "raspberrypi,firmware-clocks"); + if (firmware) { + of_node_put(firmware); + return; + } + rpi_clk = platform_device_register_data(dev, "raspberrypi-clk", -1, NULL, 0); } From fbac2e7787ac6fd2226a5935c80c0ff80d607bce Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:44 +0200 Subject: [PATCH 19/94] clk: bcm: rpi: Allow the driver to be probed by DT The current firmware clock driver for the RaspberryPi can only be probed by manually registering an associated platform_device. While this works fine for cpufreq where the device gets attached a clkdev lookup, it would be tedious to maintain a table of all the devices using one of the clocks exposed by the firmware. Since the DT on the other hand is the perfect place to store those associations, make the firmware clocks driver probe-able through the device tree so that we can represent it as a node. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Reviewed-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/cb8203b862e386ac6c3df3eff0bb5a238b6ec97a.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 1654fd0eedc9..8610355bda47 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -255,8 +255,16 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) struct raspberrypi_clk *rpi; int ret; - firmware_node = of_find_compatible_node(NULL, NULL, - "raspberrypi,bcm2835-firmware"); + /* + * We can be probed either through the an old-fashioned + * platform device registration or through a DT node that is a + * child of the firmware node. Handle both cases. + */ + if (dev->of_node) + firmware_node = of_get_parent(dev->of_node); + else + firmware_node = of_find_compatible_node(NULL, NULL, + "raspberrypi,bcm2835-firmware"); if (!firmware_node) { dev_err(dev, "Missing firmware node\n"); return -ENOENT; @@ -300,9 +308,16 @@ static int raspberrypi_clk_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id raspberrypi_clk_match[] = { + { .compatible = "raspberrypi,firmware-clocks" }, + { }, +}; +MODULE_DEVICE_TABLE(of, raspberrypi_clk_match); + static struct platform_driver raspberrypi_clk_driver = { .driver = { .name = "raspberrypi-clk", + .of_match_table = raspberrypi_clk_match, }, .probe = raspberrypi_clk_probe, .remove = raspberrypi_clk_remove, From 869bd27541fe4eb1468dd4f0ddf76af6dd9b35ac Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:45 +0200 Subject: [PATCH 20/94] clk: bcm: rpi: Statically init clk_init_data Instead of declaring the clk_init_data and then calling memset on it, just initialise properly. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/0342572daa561dc1bb4c9fd10641b2016493e32b.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 8610355bda47..ddc72207212e 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -175,11 +175,10 @@ static const struct clk_ops raspberrypi_firmware_pll_clk_ops = { static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) { + struct clk_init_data init = {}; u32 min_rate = 0, max_rate = 0; - struct clk_init_data init; int ret; - memset(&init, 0, sizeof(init)); /* All of the PLLs derive from the external oscillator. */ init.parent_names = (const char *[]){ "osc" }; From 72856a4ed555892c0c793becebba93fc43c50856 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:46 +0200 Subject: [PATCH 21/94] clk: bcm: rpi: Use clk_hw_register for pllb_arm The pllb_arm clock is defined as a fixed factor clock with the pllb clock as a parent. However, all its configuration is entirely static, and thus we don't really need to call clk_hw_register_fixed_factor() but can simply call clk_hw_register() with a static clk_fixed_factor structure. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/1146177664999eeda65856d28ce94025021dd85e.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index ddc72207212e..5f0d4875e145 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -225,16 +225,28 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) return devm_clk_hw_register(rpi->dev, &rpi->pllb); } +static struct clk_fixed_factor raspberrypi_clk_pllb_arm = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data) { + .name = "pllb_arm", + .parent_names = (const char *[]){ "pllb" }, + .num_parents = 1, + .ops = &clk_fixed_factor_ops, + .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, + }, +}; + static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) { - rpi->pllb_arm = clk_hw_register_fixed_factor(rpi->dev, - "pllb_arm", "pllb", - CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, - 1, 2); - if (IS_ERR(rpi->pllb_arm)) { + int ret; + + ret = clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw); + if (ret) { dev_err(rpi->dev, "Failed to initialize pllb_arm\n"); - return PTR_ERR(rpi->pllb_arm); + return ret; } + rpi->pllb_arm = &raspberrypi_clk_pllb_arm.hw; rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0"); if (!rpi->pllb_arm_lookup) { From c70011a985001e4dec4ce10154b9ff0f00f4140f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:47 +0200 Subject: [PATCH 22/94] clk: bcm: rpi: Remove global pllb_arm clock pointer The pllb_arm clk_hw pointer in the raspberry_clk structure isn't used anywhere but in the raspberrypi_register_pllb_arm. Let's remove it, this will make our lives easier in future patches. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/842859cf1a77478620f45049178a588448202858.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 5f0d4875e145..b21dd6ddc4fe 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -40,7 +40,6 @@ struct raspberrypi_clk { unsigned long max_rate; struct clk_hw pllb; - struct clk_hw *pllb_arm; struct clk_lookup *pllb_arm_lookup; }; @@ -246,12 +245,12 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) dev_err(rpi->dev, "Failed to initialize pllb_arm\n"); return ret; } - rpi->pllb_arm = &raspberrypi_clk_pllb_arm.hw; - rpi->pllb_arm_lookup = clkdev_hw_create(rpi->pllb_arm, NULL, "cpu0"); + rpi->pllb_arm_lookup = clkdev_hw_create(&raspberrypi_clk_pllb_arm.hw, + NULL, "cpu0"); if (!rpi->pllb_arm_lookup) { dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n"); - clk_hw_unregister_fixed_factor(rpi->pllb_arm); + clk_hw_unregister_fixed_factor(&raspberrypi_clk_pllb_arm.hw); return -ENOMEM; } From 683de1868164ec8d252ec9261a5dfd0f9edd7f52 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:48 +0200 Subject: [PATCH 23/94] clk: bcm: rpi: Make sure pllb_arm is removed The pllb_arm clock was created at probe time, but was never removed if something went wrong later in probe, or if the driver was ever removed from the system. Now that we are using clk_hw_register(), we can just use its managed variant to take care of that for us. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/34254ed1556614658e5dad5cca4cf4fe617df7fc.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index b21dd6ddc4fe..d62605861028 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -240,7 +240,7 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) { int ret; - ret = clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw); + ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw); if (ret) { dev_err(rpi->dev, "Failed to initialize pllb_arm\n"); return ret; @@ -250,7 +250,6 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) NULL, "cpu0"); if (!rpi->pllb_arm_lookup) { dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n"); - clk_hw_unregister_fixed_factor(&raspberrypi_clk_pllb_arm.hw); return -ENOMEM; } From 8f60112f66bf3a17ef3206e716064aa76011b94d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:49 +0200 Subject: [PATCH 24/94] clk: bcm: rpi: Remove pllb_arm_lookup global pointer The pllb_arm_lookup pointer in the struct raspberrypi_clk is not used for anything but to store the returned pointer to clkdev_hw_create, and is not used anywhere else in the driver. Let's remove that global pointer from the structure. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/189407f54906d2b07c91de7a4eeb6d8c8934280f.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index d62605861028..5a06c4991c7f 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -40,7 +40,6 @@ struct raspberrypi_clk { unsigned long max_rate; struct clk_hw pllb; - struct clk_lookup *pllb_arm_lookup; }; /* @@ -238,6 +237,7 @@ static struct clk_fixed_factor raspberrypi_clk_pllb_arm = { static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) { + struct clk_lookup *pllb_arm_lookup; int ret; ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw); @@ -246,9 +246,9 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) return ret; } - rpi->pllb_arm_lookup = clkdev_hw_create(&raspberrypi_clk_pllb_arm.hw, - NULL, "cpu0"); - if (!rpi->pllb_arm_lookup) { + pllb_arm_lookup = clkdev_hw_create(&raspberrypi_clk_pllb_arm.hw, + NULL, "cpu0"); + if (!pllb_arm_lookup) { dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n"); return -ENOMEM; } From 55ee6a992dfe9c477da629b1ddf33a0e1bbd83bc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:50 +0200 Subject: [PATCH 25/94] clk: bcm: rpi: Switch to clk_hw_register_clkdev Since we don't care about retrieving the clk_lookup structure pointer returned by clkdev_hw_create, we can just use the clk_hw_register_clkdev function. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/59f6208b6fe3367e735b0cca4f65c2c937639af9.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 5a06c4991c7f..23f06618a356 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -237,7 +237,6 @@ static struct clk_fixed_factor raspberrypi_clk_pllb_arm = { static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) { - struct clk_lookup *pllb_arm_lookup; int ret; ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw); @@ -246,11 +245,11 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) return ret; } - pllb_arm_lookup = clkdev_hw_create(&raspberrypi_clk_pllb_arm.hw, - NULL, "cpu0"); - if (!pllb_arm_lookup) { - dev_err(rpi->dev, "Failed to initialize pllb_arm_lookup\n"); - return -ENOMEM; + ret = clk_hw_register_clkdev(&raspberrypi_clk_pllb_arm.hw, + NULL, "cpu0"); + if (ret) { + dev_err(rpi->dev, "Failed to initialize clkdev\n"); + return ret; } return 0; From 9bd43a6184c2559032a2a8675c135abf7777a736 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:51 +0200 Subject: [PATCH 26/94] clk: bcm: rpi: Make sure the clkdev lookup is removed The clkdev lookup created for the cpufreq device is never removed if there's an issue later in probe or at module removal time. Let's convert to the managed variant of the clk_hw_register_clkdev function to make sure it happens. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/075e2c6d315eccdaf8fb72b320712b86e6c25b22.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 23f06618a356..a20492fade6a 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -245,8 +245,9 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) return ret; } - ret = clk_hw_register_clkdev(&raspberrypi_clk_pllb_arm.hw, - NULL, "cpu0"); + ret = devm_clk_hw_register_clkdev(rpi->dev, + &raspberrypi_clk_pllb_arm.hw, + NULL, "cpu0"); if (ret) { dev_err(rpi->dev, "Failed to initialize clkdev\n"); return ret; From df4b6a4c3bf5b0bc0fb5c35af9ca6da9c78922ee Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:52 +0200 Subject: [PATCH 27/94] clk: bcm: rpi: Use CCF boundaries instead of rolling our own The raspberrypi firmware clock driver has a min_rate / max_rate clamping by storing the info it needs in a private structure. However, the CCF already provides such a facility, so we can switch to it to remove the boilerplate. Reviewed-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/d4c53dab6de5d5f70743d9c139d0117589530e62.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index a20492fade6a..e135ad28d38d 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -36,9 +36,6 @@ struct raspberrypi_clk { struct rpi_firmware *firmware; struct platform_device *cpufreq; - unsigned long min_rate; - unsigned long max_rate; - struct clk_hw pllb; }; @@ -142,13 +139,11 @@ static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, static int raspberrypi_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, - pllb); u64 div, final_rate; u32 ndiv, fdiv; /* We can't use req->rate directly as it would overflow */ - final_rate = clamp(req->rate, rpi->min_rate, rpi->max_rate); + final_rate = clamp(req->rate, req->min_rate, req->max_rate); div = (u64)final_rate << A2W_PLL_FRAC_BITS; do_div(div, req->best_parent_rate); @@ -215,12 +210,15 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n", min_rate, max_rate); - rpi->min_rate = min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE; - rpi->max_rate = max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE; - rpi->pllb.init = &init; - return devm_clk_hw_register(rpi->dev, &rpi->pllb); + ret = devm_clk_hw_register(rpi->dev, &rpi->pllb); + if (!ret) + clk_hw_set_rate_range(&rpi->pllb, + min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE, + max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE); + + return ret; } static struct clk_fixed_factor raspberrypi_clk_pllb_arm = { From f922c560c95613f9aa45e135380bb78d3abbdb35 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:53 +0200 Subject: [PATCH 28/94] clk: bcm: rpi: Create a data structure for the clocks So far the driver has really only been providing a single clock, and stored both the data associated to that clock in particular with the data associated to the "controller". Since we will change that in the future, let's decouple the clock data from the provider data. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/ee7f508db226214fab4add7f93a351f4137c86a1.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index e135ad28d38d..00735704eabc 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -35,8 +35,11 @@ struct raspberrypi_clk { struct device *dev; struct rpi_firmware *firmware; struct platform_device *cpufreq; +}; - struct clk_hw pllb; +struct raspberrypi_clk_data { + struct clk_hw hw; + struct raspberrypi_clk *rpi; }; /* @@ -80,8 +83,9 @@ static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag, static int raspberrypi_fw_pll_is_on(struct clk_hw *hw) { - struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, - pllb); + struct raspberrypi_clk_data *data = + container_of(hw, struct raspberrypi_clk_data, hw); + struct raspberrypi_clk *rpi = data->rpi; u32 val = 0; int ret; @@ -98,8 +102,9 @@ static int raspberrypi_fw_pll_is_on(struct clk_hw *hw) static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, - pllb); + struct raspberrypi_clk_data *data = + container_of(hw, struct raspberrypi_clk_data, hw); + struct raspberrypi_clk *rpi = data->rpi; u32 val = 0; int ret; @@ -116,8 +121,9 @@ static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct raspberrypi_clk *rpi = container_of(hw, struct raspberrypi_clk, - pllb); + struct raspberrypi_clk_data *data = + container_of(hw, struct raspberrypi_clk_data, hw); + struct raspberrypi_clk *rpi = data->rpi; u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE; int ret; @@ -168,10 +174,15 @@ static const struct clk_ops raspberrypi_firmware_pll_clk_ops = { static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) { + struct raspberrypi_clk_data *data; struct clk_init_data init = {}; u32 min_rate = 0, max_rate = 0; int ret; + data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->rpi = rpi; /* All of the PLLs derive from the external oscillator. */ init.parent_names = (const char *[]){ "osc" }; @@ -210,11 +221,11 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n", min_rate, max_rate); - rpi->pllb.init = &init; + data->hw.init = &init; - ret = devm_clk_hw_register(rpi->dev, &rpi->pllb); + ret = devm_clk_hw_register(rpi->dev, &data->hw); if (!ret) - clk_hw_set_rate_range(&rpi->pllb, + clk_hw_set_rate_range(&data->hw, min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE, max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE); From 8a1f3ebc38fca949ad69feb1e536b71360e8cbb4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:54 +0200 Subject: [PATCH 29/94] clk: bcm: rpi: Add clock id to data The driver has really only supported one clock so far and has hardcoded the ID used in communications with the firmware in all the functions implementing the clock framework hooks. Let's store that in the clock data structure so that we can support more clocks later on. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/e23c37961b97b027e21efa3b818578970f88527a.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 00735704eabc..97ac04604b0a 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -39,6 +39,9 @@ struct raspberrypi_clk { struct raspberrypi_clk_data { struct clk_hw hw; + + unsigned int id; + struct raspberrypi_clk *rpi; }; @@ -91,7 +94,7 @@ static int raspberrypi_fw_pll_is_on(struct clk_hw *hw) ret = raspberrypi_clock_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCK_STATE, - RPI_FIRMWARE_ARM_CLK_ID, &val); + data->id, &val); if (ret) return 0; @@ -110,8 +113,7 @@ static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, ret = raspberrypi_clock_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCK_RATE, - RPI_FIRMWARE_ARM_CLK_ID, - &val); + data->id, &val); if (ret) return ret; @@ -129,8 +131,7 @@ static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, ret = raspberrypi_clock_property(rpi->firmware, RPI_FIRMWARE_SET_CLOCK_RATE, - RPI_FIRMWARE_ARM_CLK_ID, - &new_rate); + data->id, &new_rate); if (ret) dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d", clk_hw_get_name(hw), ret); @@ -183,6 +184,7 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) if (!data) return -ENOMEM; data->rpi = rpi; + data->id = RPI_FIRMWARE_ARM_CLK_ID; /* All of the PLLs derive from the external oscillator. */ init.parent_names = (const char *[]){ "osc" }; @@ -194,8 +196,7 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) /* Get min & max rates set by the firmware */ ret = raspberrypi_clock_property(rpi->firmware, RPI_FIRMWARE_GET_MIN_CLOCK_RATE, - RPI_FIRMWARE_ARM_CLK_ID, - &min_rate); + data->id, &min_rate); if (ret) { dev_err(rpi->dev, "Failed to get %s min freq: %d\n", init.name, ret); @@ -204,8 +205,7 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) ret = raspberrypi_clock_property(rpi->firmware, RPI_FIRMWARE_GET_MAX_CLOCK_RATE, - RPI_FIRMWARE_ARM_CLK_ID, - &max_rate); + data->id, &max_rate); if (ret) { dev_err(rpi->dev, "Failed to get %s max freq: %d\n", init.name, ret); From 81df01518879d9d0ccce40564883ac0ba3299c47 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:55 +0200 Subject: [PATCH 30/94] clk: bcm: rpi: Pass the clocks data to the firmware function The raspberry_clock_property only takes the clock ID as an argument, but now that we have a clock data structure it makes more sense to just pass that structure instead. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/d7a3b4df3ca23feb6e0d9c7ae2d232bfb913f926.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 97ac04604b0a..3fce49a65a79 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -65,11 +65,12 @@ struct raspberrypi_firmware_prop { __le32 disable_turbo; } __packed; -static int raspberrypi_clock_property(struct rpi_firmware *firmware, u32 tag, - u32 clk, u32 *val) +static int raspberrypi_clock_property(struct rpi_firmware *firmware, + const struct raspberrypi_clk_data *data, + u32 tag, u32 *val) { struct raspberrypi_firmware_prop msg = { - .id = cpu_to_le32(clk), + .id = cpu_to_le32(data->id), .val = cpu_to_le32(*val), .disable_turbo = cpu_to_le32(1), }; @@ -92,9 +93,8 @@ static int raspberrypi_fw_pll_is_on(struct clk_hw *hw) u32 val = 0; int ret; - ret = raspberrypi_clock_property(rpi->firmware, - RPI_FIRMWARE_GET_CLOCK_STATE, - data->id, &val); + ret = raspberrypi_clock_property(rpi->firmware, data, + RPI_FIRMWARE_GET_CLOCK_STATE, &val); if (ret) return 0; @@ -111,9 +111,8 @@ static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, u32 val = 0; int ret; - ret = raspberrypi_clock_property(rpi->firmware, - RPI_FIRMWARE_GET_CLOCK_RATE, - data->id, &val); + ret = raspberrypi_clock_property(rpi->firmware, data, + RPI_FIRMWARE_GET_CLOCK_RATE, &val); if (ret) return ret; @@ -129,9 +128,9 @@ static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE; int ret; - ret = raspberrypi_clock_property(rpi->firmware, + ret = raspberrypi_clock_property(rpi->firmware, data, RPI_FIRMWARE_SET_CLOCK_RATE, - data->id, &new_rate); + &new_rate); if (ret) dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d", clk_hw_get_name(hw), ret); @@ -194,18 +193,18 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED; /* Get min & max rates set by the firmware */ - ret = raspberrypi_clock_property(rpi->firmware, + ret = raspberrypi_clock_property(rpi->firmware, data, RPI_FIRMWARE_GET_MIN_CLOCK_RATE, - data->id, &min_rate); + &min_rate); if (ret) { dev_err(rpi->dev, "Failed to get %s min freq: %d\n", init.name, ret); return ret; } - ret = raspberrypi_clock_property(rpi->firmware, + ret = raspberrypi_clock_property(rpi->firmware, data, RPI_FIRMWARE_GET_MAX_CLOCK_RATE, - data->id, &max_rate); + &max_rate); if (ret) { dev_err(rpi->dev, "Failed to get %s max freq: %d\n", init.name, ret); From c1ce3509eca684e72d0910192d5549d01558b658 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:56 +0200 Subject: [PATCH 31/94] clk: bcm: rpi: Rename is_prepared function The raspberrypi_fw_pll_is_on function doesn't only apply to PLL registered in the driver, but any clock exposed by the firmware. Since we also implement the is_prepared hook, make the function consistent with the other function names. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/ac93cc4e245316bb7e7426ac5ab0de8f3d919731.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 3fce49a65a79..58ac1b104429 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -85,7 +85,7 @@ static int raspberrypi_clock_property(struct rpi_firmware *firmware, return 0; } -static int raspberrypi_fw_pll_is_on(struct clk_hw *hw) +static int raspberrypi_fw_is_prepared(struct clk_hw *hw) { struct raspberrypi_clk_data *data = container_of(hw, struct raspberrypi_clk_data, hw); @@ -166,7 +166,7 @@ static int raspberrypi_pll_determine_rate(struct clk_hw *hw, } static const struct clk_ops raspberrypi_firmware_pll_clk_ops = { - .is_prepared = raspberrypi_fw_pll_is_on, + .is_prepared = raspberrypi_fw_is_prepared, .recalc_rate = raspberrypi_fw_pll_get_rate, .set_rate = raspberrypi_fw_pll_set_rate, .determine_rate = raspberrypi_pll_determine_rate, From 3ea59ace7c0f475bf12f13b63a47a6983959d754 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:57 +0200 Subject: [PATCH 32/94] clk: bcm: rpi: Split pllb clock hooks The driver only supports the pllb for now and all the clock framework hooks are a mix of the generic firmware interface and the specifics of the pllb. Since we will support more clocks in the future let's split the generic and specific hooks Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/fdc21962fdc7de5c46232f198672d5d5c868ec74.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 58ac1b104429..19571602ba64 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -102,8 +102,8 @@ static int raspberrypi_fw_is_prepared(struct clk_hw *hw) } -static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, - unsigned long parent_rate) +static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw, + unsigned long parent_rate) { struct raspberrypi_clk_data *data = container_of(hw, struct raspberrypi_clk_data, hw); @@ -116,21 +116,27 @@ static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, if (ret) return ret; - return val * RPI_FIRMWARE_PLLB_ARM_DIV_RATE; + return val; } -static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) +static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + return raspberrypi_fw_get_rate(hw, parent_rate) * + RPI_FIRMWARE_PLLB_ARM_DIV_RATE; +} + +static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) { struct raspberrypi_clk_data *data = container_of(hw, struct raspberrypi_clk_data, hw); struct raspberrypi_clk *rpi = data->rpi; - u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE; + u32 _rate = rate; int ret; ret = raspberrypi_clock_property(rpi->firmware, data, - RPI_FIRMWARE_SET_CLOCK_RATE, - &new_rate); + RPI_FIRMWARE_SET_CLOCK_RATE, &_rate); if (ret) dev_err_ratelimited(rpi->dev, "Failed to change %s frequency: %d", clk_hw_get_name(hw), ret); @@ -138,6 +144,14 @@ static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } +static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE; + + return raspberrypi_fw_set_rate(hw, new_rate, parent_rate); +} + /* * Sadly there is no firmware rate rounding interface. We borrowed it from * clk-bcm2835. From 23e114b6b7a03a98d27cf327f0d173ad2d219c13 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:58 +0200 Subject: [PATCH 33/94] clk: bcm: rpi: Make the PLLB registration function return a clk_hw The raspberrypi_register_pllb has been returning an integer so far to notify whether the functions has exited successfully or not. However, the OF provider functions in the clock framework require access to the clk_hw structure so that we can expose those clocks to device tree consumers. Since we'll want that for the future clocks, let's return a clk_hw pointer instead of the return code. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/97218559db643e62fdd2b5e3046a2a05b8c2e769.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 46 ++++++++++++++++--------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 19571602ba64..d2cb90c086a7 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -186,7 +186,7 @@ static const struct clk_ops raspberrypi_firmware_pll_clk_ops = { .determine_rate = raspberrypi_pll_determine_rate, }; -static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) +static struct clk_hw *raspberrypi_register_pllb(struct raspberrypi_clk *rpi) { struct raspberrypi_clk_data *data; struct clk_init_data init = {}; @@ -195,7 +195,7 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL); if (!data) - return -ENOMEM; + return ERR_PTR(-ENOMEM); data->rpi = rpi; data->id = RPI_FIRMWARE_ARM_CLK_ID; @@ -213,7 +213,7 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) if (ret) { dev_err(rpi->dev, "Failed to get %s min freq: %d\n", init.name, ret); - return ret; + return ERR_PTR(ret); } ret = raspberrypi_clock_property(rpi->firmware, data, @@ -222,13 +222,13 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) if (ret) { dev_err(rpi->dev, "Failed to get %s max freq: %d\n", init.name, ret); - return ret; + return ERR_PTR(ret); } if (!min_rate || !max_rate) { dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n", min_rate, max_rate); - return -EINVAL; + return ERR_PTR(-EINVAL); } dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n", @@ -237,12 +237,14 @@ static int raspberrypi_register_pllb(struct raspberrypi_clk *rpi) data->hw.init = &init; ret = devm_clk_hw_register(rpi->dev, &data->hw); - if (!ret) - clk_hw_set_rate_range(&data->hw, - min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE, - max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE); + if (ret) + return ERR_PTR(ret); - return ret; + clk_hw_set_rate_range(&data->hw, + min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE, + max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE); + + return &data->hw; } static struct clk_fixed_factor raspberrypi_clk_pllb_arm = { @@ -257,14 +259,14 @@ static struct clk_fixed_factor raspberrypi_clk_pllb_arm = { }, }; -static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) +static struct clk_hw *raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) { int ret; ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw); if (ret) { dev_err(rpi->dev, "Failed to initialize pllb_arm\n"); - return ret; + return ERR_PTR(ret); } ret = devm_clk_hw_register_clkdev(rpi->dev, @@ -272,10 +274,10 @@ static int raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) NULL, "cpu0"); if (ret) { dev_err(rpi->dev, "Failed to initialize clkdev\n"); - return ret; + return ERR_PTR(ret); } - return 0; + return &raspberrypi_clk_pllb_arm.hw; } static int raspberrypi_clk_probe(struct platform_device *pdev) @@ -284,7 +286,7 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rpi_firmware *firmware; struct raspberrypi_clk *rpi; - int ret; + struct clk_hw *hw; /* * We can be probed either through the an old-fashioned @@ -314,15 +316,15 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) rpi->firmware = firmware; platform_set_drvdata(pdev, rpi); - ret = raspberrypi_register_pllb(rpi); - if (ret) { - dev_err(dev, "Failed to initialize pllb, %d\n", ret); - return ret; + hw = raspberrypi_register_pllb(rpi); + if (IS_ERR(hw)) { + dev_err(dev, "Failed to initialize pllb, %ld\n", PTR_ERR(hw)); + return PTR_ERR(hw); } - ret = raspberrypi_register_pllb_arm(rpi); - if (ret) - return ret; + hw = raspberrypi_register_pllb_arm(rpi); + if (IS_ERR(hw)) + return PTR_ERR(hw); rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq", -1, NULL, 0); From d4b4f1b6b97e56d49a69d6ee734f96f4d3d35762 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:59 +0200 Subject: [PATCH 34/94] clk: bcm: rpi: Add DT provider for the clocks For the upcoming registration of the clocks provided by the firmware, make sure it's exposed to the device tree providers. Cc: Michael Turquette Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/4d8dbe4aaae98b3d3812ad7c3dba53d645cadbaf.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index d2cb90c086a7..5f4e2d49432f 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -31,6 +31,8 @@ #define A2W_PLL_FRAC_BITS 20 +#define NUM_FW_CLKS 16 + struct raspberrypi_clk { struct device *dev; struct rpi_firmware *firmware; @@ -282,11 +284,13 @@ static struct clk_hw *raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) static int raspberrypi_clk_probe(struct platform_device *pdev) { + struct clk_hw_onecell_data *clk_data; struct device_node *firmware_node; struct device *dev = &pdev->dev; struct rpi_firmware *firmware; struct raspberrypi_clk *rpi; struct clk_hw *hw; + int ret; /* * We can be probed either through the an old-fashioned @@ -316,6 +320,11 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) rpi->firmware = firmware; platform_set_drvdata(pdev, rpi); + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, NUM_FW_CLKS), + GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + hw = raspberrypi_register_pllb(rpi); if (IS_ERR(hw)) { dev_err(dev, "Failed to initialize pllb, %ld\n", PTR_ERR(hw)); @@ -325,6 +334,13 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) hw = raspberrypi_register_pllb_arm(rpi); if (IS_ERR(hw)) return PTR_ERR(hw); + clk_data->hws[RPI_FIRMWARE_ARM_CLK_ID] = hw; + clk_data->num = RPI_FIRMWARE_ARM_CLK_ID + 1; + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + clk_data); + if (ret) + return ret; rpi->cpufreq = platform_device_register_data(dev, "raspberrypi-cpufreq", -1, NULL, 0); From be1559f69768da4576f5b4b9073466e82c031153 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:00 +0200 Subject: [PATCH 35/94] clk: bcm: rpi: Add an enum for the firmware clocks While the firmware allows us to discover the available clocks, we need to discriminate those clocks to only register the ones meaningful to Linux. The firmware also doesn't provide a clock name, so having a list of the ID will help us to give clocks a proper name later on. Acked-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/4738f77ee7de9b48a3bb1c558ead958d0cc064d9.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 5f4e2d49432f..eebd16040f8a 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -18,7 +18,23 @@ #include -#define RPI_FIRMWARE_ARM_CLK_ID 0x00000003 +enum rpi_firmware_clk_id { + RPI_FIRMWARE_EMMC_CLK_ID = 1, + RPI_FIRMWARE_UART_CLK_ID, + RPI_FIRMWARE_ARM_CLK_ID, + RPI_FIRMWARE_CORE_CLK_ID, + RPI_FIRMWARE_V3D_CLK_ID, + RPI_FIRMWARE_H264_CLK_ID, + RPI_FIRMWARE_ISP_CLK_ID, + RPI_FIRMWARE_SDRAM_CLK_ID, + RPI_FIRMWARE_PIXEL_CLK_ID, + RPI_FIRMWARE_PWM_CLK_ID, + RPI_FIRMWARE_HEVC_CLK_ID, + RPI_FIRMWARE_EMMC2_CLK_ID, + RPI_FIRMWARE_M2MC_CLK_ID, + RPI_FIRMWARE_PIXEL_BVB_CLK_ID, + RPI_FIRMWARE_NUM_CLK_ID, +}; #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0) #define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1) @@ -31,8 +47,6 @@ #define A2W_PLL_FRAC_BITS 20 -#define NUM_FW_CLKS 16 - struct raspberrypi_clk { struct device *dev; struct rpi_firmware *firmware; @@ -320,7 +334,8 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) rpi->firmware = firmware; platform_set_drvdata(pdev, rpi); - clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, NUM_FW_CLKS), + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, + RPI_FIRMWARE_NUM_CLK_ID), GFP_KERNEL); if (!clk_data) return -ENOMEM; From 93d2725affd65686792f4b57e49ef660f3c8c0f9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:01 +0200 Subject: [PATCH 36/94] clk: bcm: rpi: Discover the firmware clocks The RaspberryPi4 firmware actually exposes more clocks than are currently handled by the driver and we will need to change some of them directly based on the pixel rate for the display related clocks, or the load for the GPU. Since the firmware implements DVFS, this rate change can have a number of side-effects, including adjusting the various PLL voltages or the PLL parents. The firmware also implements thermal throttling, so even some thermal pressure can change those parameters behind Linux back. DVFS is currently implemented on the arm, core, h264, v3d, isp and hevc clocks, so updating any of them using the MMIO driver (and thus behind the firmware's back) can lead to troubles, the arm clock obviously being the most problematic. In order to make Linux play as nice as possible with those constraints, it makes sense to rely on the firmware clocks as much as possible. However, the firmware doesn't seem to provide some equivalents to their MMIO counterparts, so we can't really replace that driver entirely. Fortunately, the firmware has an interface to discover the clocks it exposes. Let's use it to discover, register the clocks in the clocks framework and then expose them through the device tree for consumers to use them. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Acked-by: Nicolas Saenz Julienne Reviewed-by: Stephen Boyd Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/438d73962741a8c5f7c689319b7443b930a87fde.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 153 +++++++++++++++++++++++++++--- 1 file changed, 141 insertions(+), 12 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index eebd16040f8a..11a62bde5203 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -296,6 +296,144 @@ static struct clk_hw *raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) return &raspberrypi_clk_pllb_arm.hw; } +static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + /* + * The firmware will do the rounding but that isn't part of + * the interface with the firmware, so we just do our best + * here. + */ + req->rate = clamp(req->rate, req->min_rate, req->max_rate); + return 0; +} + +static const struct clk_ops raspberrypi_firmware_clk_ops = { + .is_prepared = raspberrypi_fw_is_prepared, + .recalc_rate = raspberrypi_fw_get_rate, + .determine_rate = raspberrypi_fw_dumb_determine_rate, + .set_rate = raspberrypi_fw_set_rate, +}; + +static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi, + unsigned int parent, + unsigned int id) +{ + struct raspberrypi_clk_data *data; + struct clk_init_data init = {}; + u32 min_rate, max_rate; + int ret; + + if (id == RPI_FIRMWARE_ARM_CLK_ID) { + struct clk_hw *hw; + + hw = raspberrypi_register_pllb(rpi); + if (IS_ERR(hw)) { + dev_err(rpi->dev, "Failed to initialize pllb, %ld\n", + PTR_ERR(hw)); + return hw; + } + + return raspberrypi_register_pllb_arm(rpi); + } + + data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return ERR_PTR(-ENOMEM); + data->rpi = rpi; + data->id = id; + + init.name = devm_kasprintf(rpi->dev, GFP_KERNEL, "fw-clk-%u", id); + init.ops = &raspberrypi_firmware_clk_ops; + init.flags = CLK_GET_RATE_NOCACHE; + + data->hw.init = &init; + + ret = raspberrypi_clock_property(rpi->firmware, data, + RPI_FIRMWARE_GET_MIN_CLOCK_RATE, + &min_rate); + if (ret) { + dev_err(rpi->dev, "Failed to get clock %d min freq: %d", + id, ret); + return ERR_PTR(ret); + } + + ret = raspberrypi_clock_property(rpi->firmware, data, + RPI_FIRMWARE_GET_MAX_CLOCK_RATE, + &max_rate); + if (ret) { + dev_err(rpi->dev, "Failed to get clock %d max freq: %d\n", + id, ret); + return ERR_PTR(ret); + } + + ret = devm_clk_hw_register(rpi->dev, &data->hw); + if (ret) + return ERR_PTR(ret); + + clk_hw_set_rate_range(&data->hw, min_rate, max_rate); + + if (id == RPI_FIRMWARE_ARM_CLK_ID) { + ret = devm_clk_hw_register_clkdev(rpi->dev, &data->hw, + NULL, "cpu0"); + if (ret) { + dev_err(rpi->dev, "Failed to initialize clkdev\n"); + return ERR_PTR(ret); + } + } + + return &data->hw; +} + +struct rpi_firmware_get_clocks_response { + u32 parent; + u32 id; +}; + +static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, + struct clk_hw_onecell_data *data) +{ + struct rpi_firmware_get_clocks_response *clks; + int ret; + + clks = devm_kcalloc(rpi->dev, + sizeof(*clks), RPI_FIRMWARE_NUM_CLK_ID, + GFP_KERNEL); + if (!clks) + return -ENOMEM; + + ret = rpi_firmware_property(rpi->firmware, RPI_FIRMWARE_GET_CLOCKS, + clks, + sizeof(*clks) * RPI_FIRMWARE_NUM_CLK_ID); + if (ret) + return ret; + + while (clks->id) { + struct clk_hw *hw; + + switch (clks->id) { + case RPI_FIRMWARE_ARM_CLK_ID: + case RPI_FIRMWARE_CORE_CLK_ID: + case RPI_FIRMWARE_M2MC_CLK_ID: + case RPI_FIRMWARE_V3D_CLK_ID: + hw = raspberrypi_clk_register(rpi, clks->parent, + clks->id); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + data->hws[clks->id] = hw; + data->num = clks->id + 1; + fallthrough; + + default: + clks++; + break; + } + } + + return 0; +} + static int raspberrypi_clk_probe(struct platform_device *pdev) { struct clk_hw_onecell_data *clk_data; @@ -303,7 +441,6 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct rpi_firmware *firmware; struct raspberrypi_clk *rpi; - struct clk_hw *hw; int ret; /* @@ -340,17 +477,9 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) if (!clk_data) return -ENOMEM; - hw = raspberrypi_register_pllb(rpi); - if (IS_ERR(hw)) { - dev_err(dev, "Failed to initialize pllb, %ld\n", PTR_ERR(hw)); - return PTR_ERR(hw); - } - - hw = raspberrypi_register_pllb_arm(rpi); - if (IS_ERR(hw)) - return PTR_ERR(hw); - clk_data->hws[RPI_FIRMWARE_ARM_CLK_ID] = hw; - clk_data->num = RPI_FIRMWARE_ARM_CLK_ID + 1; + ret = raspberrypi_discover_clocks(rpi, clk_data); + if (ret) + return ret; ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data); From 7dad8a613185320093de021ca8abba986bc043cb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:02 +0200 Subject: [PATCH 37/94] clk: bcm: rpi: Give firmware clocks a name We've registered the firmware clocks using their ID as name, but it's much more convenient to register them using their proper name. Since the firmware doesn't provide it, we have to duplicate it. Acked-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/a52a5f5768cd33716cdd35237c6613f26ad75013.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 11a62bde5203..adc0bb56008a 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -36,6 +36,23 @@ enum rpi_firmware_clk_id { RPI_FIRMWARE_NUM_CLK_ID, }; +static char *rpi_firmware_clk_names[] = { + [RPI_FIRMWARE_EMMC_CLK_ID] = "emmc", + [RPI_FIRMWARE_UART_CLK_ID] = "uart", + [RPI_FIRMWARE_ARM_CLK_ID] = "arm", + [RPI_FIRMWARE_CORE_CLK_ID] = "core", + [RPI_FIRMWARE_V3D_CLK_ID] = "v3d", + [RPI_FIRMWARE_H264_CLK_ID] = "h264", + [RPI_FIRMWARE_ISP_CLK_ID] = "isp", + [RPI_FIRMWARE_SDRAM_CLK_ID] = "sdram", + [RPI_FIRMWARE_PIXEL_CLK_ID] = "pixel", + [RPI_FIRMWARE_PWM_CLK_ID] = "pwm", + [RPI_FIRMWARE_HEVC_CLK_ID] = "hevc", + [RPI_FIRMWARE_EMMC2_CLK_ID] = "emmc2", + [RPI_FIRMWARE_M2MC_CLK_ID] = "m2mc", + [RPI_FIRMWARE_PIXEL_BVB_CLK_ID] = "pixel-bvb", +}; + #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0) #define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1) @@ -343,7 +360,9 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi, data->rpi = rpi; data->id = id; - init.name = devm_kasprintf(rpi->dev, GFP_KERNEL, "fw-clk-%u", id); + init.name = devm_kasprintf(rpi->dev, GFP_KERNEL, + "fw-clk-%s", + rpi_firmware_clk_names[id]); init.ops = &raspberrypi_firmware_clk_ops; init.flags = CLK_GET_RATE_NOCACHE; From dbe01b4412914c7ce8fb11ea45bf67fafbffd068 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:03 +0200 Subject: [PATCH 38/94] Revert "clk: bcm2835: remove pllb" This reverts commit 2256d89333bd17b8b56b42734a7e1046d52f7fc3. Since we will be expanding the firmware clock driver, we'll need to remove the quirks to deal with the PLLB. However, we still want to expose the clock tree properly, so having that clock in the MMIO driver will allow that. Acked-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/5d26a4c58248f5be7760a7f2f720a1310baea5dd.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2835.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 6bb7efa12037..32f5c13be9d1 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1684,10 +1684,32 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .fixed_divider = 1, .flags = CLK_SET_RATE_PARENT), - /* - * PLLB is used for the ARM's clock. Controlled by firmware, see - * clk-raspberrypi.c. - */ + /* PLLB is used for the ARM's clock. */ + [BCM2835_PLLB] = REGISTER_PLL( + SOC_ALL, + .name = "pllb", + .cm_ctrl_reg = CM_PLLB, + .a2w_ctrl_reg = A2W_PLLB_CTRL, + .frac_reg = A2W_PLLB_FRAC, + .ana_reg_base = A2W_PLLB_ANA0, + .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE, + .lock_mask = CM_LOCK_FLOCKB, + + .ana = &bcm2835_ana_default, + + .min_rate = 600000000u, + .max_rate = 3000000000u, + .max_fb_rate = BCM2835_MAX_FB_RATE), + [BCM2835_PLLB_ARM] = REGISTER_PLL_DIV( + SOC_ALL, + .name = "pllb_arm", + .source_pll = "pllb", + .cm_reg = CM_PLLB, + .a2w_reg = A2W_PLLB_ARM, + .load_mask = CM_PLLB_LOADARM, + .hold_mask = CM_PLLB_HOLDARM, + .fixed_divider = 1, + .flags = CLK_SET_RATE_PARENT), /* * PLLC is the core PLL, used to drive the core VPU clock. From b2683d069bcae4277332243850d07ac24be05ab2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:05 +0200 Subject: [PATCH 39/94] clk: bcm2835: Allow custom CCF flags for the PLLs While some clock types allow for each clock to specify its own custom flags, the PLLs can't. We will need this for the PLLB, so let's add it. Acked-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/ae8bd505d8851f6646e244cd76b6b289346973c8.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2835.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 32f5c13be9d1..b50f00f109bf 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -421,6 +421,7 @@ struct bcm2835_pll_data { u32 reference_enable_mask; /* Bit in CM_LOCK to indicate when the PLL has locked. */ u32 lock_mask; + u32 flags; const struct bcm2835_pll_ana_bits *ana; @@ -1310,7 +1311,7 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, init.num_parents = 1; init.name = pll_data->name; init.ops = &bcm2835_pll_clk_ops; - init.flags = CLK_IGNORE_UNUSED; + init.flags = pll_data->flags | CLK_IGNORE_UNUSED; pll = kzalloc(sizeof(*pll), GFP_KERNEL); if (!pll) From 0d46fafc0364688c54b4a9d21cee0cb2eabf43bd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:06 +0200 Subject: [PATCH 40/94] clk: bcm2835: Don't cache the PLLB rate The PLLB rate will be changed through the firmware clocks drivers and will change behind this drivers' back, so we don't want to cache the rate. Acked-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/9864daba2f584ed49aee5ed1d2f4d48507c58197.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2835.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index b50f00f109bf..027eba31f793 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1700,7 +1700,8 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .min_rate = 600000000u, .max_rate = 3000000000u, - .max_fb_rate = BCM2835_MAX_FB_RATE), + .max_fb_rate = BCM2835_MAX_FB_RATE, + .flags = CLK_GET_RATE_NOCACHE), [BCM2835_PLLB_ARM] = REGISTER_PLL_DIV( SOC_ALL, .name = "pllb_arm", @@ -1710,7 +1711,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = { .load_mask = CM_PLLB_LOADARM, .hold_mask = CM_PLLB_HOLDARM, .fixed_divider = 1, - .flags = CLK_SET_RATE_PARENT), + .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE), /* * PLLC is the core PLL, used to drive the core VPU clock. From 56643d9ad2b4933d55f872f61195c1650f9958e9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:07 +0200 Subject: [PATCH 41/94] clk: bcm: rpi: Remove the quirks for the CPU clock The CPU clock has had so far a bunch of quirks to expose the clock tree properly, but since we reverted to exposing them through the MMIO driver, we can remove that code from the firmware driver. Acked-by: Nicolas Saenz Julienne Tested-by: Nicolas Saenz Julienne Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/acdf820c2f78a25dd7480a0c018b8b387acd013e.1592210452.git-series.maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-raspberrypi.c | 164 ------------------------------ 1 file changed, 164 deletions(-) diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index adc0bb56008a..5cc82954e1ce 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -56,14 +56,6 @@ static char *rpi_firmware_clk_names[] = { #define RPI_FIRMWARE_STATE_ENABLE_BIT BIT(0) #define RPI_FIRMWARE_STATE_WAIT_BIT BIT(1) -/* - * Even though the firmware interface alters 'pllb' the frequencies are - * provided as per 'pllb_arm'. We need to scale before passing them trough. - */ -#define RPI_FIRMWARE_PLLB_ARM_DIV_RATE 2 - -#define A2W_PLL_FRAC_BITS 20 - struct raspberrypi_clk { struct device *dev; struct rpi_firmware *firmware; @@ -152,13 +144,6 @@ static unsigned long raspberrypi_fw_get_rate(struct clk_hw *hw, return val; } -static unsigned long raspberrypi_fw_pll_get_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return raspberrypi_fw_get_rate(hw, parent_rate) * - RPI_FIRMWARE_PLLB_ARM_DIV_RATE; -} - static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { @@ -177,142 +162,6 @@ static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate, return ret; } -static int raspberrypi_fw_pll_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - u32 new_rate = rate / RPI_FIRMWARE_PLLB_ARM_DIV_RATE; - - return raspberrypi_fw_set_rate(hw, new_rate, parent_rate); -} - -/* - * Sadly there is no firmware rate rounding interface. We borrowed it from - * clk-bcm2835. - */ -static int raspberrypi_pll_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - u64 div, final_rate; - u32 ndiv, fdiv; - - /* We can't use req->rate directly as it would overflow */ - final_rate = clamp(req->rate, req->min_rate, req->max_rate); - - div = (u64)final_rate << A2W_PLL_FRAC_BITS; - do_div(div, req->best_parent_rate); - - ndiv = div >> A2W_PLL_FRAC_BITS; - fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1); - - final_rate = ((u64)req->best_parent_rate * - ((ndiv << A2W_PLL_FRAC_BITS) + fdiv)); - - req->rate = final_rate >> A2W_PLL_FRAC_BITS; - - return 0; -} - -static const struct clk_ops raspberrypi_firmware_pll_clk_ops = { - .is_prepared = raspberrypi_fw_is_prepared, - .recalc_rate = raspberrypi_fw_pll_get_rate, - .set_rate = raspberrypi_fw_pll_set_rate, - .determine_rate = raspberrypi_pll_determine_rate, -}; - -static struct clk_hw *raspberrypi_register_pllb(struct raspberrypi_clk *rpi) -{ - struct raspberrypi_clk_data *data; - struct clk_init_data init = {}; - u32 min_rate = 0, max_rate = 0; - int ret; - - data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return ERR_PTR(-ENOMEM); - data->rpi = rpi; - data->id = RPI_FIRMWARE_ARM_CLK_ID; - - /* All of the PLLs derive from the external oscillator. */ - init.parent_names = (const char *[]){ "osc" }; - init.num_parents = 1; - init.name = "pllb"; - init.ops = &raspberrypi_firmware_pll_clk_ops; - init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED; - - /* Get min & max rates set by the firmware */ - ret = raspberrypi_clock_property(rpi->firmware, data, - RPI_FIRMWARE_GET_MIN_CLOCK_RATE, - &min_rate); - if (ret) { - dev_err(rpi->dev, "Failed to get %s min freq: %d\n", - init.name, ret); - return ERR_PTR(ret); - } - - ret = raspberrypi_clock_property(rpi->firmware, data, - RPI_FIRMWARE_GET_MAX_CLOCK_RATE, - &max_rate); - if (ret) { - dev_err(rpi->dev, "Failed to get %s max freq: %d\n", - init.name, ret); - return ERR_PTR(ret); - } - - if (!min_rate || !max_rate) { - dev_err(rpi->dev, "Unexpected frequency range: min %u, max %u\n", - min_rate, max_rate); - return ERR_PTR(-EINVAL); - } - - dev_info(rpi->dev, "CPU frequency range: min %u, max %u\n", - min_rate, max_rate); - - data->hw.init = &init; - - ret = devm_clk_hw_register(rpi->dev, &data->hw); - if (ret) - return ERR_PTR(ret); - - clk_hw_set_rate_range(&data->hw, - min_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE, - max_rate * RPI_FIRMWARE_PLLB_ARM_DIV_RATE); - - return &data->hw; -} - -static struct clk_fixed_factor raspberrypi_clk_pllb_arm = { - .mult = 1, - .div = 2, - .hw.init = &(struct clk_init_data) { - .name = "pllb_arm", - .parent_names = (const char *[]){ "pllb" }, - .num_parents = 1, - .ops = &clk_fixed_factor_ops, - .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE, - }, -}; - -static struct clk_hw *raspberrypi_register_pllb_arm(struct raspberrypi_clk *rpi) -{ - int ret; - - ret = devm_clk_hw_register(rpi->dev, &raspberrypi_clk_pllb_arm.hw); - if (ret) { - dev_err(rpi->dev, "Failed to initialize pllb_arm\n"); - return ERR_PTR(ret); - } - - ret = devm_clk_hw_register_clkdev(rpi->dev, - &raspberrypi_clk_pllb_arm.hw, - NULL, "cpu0"); - if (ret) { - dev_err(rpi->dev, "Failed to initialize clkdev\n"); - return ERR_PTR(ret); - } - - return &raspberrypi_clk_pllb_arm.hw; -} - static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { @@ -341,19 +190,6 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi, u32 min_rate, max_rate; int ret; - if (id == RPI_FIRMWARE_ARM_CLK_ID) { - struct clk_hw *hw; - - hw = raspberrypi_register_pllb(rpi); - if (IS_ERR(hw)) { - dev_err(rpi->dev, "Failed to initialize pllb, %ld\n", - PTR_ERR(hw)); - return hw; - } - - return raspberrypi_register_pllb_arm(rpi); - } - data = devm_kzalloc(rpi->dev, sizeof(*data), GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); From 2afc6ec090b29c4014870b0d78334831d6163b9b Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Mon, 22 Jun 2020 09:58:09 +0530 Subject: [PATCH 42/94] dt-bindings: clock: add ipq6018 a53 pll compatible cpus on ipq6018 are clocked by a53 pll, add device compatible for a53 pll found on ipq6018 devices. Reviewed-by: Rob Herring Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1592800092-20533-2-git-send-email-sivaprak@codeaurora.org Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,a53pll.yaml | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml index 20d2638b4cd2..db3d0ea6bc7a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml @@ -15,7 +15,9 @@ description: properties: compatible: - const: qcom,msm8916-a53pll + enum: + - qcom,ipq6018-a53pll + - qcom,msm8916-a53pll reg: maxItems: 1 @@ -23,6 +25,14 @@ properties: '#clock-cells': const: 0 + clocks: + items: + - description: board XO clock + + clock-names: + items: + - const: xo + required: - compatible - reg @@ -38,3 +48,12 @@ examples: reg = <0xb016000 0x40>; #clock-cells = <0>; }; + #Example 2 - A53 PLL found on IPQ6018 devices + - | + a53pll_ipq: clock-controller@b116000 { + compatible = "qcom,ipq6018-a53pll"; + reg = <0x0b116000 0x40>; + #clock-cells = <0>; + clocks = <&xo>; + clock-names = "xo"; + }; From ecd2bacfbbc4d7a2a1beb96fa7836a8ca6e4cf71 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Mon, 22 Jun 2020 09:58:10 +0530 Subject: [PATCH 43/94] clk: qcom: Add ipq apss pll driver 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 Link: https://lore.kernel.org/r/1592800092-20533-3-git-send-email-sivaprak@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 8 +++ drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/apss-ipq-pll.c | 95 +++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 drivers/clk/qcom/apss-ipq-pll.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index cde6ca90a06b..49e265ddcdab 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 7ec8561a1270..7942c00902ec 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 000000000000..30be87fb222a --- /dev/null +++ b/drivers/clk/qcom/apss-ipq-pll.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2018, The Linux Foundation. All rights reserved. +#include +#include +#include +#include + +#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; + void __iomem *base; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + regmap = devm_regmap_init_mmio(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"); From 49bcaef86eba1a8097980f341e243ba01177a685 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Mon, 22 Jun 2020 09:58:11 +0530 Subject: [PATCH 44/94] clk: qcom: Add DT bindings for ipq6018 apss clock controller Add dt-binding for ipq6018 apss clock controller Acked-by: Rob Herring Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1592800092-20533-4-git-send-email-sivaprak@codeaurora.org Signed-off-by: Stephen Boyd --- 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 000000000000..77b6e05492e2 --- /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 From 5e77b4ef1b19a4ce4051ff2afb706ee675e4b412 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Mon, 22 Jun 2020 09:58:12 +0530 Subject: [PATCH 45/94] clk: qcom: Add ipq6018 apss clock controller 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. Reviewed-by: Stephen Boyd Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1592800092-20533-5-git-send-email-sivaprak@codeaurora.org Signed-off-by: Stephen Boyd --- 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 49e265ddcdab..f510ef61db69 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 7942c00902ec..21439b94395a 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 000000000000..004f7e1ecdc2 --- /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 +#include +#include +#include +#include +#include + +#include + +#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"); From e8c849c2a8e8d300922399ac02065bebf53393a6 Mon Sep 17 00:00:00 2001 From: Sarang Mairal Date: Wed, 10 Jun 2020 21:19:41 -0500 Subject: [PATCH 46/94] clk: add function documentation for clk_hw_round_rate() Information about usage and prerequisites for this API. Signed-off-by: Sarang Mairal Link: https://lore.kernel.org/r/20200611021941.786-2-sarangmairal@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 3f588ed06ce3..236923b25543 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1400,6 +1400,21 @@ int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) } EXPORT_SYMBOL_GPL(__clk_determine_rate); +/** + * clk_hw_round_rate() - round the given rate for a hw clk + * @hw: the hw clk for which we are rounding a rate + * @rate: the rate which is to be rounded + * + * Takes in a rate as input and rounds it to a rate that the clk can actually + * use. + * + * Context: prepare_lock must be held. + * For clk providers to call from within clk_ops such as .round_rate, + * .determine_rate. + * + * Return: returns rounded rate of hw clk if clk supports round_rate operation + * else returns the parent rate. + */ unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate) { int ret; From b608013ac5b55a2e42d8734f29f9757b75d26165 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 22 Jun 2020 11:02:52 +0200 Subject: [PATCH 47/94] clk: qcom: smd: Add support for SDM660 rpm clocks Add rpm smd clocks, PMIC and bus clocks which are required on SDM630/660 (and APQ variants) for clients to vote on. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20200622090252.36568-1-konradybcio@gmail.com Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,rpmcc.txt | 1 + drivers/clk/qcom/clk-smd-rpm.c | 76 +++++++++++++++++++ include/dt-bindings/clock/qcom,rpmcc.h | 10 +++ 3 files changed, 87 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index 90a1349bc713..86190acc71bc 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -20,6 +20,7 @@ Required properties : "qcom,rpmcc-msm8996", "qcom,rpmcc" "qcom,rpmcc-msm8998", "qcom,rpmcc" "qcom,rpmcc-qcs404", "qcom,rpmcc" + "qcom,rpmcc-sdm660", "qcom,rpmcc" - #clock-cells : shall contain 1 diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 52f63ad787ba..643bc355df5c 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -766,6 +766,81 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8998 = { .num_clks = ARRAY_SIZE(msm8998_clks), }; +/* sdm660 */ +DEFINE_CLK_SMD_RPM_BRANCH(sdm660, bi_tcxo, bi_tcxo_a, QCOM_SMD_RPM_MISC_CLK, 0, + 19200000); +DEFINE_CLK_SMD_RPM(sdm660, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); +DEFINE_CLK_SMD_RPM(sdm660, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); +DEFINE_CLK_SMD_RPM(sdm660, cnoc_periph_clk, cnoc_periph_a_clk, + QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(sdm660, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(sdm660, mmssnoc_axi_clk, mmssnoc_axi_a_clk, + QCOM_SMD_RPM_MMAXI_CLK, 0); +DEFINE_CLK_SMD_RPM(sdm660, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); +DEFINE_CLK_SMD_RPM(sdm660, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); +DEFINE_CLK_SMD_RPM(sdm660, aggre2_noc_clk, aggre2_noc_a_clk, + QCOM_SMD_RPM_AGGR_CLK, 2); +DEFINE_CLK_SMD_RPM_QDSS(sdm660, qdss_clk, qdss_a_clk, + QCOM_SMD_RPM_MISC_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, rf_clk1, rf_clk1_a, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, div_clk1, div_clk1_a, 11); +DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk1, ln_bb_clk1_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk2, ln_bb_clk2_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER(sdm660, ln_bb_clk3, ln_bb_clk3_a, 3); + +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, rf_clk1_pin, rf_clk1_a_pin, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk1_pin, + ln_bb_clk1_pin_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk2_pin, + ln_bb_clk2_pin_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(sdm660, ln_bb_clk3_pin, + ln_bb_clk3_pin_a, 3); +static struct clk_smd_rpm *sdm660_clks[] = { + [RPM_SMD_XO_CLK_SRC] = &sdm660_bi_tcxo, + [RPM_SMD_XO_A_CLK_SRC] = &sdm660_bi_tcxo_a, + [RPM_SMD_SNOC_CLK] = &sdm660_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &sdm660_snoc_a_clk, + [RPM_SMD_CNOC_CLK] = &sdm660_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &sdm660_cnoc_a_clk, + [RPM_SMD_CNOC_PERIPH_CLK] = &sdm660_cnoc_periph_clk, + [RPM_SMD_CNOC_PERIPH_A_CLK] = &sdm660_cnoc_periph_a_clk, + [RPM_SMD_BIMC_CLK] = &sdm660_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &sdm660_bimc_a_clk, + [RPM_SMD_MMSSNOC_AXI_CLK] = &sdm660_mmssnoc_axi_clk, + [RPM_SMD_MMSSNOC_AXI_CLK_A] = &sdm660_mmssnoc_axi_a_clk, + [RPM_SMD_IPA_CLK] = &sdm660_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &sdm660_ipa_a_clk, + [RPM_SMD_CE1_CLK] = &sdm660_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &sdm660_ce1_a_clk, + [RPM_SMD_AGGR2_NOC_CLK] = &sdm660_aggre2_noc_clk, + [RPM_SMD_AGGR2_NOC_A_CLK] = &sdm660_aggre2_noc_a_clk, + [RPM_SMD_QDSS_CLK] = &sdm660_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &sdm660_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &sdm660_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &sdm660_rf_clk1_a, + [RPM_SMD_DIV_CLK1] = &sdm660_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &sdm660_div_clk1_a, + [RPM_SMD_LN_BB_CLK] = &sdm660_ln_bb_clk1, + [RPM_SMD_LN_BB_A_CLK] = &sdm660_ln_bb_clk1_a, + [RPM_SMD_LN_BB_CLK2] = &sdm660_ln_bb_clk2, + [RPM_SMD_LN_BB_CLK2_A] = &sdm660_ln_bb_clk2_a, + [RPM_SMD_LN_BB_CLK3] = &sdm660_ln_bb_clk3, + [RPM_SMD_LN_BB_CLK3_A] = &sdm660_ln_bb_clk3_a, + [RPM_SMD_RF_CLK1_PIN] = &sdm660_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &sdm660_rf_clk1_a_pin, + [RPM_SMD_LN_BB_CLK1_PIN] = &sdm660_ln_bb_clk1_pin, + [RPM_SMD_LN_BB_CLK1_A_PIN] = &sdm660_ln_bb_clk1_pin_a, + [RPM_SMD_LN_BB_CLK2_PIN] = &sdm660_ln_bb_clk2_pin, + [RPM_SMD_LN_BB_CLK2_A_PIN] = &sdm660_ln_bb_clk2_pin_a, + [RPM_SMD_LN_BB_CLK3_PIN] = &sdm660_ln_bb_clk3_pin, + [RPM_SMD_LN_BB_CLK3_A_PIN] = &sdm660_ln_bb_clk3_pin_a, +}; + +static const struct rpm_smd_clk_desc rpm_clk_sdm660 = { + .clks = sdm660_clks, + .num_clks = ARRAY_SIZE(sdm660_clks), +}; + static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, @@ -773,6 +848,7 @@ static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, { .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 }, { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, + { .compatible = "qcom,rpmcc-sdm660", .data = &rpm_clk_sdm660 }, { } }; MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table); diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index ae74c43c485d..d1afa634b58d 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -133,5 +133,15 @@ #define RPM_SMD_RF_CLK3_A 87 #define RPM_SMD_RF_CLK3_PIN 88 #define RPM_SMD_RF_CLK3_A_PIN 89 +#define RPM_SMD_MMSSNOC_AXI_CLK 90 +#define RPM_SMD_MMSSNOC_AXI_CLK_A 91 +#define RPM_SMD_CNOC_PERIPH_CLK 92 +#define RPM_SMD_CNOC_PERIPH_A_CLK 93 +#define RPM_SMD_LN_BB_CLK3 94 +#define RPM_SMD_LN_BB_CLK3_A 95 +#define RPM_SMD_LN_BB_CLK1_PIN 96 +#define RPM_SMD_LN_BB_CLK1_A_PIN 97 +#define RPM_SMD_LN_BB_CLK2_PIN 98 +#define RPM_SMD_LN_BB_CLK2_A_PIN 99 #endif From f2de5257dbb4a3437060546fe75551b5538d224b Mon Sep 17 00:00:00 2001 From: Vincent Knecht Date: Sat, 13 Jun 2020 09:27:43 +0200 Subject: [PATCH 48/94] dt-bindings: clock: rpmcc: Document MSM8936 compatible Acked-by: Rob Herring Signed-off-by: Vincent Knecht Link: https://lore.kernel.org/r/20200613072745.1249003-3-vincent.knecht@mailoo.org Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/qcom,rpmcc.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index 86190acc71bc..8786d19ffe17 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -13,6 +13,7 @@ Required properties : "qcom,rpmcc-msm8660", "qcom,rpmcc" "qcom,rpmcc-apq8060", "qcom,rpmcc" "qcom,rpmcc-msm8916", "qcom,rpmcc" + "qcom,rpmcc-msm8936", "qcom,rpmcc" "qcom,rpmcc-msm8974", "qcom,rpmcc" "qcom,rpmcc-msm8976", "qcom,rpmcc" "qcom,rpmcc-apq8064", "qcom,rpmcc" From 59390282b7542c6050c1deaca0b2949180903175 Mon Sep 17 00:00:00 2001 From: Vincent Knecht Date: Sat, 13 Jun 2020 09:27:42 +0200 Subject: [PATCH 49/94] clk: qcom: smd: Add support for MSM8936 rpm clocks Add missing definition of rpm clk for msm8936 soc (also used by msm8939) Signed-off-by: Vincent Knecht Link: https://lore.kernel.org/r/20200613072745.1249003-2-vincent.knecht@mailoo.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 50 ++++++++++++++++++++++++++ include/dt-bindings/clock/qcom,rpmcc.h | 2 ++ 2 files changed, 52 insertions(+) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 643bc355df5c..083399affc8e 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -452,6 +452,55 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8916 = { .num_clks = ARRAY_SIZE(msm8916_clks), }; +/* msm8936 */ +DEFINE_CLK_SMD_RPM(msm8936, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8936, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); +DEFINE_CLK_SMD_RPM(msm8936, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8936, sysmmnoc_clk, sysmmnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); +DEFINE_CLK_SMD_RPM_QDSS(msm8936, qdss_clk, qdss_a_clk, QCOM_SMD_RPM_MISC_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk1, bb_clk1_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, bb_clk2, bb_clk2_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk1, rf_clk1_a, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8936, rf_clk2, rf_clk2_a, 5); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk1_pin, bb_clk1_a_pin, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, bb_clk2_pin, bb_clk2_a_pin, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk1_pin, rf_clk1_a_pin, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8936, rf_clk2_pin, rf_clk2_a_pin, 5); + +static struct clk_smd_rpm *msm8936_clks[] = { + [RPM_SMD_PCNOC_CLK] = &msm8936_pcnoc_clk, + [RPM_SMD_PCNOC_A_CLK] = &msm8936_pcnoc_a_clk, + [RPM_SMD_SNOC_CLK] = &msm8936_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8936_snoc_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8936_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8936_bimc_a_clk, + [RPM_SMD_SYSMMNOC_CLK] = &msm8936_sysmmnoc_clk, + [RPM_SMD_SYSMMNOC_A_CLK] = &msm8936_sysmmnoc_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8936_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8936_qdss_a_clk, + [RPM_SMD_BB_CLK1] = &msm8936_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8936_bb_clk1_a, + [RPM_SMD_BB_CLK2] = &msm8936_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8936_bb_clk2_a, + [RPM_SMD_RF_CLK1] = &msm8936_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8936_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8936_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8936_rf_clk2_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8936_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8936_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2_PIN] = &msm8936_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8936_bb_clk2_a_pin, + [RPM_SMD_RF_CLK1_PIN] = &msm8936_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8936_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8936_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8936_rf_clk2_a_pin, +}; + +static const struct rpm_smd_clk_desc rpm_clk_msm8936 = { + .clks = msm8936_clks, + .num_clks = ARRAY_SIZE(msm8936_clks), +}; + /* msm8974 */ DEFINE_CLK_SMD_RPM(msm8974, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8974, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); @@ -843,6 +892,7 @@ static const struct rpm_smd_clk_desc rpm_clk_sdm660 = { static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 }, + { .compatible = "qcom,rpmcc-msm8936", .data = &rpm_clk_msm8936 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, { .compatible = "qcom,rpmcc-msm8976", .data = &rpm_clk_msm8976 }, { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index d1afa634b58d..e98ed70d91b3 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -143,5 +143,7 @@ #define RPM_SMD_LN_BB_CLK1_A_PIN 97 #define RPM_SMD_LN_BB_CLK2_PIN 98 #define RPM_SMD_LN_BB_CLK2_A_PIN 99 +#define RPM_SMD_SYSMMNOC_CLK 100 +#define RPM_SMD_SYSMMNOC_A_CLK 101 #endif From f491276a5168598758ea7fc381195e4ba9af39f8 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Wed, 3 Jun 2020 10:43:27 -0500 Subject: [PATCH 50/94] clk: vc5: Allow Versaclock driver to support multiple instances Currently, the Versaclock driver is only expecting one instance and uses hard-coded names for the various clock names. Unfortunately, this is a problem when there is more than one instance of the driver, because the subsequent instantiations of the driver use the identical name. Each clock after the fist fails to load, because the clock subsystem cannot handle two clocks with identical name. This patch removes the hard-coded name arrays and uses kasprintf to assign clock names based on names of their respective node and parent node which gives each clock a unique identifying name. For a verasaclock node with a name like: versaclock5: versaclock_som@6a The updated clock names would appear like: versaclock_som.mux versaclock_som.out0_sel_i2cb versaclock_som.pfd versaclock_som.pll versaclock_som.fod3 versaclock_som.out4 versaclock_som.fod2 versaclock_som.out3 versaclock_som.fod1 versaclock_som.out2 versaclock_som.fod0 versaclock_som.out1 Signed-off-by: Adam Ford Link: https://lore.kernel.org/r/20200603154329.31579-1-aford173@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 84 +++++++++++++++-------------------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index fa96659f8023..41e3a75963b9 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -161,30 +161,6 @@ struct vc5_driver_data { struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; }; -static const char * const vc5_mux_names[] = { - "mux" -}; - -static const char * const vc5_dbl_names[] = { - "dbl" -}; - -static const char * const vc5_pfd_names[] = { - "pfd" -}; - -static const char * const vc5_pll_names[] = { - "pll" -}; - -static const char * const vc5_fod_names[] = { - "fod0", "fod1", "fod2", "fod3", -}; - -static const char * const vc5_clk_out_names[] = { - "out0_sel_i2cb", "out1", "out2", "out3", "out4", -}; - /* * VersaClock5 i2c regmap */ @@ -692,8 +668,7 @@ static int vc5_map_index_to_output(const enum vc5_model model, static const struct of_device_id clk_vc5_of_match[]; -static int vc5_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct vc5_driver_data *vc5; struct clk_init_data init; @@ -742,7 +717,7 @@ static int vc5_probe(struct i2c_client *client, if (!IS_ERR(vc5->pin_clkin)) { vc5->clk_mux_ins |= VC5_MUX_IN_CLKIN; parent_names[init.num_parents++] = - __clk_get_name(vc5->pin_clkin); + __clk_get_name(vc5->pin_clkin); } if (!init.num_parents) { @@ -750,12 +725,13 @@ static int vc5_probe(struct i2c_client *client, return -EINVAL; } - init.name = vc5_mux_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.mux", client->dev.of_node); init.ops = &vc5_mux_ops; init.flags = 0; init.parent_names = parent_names; vc5->clk_mux.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); goto err_clk; @@ -764,13 +740,16 @@ static int vc5_probe(struct i2c_client *client, if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) { /* Register frequency doubler */ memset(&init, 0, sizeof(init)); - init.name = vc5_dbl_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.dbl", + client->dev.of_node); init.ops = &vc5_dbl_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_mux_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mux); init.num_parents = 1; vc5->clk_mul.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); @@ -780,16 +759,18 @@ static int vc5_probe(struct i2c_client *client, /* Register PFD */ memset(&init, 0, sizeof(init)); - init.name = vc5_pfd_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.pfd", client->dev.of_node); init.ops = &vc5_pfd_ops; init.flags = CLK_SET_RATE_PARENT; + init.parent_names = parent_names; if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) - init.parent_names = vc5_dbl_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mul); else - init.parent_names = vc5_mux_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mux); init.num_parents = 1; vc5->clk_pfd.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); goto err_clk; @@ -797,15 +778,17 @@ static int vc5_probe(struct i2c_client *client, /* Register PLL */ memset(&init, 0, sizeof(init)); - init.name = vc5_pll_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.pll", client->dev.of_node); init.ops = &vc5_pll_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_pfd_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_pfd); init.num_parents = 1; vc5->clk_pll.num = 0; vc5->clk_pll.vc5 = vc5; vc5->clk_pll.hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); goto err_clk; @@ -815,15 +798,18 @@ static int vc5_probe(struct i2c_client *client, for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) { idx = vc5_map_index_to_output(vc5->chip_info->model, n); memset(&init, 0, sizeof(init)); - init.name = vc5_fod_names[idx]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.fod%d", + client->dev.of_node, idx); init.ops = &vc5_fod_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_pll_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_pll.hw); init.num_parents = 1; vc5->clk_fod[n].num = idx; vc5->clk_fod[n].vc5 = vc5; vc5->clk_fod[n].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); @@ -833,32 +819,36 @@ static int vc5_probe(struct i2c_client *client, /* Register MUX-connected OUT0_I2C_SELB output */ memset(&init, 0, sizeof(init)); - init.name = vc5_clk_out_names[0]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.out0_sel_i2cb", + client->dev.of_node); init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = vc5_mux_names; + init.parent_names = parent_names; + parent_names[0] = clk_hw_get_name(&vc5->clk_mux); init.num_parents = 1; vc5->clk_out[0].num = idx; vc5->clk_out[0].vc5 = vc5; vc5->clk_out[0].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { - dev_err(&client->dev, "unable to register %s\n", - init.name); + dev_err(&client->dev, "unable to register %s\n", init.name); goto err_clk; } /* Register FOD-connected OUTx outputs */ for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) { idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1); - parent_names[0] = vc5_fod_names[idx]; + parent_names[0] = clk_hw_get_name(&vc5->clk_fod[idx].hw); if (n == 1) - parent_names[1] = vc5_mux_names[0]; + parent_names[1] = clk_hw_get_name(&vc5->clk_mux); else - parent_names[1] = vc5_clk_out_names[n - 1]; + parent_names[1] = + clk_hw_get_name(&vc5->clk_out[n - 1].hw); memset(&init, 0, sizeof(init)); - init.name = vc5_clk_out_names[idx + 1]; + init.name = kasprintf(GFP_KERNEL, "%pOFn.out%d", + client->dev.of_node, idx + 1); init.ops = &vc5_clk_out_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = parent_names; @@ -866,8 +856,8 @@ static int vc5_probe(struct i2c_client *client, vc5->clk_out[n].num = idx; vc5->clk_out[n].vc5 = vc5; vc5->clk_out[n].hw.init = &init; - ret = devm_clk_hw_register(&client->dev, - &vc5->clk_out[n].hw); + ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw); + kfree(init.name); /* clock framework made a copy of the name */ if (ret) { dev_err(&client->dev, "unable to register %s\n", init.name); From 34662f6e30846ae0f82bbc9605deff67781f6616 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Wed, 3 Jun 2020 10:43:28 -0500 Subject: [PATCH 51/94] dt: Add additional option bindings for IDT VersaClock The VersaClock driver now supports some additional bindings to support child nodes which can configure optional settings like mode, voltage and slew. This patch updates the binding document to describe what is available in the driver. Signed-off-by: Adam Ford Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200603154329.31579-2-aford173@gmail.com Signed-off-by: Stephen Boyd --- .../bindings/clock/idt,versaclock5.txt | 33 +++++++++++++++++++ include/dt-bindings/clk/versaclock.h | 13 ++++++++ 2 files changed, 46 insertions(+) create mode 100644 include/dt-bindings/clk/versaclock.h diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt b/Documentation/devicetree/bindings/clock/idt,versaclock5.txt index bcff681a4bd0..6165b6ddb1a9 100644 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.txt @@ -31,6 +31,29 @@ Required properties: - 5p49v5933 and - 5p49v5935: (optional) property not present or "clkin". +For all output ports, a corresponding, optional child node named OUT1, +OUT2, etc. can represent a each output, and the node can be used to +specify the following: + +- itd,mode: can be one of the following: + - VC5_LVPECL + - VC5_CMOS + - VC5_HCSL33 + - VC5_LVDS + - VC5_CMOS2 + - VC5_CMOSD + - VC5_HCSL25 + +- idt,voltage-microvolts: can be one of the following + - 1800000 + - 2500000 + - 3300000 +- idt,slew-percent: Percent of normal, can be one of + - 80 + - 85 + - 90 + - 100 + ==Mapping between clock specifier and physical pins== When referencing the provided clock in the DT using phandle and @@ -81,6 +104,16 @@ i2c-master-node { /* Connect XIN input to 25MHz reference */ clocks = <&ref25m>; clock-names = "xin"; + + OUT1 { + itd,mode = ; + idt,voltage-microvolts = <1800000>; + idt,slew-percent = <80>; + }; + OUT2 { + ... + }; + ... }; }; diff --git a/include/dt-bindings/clk/versaclock.h b/include/dt-bindings/clk/versaclock.h new file mode 100644 index 000000000000..c6a6a0946564 --- /dev/null +++ b/include/dt-bindings/clk/versaclock.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* This file defines field values used by the versaclock 6 family + * for defining output type + */ + +#define VC5_LVPECL 0 +#define VC5_CMOS 1 +#define VC5_HCSL33 2 +#define VC5_LVDS 3 +#define VC5_CMOS2 4 +#define VC5_CMOSD 5 +#define VC5_HCSL25 6 From 260249f929e81d3d5764117fdd6b9e43eb8fb1d5 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Wed, 3 Jun 2020 10:43:29 -0500 Subject: [PATCH 52/94] clk: vc5: Enable addition output configurations of the Versaclock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing driver is expecting the Versaclock to be pre-programmed, and only sets the output frequency. Unfortunately, not all devices are pre-programmed, and the Versaclock chip has more options beyond just the frequency. This patch enables the following additional features: - Programmable voltage: 1.8V, 2.5V, or 3.3V​ - Slew Percentage of normal: 85%, 90%, or 100% - Output Type: LVPECL, CMOS, HCSL, or LVDS Signed-off-by: Adam Ford Link: https://lore.kernel.org/r/20200603154329.31579-3-aford173@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 156 ++++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 41e3a75963b9..9a5fb3834b9a 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -24,6 +24,8 @@ #include #include +#include + /* VersaClock5 registers */ #define VC5_OTP_CONTROL 0x00 @@ -89,6 +91,28 @@ /* Clock control register for clock 1,2 */ #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n)) +#define VC5_CLK_OUTPUT_CFG0_CFG_SHIFT 5 +#define VC5_CLK_OUTPUT_CFG0_CFG_MASK GENMASK(7, VC5_CLK_OUTPUT_CFG0_CFG_SHIFT) + +#define VC5_CLK_OUTPUT_CFG0_CFG_LVPECL (VC5_LVPECL) +#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS (VC5_CMOS) +#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL33 (VC5_HCSL33) +#define VC5_CLK_OUTPUT_CFG0_CFG_LVDS (VC5_LVDS) +#define VC5_CLK_OUTPUT_CFG0_CFG_CMOS2 (VC5_CMOS2) +#define VC5_CLK_OUTPUT_CFG0_CFG_CMOSD (VC5_CMOSD) +#define VC5_CLK_OUTPUT_CFG0_CFG_HCSL25 (VC5_HCSL25) + +#define VC5_CLK_OUTPUT_CFG0_PWR_SHIFT 3 +#define VC5_CLK_OUTPUT_CFG0_PWR_MASK GENMASK(4, VC5_CLK_OUTPUT_CFG0_PWR_SHIFT) +#define VC5_CLK_OUTPUT_CFG0_PWR_18 (0<regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), VC5_CLK_OUTPUT_CFG1_EN_CLKBUF, VC5_CLK_OUTPUT_CFG1_EN_CLKBUF); + if (hwdata->clk_output_cfg0_mask) { + dev_dbg(&vc5->client->dev, "Update output %d mask 0x%0X val 0x%0X\n", + hwdata->num, hwdata->clk_output_cfg0_mask, + hwdata->clk_output_cfg0); + + regmap_update_bits(vc5->regmap, + VC5_CLK_OUTPUT_CFG(hwdata->num, 0), + hwdata->clk_output_cfg0_mask, + hwdata->clk_output_cfg0); + } + return 0; } @@ -666,6 +703,120 @@ static int vc5_map_index_to_output(const enum vc5_model model, } } +static int vc5_update_mode(struct device_node *np_output, + struct vc5_hw_data *clk_out) +{ + u32 value; + + if (!of_property_read_u32(np_output, "idt,mode", &value)) { + clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_CFG_MASK; + switch (value) { + case VC5_CLK_OUTPUT_CFG0_CFG_LVPECL: + case VC5_CLK_OUTPUT_CFG0_CFG_CMOS: + case VC5_CLK_OUTPUT_CFG0_CFG_HCSL33: + case VC5_CLK_OUTPUT_CFG0_CFG_LVDS: + case VC5_CLK_OUTPUT_CFG0_CFG_CMOS2: + case VC5_CLK_OUTPUT_CFG0_CFG_CMOSD: + case VC5_CLK_OUTPUT_CFG0_CFG_HCSL25: + clk_out->clk_output_cfg0 |= + value << VC5_CLK_OUTPUT_CFG0_CFG_SHIFT; + break; + default: + return -EINVAL; + } + } + return 0; +} + +static int vc5_update_power(struct device_node *np_output, + struct vc5_hw_data *clk_out) +{ + u32 value; + + if (!of_property_read_u32(np_output, + "idt,voltage-microvolts", &value)) { + clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_PWR_MASK; + switch (value) { + case 1800000: + clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_18; + break; + case 2500000: + clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_25; + break; + case 3300000: + clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_PWR_33; + break; + default: + return -EINVAL; + } + } + return 0; +} + +static int vc5_update_slew(struct device_node *np_output, + struct vc5_hw_data *clk_out) +{ + u32 value; + + if (!of_property_read_u32(np_output, "idt,slew-percent", &value)) { + clk_out->clk_output_cfg0_mask |= VC5_CLK_OUTPUT_CFG0_SLEW_MASK; + switch (value) { + case 80: + clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_80; + break; + case 85: + clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_85; + break; + case 90: + clk_out->clk_output_cfg0 |= VC5_CLK_OUTPUT_CFG0_SLEW_90; + break; + case 100: + clk_out->clk_output_cfg0 |= + VC5_CLK_OUTPUT_CFG0_SLEW_100; + break; + default: + return -EINVAL; + } + } + return 0; +} + +static int vc5_get_output_config(struct i2c_client *client, + struct vc5_hw_data *clk_out) +{ + struct device_node *np_output; + char *child_name; + int ret = 0; + + child_name = kasprintf(GFP_KERNEL, "OUT%d", clk_out->num + 1); + np_output = of_get_child_by_name(client->dev.of_node, child_name); + kfree(child_name); + if (!np_output) + goto output_done; + + ret = vc5_update_mode(np_output, clk_out); + if (ret) + goto output_error; + + ret = vc5_update_power(np_output, clk_out); + if (ret) + goto output_error; + + ret = vc5_update_slew(np_output, clk_out); + +output_error: + if (ret) { + dev_err(&client->dev, + "Invalid clock output configuration OUT%d\n", + clk_out->num + 1); + } + + of_node_put(np_output); + +output_done: + return ret; +} + static const struct of_device_id clk_vc5_of_match[]; static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) @@ -863,6 +1014,11 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) init.name); goto err_clk; } + + /* Fetch Clock Output configuration from DT (if specified) */ + ret = vc5_get_output_config(client, &vc5->clk_out[n]); + if (ret) + goto err_clk; } ret = of_clk_add_hw_provider(client->dev.of_node, vc5_of_clk_get, vc5); From eb46f547a2fa9d5913c76066eab34efbd7f2252c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 26 Jun 2020 13:25:13 +0200 Subject: [PATCH 53/94] clk: bcm: dvp: Add missing module informations The driver for the DVP controller in the BCM2711 was missing the MODULE_* macros resulting in a modpost warning at compilation. Fixes: 1bc95972715a ("clk: bcm: Add BCM2711 DVP driver") Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20200626112513.90816-1-maxime@cerno.tech Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2711-dvp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/bcm/clk-bcm2711-dvp.c b/drivers/clk/bcm/clk-bcm2711-dvp.c index 84dbc886e303..8333e20dc9d2 100644 --- a/drivers/clk/bcm/clk-bcm2711-dvp.c +++ b/drivers/clk/bcm/clk-bcm2711-dvp.c @@ -118,3 +118,7 @@ static struct platform_driver clk_dvp_driver = { }, }; module_platform_driver(clk_dvp_driver); + +MODULE_AUTHOR("Maxime Ripard "); +MODULE_DESCRIPTION("BCM2711 DVP clock driver"); +MODULE_LICENSE("GPL"); From dbb988b4e7eb924ffceaa2a7da6e794c868cb2f3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 28 Jun 2020 02:30:55 +0000 Subject: [PATCH 54/94] clk: qcom: Fix return value check in apss_ipq6018_probe() In case of error, the function dev_get_regmap() returns NULL pointer not ERR_PTR(). The IS_ERR() test in the return value check should be replaced with NULL test. Fixes: 5e77b4ef1b19 ("clk: qcom: Add ipq6018 apss clock controller") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20200628023055.50608-1-weiyongjun1@huawei.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/apss-ipq6018.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/apss-ipq6018.c b/drivers/clk/qcom/apss-ipq6018.c index 004f7e1ecdc2..d78ff2f310bf 100644 --- a/drivers/clk/qcom/apss-ipq6018.c +++ b/drivers/clk/qcom/apss-ipq6018.c @@ -87,8 +87,8 @@ 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); + if (!regmap) + return -ENODEV; return qcom_cc_really_probe(pdev, &apss_ipq6018_desc, regmap); } From 6d0efeb14bbe2350a94ba07b403a686d731c5179 Mon Sep 17 00:00:00 2001 From: Ilia Lin Date: Fri, 3 Jul 2020 10:49:41 +0200 Subject: [PATCH 55/94] soc: qcom: Separate kryo l2 accessors from PMU driver The driver provides kernel level API for other drivers to access the MSM8996 L2 cache registers. Separating the L2 access code from the PMU driver and making it public to allow other drivers use it. The accesses must be separated with a single spinlock, maintained in this driver. Signed-off-by: Ilia Lin Signed-off-by: Loic Poulain Link: https://lore.kernel.org/r/1593766185-16346-2-git-send-email-loic.poulain@linaro.org Acked-by: Will Deacon Signed-off-by: Stephen Boyd --- drivers/perf/Kconfig | 1 + drivers/perf/qcom_l2_pmu.c | 90 ++++++++-------------------- drivers/soc/qcom/Kconfig | 4 ++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/kryo-l2-accessors.c | 57 ++++++++++++++++++ include/soc/qcom/kryo-l2-accessors.h | 12 ++++ 6 files changed, 99 insertions(+), 66 deletions(-) create mode 100644 drivers/soc/qcom/kryo-l2-accessors.c create mode 100644 include/soc/qcom/kryo-l2-accessors.h diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index a9261cf48293..7305d57d1890 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig @@ -82,6 +82,7 @@ config FSL_IMX8_DDR_PMU config QCOM_L2_PMU bool "Qualcomm Technologies L2-cache PMU" depends on ARCH_QCOM && ARM64 && ACPI + select QCOM_KRYO_L2_ACCESSORS help Provides support for the L2 cache performance monitor unit (PMU) in Qualcomm Technologies processors. diff --git a/drivers/perf/qcom_l2_pmu.c b/drivers/perf/qcom_l2_pmu.c index 21d6991dbe0b..02ca1fadbedd 100644 --- a/drivers/perf/qcom_l2_pmu.c +++ b/drivers/perf/qcom_l2_pmu.c @@ -23,6 +23,7 @@ #include #include #include +#include #define MAX_L2_CTRS 9 @@ -79,8 +80,6 @@ #define L2_COUNTER_RELOAD BIT_ULL(31) #define L2_CYCLE_COUNTER_RELOAD BIT_ULL(63) -#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6) -#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7) #define reg_idx(reg, i) (((i) * IA_L2_REG_OFFSET) + reg##_BASE) @@ -99,48 +98,7 @@ #define L2_EVENT_STREX 0x421 #define L2_EVENT_CLREX 0x422 -static DEFINE_RAW_SPINLOCK(l2_access_lock); -/** - * set_l2_indirect_reg: write value to an L2 register - * @reg: Address of L2 register. - * @value: Value to be written to register. - * - * Use architecturally required barriers for ordering between system register - * accesses - */ -static void set_l2_indirect_reg(u64 reg, u64 val) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&l2_access_lock, flags); - write_sysreg_s(reg, L2CPUSRSELR_EL1); - isb(); - write_sysreg_s(val, L2CPUSRDR_EL1); - isb(); - raw_spin_unlock_irqrestore(&l2_access_lock, flags); -} - -/** - * get_l2_indirect_reg: read an L2 register value - * @reg: Address of L2 register. - * - * Use architecturally required barriers for ordering between system register - * accesses - */ -static u64 get_l2_indirect_reg(u64 reg) -{ - u64 val; - unsigned long flags; - - raw_spin_lock_irqsave(&l2_access_lock, flags); - write_sysreg_s(reg, L2CPUSRSELR_EL1); - isb(); - val = read_sysreg_s(L2CPUSRDR_EL1); - raw_spin_unlock_irqrestore(&l2_access_lock, flags); - - return val; -} struct cluster_pmu; @@ -211,28 +169,28 @@ static inline struct cluster_pmu *get_cluster_pmu( static void cluster_pmu_reset(void) { /* Reset all counters */ - set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL); - set_l2_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask); - set_l2_indirect_reg(L2PMINTENCLR, l2_counter_present_mask); - set_l2_indirect_reg(L2PMOVSCLR, l2_counter_present_mask); + kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_RESET_ALL); + kryo_l2_set_indirect_reg(L2PMCNTENCLR, l2_counter_present_mask); + kryo_l2_set_indirect_reg(L2PMINTENCLR, l2_counter_present_mask); + kryo_l2_set_indirect_reg(L2PMOVSCLR, l2_counter_present_mask); } static inline void cluster_pmu_enable(void) { - set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE); + kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_ENABLE); } static inline void cluster_pmu_disable(void) { - set_l2_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE); + kryo_l2_set_indirect_reg(L2PMCR, L2PMCR_COUNTERS_DISABLE); } static inline void cluster_pmu_counter_set_value(u32 idx, u64 value) { if (idx == l2_cycle_ctr_idx) - set_l2_indirect_reg(L2PMCCNTR, value); + kryo_l2_set_indirect_reg(L2PMCCNTR, value); else - set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value); + kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx), value); } static inline u64 cluster_pmu_counter_get_value(u32 idx) @@ -240,46 +198,46 @@ static inline u64 cluster_pmu_counter_get_value(u32 idx) u64 value; if (idx == l2_cycle_ctr_idx) - value = get_l2_indirect_reg(L2PMCCNTR); + value = kryo_l2_get_indirect_reg(L2PMCCNTR); else - value = get_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx)); + value = kryo_l2_get_indirect_reg(reg_idx(IA_L2PMXEVCNTR, idx)); return value; } static inline void cluster_pmu_counter_enable(u32 idx) { - set_l2_indirect_reg(L2PMCNTENSET, idx_to_reg_bit(idx)); + kryo_l2_set_indirect_reg(L2PMCNTENSET, idx_to_reg_bit(idx)); } static inline void cluster_pmu_counter_disable(u32 idx) { - set_l2_indirect_reg(L2PMCNTENCLR, idx_to_reg_bit(idx)); + kryo_l2_set_indirect_reg(L2PMCNTENCLR, idx_to_reg_bit(idx)); } static inline void cluster_pmu_counter_enable_interrupt(u32 idx) { - set_l2_indirect_reg(L2PMINTENSET, idx_to_reg_bit(idx)); + kryo_l2_set_indirect_reg(L2PMINTENSET, idx_to_reg_bit(idx)); } static inline void cluster_pmu_counter_disable_interrupt(u32 idx) { - set_l2_indirect_reg(L2PMINTENCLR, idx_to_reg_bit(idx)); + kryo_l2_set_indirect_reg(L2PMINTENCLR, idx_to_reg_bit(idx)); } static inline void cluster_pmu_set_evccntcr(u32 val) { - set_l2_indirect_reg(L2PMCCNTCR, val); + kryo_l2_set_indirect_reg(L2PMCCNTCR, val); } static inline void cluster_pmu_set_evcntcr(u32 ctr, u32 val) { - set_l2_indirect_reg(reg_idx(IA_L2PMXEVCNTCR, ctr), val); + kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVCNTCR, ctr), val); } static inline void cluster_pmu_set_evtyper(u32 ctr, u32 val) { - set_l2_indirect_reg(reg_idx(IA_L2PMXEVTYPER, ctr), val); + kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVTYPER, ctr), val); } static void cluster_pmu_set_resr(struct cluster_pmu *cluster, @@ -295,11 +253,11 @@ static void cluster_pmu_set_resr(struct cluster_pmu *cluster, spin_lock_irqsave(&cluster->pmu_lock, flags); - resr_val = get_l2_indirect_reg(L2PMRESR); + resr_val = kryo_l2_get_indirect_reg(L2PMRESR); resr_val &= ~(L2PMRESR_GROUP_MASK << shift); resr_val |= field; resr_val |= L2PMRESR_EN; - set_l2_indirect_reg(L2PMRESR, resr_val); + kryo_l2_set_indirect_reg(L2PMRESR, resr_val); spin_unlock_irqrestore(&cluster->pmu_lock, flags); } @@ -315,14 +273,14 @@ static inline void cluster_pmu_set_evfilter_sys_mode(u32 ctr) L2PMXEVFILTER_ORGFILTER_IDINDEP | L2PMXEVFILTER_ORGFILTER_ALL; - set_l2_indirect_reg(reg_idx(IA_L2PMXEVFILTER, ctr), val); + kryo_l2_set_indirect_reg(reg_idx(IA_L2PMXEVFILTER, ctr), val); } static inline u32 cluster_pmu_getreset_ovsr(void) { - u32 result = get_l2_indirect_reg(L2PMOVSSET); + u32 result = kryo_l2_get_indirect_reg(L2PMOVSSET); - set_l2_indirect_reg(L2PMOVSCLR, result); + kryo_l2_set_indirect_reg(L2PMOVSCLR, result); return result; } @@ -767,7 +725,7 @@ static int get_num_counters(void) { int val; - val = get_l2_indirect_reg(L2PMCR); + val = kryo_l2_get_indirect_reg(L2PMCR); /* * Read number of counters from L2PMCR and add 1 diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 07bb261a63d2..cdc4f46d64ef 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -53,6 +53,10 @@ config QCOM_LLCC SDM845. This provides interfaces to clients that use the LLCC. Say yes here to enable LLCC slice driver. +config QCOM_KRYO_L2_ACCESSORS + bool + depends on ARCH_QCOM && ARM64 || COMPILE_TEST + config QCOM_MDT_LOADER tristate select QCOM_SCM diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 7d7e2ecbdce6..93392d9dc7f7 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -24,3 +24,4 @@ obj-$(CONFIG_QCOM_APR) += apr.o obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o +obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) += kryo-l2-accessors.o diff --git a/drivers/soc/qcom/kryo-l2-accessors.c b/drivers/soc/qcom/kryo-l2-accessors.c new file mode 100644 index 000000000000..c20cb92077c0 --- /dev/null +++ b/drivers/soc/qcom/kryo-l2-accessors.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#define L2CPUSRSELR_EL1 sys_reg(3, 3, 15, 0, 6) +#define L2CPUSRDR_EL1 sys_reg(3, 3, 15, 0, 7) + +static DEFINE_RAW_SPINLOCK(l2_access_lock); + +/** + * kryo_l2_set_indirect_reg() - write value to an L2 register + * @reg: Address of L2 register. + * @value: Value to be written to register. + * + * Use architecturally required barriers for ordering between system register + * accesses, and system registers with respect to device memory + */ +void kryo_l2_set_indirect_reg(u64 reg, u64 val) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&l2_access_lock, flags); + write_sysreg_s(reg, L2CPUSRSELR_EL1); + isb(); + write_sysreg_s(val, L2CPUSRDR_EL1); + isb(); + raw_spin_unlock_irqrestore(&l2_access_lock, flags); +} +EXPORT_SYMBOL(kryo_l2_set_indirect_reg); + +/** + * kryo_l2_get_indirect_reg() - read an L2 register value + * @reg: Address of L2 register. + * + * Use architecturally required barriers for ordering between system register + * accesses, and system registers with respect to device memory + */ +u64 kryo_l2_get_indirect_reg(u64 reg) +{ + u64 val; + unsigned long flags; + + raw_spin_lock_irqsave(&l2_access_lock, flags); + write_sysreg_s(reg, L2CPUSRSELR_EL1); + isb(); + val = read_sysreg_s(L2CPUSRDR_EL1); + raw_spin_unlock_irqrestore(&l2_access_lock, flags); + + return val; +} +EXPORT_SYMBOL(kryo_l2_get_indirect_reg); diff --git a/include/soc/qcom/kryo-l2-accessors.h b/include/soc/qcom/kryo-l2-accessors.h new file mode 100644 index 000000000000..673c5344afe3 --- /dev/null +++ b/include/soc/qcom/kryo-l2-accessors.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + */ + +#ifndef __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H +#define __SOC_ARCH_QCOM_KRYO_L2_ACCESSORS_H + +void kryo_l2_set_indirect_reg(u64 reg, u64 val); +u64 kryo_l2_get_indirect_reg(u64 reg); + +#endif From 2283f9e03328b2437abddf446027931631af1031 Mon Sep 17 00:00:00 2001 From: Ilia Lin Date: Fri, 3 Jul 2020 10:49:43 +0200 Subject: [PATCH 56/94] dt-bindings: clk: qcom: Add bindings for CPU clock for msm8996 Each of the CPU clusters (Power and Perf) on msm8996 are clocked via 2 PLLs, a primary and alternate. There are also 2 Mux'es, a primary and secondary all connected together as shown below +-------+ XO | | +------------------>0 | | | PLL/2 | SMUX +----+ +------->1 | | | | | | | +-------+ | +-------+ | +---->0 | | | | +---------------+ | +----------->1 | CPU clk |Primary PLL +----+ PLL_EARLY | | +------> | +------+-----------+ +------>2 PMUX | +---------------+ | | | | | +------+ | +-->3 | +--^+ ACD +-----+ | +-------+ +---------------+ +------+ | |Alt PLL | | | +---------------------------+ +---------------+ PLL_EARLY The primary PLL is what drives the CPU clk, except for times when we are reprogramming the PLL itself (for rate changes) when we temporarily switch to an alternate PLL. A subsequent patch adds support to switch between primary and alternate PLL during rate changes. The primary PLL operates on a single VCO range, between 600MHz and 3GHz. However the CPUs do support OPPs with frequencies between 300MHz and 600MHz. In order to support running the CPUs at those frequencies we end up having to lock the PLL at twice the rate and drive the CPU clk via the PLL/2 output and SMUX. Signed-off-by: Ilia Lin Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1593766185-16346-4-git-send-email-loic.poulain@linaro.org Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,msm8996-apcc.yaml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml diff --git a/Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml b/Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml new file mode 100644 index 000000000000..d673edeed98d --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,kryocc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm clock controller for MSM8996 CPUs + +maintainers: + - Loic Poulain + +description: | + Qualcomm CPU clock controller for MSM8996 CPUs, clock 0 is for Power cluster + and clock 1 is for Perf cluster. + +properties: + compatible: + enum: + - qcom,msm8996-apcc + + reg: + maxItems: 1 + + '#clock-cells': + const: 1 + + clocks: + items: + - description: Primary PLL clock for power cluster (little) + - description: Primary PLL clock for perf cluster (big) + - description: Alternate PLL clock for power cluster (little) + - description: Alternate PLL clock for perf cluster (big) + + clock-names: + items: + - const: pwrcl_pll + - const: perfcl_pll + - const: pwrcl_alt_pll + - const: perfcl_alt_pll + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + # Example for msm8996 + - | + kryocc: clock-controller@6400000 { + compatible = "qcom,msm8996-apcc"; + reg = <0x6400000 0x90000>; + #clock-cells = <1>; + }; +... From 03e342dc45c9ec07303953d4e4af11879be36609 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 3 Jul 2020 10:49:42 +0200 Subject: [PATCH 57/94] clk: qcom: Add CPU clock driver for msm8996 Each of the CPU clusters (Power and Perf) on msm8996 are clocked via 2 PLLs, a primary and alternate. There are also 2 Mux'es, a primary and secondary all connected together as shown below +-------+ XO | | +------------------>0 | | | PLL/2 | SMUX +----+ +------->1 | | | | | | | +-------+ | +-------+ | +---->0 | | | | +---------------+ | +----------->1 | CPU clk |Primary PLL +----+ PLL_EARLY | | +------> | +------+-----------+ +------>2 PMUX | +---------------+ | | | | | +------+ | +-->3 | +--^+ ACD +-----+ | +-------+ +---------------+ +------+ | |Alt PLL | | | +---------------------------+ +---------------+ PLL_EARLY The primary PLL is what drives the CPU clk, except for times when we are reprogramming the PLL itself (for rate changes) when we temporarily switch to an alternate PLL. A subsequent patch adds support to switch between primary and alternate PLL during rate changes. The primary PLL operates on a single VCO range, between 600MHz and 3GHz. However the CPUs do support OPPs with frequencies between 300MHz and 600MHz. In order to support running the CPUs at those frequencies we end up having to lock the PLL at twice the rate and drive the CPU clk via the PLL/2 output and SMUX. So for frequencies above 600MHz we follow the following path Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk and for frequencies between 300MHz and 600MHz we follow Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk ACD stands for Adaptive Clock Distribution and is used to detect voltage droops. Signed-off-by: Rajendra Nayak Rajendra Nayak: Initial RFC - https://lkml.org/lkml/2016/9/29/84 Signed-off-by: Ilia Lin Ilia Lin: - reworked clock registering - Added clock-tree diagram - non-builtin support - clock notifier on rate change - https://lkml.org/lkml/2018/5/24/123 Signed-off-by: Loic Poulain Loic Poulain: - fixed driver remove / clk deregistering - Removed useless memory barriers - devm usage when possible - Fixed Kconfig depends Link: https://lore.kernel.org/r/1593766185-16346-3-git-send-email-loic.poulain@linaro.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/clk-alpha-pll.h | 6 + drivers/clk/qcom/clk-cpu-8996.c | 538 +++++++++++++++++++++++++++++++ 4 files changed, 554 insertions(+) create mode 100644 drivers/clk/qcom/clk-cpu-8996.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index f510ef61db69..318c0adfaae1 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -37,6 +37,15 @@ config QCOM_CLK_APCS_MSM8916 Say Y if you want to support CPU frequency scaling on devices such as msm8916. +config QCOM_CLK_APCC_MSM8996 + tristate "MSM8996 CPU Clock Controller" + select QCOM_KRYO_L2_ACCESSORS + depends on ARM64 + help + Support for the CPU clock controller on msm8996 devices. + Say Y if you want to support CPU clock scaling using CPUfreq + drivers for dyanmic power management. + config QCOM_CLK_RPM tristate "RPM based Clock Controller" depends on MFD_QCOM_RPM diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 21439b94395a..ae0979bebe18 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o obj-$(CONFIG_MSM_MMCC_8998) += mmcc-msm8998.o obj-$(CONFIG_QCOM_A53PLL) += a53-pll.o obj-$(CONFIG_QCOM_CLK_APCS_MSM8916) += apcs-msm8916.o +obj-$(CONFIG_QCOM_CLK_APCC_MSM8996) += clk-cpu-8996.o obj-$(CONFIG_QCOM_CLK_RPM) += clk-rpm.o obj-$(CONFIG_QCOM_CLK_RPMH) += clk-rpmh.o obj-$(CONFIG_QCOM_CLK_SMD_RPM) += clk-smd-rpm.o diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 704674a153b6..1ba82be93dd5 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -47,6 +47,12 @@ struct pll_vco { u32 val; }; +#define VCO(a, b, c) { \ + .val = a,\ + .min_freq = b,\ + .max_freq = c,\ +} + /** * struct clk_alpha_pll - phase locked loop (PLL) * @offset: base address of registers diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c new file mode 100644 index 000000000000..77a2d2806e58 --- /dev/null +++ b/drivers/clk/qcom/clk-cpu-8996.c @@ -0,0 +1,538 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +/* + * Each of the CPU clusters (Power and Perf) on msm8996 are + * clocked via 2 PLLs, a primary and alternate. There are also + * 2 Mux'es, a primary and secondary all connected together + * as shown below + * + * +-------+ + * XO | | + * +------------------>0 | + * | | + * PLL/2 | SMUX +----+ + * +------->1 | | + * | | | | + * | +-------+ | +-------+ + * | +---->0 | + * | | | + * +---------------+ | +----------->1 | CPU clk + * |Primary PLL +----+ PLL_EARLY | | +------> + * | +------+-----------+ +------>2 PMUX | + * +---------------+ | | | | + * | +------+ | +-->3 | + * +--^+ ACD +-----+ | +-------+ + * +---------------+ +------+ | + * |Alt PLL | | + * | +---------------------------+ + * +---------------+ PLL_EARLY + * + * The primary PLL is what drives the CPU clk, except for times + * when we are reprogramming the PLL itself (for rate changes) when + * we temporarily switch to an alternate PLL. + * + * The primary PLL operates on a single VCO range, between 600MHz + * and 3GHz. However the CPUs do support OPPs with frequencies + * between 300MHz and 600MHz. In order to support running the CPUs + * at those frequencies we end up having to lock the PLL at twice + * the rate and drive the CPU clk via the PLL/2 output and SMUX. + * + * So for frequencies above 600MHz we follow the following path + * Primary PLL --> PLL_EARLY --> PMUX(1) --> CPU clk + * and for frequencies between 300MHz and 600MHz we follow + * Primary PLL --> PLL/2 --> SMUX(1) --> PMUX(0) --> CPU clk + * + * ACD stands for Adaptive Clock Distribution and is used to + * detect voltage droops. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk-alpha-pll.h" +#include "clk-regmap.h" + +enum _pmux_input { + DIV_2_INDEX = 0, + PLL_INDEX, + ACD_INDEX, + ALT_INDEX, + NUM_OF_PMUX_INPUTS +}; + +#define DIV_2_THRESHOLD 600000000 +#define PWRCL_REG_OFFSET 0x0 +#define PERFCL_REG_OFFSET 0x80000 +#define MUX_OFFSET 0x40 +#define ALT_PLL_OFFSET 0x100 +#define SSSCTL_OFFSET 0x160 + +static const u8 prim_pll_regs[PLL_OFF_MAX_REGS] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_ALPHA_VAL] = 0x08, + [PLL_OFF_USER_CTL] = 0x10, + [PLL_OFF_CONFIG_CTL] = 0x18, + [PLL_OFF_CONFIG_CTL_U] = 0x1c, + [PLL_OFF_TEST_CTL] = 0x20, + [PLL_OFF_TEST_CTL_U] = 0x24, + [PLL_OFF_STATUS] = 0x28, +}; + +static const u8 alt_pll_regs[PLL_OFF_MAX_REGS] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_ALPHA_VAL] = 0x08, + [PLL_OFF_ALPHA_VAL_U] = 0x0c, + [PLL_OFF_USER_CTL] = 0x10, + [PLL_OFF_USER_CTL_U] = 0x14, + [PLL_OFF_CONFIG_CTL] = 0x18, + [PLL_OFF_TEST_CTL] = 0x20, + [PLL_OFF_TEST_CTL_U] = 0x24, + [PLL_OFF_STATUS] = 0x28, +}; + +/* PLLs */ + +static const struct alpha_pll_config hfpll_config = { + .l = 60, + .config_ctl_val = 0x200d4aa8, + .config_ctl_hi_val = 0x006, + .pre_div_mask = BIT(12), + .post_div_mask = 0x3 << 8, + .post_div_val = 0x1 << 8, + .main_output_mask = BIT(0), + .early_output_mask = BIT(3), +}; + +static struct clk_alpha_pll perfcl_pll = { + .offset = PERFCL_REG_OFFSET, + .regs = prim_pll_regs, + .flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE, + .clkr.hw.init = &(struct clk_init_data){ + .name = "perfcl_pll", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_huayra_ops, + }, +}; + +static struct clk_alpha_pll pwrcl_pll = { + .offset = PWRCL_REG_OFFSET, + .regs = prim_pll_regs, + .flags = SUPPORTS_DYNAMIC_UPDATE | SUPPORTS_FSM_MODE, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pwrcl_pll", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_huayra_ops, + }, +}; + +static const struct pll_vco alt_pll_vco_modes[] = { + VCO(3, 250000000, 500000000), + VCO(2, 500000000, 750000000), + VCO(1, 750000000, 1000000000), + VCO(0, 1000000000, 2150400000), +}; + +static const struct alpha_pll_config altpll_config = { + .l = 16, + .vco_val = 0x3 << 20, + .vco_mask = 0x3 << 20, + .config_ctl_val = 0x4001051b, + .post_div_mask = 0x3 << 8, + .post_div_val = 0x1 << 8, + .main_output_mask = BIT(0), + .early_output_mask = BIT(3), +}; + +static struct clk_alpha_pll perfcl_alt_pll = { + .offset = PERFCL_REG_OFFSET + ALT_PLL_OFFSET, + .regs = alt_pll_regs, + .vco_table = alt_pll_vco_modes, + .num_vco = ARRAY_SIZE(alt_pll_vco_modes), + .flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE, + .clkr.hw.init = &(struct clk_init_data) { + .name = "perfcl_alt_pll", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_hwfsm_ops, + }, +}; + +static struct clk_alpha_pll pwrcl_alt_pll = { + .offset = PWRCL_REG_OFFSET + ALT_PLL_OFFSET, + .regs = alt_pll_regs, + .vco_table = alt_pll_vco_modes, + .num_vco = ARRAY_SIZE(alt_pll_vco_modes), + .flags = SUPPORTS_OFFLINE_REQ | SUPPORTS_FSM_MODE, + .clkr.hw.init = &(struct clk_init_data) { + .name = "pwrcl_alt_pll", + .parent_names = (const char *[]){ "xo" }, + .num_parents = 1, + .ops = &clk_alpha_pll_hwfsm_ops, + }, +}; + +struct clk_cpu_8996_mux { + u32 reg; + u8 shift; + u8 width; + struct notifier_block nb; + struct clk_hw *pll; + struct clk_hw *pll_div_2; + struct clk_regmap clkr; +}; + +static int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event, + void *data); + +#define to_clk_cpu_8996_mux_nb(_nb) \ + container_of(_nb, struct clk_cpu_8996_mux, nb) + +static inline struct clk_cpu_8996_mux *to_clk_cpu_8996_mux_hw(struct clk_hw *hw) +{ + return container_of(to_clk_regmap(hw), struct clk_cpu_8996_mux, clkr); +} + +static u8 clk_cpu_8996_mux_get_parent(struct clk_hw *hw) +{ + struct clk_regmap *clkr = to_clk_regmap(hw); + struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw); + u32 mask = GENMASK(cpuclk->width - 1, 0); + u32 val; + + regmap_read(clkr->regmap, cpuclk->reg, &val); + val >>= cpuclk->shift; + + return val & mask; +} + +static int clk_cpu_8996_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_regmap *clkr = to_clk_regmap(hw); + struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw); + u32 mask = GENMASK(cpuclk->width + cpuclk->shift - 1, cpuclk->shift); + u32 val; + + val = index; + val <<= cpuclk->shift; + + return regmap_update_bits(clkr->regmap, cpuclk->reg, mask, val); +} + +static int clk_cpu_8996_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_hw(hw); + struct clk_hw *parent = cpuclk->pll; + + if (cpuclk->pll_div_2 && req->rate < DIV_2_THRESHOLD) { + if (req->rate < (DIV_2_THRESHOLD / 2)) + return -EINVAL; + + parent = cpuclk->pll_div_2; + } + + req->best_parent_rate = clk_hw_round_rate(parent, req->rate); + req->best_parent_hw = parent; + + return 0; +} + +static const struct clk_ops clk_cpu_8996_mux_ops = { + .set_parent = clk_cpu_8996_mux_set_parent, + .get_parent = clk_cpu_8996_mux_get_parent, + .determine_rate = clk_cpu_8996_mux_determine_rate, +}; + +static struct clk_cpu_8996_mux pwrcl_smux = { + .reg = PWRCL_REG_OFFSET + MUX_OFFSET, + .shift = 2, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "pwrcl_smux", + .parent_names = (const char *[]){ + "xo", + "pwrcl_pll_main", + }, + .num_parents = 2, + .ops = &clk_cpu_8996_mux_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_cpu_8996_mux perfcl_smux = { + .reg = PERFCL_REG_OFFSET + MUX_OFFSET, + .shift = 2, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "perfcl_smux", + .parent_names = (const char *[]){ + "xo", + "perfcl_pll_main", + }, + .num_parents = 2, + .ops = &clk_cpu_8996_mux_ops, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_cpu_8996_mux pwrcl_pmux = { + .reg = PWRCL_REG_OFFSET + MUX_OFFSET, + .shift = 0, + .width = 2, + .pll = &pwrcl_pll.clkr.hw, + .pll_div_2 = &pwrcl_smux.clkr.hw, + .nb.notifier_call = cpu_clk_notifier_cb, + .clkr.hw.init = &(struct clk_init_data) { + .name = "pwrcl_pmux", + .parent_names = (const char *[]){ + "pwrcl_smux", + "pwrcl_pll", + "pwrcl_pll_acd", + "pwrcl_alt_pll", + }, + .num_parents = 4, + .ops = &clk_cpu_8996_mux_ops, + /* CPU clock is critical and should never be gated */ + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + }, +}; + +static struct clk_cpu_8996_mux perfcl_pmux = { + .reg = PERFCL_REG_OFFSET + MUX_OFFSET, + .shift = 0, + .width = 2, + .pll = &perfcl_pll.clkr.hw, + .pll_div_2 = &perfcl_smux.clkr.hw, + .nb.notifier_call = cpu_clk_notifier_cb, + .clkr.hw.init = &(struct clk_init_data) { + .name = "perfcl_pmux", + .parent_names = (const char *[]){ + "perfcl_smux", + "perfcl_pll", + "perfcl_pll_acd", + "perfcl_alt_pll", + }, + .num_parents = 4, + .ops = &clk_cpu_8996_mux_ops, + /* CPU clock is critical and should never be gated */ + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, + }, +}; + +static const struct regmap_config cpu_msm8996_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x80210, + .fast_io = true, + .val_format_endian = REGMAP_ENDIAN_LITTLE, +}; + +struct clk_regmap *cpu_msm8996_clks[] = { + &perfcl_pll.clkr, + &pwrcl_pll.clkr, + &perfcl_alt_pll.clkr, + &pwrcl_alt_pll.clkr, + &perfcl_smux.clkr, + &pwrcl_smux.clkr, + &perfcl_pmux.clkr, + &pwrcl_pmux.clkr, +}; + +static int qcom_cpu_clk_msm8996_register_clks(struct device *dev, + struct regmap *regmap) +{ + int i, ret; + + perfcl_smux.pll = clk_hw_register_fixed_factor(dev, "perfcl_pll_main", + "perfcl_pll", + CLK_SET_RATE_PARENT, + 1, 2); + if (IS_ERR(perfcl_smux.pll)) { + dev_err(dev, "Failed to initialize perfcl_pll_main\n"); + return PTR_ERR(perfcl_smux.pll); + } + + pwrcl_smux.pll = clk_hw_register_fixed_factor(dev, "pwrcl_pll_main", + "pwrcl_pll", + CLK_SET_RATE_PARENT, + 1, 2); + if (IS_ERR(pwrcl_smux.pll)) { + dev_err(dev, "Failed to initialize pwrcl_pll_main\n"); + clk_hw_unregister(perfcl_smux.pll); + return PTR_ERR(pwrcl_smux.pll); + } + + for (i = 0; i < ARRAY_SIZE(cpu_msm8996_clks); i++) { + ret = devm_clk_register_regmap(dev, cpu_msm8996_clks[i]); + if (ret) { + clk_hw_unregister(perfcl_smux.pll); + clk_hw_unregister(pwrcl_smux.pll); + return ret; + } + } + + clk_alpha_pll_configure(&perfcl_pll, regmap, &hfpll_config); + clk_alpha_pll_configure(&pwrcl_pll, regmap, &hfpll_config); + clk_alpha_pll_configure(&perfcl_alt_pll, regmap, &altpll_config); + clk_alpha_pll_configure(&pwrcl_alt_pll, regmap, &altpll_config); + + /* Enable alt PLLs */ + clk_prepare_enable(pwrcl_alt_pll.clkr.hw.clk); + clk_prepare_enable(perfcl_alt_pll.clkr.hw.clk); + + clk_notifier_register(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb); + clk_notifier_register(perfcl_pmux.clkr.hw.clk, &perfcl_pmux.nb); + + return ret; +} + +static int qcom_cpu_clk_msm8996_unregister_clks(void) +{ + int ret = 0; + + ret = clk_notifier_unregister(pwrcl_pmux.clkr.hw.clk, &pwrcl_pmux.nb); + if (ret) + return ret; + + ret = clk_notifier_unregister(perfcl_pmux.clkr.hw.clk, &perfcl_pmux.nb); + if (ret) + return ret; + + clk_hw_unregister(perfcl_smux.pll); + clk_hw_unregister(pwrcl_smux.pll); + + return 0; +} + +#define CPU_AFINITY_MASK 0xFFF +#define PWRCL_CPU_REG_MASK 0x3 +#define PERFCL_CPU_REG_MASK 0x103 + +#define L2ACDCR_REG 0x580ULL +#define L2ACDTD_REG 0x581ULL +#define L2ACDDVMRC_REG 0x584ULL +#define L2ACDSSCR_REG 0x589ULL + +static DEFINE_SPINLOCK(qcom_clk_acd_lock); +static void __iomem *base; + +static void qcom_cpu_clk_msm8996_acd_init(void __iomem *base) +{ + u64 hwid; + unsigned long flags; + + spin_lock_irqsave(&qcom_clk_acd_lock, flags); + + hwid = read_cpuid_mpidr() & CPU_AFINITY_MASK; + + kryo_l2_set_indirect_reg(L2ACDTD_REG, 0x00006a11); + kryo_l2_set_indirect_reg(L2ACDDVMRC_REG, 0x000e0f0f); + kryo_l2_set_indirect_reg(L2ACDSSCR_REG, 0x00000601); + + if (PWRCL_CPU_REG_MASK == (hwid | PWRCL_CPU_REG_MASK)) { + writel(0xf, base + PWRCL_REG_OFFSET + SSSCTL_OFFSET); + kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002c5ffd); + } + + if (PERFCL_CPU_REG_MASK == (hwid | PERFCL_CPU_REG_MASK)) { + kryo_l2_set_indirect_reg(L2ACDCR_REG, 0x002c5ffd); + writel(0xf, base + PERFCL_REG_OFFSET + SSSCTL_OFFSET); + } + + spin_unlock_irqrestore(&qcom_clk_acd_lock, flags); +} + +static int cpu_clk_notifier_cb(struct notifier_block *nb, unsigned long event, + void *data) +{ + struct clk_cpu_8996_mux *cpuclk = to_clk_cpu_8996_mux_nb(nb); + struct clk_notifier_data *cnd = data; + int ret; + + switch (event) { + case PRE_RATE_CHANGE: + ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, ALT_INDEX); + qcom_cpu_clk_msm8996_acd_init(base); + break; + case POST_RATE_CHANGE: + if (cnd->new_rate < DIV_2_THRESHOLD) + ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, + DIV_2_INDEX); + else + ret = clk_cpu_8996_mux_set_parent(&cpuclk->clkr.hw, + ACD_INDEX); + break; + default: + ret = 0; + break; + } + + return notifier_from_errno(ret); +}; + +static int qcom_cpu_clk_msm8996_driver_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + struct clk_hw_onecell_data *data; + struct device *dev = &pdev->dev; + int ret; + + data = devm_kzalloc(dev, struct_size(data, hws, 2), GFP_KERNEL); + if (!data) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + regmap = devm_regmap_init_mmio(dev, base, &cpu_msm8996_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + ret = qcom_cpu_clk_msm8996_register_clks(dev, regmap); + if (ret) + return ret; + + qcom_cpu_clk_msm8996_acd_init(base); + + data->hws[0] = &pwrcl_pmux.clkr.hw; + data->hws[1] = &perfcl_pmux.clkr.hw; + data->num = 2; + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data); +} + +static int qcom_cpu_clk_msm8996_driver_remove(struct platform_device *pdev) +{ + return qcom_cpu_clk_msm8996_unregister_clks(); +} + +static const struct of_device_id qcom_cpu_clk_msm8996_match_table[] = { + { .compatible = "qcom,msm8996-apcc" }, + {} +}; +MODULE_DEVICE_TABLE(of, qcom_cpu_clk_msm8996_match_table); + +static struct platform_driver qcom_cpu_clk_msm8996_driver = { + .probe = qcom_cpu_clk_msm8996_driver_probe, + .remove = qcom_cpu_clk_msm8996_driver_remove, + .driver = { + .name = "qcom-msm8996-apcc", + .of_match_table = qcom_cpu_clk_msm8996_match_table, + }, +}; +module_platform_driver(qcom_cpu_clk_msm8996_driver); + +MODULE_DESCRIPTION("QCOM MSM8996 CPU Clock Driver"); +MODULE_LICENSE("GPL v2"); From e7fb524cfccaf649b257d517f437392f50b3931f Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Sun, 5 Jul 2020 14:47:54 +0530 Subject: [PATCH 58/94] dt-bindings: clock: qcom: ipq8074: Add missing bindings for PCIe Add missing clock bindings for PCIe port0 of ipq8074. Co-developed-by: Selvam Sathappan Periakaruppan Signed-off-by: Selvam Sathappan Periakaruppan Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1593940680-2363-4-git-send-email-sivaprak@codeaurora.org [sboyd@kernel.org: Clean up commit text subject] Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/qcom,gcc-ipq8074.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/dt-bindings/clock/qcom,gcc-ipq8074.h b/include/dt-bindings/clock/qcom,gcc-ipq8074.h index 4de4811a3540..e3e018565add 100644 --- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h +++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h @@ -362,5 +362,9 @@ #define GCC_PCIE1_AXI_SLAVE_ARES 128 #define GCC_PCIE1_AHB_ARES 129 #define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130 +#define GCC_PCIE0_AXI_SLAVE_STICKY_ARES 131 +#define GCC_PCIE0_AXI_S_BRIDGE_CLK 132 +#define GCC_PCIE0_RCHNG_CLK_SRC 133 +#define GCC_PCIE0_RCHNG_CLK 134 #endif From f0cfcf1ade201dcfd3365f231efc90e846fa46df Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Sun, 5 Jul 2020 14:47:55 +0530 Subject: [PATCH 59/94] clk: qcom: ipq8074: Add missing clocks for pcie Add missing clocks and resets for pcie port0 of ipq8074 devices. Co-developed-by: Selvam Sathappan Periakaruppan Signed-off-by: Selvam Sathappan Periakaruppan Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1593940680-2363-5-git-send-email-sivaprak@codeaurora.org [sboyd@kernel.org: Make freq table static const] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-ipq8074.c | 60 ++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c index e01f5f591d1e..ef2c9c4cf9ab 100644 --- a/drivers/clk/qcom/gcc-ipq8074.c +++ b/drivers/clk/qcom/gcc-ipq8074.c @@ -4316,6 +4316,62 @@ static struct clk_branch gcc_gp3_clk = { }, }; +static const struct freq_tbl ftbl_pcie_rchng_clk_src[] = { + F(19200000, P_XO, 1, 0, 0), + F(100000000, P_GPLL0, 8, 0, 0), + { } +}; + +struct clk_rcg2 pcie0_rchng_clk_src = { + .cmd_rcgr = 0x75070, + .freq_tbl = ftbl_pcie_rchng_clk_src, + .hid_width = 5, + .parent_map = gcc_xo_gpll0_map, + .clkr.hw.init = &(struct clk_init_data){ + .name = "pcie0_rchng_clk_src", + .parent_hws = (const struct clk_hw *[]) { + &gpll0.clkr.hw }, + .num_parents = 2, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gcc_pcie0_rchng_clk = { + .halt_reg = 0x75070, + .halt_bit = 31, + .clkr = { + .enable_reg = 0x75070, + .enable_mask = BIT(1), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_rchng_clk", + .parent_hws = (const struct clk_hw *[]){ + &pcie0_rchng_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie0_axi_s_bridge_clk = { + .halt_reg = 0x75048, + .halt_bit = 31, + .clkr = { + .enable_reg = 0x75048, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_pcie0_axi_s_bridge_clk", + .parent_hws = (const struct clk_hw *[]){ + &pcie0_axi_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_hw *gcc_ipq8074_hws[] = { &gpll0_out_main_div2.hw, &gpll6_out_main_div2.hw, @@ -4551,6 +4607,9 @@ static struct clk_regmap *gcc_ipq8074_clks[] = { [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_PCIE0_RCHNG_CLK_SRC] = &pcie0_rchng_clk_src.clkr, + [GCC_PCIE0_RCHNG_CLK] = &gcc_pcie0_rchng_clk.clkr, + [GCC_PCIE0_AXI_S_BRIDGE_CLK] = &gcc_pcie0_axi_s_bridge_clk.clkr, }; static const struct qcom_reset_map gcc_ipq8074_resets[] = { @@ -4678,6 +4737,7 @@ static const struct qcom_reset_map gcc_ipq8074_resets[] = { [GCC_PCIE0_AXI_SLAVE_ARES] = { 0x75040, 4 }, [GCC_PCIE0_AHB_ARES] = { 0x75040, 5 }, [GCC_PCIE0_AXI_MASTER_STICKY_ARES] = { 0x75040, 6 }, + [GCC_PCIE0_AXI_SLAVE_STICKY_ARES] = { 0x75040, 7 }, [GCC_PCIE1_PIPE_ARES] = { 0x76040, 0 }, [GCC_PCIE1_SLEEP_ARES] = { 0x76040, 1 }, [GCC_PCIE1_CORE_STICKY_ARES] = { 0x76040, 2 }, From b4297844995f380588e6f935a2f98c399129a9b2 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 24 Jun 2020 01:00:18 +0200 Subject: [PATCH 60/94] clk: qcom: smd: Add support for MSM8992/4 rpm clocks Add rpm smd clocks, PMIC and bus clocks which are required on MSM8992, MSM8994 (and APQ variants) for clients to vote on. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20200623230018.303776-1-konradybcio@gmail.com [sboyd@kernel.org: Fixed up binding numbers] Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,rpmcc.txt | 2 + drivers/clk/qcom/clk-smd-rpm.c | 171 ++++++++++++++++++ include/dt-bindings/clock/qcom,rpmcc.h | 4 + 3 files changed, 177 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt index 8786d19ffe17..b44a0622fb3a 100644 --- a/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt +++ b/Documentation/devicetree/bindings/clock/qcom,rpmcc.txt @@ -18,6 +18,8 @@ Required properties : "qcom,rpmcc-msm8976", "qcom,rpmcc" "qcom,rpmcc-apq8064", "qcom,rpmcc" "qcom,rpmcc-ipq806x", "qcom,rpmcc" + "qcom,rpmcc-msm8992",·"qcom,rpmcc" + "qcom,rpmcc-msm8994",·"qcom,rpmcc" "qcom,rpmcc-msm8996", "qcom,rpmcc" "qcom,rpmcc-msm8998", "qcom,rpmcc" "qcom,rpmcc-qcs404", "qcom,rpmcc" diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 083399affc8e..0e1dfa89489e 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -623,6 +623,175 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8976 = { .num_clks = ARRAY_SIZE(msm8976_clks), }; +/* msm8992 */ +DEFINE_CLK_SMD_RPM(msm8992, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8992, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); +DEFINE_CLK_SMD_RPM(msm8992, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8992, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); +DEFINE_CLK_SMD_RPM(msm8992, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); +DEFINE_CLK_SMD_RPM(msm8992, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk1, bb_clk1_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk1_pin, bb_clk1_a_pin, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, bb_clk2, bb_clk2_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, bb_clk2_pin, bb_clk2_a_pin, 2); + +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk1, div_clk1_a, 11); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk2, div_clk2_a, 12); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, div_clk3, div_clk3_a, 13); +DEFINE_CLK_SMD_RPM(msm8992, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, ln_bb_clk, ln_bb_a_clk, 8); +DEFINE_CLK_SMD_RPM(msm8992, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, + QCOM_SMD_RPM_BUS_CLK, 3); +DEFINE_CLK_SMD_RPM_QDSS(msm8992, qdss_clk, qdss_a_clk, + QCOM_SMD_RPM_MISC_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk1, rf_clk1_a, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8992, rf_clk2, rf_clk2_a, 5); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk1_pin, rf_clk1_a_pin, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8992, rf_clk2_pin, rf_clk2_a_pin, 5); + +DEFINE_CLK_SMD_RPM(msm8992, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8992, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1); + +static struct clk_smd_rpm *msm8992_clks[] = { + [RPM_SMD_PNOC_CLK] = &msm8992_pnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8992_pnoc_a_clk, + [RPM_SMD_OCMEMGX_CLK] = &msm8992_ocmemgx_clk, + [RPM_SMD_OCMEMGX_A_CLK] = &msm8992_ocmemgx_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8992_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8992_bimc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8992_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8992_cnoc_a_clk, + [RPM_SMD_GFX3D_CLK_SRC] = &msm8992_gfx3d_clk_src, + [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8992_gfx3d_a_clk_src, + [RPM_SMD_SNOC_CLK] = &msm8992_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8992_snoc_a_clk, + [RPM_SMD_BB_CLK1] = &msm8992_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8992_bb_clk1_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8992_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8992_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2] = &msm8992_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8992_bb_clk2_a, + [RPM_SMD_BB_CLK2_PIN] = &msm8992_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8992_bb_clk2_a_pin, + [RPM_SMD_DIV_CLK1] = &msm8992_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8992_div_clk1_a, + [RPM_SMD_DIV_CLK2] = &msm8992_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8992_div_clk2_a, + [RPM_SMD_DIV_CLK3] = &msm8992_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8992_div_clk3_a, + [RPM_SMD_IPA_CLK] = &msm8992_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8992_ipa_a_clk, + [RPM_SMD_LN_BB_CLK] = &msm8992_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8992_ln_bb_a_clk, + [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8992_mmssnoc_ahb_clk, + [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8992_mmssnoc_ahb_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8992_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8992_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8992_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8992_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8992_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8992_rf_clk2_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8992_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8992_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8992_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8992_rf_clk2_a_pin, + [RPM_SMD_CE1_CLK] = &msm8992_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8992_ce1_a_clk, + [RPM_SMD_CE2_CLK] = &msm8992_ce2_clk, + [RPM_SMD_CE2_A_CLK] = &msm8992_ce2_a_clk, +}; + +static const struct rpm_smd_clk_desc rpm_clk_msm8992 = { + .clks = msm8992_clks, + .num_clks = ARRAY_SIZE(msm8992_clks), +}; + +/* msm8994 */ +DEFINE_CLK_SMD_RPM(msm8994, pnoc_clk, pnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8994, ocmemgx_clk, ocmemgx_a_clk, QCOM_SMD_RPM_MEM_CLK, 2); +DEFINE_CLK_SMD_RPM(msm8994, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8994, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2); +DEFINE_CLK_SMD_RPM(msm8994, gfx3d_clk_src, gfx3d_a_clk_src, QCOM_SMD_RPM_MEM_CLK, 1); +DEFINE_CLK_SMD_RPM(msm8994, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk1, bb_clk1_a, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk1_pin, bb_clk1_a_pin, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, bb_clk2, bb_clk2_a, 2); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, bb_clk2_pin, bb_clk2_a_pin, 2); + +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk1, div_clk1_a, 11); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk2, div_clk2_a, 12); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, div_clk3, div_clk3_a, 13); +DEFINE_CLK_SMD_RPM(msm8994, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, ln_bb_clk, ln_bb_a_clk, 8); +DEFINE_CLK_SMD_RPM(msm8994, mmssnoc_ahb_clk, mmssnoc_ahb_a_clk, + QCOM_SMD_RPM_BUS_CLK, 3); +DEFINE_CLK_SMD_RPM_QDSS(msm8994, qdss_clk, qdss_a_clk, + QCOM_SMD_RPM_MISC_CLK, 1); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk1, rf_clk1_a, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8994, rf_clk2, rf_clk2_a, 5); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk1_pin, rf_clk1_a_pin, 4); +DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8994, rf_clk2_pin, rf_clk2_a_pin, 5); + +DEFINE_CLK_SMD_RPM(msm8994, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0); +DEFINE_CLK_SMD_RPM(msm8994, ce2_clk, ce2_a_clk, QCOM_SMD_RPM_CE_CLK, 1); +DEFINE_CLK_SMD_RPM(msm8994, ce3_clk, ce3_a_clk, QCOM_SMD_RPM_CE_CLK, 2); + +static struct clk_smd_rpm *msm8994_clks[] = { + [RPM_SMD_PNOC_CLK] = &msm8994_pnoc_clk, + [RPM_SMD_PNOC_A_CLK] = &msm8994_pnoc_a_clk, + [RPM_SMD_OCMEMGX_CLK] = &msm8994_ocmemgx_clk, + [RPM_SMD_OCMEMGX_A_CLK] = &msm8994_ocmemgx_a_clk, + [RPM_SMD_BIMC_CLK] = &msm8994_bimc_clk, + [RPM_SMD_BIMC_A_CLK] = &msm8994_bimc_a_clk, + [RPM_SMD_CNOC_CLK] = &msm8994_cnoc_clk, + [RPM_SMD_CNOC_A_CLK] = &msm8994_cnoc_a_clk, + [RPM_SMD_GFX3D_CLK_SRC] = &msm8994_gfx3d_clk_src, + [RPM_SMD_GFX3D_A_CLK_SRC] = &msm8994_gfx3d_a_clk_src, + [RPM_SMD_SNOC_CLK] = &msm8994_snoc_clk, + [RPM_SMD_SNOC_A_CLK] = &msm8994_snoc_a_clk, + [RPM_SMD_BB_CLK1] = &msm8994_bb_clk1, + [RPM_SMD_BB_CLK1_A] = &msm8994_bb_clk1_a, + [RPM_SMD_BB_CLK1_PIN] = &msm8994_bb_clk1_pin, + [RPM_SMD_BB_CLK1_A_PIN] = &msm8994_bb_clk1_a_pin, + [RPM_SMD_BB_CLK2] = &msm8994_bb_clk2, + [RPM_SMD_BB_CLK2_A] = &msm8994_bb_clk2_a, + [RPM_SMD_BB_CLK2_PIN] = &msm8994_bb_clk2_pin, + [RPM_SMD_BB_CLK2_A_PIN] = &msm8994_bb_clk2_a_pin, + [RPM_SMD_DIV_CLK1] = &msm8994_div_clk1, + [RPM_SMD_DIV_A_CLK1] = &msm8994_div_clk1_a, + [RPM_SMD_DIV_CLK2] = &msm8994_div_clk2, + [RPM_SMD_DIV_A_CLK2] = &msm8994_div_clk2_a, + [RPM_SMD_DIV_CLK3] = &msm8994_div_clk3, + [RPM_SMD_DIV_A_CLK3] = &msm8994_div_clk3_a, + [RPM_SMD_IPA_CLK] = &msm8994_ipa_clk, + [RPM_SMD_IPA_A_CLK] = &msm8994_ipa_a_clk, + [RPM_SMD_LN_BB_CLK] = &msm8994_ln_bb_clk, + [RPM_SMD_LN_BB_A_CLK] = &msm8994_ln_bb_a_clk, + [RPM_SMD_MMSSNOC_AHB_CLK] = &msm8994_mmssnoc_ahb_clk, + [RPM_SMD_MMSSNOC_AHB_A_CLK] = &msm8994_mmssnoc_ahb_a_clk, + [RPM_SMD_QDSS_CLK] = &msm8994_qdss_clk, + [RPM_SMD_QDSS_A_CLK] = &msm8994_qdss_a_clk, + [RPM_SMD_RF_CLK1] = &msm8994_rf_clk1, + [RPM_SMD_RF_CLK1_A] = &msm8994_rf_clk1_a, + [RPM_SMD_RF_CLK2] = &msm8994_rf_clk2, + [RPM_SMD_RF_CLK2_A] = &msm8994_rf_clk2_a, + [RPM_SMD_RF_CLK1_PIN] = &msm8994_rf_clk1_pin, + [RPM_SMD_RF_CLK1_A_PIN] = &msm8994_rf_clk1_a_pin, + [RPM_SMD_RF_CLK2_PIN] = &msm8994_rf_clk2_pin, + [RPM_SMD_RF_CLK2_A_PIN] = &msm8994_rf_clk2_a_pin, + [RPM_SMD_CE1_CLK] = &msm8994_ce1_clk, + [RPM_SMD_CE1_A_CLK] = &msm8994_ce1_a_clk, + [RPM_SMD_CE2_CLK] = &msm8994_ce2_clk, + [RPM_SMD_CE2_A_CLK] = &msm8994_ce2_a_clk, + [RPM_SMD_CE3_CLK] = &msm8994_ce3_clk, + [RPM_SMD_CE3_A_CLK] = &msm8994_ce3_a_clk, +}; + +static const struct rpm_smd_clk_desc rpm_clk_msm8994 = { + .clks = msm8994_clks, + .num_clks = ARRAY_SIZE(msm8994_clks), +}; + /* msm8996 */ DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0); DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1); @@ -895,6 +1064,8 @@ static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-msm8936", .data = &rpm_clk_msm8936 }, { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 }, { .compatible = "qcom,rpmcc-msm8976", .data = &rpm_clk_msm8976 }, + { .compatible = "qcom,rpmcc-msm8992", .data = &rpm_clk_msm8992 }, + { .compatible = "qcom,rpmcc-msm8994", .data = &rpm_clk_msm8994 }, { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 }, { .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 }, { .compatible = "qcom,rpmcc-qcs404", .data = &rpm_clk_qcs404 }, diff --git a/include/dt-bindings/clock/qcom,rpmcc.h b/include/dt-bindings/clock/qcom,rpmcc.h index e98ed70d91b3..8aaba7cd9589 100644 --- a/include/dt-bindings/clock/qcom,rpmcc.h +++ b/include/dt-bindings/clock/qcom,rpmcc.h @@ -145,5 +145,9 @@ #define RPM_SMD_LN_BB_CLK2_A_PIN 99 #define RPM_SMD_SYSMMNOC_CLK 100 #define RPM_SMD_SYSMMNOC_A_CLK 101 +#define RPM_SMD_CE2_CLK 102 +#define RPM_SMD_CE2_A_CLK 103 +#define RPM_SMD_CE3_CLK 104 +#define RPM_SMD_CE3_A_CLK 105 #endif From 6c4411f14d1afa8ead90cd4cf18a308c43ac6908 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Jul 2020 17:28:30 -0700 Subject: [PATCH 61/94] clk: : drop a duplicated word Drop the repeated word "not" in a comment. Signed-off-by: Randy Dunlap Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Link: https://lore.kernel.org/r/20200719002830.20319-1-rdunlap@infradead.org Signed-off-by: Stephen Boyd --- include/linux/clk-provider.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index bd1ee9039558..6f815be99b77 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -189,7 +189,7 @@ struct clk_duty { * and >= numerator) Return 0 on success, otherwise -EERROR. * * @init: Perform platform-specific initialization magic. - * This is not not used by any of the basic clock types. + * This is not used by any of the basic clock types. * This callback exist for HW which needs to perform some * initialisation magic for CCF to get an accurate view of the * clock. It may also be used dynamic resource allocation is From 044f507dc0a3070985592d84707a9d69746d84c6 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Thu, 16 Jul 2020 11:02:50 +0530 Subject: [PATCH 62/94] clk: qcom: ipq8074: Add correct index for PCIe clocks The PCIe clocks GCC_PCIE0_AXI_S_BRIDGE_CLK, GCC_PCIE0_RCHNG_CLK_SRC, GCC_PCIE0_RCHNG_CLK are wrongly added to the gcc reset group. Move them to the gcc clock group. Reported-by: kernel test robot Signed-off-by: Sivaprakash Murugesan Link: https://lore.kernel.org/r/1594877570-9280-1-git-send-email-sivaprak@codeaurora.org Fixes: e7fb524cfcca ("dt-bindings: clock: qcom: ipq8074: Add missing bindings for PCIe") Signed-off-by: Stephen Boyd --- include/dt-bindings/clock/qcom,gcc-ipq8074.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/dt-bindings/clock/qcom,gcc-ipq8074.h b/include/dt-bindings/clock/qcom,gcc-ipq8074.h index e3e018565add..8e2bec1c91bf 100644 --- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h +++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h @@ -230,6 +230,9 @@ #define GCC_GP1_CLK 221 #define GCC_GP2_CLK 222 #define GCC_GP3_CLK 223 +#define GCC_PCIE0_AXI_S_BRIDGE_CLK 224 +#define GCC_PCIE0_RCHNG_CLK_SRC 225 +#define GCC_PCIE0_RCHNG_CLK 226 #define GCC_BLSP1_BCR 0 #define GCC_BLSP1_QUP1_BCR 1 @@ -363,8 +366,5 @@ #define GCC_PCIE1_AHB_ARES 129 #define GCC_PCIE1_AXI_MASTER_STICKY_ARES 130 #define GCC_PCIE0_AXI_SLAVE_STICKY_ARES 131 -#define GCC_PCIE0_AXI_S_BRIDGE_CLK 132 -#define GCC_PCIE0_RCHNG_CLK_SRC 133 -#define GCC_PCIE0_RCHNG_CLK 134 #endif From 8607fa169178a4a38f232612e036def96b5ecd1d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 14 Jul 2020 22:21:55 +0800 Subject: [PATCH 63/94] clk: qcom: msm8996: Make symbol 'cpu_msm8996_clks' static The sparse tool complains as follows: drivers/clk/qcom/clk-cpu-8996.c:341:19: warning: symbol 'cpu_msm8996_clks' was not declared. Should it be static? This variable is not used outside of clk-cpu-8996.c, so this commit marks it static. Fixes: 03e342dc45c9 ("clk: qcom: Add CPU clock driver for msm8996") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20200714142155.35085-1-weiyongjun1@huawei.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-cpu-8996.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/clk-cpu-8996.c b/drivers/clk/qcom/clk-cpu-8996.c index 77a2d2806e58..4a4fde8dd12d 100644 --- a/drivers/clk/qcom/clk-cpu-8996.c +++ b/drivers/clk/qcom/clk-cpu-8996.c @@ -338,7 +338,7 @@ static const struct regmap_config cpu_msm8996_regmap_config = { .val_format_endian = REGMAP_ENDIAN_LITTLE, }; -struct clk_regmap *cpu_msm8996_clks[] = { +static struct clk_regmap *cpu_msm8996_clks[] = { &perfcl_pll.clkr, &pwrcl_pll.clkr, &perfcl_alt_pll.clkr, From 5ce728fa78ddbef667fd757ad008d33e39e7312a Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Thu, 16 Jul 2020 04:28:10 +0200 Subject: [PATCH 64/94] ipq806x: gcc: add support for child probe Add support for child probing needed for tsens driver that share the same regs of gcc for this platform. Signed-off-by: Ansuel Smith Reviewed-by: Amit Kucheria Link: https://lore.kernel.org/r/20200716022817.30439-2-ansuelsmth@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-ipq806x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c index a8456e09c44d..d6b7adb4be38 100644 --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c @@ -3089,7 +3089,7 @@ static int gcc_ipq806x_probe(struct platform_device *pdev) regmap_write(regmap, 0x3cf8, 8); regmap_write(regmap, 0x3d18, 8); - return 0; + return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); } static struct platform_driver gcc_ipq806x_driver = { From 9c3df2b1993da9ab1110702d7b2815d5cd8c02f3 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 15 Jul 2020 12:24:10 +0530 Subject: [PATCH 65/94] clk: qcom: gcc: Make disp gpll0 branch aon for sc7180/sdm845 The display gpll0 branch clock inside GCC needs to always be enabled. Otherwise the AHB clk (disp_cc_mdss_ahb_clk_src) for the display clk controller (dispcc) will stop clocking while sourcing from gpll0 when this branch inside GCC is turned off during unused clk disabling. We can never turn this branch off because the AHB clk for the display subsystem is needed to read/write any registers inside the display subsystem including clk related ones. This makes this branch a really easy way to turn off AHB access to the display subsystem and cause all sorts of mayhem. Let's just make the clk ops keep the clk enabled forever and ignore any attempts to disable this clk so that dispcc accesses keep working. Signed-off-by: Taniya Das Reported-by: Evan Green Link: https://lore.kernel.org/r/1594796050-14511-1-git-send-email-tdas@codeaurora.org Fixes: 17269568f726 ("clk: qcom: Add Global Clock controller (GCC) driver for SC7180") Fixes: 06391eddb60a ("clk: qcom: Add Global Clock controller (GCC) driver for SDM845") [sboyd@kernel.org: Fill out commit text more] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sc7180.c | 2 +- drivers/clk/qcom/gcc-sdm845.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/gcc-sc7180.c b/drivers/clk/qcom/gcc-sc7180.c index ca4383e3a02a..538677befb86 100644 --- a/drivers/clk/qcom/gcc-sc7180.c +++ b/drivers/clk/qcom/gcc-sc7180.c @@ -1061,7 +1061,7 @@ static struct clk_branch gcc_disp_gpll0_clk_src = { .hw = &gpll0.clkr.hw, }, .num_parents = 1, - .ops = &clk_branch2_ops, + .ops = &clk_branch2_aon_ops, }, }, }; diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c index f6ce888098be..90f7febaf528 100644 --- a/drivers/clk/qcom/gcc-sdm845.c +++ b/drivers/clk/qcom/gcc-sdm845.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. */ #include @@ -1344,7 +1344,7 @@ static struct clk_branch gcc_disp_gpll0_clk_src = { "gpll0", }, .num_parents = 1, - .ops = &clk_branch2_ops, + .ops = &clk_branch2_aon_ops, }, }, }; From ba937f51090d04bde3c2b9bf1213dabac706461d Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Tue, 21 Jul 2020 12:18:34 +0200 Subject: [PATCH 66/94] dt-bindings: clock: Fix qcom,msm8996-apcc yaml syntax Fix errors reported by dt_binding_check. - Fix literal block scalar for dts example - Fix schema identifier URI Signed-off-by: Loic Poulain Link: https://lore.kernel.org/r/1595326714-20485-1-git-send-email-loic.poulain@linaro.org Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,msm8996-apcc.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml b/Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml index d673edeed98d..a20cb10636dd 100644 --- a/Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,msm8996-apcc.yaml @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only %YAML 1.2 --- -$id: http://devicetree.org/schemas/clock/qcom,kryocc.yaml# +$id: http://devicetree.org/schemas/clock/qcom,msm8996-apcc.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Qualcomm clock controller for MSM8996 CPUs @@ -46,11 +46,9 @@ required: additionalProperties: false examples: - # Example for msm8996 - | kryocc: clock-controller@6400000 { compatible = "qcom,msm8996-apcc"; reg = <0x6400000 0x90000>; #clock-cells = <1>; - }; -... + }; From 8200597fb16651e5b2280b694dd86352b738657b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 25 Jun 2020 14:27:36 +0100 Subject: [PATCH 67/94] clk: vc5: fix use of memory after it has been kfree'd There are a several places where printing an error message of init.name occurs after init.name has been kfree'd. Also the failure message is duplicated each time in the code. Fix this by adding a registration error failure path for these cases, moving the duplicated error messages to one common point and kfree'ing init.name only after it has been used. Changes also shrink the object code size by 171 bytes (x86-64, gcc 9.3): Before: text data bss dec hex filename 21057 3960 64 25081 61f9 drivers/clk/clk-versaclock5.o After: text data bss dec hex filename 20886 3960 64 24910 614e drivers/clk/clk-versaclock5.o Addresses-Coverity: ("Use after free") Fixes: f491276a5168 ("clk: vc5: Allow Versaclock driver to support multiple instances") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20200625132736.88832-1-colin.king@canonical.com Reviewed-by: Luca Ceresoli [sboyd@kernel.org: Drop stray newline] Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 50 +++++++++++++---------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 9a5fb3834b9a..d6fa15b6f37f 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -882,11 +882,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) init.parent_names = parent_names; vc5->clk_mux.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_mux); + if (ret) + goto err_clk_register; kfree(init.name); /* clock framework made a copy of the name */ - if (ret) { - dev_err(&client->dev, "unable to register %s\n", init.name); - goto err_clk; - } if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) { /* Register frequency doubler */ @@ -900,12 +898,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) init.num_parents = 1; vc5->clk_mul.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul); + if (ret) + goto err_clk_register; kfree(init.name); /* clock framework made a copy of the name */ - if (ret) { - dev_err(&client->dev, "unable to register %s\n", - init.name); - goto err_clk; - } } /* Register PFD */ @@ -921,11 +916,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) init.num_parents = 1; vc5->clk_pfd.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); + if (ret) + goto err_clk_register; kfree(init.name); /* clock framework made a copy of the name */ - if (ret) { - dev_err(&client->dev, "unable to register %s\n", init.name); - goto err_clk; - } /* Register PLL */ memset(&init, 0, sizeof(init)); @@ -939,11 +932,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) vc5->clk_pll.vc5 = vc5; vc5->clk_pll.hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_pll.hw); + if (ret) + goto err_clk_register; kfree(init.name); /* clock framework made a copy of the name */ - if (ret) { - dev_err(&client->dev, "unable to register %s\n", init.name); - goto err_clk; - } /* Register FODs */ for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) { @@ -960,12 +951,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) vc5->clk_fod[n].vc5 = vc5; vc5->clk_fod[n].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_fod[n].hw); + if (ret) + goto err_clk_register; kfree(init.name); /* clock framework made a copy of the name */ - if (ret) { - dev_err(&client->dev, "unable to register %s\n", - init.name); - goto err_clk; - } } /* Register MUX-connected OUT0_I2C_SELB output */ @@ -981,11 +969,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) vc5->clk_out[0].vc5 = vc5; vc5->clk_out[0].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[0].hw); - kfree(init.name); /* clock framework made a copy of the name */ - if (ret) { - dev_err(&client->dev, "unable to register %s\n", init.name); - goto err_clk; - } + if (ret) + goto err_clk_register; + kfree(init.name); /* clock framework made a copy of the name */ /* Register FOD-connected OUTx outputs */ for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) { @@ -1008,12 +994,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) vc5->clk_out[n].vc5 = vc5; vc5->clk_out[n].hw.init = &init; ret = devm_clk_hw_register(&client->dev, &vc5->clk_out[n].hw); + if (ret) + goto err_clk_register; kfree(init.name); /* clock framework made a copy of the name */ - if (ret) { - dev_err(&client->dev, "unable to register %s\n", - init.name); - goto err_clk; - } /* Fetch Clock Output configuration from DT (if specified) */ ret = vc5_get_output_config(client, &vc5->clk_out[n]); @@ -1029,6 +1012,9 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) return 0; +err_clk_register: + dev_err(&client->dev, "unable to register %s\n", init.name); + kfree(init.name); /* clock framework made a copy of the name */ err_clk: if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL) clk_unregister_fixed_rate(vc5->pin_xin); From faf29338f3cb6ebcbff7297471b0fa56639a98bc Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Thu, 16 Jul 2020 07:26:20 -0500 Subject: [PATCH 68/94] clk: vc5: Add memory check to prevent oops When getting the names of the child nodes, kasprintf is used to allocate memory which is used to create the string for the node name. Unfortunately, there is no memory check to determine if this allocation fails, it may cause an error when trying to get child node name. This patch will check if the memory allocation fails, and returns and -ENOMEM error instead of blindly moving on. Fixes: 260249f929e8 ("clk: vc5: Enable addition output configurations of the Versaclock") Suggested-by: Dan Carpenter Signed-off-by: Adam Ford Reviewed-by: Luca Ceresoli Link: https://lore.kernel.org/r/20200716122620.4538-1-aford173@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index d6fa15b6f37f..32f0aa64f062 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -789,10 +789,13 @@ static int vc5_get_output_config(struct i2c_client *client, int ret = 0; child_name = kasprintf(GFP_KERNEL, "OUT%d", clk_out->num + 1); + if (!child_name) + return -ENOMEM; + np_output = of_get_child_by_name(client->dev.of_node, child_name); kfree(child_name); if (!np_output) - goto output_done; + return 0; ret = vc5_update_mode(np_output, clk_out); if (ret) @@ -813,7 +816,6 @@ output_error: of_node_put(np_output); -output_done: return ret; } @@ -828,7 +830,7 @@ static int vc5_probe(struct i2c_client *client, const struct i2c_device_id *id) int ret; vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL); - if (vc5 == NULL) + if (!vc5) return -ENOMEM; i2c_set_clientdata(client, vc5); From 2a08a9232ba2e6103843870e68edae8e381eb02a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 26 Jun 2020 13:54:33 +0200 Subject: [PATCH 69/94] dt-bindings: arm: bcm: Add a select to the RPI Firmware binding The RaspberryPi firmware binding uses two compatible, include simple-bus. The select statement generated by default will thus select any node that has simple-bus, not all of them being the raspberrypi firmware node. This results in warnings being wrongfully reported. Let's add a custom select statement to fix that. Fixes: d4c708c032df ("dt-bindings: arm: bcm: Convert BCM2835 firmware binding to YAML") Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20200626115433.125735-1-maxime@cerno.tech Acked-by: Florian Fainelli Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml index b48ed875eb8e..17e4f20c8d39 100644 --- a/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml +++ b/Documentation/devicetree/bindings/arm/bcm/raspberrypi,bcm2835-firmware.yaml @@ -10,6 +10,15 @@ maintainers: - Eric Anholt - Stefan Wahren +select: + properties: + compatible: + contains: + const: raspberrypi,bcm2835-firmware + + required: + - compatible + properties: compatible: items: From 3ba72c35cf1c79cb95eebd7fa20f416c4fa952eb Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 23 Jul 2020 09:41:10 +0200 Subject: [PATCH 70/94] dt-bindings: clk: versaclock5: fix 'idt' prefix typos 'idt' is misspelled 'itd' in a few places, fix it. Fixes: 34662f6e3084 ("dt: Add additional option bindings for IDT VersaClock") Signed-off-by: Luca Ceresoli Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20200723074112.3159-2-luca@lucaceresoli.net Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/idt,versaclock5.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt b/Documentation/devicetree/bindings/clock/idt,versaclock5.txt index 6165b6ddb1a9..9656d4cf221c 100644 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.txt @@ -35,7 +35,7 @@ For all output ports, a corresponding, optional child node named OUT1, OUT2, etc. can represent a each output, and the node can be used to specify the following: -- itd,mode: can be one of the following: +- idt,mode: can be one of the following: - VC5_LVPECL - VC5_CMOS - VC5_HCSL33 @@ -106,7 +106,7 @@ i2c-master-node { clock-names = "xin"; OUT1 { - itd,mode = ; + idt,mode = ; idt,voltage-microvolts = <1800000>; idt,slew-percent = <80>; }; From db136ac978ffbcc9a07b69906d7f6d2c49e033c0 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 23 Jul 2020 09:41:11 +0200 Subject: [PATCH 71/94] MAINTAINERS: take over IDT VersaClock 5 clock driver Marek has been the primary developer of this driver (thanks!). Now as he is not working on it anymore he suggested I take over maintainership. Cc: Marek Vasut Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20200723074112.3159-3-luca@lucaceresoli.net Signed-off-by: Stephen Boyd --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 68f21d46614c..5aa16c245c63 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8324,7 +8324,7 @@ W: https://github.com/o2genum/ideapad-slidebar F: drivers/input/misc/ideapad_slidebar.c IDT VersaClock 5 CLOCK DRIVER -M: Marek Vasut +M: Luca Ceresoli S: Maintained F: drivers/clk/clk-versaclock5.c From 45c940184b501fc65592432a269b7a34cf2237b6 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 23 Jul 2020 09:41:12 +0200 Subject: [PATCH 72/94] dt-bindings: clk: versaclock5: convert to yaml Convert to yaml the VersaClock bindings document. The mapping between clock specifier and physical pins cannot be described formally in yaml schema, then keep it verbatim in the description field. Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20200723074112.3159-4-luca@lucaceresoli.net Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../bindings/clock/idt,versaclock5.txt | 125 -------------- .../bindings/clock/idt,versaclock5.yaml | 154 ++++++++++++++++++ MAINTAINERS | 1 + 3 files changed, 155 insertions(+), 125 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/idt,versaclock5.txt create mode 100644 Documentation/devicetree/bindings/clock/idt,versaclock5.yaml diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt b/Documentation/devicetree/bindings/clock/idt,versaclock5.txt deleted file mode 100644 index 9656d4cf221c..000000000000 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.txt +++ /dev/null @@ -1,125 +0,0 @@ -Binding for IDT VersaClock 5,6 programmable i2c clock generators. - -The IDT VersaClock 5 and VersaClock 6 are programmable i2c clock -generators providing from 3 to 12 output clocks. - -==I2C device node== - -Required properties: -- compatible: shall be one of - "idt,5p49v5923" - "idt,5p49v5925" - "idt,5p49v5933" - "idt,5p49v5935" - "idt,5p49v6901" - "idt,5p49v6965" -- reg: i2c device address, shall be 0x68 or 0x6a. -- #clock-cells: from common clock binding; shall be set to 1. -- clocks: from common clock binding; list of parent clock handles, - - 5p49v5923 and - 5p49v5925 and - 5p49v6901: (required) either or both of XTAL or CLKIN - reference clock. - - 5p49v5933 and - - 5p49v5935: (optional) property not present (internal - Xtal used) or CLKIN reference - clock. -- clock-names: from common clock binding; clock input names, can be - - 5p49v5923 and - 5p49v5925 and - 5p49v6901: (required) either or both of "xin", "clkin". - - 5p49v5933 and - - 5p49v5935: (optional) property not present or "clkin". - -For all output ports, a corresponding, optional child node named OUT1, -OUT2, etc. can represent a each output, and the node can be used to -specify the following: - -- idt,mode: can be one of the following: - - VC5_LVPECL - - VC5_CMOS - - VC5_HCSL33 - - VC5_LVDS - - VC5_CMOS2 - - VC5_CMOSD - - VC5_HCSL25 - -- idt,voltage-microvolts: can be one of the following - - 1800000 - - 2500000 - - 3300000 -- idt,slew-percent: Percent of normal, can be one of - - 80 - - 85 - - 90 - - 100 - -==Mapping between clock specifier and physical pins== - -When referencing the provided clock in the DT using phandle and -clock specifier, the following mapping applies: - -5P49V5923: - 0 -- OUT0_SEL_I2CB - 1 -- OUT1 - 2 -- OUT2 - -5P49V5933: - 0 -- OUT0_SEL_I2CB - 1 -- OUT1 - 2 -- OUT4 - -5P49V5925 and -5P49V5935: - 0 -- OUT0_SEL_I2CB - 1 -- OUT1 - 2 -- OUT2 - 3 -- OUT3 - 4 -- OUT4 - -5P49V6901: - 0 -- OUT0_SEL_I2CB - 1 -- OUT1 - 2 -- OUT2 - 3 -- OUT3 - 4 -- OUT4 - -==Example== - -/* 25MHz reference crystal */ -ref25: ref25m { - compatible = "fixed-clock"; - #clock-cells = <0>; - clock-frequency = <25000000>; -}; - -i2c-master-node { - - /* IDT 5P49V5923 i2c clock generator */ - vc5: clock-generator@6a { - compatible = "idt,5p49v5923"; - reg = <0x6a>; - #clock-cells = <1>; - - /* Connect XIN input to 25MHz reference */ - clocks = <&ref25m>; - clock-names = "xin"; - - OUT1 { - idt,mode = ; - idt,voltage-microvolts = <1800000>; - idt,slew-percent = <80>; - }; - OUT2 { - ... - }; - ... - }; -}; - -/* Consumer referencing the 5P49V5923 pin OUT1 */ -consumer { - ... - clocks = <&vc5 1>; - ... -} diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml new file mode 100644 index 000000000000..3d4e1685cc55 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml @@ -0,0 +1,154 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/idt,versaclock5.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Binding for IDT VersaClock 5 and 6 programmable I2C clock generators + +description: | + The IDT VersaClock 5 and VersaClock 6 are programmable I2C + clock generators providing from 3 to 12 output clocks. + + When referencing the provided clock in the DT using phandle and clock + specifier, the following mapping applies: + + - 5P49V5923: + 0 -- OUT0_SEL_I2CB + 1 -- OUT1 + 2 -- OUT2 + + - 5P49V5933: + 0 -- OUT0_SEL_I2CB + 1 -- OUT1 + 2 -- OUT4 + + - other parts: + 0 -- OUT0_SEL_I2CB + 1 -- OUT1 + 2 -- OUT2 + 3 -- OUT3 + 4 -- OUT4 + +maintainers: + - Luca Ceresoli + +properties: + compatible: + enum: + - idt,5p49v5923 + - idt,5p49v5925 + - idt,5p49v5933 + - idt,5p49v5935 + - idt,5p49v6901 + - idt,5p49v6965 + + reg: + description: I2C device address + enum: [ 0x68, 0x6a ] + + '#clock-cells': + const: 1 + +patternProperties: + "^OUT[1-4]$": + type: object + description: + Description of one of the outputs (OUT1..OUT4). See "Clock1 Output + Configuration" in the Versaclock 5/6/6E Family Register Description + and Programming Guide. + properties: + idt,mode: + description: + The output drive mode. Values defined in dt-bindings/clk/versaclock.h + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 6 + idt,voltage-microvolt: + description: The output drive voltage. + enum: [ 1800000, 2500000, 3300000 ] + idt,slew-percent: + description: The Slew rate control for CMOS single-ended. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 80, 85, 90, 100 ] + +required: + - compatible + - reg + - '#clock-cells' + +allOf: + - if: + properties: + compatible: + enum: + - idt,5p49v5933 + - idt,5p49v5935 + then: + # Devices with builtin crystal + optional external input + properties: + clock-names: + const: clkin + clocks: + maxItems: 1 + else: + # Devices without builtin crystal + properties: + clock-names: + minItems: 1 + maxItems: 2 + items: + enum: [ xin, clkin ] + clocks: + minItems: 1 + maxItems: 2 + required: + - clock-names + - clocks + +examples: + - | + #include + + /* 25MHz reference crystal */ + ref25: ref25m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + i2c@0 { + reg = <0x0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + + /* IDT 5P49V5923 I2C clock generator */ + vc5: clock-generator@6a { + compatible = "idt,5p49v5923"; + reg = <0x6a>; + #clock-cells = <1>; + + /* Connect XIN input to 25MHz reference */ + clocks = <&ref25m>; + clock-names = "xin"; + + OUT1 { + idt,drive-mode = ; + idt,voltage-microvolts = <1800000>; + idt,slew-percent = <80>; + }; + + OUT4 { + idt,drive-mode = ; + }; + }; + }; + + /* Consumer referencing the 5P49V5923 pin OUT1 */ + consumer { + /* ... */ + clocks = <&vc5 1>; + /* ... */ + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index 5aa16c245c63..09d6efd1d0d0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8326,6 +8326,7 @@ F: drivers/input/misc/ideapad_slidebar.c IDT VersaClock 5 CLOCK DRIVER M: Luca Ceresoli S: Maintained +F: Documentation/devicetree/bindings/clock/idt,versaclock5.yaml F: drivers/clk/clk-versaclock5.c IEEE 802.15.4 SUBSYSTEM From 3bca66b08ec833c4506e97371f2c74e7de00792a Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Thu, 23 Jul 2020 09:26:03 +0200 Subject: [PATCH 73/94] clk: vc5: use a dedicated struct to describe the output drivers Reusing the generic struct vc5_hw_data for all blocks is handy. However it implies we allocate space the div_int and div_frc fields even for the output drivers where they are unused, and the clk_output_cfg0 and clk_output_cfg0_mask fields for all components even though they are used only for the output drivers. Use a dedicated struct for the output drivers so that each block uses exactly the fields it needs, not more. Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20200723072603.1795-1-luca@lucaceresoli.net Signed-off-by: Stephen Boyd --- drivers/clk/clk-versaclock5.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 32f0aa64f062..c90460e7ef21 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -167,6 +167,12 @@ struct vc5_hw_data { u32 div_int; u32 div_frc; unsigned int num; +}; + +struct vc5_out_data { + struct clk_hw hw; + struct vc5_driver_data *vc5; + unsigned int num; unsigned int clk_output_cfg0; unsigned int clk_output_cfg0_mask; }; @@ -184,7 +190,7 @@ struct vc5_driver_data { struct clk_hw clk_pfd; struct vc5_hw_data clk_pll; struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM]; - struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; + struct vc5_out_data clk_out[VC5_MAX_CLK_OUT_NUM]; }; /* @@ -567,7 +573,7 @@ static const struct clk_ops vc5_fod_ops = { static int vc5_clk_out_prepare(struct clk_hw *hw) { - struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); + struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw); struct vc5_driver_data *vc5 = hwdata->vc5; const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM | VC5_OUT_DIV_CONTROL_SEL_EXT | @@ -609,7 +615,7 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) static void vc5_clk_out_unprepare(struct clk_hw *hw) { - struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); + struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw); struct vc5_driver_data *vc5 = hwdata->vc5; /* Disable the clock buffer */ @@ -619,7 +625,7 @@ static void vc5_clk_out_unprepare(struct clk_hw *hw) static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw) { - struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); + struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw); struct vc5_driver_data *vc5 = hwdata->vc5; const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM | VC5_OUT_DIV_CONTROL_SEL_EXT | @@ -649,7 +655,7 @@ static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw) static int vc5_clk_out_set_parent(struct clk_hw *hw, u8 index) { - struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); + struct vc5_out_data *hwdata = container_of(hw, struct vc5_out_data, hw); struct vc5_driver_data *vc5 = hwdata->vc5; const u8 mask = VC5_OUT_DIV_CONTROL_RESET | VC5_OUT_DIV_CONTROL_SELB_NORM | @@ -704,7 +710,7 @@ static int vc5_map_index_to_output(const enum vc5_model model, } static int vc5_update_mode(struct device_node *np_output, - struct vc5_hw_data *clk_out) + struct vc5_out_data *clk_out) { u32 value; @@ -729,7 +735,7 @@ static int vc5_update_mode(struct device_node *np_output, } static int vc5_update_power(struct device_node *np_output, - struct vc5_hw_data *clk_out) + struct vc5_out_data *clk_out) { u32 value; @@ -754,7 +760,7 @@ static int vc5_update_power(struct device_node *np_output, } static int vc5_update_slew(struct device_node *np_output, - struct vc5_hw_data *clk_out) + struct vc5_out_data *clk_out) { u32 value; @@ -782,7 +788,7 @@ static int vc5_update_slew(struct device_node *np_output, } static int vc5_get_output_config(struct i2c_client *client, - struct vc5_hw_data *clk_out) + struct vc5_out_data *clk_out) { struct device_node *np_output; char *child_name; From 667f39b59b494d96ae70f4217637db2ebbee3df0 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:32 -0400 Subject: [PATCH 74/94] clk: qcom: gcc: fix sm8150 GPU and NPU clocks Fix the parents and set BRANCH_HALT_SKIP. From the downstream driver it should be a 500us delay and not skip, however this matches what was done for other clocks that had 500us delay in downstream. Fixes: f73a4230d5bb ("clk: qcom: gcc: Add GPU and NPU clocks for SM8150") Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-2-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sm8150.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c index 72524cf11048..55e9d6d75a0c 100644 --- a/drivers/clk/qcom/gcc-sm8150.c +++ b/drivers/clk/qcom/gcc-sm8150.c @@ -1617,6 +1617,7 @@ static struct clk_branch gcc_gpu_cfg_ahb_clk = { }; static struct clk_branch gcc_gpu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x52004, .enable_mask = BIT(15), @@ -1632,13 +1633,14 @@ static struct clk_branch gcc_gpu_gpll0_clk_src = { }; static struct clk_branch gcc_gpu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x52004, .enable_mask = BIT(16), .hw.init = &(struct clk_init_data){ .name = "gcc_gpu_gpll0_div_clk_src", .parent_hws = (const struct clk_hw *[]){ - &gcc_gpu_gpll0_clk_src.clkr.hw }, + &gpll0_out_even.clkr.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, @@ -1729,6 +1731,7 @@ static struct clk_branch gcc_npu_cfg_ahb_clk = { }; static struct clk_branch gcc_npu_gpll0_clk_src = { + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x52004, .enable_mask = BIT(18), @@ -1744,13 +1747,14 @@ static struct clk_branch gcc_npu_gpll0_clk_src = { }; static struct clk_branch gcc_npu_gpll0_div_clk_src = { + .halt_check = BRANCH_HALT_SKIP, .clkr = { .enable_reg = 0x52004, .enable_mask = BIT(19), .hw.init = &(struct clk_init_data){ .name = "gcc_npu_gpll0_div_clk_src", .parent_hws = (const struct clk_hw *[]){ - &gcc_npu_gpll0_clk_src.clkr.hw }, + &gpll0_out_even.clkr.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, .ops = &clk_branch2_ops, From c8b9002f44e4a1d2771b2f59f6de900864b1f9d7 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:33 -0400 Subject: [PATCH 75/94] clk: qcom: clk-alpha-pll: remove unused/incorrect PLL_CAL_VAL 0x44 isn't a register offset, it is the value that goes into CAL_L_VAL. Fixes: 548a909597d5 ("clk: qcom: clk-alpha-pll: Add support for Trion PLLs") Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-3-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 9b2dfa08acb2..1325139173c9 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -56,7 +56,6 @@ #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) -#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL]) const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [CLK_ALPHA_PLL_TYPE_DEFAULT] = { @@ -115,7 +114,6 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_STATUS] = 0x30, [PLL_OFF_OPMODE] = 0x38, [PLL_OFF_ALPHA_VAL] = 0x40, - [PLL_OFF_CAL_VAL] = 0x44, }, [CLK_ALPHA_PLL_TYPE_LUCID] = { [PLL_OFF_L_VAL] = 0x04, From 0b01489475c655f8ccce8fa13cc4088954ac5503 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:34 -0400 Subject: [PATCH 76/94] clk: qcom: clk-alpha-pll: same regs and ops for trion and lucid Fixed ops were already identical, this adds support for non-fixed ops by sharing between trion and lucid. This also changes the names for trion ops to be consistent with the rest. Note LUCID_PCAL_DONE is renamed to TRION_PCAL_DONE because it is wrong for lucid, LUCID_PCAL_DONE should be BIT(27). Next patch will address this. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-4-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 58 ++++++++++---------------------- drivers/clk/qcom/clk-alpha-pll.h | 17 ++++++---- drivers/clk/qcom/gcc-sm8150.c | 8 ++--- 3 files changed, 32 insertions(+), 51 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 1325139173c9..be7ffeae21b1 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -101,21 +101,6 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_FRAC] = 0x38, }, [CLK_ALPHA_PLL_TYPE_TRION] = { - [PLL_OFF_L_VAL] = 0x04, - [PLL_OFF_CAL_L_VAL] = 0x08, - [PLL_OFF_USER_CTL] = 0x0c, - [PLL_OFF_USER_CTL_U] = 0x10, - [PLL_OFF_USER_CTL_U1] = 0x14, - [PLL_OFF_CONFIG_CTL] = 0x18, - [PLL_OFF_CONFIG_CTL_U] = 0x1c, - [PLL_OFF_CONFIG_CTL_U1] = 0x20, - [PLL_OFF_TEST_CTL] = 0x24, - [PLL_OFF_TEST_CTL_U] = 0x28, - [PLL_OFF_STATUS] = 0x30, - [PLL_OFF_OPMODE] = 0x38, - [PLL_OFF_ALPHA_VAL] = 0x40, - }, - [CLK_ALPHA_PLL_TYPE_LUCID] = { [PLL_OFF_L_VAL] = 0x04, [PLL_OFF_CAL_L_VAL] = 0x08, [PLL_OFF_USER_CTL] = 0x0c, @@ -154,9 +139,9 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define PLL_OUT_MASK 0x7 #define PLL_RATE_MARGIN 500 -/* LUCID PLL specific settings and offsets */ -#define LUCID_PLL_CAL_VAL 0x44 -#define LUCID_PCAL_DONE BIT(26) +/* TRION PLL specific settings and offsets */ +#define TRION_PLL_CAL_VAL 0x44 +#define TRION_PCAL_DONE BIT(26) #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ @@ -910,14 +895,14 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = { }; EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops); -const struct clk_ops clk_trion_fixed_pll_ops = { +const struct clk_ops clk_alpha_pll_fixed_trion_ops = { .enable = clk_trion_pll_enable, .disable = clk_trion_pll_disable, .is_enabled = clk_trion_pll_is_enabled, .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, }; -EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops); +EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_trion_ops); static unsigned long clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) @@ -1337,12 +1322,12 @@ clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate, val << PLL_POST_DIV_SHIFT); } -const struct clk_ops clk_trion_pll_postdiv_ops = { +const struct clk_ops clk_alpha_pll_postdiv_trion_ops = { .recalc_rate = clk_trion_pll_postdiv_recalc_rate, .round_rate = clk_trion_pll_postdiv_round_rate, .set_rate = clk_trion_pll_postdiv_set_rate, }; -EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops); +EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_trion_ops); static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) @@ -1397,13 +1382,13 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_fabia_ops); * @regmap: register map * @config: configuration to apply for pll */ -void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, +void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config) { if (config->l) regmap_write(regmap, PLL_L_VAL(pll), config->l); - regmap_write(regmap, PLL_CAL_L_VAL(pll), LUCID_PLL_CAL_VAL); + regmap_write(regmap, PLL_CAL_L_VAL(pll), TRION_PLL_CAL_VAL); if (config->alpha) regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); @@ -1456,13 +1441,13 @@ void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, /* Place the PLL in STANDBY mode */ regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); } -EXPORT_SYMBOL_GPL(clk_lucid_pll_configure); +EXPORT_SYMBOL_GPL(clk_trion_pll_configure); /* - * The Lucid PLL requires a power-on self-calibration which happens when the + * The TRION PLL requires a power-on self-calibration which happens when the * PLL comes out of reset. Calibrate in case it is not completed. */ -static int alpha_pll_lucid_prepare(struct clk_hw *hw) +static int alpha_pll_trion_prepare(struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 regval; @@ -1470,7 +1455,7 @@ static int alpha_pll_lucid_prepare(struct clk_hw *hw) /* Return early if calibration is not needed. */ regmap_read(pll->clkr.regmap, PLL_STATUS(pll), ®val); - if (regval & LUCID_PCAL_DONE) + if (regval & TRION_PCAL_DONE) return 0; /* On/off to calibrate */ @@ -1481,7 +1466,7 @@ static int alpha_pll_lucid_prepare(struct clk_hw *hw) return ret; } -static int alpha_pll_lucid_set_rate(struct clk_hw *hw, unsigned long rate, +static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); @@ -1535,26 +1520,17 @@ static int alpha_pll_lucid_set_rate(struct clk_hw *hw, unsigned long rate, return 0; } -const struct clk_ops clk_alpha_pll_lucid_ops = { - .prepare = alpha_pll_lucid_prepare, +const struct clk_ops clk_alpha_pll_trion_ops = { + .prepare = alpha_pll_trion_prepare, .enable = clk_trion_pll_enable, .disable = clk_trion_pll_disable, .is_enabled = clk_trion_pll_is_enabled, .recalc_rate = clk_trion_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, - .set_rate = alpha_pll_lucid_set_rate, + .set_rate = alpha_pll_trion_set_rate, }; EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops); -const struct clk_ops clk_alpha_pll_fixed_lucid_ops = { - .enable = clk_trion_pll_enable, - .disable = clk_trion_pll_disable, - .is_enabled = clk_trion_pll_is_enabled, - .recalc_rate = clk_trion_pll_recalc_rate, - .round_rate = clk_alpha_pll_round_rate, -}; -EXPORT_SYMBOL_GPL(clk_alpha_pll_fixed_lucid_ops); - const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = { .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index 1ba82be93dd5..d283ba739057 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -14,7 +14,7 @@ enum { CLK_ALPHA_PLL_TYPE_BRAMMO, CLK_ALPHA_PLL_TYPE_FABIA, CLK_ALPHA_PLL_TYPE_TRION, - CLK_ALPHA_PLL_TYPE_LUCID, + CLK_ALPHA_PLL_TYPE_LUCID = CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_MAX, }; @@ -134,18 +134,23 @@ extern const struct clk_ops clk_alpha_pll_fabia_ops; extern const struct clk_ops clk_alpha_pll_fixed_fabia_ops; extern const struct clk_ops clk_alpha_pll_postdiv_fabia_ops; -extern const struct clk_ops clk_alpha_pll_lucid_ops; -extern const struct clk_ops clk_alpha_pll_fixed_lucid_ops; +extern const struct clk_ops clk_alpha_pll_trion_ops; +extern const struct clk_ops clk_alpha_pll_fixed_trion_ops; +extern const struct clk_ops clk_alpha_pll_postdiv_trion_ops; + +#define clk_alpha_pll_lucid_ops clk_alpha_pll_trion_ops +#define clk_alpha_pll_fixed_lucid_ops clk_alpha_pll_fixed_trion_ops extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops; void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); -void clk_lucid_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, +void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); +#define clk_lucid_pll_configure(pll, regmap, config) \ + clk_trion_pll_configure(pll, regmap, config) + -extern const struct clk_ops clk_trion_fixed_pll_ops; -extern const struct clk_ops clk_trion_pll_postdiv_ops; #endif diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c index 55e9d6d75a0c..d7778def37da 100644 --- a/drivers/clk/qcom/gcc-sm8150.c +++ b/drivers/clk/qcom/gcc-sm8150.c @@ -53,7 +53,7 @@ static struct clk_alpha_pll gpll0 = { .name = "bi_tcxo", }, .num_parents = 1, - .ops = &clk_trion_fixed_pll_ops, + .ops = &clk_alpha_pll_fixed_trion_ops, }, }, }; @@ -79,7 +79,7 @@ static struct clk_alpha_pll_postdiv gpll0_out_even = { .hw = &gpll0.clkr.hw, }, .num_parents = 1, - .ops = &clk_trion_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_trion_ops, }, }; @@ -98,7 +98,7 @@ static struct clk_alpha_pll gpll7 = { .name = "bi_tcxo", }, .num_parents = 1, - .ops = &clk_trion_fixed_pll_ops, + .ops = &clk_alpha_pll_fixed_trion_ops, }, }, }; @@ -118,7 +118,7 @@ static struct clk_alpha_pll gpll9 = { .name = "bi_tcxo", }, .num_parents = 1, - .ops = &clk_trion_fixed_pll_ops, + .ops = &clk_alpha_pll_fixed_trion_ops, }, }, }; From d28b503c248df8a3b4c73b504a043bdf7e2d5207 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:35 -0400 Subject: [PATCH 77/94] clk: qcom: clk-alpha-pll: use the right PCAL_DONE value for lucid pll Lucid PCAL_DONE is different from trion. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-5-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-alpha-pll.c | 28 ++++++++++++++++++++++++++-- drivers/clk/qcom/clk-alpha-pll.h | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index be7ffeae21b1..26139ef005e4 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -143,6 +143,9 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define TRION_PLL_CAL_VAL 0x44 #define TRION_PCAL_DONE BIT(26) +/* LUCID PLL specific settings and offsets */ +#define LUCID_PCAL_DONE BIT(27) + #define pll_alpha_width(p) \ ((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \ ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH) @@ -1447,7 +1450,7 @@ EXPORT_SYMBOL_GPL(clk_trion_pll_configure); * The TRION PLL requires a power-on self-calibration which happens when the * PLL comes out of reset. Calibrate in case it is not completed. */ -static int alpha_pll_trion_prepare(struct clk_hw *hw) +static int __alpha_pll_trion_prepare(struct clk_hw *hw, u32 pcal_done) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 regval; @@ -1455,7 +1458,7 @@ static int alpha_pll_trion_prepare(struct clk_hw *hw) /* Return early if calibration is not needed. */ regmap_read(pll->clkr.regmap, PLL_STATUS(pll), ®val); - if (regval & TRION_PCAL_DONE) + if (regval & pcal_done) return 0; /* On/off to calibrate */ @@ -1466,6 +1469,16 @@ static int alpha_pll_trion_prepare(struct clk_hw *hw) return ret; } +static int alpha_pll_trion_prepare(struct clk_hw *hw) +{ + return __alpha_pll_trion_prepare(hw, TRION_PCAL_DONE); +} + +static int alpha_pll_lucid_prepare(struct clk_hw *hw) +{ + return __alpha_pll_trion_prepare(hw, LUCID_PCAL_DONE); +} + static int alpha_pll_trion_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) { @@ -1529,6 +1542,17 @@ const struct clk_ops clk_alpha_pll_trion_ops = { .round_rate = clk_alpha_pll_round_rate, .set_rate = alpha_pll_trion_set_rate, }; +EXPORT_SYMBOL_GPL(clk_alpha_pll_trion_ops); + +const struct clk_ops clk_alpha_pll_lucid_ops = { + .prepare = alpha_pll_lucid_prepare, + .enable = clk_trion_pll_enable, + .disable = clk_trion_pll_disable, + .is_enabled = clk_trion_pll_is_enabled, + .recalc_rate = clk_trion_pll_recalc_rate, + .round_rate = clk_alpha_pll_round_rate, + .set_rate = alpha_pll_trion_set_rate, +}; EXPORT_SYMBOL_GPL(clk_alpha_pll_lucid_ops); const struct clk_ops clk_alpha_pll_postdiv_lucid_ops = { diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h index d283ba739057..d3201b87c0cd 100644 --- a/drivers/clk/qcom/clk-alpha-pll.h +++ b/drivers/clk/qcom/clk-alpha-pll.h @@ -138,7 +138,7 @@ extern const struct clk_ops clk_alpha_pll_trion_ops; extern const struct clk_ops clk_alpha_pll_fixed_trion_ops; extern const struct clk_ops clk_alpha_pll_postdiv_trion_ops; -#define clk_alpha_pll_lucid_ops clk_alpha_pll_trion_ops +extern const struct clk_ops clk_alpha_pll_lucid_ops; #define clk_alpha_pll_fixed_lucid_ops clk_alpha_pll_fixed_trion_ops extern const struct clk_ops clk_alpha_pll_postdiv_lucid_ops; From 3f6b25062587cd18ef01bf67ca67e601e6abde94 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:36 -0400 Subject: [PATCH 78/94] clk: qcom: gcc: remove unnecessary vco_table from SM8150 The fixed alpha pll ops only use it for clamping in round_rate, which is unnecessary. This is consistent with SM8250 GCC not using vco_table. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-6-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sm8150.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/clk/qcom/gcc-sm8150.c b/drivers/clk/qcom/gcc-sm8150.c index d7778def37da..8e9b5b3cceaf 100644 --- a/drivers/clk/qcom/gcc-sm8150.c +++ b/drivers/clk/qcom/gcc-sm8150.c @@ -34,14 +34,8 @@ enum { P_SLEEP_CLK, }; -static const struct pll_vco trion_vco[] = { - { 249600000, 2000000000, 0 }, -}; - static struct clk_alpha_pll gpll0 = { .offset = 0x0, - .vco_table = trion_vco, - .num_vco = ARRAY_SIZE(trion_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION], .clkr = { .enable_reg = 0x52000, @@ -85,8 +79,6 @@ static struct clk_alpha_pll_postdiv gpll0_out_even = { static struct clk_alpha_pll gpll7 = { .offset = 0x1a000, - .vco_table = trion_vco, - .num_vco = ARRAY_SIZE(trion_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION], .clkr = { .enable_reg = 0x52000, @@ -105,8 +97,6 @@ static struct clk_alpha_pll gpll7 = { static struct clk_alpha_pll gpll9 = { .offset = 0x1c000, - .vco_table = trion_vco, - .num_vco = ARRAY_SIZE(trion_vco), .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION], .clkr = { .enable_reg = 0x52000, From 23e2653ee649125d1fddd1b16c2d2ca95c684631 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:37 -0400 Subject: [PATCH 79/94] dt-bindings: clock: combine qcom,sdm845-gpucc and qcom,sc7180-gpucc These two bindings are almost identical, so combine them into one. This will make it easier to add the sm8150 and sm8250 gpucc bindings. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-7-jonathan@marek.ca Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- ...qcom,sdm845-gpucc.yaml => qcom,gpucc.yaml} | 14 ++-- .../bindings/clock/qcom,sc7180-gpucc.yaml | 74 ------------------- 2 files changed, 9 insertions(+), 79 deletions(-) rename Documentation/devicetree/bindings/clock/{qcom,sdm845-gpucc.yaml => qcom,gpucc.yaml} (82%) delete mode 100644 Documentation/devicetree/bindings/clock/qcom,sc7180-gpucc.yaml diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml similarity index 82% rename from Documentation/devicetree/bindings/clock/qcom,sdm845-gpucc.yaml rename to Documentation/devicetree/bindings/clock/qcom,gpucc.yaml index 8a0c576ba8b3..aab6bef79771 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sdm845-gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml @@ -1,23 +1,27 @@ # SPDX-License-Identifier: GPL-2.0-only %YAML 1.2 --- -$id: http://devicetree.org/schemas/clock/qcom,sdm845-gpucc.yaml# +$id: http://devicetree.org/schemas/clock/qcom,gpucc.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Qualcomm Graphics Clock & Reset Controller Binding for SDM845 +title: Qualcomm Graphics Clock & Reset Controller Binding maintainers: - Taniya Das description: | Qualcomm graphics clock control module which supports the clocks, resets and - power domains on SDM845. + power domains on SDM845/SC7180. - See also dt-bindings/clock/qcom,gpucc-sdm845.h. + See also: + dt-bindings/clock/qcom,gpucc-sdm845.h + dt-bindings/clock/qcom,gpucc-sc7180.h properties: compatible: - const: qcom,sdm845-gpucc + enum: + - qcom,sdm845-gpucc + - qcom,sc7180-gpucc clocks: items: diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-gpucc.yaml deleted file mode 100644 index fe08461fce05..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,sc7180-gpucc.yaml +++ /dev/null @@ -1,74 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/clock/qcom,sc7180-gpucc.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Qualcomm Graphics Clock & Reset Controller Binding for SC7180 - -maintainers: - - Taniya Das - -description: | - Qualcomm graphics clock control module which supports the clocks, resets and - power domains on SC7180. - - See also dt-bindings/clock/qcom,gpucc-sc7180.h. - -properties: - compatible: - const: qcom,sc7180-gpucc - - clocks: - items: - - description: Board XO source - - description: GPLL0 main branch source - - description: GPLL0 div branch source - - clock-names: - items: - - const: bi_tcxo - - const: gcc_gpu_gpll0_clk_src - - const: gcc_gpu_gpll0_div_clk_src - - '#clock-cells': - const: 1 - - '#reset-cells': - const: 1 - - '#power-domain-cells': - const: 1 - - reg: - maxItems: 1 - -required: - - compatible - - reg - - clocks - - clock-names - - '#clock-cells' - - '#reset-cells' - - '#power-domain-cells' - -additionalProperties: false - -examples: - - | - #include - #include - clock-controller@5090000 { - compatible = "qcom,sc7180-gpucc"; - reg = <0x05090000 0x9000>; - clocks = <&rpmhcc RPMH_CXO_CLK>, - <&gcc GCC_GPU_GPLL0_CLK_SRC>, - <&gcc GCC_GPU_GPLL0_DIV_CLK_SRC>; - clock-names = "bi_tcxo", - "gcc_gpu_gpll0_clk_src", - "gcc_gpu_gpll0_div_clk_src"; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; - }; -... From f793e45494586f742410f17539f1ea4156ea7bf9 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:38 -0400 Subject: [PATCH 80/94] dt-bindings: clock: add SM8150 QCOM Graphics clock bindings Add device tree bindings for graphics clock controller for Qualcomm Technology Inc's SM8150 SoCs. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-8-jonathan@marek.ca Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gpucc.yaml | 4 ++- include/dt-bindings/clock/qcom,gpucc-sm8150.h | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 include/dt-bindings/clock/qcom,gpucc-sm8150.h diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml index aab6bef79771..3e064ed0e0ea 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml @@ -11,17 +11,19 @@ maintainers: description: | Qualcomm graphics clock control module which supports the clocks, resets and - power domains on SDM845/SC7180. + power domains on SDM845/SC7180/SM8150. See also: dt-bindings/clock/qcom,gpucc-sdm845.h dt-bindings/clock/qcom,gpucc-sc7180.h + dt-bindings/clock/qcom,gpucc-sm8150.h properties: compatible: enum: - qcom,sdm845-gpucc - qcom,sc7180-gpucc + - qcom,sm8150-gpucc clocks: items: diff --git a/include/dt-bindings/clock/qcom,gpucc-sm8150.h b/include/dt-bindings/clock/qcom,gpucc-sm8150.h new file mode 100644 index 000000000000..c5b70aad7770 --- /dev/null +++ b/include/dt-bindings/clock/qcom,gpucc-sm8150.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8150_H +#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8150_H + +/* GPU_CC clock registers */ +#define GPU_CC_AHB_CLK 0 +#define GPU_CC_CRC_AHB_CLK 1 +#define GPU_CC_CX_APB_CLK 2 +#define GPU_CC_CX_GMU_CLK 3 +#define GPU_CC_CX_SNOC_DVM_CLK 4 +#define GPU_CC_CXO_AON_CLK 5 +#define GPU_CC_CXO_CLK 6 +#define GPU_CC_GMU_CLK_SRC 7 +#define GPU_CC_GX_GMU_CLK 8 +#define GPU_CC_PLL1 9 + +/* GPU_CC Resets */ +#define GPUCC_GPU_CC_CX_BCR 0 +#define GPUCC_GPU_CC_GFX3D_AON_BCR 1 +#define GPUCC_GPU_CC_GMU_BCR 2 +#define GPUCC_GPU_CC_GX_BCR 3 +#define GPUCC_GPU_CC_SPDM_BCR 4 +#define GPUCC_GPU_CC_XO_BCR 5 + +/* GPU_CC GDSCRs */ +#define GPU_CX_GDSC 0 +#define GPU_GX_GDSC 1 + +#endif From 324e0bfcfb005f161bbb31ea21ddad0f1bc8f400 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:39 -0400 Subject: [PATCH 81/94] dt-bindings: clock: add SM8250 QCOM Graphics clock bindings Add device tree bindings for graphics clock controller for Qualcomm Technology Inc's SM8250 SoCs. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-9-jonathan@marek.ca Reviewed-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/qcom,gpucc.yaml | 4 ++- include/dt-bindings/clock/qcom,gpucc-sm8250.h | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 include/dt-bindings/clock/qcom,gpucc-sm8250.h diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml index 3e064ed0e0ea..df943c4c3234 100644 --- a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml @@ -11,12 +11,13 @@ maintainers: description: | Qualcomm graphics clock control module which supports the clocks, resets and - power domains on SDM845/SC7180/SM8150. + power domains on SDM845/SC7180/SM8150/SM8250. See also: dt-bindings/clock/qcom,gpucc-sdm845.h dt-bindings/clock/qcom,gpucc-sc7180.h dt-bindings/clock/qcom,gpucc-sm8150.h + dt-bindings/clock/qcom,gpucc-sm8250.h properties: compatible: @@ -24,6 +25,7 @@ properties: - qcom,sdm845-gpucc - qcom,sc7180-gpucc - qcom,sm8150-gpucc + - qcom,sm8250-gpucc clocks: items: diff --git a/include/dt-bindings/clock/qcom,gpucc-sm8250.h b/include/dt-bindings/clock/qcom,gpucc-sm8250.h new file mode 100644 index 000000000000..dc8e387c48ad --- /dev/null +++ b/include/dt-bindings/clock/qcom,gpucc-sm8250.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8250_H +#define _DT_BINDINGS_CLK_QCOM_GPU_CC_SM8250_H + +/* GPU_CC clock registers */ +#define GPU_CC_AHB_CLK 0 +#define GPU_CC_CRC_AHB_CLK 1 +#define GPU_CC_CX_APB_CLK 2 +#define GPU_CC_CX_GMU_CLK 3 +#define GPU_CC_CX_SNOC_DVM_CLK 4 +#define GPU_CC_CXO_AON_CLK 5 +#define GPU_CC_CXO_CLK 6 +#define GPU_CC_GMU_CLK_SRC 7 +#define GPU_CC_GX_GMU_CLK 8 +#define GPU_CC_PLL1 9 +#define GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK 10 + +/* GPU_CC Resets */ +#define GPUCC_GPU_CC_ACD_BCR 0 +#define GPUCC_GPU_CC_CX_BCR 1 +#define GPUCC_GPU_CC_GFX3D_AON_BCR 2 +#define GPUCC_GPU_CC_GMU_BCR 3 +#define GPUCC_GPU_CC_GX_BCR 4 +#define GPUCC_GPU_CC_XO_BCR 5 + +/* GPU_CC GDSCRs */ +#define GPU_CX_GDSC 0 +#define GPU_GX_GDSC 1 + +#endif From 0638226dd0953c0c34f8df203b6c32d6066ceb65 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:40 -0400 Subject: [PATCH 82/94] clk: qcom: add common gdsc_gx_do_nothing_enable for gpucc drivers All gpucc drivers need this, so move it to common code instead of duplicating it in every gpucc driver. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-10-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gdsc.c | 25 +++++++++++++++++++++++++ drivers/clk/qcom/gdsc.h | 1 + drivers/clk/qcom/gpucc-sc7180.c | 27 +-------------------------- drivers/clk/qcom/gpucc-sdm845.c | 27 +-------------------------- 4 files changed, 28 insertions(+), 52 deletions(-) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 04944f11659b..628397703717 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -433,3 +433,28 @@ void gdsc_unregister(struct gdsc_desc *desc) } of_genpd_del_provider(dev->of_node); } + +/* + * On SDM845+ the GPU GX domain is *almost* entirely controlled by the GMU + * running in the CX domain so the CPU doesn't need to know anything about the + * GX domain EXCEPT.... + * + * Hardware constraints dictate that the GX be powered down before the CX. If + * the GMU crashes it could leave the GX on. In order to successfully bring back + * the device the CPU needs to disable the GX headswitch. There being no sane + * way to reach in and touch that register from deep inside the GPU driver we + * need to set up the infrastructure to be able to ensure that the GPU can + * ensure that the GX is off during this super special case. We do this by + * defining a GX gdsc with a dummy enable function and a "default" disable + * function. + * + * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU + * driver. During power up, nothing will happen from the CPU (and the GMU will + * power up normally but during power down this will ensure that the GX domain + * is *really* off - this gives us a semi standard way of doing what we need. + */ +int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain) +{ + /* Do nothing but give genpd the impression that we were successful */ + return 0; +} diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index c36fc26dcdff..1896bfb2bbd1 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -68,6 +68,7 @@ struct gdsc_desc { int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *, struct regmap *); void gdsc_unregister(struct gdsc_desc *desc); +int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain); #else static inline int gdsc_register(struct gdsc_desc *desc, struct reset_controller_dev *rcdev, diff --git a/drivers/clk/qcom/gpucc-sc7180.c b/drivers/clk/qcom/gpucc-sc7180.c index 7b656b6aeced..88a739b6fec3 100644 --- a/drivers/clk/qcom/gpucc-sc7180.c +++ b/drivers/clk/qcom/gpucc-sc7180.c @@ -170,37 +170,12 @@ static struct gdsc cx_gdsc = { .flags = VOTABLE, }; -/* - * On SC7180 the GPU GX domain is *almost* entirely controlled by the GMU - * running in the CX domain so the CPU doesn't need to know anything about the - * GX domain EXCEPT.... - * - * Hardware constraints dictate that the GX be powered down before the CX. If - * the GMU crashes it could leave the GX on. In order to successfully bring back - * the device the CPU needs to disable the GX headswitch. There being no sane - * way to reach in and touch that register from deep inside the GPU driver we - * need to set up the infrastructure to be able to ensure that the GPU can - * ensure that the GX is off during this super special case. We do this by - * defining a GX gdsc with a dummy enable function and a "default" disable - * function. - * - * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU - * driver. During power up, nothing will happen from the CPU (and the GMU will - * power up normally but during power down this will ensure that the GX domain - * is *really* off - this gives us a semi standard way of doing what we need. - */ -static int gx_gdsc_enable(struct generic_pm_domain *domain) -{ - /* Do nothing but give genpd the impression that we were successful */ - return 0; -} - static struct gdsc gx_gdsc = { .gdscr = 0x100c, .clamp_io_ctrl = 0x1508, .pd = { .name = "gx_gdsc", - .power_on = gx_gdsc_enable, + .power_on = gdsc_gx_do_nothing_enable, }, .pwrsts = PWRSTS_OFF_ON, .flags = CLAMP_IO, diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c index e40efba1bf7d..5663698b306b 100644 --- a/drivers/clk/qcom/gpucc-sdm845.c +++ b/drivers/clk/qcom/gpucc-sdm845.c @@ -131,37 +131,12 @@ static struct gdsc gpu_cx_gdsc = { .flags = VOTABLE, }; -/* - * On SDM845 the GPU GX domain is *almost* entirely controlled by the GMU - * running in the CX domain so the CPU doesn't need to know anything about the - * GX domain EXCEPT.... - * - * Hardware constraints dictate that the GX be powered down before the CX. If - * the GMU crashes it could leave the GX on. In order to successfully bring back - * the device the CPU needs to disable the GX headswitch. There being no sane - * way to reach in and touch that register from deep inside the GPU driver we - * need to set up the infrastructure to be able to ensure that the GPU can - * ensure that the GX is off during this super special case. We do this by - * defining a GX gdsc with a dummy enable function and a "default" disable - * function. - * - * This allows us to attach with genpd_dev_pm_attach_by_name() in the GPU - * driver. During power up, nothing will happen from the CPU (and the GMU will - * power up normally but during power down this will ensure that the GX domain - * is *really* off - this gives us a semi standard way of doing what we need. - */ -static int gx_gdsc_enable(struct generic_pm_domain *domain) -{ - /* Do nothing but give genpd the impression that we were successful */ - return 0; -} - static struct gdsc gpu_gx_gdsc = { .gdscr = 0x100c, .clamp_io_ctrl = 0x1508, .pd = { .name = "gpu_gx_gdsc", - .power_on = gx_gdsc_enable, + .power_on = gdsc_gx_do_nothing_enable, }, .pwrsts = PWRSTS_OFF_ON, .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR, From 0cef71f2ccc84dd85a60b312343f1973f149e2d3 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:41 -0400 Subject: [PATCH 83/94] clk: qcom: Add graphics clock controller driver for SM8150 Add support for the graphics clock controller found on SM8150 based devices. This is initially copied from the downstream kernel, but has been modified to more closely match the upstream sc7180 driver. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-11-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 8 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gpucc-sm8150.c | 320 ++++++++++++++++++++++++++++++++ 3 files changed, 329 insertions(+) create mode 100644 drivers/clk/qcom/gpucc-sm8150.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 318c0adfaae1..9643de4465dc 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -419,6 +419,14 @@ config SM_GCC_8250 Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, SD/UFS, PCIe etc. +config SM_GPUCC_8150 + tristate "SM8150 Graphics Clock Controller" + select SM_GCC_8150 + help + Support for the graphics clock controller on SM8150 devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config SPMI_PMIC_CLKDIV tristate "SPMI PMIC clkdiv Support" depends on SPMI || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index ae0979bebe18..02c87943f9fd 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o +obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o diff --git a/drivers/clk/qcom/gpucc-sm8150.c b/drivers/clk/qcom/gpucc-sm8150.c new file mode 100644 index 000000000000..27c40754b2c7 --- /dev/null +++ b/drivers/clk/qcom/gpucc-sm8150.c @@ -0,0 +1,320 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include + +#include "common.h" +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "reset.h" +#include "gdsc.h" + +enum { + P_BI_TCXO, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL1_OUT_MAIN, +}; + +static const struct pll_vco trion_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static struct alpha_pll_config gpu_cc_pll1_config = { + .l = 0x1a, + .alpha = 0xaaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002267, + .config_ctl_hi1_val = 0x00000024, + .test_ctl_val = 0x00000000, + .test_ctl_hi_val = 0x00000002, + .test_ctl_hi1_val = 0x00000000, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x000000d0, +}; + +static struct clk_alpha_pll gpu_cc_pll1 = { + .offset = 0x100, + .vco_table = trion_vco, + .num_vco = ARRAY_SIZE(trion_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_pll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_trion_ops, + }, + }, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .fw_name = "gcc_gpu_gpll0_clk_src" }, + { .fw_name = "gcc_gpu_gpll0_div_clk_src" }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0), + F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x1120, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gmu_clk_src", + .parent_data = gpu_cc_parent_data_0, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gpu_cc_ahb_clk = { + .halt_reg = 0x1078, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x107c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x107c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_crc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_apb_clk = { + .halt_reg = 0x1088, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_apb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x1098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_gmu_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { + .halt_reg = 0x108c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x108c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_snoc_dvm_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_aon_clk = { + .halt_reg = 0x1004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_aon_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x109c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x109c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gmu_clk = { + .halt_reg = 0x1064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gmu_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cx_gdsc = { + .gdscr = 0x106c, + .gds_hw_ctrl = 0x1540, + .pd = { + .name = "gpu_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc gpu_gx_gdsc = { + .gdscr = 0x100c, + .clamp_io_ctrl = 0x1508, + .pd = { + .name = "gpu_gx_gdsc", + .power_on = gdsc_gx_do_nothing_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR, +}; + +static struct clk_regmap *gpu_cc_sm8150_clocks[] = { + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, + [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, +}; + +static const struct qcom_reset_map gpu_cc_sm8150_resets[] = { + [GPUCC_GPU_CC_CX_BCR] = { 0x1068 }, + [GPUCC_GPU_CC_GMU_BCR] = { 0x111c }, + [GPUCC_GPU_CC_GX_BCR] = { 0x1008 }, + [GPUCC_GPU_CC_SPDM_BCR] = { 0x1110 }, + [GPUCC_GPU_CC_XO_BCR] = { 0x1000 }, +}; + +static struct gdsc *gpu_cc_sm8150_gdscs[] = { + [GPU_CX_GDSC] = &gpu_cx_gdsc, + [GPU_GX_GDSC] = &gpu_gx_gdsc, +}; + +static const struct regmap_config gpu_cc_sm8150_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x8008, + .fast_io = true, +}; + +static const struct qcom_cc_desc gpu_cc_sm8150_desc = { + .config = &gpu_cc_sm8150_regmap_config, + .clks = gpu_cc_sm8150_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_sm8150_clocks), + .resets = gpu_cc_sm8150_resets, + .num_resets = ARRAY_SIZE(gpu_cc_sm8150_resets), + .gdscs = gpu_cc_sm8150_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_sm8150_gdscs), +}; + +static const struct of_device_id gpu_cc_sm8150_match_table[] = { + { .compatible = "qcom,sm8150-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_sm8150_match_table); + +static int gpu_cc_sm8150_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &gpu_cc_sm8150_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_trion_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); + + return qcom_cc_really_probe(pdev, &gpu_cc_sm8150_desc, regmap); +} + +static struct platform_driver gpu_cc_sm8150_driver = { + .probe = gpu_cc_sm8150_probe, + .driver = { + .name = "sm8150-gpucc", + .of_match_table = gpu_cc_sm8150_match_table, + }, +}; + +static int __init gpu_cc_sm8150_init(void) +{ + return platform_driver_register(&gpu_cc_sm8150_driver); +} +subsys_initcall(gpu_cc_sm8150_init); + +static void __exit gpu_cc_sm8150_exit(void) +{ + platform_driver_unregister(&gpu_cc_sm8150_driver); +} +module_exit(gpu_cc_sm8150_exit); + +MODULE_DESCRIPTION("QTI GPUCC SM8150 Driver"); +MODULE_LICENSE("GPL v2"); From 28f0769c772bb0c431e2833978474d4dfe3754a7 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 9 Jul 2020 09:52:42 -0400 Subject: [PATCH 84/94] clk: qcom: Add graphics clock controller driver for SM8250 Add support for the graphics clock controller found on SM8250 based devices. This is initially copied from the downstream kernel, but has been modified to more closely match the upstream sc7180 driver. Signed-off-by: Jonathan Marek Tested-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20200709135251.643-12-jonathan@marek.ca Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 8 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/gpucc-sm8250.c | 348 ++++++++++++++++++++++++++++++++ 3 files changed, 357 insertions(+) create mode 100644 drivers/clk/qcom/gpucc-sm8250.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 9643de4465dc..cd0f01136039 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -427,6 +427,14 @@ config SM_GPUCC_8150 Say Y if you want to support graphics controller devices and functionality such as 3D graphics. +config SM_GPUCC_8250 + tristate "SM8250 Graphics Clock Controller" + select SM_GCC_8250 + help + Support for the graphics clock controller on SM8250 devices. + Say Y if you want to support graphics controller devices and + functionality such as 3D graphics. + config SPMI_PMIC_CLKDIV tristate "SPMI PMIC clkdiv Support" depends on SPMI || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 02c87943f9fd..1e9a21882ed5 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -66,6 +66,7 @@ obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o +obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o diff --git a/drivers/clk/qcom/gpucc-sm8250.c b/drivers/clk/qcom/gpucc-sm8250.c new file mode 100644 index 000000000000..3fa7d1f9ff98 --- /dev/null +++ b/drivers/clk/qcom/gpucc-sm8250.c @@ -0,0 +1,348 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include + +#include + +#include "common.h" +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-pll.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "reset.h" +#include "gdsc.h" + +#define CX_GMU_CBCR_SLEEP_MASK 0xf +#define CX_GMU_CBCR_SLEEP_SHIFT 4 +#define CX_GMU_CBCR_WAKE_MASK 0xf +#define CX_GMU_CBCR_WAKE_SHIFT 8 + +enum { + P_BI_TCXO, + P_CORE_BI_PLL_TEST_SE, + P_GPLL0_OUT_MAIN, + P_GPLL0_OUT_MAIN_DIV, + P_GPU_CC_PLL0_OUT_MAIN, + P_GPU_CC_PLL1_OUT_MAIN, +}; + +static struct pll_vco lucid_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static const struct alpha_pll_config gpu_cc_pll1_config = { + .l = 0x1a, + .alpha = 0xaaa, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x029a699c, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll gpu_cc_pll1 = { + .offset = 0x100, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_pll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct parent_map gpu_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_GPU_CC_PLL1_OUT_MAIN, 3 }, + { P_GPLL0_OUT_MAIN, 5 }, + { P_GPLL0_OUT_MAIN_DIV, 6 }, +}; + +static const struct clk_parent_data gpu_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &gpu_cc_pll1.clkr.hw }, + { .fw_name = "gcc_gpu_gpll0_clk_src" }, + { .fw_name = "gcc_gpu_gpll0_div_clk_src" }, +}; + +static const struct freq_tbl ftbl_gpu_cc_gmu_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_GPLL0_OUT_MAIN_DIV, 1.5, 0, 0), + F(500000000, P_GPU_CC_PLL1_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 gpu_cc_gmu_clk_src = { + .cmd_rcgr = 0x1120, + .mnd_width = 0, + .hid_width = 5, + .parent_map = gpu_cc_parent_map_0, + .freq_tbl = ftbl_gpu_cc_gmu_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gmu_clk_src", + .parent_data = gpu_cc_parent_data_0, + .num_parents = ARRAY_SIZE(gpu_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch gpu_cc_ahb_clk = { + .halt_reg = 0x1078, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1078, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_crc_ahb_clk = { + .halt_reg = 0x107c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x107c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_crc_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_apb_clk = { + .halt_reg = 0x1088, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x1088, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_apb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_gmu_clk = { + .halt_reg = 0x1098, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1098, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_gmu_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cx_snoc_dvm_clk = { + .halt_reg = 0x108c, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x108c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cx_snoc_dvm_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_aon_clk = { + .halt_reg = 0x1004, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0x1004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_aon_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_cxo_clk = { + .halt_reg = 0x109c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x109c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_cxo_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_gx_gmu_clk = { + .halt_reg = 0x1064, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x1064, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_gx_gmu_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &gpu_cc_gmu_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gpu_cc_hlos1_vote_gpu_smmu_clk = { + .halt_reg = 0x5000, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x5000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gpu_cc_hlos1_vote_gpu_smmu_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc gpu_cx_gdsc = { + .gdscr = 0x106c, + .gds_hw_ctrl = 0x1540, + .pd = { + .name = "gpu_cx_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc gpu_gx_gdsc = { + .gdscr = 0x100c, + .clamp_io_ctrl = 0x1508, + .pd = { + .name = "gpu_gx_gdsc", + .power_on = gdsc_gx_do_nothing_enable, + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = CLAMP_IO | AON_RESET | POLL_CFG_GDSCR, +}; + +static struct clk_regmap *gpu_cc_sm8250_clocks[] = { + [GPU_CC_AHB_CLK] = &gpu_cc_ahb_clk.clkr, + [GPU_CC_CRC_AHB_CLK] = &gpu_cc_crc_ahb_clk.clkr, + [GPU_CC_CX_APB_CLK] = &gpu_cc_cx_apb_clk.clkr, + [GPU_CC_CX_GMU_CLK] = &gpu_cc_cx_gmu_clk.clkr, + [GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr, + [GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr, + [GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr, + [GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr, + [GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr, + [GPU_CC_PLL1] = &gpu_cc_pll1.clkr, + [GPU_CC_HLOS1_VOTE_GPU_SMMU_CLK] = &gpu_cc_hlos1_vote_gpu_smmu_clk.clkr, +}; + +static const struct qcom_reset_map gpu_cc_sm8250_resets[] = { + [GPUCC_GPU_CC_ACD_BCR] = { 0x1160 }, + [GPUCC_GPU_CC_CX_BCR] = { 0x1068 }, + [GPUCC_GPU_CC_GFX3D_AON_BCR] = { 0x10a0 }, + [GPUCC_GPU_CC_GMU_BCR] = { 0x111c }, + [GPUCC_GPU_CC_GX_BCR] = { 0x1008 }, + [GPUCC_GPU_CC_XO_BCR] = { 0x1000 }, +}; + +static struct gdsc *gpu_cc_sm8250_gdscs[] = { + [GPU_CX_GDSC] = &gpu_cx_gdsc, + [GPU_GX_GDSC] = &gpu_gx_gdsc, +}; + +static const struct regmap_config gpu_cc_sm8250_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x8008, + .fast_io = true, +}; + +static const struct qcom_cc_desc gpu_cc_sm8250_desc = { + .config = &gpu_cc_sm8250_regmap_config, + .clks = gpu_cc_sm8250_clocks, + .num_clks = ARRAY_SIZE(gpu_cc_sm8250_clocks), + .resets = gpu_cc_sm8250_resets, + .num_resets = ARRAY_SIZE(gpu_cc_sm8250_resets), + .gdscs = gpu_cc_sm8250_gdscs, + .num_gdscs = ARRAY_SIZE(gpu_cc_sm8250_gdscs), +}; + +static const struct of_device_id gpu_cc_sm8250_match_table[] = { + { .compatible = "qcom,sm8250-gpucc" }, + { } +}; +MODULE_DEVICE_TABLE(of, gpu_cc_sm8250_match_table); + +static int gpu_cc_sm8250_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + unsigned int value, mask; + + regmap = qcom_cc_map(pdev, &gpu_cc_sm8250_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_pll_configure(&gpu_cc_pll1, regmap, &gpu_cc_pll1_config); + + /* + * Configure gpu_cc_cx_gmu_clk with recommended + * wakeup/sleep settings + */ + mask = CX_GMU_CBCR_WAKE_MASK << CX_GMU_CBCR_WAKE_SHIFT; + mask |= CX_GMU_CBCR_SLEEP_MASK << CX_GMU_CBCR_SLEEP_SHIFT; + value = 0xf << CX_GMU_CBCR_WAKE_SHIFT | 0xf << CX_GMU_CBCR_SLEEP_SHIFT; + regmap_update_bits(regmap, 0x1098, mask, value); + + return qcom_cc_really_probe(pdev, &gpu_cc_sm8250_desc, regmap); +} + +static struct platform_driver gpu_cc_sm8250_driver = { + .probe = gpu_cc_sm8250_probe, + .driver = { + .name = "sm8250-gpucc", + .of_match_table = gpu_cc_sm8250_match_table, + }, +}; + +static int __init gpu_cc_sm8250_init(void) +{ + return platform_driver_register(&gpu_cc_sm8250_driver); +} +subsys_initcall(gpu_cc_sm8250_init); + +static void __exit gpu_cc_sm8250_exit(void) +{ + platform_driver_unregister(&gpu_cc_sm8250_driver); +} +module_exit(gpu_cc_sm8250_exit); + +MODULE_DESCRIPTION("QTI GPU_CC SM8250 Driver"); +MODULE_LICENSE("GPL v2"); From 413d84b88bee08ed59713e782053ff38d206c606 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Fri, 24 Jul 2020 02:40:25 -0700 Subject: [PATCH 85/94] clk: qcom: Export gdsc_gx_do_nothing_enable() to modules A clk driver can be a module but the gdsc code is in the common module. Export this symbol so that allmodconfig builds keep working. Cc: Jonathan Marek Fixes: 0638226dd095 ("clk: qcom: add common gdsc_gx_do_nothing_enable for gpucc drivers") Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20200724094025.3261266-1-sboyd@kernel.org --- drivers/clk/qcom/gdsc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 628397703717..7e4273f314f7 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -458,3 +459,4 @@ int gdsc_gx_do_nothing_enable(struct generic_pm_domain *domain) /* Do nothing but give genpd the impression that we were successful */ return 0; } +EXPORT_SYMBOL_GPL(gdsc_gx_do_nothing_enable); From 6378cfdcc32d3790b04c953e7766324d8ee04a90 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 22 Jun 2020 02:09:35 -0700 Subject: [PATCH 86/94] clk: Clean up kernel-doc errors Two things aren't documented causing kernel-doc to fail when checking the core clk.c file. Fix them so that this file is clean. Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20200622090935.213833-1-sboyd@kernel.org --- drivers/clk/clk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 236923b25543..47c0ee9da462 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4135,6 +4135,7 @@ static int devm_clk_hw_match(struct device *dev, void *res, void *data) /** * devm_clk_unregister - resource managed clk_unregister() + * @dev: device that is unregistering the clock data * @clk: clock to unregister * * Deallocate a clock allocated with devm_clk_register(). Normally @@ -4324,6 +4325,8 @@ static void clk_core_reparent_orphans(void) * @node: Pointer to device tree node of clock provider * @get: Get clock callback. Returns NULL or a struct clk for the * given clock specifier + * @get_hw: Get clk_hw callback. Returns NULL, ERR_PTR or a + * struct clk_hw for the given clock specifier * @data: context pointer to be passed into @get callback */ struct of_clk_provider { From 173722995cdb7c22d21abd484a5001c903df1e20 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 24 Jul 2020 21:37:55 +0530 Subject: [PATCH 87/94] clk: qcom: gdsc: Add support to enable retention of GSDCR Add support for the RETAIN_FF_ENABLE feature which enables the usage of retention registers. These registers maintain their state after disabling and re-enabling a GDSC. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1595606878-2664-2-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gdsc.c | 12 ++++++++++++ drivers/clk/qcom/gdsc.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index 7e4273f314f7..bfc4ac02f9ea 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -30,6 +30,7 @@ /* CFG_GDSCR */ #define GDSC_POWER_UP_COMPLETE BIT(16) #define GDSC_POWER_DOWN_COMPLETE BIT(15) +#define GDSC_RETAIN_FF_ENABLE BIT(11) #define CFG_GDSCR_OFFSET 0x4 /* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */ @@ -217,6 +218,14 @@ static inline void gdsc_assert_reset_aon(struct gdsc *sc) regmap_update_bits(sc->regmap, sc->clamp_io_ctrl, GMEM_RESET_MASK, 0); } + +static void gdsc_retain_ff_on(struct gdsc *sc) +{ + u32 mask = GDSC_RETAIN_FF_ENABLE; + + regmap_update_bits(sc->regmap, sc->gdscr, mask, mask); +} + static int gdsc_enable(struct generic_pm_domain *domain) { struct gdsc *sc = domain_to_gdsc(domain); @@ -269,6 +278,9 @@ static int gdsc_enable(struct generic_pm_domain *domain) udelay(1); } + if (sc->flags & RETAIN_FF_ENABLE) + gdsc_retain_ff_on(sc); + return 0; } diff --git a/drivers/clk/qcom/gdsc.h b/drivers/clk/qcom/gdsc.h index 1896bfb2bbd1..bd537438c793 100644 --- a/drivers/clk/qcom/gdsc.h +++ b/drivers/clk/qcom/gdsc.h @@ -50,6 +50,7 @@ struct gdsc { #define AON_RESET BIT(4) #define POLL_CFG_GDSCR BIT(5) #define ALWAYS_ON BIT(6) +#define RETAIN_FF_ENABLE BIT(7) struct reset_controller_dev *rcdev; unsigned int *resets; unsigned int reset_count; From 381cc6f97cdaf15dabceb1b48fa82c9de0163e58 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 24 Jul 2020 21:37:56 +0530 Subject: [PATCH 88/94] dt-bindings: clock: Add YAML schemas for LPASS clocks on SC7180 The LPASS(Low Power Audio Subsystem) clock provider have a bunch of generic properties that are needed in a device tree. Also add clock ids for GCC LPASS and LPASS Core clock IDs for LPASS client to request for the clocks. Signed-off-by: Taniya Das Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/1595606878-2664-3-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- .../clock/qcom,sc7180-lpasscorecc.yaml | 102 ++++++++++++++++++ include/dt-bindings/clock/qcom,gcc-sc7180.h | 1 + .../clock/qcom,lpasscorecc-sc7180.h | 29 +++++ 3 files changed, 132 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml create mode 100644 include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml new file mode 100644 index 000000000000..a838250b33e7 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml @@ -0,0 +1,102 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,sc7180-lpasscorecc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm LPASS Core Clock Controller Binding for SC7180 + +maintainers: + - Taniya Das + +description: | + Qualcomm LPASS core clock control module which supports the clocks and + power domains on SC7180. + + See also: + - dt-bindings/clock/qcom,lpasscorecc-sc7180.h + +properties: + compatible: + enum: + - qcom,sc7180-lpasshm + - qcom,sc7180-lpasscorecc + + clocks: + items: + - description: gcc_lpass_sway clock from GCC + + clock-names: + items: + - const: iface + + power-domains: + maxItems: 1 + + '#clock-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + minItems: 1 + items: + - description: lpass core cc register + - description: lpass audio cc register + + reg-names: + items: + - const: lpass_core_cc + - const: lpass_audio_cc + +if: + properties: + compatible: + contains: + const: qcom,sc7180-lpasshm +then: + properties: + reg: + maxItems: 1 + +else: + properties: + reg: + minItems: 2 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include + #include + clock-controller@63000000 { + compatible = "qcom,sc7180-lpasshm"; + reg = <0x63000000 0x28>; + clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>; + clock-names = "iface"; + #clock-cells = <1>; + #power-domain-cells = <1>; + }; + + - | + clock-controller@62d00000 { + compatible = "qcom,sc7180-lpasscorecc"; + reg = <0x62d00000 0x50000>, <0x62780000 0x30000>; + reg-names = "lpass_core_cc", "lpass_audio_cc"; + clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>; + clock-names = "iface"; + power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>; + #clock-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/include/dt-bindings/clock/qcom,gcc-sc7180.h b/include/dt-bindings/clock/qcom,gcc-sc7180.h index 992b67b7e5e4..bdf43adc7897 100644 --- a/include/dt-bindings/clock/qcom,gcc-sc7180.h +++ b/include/dt-bindings/clock/qcom,gcc-sc7180.h @@ -138,6 +138,7 @@ #define GCC_MSS_Q6_MEMNOC_AXI_CLK 128 #define GCC_MSS_SNOC_AXI_CLK 129 #define GCC_SEC_CTRL_CLK_SRC 130 +#define GCC_LPASS_CFG_NOC_SWAY_CLK 131 /* GCC resets */ #define GCC_QUSB2PHY_PRIM_BCR 0 diff --git a/include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h b/include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h new file mode 100644 index 000000000000..a55d01db2b20 --- /dev/null +++ b/include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_LPASS_CORE_CC_SC7180_H +#define _DT_BINDINGS_CLK_QCOM_LPASS_CORE_CC_SC7180_H + +/* LPASS_CORE_CC clocks */ +#define LPASS_LPAAUDIO_DIG_PLL 0 +#define LPASS_LPAAUDIO_DIG_PLL_OUT_ODD 1 +#define CORE_CLK_SRC 2 +#define EXT_MCLK0_CLK_SRC 3 +#define LPAIF_PRI_CLK_SRC 4 +#define LPAIF_SEC_CLK_SRC 5 +#define LPASS_AUDIO_CORE_CORE_CLK 6 +#define LPASS_AUDIO_CORE_EXT_MCLK0_CLK 7 +#define LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK 8 +#define LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK 9 +#define LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK 10 + +/* LPASS Core power domains */ +#define LPASS_CORE_HM_GDSCR 0 + +/* LPASS Audio power domains */ +#define LPASS_AUDIO_HM_GDSCR 0 +#define LPASS_PDC_HM_GDSCR 1 + +#endif From 47110b6aa5c8269da4a3b5129b066211f978aa86 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 24 Jul 2020 21:37:57 +0530 Subject: [PATCH 89/94] clk: qcom: gcc: Add support for GCC LPASS clock for SC7180 Add the GCC lpass clock which is required to access the LPASS core clocks. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1595606878-2664-4-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sc7180.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/clk/qcom/gcc-sc7180.c b/drivers/clk/qcom/gcc-sc7180.c index 538677befb86..68d8f7aaf64e 100644 --- a/drivers/clk/qcom/gcc-sc7180.c +++ b/drivers/clk/qcom/gcc-sc7180.c @@ -2251,6 +2251,19 @@ static struct clk_branch gcc_mss_q6_memnoc_axi_clk = { }, }; +static struct clk_branch gcc_lpass_cfg_noc_sway_clk = { + .halt_reg = 0x47018, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x47018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "gcc_lpass_cfg_noc_sway_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct gdsc ufs_phy_gdsc = { .gdscr = 0x77004, .pd = { @@ -2428,6 +2441,7 @@ static struct clk_regmap *gcc_sc7180_clocks[] = { [GCC_MSS_Q6_MEMNOC_AXI_CLK] = &gcc_mss_q6_memnoc_axi_clk.clkr, [GCC_MSS_SNOC_AXI_CLK] = &gcc_mss_snoc_axi_clk.clkr, [GCC_SEC_CTRL_CLK_SRC] = &gcc_sec_ctrl_clk_src.clkr, + [GCC_LPASS_CFG_NOC_SWAY_CLK] = &gcc_lpass_cfg_noc_sway_clk.clkr, }; static const struct qcom_reset_map gcc_sc7180_resets[] = { From edab812d802d248e3d07719c036a865c67ad3a87 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Fri, 24 Jul 2020 21:37:58 +0530 Subject: [PATCH 90/94] clk: qcom: lpass: Add support for LPASS clock controller for SC7180 The Low Power Audio subsystem clocks are required for Audio client to be able to request for the clocks and power domains. Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1595606878-2664-5-git-send-email-tdas@codeaurora.org [sboyd@kernel.org: Drop unused ret in probe function] Signed-off-by: Stephen Boyd --- drivers/clk/qcom/Kconfig | 9 + drivers/clk/qcom/Makefile | 1 + drivers/clk/qcom/lpasscorecc-sc7180.c | 476 ++++++++++++++++++++++++++ 3 files changed, 486 insertions(+) create mode 100644 drivers/clk/qcom/lpasscorecc-sc7180.c diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index cd0f01136039..058327310c25 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -308,6 +308,15 @@ config SC_GCC_7180 Say Y if you want to use peripheral devices such as UART, SPI, I2C, USB, UFS, SDCC, etc. +config SC_LPASS_CORECC_7180 + tristate "SC7180 LPASS Core Clock Controller" + select SC_GCC_7180 + help + Support for the LPASS(Low Power Audio Subsystem) core clock controller + on SC7180 devices. + Say Y if you want to use LPASS clocks and power domains of the LPASS + core clock controller. + config SC_GPUCC_7180 tristate "SC7180 Graphics Clock Controller" select SC_GCC_7180 diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 1e9a21882ed5..9677e769e7e9 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_QCS_TURING_404) += turingcc-qcs404.o obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o obj-$(CONFIG_SC_GPUCC_7180) += gpucc-sc7180.o +obj-$(CONFIG_SC_LPASS_CORECC_7180) += lpasscorecc-sc7180.o obj-$(CONFIG_SC_MSS_7180) += mss-sc7180.o obj-$(CONFIG_SC_VIDEOCC_7180) += videocc-sc7180.o obj-$(CONFIG_SDM_CAMCC_845) += camcc-sdm845.o diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c new file mode 100644 index 000000000000..d4c1864e1ee9 --- /dev/null +++ b/drivers/clk/qcom/lpasscorecc-sc7180.c @@ -0,0 +1,476 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "common.h" +#include "gdsc.h" + +enum { + P_BI_TCXO, + P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, + P_SLEEP_CLK, +}; + +static struct pll_vco fabia_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static const struct alpha_pll_config lpass_lpaaudio_dig_pll_config = { + .l = 0x20, + .alpha = 0x0, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002067, + .test_ctl_val = 0x40000000, + .test_ctl_hi_val = 0x00000000, + .user_ctl_val = 0x00005105, + .user_ctl_hi_val = 0x00004805, +}; + +static const u8 clk_alpha_pll_regs_offset[][PLL_OFF_MAX_REGS] = { + [CLK_ALPHA_PLL_TYPE_FABIA] = { + [PLL_OFF_L_VAL] = 0x04, + [PLL_OFF_CAL_L_VAL] = 0x8, + [PLL_OFF_USER_CTL] = 0x0c, + [PLL_OFF_USER_CTL_U] = 0x10, + [PLL_OFF_USER_CTL_U1] = 0x14, + [PLL_OFF_CONFIG_CTL] = 0x18, + [PLL_OFF_CONFIG_CTL_U] = 0x1C, + [PLL_OFF_CONFIG_CTL_U1] = 0x20, + [PLL_OFF_TEST_CTL] = 0x24, + [PLL_OFF_TEST_CTL_U] = 0x28, + [PLL_OFF_STATUS] = 0x30, + [PLL_OFF_OPMODE] = 0x38, + [PLL_OFF_FRAC] = 0x40, + }, +}; + +static struct clk_alpha_pll lpass_lpaaudio_dig_pll = { + .offset = 0x1000, + .vco_table = fabia_vco, + .num_vco = ARRAY_SIZE(fabia_vco), + .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "lpass_lpaaudio_dig_pll", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_fabia_ops, + }, + }, +}; + +static const struct clk_div_table + post_div_table_lpass_lpaaudio_dig_pll_out_odd[] = { + { 0x5, 5 }, + { } +}; + +static struct clk_alpha_pll_postdiv lpass_lpaaudio_dig_pll_out_odd = { + .offset = 0x1000, + .post_div_shift = 12, + .post_div_table = post_div_table_lpass_lpaaudio_dig_pll_out_odd, + .num_post_div = + ARRAY_SIZE(post_div_table_lpass_lpaaudio_dig_pll_out_odd), + .width = 4, + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], + .clkr.hw.init = &(struct clk_init_data){ + .name = "lpass_lpaaudio_dig_pll_out_odd", + .parent_data = &(const struct clk_parent_data){ + .hw = &lpass_lpaaudio_dig_pll.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_alpha_pll_postdiv_fabia_ops, + }, +}; + +static const struct parent_map lpass_core_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 5 }, +}; + +static const struct clk_parent_data lpass_core_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &lpass_lpaaudio_dig_pll_out_odd.clkr.hw }, +}; + +static const struct parent_map lpass_core_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, +}; + +static struct clk_rcg2 core_clk_src = { + .cmd_rcgr = 0x1d000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_core_cc_parent_map_2, + .clkr.hw.init = &(struct clk_init_data){ + .name = "core_clk_src", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_ext_mclk0_clk_src[] = { + F(9600000, P_BI_TCXO, 2, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static const struct freq_tbl ftbl_ext_lpaif_clk_src[] = { + F(256000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 32), + F(512000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 16), + F(768000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 16), + F(1024000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 8), + F(1536000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 8), + F(2048000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 4), + F(3072000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 4), + F(4096000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 2), + F(6144000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 2), + F(8192000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 0, 0), + F(9600000, P_BI_TCXO, 2, 0, 0), + F(12288000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 0, 0), + F(19200000, P_BI_TCXO, 1, 0, 0), + F(24576000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 5, 0, 0), + { } +}; + +static struct clk_rcg2 ext_mclk0_clk_src = { + .cmd_rcgr = 0x20000, + .mnd_width = 8, + .hid_width = 5, + .parent_map = lpass_core_cc_parent_map_0, + .freq_tbl = ftbl_ext_mclk0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "ext_mclk0_clk_src", + .parent_data = lpass_core_cc_parent_data_0, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 lpaif_pri_clk_src = { + .cmd_rcgr = 0x10000, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_core_cc_parent_map_0, + .freq_tbl = ftbl_ext_lpaif_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "lpaif_pri_clk_src", + .parent_data = lpass_core_cc_parent_data_0, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 lpaif_sec_clk_src = { + .cmd_rcgr = 0x11000, + .mnd_width = 16, + .hid_width = 5, + .parent_map = lpass_core_cc_parent_map_0, + .freq_tbl = ftbl_ext_lpaif_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "lpaif_sec_clk_src", + .parent_data = lpass_core_cc_parent_data_0, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_branch lpass_audio_core_ext_mclk0_clk = { + .halt_reg = 0x20014, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x20014, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x20014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lpass_audio_core_ext_mclk0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &ext_mclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_core_lpaif_pri_ibit_clk = { + .halt_reg = 0x10018, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x10018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x10018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lpass_audio_core_lpaif_pri_ibit_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &lpaif_pri_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_core_lpaif_sec_ibit_clk = { + .halt_reg = 0x11018, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x11018, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x11018, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lpass_audio_core_lpaif_sec_ibit_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &lpaif_sec_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch lpass_audio_core_sysnoc_mport_core_clk = { + .halt_reg = 0x23000, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x23000, + .hwcg_bit = 1, + .clkr = { + .enable_reg = 0x23000, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "lpass_audio_core_sysnoc_mport_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &core_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_regmap *lpass_core_cc_sc7180_clocks[] = { + [EXT_MCLK0_CLK_SRC] = &ext_mclk0_clk_src.clkr, + [LPAIF_PRI_CLK_SRC] = &lpaif_pri_clk_src.clkr, + [LPAIF_SEC_CLK_SRC] = &lpaif_sec_clk_src.clkr, + [CORE_CLK_SRC] = &core_clk_src.clkr, + [LPASS_AUDIO_CORE_EXT_MCLK0_CLK] = &lpass_audio_core_ext_mclk0_clk.clkr, + [LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK] = + &lpass_audio_core_lpaif_pri_ibit_clk.clkr, + [LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK] = + &lpass_audio_core_lpaif_sec_ibit_clk.clkr, + [LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK] = + &lpass_audio_core_sysnoc_mport_core_clk.clkr, + [LPASS_LPAAUDIO_DIG_PLL] = &lpass_lpaaudio_dig_pll.clkr, + [LPASS_LPAAUDIO_DIG_PLL_OUT_ODD] = &lpass_lpaaudio_dig_pll_out_odd.clkr, +}; + +static struct gdsc lpass_pdc_hm_gdsc = { + .gdscr = 0x3090, + .pd = { + .name = "lpass_pdc_hm_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = VOTABLE, +}; + +static struct gdsc lpass_audio_hm_gdsc = { + .gdscr = 0x9090, + .pd = { + .name = "lpass_audio_hm_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc lpass_core_hm_gdsc = { + .gdscr = 0x0, + .pd = { + .name = "lpass_core_hm_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = RETAIN_FF_ENABLE, +}; + +static struct gdsc *lpass_core_hm_sc7180_gdscs[] = { + [LPASS_CORE_HM_GDSCR] = &lpass_core_hm_gdsc, +}; + +static struct gdsc *lpass_audio_hm_sc7180_gdscs[] = { + [LPASS_PDC_HM_GDSCR] = &lpass_pdc_hm_gdsc, + [LPASS_AUDIO_HM_GDSCR] = &lpass_audio_hm_gdsc, +}; + +static struct regmap_config lpass_core_cc_sc7180_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .fast_io = true, +}; + +static const struct qcom_cc_desc lpass_core_hm_sc7180_desc = { + .config = &lpass_core_cc_sc7180_regmap_config, + .gdscs = lpass_core_hm_sc7180_gdscs, + .num_gdscs = ARRAY_SIZE(lpass_core_hm_sc7180_gdscs), +}; + +static const struct qcom_cc_desc lpass_core_cc_sc7180_desc = { + .config = &lpass_core_cc_sc7180_regmap_config, + .clks = lpass_core_cc_sc7180_clocks, + .num_clks = ARRAY_SIZE(lpass_core_cc_sc7180_clocks), +}; + +static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = { + .config = &lpass_core_cc_sc7180_regmap_config, + .gdscs = lpass_audio_hm_sc7180_gdscs, + .num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs), +}; + +static int lpass_core_cc_sc7180_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc; + struct regmap *regmap; + int ret; + + lpass_core_cc_sc7180_regmap_config.name = "lpass_audio_cc"; + desc = &lpass_audio_hm_sc7180_desc; + ret = qcom_cc_probe_by_index(pdev, 1, desc); + if (ret) + return ret; + + lpass_core_cc_sc7180_regmap_config.name = "lpass_core_cc"; + regmap = qcom_cc_map(pdev, &lpass_core_cc_sc7180_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* + * Keep the CLK always-ON + * LPASS_AUDIO_CORE_SYSNOC_SWAY_CORE_CLK + */ + regmap_update_bits(regmap, 0x24000, BIT(0), BIT(0)); + + /* PLL settings */ + regmap_write(regmap, 0x1008, 0x20); + regmap_update_bits(regmap, 0x1014, BIT(0), BIT(0)); + + clk_fabia_pll_configure(&lpass_lpaaudio_dig_pll, regmap, + &lpass_lpaaudio_dig_pll_config); + + return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap); +} + +static int lpass_hm_core_probe(struct platform_device *pdev) +{ + const struct qcom_cc_desc *desc; + + lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core"; + desc = &lpass_core_hm_sc7180_desc; + + return qcom_cc_probe_by_index(pdev, 0, desc); +} + +static const struct of_device_id lpass_core_cc_sc7180_match_table[] = { + { + .compatible = "qcom,sc7180-lpasshm", + .data = lpass_hm_core_probe, + }, + { + .compatible = "qcom,sc7180-lpasscorecc", + .data = lpass_core_cc_sc7180_probe, + }, + { } +}; +MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7180_match_table); + +static int lpass_core_sc7180_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *p); + int ret; + + pm_runtime_enable(&pdev->dev); + ret = pm_clk_create(&pdev->dev); + if (ret) + return ret; + + ret = pm_clk_add(&pdev->dev, "iface"); + if (ret < 0) { + dev_err(&pdev->dev, "failed to acquire iface clock\n"); + goto disable_pm_runtime; + } + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + ret = clk_probe(pdev); + 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 const struct dev_pm_ops lpass_core_cc_pm_ops = { + SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) +}; + +static struct platform_driver lpass_core_cc_sc7180_driver = { + .probe = lpass_core_sc7180_probe, + .driver = { + .name = "lpass_core_cc-sc7180", + .of_match_table = lpass_core_cc_sc7180_match_table, + .pm = &lpass_core_cc_pm_ops, + }, +}; + +static int __init lpass_core_cc_sc7180_init(void) +{ + return platform_driver_register(&lpass_core_cc_sc7180_driver); +} +subsys_initcall(lpass_core_cc_sc7180_init); + +static void __exit lpass_core_cc_sc7180_exit(void) +{ + platform_driver_unregister(&lpass_core_cc_sc7180_driver); +} +module_exit(lpass_core_cc_sc7180_exit); + +MODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7180 Driver"); +MODULE_LICENSE("GPL v2"); From b538304da7855f4e31f91f915f259936eb67a1e6 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sun, 26 Jul 2020 13:11:58 +0200 Subject: [PATCH 91/94] clk: qcom: gcc-sdm660: Add missing modem reset This will be required in order to support the modem upstream. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20200726111215.22361-2-konradybcio@gmail.com Fixes: f2a76a2955c0 ("clk: qcom: Add Global Clock controller (GCC) driver for SDM660") Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sdm660.c | 1 + include/dt-bindings/clock/qcom,gcc-sdm660.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c index bf5730832ef3..a85283786278 100644 --- a/drivers/clk/qcom/gcc-sdm660.c +++ b/drivers/clk/qcom/gcc-sdm660.c @@ -2402,6 +2402,7 @@ static const struct qcom_reset_map gcc_sdm660_resets[] = { [GCC_USB_20_BCR] = { 0x2f000 }, [GCC_USB_30_BCR] = { 0xf000 }, [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 }, + [GCC_MSS_RESTART] = { 0x79000 }, }; static const struct regmap_config gcc_sdm660_regmap_config = { diff --git a/include/dt-bindings/clock/qcom,gcc-sdm660.h b/include/dt-bindings/clock/qcom,gcc-sdm660.h index 468302282913..df8a6f3d367e 100644 --- a/include/dt-bindings/clock/qcom,gcc-sdm660.h +++ b/include/dt-bindings/clock/qcom,gcc-sdm660.h @@ -152,5 +152,6 @@ #define GCC_USB_20_BCR 6 #define GCC_USB_30_BCR 7 #define GCC_USB_PHY_CFG_AHB2PHY_BCR 8 +#define GCC_MSS_RESTART 9 #endif From 3386af51d3bcebcba3f7becdb1ef2e384abe90cf Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sun, 26 Jul 2020 13:12:05 +0200 Subject: [PATCH 92/94] clk: qcom: gcc-sdm660: Fix up gcc_mss_mnoc_bimc_axi_clk Add missing halt_check, hwcg_reg and hwcg_bit properties. These were likely omitted when porting the driver upstream. Signed-off-by: Konrad Dybcio Link: https://lore.kernel.org/r/20200726111215.22361-9-konradybcio@gmail.com Fixes: f2a76a2955c0 ("clk: qcom: Add Global Clock controller (GCC) driver for SDM660") Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-sdm660.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c index a85283786278..f0b47b7d50ca 100644 --- a/drivers/clk/qcom/gcc-sdm660.c +++ b/drivers/clk/qcom/gcc-sdm660.c @@ -1715,6 +1715,9 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = { static struct clk_branch gcc_mss_mnoc_bimc_axi_clk = { .halt_reg = 0x8a004, + .halt_check = BRANCH_HALT, + .hwcg_reg = 0x8a004, + .hwcg_bit = 1, .clkr = { .enable_reg = 0x8a004, .enable_mask = BIT(0), From 9f4db31ea09e3c1e25b60b1d93e549fd38360197 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Fri, 31 Jul 2020 13:30:10 -0700 Subject: [PATCH 93/94] dt-bindings: clock: Fix YAML schemas for LPASS clocks on SC7180 The YAML schemas that landed forgot one clock: "bi_tcxo". Presumably the bindings were developed against the v4 version of the driver and when the ".name" was removed in v5 of the driver things broke. While touching this, add the needed includes in each example. I believe both examples are supposed to be independent of each other. Let's fix the bindings. Fixes: 381cc6f97cda ("dt-bindings: clock: Add YAML schemas for LPASS clocks on SC7180") Signed-off-by: Douglas Anderson Link: https://lore.kernel.org/r/20200731133006.1.Iee81b115f5be50d6d69500fe1bda11bba6e16143@changeid Signed-off-by: Stephen Boyd --- .../bindings/clock/qcom,sc7180-lpasscorecc.yaml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml index a838250b33e7..c54172fbf29f 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml @@ -25,10 +25,12 @@ properties: clocks: items: - description: gcc_lpass_sway clock from GCC + - description: Board XO source clock-names: items: - const: iface + - const: bi_tcxo power-domains: maxItems: 1 @@ -77,24 +79,28 @@ additionalProperties: false examples: - | + #include #include #include clock-controller@63000000 { compatible = "qcom,sc7180-lpasshm"; reg = <0x63000000 0x28>; - clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>; - clock-names = "iface"; + clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>, <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "bi_tcxo"; #clock-cells = <1>; #power-domain-cells = <1>; }; - | + #include + #include + #include clock-controller@62d00000 { compatible = "qcom,sc7180-lpasscorecc"; reg = <0x62d00000 0x50000>, <0x62780000 0x30000>; reg-names = "lpass_core_cc", "lpass_audio_cc"; - clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>; - clock-names = "iface"; + clocks = <&gcc GCC_LPASS_CFG_NOC_SWAY_CLK>, <&rpmhcc RPMH_CXO_CLK>; + clock-names = "iface", "bi_tcxo"; power-domains = <&lpass_hm LPASS_CORE_HM_GDSCR>; #clock-cells = <1>; #power-domain-cells = <1>; From f34e4651ce66a754f41203284acf09b28b9dd955 Mon Sep 17 00:00:00 2001 From: Nicolas Saenz Julienne Date: Thu, 30 Jul 2020 20:26:19 +0200 Subject: [PATCH 94/94] clk: bcm2835: Do not use prediv with bcm2711's PLLs Contrary to previous SoCs, bcm2711 doesn't have a prescaler in the PLL feedback loop. Bypass it by zeroing fb_prediv_mask when running on bcm2711. Note that, since the prediv configuration bits were re-purposed, this was triggering miscalculations on all clocks hanging from the VPU clock, notably the aux UART, making its output unintelligible. Fixes: 42de9ad400af ("clk: bcm2835: Add BCM2711_CLOCK_EMMC2 support") Reported-by: Nathan Chancellor Signed-off-by: Nicolas Saenz Julienne Link: https://lore.kernel.org/r/20200730182619.23246-1-nsaenzjulienne@suse.de Tested-by: Nathan Chancellor Reviewed-by: Florian Fainelli Signed-off-by: Stephen Boyd --- drivers/clk/bcm/clk-bcm2835.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 027eba31f793..3439bc65bb4e 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -314,6 +314,7 @@ struct bcm2835_cprman { struct device *dev; void __iomem *regs; spinlock_t regs_lock; /* spinlock for all clocks */ + unsigned int soc; /* * Real names of cprman clock parents looked up through @@ -526,6 +527,20 @@ static int bcm2835_pll_is_on(struct clk_hw *hw) A2W_PLL_CTRL_PRST_DISABLE; } +static u32 bcm2835_pll_get_prediv_mask(struct bcm2835_cprman *cprman, + const struct bcm2835_pll_data *data) +{ + /* + * On BCM2711 there isn't a pre-divisor available in the PLL feedback + * loop. Bits 13:14 of ANA1 (PLLA,PLLB,PLLC,PLLD) have been re-purposed + * for to for VCO RANGE bits. + */ + if (cprman->soc & SOC_BCM2711) + return 0; + + return data->ana->fb_prediv_mask; +} + static void bcm2835_pll_choose_ndiv_and_fdiv(unsigned long rate, unsigned long parent_rate, u32 *ndiv, u32 *fdiv) @@ -583,7 +598,7 @@ static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw, ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT; pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT; using_prediv = cprman_read(cprman, data->ana_reg_base + 4) & - data->ana->fb_prediv_mask; + bcm2835_pll_get_prediv_mask(cprman, data); if (using_prediv) { ndiv *= 2; @@ -666,6 +681,7 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw); struct bcm2835_cprman *cprman = pll->cprman; const struct bcm2835_pll_data *data = pll->data; + u32 prediv_mask = bcm2835_pll_get_prediv_mask(cprman, data); bool was_using_prediv, use_fb_prediv, do_ana_setup_first; u32 ndiv, fdiv, a2w_ctl; u32 ana[4]; @@ -683,7 +699,7 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, for (i = 3; i >= 0; i--) ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4); - was_using_prediv = ana[1] & data->ana->fb_prediv_mask; + was_using_prediv = ana[1] & prediv_mask; ana[0] &= ~data->ana->mask0; ana[0] |= data->ana->set0; @@ -693,10 +709,10 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw, ana[3] |= data->ana->set3; if (was_using_prediv && !use_fb_prediv) { - ana[1] &= ~data->ana->fb_prediv_mask; + ana[1] &= ~prediv_mask; do_ana_setup_first = true; } else if (!was_using_prediv && use_fb_prediv) { - ana[1] |= data->ana->fb_prediv_mask; + ana[1] |= prediv_mask; do_ana_setup_first = false; } else { do_ana_setup_first = true; @@ -2262,6 +2278,7 @@ static int bcm2835_clk_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cprman); cprman->onecell.num = asize; + cprman->soc = pdata->soc; hws = cprman->onecell.hws; for (i = 0; i < asize; i++) {