From 2f1efa5340eff9af36c9a7347bb97abd726128a0 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 10 Jun 2020 10:30:12 +0200 Subject: clk: meson: g12a: Add support for NNA CLK source clocks This adds the Neural Network Accelerator source clocks hierarchy, it's 2 simple composite clocks to feed the AXI interface and the Core of the Neural Network Accelerator IP. This IP is only present on the Amlogic SM1 SoCs family. Signed-off-by: Dmitry Shmidt Signed-off-by: Neil Armstrong Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200610083012.5024-3-narmstrong@baylibre.com --- drivers/clk/meson/g12a.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/clk/meson/g12a.h | 7 ++- 2 files changed, 125 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 30c15766ebb1..9803d44bb157 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -3981,6 +3981,113 @@ static struct clk_regmap g12a_spicc1_sclk = { }, }; +/* Neural Network Accelerator source clock */ + +static const struct clk_parent_data nna_clk_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &g12a_gp0_pll.hw, }, + { .hw = &g12a_hifi_pll.hw, }, + { .hw = &g12a_fclk_div2p5.hw, }, + { .hw = &g12a_fclk_div3.hw, }, + { .hw = &g12a_fclk_div4.hw, }, + { .hw = &g12a_fclk_div5.hw, }, + { .hw = &g12a_fclk_div7.hw }, +}; + +static struct clk_regmap sm1_nna_axi_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_NNA_CLK_CNTL, + .mask = 7, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "nna_axi_clk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = nna_clk_parent_data, + .num_parents = ARRAY_SIZE(nna_clk_parent_data), + }, +}; + +static struct clk_regmap sm1_nna_axi_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_NNA_CLK_CNTL, + .shift = 0, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "nna_axi_clk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sm1_nna_axi_clk_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sm1_nna_axi_clk = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_NNA_CLK_CNTL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "nna_axi_clk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sm1_nna_axi_clk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sm1_nna_core_clk_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = HHI_NNA_CLK_CNTL, + .mask = 7, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "nna_core_clk_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = nna_clk_parent_data, + .num_parents = ARRAY_SIZE(nna_clk_parent_data), + }, +}; + +static struct clk_regmap sm1_nna_core_clk_div = { + .data = &(struct clk_regmap_div_data){ + .offset = HHI_NNA_CLK_CNTL, + .shift = 16, + .width = 7, + }, + .hw.init = &(struct clk_init_data){ + .name = "nna_core_clk_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sm1_nna_core_clk_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sm1_nna_core_clk = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_NNA_CLK_CNTL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "nna_core_clk", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sm1_nna_core_clk_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + #define MESON_GATE(_name, _reg, _bit) \ MESON_PCLK(_name, _reg, _bit, &g12a_clk81.hw) @@ -4779,6 +4886,12 @@ static struct clk_hw_onecell_data sm1_hw_onecell_data = { [CLKID_SPICC1_SCLK_SEL] = &g12a_spicc1_sclk_sel.hw, [CLKID_SPICC1_SCLK_DIV] = &g12a_spicc1_sclk_div.hw, [CLKID_SPICC1_SCLK] = &g12a_spicc1_sclk.hw, + [CLKID_NNA_AXI_CLK_SEL] = &sm1_nna_axi_clk_sel.hw, + [CLKID_NNA_AXI_CLK_DIV] = &sm1_nna_axi_clk_div.hw, + [CLKID_NNA_AXI_CLK] = &sm1_nna_axi_clk.hw, + [CLKID_NNA_CORE_CLK_SEL] = &sm1_nna_core_clk_sel.hw, + [CLKID_NNA_CORE_CLK_DIV] = &sm1_nna_core_clk_div.hw, + [CLKID_NNA_CORE_CLK] = &sm1_nna_core_clk.hw, [NR_CLKS] = NULL, }, .num = NR_CLKS, @@ -5020,6 +5133,12 @@ static struct clk_regmap *const g12a_clk_regmaps[] = { &g12a_spicc1_sclk_sel, &g12a_spicc1_sclk_div, &g12a_spicc1_sclk, + &sm1_nna_axi_clk_sel, + &sm1_nna_axi_clk_div, + &sm1_nna_axi_clk, + &sm1_nna_core_clk_sel, + &sm1_nna_core_clk_div, + &sm1_nna_core_clk, }; static const struct reg_sequence g12a_init_regs[] = { diff --git a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h index a8852556836e..69b6a69549c7 100644 --- a/drivers/clk/meson/g12a.h +++ b/drivers/clk/meson/g12a.h @@ -70,6 +70,7 @@ #define HHI_MALI_CLK_CNTL 0x1b0 #define HHI_VPU_CLKC_CNTL 0x1b4 #define HHI_VPU_CLK_CNTL 0x1bC +#define HHI_NNA_CLK_CNTL 0x1C8 #define HHI_HDMI_CLK_CNTL 0x1CC #define HHI_VDEC_CLK_CNTL 0x1E0 #define HHI_VDEC2_CLK_CNTL 0x1E4 @@ -259,8 +260,12 @@ #define CLKID_SPICC0_SCLK_DIV 257 #define CLKID_SPICC1_SCLK_SEL 259 #define CLKID_SPICC1_SCLK_DIV 260 +#define CLKID_NNA_AXI_CLK_SEL 262 +#define CLKID_NNA_AXI_CLK_DIV 263 +#define CLKID_NNA_CORE_CLK_SEL 265 +#define CLKID_NNA_CORE_CLK_DIV 266 -#define NR_CLKS 262 +#define NR_CLKS 268 /* include the CLKIDs that have been made part of the DT binding */ #include -- cgit v1.2.3-58-ga151 From cf8030d7035bd3e89c9e66f7193a7fc8057a9b9a Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Tue, 9 Jun 2020 13:08:46 +0200 Subject: 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(+) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From 90741a7268dfe4d4f159c8e10a1c1cb9d4e31dd9 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Wed, 10 Jun 2020 16:08:58 +0200 Subject: 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(+) (limited to 'drivers/clk') 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, }, -- cgit v1.2.3-58-ga151 From e244d2058dcdff6c7ac21efefed75eba43525140 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Mon, 15 Jun 2020 11:02:31 +0200 Subject: 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(-) (limited to 'drivers/clk') 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) -- cgit v1.2.3-58-ga151 From 1bc95972715ab81fd3fa9f5b45ace5bb607af1b5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 11 Jun 2020 11:23:16 +0200 Subject: 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 (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From fbac2e7787ac6fd2226a5935c80c0ff80d607bce Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:44 +0200 Subject: 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(-) (limited to 'drivers/clk') 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, -- cgit v1.2.3-58-ga151 From 869bd27541fe4eb1468dd4f0ddf76af6dd9b35ac Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:45 +0200 Subject: 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(-) (limited to 'drivers/clk') 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" }; -- cgit v1.2.3-58-ga151 From 72856a4ed555892c0c793becebba93fc43c50856 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:46 +0200 Subject: 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(-) (limited to 'drivers/clk') 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) { -- cgit v1.2.3-58-ga151 From c70011a985001e4dec4ce10154b9ff0f00f4140f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:47 +0200 Subject: 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(-) (limited to 'drivers/clk') 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; } -- cgit v1.2.3-58-ga151 From 683de1868164ec8d252ec9261a5dfd0f9edd7f52 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:48 +0200 Subject: 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(-) (limited to 'drivers/clk') 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; } -- cgit v1.2.3-58-ga151 From 8f60112f66bf3a17ef3206e716064aa76011b94d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:49 +0200 Subject: 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(-) (limited to 'drivers/clk') 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; } -- cgit v1.2.3-58-ga151 From 55ee6a992dfe9c477da629b1ddf33a0e1bbd83bc Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:50 +0200 Subject: 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(-) (limited to 'drivers/clk') 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; -- cgit v1.2.3-58-ga151 From 9bd43a6184c2559032a2a8675c135abf7777a736 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:51 +0200 Subject: 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(-) (limited to 'drivers/clk') 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; -- cgit v1.2.3-58-ga151 From df4b6a4c3bf5b0bc0fb5c35af9ca6da9c78922ee Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:52 +0200 Subject: 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(-) (limited to 'drivers/clk') 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 = { -- cgit v1.2.3-58-ga151 From f922c560c95613f9aa45e135380bb78d3abbdb35 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:53 +0200 Subject: 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(-) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From 8a1f3ebc38fca949ad69feb1e536b71360e8cbb4 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:54 +0200 Subject: 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(-) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From 81df01518879d9d0ccce40564883ac0ba3299c47 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:55 +0200 Subject: 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(-) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From c1ce3509eca684e72d0910192d5549d01558b658 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:56 +0200 Subject: 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(-) (limited to 'drivers/clk') 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, -- cgit v1.2.3-58-ga151 From 3ea59ace7c0f475bf12f13b63a47a6983959d754 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:57 +0200 Subject: 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(-) (limited to 'drivers/clk') 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. -- cgit v1.2.3-58-ga151 From 23e114b6b7a03a98d27cf327f0d173ad2d219c13 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:58 +0200 Subject: 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(-) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From d4b4f1b6b97e56d49a69d6ee734f96f4d3d35762 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:40:59 +0200 Subject: 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(+) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From be1559f69768da4576f5b4b9073466e82c031153 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:00 +0200 Subject: 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(-) (limited to 'drivers/clk') 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; -- cgit v1.2.3-58-ga151 From 93d2725affd65686792f4b57e49ef660f3c8c0f9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:01 +0200 Subject: 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(-) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From 7dad8a613185320093de021ca8abba986bc043cb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:02 +0200 Subject: 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(-) (limited to 'drivers/clk') 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; -- cgit v1.2.3-58-ga151 From dbe01b4412914c7ce8fb11ea45bf67fafbffd068 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:03 +0200 Subject: 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(-) (limited to 'drivers/clk') 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. -- cgit v1.2.3-58-ga151 From b2683d069bcae4277332243850d07ac24be05ab2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:05 +0200 Subject: 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(-) (limited to 'drivers/clk') 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) -- cgit v1.2.3-58-ga151 From 0d46fafc0364688c54b4a9d21cee0cb2eabf43bd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:06 +0200 Subject: 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(-) (limited to 'drivers/clk') 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. -- cgit v1.2.3-58-ga151 From 56643d9ad2b4933d55f872f61195c1650f9958e9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 15 Jun 2020 10:41:07 +0200 Subject: 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(-) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From 6f3bcf56f8eec78e51cac8b3dd67ed7ec67e3e1e Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 16 Jun 2020 15:24:16 -0500 Subject: clk: socfpga: agilex: add nand_x_clk and nand_ecc_clk And the nand_x_clk and nand_ecc_clk. Make the nand_x_clk be the main clock that is feeding the NAND IP and correct it's parent to be the l4_mp_clk. Signed-off-by: Dinh Nguyen Link: https://lore.kernel.org/r/20200616202417.14376-2-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-agilex.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 699527f7e764..1b2e0ad01b24 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -294,8 +294,12 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 8, 0, 0, 0, 0, 0, 0}, { AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 9, 0, 0, 0, 0, 0, 0}, - { AGILEX_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0x7C, + { AGILEX_NAND_X_CLK, "nand_x_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 10, 0, 0, 0, 0, 0, 0}, + { AGILEX_NAND_CLK, "nand_clk", "nand_x_clk", NULL, 1, 0, 0x7C, + 10, 0, 0, 0, 0, 0, 4}, + { AGILEX_NAND_ECC_CLK, "nand_ecc_clk", "nand_x_clk", NULL, 1, 0, 0x7C, + 10, 0, 0, 0, 0, 0, 4}, }; static int agilex_clk_register_c_perip(const struct stratix10_perip_c_clock *clks, -- cgit v1.2.3-58-ga151 From 44a7f3e8222a7345b72a83a26d6d599bba815cf9 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Tue, 16 Jun 2020 15:24:17 -0500 Subject: clk: socfpga: agilex: mpu_l2ram_clk should be mpu_ccu_clk Preliminary documentation documented the mpu_l2ram_clk, but since then, the mpu_l2ram_clk is no longer documented. It's now referred to as mpu_ccu_clk. Signed-off-by: Dinh Nguyen Link: https://lore.kernel.org/r/20200616202417.14376-3-dinguyen@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-agilex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/clk') diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 1b2e0ad01b24..8fb12cbe0208 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -252,7 +252,7 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 0, 0, 0, 0, 0x30, 0, 0}, { AGILEX_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x24, 0, 0, 0, 0, 0, 0, 4}, - { AGILEX_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x24, + { AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24, 0, 0, 0, 0, 0, 0, 2}, { AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24, 1, 0x44, 0, 2, 0, 0, 0}, -- cgit v1.2.3-58-ga151 From ecd2bacfbbc4d7a2a1beb96fa7836a8ca6e4cf71 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Mon, 22 Jun 2020 09:58:10 +0530 Subject: 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 (limited to 'drivers/clk') 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"); -- cgit v1.2.3-58-ga151 From 5e77b4ef1b19a4ce4051ff2afb706ee675e4b412 Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Mon, 22 Jun 2020 09:58:12 +0530 Subject: 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 (limited to 'drivers/clk') 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"); -- cgit v1.2.3-58-ga151 From e8c849c2a8e8d300922399ac02065bebf53393a6 Mon Sep 17 00:00:00 2001 From: Sarang Mairal Date: Wed, 10 Jun 2020 21:19:41 -0500 Subject: 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(+) (limited to 'drivers/clk') 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; -- cgit v1.2.3-58-ga151 From b608013ac5b55a2e42d8734f29f9757b75d26165 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Mon, 22 Jun 2020 11:02:52 +0200 Subject: 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(+) (limited to 'drivers/clk') 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 -- cgit v1.2.3-58-ga151 From ed4a11807d2a35ccfc0d00371f20b826f670b5f2 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 16 Jun 2020 18:26:24 +0200 Subject: clk: renesas: cpg-mssr: Mark clocks as critical only if on at boot This allows us to add the RWDT clock to the list of critical clocks without keeping it enabled needlessly if not used. Changing the semantics of crit_mod_clks in this way is safe for the current user (INTC-AP) because it is never off at boot time. Signed-off-by: Ulrich Hecht Link: https://lore.kernel.org/r/20200616162626.27944-2-uli+renesas@fpond.eu Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/renesas-cpg-mssr.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index dcb6e2706d37..4648a829db66 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -416,14 +416,6 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, init.name = mod->name; init.ops = &cpg_mstp_clock_ops; init.flags = CLK_SET_RATE_PARENT; - for (i = 0; i < info->num_crit_mod_clks; i++) - if (id == info->crit_mod_clks[i]) { - dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n", - mod->name); - init.flags |= CLK_IS_CRITICAL; - break; - } - parent_name = __clk_get_name(parent); init.parent_names = &parent_name; init.num_parents = 1; @@ -432,6 +424,15 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod, clock->priv = priv; clock->hw.init = &init; + for (i = 0; i < info->num_crit_mod_clks; i++) + if (id == info->crit_mod_clks[i] && + cpg_mstp_clock_is_enabled(&clock->hw)) { + dev_dbg(dev, "MSTP %s setting CLK_IS_CRITICAL\n", + mod->name); + init.flags |= CLK_IS_CRITICAL; + break; + } + clk = clk_register(NULL, &clock->hw); if (IS_ERR(clk)) goto fail; -- cgit v1.2.3-58-ga151 From f23f1101ad0ef1acdc219d3364522166e2c711ce Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 16 Jun 2020 18:26:25 +0200 Subject: clk: renesas: rcar-gen3: Mark RWDT clocks as critical Ensures RWDT remains alert throughout the boot process if enabled. This patch applies the change to the following SoCs: r8a77950, r8a77951, r8a77960, r8a77961, r8a77965, r8a77970, r8a77980, r8a77990 and r8a77995. Signed-off-by: Ulrich Hecht Link: https://lore.kernel.org/r/20200616162626.27944-3-uli+renesas@fpond.eu Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a7795-cpg-mssr.c | 2 +- drivers/clk/renesas/r8a7796-cpg-mssr.c | 2 +- drivers/clk/renesas/r8a77965-cpg-mssr.c | 1 + drivers/clk/renesas/r8a77970-cpg-mssr.c | 2 +- drivers/clk/renesas/r8a77980-cpg-mssr.c | 2 +- drivers/clk/renesas/r8a77990-cpg-mssr.c | 1 + drivers/clk/renesas/r8a77995-cpg-mssr.c | 2 +- 7 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a7795-cpg-mssr.c b/drivers/clk/renesas/r8a7795-cpg-mssr.c index ff5b3020cb03..068018ae3c6e 100644 --- a/drivers/clk/renesas/r8a7795-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7795-cpg-mssr.c @@ -287,10 +287,10 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = { }; static const unsigned int r8a7795_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; - /* * CPG Clock Data */ diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index e8d466dbc7f9..2cd6e3876fbd 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -262,10 +262,10 @@ static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = { }; static const unsigned int r8a7796_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; - /* * CPG Clock Data */ diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index 7a05a2fc1cc6..2b55a06ac5cf 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -263,6 +263,7 @@ static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { }; static const unsigned int r8a77965_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; diff --git a/drivers/clk/renesas/r8a77970-cpg-mssr.c b/drivers/clk/renesas/r8a77970-cpg-mssr.c index cbed3769a100..0f59c84229a8 100644 --- a/drivers/clk/renesas/r8a77970-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77970-cpg-mssr.c @@ -165,10 +165,10 @@ static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = { }; static const unsigned int r8a77970_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; - /* * CPG Clock Data */ diff --git a/drivers/clk/renesas/r8a77980-cpg-mssr.c b/drivers/clk/renesas/r8a77980-cpg-mssr.c index 7227f675e61f..9fe372286c1e 100644 --- a/drivers/clk/renesas/r8a77980-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77980-cpg-mssr.c @@ -180,10 +180,10 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = { }; static const unsigned int r8a77980_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; - /* * CPG Clock Data */ diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c index 8eda2e3e2480..2b97ab61d044 100644 --- a/drivers/clk/renesas/r8a77990-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -245,6 +245,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { }; static const unsigned int r8a77990_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 056ebf3e70e2..5b4691117b47 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -183,10 +183,10 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { }; static const unsigned int r8a77995_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; - /* * CPG Clock Data */ -- cgit v1.2.3-58-ga151 From 52bc5ea6edde35bc65ed6ecd7639534e78002c74 Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Tue, 16 Jun 2020 18:26:26 +0200 Subject: clk: renesas: rzg2: Mark RWDT clocks as critical Ensures RWDT remains alert throughout the boot process if enabled. This patch applies the change to the following SoCs: r8a774a1, r8a774b1 and r8a774c0. Signed-off-by: Ulrich Hecht Link: https://lore.kernel.org/r/20200616162626.27944-4-uli+renesas@fpond.eu Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/r8a774a1-cpg-mssr.c | 1 + drivers/clk/renesas/r8a774b1-cpg-mssr.c | 1 + drivers/clk/renesas/r8a774c0-cpg-mssr.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c index e05bfa200480..fd54b9f625da 100644 --- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c @@ -237,6 +237,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = { }; static const unsigned int r8a774a1_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; diff --git a/drivers/clk/renesas/r8a774b1-cpg-mssr.c b/drivers/clk/renesas/r8a774b1-cpg-mssr.c index c9af70917312..f436691271ec 100644 --- a/drivers/clk/renesas/r8a774b1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774b1-cpg-mssr.c @@ -233,6 +233,7 @@ static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = { }; static const unsigned int r8a774b1_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c index f91e7a484753..9fc9fa9e531a 100644 --- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c @@ -238,6 +238,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = { }; static const unsigned int r8a774c0_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ MOD_CLK_ID(408), /* INTC-AP (GIC) */ }; -- cgit v1.2.3-58-ga151 From 59390282b7542c6050c1deaca0b2949180903175 Mon Sep 17 00:00:00 2001 From: Vincent Knecht Date: Sat, 13 Jun 2020 09:27:42 +0200 Subject: 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(+) (limited to 'drivers/clk') 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 -- cgit v1.2.3-58-ga151 From f491276a5168598758ea7fc381195e4ba9af39f8 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Wed, 3 Jun 2020 10:43:27 -0500 Subject: 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(-) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From 260249f929e81d3d5764117fdd6b9e43eb8fb1d5 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Wed, 3 Jun 2020 10:43:29 -0500 Subject: 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(+) (limited to 'drivers/clk') 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); -- cgit v1.2.3-58-ga151 From d4db5721f3c847df43b967d9f02994b15e4a48e6 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Sat, 20 Jun 2020 18:14:22 +0200 Subject: clk: meson: meson8b: Drop CLK_IS_CRITICAL from fclk_div2 Drop CLK_IS_CRITICAL from fclk_div2. This was added because we didn't know the relation between this clock and RGMII Ethernet. It turns out that fclk_div2 is used as "timing adjustment clock" to generate the RX delay on the MAC side - which was enabled by u-boot on Odriod-C1. When using the RX delay on the PHY side or not using a RX delay at all then this clock can be disabled. Signed-off-by: Martin Blumenstingl Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200620161422.24114-1-martin.blumenstingl@googlemail.com --- drivers/clk/meson/meson8b.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index edc09d050ecf..3d826711c820 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -293,13 +293,6 @@ static struct clk_regmap meson8b_fclk_div2 = { &meson8b_fclk_div2_div.hw }, .num_parents = 1, - /* - * FIXME: Ethernet with a RGMII PHYs is not working if - * fclk_div2 is disabled. it is currently unclear why this - * is. keep it enabled until the Ethernet driver knows how - * to manage this clock. - */ - .flags = CLK_IS_CRITICAL, }, }; -- cgit v1.2.3-58-ga151 From eb46f547a2fa9d5913c76066eab34efbd7f2252c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Fri, 26 Jun 2020 13:25:13 +0200 Subject: 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(+) (limited to 'drivers/clk') 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"); -- cgit v1.2.3-58-ga151 From dbb988b4e7eb924ffceaa2a7da6e794c868cb2f3 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 28 Jun 2020 02:30:55 +0000 Subject: 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(-) (limited to 'drivers/clk') 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); } -- cgit v1.2.3-58-ga151 From e653b41131f60054dbfa0c7431613d6aeaee2212 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Mon, 29 Jun 2020 22:39:03 +0200 Subject: clk: meson: meson8b: add the vclk_en gate clock HHI_VID_CLK_CNTL[19] is documented as CLK_EN0. This description is the same in the public S912 datasheet and the GXBB driver calls this gate "vclk". Add this gate clock to the Meson8/Meson8b/Meson8m2 clock controller because it's needed to make the video output work. Signed-off-by: Martin Blumenstingl Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200629203904.2989007-2-martin.blumenstingl@googlemail.com --- drivers/clk/meson/meson8b.c | 30 +++++++++++++++++++++++++----- drivers/clk/meson/meson8b.h | 3 ++- 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 3d826711c820..d5b90d61a530 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -1204,6 +1204,22 @@ static struct clk_regmap meson8b_vclk_in_en = { }, }; +static struct clk_regmap meson8b_vclk_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VID_CLK_CNTL, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk_en", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk_in_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + static struct clk_regmap meson8b_vclk_div1_gate = { .data = &(struct clk_regmap_gate_data){ .offset = HHI_VID_CLK_CNTL, @@ -1213,7 +1229,7 @@ static struct clk_regmap meson8b_vclk_div1_gate = { .name = "vclk_div1_en", .ops = &clk_regmap_gate_ro_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk_in_en.hw + &meson8b_vclk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1227,7 +1243,7 @@ static struct clk_fixed_factor meson8b_vclk_div2_div = { .name = "vclk_div2", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk_in_en.hw + &meson8b_vclk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1257,7 +1273,7 @@ static struct clk_fixed_factor meson8b_vclk_div4_div = { .name = "vclk_div4", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk_in_en.hw + &meson8b_vclk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1287,7 +1303,7 @@ static struct clk_fixed_factor meson8b_vclk_div6_div = { .name = "vclk_div6", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk_in_en.hw + &meson8b_vclk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1317,7 +1333,7 @@ static struct clk_fixed_factor meson8b_vclk_div12_div = { .name = "vclk_div12", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk_in_en.hw + &meson8b_vclk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -2820,6 +2836,7 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = { [CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw, [CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw, [CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw, + [CLKID_VCLK_EN] = &meson8b_vclk_en.hw, [CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw, [CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw, [CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw, @@ -3025,6 +3042,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw, [CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw, [CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw, + [CLKID_VCLK_EN] = &meson8b_vclk_en.hw, [CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw, [CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw, [CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw, @@ -3241,6 +3259,7 @@ static struct clk_hw_onecell_data meson8m2_hw_onecell_data = { [CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw, [CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw, [CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw, + [CLKID_VCLK_EN] = &meson8b_vclk_en.hw, [CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw, [CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw, [CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw, @@ -3443,6 +3462,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_vid_pll_final_div, &meson8b_vclk_in_sel, &meson8b_vclk_in_en, + &meson8b_vclk_en, &meson8b_vclk_div1_gate, &meson8b_vclk_div2_div_gate, &meson8b_vclk_div4_div_gate, diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index cd38ae2a9cb5..c8ab2a632295 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -180,8 +180,9 @@ #define CLKID_CTS_AMCLK_DIV 208 #define CLKID_CTS_MCLK_I958_SEL 210 #define CLKID_CTS_MCLK_I958_DIV 211 +#define CLKID_VCLK_EN 214 -#define CLK_NR_CLKS 214 +#define CLK_NR_CLKS 215 /* * include the CLKID and RESETID that have -- cgit v1.2.3-58-ga151 From 2568528f55356a2f20f80a18244d3e235cbd2cab Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Mon, 29 Jun 2020 22:39:04 +0200 Subject: clk: meson: meson8b: add the vclk2_en gate clock HHI_VIID_CLK_CNTL[19] is not part of the public S805 datasheet. However, the GXBB driver defines this bit as a gate called "vclk2" and in the 3.10 kernel GPL code dump the following line can found: WRITE_LCD_CBUS_REG_BITS(HHI_VIID_CLK_CNTL, 0, 19, 1); //disable vclk2_en Add this gate clock to the Meson8/Meson8b/Meson8m2 clock controller to complete the VCLK2 clock tree. Signed-off-by: Martin Blumenstingl Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20200629203904.2989007-3-martin.blumenstingl@googlemail.com --- drivers/clk/meson/meson8b.c | 30 +++++++++++++++++++++++++----- drivers/clk/meson/meson8b.h | 3 ++- 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index d5b90d61a530..862f0756b50f 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -1387,6 +1387,22 @@ static struct clk_regmap meson8b_vclk2_clk_in_en = { }, }; +static struct clk_regmap meson8b_vclk2_clk_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = HHI_VIID_CLK_DIV, + .bit_idx = 19, + }, + .hw.init = &(struct clk_init_data){ + .name = "vclk2_en", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &meson8b_vclk2_clk_in_en.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + static struct clk_regmap meson8b_vclk2_div1_gate = { .data = &(struct clk_regmap_gate_data){ .offset = HHI_VIID_CLK_DIV, @@ -1396,7 +1412,7 @@ static struct clk_regmap meson8b_vclk2_div1_gate = { .name = "vclk2_div1_en", .ops = &clk_regmap_gate_ro_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk2_clk_in_en.hw + &meson8b_vclk2_clk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1410,7 +1426,7 @@ static struct clk_fixed_factor meson8b_vclk2_div2_div = { .name = "vclk2_div2", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk2_clk_in_en.hw + &meson8b_vclk2_clk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1440,7 +1456,7 @@ static struct clk_fixed_factor meson8b_vclk2_div4_div = { .name = "vclk2_div4", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk2_clk_in_en.hw + &meson8b_vclk2_clk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1470,7 +1486,7 @@ static struct clk_fixed_factor meson8b_vclk2_div6_div = { .name = "vclk2_div6", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk2_clk_in_en.hw + &meson8b_vclk2_clk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -1500,7 +1516,7 @@ static struct clk_fixed_factor meson8b_vclk2_div12_div = { .name = "vclk2_div12", .ops = &clk_fixed_factor_ops, .parent_hws = (const struct clk_hw *[]) { - &meson8b_vclk2_clk_in_en.hw + &meson8b_vclk2_clk_en.hw }, .num_parents = 1, .flags = CLK_SET_RATE_PARENT, @@ -2848,6 +2864,7 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = { [CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw, [CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw, [CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw, + [CLKID_VCLK2_EN] = &meson8b_vclk2_clk_en.hw, [CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw, [CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw, [CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw, @@ -3054,6 +3071,7 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { [CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw, [CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw, [CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw, + [CLKID_VCLK2_EN] = &meson8b_vclk2_clk_en.hw, [CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw, [CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw, [CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw, @@ -3271,6 +3289,7 @@ static struct clk_hw_onecell_data meson8m2_hw_onecell_data = { [CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw, [CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw, [CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw, + [CLKID_VCLK2_EN] = &meson8b_vclk2_clk_en.hw, [CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw, [CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw, [CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw, @@ -3470,6 +3489,7 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = { &meson8b_vclk_div12_div_gate, &meson8b_vclk2_in_sel, &meson8b_vclk2_clk_in_en, + &meson8b_vclk2_clk_en, &meson8b_vclk2_div1_gate, &meson8b_vclk2_div2_div_gate, &meson8b_vclk2_div4_div_gate, diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index c8ab2a632295..699c5bc7c817 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -181,8 +181,9 @@ #define CLKID_CTS_MCLK_I958_SEL 210 #define CLKID_CTS_MCLK_I958_DIV 211 #define CLKID_VCLK_EN 214 +#define CLKID_VCLK2_EN 215 -#define CLK_NR_CLKS 215 +#define CLK_NR_CLKS 216 /* * include the CLKID and RESETID that have -- cgit v1.2.3-58-ga151 From 03e342dc45c9ec07303953d4e4af11879be36609 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 3 Jul 2020 10:49:42 +0200 Subject: 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 (limited to 'drivers/clk') 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"); -- cgit v1.2.3-58-ga151 From 5f1d8970d4cdba6ef3b2f3f11ef15edd62ce551a Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Fri, 3 Jul 2020 19:51:14 +0200 Subject: Replace HTTP links with HTTPS ones: Common CLK framework Rationale: Reduces attack surface on kernel devs opening the links for MITM as HTTPS traffic is much harder to manipulate. Deterministic algorithm: For each file: If not .svg: For each line: If doesn't contain `\bxmlns\b`: For each link, `\bhttp://[^# \t\r\n]*(?:\w|/)`: If both the HTTP and HTTPS versions return 200 OK and serve the same content: Replace HTTP with HTTPS. Signed-off-by: Alexander A. Klimov Link: https://lore.kernel.org/r/20200703175114.15027-1-grandmaster@al2klimov.de Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/clock-bindings.txt | 2 +- Documentation/devicetree/bindings/clock/silabs,si514.txt | 2 +- Documentation/devicetree/bindings/clock/silabs,si5351.txt | 2 +- Documentation/devicetree/bindings/clock/silabs,si570.txt | 4 ++-- Documentation/devicetree/bindings/clock/ti,cdce706.txt | 2 +- Documentation/devicetree/bindings/clock/ti,cdce925.txt | 8 ++++---- drivers/clk/clk-cdce706.c | 2 +- drivers/clk/clk-gpio.c | 2 +- drivers/clk/clk-si5351.c | 4 ++-- drivers/clk/keystone/sci-clk.c | 2 +- drivers/clk/keystone/syscon-clk.c | 2 +- drivers/clk/meson/meson8b.h | 2 +- drivers/clk/versatile/icst.c | 2 +- drivers/clk/versatile/icst.h | 2 +- 14 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/clk') diff --git a/Documentation/devicetree/bindings/clock/clock-bindings.txt b/Documentation/devicetree/bindings/clock/clock-bindings.txt index 8a55fdcf96ee..f2ea53832ac6 100644 --- a/Documentation/devicetree/bindings/clock/clock-bindings.txt +++ b/Documentation/devicetree/bindings/clock/clock-bindings.txt @@ -9,7 +9,7 @@ specifier is an array of zero, one or more cells identifying the clock output on a device. The length of a clock specifier is defined by the value of a #clock-cells property in the clock provider node. -[1] http://patchwork.ozlabs.org/patch/31551/ +[1] https://patchwork.ozlabs.org/patch/31551/ ==Clock providers== diff --git a/Documentation/devicetree/bindings/clock/silabs,si514.txt b/Documentation/devicetree/bindings/clock/silabs,si514.txt index ea1a9dbc63b6..a4f28ec86f35 100644 --- a/Documentation/devicetree/bindings/clock/silabs,si514.txt +++ b/Documentation/devicetree/bindings/clock/silabs,si514.txt @@ -6,7 +6,7 @@ found in the datasheet[2]. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Si514 datasheet - http://www.silabs.com/Support%20Documents/TechnicalDocs/si514.pdf + https://www.silabs.com/Support%20Documents/TechnicalDocs/si514.pdf Required properties: - compatible: Shall be "silabs,si514" diff --git a/Documentation/devicetree/bindings/clock/silabs,si5351.txt b/Documentation/devicetree/bindings/clock/silabs,si5351.txt index f00191cad8cd..8fe6f80afade 100644 --- a/Documentation/devicetree/bindings/clock/silabs,si5351.txt +++ b/Documentation/devicetree/bindings/clock/silabs,si5351.txt @@ -2,7 +2,7 @@ Binding for Silicon Labs Si5351a/b/c programmable i2c clock generator. Reference [1] Si5351A/B/C Data Sheet - http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf + https://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf The Si5351a/b/c are programmable i2c clock generators with up to 8 output clocks. Si5351a also has a reduced pin-count package (MSOP10) where only diff --git a/Documentation/devicetree/bindings/clock/silabs,si570.txt b/Documentation/devicetree/bindings/clock/silabs,si570.txt index c09f21e1d98f..901935e929d2 100644 --- a/Documentation/devicetree/bindings/clock/silabs,si570.txt +++ b/Documentation/devicetree/bindings/clock/silabs,si570.txt @@ -7,9 +7,9 @@ found in the data sheets[2][3]. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt [2] Si570/571 Data Sheet - http://www.silabs.com/Support%20Documents/TechnicalDocs/si570.pdf + https://www.silabs.com/Support%20Documents/TechnicalDocs/si570.pdf [3] Si598/599 Data Sheet - http://www.silabs.com/Support%20Documents/TechnicalDocs/si598-99.pdf + https://www.silabs.com/Support%20Documents/TechnicalDocs/si598-99.pdf Required properties: - compatible: Shall be one of "silabs,si570", "silabs,si571", diff --git a/Documentation/devicetree/bindings/clock/ti,cdce706.txt b/Documentation/devicetree/bindings/clock/ti,cdce706.txt index 959d96632f5d..21c3ff764788 100644 --- a/Documentation/devicetree/bindings/clock/ti,cdce706.txt +++ b/Documentation/devicetree/bindings/clock/ti,cdce706.txt @@ -1,7 +1,7 @@ Bindings for Texas Instruments CDCE706 programmable 3-PLL clock synthesizer/multiplier/divider. -Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf +Reference: https://www.ti.com/lit/ds/symlink/cdce706.pdf I2C device node required properties: - compatible: shall be "ti,cdce706". diff --git a/Documentation/devicetree/bindings/clock/ti,cdce925.txt b/Documentation/devicetree/bindings/clock/ti,cdce925.txt index 26544c85202a..df42ab72718f 100644 --- a/Documentation/devicetree/bindings/clock/ti,cdce925.txt +++ b/Documentation/devicetree/bindings/clock/ti,cdce925.txt @@ -4,10 +4,10 @@ Reference This binding uses the common clock binding[1]. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt -[2] http://www.ti.com/product/cdce913 -[3] http://www.ti.com/product/cdce925 -[4] http://www.ti.com/product/cdce937 -[5] http://www.ti.com/product/cdce949 +[2] https://www.ti.com/product/cdce913 +[3] https://www.ti.com/product/cdce925 +[4] https://www.ti.com/product/cdce937 +[5] https://www.ti.com/product/cdce949 The driver provides clock sources for each output Y1 through Y5. diff --git a/drivers/clk/clk-cdce706.c b/drivers/clk/clk-cdce706.c index 239102e37e2f..c91e9096b070 100644 --- a/drivers/clk/clk-cdce706.c +++ b/drivers/clk/clk-cdce706.c @@ -4,7 +4,7 @@ * * Copyright (c) 2014 Cadence Design Systems Inc. * - * Reference: http://www.ti.com/lit/ds/symlink/cdce706.pdf + * Reference: https://www.ti.com/lit/ds/symlink/cdce706.pdf */ #include diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index 70397b4b5ffe..38755a241ab7 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2013 - 2014 Texas Instruments Incorporated - https://www.ti.com * * Authors: * Jyri Sarha diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c index 71de3618e508..1e1702e609cb 100644 --- a/drivers/clk/clk-si5351.c +++ b/drivers/clk/clk-si5351.c @@ -7,9 +7,9 @@ * * References: * [1] "Si5351A/B/C Data Sheet" - * http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf + * https://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf * [2] "Manually Generating an Si5351 Register Map" - * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf + * https://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf */ #include diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index 7edf8c8432b6..2ad26cb927fd 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -1,7 +1,7 @@ /* * SCI Clock driver for keystone based devices * - * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2015-2016 Texas Instruments Incorporated - https://www.ti.com/ * Tero Kristo * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c index 8d7dbea3bd30..5b3d36462174 100644 --- a/drivers/clk/keystone/syscon-clk.c +++ b/drivers/clk/keystone/syscon-clk.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/ */ #include diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h index cd38ae2a9cb5..3958b580d942 100644 --- a/drivers/clk/meson/meson8b.h +++ b/drivers/clk/meson/meson8b.h @@ -17,7 +17,7 @@ * blocks below. Those offsets must be multiplied by 4 before adding them to * the base address to get the right value * - * [0] http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf + * [0] https://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf */ #define HHI_GP_PLL_CNTL 0x40 /* 0x10 offset in data sheet */ #define HHI_GP_PLL_CNTL2 0x44 /* 0x11 offset in data sheet */ diff --git a/drivers/clk/versatile/icst.c b/drivers/clk/versatile/icst.c index ba4b2d22ec97..307cb3774f87 100644 --- a/drivers/clk/versatile/icst.c +++ b/drivers/clk/versatile/icst.c @@ -5,7 +5,7 @@ * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. * * Support functions for calculating clocks/divisors for the ICST307 - * clock generators. See http://www.idt.com/ for more information + * clock generators. See https://www.idt.com/ for more information * on these devices. * * This is an almost identical implementation to the ICST525 clock generator. diff --git a/drivers/clk/versatile/icst.h b/drivers/clk/versatile/icst.h index 73a3062b4535..29622768b02a 100644 --- a/drivers/clk/versatile/icst.h +++ b/drivers/clk/versatile/icst.h @@ -3,7 +3,7 @@ * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. * * Support functions for calculating clocks/divisors for the ICST - * clock generators. See http://www.idt.com/ for more information + * clock generators. See https://www.idt.com/ for more information * on these devices. */ #ifndef ICST_H -- cgit v1.2.3-58-ga151 From f0cfcf1ade201dcfd3365f231efc90e846fa46df Mon Sep 17 00:00:00 2001 From: Sivaprakash Murugesan Date: Sun, 5 Jul 2020 14:47:55 +0530 Subject: 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(+) (limited to 'drivers/clk') 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 }, -- cgit v1.2.3-58-ga151 From b4297844995f380588e6f935a2f98c399129a9b2 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Wed, 24 Jun 2020 01:00:18 +0200 Subject: 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(+) (limited to 'drivers/clk') 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 -- cgit v1.2.3-58-ga151 From b545b9c393cb4486a7b70ef2fd8d0c8451872342 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 14 Jun 2020 14:51:40 +0300 Subject: clk: Drop duplicate selection in Kconfig There is no need to select RATIONAL in individual drivers, since common clock symbol does it already. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20200614115140.41262-1-andriy.shevchenko@linux.intel.com Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/clk') diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 69934c0c3dd8..42301ebf06e9 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -120,7 +120,6 @@ config COMMON_CLK_SI5351 tristate "Clock driver for SiLabs 5351A/B/C" depends on I2C select REGMAP_I2C - select RATIONAL help This driver supports Silicon Labs 5351A/B/C programmable clock generators. @@ -162,7 +161,6 @@ config COMMON_CLK_CDCE706 tristate "Clock driver for TI CDCE706 clock synthesizer" depends on I2C select REGMAP_I2C - select RATIONAL help This driver supports TI CDCE706 programmable 3-PLL clock synthesizer. -- cgit v1.2.3-58-ga151 From c8a53fa1d211936ddcabf82ff991c18672b3d63a Mon Sep 17 00:00:00 2001 From: Marian-Cristian Rotariu Date: Tue, 7 Jul 2020 17:18:10 +0100 Subject: clk: renesas: cpg-mssr: Add r8a774e1 support Add support for the RZ/G2H (R8A774E1) SoC to the Renesas Clock Pulse Generator / Module Standby and Software Reset driver. Signed-off-by: Marian-Cristian Rotariu Signed-off-by: Lad Prabhakar Link: https://lore.kernel.org/r/1594138692-16816-11-git-send-email-prabhakar.mahadev-lad.rj@bp.renesas.com [geert: Mark RWDT critical, cfr. commit f23f1101ad0ef1ac ("clk: renesas: rcar-gen3: Mark RWDT clocks as critical")] Signed-off-by: Geert Uytterhoeven --- drivers/clk/renesas/Kconfig | 5 + drivers/clk/renesas/Makefile | 1 + drivers/clk/renesas/r8a774e1-cpg-mssr.c | 349 ++++++++++++++++++++++++++++++++ drivers/clk/renesas/renesas-cpg-mssr.c | 6 + drivers/clk/renesas/renesas-cpg-mssr.h | 1 + 5 files changed, 362 insertions(+) create mode 100644 drivers/clk/renesas/r8a774e1-cpg-mssr.c (limited to 'drivers/clk') diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 9eb79bf90643..28e8730ce263 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -15,6 +15,7 @@ config CLK_RENESAS select CLK_R8A774A1 if ARCH_R8A774A1 select CLK_R8A774B1 if ARCH_R8A774B1 select CLK_R8A774C0 if ARCH_R8A774C0 + select CLK_R8A774E1 if ARCH_R8A774E1 select CLK_R8A7778 if ARCH_R8A7778 select CLK_R8A7779 if ARCH_R8A7779 select CLK_R8A7790 if ARCH_R8A7790 @@ -84,6 +85,10 @@ config CLK_R8A774C0 bool "RZ/G2E clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG +config CLK_R8A774E1 + bool "RZ/G2H clock support" if COMPILE_TEST + select CLK_RCAR_GEN3_CPG + config CLK_R8A7778 bool "R-Car M1A clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index a4066f9b34ef..c7c03ab9a6a3 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_CLK_R8A77470) += r8a77470-cpg-mssr.o obj-$(CONFIG_CLK_R8A774A1) += r8a774a1-cpg-mssr.o obj-$(CONFIG_CLK_R8A774B1) += r8a774b1-cpg-mssr.o obj-$(CONFIG_CLK_R8A774C0) += r8a774c0-cpg-mssr.o +obj-$(CONFIG_CLK_R8A774E1) += r8a774e1-cpg-mssr.o obj-$(CONFIG_CLK_R8A7778) += clk-r8a7778.o obj-$(CONFIG_CLK_R8A7779) += clk-r8a7779.o obj-$(CONFIG_CLK_R8A7790) += r8a7790-cpg-mssr.o diff --git a/drivers/clk/renesas/r8a774e1-cpg-mssr.c b/drivers/clk/renesas/r8a774e1-cpg-mssr.c new file mode 100644 index 000000000000..b96c486abb44 --- /dev/null +++ b/drivers/clk/renesas/r8a774e1-cpg-mssr.c @@ -0,0 +1,349 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * r8a774e1 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2020 Renesas Electronics Corp. + * + * Based on r8a7795-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + */ + +#include +#include +#include +#include + +#include + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A774E1_CLK_CANFD, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL0, + CLK_PLL1, + CLK_PLL2, + CLK_PLL3, + CLK_PLL4, + CLK_PLL1_DIV2, + CLK_PLL1_DIV4, + CLK_S0, + CLK_S1, + CLK_S2, + CLK_S3, + CLK_SDSRC, + CLK_RPCSRC, + CLK_RINT, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +static const struct cpg_core_clk r8a774e1_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), + DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), + DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN), + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), + DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1), + DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A774E1_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774E1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774E1_CLK_RPC), + + DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), + + /* Core Clock Outputs */ + DEF_GEN3_Z("z", R8A774E1_CLK_Z, CLK_TYPE_GEN3_Z, CLK_PLL0, 2, 8), + DEF_GEN3_Z("z2", R8A774E1_CLK_Z2, CLK_TYPE_GEN3_Z, CLK_PLL2, 2, 0), + DEF_FIXED("ztr", R8A774E1_CLK_ZTR, CLK_PLL1_DIV2, 6, 1), + DEF_FIXED("ztrd2", R8A774E1_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1), + DEF_FIXED("zt", R8A774E1_CLK_ZT, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("zx", R8A774E1_CLK_ZX, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED("s0d1", R8A774E1_CLK_S0D1, CLK_S0, 1, 1), + DEF_FIXED("s0d2", R8A774E1_CLK_S0D2, CLK_S0, 2, 1), + DEF_FIXED("s0d3", R8A774E1_CLK_S0D3, CLK_S0, 3, 1), + DEF_FIXED("s0d4", R8A774E1_CLK_S0D4, CLK_S0, 4, 1), + DEF_FIXED("s0d6", R8A774E1_CLK_S0D6, CLK_S0, 6, 1), + DEF_FIXED("s0d8", R8A774E1_CLK_S0D8, CLK_S0, 8, 1), + DEF_FIXED("s0d12", R8A774E1_CLK_S0D12, CLK_S0, 12, 1), + DEF_FIXED("s1d2", R8A774E1_CLK_S1D2, CLK_S1, 2, 1), + DEF_FIXED("s1d4", R8A774E1_CLK_S1D4, CLK_S1, 4, 1), + DEF_FIXED("s2d1", R8A774E1_CLK_S2D1, CLK_S2, 1, 1), + DEF_FIXED("s2d2", R8A774E1_CLK_S2D2, CLK_S2, 2, 1), + DEF_FIXED("s2d4", R8A774E1_CLK_S2D4, CLK_S2, 4, 1), + DEF_FIXED("s3d1", R8A774E1_CLK_S3D1, CLK_S3, 1, 1), + DEF_FIXED("s3d2", R8A774E1_CLK_S3D2, CLK_S3, 2, 1), + DEF_FIXED("s3d4", R8A774E1_CLK_S3D4, CLK_S3, 4, 1), + + DEF_GEN3_SD("sd0", R8A774E1_CLK_SD0, CLK_SDSRC, 0x074), + DEF_GEN3_SD("sd1", R8A774E1_CLK_SD1, CLK_SDSRC, 0x078), + DEF_GEN3_SD("sd2", R8A774E1_CLK_SD2, CLK_SDSRC, 0x268), + DEF_GEN3_SD("sd3", R8A774E1_CLK_SD3, CLK_SDSRC, 0x26c), + + DEF_FIXED("cl", R8A774E1_CLK_CL, CLK_PLL1_DIV2, 48, 1), + DEF_FIXED("cr", R8A774E1_CLK_CR, CLK_PLL1_DIV4, 2, 1), + DEF_FIXED("cp", R8A774E1_CLK_CP, CLK_EXTAL, 2, 1), + DEF_FIXED("cpex", R8A774E1_CLK_CPEX, CLK_EXTAL, 2, 1), + + DEF_DIV6P1("canfd", R8A774E1_CLK_CANFD, CLK_PLL1_DIV4, 0x244), + DEF_DIV6P1("csi0", R8A774E1_CLK_CSI0, CLK_PLL1_DIV4, 0x00c), + DEF_DIV6P1("mso", R8A774E1_CLK_MSO, CLK_PLL1_DIV4, 0x014), + DEF_DIV6P1("hdmi", R8A774E1_CLK_HDMI, CLK_PLL1_DIV4, 0x250), + + DEF_GEN3_OSC("osc", R8A774E1_CLK_OSC, CLK_EXTAL, 8), + + DEF_BASE("r", R8A774E1_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT), +}; + +static const struct mssr_mod_clk r8a774e1_mod_clks[] __initconst = { + DEF_MOD("fdp1-1", 118, R8A774E1_CLK_S0D1), + DEF_MOD("fdp1-0", 119, R8A774E1_CLK_S0D1), + DEF_MOD("tmu4", 121, R8A774E1_CLK_S0D6), + DEF_MOD("tmu3", 122, R8A774E1_CLK_S3D2), + DEF_MOD("tmu2", 123, R8A774E1_CLK_S3D2), + DEF_MOD("tmu1", 124, R8A774E1_CLK_S3D2), + DEF_MOD("tmu0", 125, R8A774E1_CLK_CP), + DEF_MOD("vcplf", 130, R8A774E1_CLK_S2D1), + DEF_MOD("vdpb", 131, R8A774E1_CLK_S2D1), + DEF_MOD("scif5", 202, R8A774E1_CLK_S3D4), + DEF_MOD("scif4", 203, R8A774E1_CLK_S3D4), + DEF_MOD("scif3", 204, R8A774E1_CLK_S3D4), + DEF_MOD("scif1", 206, R8A774E1_CLK_S3D4), + DEF_MOD("scif0", 207, R8A774E1_CLK_S3D4), + DEF_MOD("msiof3", 208, R8A774E1_CLK_MSO), + DEF_MOD("msiof2", 209, R8A774E1_CLK_MSO), + DEF_MOD("msiof1", 210, R8A774E1_CLK_MSO), + DEF_MOD("msiof0", 211, R8A774E1_CLK_MSO), + DEF_MOD("sys-dmac2", 217, R8A774E1_CLK_S3D1), + DEF_MOD("sys-dmac1", 218, R8A774E1_CLK_S3D1), + DEF_MOD("sys-dmac0", 219, R8A774E1_CLK_S0D3), + DEF_MOD("cmt3", 300, R8A774E1_CLK_R), + DEF_MOD("cmt2", 301, R8A774E1_CLK_R), + DEF_MOD("cmt1", 302, R8A774E1_CLK_R), + DEF_MOD("cmt0", 303, R8A774E1_CLK_R), + DEF_MOD("tpu0", 304, R8A774E1_CLK_S3D4), + DEF_MOD("scif2", 310, R8A774E1_CLK_S3D4), + DEF_MOD("sdif3", 311, R8A774E1_CLK_SD3), + DEF_MOD("sdif2", 312, R8A774E1_CLK_SD2), + DEF_MOD("sdif1", 313, R8A774E1_CLK_SD1), + DEF_MOD("sdif0", 314, R8A774E1_CLK_SD0), + DEF_MOD("pcie1", 318, R8A774E1_CLK_S3D1), + DEF_MOD("pcie0", 319, R8A774E1_CLK_S3D1), + DEF_MOD("usb3-if0", 328, R8A774E1_CLK_S3D1), + DEF_MOD("usb-dmac0", 330, R8A774E1_CLK_S3D1), + DEF_MOD("usb-dmac1", 331, R8A774E1_CLK_S3D1), + DEF_MOD("rwdt", 402, R8A774E1_CLK_R), + DEF_MOD("intc-ex", 407, R8A774E1_CLK_CP), + DEF_MOD("intc-ap", 408, R8A774E1_CLK_S0D3), + DEF_MOD("audmac1", 501, R8A774E1_CLK_S1D2), + DEF_MOD("audmac0", 502, R8A774E1_CLK_S1D2), + DEF_MOD("hscif4", 516, R8A774E1_CLK_S3D1), + DEF_MOD("hscif3", 517, R8A774E1_CLK_S3D1), + DEF_MOD("hscif2", 518, R8A774E1_CLK_S3D1), + DEF_MOD("hscif1", 519, R8A774E1_CLK_S3D1), + DEF_MOD("hscif0", 520, R8A774E1_CLK_S3D1), + DEF_MOD("thermal", 522, R8A774E1_CLK_CP), + DEF_MOD("pwm", 523, R8A774E1_CLK_S0D12), + DEF_MOD("fcpvd1", 602, R8A774E1_CLK_S0D2), + DEF_MOD("fcpvd0", 603, R8A774E1_CLK_S0D2), + DEF_MOD("fcpvb1", 606, R8A774E1_CLK_S0D1), + DEF_MOD("fcpvb0", 607, R8A774E1_CLK_S0D1), + DEF_MOD("fcpvi1", 610, R8A774E1_CLK_S0D1), + DEF_MOD("fcpvi0", 611, R8A774E1_CLK_S0D1), + DEF_MOD("fcpf1", 614, R8A774E1_CLK_S0D1), + DEF_MOD("fcpf0", 615, R8A774E1_CLK_S0D1), + DEF_MOD("fcpcs", 619, R8A774E1_CLK_S0D1), + DEF_MOD("vspd1", 622, R8A774E1_CLK_S0D2), + DEF_MOD("vspd0", 623, R8A774E1_CLK_S0D2), + DEF_MOD("vspbc", 624, R8A774E1_CLK_S0D1), + DEF_MOD("vspbd", 626, R8A774E1_CLK_S0D1), + DEF_MOD("vspi1", 630, R8A774E1_CLK_S0D1), + DEF_MOD("vspi0", 631, R8A774E1_CLK_S0D1), + DEF_MOD("ehci1", 702, R8A774E1_CLK_S3D2), + DEF_MOD("ehci0", 703, R8A774E1_CLK_S3D2), + DEF_MOD("hsusb", 704, R8A774E1_CLK_S3D2), + DEF_MOD("csi20", 714, R8A774E1_CLK_CSI0), + DEF_MOD("csi40", 716, R8A774E1_CLK_CSI0), + DEF_MOD("du3", 721, R8A774E1_CLK_S2D1), + DEF_MOD("du1", 723, R8A774E1_CLK_S2D1), + DEF_MOD("du0", 724, R8A774E1_CLK_S2D1), + DEF_MOD("lvds", 727, R8A774E1_CLK_S0D4), + DEF_MOD("hdmi0", 729, R8A774E1_CLK_HDMI), + DEF_MOD("vin7", 804, R8A774E1_CLK_S0D2), + DEF_MOD("vin6", 805, R8A774E1_CLK_S0D2), + DEF_MOD("vin5", 806, R8A774E1_CLK_S0D2), + DEF_MOD("vin4", 807, R8A774E1_CLK_S0D2), + DEF_MOD("vin3", 808, R8A774E1_CLK_S0D2), + DEF_MOD("vin2", 809, R8A774E1_CLK_S0D2), + DEF_MOD("vin1", 810, R8A774E1_CLK_S0D2), + DEF_MOD("vin0", 811, R8A774E1_CLK_S0D2), + DEF_MOD("etheravb", 812, R8A774E1_CLK_S0D6), + DEF_MOD("sata0", 815, R8A774E1_CLK_S3D2), + DEF_MOD("gpio7", 905, R8A774E1_CLK_S3D4), + DEF_MOD("gpio6", 906, R8A774E1_CLK_S3D4), + DEF_MOD("gpio5", 907, R8A774E1_CLK_S3D4), + DEF_MOD("gpio4", 908, R8A774E1_CLK_S3D4), + DEF_MOD("gpio3", 909, R8A774E1_CLK_S3D4), + DEF_MOD("gpio2", 910, R8A774E1_CLK_S3D4), + DEF_MOD("gpio1", 911, R8A774E1_CLK_S3D4), + DEF_MOD("gpio0", 912, R8A774E1_CLK_S3D4), + DEF_MOD("can-fd", 914, R8A774E1_CLK_S3D2), + DEF_MOD("can-if1", 915, R8A774E1_CLK_S3D4), + DEF_MOD("can-if0", 916, R8A774E1_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774E1_CLK_RPCD2), + DEF_MOD("i2c6", 918, R8A774E1_CLK_S0D6), + DEF_MOD("i2c5", 919, R8A774E1_CLK_S0D6), + DEF_MOD("adg", 922, R8A774E1_CLK_S0D1), + DEF_MOD("i2c-dvfs", 926, R8A774E1_CLK_CP), + DEF_MOD("i2c4", 927, R8A774E1_CLK_S0D6), + DEF_MOD("i2c3", 928, R8A774E1_CLK_S0D6), + DEF_MOD("i2c2", 929, R8A774E1_CLK_S3D2), + DEF_MOD("i2c1", 930, R8A774E1_CLK_S3D2), + DEF_MOD("i2c0", 931, R8A774E1_CLK_S3D2), + DEF_MOD("ssi-all", 1005, R8A774E1_CLK_S3D4), + DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)), + DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)), + DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)), + DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)), + DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)), + DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)), + DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)), + DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)), + DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)), + DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)), + DEF_MOD("scu-all", 1017, R8A774E1_CLK_S3D4), + DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)), + DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)), + DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)), + DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)), + DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)), + DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)), + DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)), + DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)), + DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)), + DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)), + DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)), + DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)), + DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)), +}; + +static const unsigned int r8a774e1_crit_mod_clks[] __initconst = { + MOD_CLK_ID(402), /* RWDT */ + MOD_CLK_ID(408), /* INTC-AP (GIC) */ +}; + +/* + * CPG Clock Data + */ + +/* + * MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4 OSC + * 14 13 19 17 (MHz) + *------------------------------------------------------------------------- + * 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144 /16 + * 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144 /16 + * 0 0 1 0 Prohibited setting + * 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144 /16 + * 0 1 0 0 20 x 1 x150 x160 x120 x160 x120 /19 + * 0 1 0 1 20 x 1 x150 x160 x120 x106 x120 /19 + * 0 1 1 0 Prohibited setting + * 0 1 1 1 20 x 1 x150 x160 x120 x160 x120 /19 + * 1 0 0 0 25 x 1 x120 x128 x96 x128 x96 /24 + * 1 0 0 1 25 x 1 x120 x128 x96 x84 x96 /24 + * 1 0 1 0 Prohibited setting + * 1 0 1 1 25 x 1 x120 x128 x96 x128 x96 /24 + * 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144 /32 + * 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144 /32 + * 1 1 1 0 Prohibited setting + * 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144 /32 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \ + (((md) & BIT(13)) >> 11) | \ + (((md) & BIT(19)) >> 18) | \ + (((md) & BIT(17)) >> 17)) + +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { + /* EXTAL div PLL1 mult/div PLL3 mult/div OSC prediv */ + { 1, 192, 1, 192, 1, 16, }, + { 1, 192, 1, 128, 1, 16, }, + { 0, /* Prohibited setting */ }, + { 1, 192, 1, 192, 1, 16, }, + { 1, 160, 1, 160, 1, 19, }, + { 1, 160, 1, 106, 1, 19, }, + { 0, /* Prohibited setting */ }, + { 1, 160, 1, 160, 1, 19, }, + { 1, 128, 1, 128, 1, 24, }, + { 1, 128, 1, 84, 1, 24, }, + { 0, /* Prohibited setting */ }, + { 1, 128, 1, 128, 1, 24, }, + { 2, 192, 1, 192, 1, 32, }, + { 2, 192, 1, 128, 1, 32, }, + { 0, /* Prohibited setting */ }, + { 2, 192, 1, 192, 1, 32, }, +}; + +static int __init r8a774e1_cpg_mssr_init(struct device *dev) +{ + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; + u32 cpg_mode; + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + if (!cpg_pll_config->extal_div) { + dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode); + return -EINVAL; + } + + return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode); +} + +const struct cpg_mssr_info r8a774e1_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a774e1_core_clks, + .num_core_clks = ARRAY_SIZE(r8a774e1_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a774e1_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a774e1_mod_clks), + .num_hw_mod_clks = 12 * 32, + + /* Critical Module Clocks */ + .crit_mod_clks = r8a774e1_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a774e1_crit_mod_clks), + + /* Callbacks */ + .init = r8a774e1_cpg_mssr_init, + .cpg_clk_register = rcar_gen3_cpg_clk_register, +}; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 4648a829db66..5a306d28738c 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -721,6 +721,12 @@ static const struct of_device_id cpg_mssr_match[] = { .data = &r8a774c0_cpg_mssr_info, }, #endif +#ifdef CONFIG_CLK_R8A774E1 + { + .compatible = "renesas,r8a774e1-cpg-mssr", + .data = &r8a774e1_cpg_mssr_info, + }, +#endif #ifdef CONFIG_CLK_R8A7790 { .compatible = "renesas,r8a7790-cpg-mssr", diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 55a18ef0efaf..1cc569484250 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -162,6 +162,7 @@ extern const struct cpg_mssr_info r8a77470_cpg_mssr_info; extern const struct cpg_mssr_info r8a774a1_cpg_mssr_info; extern const struct cpg_mssr_info r8a774b1_cpg_mssr_info; extern const struct cpg_mssr_info r8a774c0_cpg_mssr_info; +extern const struct cpg_mssr_info r8a774e1_cpg_mssr_info; extern const struct cpg_mssr_info r8a7790_cpg_mssr_info; extern const struct cpg_mssr_info r8a7791_cpg_mssr_info; extern const struct cpg_mssr_info r8a7792_cpg_mssr_info; -- cgit v1.2.3-58-ga151 From 8607fa169178a4a38f232612e036def96b5ecd1d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 14 Jul 2020 22:21:55 +0800 Subject: 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(-) (limited to 'drivers/clk') 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, -- cgit v1.2.3-58-ga151 From 5ce728fa78ddbef667fd757ad008d33e39e7312a Mon Sep 17 00:00:00 2001 From: Ansuel Smith Date: Thu, 16 Jul 2020 04:28:10 +0200 Subject: 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(-) (limited to 'drivers/clk') 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 = { -- cgit v1.2.3-58-ga151 From 9c3df2b1993da9ab1110702d7b2815d5cd8c02f3 Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Wed, 15 Jul 2020 12:24:10 +0530 Subject: 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(-) (limited to 'drivers/clk') 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, }, }, }; -- cgit v1.2.3-58-ga151