diff options
173 files changed, 5526 insertions, 1307 deletions
diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt index fd0061712443..a87ec15e28d2 100644 --- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt +++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt @@ -86,6 +86,7 @@ This binding uses the common clock binding[1]. Required properties: - compatible: Should be one of: + "fsl,imx8dxl-clk" "fsl,imx8qm-clk" "fsl,imx8qxp-clk" followed by "fsl,scu-clk" diff --git a/Documentation/devicetree/bindings/clock/bitmain,bm1880-clk.yaml b/Documentation/devicetree/bindings/clock/bitmain,bm1880-clk.yaml index 228c9313df53..f0f9392470a6 100644 --- a/Documentation/devicetree/bindings/clock/bitmain,bm1880-clk.yaml +++ b/Documentation/devicetree/bindings/clock/bitmain,bm1880-clk.yaml @@ -61,16 +61,4 @@ examples: #clock-cells = <1>; }; - # Example UART controller node that consumes clock generated by the clock controller: - - | - uart0: serial@58018000 { - compatible = "snps,dw-apb-uart"; - reg = <0x58018000 0x2000>; - clocks = <&clk 45>, <&clk 46>; - clock-names = "baudclk", "apb_pclk"; - interrupts = <0 9 4>; - reg-shift = <2>; - reg-io-width = <4>; - }; - ... diff --git a/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml b/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml new file mode 100644 index 000000000000..0abd6ba82dfd --- /dev/null +++ b/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml @@ -0,0 +1,91 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/cirrus,cs2000-cp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Binding CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier + +maintainers: + - Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + +description: | + The CS2000-CP is an extremely versatile system clocking device that + utilizes a programmable phase lock loop. + + Link: https://www.cirrus.com/products/cs2000/ + +properties: + compatible: + enum: + - cirrus,cs2000-cp + + clocks: + description: + Common clock binding for CLK_IN, XTI/REF_CLK + minItems: 2 + maxItems: 2 + + clock-names: + items: + - const: clk_in + - const: ref_clk + + '#clock-cells': + const: 0 + + reg: + maxItems: 1 + + cirrus,aux-output-source: + description: + Specifies the function of the auxiliary clock output pin + $ref: /schemas/types.yaml#/definitions/uint32 + enum: + - 0 # CS2000CP_AUX_OUTPUT_REF_CLK: ref_clk input + - 1 # CS2000CP_AUX_OUTPUT_CLK_IN: clk_in input + - 2 # CS2000CP_AUX_OUTPUT_CLK_OUT: clk_out output + - 3 # CS2000CP_AUX_OUTPUT_PLL_LOCK: pll lock status + default: 0 + + cirrus,clock-skip: + description: + This mode allows the PLL to maintain lock even when CLK_IN + has missing pulses for up to 20 ms. + $ref: /schemas/types.yaml#/definitions/flag + + cirrus,dynamic-mode: + description: + In dynamic mode, the CLK_IN input is used to drive the + digital PLL of the silicon. + If not given, the static mode shall be used to derive the + output signal directly from the REF_CLK input. + $ref: /schemas/types.yaml#/definitions/flag + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/cirrus,cs2000-cp.h> + + i2c@0 { + reg = <0x0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + + clock-controller@4f { + #clock-cells = <0>; + compatible = "cirrus,cs2000-cp"; + reg = <0x4f>; + clocks = <&rcar_sound 0>, <&x12_clk>; + clock-names = "clk_in", "ref_clk"; + cirrus,aux-output-source = <CS2000CP_AUX_OUTPUT_CLK_OUT>; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/cs2000-cp.txt b/Documentation/devicetree/bindings/clock/cs2000-cp.txt deleted file mode 100644 index 54e6df0bee8a..000000000000 --- a/Documentation/devicetree/bindings/clock/cs2000-cp.txt +++ /dev/null @@ -1,22 +0,0 @@ -CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier - -Required properties: - -- compatible: "cirrus,cs2000-cp" -- reg: The chip select number on the I2C bus -- clocks: common clock binding for CLK_IN, XTI/REF_CLK -- clock-names: CLK_IN : clk_in, XTI/REF_CLK : ref_clk -- #clock-cells: must be <0> - -Example: - -&i2c2 { - ... - cs2000: clk_multiplier@4f { - #clock-cells = <0>; - compatible = "cirrus,cs2000-cp"; - reg = <0x4f>; - clocks = <&rcar_sound 0>, <&x12_clk>; - clock-names = "clk_in", "ref_clk"; - }; -}; diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml index ffd6ae0eed64..be66f1e8b547 100644 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml @@ -191,11 +191,4 @@ examples: }; }; - /* Consumer referencing the 5P49V5923 pin OUT1 */ - consumer { - /* ... */ - clocks = <&vc5 1>; - /* ... */ - }; - ... diff --git a/Documentation/devicetree/bindings/clock/imx1-clock.yaml b/Documentation/devicetree/bindings/clock/imx1-clock.yaml index f4833a29b79e..56f524780b1a 100644 --- a/Documentation/devicetree/bindings/clock/imx1-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx1-clock.yaml @@ -40,12 +40,3 @@ examples: compatible = "fsl,imx1-ccm"; reg = <0x0021b000 0x1000>; }; - - pwm@208000 { - #pwm-cells = <2>; - compatible = "fsl,imx1-pwm"; - reg = <0x00208000 0x1000>; - interrupts = <34>; - clocks = <&clks IMX1_CLK_DUMMY>, <&clks IMX1_CLK_PER1>; - clock-names = "ipg", "per"; - }; diff --git a/Documentation/devicetree/bindings/clock/imx21-clock.yaml b/Documentation/devicetree/bindings/clock/imx21-clock.yaml index 518ad9a4733c..e2d50544700a 100644 --- a/Documentation/devicetree/bindings/clock/imx21-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx21-clock.yaml @@ -40,12 +40,3 @@ examples: reg = <0x10027000 0x800>; #clock-cells = <1>; }; - - serial@1000a000 { - compatible = "fsl,imx21-uart"; - reg = <0x1000a000 0x1000>; - interrupts = <20>; - clocks = <&clks IMX21_CLK_UART1_IPG_GATE>, - <&clks IMX21_CLK_PER1>; - clock-names = "ipg", "per"; - }; diff --git a/Documentation/devicetree/bindings/clock/imx23-clock.yaml b/Documentation/devicetree/bindings/clock/imx23-clock.yaml index 5e296a00e14f..7e890ab9c77d 100644 --- a/Documentation/devicetree/bindings/clock/imx23-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx23-clock.yaml @@ -83,12 +83,3 @@ examples: reg = <0x80040000 0x2000>; #clock-cells = <1>; }; - - serial@8006c000 { - compatible = "fsl,imx23-auart"; - reg = <0x8006c000 0x2000>; - interrupts = <24>; - clocks = <&clks 32>; - dmas = <&dma_apbx 6>, <&dma_apbx 7>; - dma-names = "rx", "tx"; - }; diff --git a/Documentation/devicetree/bindings/clock/imx25-clock.yaml b/Documentation/devicetree/bindings/clock/imx25-clock.yaml index 2a2b10778e72..1792e138984b 100644 --- a/Documentation/devicetree/bindings/clock/imx25-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx25-clock.yaml @@ -176,11 +176,3 @@ examples: interrupts = <31>; #clock-cells = <1>; }; - - serial@43f90000 { - compatible = "fsl,imx25-uart", "fsl,imx21-uart"; - reg = <0x43f90000 0x4000>; - interrupts = <45>; - clocks = <&clks 79>, <&clks 50>; - clock-names = "ipg", "per"; - }; diff --git a/Documentation/devicetree/bindings/clock/imx27-clock.yaml b/Documentation/devicetree/bindings/clock/imx27-clock.yaml index 160268f24487..99925aa22a4c 100644 --- a/Documentation/devicetree/bindings/clock/imx27-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx27-clock.yaml @@ -44,12 +44,3 @@ examples: interrupts = <31>; #clock-cells = <1>; }; - - serial@1000a000 { - compatible = "fsl,imx27-uart", "fsl,imx21-uart"; - reg = <0x1000a000 0x1000>; - interrupts = <20>; - clocks = <&clks IMX27_CLK_UART1_IPG_GATE>, - <&clks IMX27_CLK_PER1_GATE>; - clock-names = "ipg", "per"; - }; diff --git a/Documentation/devicetree/bindings/clock/imx28-clock.yaml b/Documentation/devicetree/bindings/clock/imx28-clock.yaml index f831b780f951..a542d680b1ca 100644 --- a/Documentation/devicetree/bindings/clock/imx28-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx28-clock.yaml @@ -106,12 +106,3 @@ examples: reg = <0x80040000 0x2000>; #clock-cells = <1>; }; - - serial@8006a000 { - compatible = "fsl,imx28-auart"; - reg = <0x8006a000 0x2000>; - interrupts = <112>; - dmas = <&dma_apbx 8>, <&dma_apbx 9>; - dma-names = "rx", "tx"; - clocks = <&clks 45>; - }; diff --git a/Documentation/devicetree/bindings/clock/imx31-clock.yaml b/Documentation/devicetree/bindings/clock/imx31-clock.yaml index d2336261c922..168c8ada5e81 100644 --- a/Documentation/devicetree/bindings/clock/imx31-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx31-clock.yaml @@ -110,11 +110,3 @@ examples: interrupts = <31>, <53>; #clock-cells = <1>; }; - - serial@43f90000 { - compatible = "fsl,imx31-uart", "fsl,imx21-uart"; - reg = <0x43f90000 0x4000>; - interrupts = <45>; - clocks = <&clks 10>, <&clks 30>; - clock-names = "ipg", "per"; - }; diff --git a/Documentation/devicetree/bindings/clock/imx35-clock.yaml b/Documentation/devicetree/bindings/clock/imx35-clock.yaml index 3e20ccaf8131..6415bb6a8d04 100644 --- a/Documentation/devicetree/bindings/clock/imx35-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx35-clock.yaml @@ -129,11 +129,3 @@ examples: interrupts = <31>; #clock-cells = <1>; }; - - mmc@53fb4000 { - compatible = "fsl,imx35-esdhc"; - reg = <0x53fb4000 0x4000>; - interrupts = <7>; - clocks = <&clks 9>, <&clks 8>, <&clks 43>; - clock-names = "ipg", "ahb", "per"; - }; diff --git a/Documentation/devicetree/bindings/clock/imx7ulp-pcc-clock.yaml b/Documentation/devicetree/bindings/clock/imx7ulp-pcc-clock.yaml index 7caf5cee9199..739c3378f8c8 100644 --- a/Documentation/devicetree/bindings/clock/imx7ulp-pcc-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx7ulp-pcc-clock.yaml @@ -108,14 +108,3 @@ examples: "upll", "sosc_bus_clk", "firc_bus_clk", "rosc", "spll_bus_clk"; }; - - mmc@40380000 { - compatible = "fsl,imx7ulp-usdhc"; - reg = <0x40380000 0x10000>; - interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>, - <&scg1 IMX7ULP_CLK_NIC1_DIV>, - <&pcc2 IMX7ULP_CLK_USDHC1>; - clock-names ="ipg", "ahb", "per"; - bus-width = <4>; - }; diff --git a/Documentation/devicetree/bindings/clock/imx7ulp-scg-clock.yaml b/Documentation/devicetree/bindings/clock/imx7ulp-scg-clock.yaml index ee8efb4ed599..d06344d7e34f 100644 --- a/Documentation/devicetree/bindings/clock/imx7ulp-scg-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx7ulp-scg-clock.yaml @@ -86,14 +86,3 @@ examples: "firc", "upll"; #clock-cells = <1>; }; - - mmc@40380000 { - compatible = "fsl,imx7ulp-usdhc"; - reg = <0x40380000 0x10000>; - interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&scg1 IMX7ULP_CLK_NIC1_BUS_DIV>, - <&scg1 IMX7ULP_CLK_NIC1_DIV>, - <&pcc2 IMX7ULP_CLK_USDHC1>; - clock-names ="ipg", "ahb", "per"; - bus-width = <4>; - }; diff --git a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml index 0f6fe365ebf3..cb80105b3c70 100644 --- a/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml +++ b/Documentation/devicetree/bindings/clock/imx8qxp-lpcg.yaml @@ -101,14 +101,3 @@ examples: "sdhc0_lpcg_ahb_clk"; power-domains = <&pd IMX_SC_R_SDHC_0>; }; - - mmc@5b010000 { - compatible = "fsl,imx8qxp-usdhc", "fsl,imx7d-usdhc"; - interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>; - reg = <0x5b010000 0x10000>; - clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>, - <&sdhc0_lpcg IMX_LPCG_CLK_5>, - <&sdhc0_lpcg IMX_LPCG_CLK_0>; - clock-names = "ipg", "ahb", "per"; - power-domains = <&pd IMX_SC_R_SDHC_0>; - }; diff --git a/Documentation/devicetree/bindings/clock/imx93-clock.yaml b/Documentation/devicetree/bindings/clock/imx93-clock.yaml new file mode 100644 index 000000000000..21a06194e4a3 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/imx93-clock.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/imx93-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP i.MX93 Clock Control Module Binding + +maintainers: + - Peng Fan <peng.fan@nxp.com> + +description: | + i.MX93 clock control module is an integrated clock controller, which + includes clock generator, clock gate and supplies to all modules. + +properties: + compatible: + enum: + - fsl,imx93-ccm + + reg: + maxItems: 1 + + clocks: + description: + specify the external clocks used by the CCM module. + items: + - description: 32k osc + - description: 24m osc + - description: ext1 clock input + + clock-names: + description: + specify the external clocks names used by the CCM module. + items: + - const: osc_32k + - const: osc_24m + - const: clk_ext1 + + '#clock-cells': + const: 1 + description: + See include/dt-bindings/clock/imx93-clock.h for the full list of + i.MX93 clock IDs. + +required: + - compatible + - reg + - '#clock-cells' + +additionalProperties: false + +examples: + # Clock Control Module node: + - | + clock-controller@44450000 { + compatible = "fsl,imx93-ccm"; + reg = <0x44450000 0x10000>; + #clock-cells = <1>; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/imxrt1050-clock.yaml b/Documentation/devicetree/bindings/clock/imxrt1050-clock.yaml new file mode 100644 index 000000000000..03fc5c1a2939 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/imxrt1050-clock.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/imxrt1050-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Clock bindings for Freescale i.MXRT + +maintainers: + - Giulio Benetti <giulio.benetti@benettiengineering.com> + - Jesse Taube <Mr.Bossman075@gmail.com> + +description: | + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. See include/dt-bindings/clock/imxrt*-clock.h + for the full list of i.MXRT clock IDs. + +properties: + compatible: + const: fsl,imxrt1050-ccm + + reg: + maxItems: 1 + + interrupts: + maxItems: 2 + + clocks: + description: 24m osc + maxItems: 1 + + clock-names: + const: osc + + '#clock-cells': + const: 1 + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/imxrt1050-clock.h> + + clks: clock-controller@400fc000 { + compatible = "fsl,imxrt1050-ccm"; + reg = <0x400fc000 0x4000>; + interrupts = <95>, <96>; + clocks = <&osc>; + clock-names = "osc"; + #clock-cells = <1>; + }; diff --git a/Documentation/devicetree/bindings/clock/microchip,mpfs.yaml b/Documentation/devicetree/bindings/clock/microchip,mpfs.yaml new file mode 100644 index 000000000000..0c15afa2214c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/microchip,mpfs.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/microchip,mpfs.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip PolarFire Clock Control Module Binding + +maintainers: + - Daire McNamara <daire.mcnamara@microchip.com> + +description: | + Microchip PolarFire clock control (CLKCFG) is an integrated clock controller, + which gates and enables all peripheral clocks. + + This device tree binding describes 33 gate clocks. Clocks are referenced by + user nodes by the CLKCFG node phandle and the clock index in the group, from + 0 to 32. + +properties: + compatible: + const: microchip,mpfs-clkcfg + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + '#clock-cells': + const: 1 + description: | + The clock consumer should specify the desired clock by having the clock + ID in its "clocks" phandle cell. See include/dt-bindings/clock/microchip,mpfs-clock.h + for the full list of PolarFire clock IDs. + +required: + - compatible + - reg + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + # Clock Config node: + - | + #include <dt-bindings/clock/microchip,mpfs-clock.h> + soc { + #address-cells = <2>; + #size-cells = <2>; + clkcfg: clock-controller@20002000 { + compatible = "microchip,mpfs-clkcfg"; + reg = <0x0 0x20002000 0x0 0x1000>; + clocks = <&ref>; + #clock-cells = <1>; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.yaml b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.yaml index ec7ab1483652..1b2181f6d440 100644 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.yaml +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-car.yaml @@ -106,10 +106,3 @@ examples: #clock-cells = <1>; #reset-cells = <1>; }; - - usb-controller@c5004000 { - compatible = "nvidia,tegra20-ehci"; - reg = <0xc5004000 0x4000>; - clocks = <&car TEGRA124_CLK_USB2>; - resets = <&car TEGRA124_CLK_USB2>; - }; diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml index f832abb7f11a..bee2dd4b29bf 100644 --- a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml +++ b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.yaml @@ -97,10 +97,3 @@ examples: power-domains = <&domain>; }; }; - - usb-controller@c5004000 { - compatible = "nvidia,tegra20-ehci"; - reg = <0xc5004000 0x4000>; - clocks = <&car TEGRA20_CLK_USB2>; - resets = <&car TEGRA20_CLK_USB2>; - }; diff --git a/Documentation/devicetree/bindings/clock/renesas,9series.yaml b/Documentation/devicetree/bindings/clock/renesas,9series.yaml new file mode 100644 index 000000000000..102eb95cb3fc --- /dev/null +++ b/Documentation/devicetree/bindings/clock/renesas,9series.yaml @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/renesas,9series.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Binding for Renesas 9-series I2C PCIe clock generators + +description: | + The Renesas 9-series are I2C PCIe clock generators providing + from 1 to 20 output clocks. + + When referencing the provided clock in the DT using phandle + and clock specifier, the following mapping applies: + + - 9FGV0241: + 0 -- DIF0 + 1 -- DIF1 + +maintainers: + - Marek Vasut <marex@denx.de> + +properties: + compatible: + enum: + - renesas,9fgv0241 + + reg: + description: I2C device address + enum: [ 0x68, 0x6a ] + + '#clock-cells': + const: 1 + + clocks: + items: + - description: XTal input clock + + renesas,out-amplitude-microvolt: + enum: [ 600000, 700000, 800000, 900000 ] + description: Output clock signal amplitude + + renesas,out-spread-spectrum: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 100000, 99750, 99500 ] + description: Output clock down spread in pcm (1/1000 of percent) + +patternProperties: + "^DIF[0-19]$": + type: object + description: + Description of one of the outputs (DIF0..DIF19). + + properties: + renesas,slew-rate: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [ 2000000, 3000000 ] + description: Output clock slew rate select in V/ns + + additionalProperties: false + +required: + - compatible + - reg + - clocks + - '#clock-cells' + +additionalProperties: false + +examples: + - | + /* 25MHz reference crystal */ + ref25: ref25m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + i2c@0 { + reg = <0x0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + + rs9: clock-generator@6a { + compatible = "renesas,9fgv0241"; + reg = <0x6a>; + #clock-cells = <1>; + + clocks = <&ref25m>; + + DIF0 { + renesas,slew-rate = <3000000>; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml index c55a7c494e01..2197c952e21d 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-div6-clock.yaml @@ -51,6 +51,18 @@ additionalProperties: false examples: - | #include <dt-bindings/clock/r8a73a4-clock.h> + + cpg_clocks: cpg_clocks@e6150000 { + compatible = "renesas,r8a73a4-cpg-clocks"; + reg = <0xe6150000 0x10000>; + clocks = <&extal1_clk>, <&extal2_clk>; + #clock-cells = <1>; + clock-output-names = "main", "pll0", "pll1", "pll2", + "pll2s", "pll2h", "z", "z2", + "i", "m3", "b", "m1", "m2", + "zx", "zs", "hp"; + }; + sdhi2_clk: sdhi2_clk@e615007c { compatible = "renesas,r8a73a4-div6-clock", "renesas,cpg-div6-clock"; reg = <0xe615007c 4>; diff --git a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml index 30b2e3d0d25d..bd3af8fc616b 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,rzg2l-cpg.yaml @@ -4,13 +4,13 @@ $id: "http://devicetree.org/schemas/clock/renesas,rzg2l-cpg.yaml#" $schema: "http://devicetree.org/meta-schemas/core.yaml#" -title: Renesas RZ/G2L Clock Pulse Generator / Module Standby Mode +title: Renesas RZ/{G2L,V2L} Clock Pulse Generator / Module Standby Mode maintainers: - Geert Uytterhoeven <geert+renesas@glider.be> description: | - On Renesas RZ/G2L SoC, the CPG (Clock Pulse Generator) and Module + On Renesas RZ/{G2L,V2L} SoC, the CPG (Clock Pulse Generator) and Module Standby Mode share the same register block. They provide the following functionalities: @@ -22,7 +22,9 @@ description: | properties: compatible: - const: renesas,r9a07g044-cpg # RZ/G2{L,LC} + enum: + - renesas,r9a07g044-cpg # RZ/G2{L,LC} + - renesas,r9a07g054-cpg # RZ/V2L reg: maxItems: 1 @@ -40,9 +42,9 @@ properties: description: | - For CPG core clocks, the two clock specifier cells must be "CPG_CORE" and a core clock reference, as defined in - <dt-bindings/clock/r9a07g044-cpg.h> + <dt-bindings/clock/r9a07g*-cpg.h> - For module clocks, the two clock specifier cells must be "CPG_MOD" and - a module number, as defined in the <dt-bindings/clock/r9a07g044-cpg.h>. + a module number, as defined in the <dt-bindings/clock/r9a07g0*-cpg.h>. const: 2 '#power-domain-cells': @@ -56,7 +58,7 @@ properties: '#reset-cells': description: The single reset specifier cell must be the module number, as defined in - the <dt-bindings/clock/r9a07g044-cpg.h>. + the <dt-bindings/clock/r9a07g0*-cpg.h>. const: 1 required: diff --git a/Documentation/devicetree/bindings/clock/starfive,jh7100-audclk.yaml b/Documentation/devicetree/bindings/clock/starfive,jh7100-audclk.yaml new file mode 100644 index 000000000000..8f49a1ae03f1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/starfive,jh7100-audclk.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/starfive,jh7100-audclk.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: StarFive JH7100 Audio Clock Generator + +maintainers: + - Emil Renner Berthing <kernel@esmil.dk> + +properties: + compatible: + const: starfive,jh7100-audclk + + reg: + maxItems: 1 + + clocks: + items: + - description: Audio source clock + - description: External 12.288MHz clock + - description: Domain 7 AHB bus clock + + clock-names: + items: + - const: audio_src + - const: audio_12288 + - const: dom7ahb_bus + + '#clock-cells': + const: 1 + description: + See <dt-bindings/clock/starfive-jh7100-audio.h> for valid indices. + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/starfive-jh7100.h> + + clock-controller@10480000 { + compatible = "starfive,jh7100-audclk"; + reg = <0x10480000 0x10000>; + clocks = <&clkgen JH7100_CLK_AUDIO_SRC>, + <&clkgen JH7100_CLK_AUDIO_12288>, + <&clkgen JH7100_CLK_DOM7AHB_BUS>; + clock-names = "audio_src", "audio_12288", "dom7ahb_bus"; + #clock-cells = <1>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index fca970a46e77..56891a9da798 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13840,7 +13840,10 @@ M: Abel Vesa <abel.vesa@nxp.com> L: linux-clk@vger.kernel.org L: linux-imx@nxp.com S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux.git clk/imx +F: Documentation/devicetree/bindings/clock/imx* F: drivers/clk/imx/ +F: include/dt-bindings/clock/imx* NXP i.MX 8MQ DCSS DRIVER M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com> @@ -18427,12 +18430,12 @@ M: Ion Badulescu <ionut@badula.org> S: Odd Fixes F: drivers/net/ethernet/adaptec/starfire* -STARFIVE JH7100 CLOCK DRIVER +STARFIVE JH7100 CLOCK DRIVERS M: Emil Renner Berthing <kernel@esmil.dk> S: Maintained -F: Documentation/devicetree/bindings/clock/starfive,jh7100-clkgen.yaml -F: drivers/clk/starfive/clk-starfive-jh7100.c -F: include/dt-bindings/clock/starfive-jh7100.h +F: Documentation/devicetree/bindings/clock/starfive,jh7100-*.yaml +F: drivers/clk/starfive/clk-starfive-jh7100* +F: include/dt-bindings/clock/starfive-jh7100*.h STARFIVE JH7100 PINCTRL DRIVER M: Emil Renner Berthing <kernel@esmil.dk> diff --git a/drivers/clk/.kunitconfig b/drivers/clk/.kunitconfig new file mode 100644 index 000000000000..3754fdb9485a --- /dev/null +++ b/drivers/clk/.kunitconfig @@ -0,0 +1,3 @@ +CONFIG_KUNIT=y +CONFIG_COMMON_CLK=y +CONFIG_CLK_GATE_KUNIT_TEST=y diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index ad4256d54361..a46a8a949ad5 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -197,6 +197,7 @@ config COMMON_CLK_CDCE925 config COMMON_CLK_CS2000_CP tristate "Clock driver for CS2000 Fractional-N Clock Synthesizer & Clock Multiplier" depends on I2C + select REGMAP_I2C help If you say yes here you get support for the CS2000 clock multiplier. @@ -231,6 +232,7 @@ config COMMON_CLK_GEMINI config COMMON_CLK_LAN966X bool "Generic Clock Controller driver for LAN966X SoC" + depends on SOC_LAN966 || COMPILE_TEST help This driver provides support for Generic Clock Controller(GCK) on LAN966X SoC. GCK generates and supplies clock to various peripherals @@ -330,9 +332,6 @@ config COMMON_CLK_PXA help Support for the Marvell PXA SoC. -config COMMON_CLK_PIC32 - def_bool COMMON_CLK && MACH_PIC32 - config COMMON_CLK_OXNAS bool "Clock driver for the OXNAS SoC Family" depends on ARCH_OXNAS || COMPILE_TEST @@ -340,6 +339,15 @@ config COMMON_CLK_OXNAS help Support for the OXNAS SoC Family clocks. +config COMMON_CLK_RS9_PCIE + tristate "Clock driver for Renesas 9-series PCIe clock generators" + depends on I2C + depends on OF + select REGMAP_I2C + help + This driver supports the Renesas 9-series PCIe clock generator + models 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ. + config COMMON_CLK_VC5 tristate "Clock driver for IDT VersaClock 5,6 devices" depends on I2C @@ -407,6 +415,7 @@ source "drivers/clk/keystone/Kconfig" source "drivers/clk/mediatek/Kconfig" source "drivers/clk/meson/Kconfig" source "drivers/clk/mstar/Kconfig" +source "drivers/clk/microchip/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/pistachio/Kconfig" source "drivers/clk/qcom/Kconfig" @@ -428,4 +437,12 @@ source "drivers/clk/x86/Kconfig" source "drivers/clk/xilinx/Kconfig" source "drivers/clk/zynqmp/Kconfig" +# Kunit test cases +config CLK_GATE_KUNIT_TEST + tristate "Basic gate type Kunit test" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Kunit test for the basic clk gate type. + endif diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 16e588630472..5b2eaf529e96 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-divider.o obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o obj-$(CONFIG_COMMON_CLK) += clk-gate.o +obj-$(CONFIG_CLK_GATE_KUNIT_TEST) += clk-gate_test.o obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o obj-$(CONFIG_COMMON_CLK) += clk-mux.o obj-$(CONFIG_COMMON_CLK) += clk-composite.o @@ -67,6 +68,7 @@ obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o +obj-$(CONFIG_COMMON_CLK_RS9_PCIE) += clk-renesas-pcie.o obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o @@ -91,7 +93,7 @@ obj-$(CONFIG_ARCH_KEYSTONE) += keystone/ obj-$(CONFIG_MACH_LOONGSON32) += loongson1/ obj-y += mediatek/ obj-$(CONFIG_ARCH_MESON) += meson/ -obj-$(CONFIG_MACH_PIC32) += microchip/ +obj-y += microchip/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_ARCH_MMP) += mmp/ endif diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index 57d06e183dff..c69a7e2f0645 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -95,7 +95,7 @@ static const struct clk_pll_table clk_audio_pll_table[] = { { 0, 45158400 }, { 1, 49152000 }, - { 0, 0 }, + { /* sentinel */ } }; /* pll clocks */ @@ -138,46 +138,46 @@ static struct clk_factor_table sd_factor_table[] = { { 272, 1, 17 * 128 }, { 273, 1, 18 * 128 }, { 274, 1, 19 * 128 }, { 275, 1, 20 * 128 }, { 276, 1, 21 * 128 }, { 277, 1, 22 * 128 }, { 278, 1, 23 * 128 }, { 279, 1, 24 * 128 }, { 280, 1, 25 * 128 }, - { 0, 0, 0 }, + { /* sentinel */ } }; static struct clk_factor_table de_factor_table[] = { { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, { 8, 1, 12 }, - { 0, 0, 0 }, + { /* sentinel */ } }; static struct clk_factor_table hde_factor_table[] = { { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, - { 0, 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table rmii_ref_div_table[] = { { 0, 4 }, { 1, 10 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table std12rate_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 }, { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table i2s_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 }, { 8, 24 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table nand_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 10 }, { 6, 12 }, { 7, 14 }, { 8, 16 }, { 9, 18 }, { 10, 20 }, { 11, 22 }, - { 0, 0 }, + { /* sentinel */ } }; /* mux clock */ diff --git a/drivers/clk/actions/owl-s700.c b/drivers/clk/actions/owl-s700.c index a2f34d13fb54..3e48105602aa 100644 --- a/drivers/clk/actions/owl-s700.c +++ b/drivers/clk/actions/owl-s700.c @@ -73,7 +73,7 @@ static struct clk_pll_table clk_audio_pll_table[] = { {0, 45158400}, {1, 49152000}, - {0, 0}, + { /* sentinel */ } }; static struct clk_pll_table clk_cvbs_pll_table[] = { @@ -82,7 +82,8 @@ static struct clk_pll_table clk_cvbs_pll_table[] = { {33, 35 * 12000000}, {34, 36 * 12000000}, {35, 37 * 12000000}, {36, 38 * 12000000}, {37, 39 * 12000000}, {38, 40 * 12000000}, {39, 41 * 12000000}, {40, 42 * 12000000}, {41, 43 * 12000000}, - {42, 44 * 12000000}, {43, 45 * 12000000}, {0, 0}, + {42, 44 * 12000000}, {43, 45 * 12000000}, + { /* sentinel */ } }; /* pll clocks */ @@ -137,7 +138,7 @@ static struct clk_factor_table sd_factor_table[] = { {276, 1, 21 * 128}, {277, 1, 22 * 128}, {278, 1, 23 * 128}, {279, 1, 24 * 128}, {280, 1, 25 * 128}, {281, 1, 26 * 128}, - {0, 0}, + { /* sentinel */ } }; static struct clk_factor_table lcd_factor_table[] = { @@ -150,18 +151,19 @@ static struct clk_factor_table lcd_factor_table[] = { {256, 1, 1 * 7}, {257, 1, 2 * 7}, {258, 1, 3 * 7}, {259, 1, 4 * 7}, {260, 1, 5 * 7}, {261, 1, 6 * 7}, {262, 1, 7 * 7}, {263, 1, 8 * 7}, {264, 1, 9 * 7}, {265, 1, 10 * 7}, {266, 1, 11 * 7}, {267, 1, 12 * 7}, - {0, 0}, + { /* sentinel */ } }; static struct clk_div_table hdmia_div_table[] = { {0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 6}, {5, 8}, {6, 12}, {7, 16}, {8, 24}, - {0, 0}, + { /* sentinel */ } }; static struct clk_div_table rmii_div_table[] = { {0, 4}, {1, 10}, + { /* sentinel */ } }; /* divider clocks */ @@ -178,13 +180,14 @@ static OWL_DIVIDER(clk_rmii_ref, "rmii_ref", "ethernet_pll", CMU_ETHERNETPLL, 2, static struct clk_factor_table de_factor_table[] = { {0, 1, 1}, {1, 2, 3}, {2, 1, 2}, {3, 2, 5}, {4, 1, 3}, {5, 1, 4}, {6, 1, 6}, {7, 1, 8}, - {8, 1, 12}, {0, 0, 0}, + {8, 1, 12}, + { /* sentinel */ } }; static struct clk_factor_table hde_factor_table[] = { {0, 1, 1}, {1, 2, 3}, {2, 1, 2}, {3, 2, 5}, {4, 1, 3}, {5, 1, 4}, {6, 1, 6}, {7, 1, 8}, - {0, 0, 0}, + { /* sentinel */ } }; /* gate clocks */ diff --git a/drivers/clk/actions/owl-s900.c b/drivers/clk/actions/owl-s900.c index 790890978424..7dc6e07fb60e 100644 --- a/drivers/clk/actions/owl-s900.c +++ b/drivers/clk/actions/owl-s900.c @@ -73,12 +73,12 @@ static struct clk_pll_table clk_audio_pll_table[] = { { 0, 45158400 }, { 1, 49152000 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_pll_table clk_edp_pll_table[] = { { 0, 810000000 }, { 1, 135000000 }, { 2, 270000000 }, - { 0, 0 }, + { /* sentinel */ } }; /* pll clocks */ @@ -120,41 +120,41 @@ static struct clk_div_table nand_div_table[] = { { 4, 8 }, { 5, 10 }, { 6, 12 }, { 7, 14 }, { 8, 16 }, { 9, 18 }, { 10, 20 }, { 11, 22 }, { 12, 24 }, { 13, 26 }, { 14, 28 }, { 15, 30 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table apb_div_table[] = { { 1, 2 }, { 2, 3 }, { 3, 4 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table eth_mac_div_table[] = { { 0, 2 }, { 1, 4 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table rmii_ref_div_table[] = { { 0, 4 }, { 1, 10 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table usb3_mac_div_table[] = { { 1, 2 }, { 2, 3 }, { 3, 4 }, - { 0, 8 }, + { /* sentinel */ } }; static struct clk_div_table i2s_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 }, { 8, 24 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_div_table hdmia_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 }, { 8, 24 }, - { 0, 0 }, + { /* sentinel */ } }; /* divider clocks */ @@ -185,24 +185,24 @@ static struct clk_factor_table sd_factor_table[] = { { 280, 1, 25 * 128 }, { 281, 1, 26 * 128 }, { 282, 1, 27 * 128 }, { 283, 1, 28 * 128 }, { 284, 1, 29 * 128 }, { 285, 1, 30 * 128 }, { 286, 1, 31 * 128 }, { 287, 1, 32 * 128 }, - { 0, 0 }, + { /* sentinel */ } }; static struct clk_factor_table dmm_factor_table[] = { { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 1, 3 }, { 4, 1, 4 }, - { 0, 0, 0 }, + { /* sentinel */ } }; static struct clk_factor_table noc_factor_table[] = { { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 1, 3 }, { 4, 1, 4 }, - { 0, 0, 0 }, + { /* sentinel */ } }; static struct clk_factor_table bisp_factor_table[] = { { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, - { 0, 0, 0 }, + { /* sentinel */ } }; /* factor clocks */ diff --git a/drivers/clk/at91/at91rm9200.c b/drivers/clk/at91/at91rm9200.c index fff4fdda974f..b174f727a8ef 100644 --- a/drivers/clk/at91/at91rm9200.c +++ b/drivers/clk/at91/at91rm9200.c @@ -143,8 +143,7 @@ static void __init at91rm9200_pmc_setup(struct device_node *np) parent_names, &at91rm9200_master_layout, &rm9200_mck_characteristics, - &rm9200_mck_lock, CLK_SET_RATE_GATE, - INT_MIN); + &rm9200_mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c index 79802f864ee5..11550e50cd9f 100644 --- a/drivers/clk/at91/at91sam9260.c +++ b/drivers/clk/at91/at91sam9260.c @@ -419,8 +419,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np, parent_names, &at91rm9200_master_layout, data->mck_characteristics, - &at91sam9260_mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &at91sam9260_mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c index 7ed984f8058c..8c9344451f46 100644 --- a/drivers/clk/at91/at91sam9g45.c +++ b/drivers/clk/at91/at91sam9g45.c @@ -154,8 +154,7 @@ static void __init at91sam9g45_pmc_setup(struct device_node *np) parent_names, &at91rm9200_master_layout, &mck_characteristics, - &at91sam9g45_mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &at91sam9g45_mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c index 63cc58944b00..0bb19400d199 100644 --- a/drivers/clk/at91/at91sam9n12.c +++ b/drivers/clk/at91/at91sam9n12.c @@ -181,8 +181,7 @@ static void __init at91sam9n12_pmc_setup(struct device_node *np) parent_names, &at91sam9x5_master_layout, &mck_characteristics, - &at91sam9n12_mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &at91sam9n12_mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c index 4d4faf6c61d8..b992137bab02 100644 --- a/drivers/clk/at91/at91sam9rl.c +++ b/drivers/clk/at91/at91sam9rl.c @@ -123,8 +123,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) parent_names, &at91rm9200_master_layout, &sam9rl_mck_characteristics, - &sam9rl_mck_lock, CLK_SET_RATE_GATE, - INT_MIN); + &sam9rl_mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c index bd8007b4f3e0..3857db2e144b 100644 --- a/drivers/clk/at91/at91sam9x5.c +++ b/drivers/clk/at91/at91sam9x5.c @@ -201,8 +201,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np, hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, parent_names, &at91sam9x5_master_layout, - &mck_characteristics, &mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index b2d0a7f4f7f9..164e2959c7cf 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c @@ -374,85 +374,6 @@ static void clk_sama7g5_master_best_diff(struct clk_rate_request *req, } } -static int clk_master_pres_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - struct clk_master *master = to_clk_master(hw); - struct clk_rate_request req_parent = *req; - const struct clk_master_characteristics *characteristics = - master->characteristics; - struct clk_hw *parent; - long best_rate = LONG_MIN, best_diff = LONG_MIN; - u32 pres; - int i; - - if (master->chg_pid < 0) - return -EOPNOTSUPP; - - parent = clk_hw_get_parent_by_index(hw, master->chg_pid); - if (!parent) - return -EOPNOTSUPP; - - for (i = 0; i <= MASTER_PRES_MAX; i++) { - if (characteristics->have_div3_pres && i == MASTER_PRES_MAX) - pres = 3; - else - pres = 1 << i; - - req_parent.rate = req->rate * pres; - if (__clk_determine_rate(parent, &req_parent)) - continue; - - clk_sama7g5_master_best_diff(req, parent, req_parent.rate, - &best_diff, &best_rate, pres); - if (!best_diff) - break; - } - - return 0; -} - -static int clk_master_pres_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_master *master = to_clk_master(hw); - unsigned long flags; - unsigned int pres, mckr, tmp; - int ret; - - pres = DIV_ROUND_CLOSEST(parent_rate, rate); - if (pres > MASTER_PRES_MAX) - return -EINVAL; - - else if (pres == 3) - pres = MASTER_PRES_MAX; - else if (pres) - pres = ffs(pres) - 1; - - spin_lock_irqsave(master->lock, flags); - ret = regmap_read(master->regmap, master->layout->offset, &mckr); - if (ret) - goto unlock; - - mckr &= master->layout->mask; - tmp = (mckr >> master->layout->pres_shift) & MASTER_PRES_MASK; - if (pres == tmp) - goto unlock; - - mckr &= ~(MASTER_PRES_MASK << master->layout->pres_shift); - mckr |= (pres << master->layout->pres_shift); - ret = regmap_write(master->regmap, master->layout->offset, mckr); - if (ret) - goto unlock; - - while (!clk_master_ready(master)) - cpu_relax(); -unlock: - spin_unlock_irqrestore(master->lock, flags); - - return ret; -} - static unsigned long clk_master_pres_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { @@ -539,13 +460,6 @@ static void clk_master_pres_restore_context(struct clk_hw *hw) pr_warn("MCKR PRES was not configured properly by firmware!\n"); } -static void clk_master_pres_restore_context_chg(struct clk_hw *hw) -{ - struct clk_master *master = to_clk_master(hw); - - clk_master_pres_set_rate(hw, master->pms.rate, master->pms.parent_rate); -} - static const struct clk_ops master_pres_ops = { .prepare = clk_master_prepare, .is_prepared = clk_master_is_prepared, @@ -555,25 +469,13 @@ static const struct clk_ops master_pres_ops = { .restore_context = clk_master_pres_restore_context, }; -static const struct clk_ops master_pres_ops_chg = { - .prepare = clk_master_prepare, - .is_prepared = clk_master_is_prepared, - .determine_rate = clk_master_pres_determine_rate, - .recalc_rate = clk_master_pres_recalc_rate, - .get_parent = clk_master_pres_get_parent, - .set_rate = clk_master_pres_set_rate, - .save_context = clk_master_pres_save_context, - .restore_context = clk_master_pres_restore_context_chg, -}; - static struct clk_hw * __init at91_clk_register_master_internal(struct regmap *regmap, const char *name, int num_parents, const char **parent_names, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, - const struct clk_ops *ops, spinlock_t *lock, u32 flags, - int chg_pid) + const struct clk_ops *ops, spinlock_t *lock, u32 flags) { struct clk_master *master; struct clk_init_data init; @@ -599,7 +501,6 @@ at91_clk_register_master_internal(struct regmap *regmap, master->layout = layout; master->characteristics = characteristics; master->regmap = regmap; - master->chg_pid = chg_pid; master->lock = lock; if (ops == &master_div_ops_chg) { @@ -628,19 +529,13 @@ at91_clk_register_master_pres(struct regmap *regmap, const char **parent_names, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, - spinlock_t *lock, u32 flags, int chg_pid) + spinlock_t *lock) { - const struct clk_ops *ops; - - if (flags & CLK_SET_RATE_GATE) - ops = &master_pres_ops; - else - ops = &master_pres_ops_chg; - return at91_clk_register_master_internal(regmap, name, num_parents, parent_names, layout, - characteristics, ops, - lock, flags, chg_pid); + characteristics, + &master_pres_ops, + lock, CLK_SET_RATE_GATE); } struct clk_hw * __init @@ -661,7 +556,7 @@ at91_clk_register_master_div(struct regmap *regmap, hw = at91_clk_register_master_internal(regmap, name, 1, &parent_name, layout, characteristics, ops, - lock, flags, -EINVAL); + lock, flags); if (!IS_ERR(hw) && safe_div) { master_div = to_clk_master(hw); diff --git a/drivers/clk/at91/dt-compat.c b/drivers/clk/at91/dt-compat.c index ca2dbb65b9df..8ca8bcacf66d 100644 --- a/drivers/clk/at91/dt-compat.c +++ b/drivers/clk/at91/dt-compat.c @@ -392,8 +392,7 @@ of_at91_clk_master_setup(struct device_node *np, hw = at91_clk_register_master_pres(regmap, "masterck_pres", num_parents, parent_names, layout, - characteristics, &mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + characteristics, &mck_lock); if (IS_ERR(hw)) goto out_free_characteristics; diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 3a1bf6194c28..efe4975bddc3 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -175,7 +175,7 @@ at91_clk_register_master_pres(struct regmap *regmap, const char *name, int num_parents, const char **parent_names, const struct clk_master_layout *layout, const struct clk_master_characteristics *characteristics, - spinlock_t *lock, u32 flags, int chg_pid); + spinlock_t *lock); struct clk_hw * __init at91_clk_register_master_div(struct regmap *regmap, const char *name, diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c index 5c264185f261..9ea4ce501bad 100644 --- a/drivers/clk/at91/sam9x60.c +++ b/drivers/clk/at91/sam9x60.c @@ -271,8 +271,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) parent_names[2] = "pllack_divck"; hw = at91_clk_register_master_pres(regmap, "masterck_pres", 3, parent_names, &sam9x60_master_layout, - &mck_characteristics, &mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c index d027294a0089..cfd0f5e23b99 100644 --- a/drivers/clk/at91/sama5d2.c +++ b/drivers/clk/at91/sama5d2.c @@ -168,7 +168,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) if (IS_ERR(regmap)) return; - sama5d2_pmc = pmc_data_allocate(PMC_AUDIOPLLCK + 1, + sama5d2_pmc = pmc_data_allocate(PMC_AUDIOPINCK + 1, nck(sama5d2_systemck), nck(sama5d2_periph32ck), nck(sama5d2_gck), 3); @@ -216,6 +216,8 @@ static void __init sama5d2_pmc_setup(struct device_node *np) if (IS_ERR(hw)) goto err_free; + sama5d2_pmc->chws[PMC_AUDIOPINCK] = hw; + hw = at91_clk_register_audio_pll_pmc(regmap, "audiopll_pmcck", "audiopll_fracck"); if (IS_ERR(hw)) @@ -240,8 +242,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np) hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, parent_names, &at91sam9x5_master_layout, - &mck_characteristics, &mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/sama5d3.c b/drivers/clk/at91/sama5d3.c index 339d0f382ff0..7e93c6edf305 100644 --- a/drivers/clk/at91/sama5d3.c +++ b/drivers/clk/at91/sama5d3.c @@ -175,8 +175,7 @@ static void __init sama5d3_pmc_setup(struct device_node *np) hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, parent_names, &at91sam9x5_master_layout, - &mck_characteristics, &mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c index 4af75b1e39e9..1a14a9bce308 100644 --- a/drivers/clk/at91/sama5d4.c +++ b/drivers/clk/at91/sama5d4.c @@ -190,8 +190,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np) hw = at91_clk_register_master_pres(regmap, "masterck_pres", 4, parent_names, &at91sam9x5_master_layout, - &mck_characteristics, &mck_lock, - CLK_SET_RATE_GATE, INT_MIN); + &mck_characteristics, &mck_lock); if (IS_ERR(hw)) goto err_free; diff --git a/drivers/clk/at91/sama7g5.c b/drivers/clk/at91/sama7g5.c index 369dfafabbca..9a213ba9e58b 100644 --- a/drivers/clk/at91/sama7g5.c +++ b/drivers/clk/at91/sama7g5.c @@ -302,6 +302,7 @@ static const struct { * @ep_count: extra parents count * @ep_mux_table: mux table for extra parents * @id: clock id + * @eid: export index in sama7g5->chws[] array * @c: true if clock is critical and cannot be disabled */ static const struct { @@ -311,6 +312,7 @@ static const struct { u8 ep_count; u8 ep_mux_table[4]; u8 id; + u8 eid; u8 c; } sama7g5_mckx[] = { { .n = "mck1", @@ -319,6 +321,7 @@ static const struct { .ep_mux_table = { 5, }, .ep_count = 1, .ep_chg_id = INT_MIN, + .eid = PMC_MCK1, .c = 1, }, { .n = "mck2", @@ -696,16 +699,16 @@ static const struct { { .n = "pdmc0_gclk", .id = 68, .r = { .max = 50000000 }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, - .pp_mux_table = { 5, 8, }, + .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, { .n = "pdmc1_gclk", .id = 69, .r = { .max = 50000000, }, - .pp = { "syspll_divpmcck", "baudpll_divpmcck", }, - .pp_mux_table = { 5, 8, }, + .pp = { "syspll_divpmcck", "audiopll_divpmcck", }, + .pp_mux_table = { 5, 9, }, .pp_count = 2, .pp_chg_id = INT_MIN, }, @@ -913,7 +916,7 @@ static void __init sama7g5_pmc_setup(struct device_node *np) if (IS_ERR(regmap)) return; - sama7g5_pmc = pmc_data_allocate(PMC_CPU + 1, + sama7g5_pmc = pmc_data_allocate(PMC_MCK1 + 1, nck(sama7g5_systemck), nck(sama7g5_periphck), nck(sama7g5_gck), 8); @@ -1027,6 +1030,9 @@ static void __init sama7g5_pmc_setup(struct device_node *np) goto err_free; alloc_mem[alloc_mem_size++] = mux_table; + + if (sama7g5_mckx[i].eid) + sama7g5_pmc->chws[sama7g5_mckx[i].eid] = hw; } hw = at91_clk_sama7g5_register_utmi(regmap, "utmick", "main_xtal"); diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c index 2d65770d8665..fdc9b669f8a7 100644 --- a/drivers/clk/at91/sckc.c +++ b/drivers/clk/at91/sckc.c @@ -535,7 +535,7 @@ static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw) /* * Assume that if it has already been selected (for example by the - * bootloader), enough time has aready passed. + * bootloader), enough time has already passed. */ if ((readl(osc->sckcr) & osc->bits->cr_oscsel)) { osc->prepared = true; diff --git a/drivers/clk/axis/clk-artpec6.c b/drivers/clk/axis/clk-artpec6.c index f95959ff85ac..a3f349d4624d 100644 --- a/drivers/clk/axis/clk-artpec6.c +++ b/drivers/clk/axis/clk-artpec6.c @@ -2,7 +2,7 @@ /* * ARTPEC-6 clock initialization * - * Copyright 2015-2016 Axis Comunications AB. + * Copyright 2015-2016 Axis Communications AB. */ #include <linux/clk-provider.h> diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 3667b4d731e7..3ad20e75fd23 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -939,10 +939,8 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw, u32 unused_frac_mask = GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1; u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS; - u64 rem; u32 div, mindiv, maxdiv; - rem = do_div(temp, rate); div = temp; div &= ~unused_frac_mask; diff --git a/drivers/clk/bcm/clk-iproc.h b/drivers/clk/bcm/clk-iproc.h index a48ddd3e0b28..d7e5b94bed45 100644 --- a/drivers/clk/bcm/clk-iproc.h +++ b/drivers/clk/bcm/clk-iproc.h @@ -89,7 +89,7 @@ * Parameters for VCO frequency configuration * * VCO frequency = - * ((ndiv_int + ndiv_frac / 2^20) * (ref freqeuncy / pdiv) + * ((ndiv_int + ndiv_frac / 2^20) * (ref frequency / pdiv) */ struct iproc_pll_vco_param { unsigned long rate; diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c index e65eeef9cbaf..5dd65164c8b1 100644 --- a/drivers/clk/bcm/clk-kona-setup.c +++ b/drivers/clk/bcm/clk-kona-setup.c @@ -510,7 +510,7 @@ static bool kona_clk_valid(struct kona_clk *bcm_clk) * placeholders for non-supported clocks. Keep track of the * position of each clock name in the original array. * - * Allocates an array of pointers to to hold the names of all + * Allocates an array of pointers to hold the names of all * non-null entries in the original array, and returns a pointer to * that array in *names. This will be used for registering the * clock with the common clock code. On successful return, diff --git a/drivers/clk/clk-clps711x.c b/drivers/clk/clk-clps711x.c index a2c6486ef170..f8417ee2961a 100644 --- a/drivers/clk/clk-clps711x.c +++ b/drivers/clk/clk-clps711x.c @@ -28,11 +28,13 @@ static const struct clk_div_table spi_div_table[] = { { .val = 1, .div = 8, }, { .val = 2, .div = 2, }, { .val = 3, .div = 1, }, + { /* sentinel */ } }; static const struct clk_div_table timer_div_table[] = { { .val = 0, .div = 256, }, { .val = 1, .div = 1, }, + { /* sentinel */ } }; struct clps711x_clk { diff --git a/drivers/clk/clk-cs2000-cp.c b/drivers/clk/clk-cs2000-cp.c index 92bc4aca0f95..dc5040a84dcc 100644 --- a/drivers/clk/clk-cs2000-cp.c +++ b/drivers/clk/clk-cs2000-cp.c @@ -11,6 +11,7 @@ #include <linux/i2c.h> #include <linux/of_device.h> #include <linux/module.h> +#include <linux/regmap.h> #define CH_MAX 4 #define RATIO_REG_SIZE 4 @@ -39,6 +40,8 @@ /* DEVICE_CFG1 */ #define RSEL(x) (((x) & 0x3) << 3) #define RSEL_MASK RSEL(0x3) +#define AUXOUTSRC(x) (((x) & 0x3) << 1) +#define AUXOUTSRC_MASK AUXOUTSRC(0x3) #define ENDEV1 (0x1) /* DEVICE_CFG2 */ @@ -47,9 +50,10 @@ #define LOCKCLK_MASK LOCKCLK(0x3) #define FRACNSRC_MASK (1 << 0) #define FRACNSRC_STATIC (0 << 0) -#define FRACNSRC_DYNAMIC (1 << 1) +#define FRACNSRC_DYNAMIC (1 << 0) /* GLOBAL_CFG */ +#define FREEZE (1 << 7) #define ENDEV2 (0x1) /* FUNC_CFG1 */ @@ -71,11 +75,40 @@ #define REF_CLK 1 #define CLK_MAX 2 +static bool cs2000_readable_reg(struct device *dev, unsigned int reg) +{ + return reg > 0; +} + +static bool cs2000_writeable_reg(struct device *dev, unsigned int reg) +{ + return reg != DEVICE_ID; +} + +static bool cs2000_volatile_reg(struct device *dev, unsigned int reg) +{ + return reg == DEVICE_CTRL; +} + +static const struct regmap_config cs2000_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = FUNC_CFG2, + .readable_reg = cs2000_readable_reg, + .writeable_reg = cs2000_writeable_reg, + .volatile_reg = cs2000_volatile_reg, +}; + struct cs2000_priv { struct clk_hw hw; struct i2c_client *client; struct clk *clk_in; struct clk *ref_clk; + struct regmap *regmap; + + bool dynamic_mode; + bool lf_ratio; + bool clk_skip; /* suspend/resume */ unsigned long saved_rate; @@ -94,55 +127,30 @@ static const struct i2c_device_id cs2000_id[] = { }; MODULE_DEVICE_TABLE(i2c, cs2000_id); -#define cs2000_read(priv, addr) \ - i2c_smbus_read_byte_data(priv_to_client(priv), addr) -#define cs2000_write(priv, addr, val) \ - i2c_smbus_write_byte_data(priv_to_client(priv), addr, val) - -static int cs2000_bset(struct cs2000_priv *priv, u8 addr, u8 mask, u8 val) -{ - s32 data; - - data = cs2000_read(priv, addr); - if (data < 0) - return data; - - data &= ~mask; - data |= (val & mask); - - return cs2000_write(priv, addr, data); -} - static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable) { int ret; - ret = cs2000_bset(priv, DEVICE_CFG1, ENDEV1, - enable ? ENDEV1 : 0); - if (ret < 0) - return ret; - - ret = cs2000_bset(priv, GLOBAL_CFG, ENDEV2, - enable ? ENDEV2 : 0); + ret = regmap_update_bits(priv->regmap, DEVICE_CFG1, ENDEV1, + enable ? ENDEV1 : 0); if (ret < 0) return ret; - ret = cs2000_bset(priv, FUNC_CFG1, CLKSKIPEN, - enable ? CLKSKIPEN : 0); + ret = regmap_update_bits(priv->regmap, GLOBAL_CFG, ENDEV2, + enable ? ENDEV2 : 0); if (ret < 0) return ret; - /* FIXME: for Static ratio mode */ - ret = cs2000_bset(priv, FUNC_CFG2, LFRATIO_MASK, - LFRATIO_12_20); + ret = regmap_update_bits(priv->regmap, FUNC_CFG1, CLKSKIPEN, + (enable && priv->clk_skip) ? CLKSKIPEN : 0); if (ret < 0) return ret; return 0; } -static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv, - u32 rate_in) +static int cs2000_ref_clk_bound_rate(struct cs2000_priv *priv, + u32 rate_in) { u32 val; @@ -155,21 +163,21 @@ static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv, else return -EINVAL; - return cs2000_bset(priv, FUNC_CFG1, - REFCLKDIV_MASK, - REFCLKDIV(val)); + return regmap_update_bits(priv->regmap, FUNC_CFG1, + REFCLKDIV_MASK, + REFCLKDIV(val)); } static int cs2000_wait_pll_lock(struct cs2000_priv *priv) { struct device *dev = priv_to_dev(priv); - s32 val; - unsigned int i; + unsigned int i, val; + int ret; for (i = 0; i < 256; i++) { - val = cs2000_read(priv, DEVICE_CTRL); - if (val < 0) - return val; + ret = regmap_read(priv->regmap, DEVICE_CTRL, &val); + if (ret < 0) + return ret; if (!(val & PLL_UNLOCK)) return 0; udelay(1); @@ -183,41 +191,43 @@ static int cs2000_wait_pll_lock(struct cs2000_priv *priv) static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable) { /* enable both AUX_OUT, CLK_OUT */ - return cs2000_bset(priv, DEVICE_CTRL, - (AUXOUTDIS | CLKOUTDIS), - enable ? 0 : - (AUXOUTDIS | CLKOUTDIS)); + return regmap_update_bits(priv->regmap, DEVICE_CTRL, + (AUXOUTDIS | CLKOUTDIS), + enable ? 0 : + (AUXOUTDIS | CLKOUTDIS)); } -static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out) +static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out, bool lf_ratio) { u64 ratio; + u32 multiplier = lf_ratio ? 12 : 20; /* - * ratio = rate_out / rate_in * 2^20 + * ratio = rate_out / rate_in * 2^multiplier * * To avoid over flow, rate_out is u64. * The result should be u32. */ - ratio = (u64)rate_out << 20; + ratio = (u64)rate_out << multiplier; do_div(ratio, rate_in); return ratio; } -static unsigned long cs2000_ratio_to_rate(u32 ratio, u32 rate_in) +static unsigned long cs2000_ratio_to_rate(u32 ratio, u32 rate_in, bool lf_ratio) { u64 rate_out; + u32 multiplier = lf_ratio ? 12 : 20; /* - * ratio = rate_out / rate_in * 2^20 + * ratio = rate_out / rate_in * 2^multiplier * * To avoid over flow, rate_out is u64. * The result should be u32 or unsigned long. */ rate_out = (u64)ratio * rate_in; - return rate_out >> 20; + return rate_out >> multiplier; } static int cs2000_ratio_set(struct cs2000_priv *priv, @@ -230,9 +240,9 @@ static int cs2000_ratio_set(struct cs2000_priv *priv, if (CH_SIZE_ERR(ch)) return -EINVAL; - val = cs2000_rate_to_ratio(rate_in, rate_out); + val = cs2000_rate_to_ratio(rate_in, rate_out, priv->lf_ratio); for (i = 0; i < RATIO_REG_SIZE; i++) { - ret = cs2000_write(priv, + ret = regmap_write(priv->regmap, Ratio_Add(ch, i), Ratio_Val(val, i)); if (ret < 0) @@ -244,14 +254,14 @@ static int cs2000_ratio_set(struct cs2000_priv *priv, static u32 cs2000_ratio_get(struct cs2000_priv *priv, int ch) { - s32 tmp; + unsigned int tmp, i; u32 val; - unsigned int i; + int ret; val = 0; for (i = 0; i < RATIO_REG_SIZE; i++) { - tmp = cs2000_read(priv, Ratio_Add(ch, i)); - if (tmp < 0) + ret = regmap_read(priv->regmap, Ratio_Add(ch, i), &tmp); + if (ret < 0) return 0; val |= Val_Ratio(tmp, i); @@ -263,22 +273,20 @@ static u32 cs2000_ratio_get(struct cs2000_priv *priv, int ch) static int cs2000_ratio_select(struct cs2000_priv *priv, int ch) { int ret; + u8 fracnsrc; if (CH_SIZE_ERR(ch)) return -EINVAL; - /* - * FIXME - * - * this driver supports static ratio mode only at this point. - */ - ret = cs2000_bset(priv, DEVICE_CFG1, RSEL_MASK, RSEL(ch)); + ret = regmap_update_bits(priv->regmap, DEVICE_CFG1, RSEL_MASK, RSEL(ch)); if (ret < 0) return ret; - ret = cs2000_bset(priv, DEVICE_CFG2, - (AUTORMOD | LOCKCLK_MASK | FRACNSRC_MASK), - (LOCKCLK(ch) | FRACNSRC_STATIC)); + fracnsrc = priv->dynamic_mode ? FRACNSRC_DYNAMIC : FRACNSRC_STATIC; + + ret = regmap_update_bits(priv->regmap, DEVICE_CFG2, + AUTORMOD | LOCKCLK_MASK | FRACNSRC_MASK, + LOCKCLK(ch) | fracnsrc); if (ret < 0) return ret; @@ -294,17 +302,39 @@ static unsigned long cs2000_recalc_rate(struct clk_hw *hw, ratio = cs2000_ratio_get(priv, ch); - return cs2000_ratio_to_rate(ratio, parent_rate); + return cs2000_ratio_to_rate(ratio, parent_rate, priv->lf_ratio); } static long cs2000_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate) { + struct cs2000_priv *priv = hw_to_priv(hw); u32 ratio; - ratio = cs2000_rate_to_ratio(*parent_rate, rate); + ratio = cs2000_rate_to_ratio(*parent_rate, rate, priv->lf_ratio); - return cs2000_ratio_to_rate(ratio, *parent_rate); + return cs2000_ratio_to_rate(ratio, *parent_rate, priv->lf_ratio); +} + +static int cs2000_select_ratio_mode(struct cs2000_priv *priv, + unsigned long rate, + unsigned long parent_rate) +{ + /* + * From the datasheet: + * + * | It is recommended that the 12.20 High-Resolution format be + * | utilized whenever the desired ratio is less than 4096 since + * | the output frequency accuracy of the PLL is directly proportional + * | to the accuracy of the timing reference clock and the resolution + * | of the R_UD. + * + * This mode is only available in dynamic mode. + */ + priv->lf_ratio = priv->dynamic_mode && ((rate / parent_rate) > 4096); + + return regmap_update_bits(priv->regmap, FUNC_CFG2, LFRATIO_MASK, + priv->lf_ratio ? LFRATIO_20_12 : LFRATIO_12_20); } static int __cs2000_set_rate(struct cs2000_priv *priv, int ch, @@ -313,7 +343,11 @@ static int __cs2000_set_rate(struct cs2000_priv *priv, int ch, { int ret; - ret = cs2000_clk_in_bound_rate(priv, parent_rate); + ret = regmap_update_bits(priv->regmap, GLOBAL_CFG, FREEZE, FREEZE); + if (ret < 0) + return ret; + + ret = cs2000_select_ratio_mode(priv, rate, parent_rate); if (ret < 0) return ret; @@ -325,6 +359,10 @@ static int __cs2000_set_rate(struct cs2000_priv *priv, int ch, if (ret < 0) return ret; + ret = regmap_update_bits(priv->regmap, GLOBAL_CFG, FREEZE, 0); + if (ret < 0) + return ret; + priv->saved_rate = rate; priv->saved_parent_rate = parent_rate; @@ -380,8 +418,13 @@ static void cs2000_disable(struct clk_hw *hw) static u8 cs2000_get_parent(struct clk_hw *hw) { - /* always return REF_CLK */ - return REF_CLK; + struct cs2000_priv *priv = hw_to_priv(hw); + + /* + * In dynamic mode, output rates are derived from CLK_IN. + * In static mode, CLK_IN is ignored, so we return REF_CLK instead. + */ + return priv->dynamic_mode ? CLK_IN : REF_CLK; } static const struct clk_ops cs2000_ops = { @@ -421,22 +464,44 @@ static int cs2000_clk_register(struct cs2000_priv *priv) struct clk_init_data init; const char *name = np->name; static const char *parent_names[CLK_MAX]; + u32 aux_out = 0; + int ref_clk_rate; int ch = 0; /* it uses ch0 only at this point */ - int rate; int ret; of_property_read_string(np, "clock-output-names", &name); - /* - * set default rate as 1/1. - * otherwise .set_rate which setup ratio - * is never called if user requests 1/1 rate - */ - rate = clk_get_rate(priv->ref_clk); - ret = __cs2000_set_rate(priv, ch, rate, rate); + priv->dynamic_mode = of_property_read_bool(np, "cirrus,dynamic-mode"); + dev_info(dev, "operating in %s mode\n", + priv->dynamic_mode ? "dynamic" : "static"); + + of_property_read_u32(np, "cirrus,aux-output-source", &aux_out); + ret = regmap_update_bits(priv->regmap, DEVICE_CFG1, + AUXOUTSRC_MASK, AUXOUTSRC(aux_out)); + if (ret < 0) + return ret; + + priv->clk_skip = of_property_read_bool(np, "cirrus,clock-skip"); + + ref_clk_rate = clk_get_rate(priv->ref_clk); + ret = cs2000_ref_clk_bound_rate(priv, ref_clk_rate); if (ret < 0) return ret; + if (priv->dynamic_mode) { + /* Default to low-frequency mode to allow for large ratios */ + priv->lf_ratio = true; + } else { + /* + * set default rate as 1/1. + * otherwise .set_rate which setup ratio + * is never called if user requests 1/1 rate + */ + ret = __cs2000_set_rate(priv, ch, ref_clk_rate, ref_clk_rate); + if (ret < 0) + return ret; + } + parent_names[CLK_IN] = __clk_get_name(priv->clk_in); parent_names[REF_CLK] = __clk_get_name(priv->ref_clk); @@ -464,12 +529,13 @@ static int cs2000_clk_register(struct cs2000_priv *priv) static int cs2000_version_print(struct cs2000_priv *priv) { struct device *dev = priv_to_dev(priv); - s32 val; const char *revision; + unsigned int val; + int ret; - val = cs2000_read(priv, DEVICE_ID); - if (val < 0) - return val; + ret = regmap_read(priv->regmap, DEVICE_ID, &val); + if (ret < 0) + return ret; /* CS2000 should be 0x0 */ if (val >> 3) @@ -518,6 +584,10 @@ static int cs2000_probe(struct i2c_client *client, priv->client = client; i2c_set_clientdata(client, priv); + priv->regmap = devm_regmap_init_i2c(client, &cs2000_regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + ret = cs2000_clk_get(priv); if (ret < 0) return ret; diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 4e4b6d367612..54942d758ee6 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -131,6 +131,28 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np, return hw; } +/** + * devm_clk_hw_register_fixed_factor_index - Register a fixed factor clock with + * parent from DT index + * @dev: device that is registering this clock + * @name: name of this clock + * @index: index of phandle in @dev 'clocks' property + * @flags: fixed factor flags + * @mult: multiplier + * @div: divider + * + * Return: Pointer to fixed factor clk_hw structure that was registered or + * an error pointer. + */ +struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev, + const char *name, unsigned int index, unsigned long flags, + unsigned int mult, unsigned int div) +{ + return __clk_hw_register_fixed_factor(dev, NULL, name, NULL, index, + flags, mult, div, true); +} +EXPORT_SYMBOL_GPL(devm_clk_hw_register_fixed_factor_index); + struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div) diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c index 4274540327ce..8efa5142ff8c 100644 --- a/drivers/clk/clk-fractional-divider.c +++ b/drivers/clk/clk-fractional-divider.c @@ -34,7 +34,7 @@ * and assume that the IP, that needs m and n, has also its own * prescaler, which is capable to divide by 2^scale. In this way * we get the denominator to satisfy the desired range (2) and - * at the same time much much better result of m and n than simple + * at the same time a much better result of m and n than simple * saturated values. */ diff --git a/drivers/clk/clk-gate_test.c b/drivers/clk/clk-gate_test.c new file mode 100644 index 000000000000..e136aaad48bf --- /dev/null +++ b/drivers/clk/clk-gate_test.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kunit test for clk gate basic type + */ +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include <kunit/test.h> + +static void clk_gate_register_test_dev(struct kunit *test) +{ + struct clk_hw *ret; + struct platform_device *pdev; + + pdev = platform_device_register_simple("test_gate_device", -1, NULL, 0); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev); + + ret = clk_hw_register_gate(&pdev->dev, "test_gate", NULL, 0, NULL, + 0, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_STREQ(test, "test_gate", clk_hw_get_name(ret)); + KUNIT_EXPECT_EQ(test, 0UL, clk_hw_get_flags(ret)); + + clk_hw_unregister_gate(ret); + platform_device_put(pdev); +} + +static void clk_gate_register_test_parent_names(struct kunit *test) +{ + struct clk_hw *parent; + struct clk_hw *ret; + + parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0, + 1000000); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + + ret = clk_hw_register_gate(NULL, "test_gate", "test_parent", 0, NULL, + 0, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret)); + + clk_hw_unregister_gate(ret); + clk_hw_unregister_fixed_rate(parent); +} + +static void clk_gate_register_test_parent_data(struct kunit *test) +{ + struct clk_hw *parent; + struct clk_hw *ret; + struct clk_parent_data pdata = { }; + + parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0, + 1000000); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + pdata.hw = parent; + + ret = clk_hw_register_gate_parent_data(NULL, "test_gate", &pdata, 0, + NULL, 0, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret)); + + clk_hw_unregister_gate(ret); + clk_hw_unregister_fixed_rate(parent); +} + +static void clk_gate_register_test_parent_data_legacy(struct kunit *test) +{ + struct clk_hw *parent; + struct clk_hw *ret; + struct clk_parent_data pdata = { }; + + parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0, + 1000000); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + pdata.name = "test_parent"; + + ret = clk_hw_register_gate_parent_data(NULL, "test_gate", &pdata, 0, + NULL, 0, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret)); + + clk_hw_unregister_gate(ret); + clk_hw_unregister_fixed_rate(parent); +} + +static void clk_gate_register_test_parent_hw(struct kunit *test) +{ + struct clk_hw *parent; + struct clk_hw *ret; + + parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0, + 1000000); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + + ret = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0, NULL, + 0, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ret); + KUNIT_EXPECT_PTR_EQ(test, parent, clk_hw_get_parent(ret)); + + clk_hw_unregister_gate(ret); + clk_hw_unregister_fixed_rate(parent); +} + +static void clk_gate_register_test_hiword_invalid(struct kunit *test) +{ + struct clk_hw *ret; + + ret = clk_hw_register_gate(NULL, "test_gate", NULL, 0, NULL, + 20, CLK_GATE_HIWORD_MASK, NULL); + + KUNIT_EXPECT_TRUE(test, IS_ERR(ret)); +} + +static struct kunit_case clk_gate_register_test_cases[] = { + KUNIT_CASE(clk_gate_register_test_dev), + KUNIT_CASE(clk_gate_register_test_parent_names), + KUNIT_CASE(clk_gate_register_test_parent_data), + KUNIT_CASE(clk_gate_register_test_parent_data_legacy), + KUNIT_CASE(clk_gate_register_test_parent_hw), + KUNIT_CASE(clk_gate_register_test_hiword_invalid), + {} +}; + +static struct kunit_suite clk_gate_register_test_suite = { + .name = "clk-gate-register-test", + .test_cases = clk_gate_register_test_cases, +}; + +struct clk_gate_test_context { + void __iomem *fake_mem; + struct clk_hw *hw; + struct clk_hw *parent; + u32 fake_reg; /* Keep at end, KASAN can detect out of bounds */ +}; + +static struct clk_gate_test_context *clk_gate_test_alloc_ctx(struct kunit *test) +{ + struct clk_gate_test_context *ctx; + + test->priv = ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); + ctx->fake_mem = (void __force __iomem *)&ctx->fake_reg; + + return ctx; +} + +static void clk_gate_test_parent_rate(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + struct clk_hw *parent = ctx->parent; + struct clk_hw *hw = ctx->hw; + unsigned long prate = clk_hw_get_rate(parent); + unsigned long rate = clk_hw_get_rate(hw); + + KUNIT_EXPECT_EQ(test, prate, rate); +} + +static void clk_gate_test_enable(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + struct clk_hw *parent = ctx->parent; + struct clk_hw *hw = ctx->hw; + struct clk *clk = hw->clk; + u32 enable_val = BIT(5); + + KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); + + KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(parent)); +} + +static void clk_gate_test_disable(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + struct clk_hw *parent = ctx->parent; + struct clk_hw *hw = ctx->hw; + struct clk *clk = hw->clk; + u32 enable_val = BIT(5); + u32 disable_val = 0; + + KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); + KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg); + + clk_disable_unprepare(clk); + KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg); + KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(parent)); +} + +static struct kunit_case clk_gate_test_cases[] = { + KUNIT_CASE(clk_gate_test_parent_rate), + KUNIT_CASE(clk_gate_test_enable), + KUNIT_CASE(clk_gate_test_disable), + {} +}; + +static int clk_gate_test_init(struct kunit *test) +{ + struct clk_hw *parent; + struct clk_hw *hw; + struct clk_gate_test_context *ctx; + + ctx = clk_gate_test_alloc_ctx(test); + parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0, + 2000000); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + + hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0, + ctx->fake_mem, 5, 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + ctx->hw = hw; + ctx->parent = parent; + + return 0; +} + +static void clk_gate_test_exit(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + + clk_hw_unregister_gate(ctx->hw); + clk_hw_unregister_fixed_rate(ctx->parent); +} + +static struct kunit_suite clk_gate_test_suite = { + .name = "clk-gate-test", + .init = clk_gate_test_init, + .exit = clk_gate_test_exit, + .test_cases = clk_gate_test_cases, +}; + +static void clk_gate_test_invert_enable(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + struct clk_hw *parent = ctx->parent; + struct clk_hw *hw = ctx->hw; + struct clk *clk = hw->clk; + u32 enable_val = 0; + + KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); + + KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(parent)); +} + +static void clk_gate_test_invert_disable(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + struct clk_hw *parent = ctx->parent; + struct clk_hw *hw = ctx->hw; + struct clk *clk = hw->clk; + u32 enable_val = 0; + u32 disable_val = BIT(15); + + KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); + KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg); + + clk_disable_unprepare(clk); + KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg); + KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(parent)); +} + +static struct kunit_case clk_gate_test_invert_cases[] = { + KUNIT_CASE(clk_gate_test_invert_enable), + KUNIT_CASE(clk_gate_test_invert_disable), + {} +}; + +static int clk_gate_test_invert_init(struct kunit *test) +{ + struct clk_hw *parent; + struct clk_hw *hw; + struct clk_gate_test_context *ctx; + + ctx = clk_gate_test_alloc_ctx(test); + parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0, + 2000000); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + + ctx->fake_reg = BIT(15); /* Default to off */ + hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0, + ctx->fake_mem, 15, + CLK_GATE_SET_TO_DISABLE, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + ctx->hw = hw; + ctx->parent = parent; + + return 0; +} + +static struct kunit_suite clk_gate_test_invert_suite = { + .name = "clk-gate-invert-test", + .init = clk_gate_test_invert_init, + .exit = clk_gate_test_exit, + .test_cases = clk_gate_test_invert_cases, +}; + +static void clk_gate_test_hiword_enable(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + struct clk_hw *parent = ctx->parent; + struct clk_hw *hw = ctx->hw; + struct clk *clk = hw->clk; + u32 enable_val = BIT(9) | BIT(9 + 16); + + KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); + + KUNIT_EXPECT_EQ(test, enable_val, ctx->fake_reg); + KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(hw)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(hw)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_enabled(parent)); + KUNIT_EXPECT_TRUE(test, clk_hw_is_prepared(parent)); +} + +static void clk_gate_test_hiword_disable(struct kunit *test) +{ + struct clk_gate_test_context *ctx = test->priv; + struct clk_hw *parent = ctx->parent; + struct clk_hw *hw = ctx->hw; + struct clk *clk = hw->clk; + u32 enable_val = BIT(9) | BIT(9 + 16); + u32 disable_val = BIT(9 + 16); + + KUNIT_ASSERT_EQ(test, clk_prepare_enable(clk), 0); + KUNIT_ASSERT_EQ(test, enable_val, ctx->fake_reg); + + clk_disable_unprepare(clk); + KUNIT_EXPECT_EQ(test, disable_val, ctx->fake_reg); + KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(hw)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(hw)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_enabled(parent)); + KUNIT_EXPECT_FALSE(test, clk_hw_is_prepared(parent)); +} + +static struct kunit_case clk_gate_test_hiword_cases[] = { + KUNIT_CASE(clk_gate_test_hiword_enable), + KUNIT_CASE(clk_gate_test_hiword_disable), + {} +}; + +static int clk_gate_test_hiword_init(struct kunit *test) +{ + struct clk_hw *parent; + struct clk_hw *hw; + struct clk_gate_test_context *ctx; + + ctx = clk_gate_test_alloc_ctx(test); + parent = clk_hw_register_fixed_rate(NULL, "test_parent", NULL, 0, + 2000000); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, parent); + + hw = clk_hw_register_gate_parent_hw(NULL, "test_gate", parent, 0, + ctx->fake_mem, 9, + CLK_GATE_HIWORD_MASK, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + + ctx->hw = hw; + ctx->parent = parent; + + return 0; +} + +static struct kunit_suite clk_gate_test_hiword_suite = { + .name = "clk-gate-hiword-test", + .init = clk_gate_test_hiword_init, + .exit = clk_gate_test_exit, + .test_cases = clk_gate_test_hiword_cases, +}; + +static void clk_gate_test_is_enabled(struct kunit *test) +{ + struct clk_hw *hw; + struct clk_gate_test_context *ctx; + + ctx = clk_gate_test_alloc_ctx(test); + ctx->fake_reg = BIT(7); + hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7, + 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + KUNIT_ASSERT_TRUE(test, clk_hw_is_enabled(hw)); + + clk_hw_unregister_gate(hw); +} + +static void clk_gate_test_is_disabled(struct kunit *test) +{ + struct clk_hw *hw; + struct clk_gate_test_context *ctx; + + ctx = clk_gate_test_alloc_ctx(test); + ctx->fake_reg = BIT(4); + hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 7, + 0, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + KUNIT_ASSERT_FALSE(test, clk_hw_is_enabled(hw)); + + clk_hw_unregister_gate(hw); +} + +static void clk_gate_test_is_enabled_inverted(struct kunit *test) +{ + struct clk_hw *hw; + struct clk_gate_test_context *ctx; + + ctx = clk_gate_test_alloc_ctx(test); + ctx->fake_reg = BIT(31); + hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 2, + CLK_GATE_SET_TO_DISABLE, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + KUNIT_ASSERT_TRUE(test, clk_hw_is_enabled(hw)); + + clk_hw_unregister_gate(hw); +} + +static void clk_gate_test_is_disabled_inverted(struct kunit *test) +{ + struct clk_hw *hw; + struct clk_gate_test_context *ctx; + + ctx = clk_gate_test_alloc_ctx(test); + ctx->fake_reg = BIT(29); + hw = clk_hw_register_gate(NULL, "test_gate", NULL, 0, ctx->fake_mem, 29, + CLK_GATE_SET_TO_DISABLE, NULL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, hw); + KUNIT_ASSERT_FALSE(test, clk_hw_is_enabled(hw)); + + clk_hw_unregister_gate(hw); +} + +static struct kunit_case clk_gate_test_enabled_cases[] = { + KUNIT_CASE(clk_gate_test_is_enabled), + KUNIT_CASE(clk_gate_test_is_disabled), + KUNIT_CASE(clk_gate_test_is_enabled_inverted), + KUNIT_CASE(clk_gate_test_is_disabled_inverted), + {} +}; + +static struct kunit_suite clk_gate_test_enabled_suite = { + .name = "clk-gate-is_enabled-test", + .test_cases = clk_gate_test_enabled_cases, +}; + +kunit_test_suites( + &clk_gate_register_test_suite, + &clk_gate_test_suite, + &clk_gate_test_invert_suite, + &clk_gate_test_hiword_suite, + &clk_gate_test_enabled_suite +); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 20582aae7a35..214045f6e989 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c @@ -40,7 +40,7 @@ static inline void clk_mux_writel(struct clk_mux *mux, u32 val) writel(val, mux->reg); } -int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, +int clk_mux_val_to_index(struct clk_hw *hw, const u32 *table, unsigned int flags, unsigned int val) { int num_parents = clk_hw_get_num_parents(hw); @@ -67,7 +67,7 @@ int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, } EXPORT_SYMBOL_GPL(clk_mux_val_to_index); -unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index) +unsigned int clk_mux_index_to_val(const u32 *table, unsigned int flags, u8 index) { unsigned int val = index; @@ -152,7 +152,7 @@ struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np, const struct clk_hw **parent_hws, const struct clk_parent_data *parent_data, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock) + u8 clk_mux_flags, const u32 *table, spinlock_t *lock) { struct clk_mux *mux; struct clk_hw *hw; @@ -218,7 +218,7 @@ struct clk_hw *__devm_clk_hw_register_mux(struct device *dev, struct device_node const struct clk_hw **parent_hws, const struct clk_parent_data *parent_data, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock) + u8 clk_mux_flags, const u32 *table, spinlock_t *lock) { struct clk_hw **ptr, *hw; @@ -244,7 +244,7 @@ EXPORT_SYMBOL_GPL(__devm_clk_hw_register_mux); struct clk *clk_register_mux_table(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock) + u8 clk_mux_flags, const u32 *table, spinlock_t *lock) { struct clk_hw *hw; diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c index 78d5ea669fea..cda5e258355b 100644 --- a/drivers/clk/clk-oxnas.c +++ b/drivers/clk/clk-oxnas.c @@ -209,15 +209,11 @@ static int oxnas_stdclk_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; const struct oxnas_stdclk_data *data; - const struct of_device_id *id; struct regmap *regmap; int ret; int i; - id = of_match_device(oxnas_stdclk_dt_ids, &pdev->dev); - if (!id) - return -ENODEV; - data = id->data; + data = of_device_get_match_data(&pdev->dev); regmap = syscon_node_to_regmap(of_get_parent(np)); if (IS_ERR(regmap)) { diff --git a/drivers/clk/clk-renesas-pcie.c b/drivers/clk/clk-renesas-pcie.c new file mode 100644 index 000000000000..59d9cf0053eb --- /dev/null +++ b/drivers/clk/clk-renesas-pcie.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Renesas 9-series PCIe clock generator driver + * + * The following series can be supported: + * - 9FGV/9DBV/9DMV/9FGL/9DML/9QXL/9SQ + * Currently supported: + * - 9FGV0241 + * + * Copyright (C) 2022 Marek Vasut <marex@denx.de> + */ + +#include <linux/clk-provider.h> +#include <linux/i2c.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regmap.h> + +#define RS9_REG_OE 0x0 +#define RS9_REG_OE_DIF_OE(n) BIT((n) + 1) +#define RS9_REG_SS 0x1 +#define RS9_REG_SS_AMP_0V6 0x0 +#define RS9_REG_SS_AMP_0V7 0x1 +#define RS9_REG_SS_AMP_0V8 0x2 +#define RS9_REG_SS_AMP_0V9 0x3 +#define RS9_REG_SS_AMP_MASK 0x3 +#define RS9_REG_SS_SSC_100 0 +#define RS9_REG_SS_SSC_M025 (1 << 3) +#define RS9_REG_SS_SSC_M050 (3 << 3) +#define RS9_REG_SS_SSC_MASK (3 << 3) +#define RS9_REG_SS_SSC_LOCK BIT(5) +#define RS9_REG_SR 0x2 +#define RS9_REG_SR_2V0_DIF(n) 0 +#define RS9_REG_SR_3V0_DIF(n) BIT((n) + 1) +#define RS9_REG_SR_DIF_MASK(n) BIT((n) + 1) +#define RS9_REG_REF 0x3 +#define RS9_REG_REF_OE BIT(4) +#define RS9_REG_REF_OD BIT(5) +#define RS9_REG_REF_SR_SLOWEST 0 +#define RS9_REG_REF_SR_SLOW (1 << 6) +#define RS9_REG_REF_SR_FAST (2 << 6) +#define RS9_REG_REF_SR_FASTER (3 << 6) +#define RS9_REG_VID 0x5 +#define RS9_REG_DID 0x6 +#define RS9_REG_BCP 0x7 + +/* Supported Renesas 9-series models. */ +enum rs9_model { + RENESAS_9FGV0241, +}; + +/* Structure to describe features of a particular 9-series model */ +struct rs9_chip_info { + const enum rs9_model model; + unsigned int num_clks; +}; + +struct rs9_driver_data { + struct i2c_client *client; + struct regmap *regmap; + const struct rs9_chip_info *chip_info; + struct clk *pin_xin; + struct clk_hw *clk_dif[2]; + u8 pll_amplitude; + u8 pll_ssc; + u8 clk_dif_sr; +}; + +/* + * Renesas 9-series i2c regmap + */ +static const struct regmap_range rs9_readable_ranges[] = { + regmap_reg_range(RS9_REG_OE, RS9_REG_REF), + regmap_reg_range(RS9_REG_VID, RS9_REG_BCP), +}; + +static const struct regmap_access_table rs9_readable_table = { + .yes_ranges = rs9_readable_ranges, + .n_yes_ranges = ARRAY_SIZE(rs9_readable_ranges), +}; + +static const struct regmap_range rs9_writeable_ranges[] = { + regmap_reg_range(RS9_REG_OE, RS9_REG_REF), + regmap_reg_range(RS9_REG_BCP, RS9_REG_BCP), +}; + +static const struct regmap_access_table rs9_writeable_table = { + .yes_ranges = rs9_writeable_ranges, + .n_yes_ranges = ARRAY_SIZE(rs9_writeable_ranges), +}; + +static const struct regmap_config rs9_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_FLAT, + .max_register = 0x8, + .rd_table = &rs9_readable_table, + .wr_table = &rs9_writeable_table, +}; + +static int rs9_get_output_config(struct rs9_driver_data *rs9, int idx) +{ + struct i2c_client *client = rs9->client; + unsigned char name[5] = "DIF0"; + struct device_node *np; + int ret; + u32 sr; + + /* Set defaults */ + rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx); + rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx); + + snprintf(name, 5, "DIF%d", idx); + np = of_get_child_by_name(client->dev.of_node, name); + if (!np) + return 0; + + /* Output clock slew rate */ + ret = of_property_read_u32(np, "renesas,slew-rate", &sr); + of_node_put(np); + if (!ret) { + if (sr == 2000000) { /* 2V/ns */ + rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx); + rs9->clk_dif_sr |= RS9_REG_SR_2V0_DIF(idx); + } else if (sr == 3000000) { /* 3V/ns (default) */ + rs9->clk_dif_sr &= ~RS9_REG_SR_DIF_MASK(idx); + rs9->clk_dif_sr |= RS9_REG_SR_3V0_DIF(idx); + } else + ret = dev_err_probe(&client->dev, -EINVAL, + "Invalid renesas,slew-rate value\n"); + } + + return ret; +} + +static int rs9_get_common_config(struct rs9_driver_data *rs9) +{ + struct i2c_client *client = rs9->client; + struct device_node *np = client->dev.of_node; + unsigned int amp, ssc; + int ret; + + /* Set defaults */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V7; + rs9->pll_ssc = RS9_REG_SS_SSC_100; + + /* Output clock amplitude */ + ret = of_property_read_u32(np, "renesas,out-amplitude-microvolt", + &); + if (!ret) { + if (amp == 600000) /* 0.6V */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V6; + else if (amp == 700000) /* 0.7V (default) */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V7; + else if (amp == 800000) /* 0.8V */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V8; + else if (amp == 900000) /* 0.9V */ + rs9->pll_amplitude = RS9_REG_SS_AMP_0V9; + else + return dev_err_probe(&client->dev, -EINVAL, + "Invalid renesas,out-amplitude-microvolt value\n"); + } + + /* Output clock spread spectrum */ + ret = of_property_read_u32(np, "renesas,out-spread-spectrum", &ssc); + if (!ret) { + if (ssc == 100000) /* 100% ... no spread (default) */ + rs9->pll_ssc = RS9_REG_SS_SSC_100; + else if (ssc == 99750) /* -0.25% ... down spread */ + rs9->pll_ssc = RS9_REG_SS_SSC_M025; + else if (ssc == 99500) /* -0.50% ... down spread */ + rs9->pll_ssc = RS9_REG_SS_SSC_M050; + else + return dev_err_probe(&client->dev, -EINVAL, + "Invalid renesas,out-spread-spectrum value\n"); + } + + return 0; +} + +static void rs9_update_config(struct rs9_driver_data *rs9) +{ + int i; + + /* If amplitude is non-default, update it. */ + if (rs9->pll_amplitude != RS9_REG_SS_AMP_0V7) { + regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_AMP_MASK, + rs9->pll_amplitude); + } + + /* If SSC is non-default, update it. */ + if (rs9->pll_ssc != RS9_REG_SS_SSC_100) { + regmap_update_bits(rs9->regmap, RS9_REG_SS, RS9_REG_SS_SSC_MASK, + rs9->pll_ssc); + } + + for (i = 0; i < rs9->chip_info->num_clks; i++) { + if (rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i)) + continue; + + regmap_update_bits(rs9->regmap, RS9_REG_SR, RS9_REG_SR_3V0_DIF(i), + rs9->clk_dif_sr & RS9_REG_SR_3V0_DIF(i)); + } +} + +static struct clk_hw * +rs9_of_clk_get(struct of_phandle_args *clkspec, void *data) +{ + struct rs9_driver_data *rs9 = data; + unsigned int idx = clkspec->args[0]; + + return rs9->clk_dif[idx]; +} + +static int rs9_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + unsigned char name[5] = "DIF0"; + struct rs9_driver_data *rs9; + struct clk_hw *hw; + int i, ret; + + rs9 = devm_kzalloc(&client->dev, sizeof(*rs9), GFP_KERNEL); + if (!rs9) + return -ENOMEM; + + i2c_set_clientdata(client, rs9); + rs9->client = client; + rs9->chip_info = device_get_match_data(&client->dev); + if (!rs9->chip_info) + return -EINVAL; + + /* Fetch common configuration from DT (if specified) */ + ret = rs9_get_common_config(rs9); + if (ret) + return ret; + + /* Fetch DIFx output configuration from DT (if specified) */ + for (i = 0; i < rs9->chip_info->num_clks; i++) { + ret = rs9_get_output_config(rs9, i); + if (ret) + return ret; + } + + rs9->regmap = devm_regmap_init_i2c(client, &rs9_regmap_config); + if (IS_ERR(rs9->regmap)) + return dev_err_probe(&client->dev, PTR_ERR(rs9->regmap), + "Failed to allocate register map\n"); + + /* Register clock */ + for (i = 0; i < rs9->chip_info->num_clks; i++) { + snprintf(name, 5, "DIF%d", i); + hw = devm_clk_hw_register_fixed_factor_index(&client->dev, name, + 0, 0, 4, 1); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + rs9->clk_dif[i] = hw; + } + + ret = devm_of_clk_add_hw_provider(&client->dev, rs9_of_clk_get, rs9); + if (!ret) + rs9_update_config(rs9); + + return ret; +} + +static int __maybe_unused rs9_suspend(struct device *dev) +{ + struct rs9_driver_data *rs9 = dev_get_drvdata(dev); + + regcache_cache_only(rs9->regmap, true); + regcache_mark_dirty(rs9->regmap); + + return 0; +} + +static int __maybe_unused rs9_resume(struct device *dev) +{ + struct rs9_driver_data *rs9 = dev_get_drvdata(dev); + int ret; + + regcache_cache_only(rs9->regmap, false); + ret = regcache_sync(rs9->regmap); + if (ret) + dev_err(dev, "Failed to restore register map: %d\n", ret); + return ret; +} + +static const struct rs9_chip_info renesas_9fgv0241_info = { + .model = RENESAS_9FGV0241, + .num_clks = 2, +}; + +static const struct i2c_device_id rs9_id[] = { + { "9fgv0241", .driver_data = RENESAS_9FGV0241 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rs9_id); + +static const struct of_device_id clk_rs9_of_match[] = { + { .compatible = "renesas,9fgv0241", .data = &renesas_9fgv0241_info }, + { } +}; +MODULE_DEVICE_TABLE(of, clk_rs9_of_match); + +static SIMPLE_DEV_PM_OPS(rs9_pm_ops, rs9_suspend, rs9_resume); + +static struct i2c_driver rs9_driver = { + .driver = { + .name = "clk-renesas-pcie-9series", + .pm = &rs9_pm_ops, + .of_match_table = clk_rs9_of_match, + }, + .probe = rs9_probe, + .id_table = rs9_id, +}; +module_i2c_driver(rs9_driver); + +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Renesas 9-series PCIe clock generator driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index f7b41366666e..41851f41b682 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -655,7 +655,7 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw, f = synth->data->freq_vco; f *= n_den >> 4; - /* Now we need to to 64-bit division: f/n_num */ + /* Now we need to do 64-bit division: f/n_num */ /* And compensate for the 4 bits we dropped */ f = div64_u64(f, (n_num >> 4)); @@ -798,6 +798,15 @@ static unsigned long si5341_output_clk_recalc_rate(struct clk_hw *hw, u32 r_divider; u8 r[3]; + err = regmap_read(output->data->regmap, + SI5341_OUT_CONFIG(output), &val); + if (err < 0) + return err; + + /* If SI5341_OUT_CFG_RDIV_FORCE2 is set, r_divider is 2 */ + if (val & SI5341_OUT_CFG_RDIV_FORCE2) + return parent_rate / 2; + err = regmap_bulk_read(output->data->regmap, SI5341_OUT_R_REG(output), r, 3); if (err < 0) @@ -814,13 +823,6 @@ static unsigned long si5341_output_clk_recalc_rate(struct clk_hw *hw, r_divider += 1; r_divider <<= 1; - err = regmap_read(output->data->regmap, - SI5341_OUT_CONFIG(output), &val); - if (err < 0) - return err; - - if (val & SI5341_OUT_CFG_RDIV_FORCE2) - r_divider = 2; return parent_rate / r_divider; } @@ -1468,7 +1470,7 @@ static ssize_t input_present_show(struct device *dev, if (res < 0) return res; res = !(status & SI5341_STATUS_LOSREF); - return snprintf(buf, PAGE_SIZE, "%d\n", res); + return sysfs_emit(buf, "%d\n", res); } static DEVICE_ATTR_RO(input_present); @@ -1483,7 +1485,7 @@ static ssize_t input_present_sticky_show(struct device *dev, if (res < 0) return res; res = !(status & SI5341_STATUS_LOSREF); - return snprintf(buf, PAGE_SIZE, "%d\n", res); + return sysfs_emit(buf, "%d\n", res); } static DEVICE_ATTR_RO(input_present_sticky); @@ -1498,7 +1500,7 @@ static ssize_t pll_locked_show(struct device *dev, if (res < 0) return res; res = !(status & SI5341_STATUS_LOL); - return snprintf(buf, PAGE_SIZE, "%d\n", res); + return sysfs_emit(buf, "%d\n", res); } static DEVICE_ATTR_RO(pll_locked); @@ -1513,7 +1515,7 @@ static ssize_t pll_locked_sticky_show(struct device *dev, if (res < 0) return res; res = !(status & SI5341_STATUS_LOL); - return snprintf(buf, PAGE_SIZE, "%d\n", res); + return sysfs_emit(buf, "%d\n", res); } static DEVICE_ATTR_RO(pll_locked_sticky); diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c index 863274aa50e3..7ad2e6203bae 100644 --- a/drivers/clk/clk-stm32mp1.c +++ b/drivers/clk/clk-stm32mp1.c @@ -155,6 +155,10 @@ static const char * const eth_src[] = { "pll4_p", "pll3_q" }; +const struct clk_parent_data ethrx_src[] = { + { .name = "ethck_k", .fw_name = "ETH_RX_CLK/ETH_REF_CLK" }, +}; + static const char * const rng_src[] = { "ck_csi", "pll4_r", "ck_lse", "ck_lsi" }; @@ -317,6 +321,7 @@ struct clock_config { const char *name; const char *parent_name; const char * const *parent_names; + const struct clk_parent_data *parent_data; int num_parents; unsigned long flags; void *cfg; @@ -576,6 +581,7 @@ static struct clk_hw * clk_stm32_register_gate_ops(struct device *dev, const char *name, const char *parent_name, + const struct clk_parent_data *parent_data, unsigned long flags, void __iomem *base, const struct stm32_gate_cfg *cfg, @@ -586,7 +592,10 @@ clk_stm32_register_gate_ops(struct device *dev, int ret; init.name = name; - init.parent_names = &parent_name; + if (parent_name) + init.parent_names = &parent_name; + if (parent_data) + init.parent_data = parent_data; init.num_parents = 1; init.flags = flags; @@ -611,6 +620,7 @@ clk_stm32_register_gate_ops(struct device *dev, static struct clk_hw * clk_stm32_register_composite(struct device *dev, const char *name, const char * const *parent_names, + const struct clk_parent_data *parent_data, int num_parents, void __iomem *base, const struct stm32_composite_cfg *cfg, unsigned long flags, spinlock_t *lock) @@ -1135,6 +1145,7 @@ _clk_stm32_register_gate(struct device *dev, return clk_stm32_register_gate_ops(dev, cfg->name, cfg->parent_name, + cfg->parent_data, cfg->flags, base, cfg->cfg, @@ -1148,8 +1159,8 @@ _clk_stm32_register_composite(struct device *dev, const struct clock_config *cfg) { return clk_stm32_register_composite(dev, cfg->name, cfg->parent_names, - cfg->num_parents, base, cfg->cfg, - cfg->flags, lock); + cfg->parent_data, cfg->num_parents, + base, cfg->cfg, cfg->flags, lock); } #define GATE(_id, _name, _parent, _flags, _offset, _bit_idx, _gate_flags)\ @@ -1258,6 +1269,16 @@ _clk_stm32_register_composite(struct device *dev, .func = _clk_stm32_register_gate,\ } +#define STM32_GATE_PDATA(_id, _name, _parent, _flags, _gate)\ +{\ + .id = _id,\ + .name = _name,\ + .parent_data = _parent,\ + .flags = _flags,\ + .cfg = (struct stm32_gate_cfg *) {_gate},\ + .func = _clk_stm32_register_gate,\ +} + #define _STM32_GATE(_gate_offset, _gate_bit_idx, _gate_flags, _mgate, _ops)\ (&(struct stm32_gate_cfg) {\ &(struct gate_cfg) {\ @@ -1291,6 +1312,10 @@ _clk_stm32_register_composite(struct device *dev, STM32_GATE(_id, _name, _parent, _flags,\ _STM32_MGATE(_mgate)) +#define MGATE_MP1_PDATA(_id, _name, _parent, _flags, _mgate)\ + STM32_GATE_PDATA(_id, _name, _parent, _flags,\ + _STM32_MGATE(_mgate)) + #define _STM32_DIV(_div_offset, _div_shift, _div_width,\ _div_flags, _div_table, _ops)\ .div = &(struct stm32_div_cfg) {\ @@ -1354,6 +1379,9 @@ _clk_stm32_register_composite(struct device *dev, #define PCLK(_id, _name, _parent, _flags, _mgate)\ MGATE_MP1(_id, _name, _parent, _flags, _mgate) +#define PCLK_PDATA(_id, _name, _parent, _flags, _mgate)\ + MGATE_MP1_PDATA(_id, _name, _parent, _flags, _mgate) + #define KCLK(_id, _name, _parents, _flags, _mgate, _mmux)\ COMPOSITE(_id, _name, _parents, CLK_OPS_PARENT_ENABLE |\ CLK_SET_RATE_NO_REPARENT | _flags,\ @@ -1951,7 +1979,7 @@ static const struct clock_config stm32mp1_clock_cfg[] = { PCLK(MDMA, "mdma", "ck_axi", 0, G_MDMA), PCLK(GPU, "gpu", "ck_axi", 0, G_GPU), PCLK(ETHTX, "ethtx", "ck_axi", 0, G_ETHTX), - PCLK(ETHRX, "ethrx", "ck_axi", 0, G_ETHRX), + PCLK_PDATA(ETHRX, "ethrx", ethrx_src, 0, G_ETHRX), PCLK(ETHMAC, "ethmac", "ck_axi", 0, G_ETHMAC), PCLK(FMC, "fmc", "ck_axi", CLK_IGNORE_UNUSED, G_FMC), PCLK(QSPI, "qspi", "ck_axi", CLK_IGNORE_UNUSED, G_QSPI), @@ -2008,7 +2036,6 @@ static const struct clock_config stm32mp1_clock_cfg[] = { KCLK(DSI_K, "dsi_k", dsi_src, 0, G_DSI, M_DSI), KCLK(ADFSDM_K, "adfsdm_k", sai_src, 0, G_ADFSDM, M_SAI1), KCLK(USBO_K, "usbo_k", usbo_src, 0, G_USBO, M_USBO), - KCLK(ETHCK_K, "ethck_k", eth_src, 0, G_ETHCK, M_ETHCK), /* Particulary Kernel Clocks (no mux or no gate) */ MGATE_MP1(DFSDM_K, "dfsdm_k", "ck_mcu", 0, G_DFSDM), @@ -2017,11 +2044,16 @@ static const struct clock_config stm32mp1_clock_cfg[] = { MGATE_MP1(GPU_K, "gpu_k", "pll2_q", 0, G_GPU), MGATE_MP1(DAC12_K, "dac12_k", "ck_lsi", 0, G_DAC12), - COMPOSITE(ETHPTP_K, "ethptp_k", eth_src, CLK_OPS_PARENT_ENABLE | + COMPOSITE(NO_ID, "ck_ker_eth", eth_src, CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_NO_REPARENT, _NO_GATE, _MMUX(M_ETHCK), - _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)), + _NO_DIV), + + MGATE_MP1(ETHCK_K, "ethck_k", "ck_ker_eth", 0, G_ETHCK), + + DIV(ETHPTP_K, "ethptp_k", "ck_ker_eth", CLK_OPS_PARENT_ENABLE | + CLK_SET_RATE_NO_REPARENT, RCC_ETHCKSELR, 4, 4, 0), /* RTC clock */ COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE, diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8de6a22498e7..d15997ea3930 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -37,7 +37,7 @@ static HLIST_HEAD(clk_root_list); static HLIST_HEAD(clk_orphan_list); static LIST_HEAD(clk_notifier_list); -static struct hlist_head *all_lists[] = { +static const struct hlist_head *all_lists[] = { &clk_root_list, &clk_orphan_list, NULL, @@ -4079,7 +4079,7 @@ static const struct clk_ops clk_nodrv_ops = { }; static void clk_core_evict_parent_cache_subtree(struct clk_core *root, - struct clk_core *target) + const struct clk_core *target) { int i; struct clk_core *child; @@ -4095,7 +4095,7 @@ static void clk_core_evict_parent_cache_subtree(struct clk_core *root, /* Remove this clk from all parent caches */ static void clk_core_evict_parent_cache(struct clk_core *core) { - struct hlist_head **lists; + const struct hlist_head **lists; struct clk_core *root; lockdep_assert_held(&prepare_lock); diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c index 56012a3d0219..9ea1a80acbe8 100644 --- a/drivers/clk/hisilicon/clk-hi3559a.c +++ b/drivers/clk/hisilicon/clk-hi3559a.c @@ -611,8 +611,8 @@ static struct hisi_mux_clock hi3559av100_shub_mux_clks[] = { /* shub div clk */ -static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}}; -static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}}; +static struct clk_div_table shub_spi_clk_table[] = {{0, 8}, {1, 4}, {2, 2}, {/*sentinel*/}}; +static struct clk_div_table shub_uart_div_clk_table[] = {{1, 8}, {2, 4}, {/*sentinel*/}}; static struct hisi_divider_clock hi3559av100_shub_div_clks[] = { { HI3559AV100_SHUB_SPI_SOURCE_CLK, "clk_spi_clk", "shub_clk", 0, 0x20, 24, 2, diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c index 9361fba7cd4c..54d9fdc93599 100644 --- a/drivers/clk/hisilicon/clk.c +++ b/drivers/clk/hisilicon/clk.c @@ -162,7 +162,7 @@ int hisi_clk_register_mux(const struct hisi_mux_clock *clks, clks[i].num_parents, clks[i].flags, base + clks[i].offset, clks[i].shift, mask, clks[i].mux_flags, - (u32 *)clks[i].table, &hisi_clk_lock); + clks[i].table, &hisi_clk_lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, clks[i].name); diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig index c08edbd04d22..25785ec9c276 100644 --- a/drivers/clk/imx/Kconfig +++ b/drivers/clk/imx/Kconfig @@ -105,3 +105,17 @@ config CLK_IMX8ULP select MXC_CLK help Build the driver for i.MX8ULP CCM Clock Driver + +config CLK_IMX93 + tristate "IMX93 CCM Clock Driver" + depends on ARCH_MXC || COMPILE_TEST + select MXC_CLK + help + Build the driver for i.MX93 CCM Clock Driver + +config CLK_IMXRT1050 + tristate "IMXRT1050 CCM Clock Driver" + depends on SOC_IMXRT + select MXC_CLK + help + Build the driver for i.MXRT1050 CCM Clock Driver diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile index b5e040026dfb..88b9b9285d22 100644 --- a/drivers/clk/imx/Makefile +++ b/drivers/clk/imx/Makefile @@ -4,6 +4,8 @@ mxc-clk-objs += clk.o mxc-clk-objs += clk-busy.o mxc-clk-objs += clk-composite-7ulp.o mxc-clk-objs += clk-composite-8m.o +mxc-clk-objs += clk-composite-93.o +mxc-clk-objs += clk-fracn-gppll.o mxc-clk-objs += clk-cpu.o mxc-clk-objs += clk-divider-gate.o mxc-clk-objs += clk-fixup-div.o @@ -26,9 +28,12 @@ obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o +obj-$(CONFIG_CLK_IMX93) += clk-imx93.o + obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \ - clk-imx8qxp-rsrc.o clk-imx8qm-rsrc.o + clk-imx8qxp-rsrc.o clk-imx8qm-rsrc.o \ + clk-imx8dxl-rsrc.o clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o obj-$(CONFIG_CLK_IMX8ULP) += clk-imx8ulp.o @@ -46,4 +51,5 @@ obj-$(CONFIG_CLK_IMX6SX) += clk-imx6sx.o obj-$(CONFIG_CLK_IMX6UL) += clk-imx6ul.o obj-$(CONFIG_CLK_IMX7D) += clk-imx7d.o obj-$(CONFIG_CLK_IMX7ULP) += clk-imx7ulp.o +obj-$(CONFIG_CLK_IMXRT1050) += clk-imxrt1050.o obj-$(CONFIG_CLK_VF610) += clk-vf610.o diff --git a/drivers/clk/imx/clk-composite-93.c b/drivers/clk/imx/clk-composite-93.c new file mode 100644 index 000000000000..b44619aa5ca5 --- /dev/null +++ b/drivers/clk/imx/clk-composite-93.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 NXP + * + * Peng Fan <peng.fan@nxp.com> + */ + +#include <linux/clk-provider.h> +#include <linux/errno.h> +#include <linux/export.h> +#include <linux/io.h> +#include <linux/slab.h> + +#include "clk.h" + +#define CCM_DIV_SHIFT 0 +#define CCM_DIV_WIDTH 8 +#define CCM_MUX_SHIFT 8 +#define CCM_MUX_MASK 3 +#define CCM_OFF_SHIFT 24 + +#define AUTHEN_OFFSET 0x30 +#define TZ_NS_SHIFT 9 +#define TZ_NS_MASK BIT(9) + +struct clk_hw *imx93_clk_composite_flags(const char *name, const char * const *parent_names, + int num_parents, void __iomem *reg, + unsigned long flags) +{ + struct clk_hw *hw = ERR_PTR(-ENOMEM), *mux_hw; + struct clk_hw *div_hw, *gate_hw; + struct clk_divider *div = NULL; + struct clk_gate *gate = NULL; + struct clk_mux *mux = NULL; + bool clk_ro = false; + + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + goto fail; + + mux_hw = &mux->hw; + mux->reg = reg; + mux->shift = CCM_MUX_SHIFT; + mux->mask = CCM_MUX_MASK; + mux->lock = &imx_ccm_lock; + + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) + goto fail; + + div_hw = &div->hw; + div->reg = reg; + div->shift = CCM_DIV_SHIFT; + div->width = CCM_DIV_WIDTH; + div->lock = &imx_ccm_lock; + div->flags = CLK_DIVIDER_ROUND_CLOSEST; + + if (!(readl(reg + AUTHEN_OFFSET) & TZ_NS_MASK)) + clk_ro = true; + + if (clk_ro) { + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + mux_hw, &clk_mux_ro_ops, div_hw, + &clk_divider_ro_ops, NULL, NULL, flags); + } else { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) + goto fail; + + gate_hw = &gate->hw; + gate->reg = reg; + gate->bit_idx = CCM_OFF_SHIFT; + gate->lock = &imx_ccm_lock; + gate->flags = CLK_GATE_SET_TO_DISABLE; + + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + mux_hw, &clk_mux_ops, div_hw, + &clk_divider_ops, gate_hw, + &clk_gate_ops, flags | CLK_SET_RATE_NO_REPARENT); + } + + if (IS_ERR(hw)) + goto fail; + + return hw; + +fail: + kfree(gate); + kfree(div); + kfree(mux); + return ERR_CAST(hw); +} +EXPORT_SYMBOL_GPL(imx93_clk_composite_flags); diff --git a/drivers/clk/imx/clk-fracn-gppll.c b/drivers/clk/imx/clk-fracn-gppll.c new file mode 100644 index 000000000000..71c102d950ab --- /dev/null +++ b/drivers/clk/imx/clk-fracn-gppll.c @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 NXP + */ + +#include <linux/bitfield.h> +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/export.h> +#include <linux/io.h> +#include <linux/iopoll.h> +#include <linux/slab.h> +#include <asm/div64.h> + +#include "clk.h" + +#define PLL_CTRL 0x0 +#define CLKMUX_BYPASS BIT(2) +#define CLKMUX_EN BIT(1) +#define POWERUP_MASK BIT(0) + +#define PLL_ANA_PRG 0x10 +#define PLL_SPREAD_SPECTRUM 0x30 + +#define PLL_NUMERATOR 0x40 +#define PLL_MFN_MASK GENMASK(31, 2) + +#define PLL_DENOMINATOR 0x50 +#define PLL_MFD_MASK GENMASK(29, 0) + +#define PLL_DIV 0x60 +#define PLL_MFI_MASK GENMASK(24, 16) +#define PLL_RDIV_MASK GENMASK(15, 13) +#define PLL_ODIV_MASK GENMASK(7, 0) + +#define PLL_DFS_CTRL(x) (0x70 + (x) * 0x10) + +#define PLL_STATUS 0xF0 +#define LOCK_STATUS BIT(0) + +#define DFS_STATUS 0xF4 + +#define LOCK_TIMEOUT_US 200 + +#define PLL_FRACN_GP(_rate, _mfi, _mfn, _mfd, _rdiv, _odiv) \ + { \ + .rate = (_rate), \ + .mfi = (_mfi), \ + .mfn = (_mfn), \ + .mfd = (_mfd), \ + .rdiv = (_rdiv), \ + .odiv = (_odiv), \ + } + +struct clk_fracn_gppll { + struct clk_hw hw; + void __iomem *base; + const struct imx_fracn_gppll_rate_table *rate_table; + int rate_count; +}; + +/* + * Fvco = Fref * (MFI + MFN / MFD) + * Fout = Fvco / (rdiv * odiv) + */ +static const struct imx_fracn_gppll_rate_table fracn_tbl[] = { + PLL_FRACN_GP(650000000U, 81, 0, 0, 0, 3), + PLL_FRACN_GP(594000000U, 198, 0, 0, 0, 8), + PLL_FRACN_GP(560000000U, 70, 0, 0, 0, 3), + PLL_FRACN_GP(400000000U, 50, 0, 0, 0, 3), + PLL_FRACN_GP(393216000U, 81, 92, 100, 0, 5) +}; + +struct imx_fracn_gppll_clk imx_fracn_gppll = { + .rate_table = fracn_tbl, + .rate_count = ARRAY_SIZE(fracn_tbl), +}; +EXPORT_SYMBOL_GPL(imx_fracn_gppll); + +static inline struct clk_fracn_gppll *to_clk_fracn_gppll(struct clk_hw *hw) +{ + return container_of(hw, struct clk_fracn_gppll, hw); +} + +static const struct imx_fracn_gppll_rate_table * +imx_get_pll_settings(struct clk_fracn_gppll *pll, unsigned long rate) +{ + const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; + int i; + + for (i = 0; i < pll->rate_count; i++) + if (rate == rate_table[i].rate) + return &rate_table[i]; + + return NULL; +} + +static long clk_fracn_gppll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); + const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; + int i; + + /* Assuming rate_table is in descending order */ + for (i = 0; i < pll->rate_count; i++) + if (rate >= rate_table[i].rate) + return rate_table[i].rate; + + /* return minimum supported value */ + return rate_table[pll->rate_count - 1].rate; +} + +static unsigned long clk_fracn_gppll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); + const struct imx_fracn_gppll_rate_table *rate_table = pll->rate_table; + u32 pll_numerator, pll_denominator, pll_div; + u32 mfi, mfn, mfd, rdiv, odiv; + u64 fvco = parent_rate; + long rate = 0; + int i; + + pll_numerator = readl_relaxed(pll->base + PLL_NUMERATOR); + mfn = FIELD_GET(PLL_MFN_MASK, pll_numerator); + + pll_denominator = readl_relaxed(pll->base + PLL_DENOMINATOR); + mfd = FIELD_GET(PLL_MFD_MASK, pll_denominator); + + pll_div = readl_relaxed(pll->base + PLL_DIV); + mfi = FIELD_GET(PLL_MFI_MASK, pll_div); + + rdiv = FIELD_GET(PLL_RDIV_MASK, pll_div); + rdiv = rdiv + 1; + odiv = FIELD_GET(PLL_ODIV_MASK, pll_div); + switch (odiv) { + case 0: + odiv = 2; + break; + case 1: + odiv = 3; + break; + default: + break; + } + + /* + * Sometimes, the recalculated rate has deviation due to + * the frac part. So find the accurate pll rate from the table + * first, if no match rate in the table, use the rate calculated + * from the equation below. + */ + for (i = 0; i < pll->rate_count; i++) { + if (rate_table[i].mfn == mfn && rate_table[i].mfi == mfi && + rate_table[i].mfd == mfd && rate_table[i].rdiv == rdiv && + rate_table[i].odiv == odiv) + rate = rate_table[i].rate; + } + + if (rate) + return (unsigned long)rate; + + /* Fvco = Fref * (MFI + MFN / MFD) */ + fvco = fvco * mfi * mfd + fvco * mfn; + do_div(fvco, mfd * rdiv * odiv); + + return (unsigned long)fvco; +} + +static int clk_fracn_gppll_wait_lock(struct clk_fracn_gppll *pll) +{ + u32 val; + + return readl_poll_timeout(pll->base + PLL_STATUS, val, + val & LOCK_STATUS, 0, LOCK_TIMEOUT_US); +} + +static int clk_fracn_gppll_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); + const struct imx_fracn_gppll_rate_table *rate; + u32 tmp, pll_div, ana_mfn; + int ret; + + rate = imx_get_pll_settings(pll, drate); + + /* Disable output */ + tmp = readl_relaxed(pll->base + PLL_CTRL); + tmp &= ~CLKMUX_EN; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + /* Power Down */ + tmp &= ~POWERUP_MASK; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + /* Disable BYPASS */ + tmp &= ~CLKMUX_BYPASS; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + pll_div = FIELD_PREP(PLL_RDIV_MASK, rate->rdiv) | rate->odiv | + FIELD_PREP(PLL_MFI_MASK, rate->mfi); + writel_relaxed(pll_div, pll->base + PLL_DIV); + writel_relaxed(rate->mfd, pll->base + PLL_DENOMINATOR); + writel_relaxed(FIELD_PREP(PLL_MFN_MASK, rate->mfn), pll->base + PLL_NUMERATOR); + + /* Wait for 5us according to fracn mode pll doc */ + udelay(5); + + /* Enable Powerup */ + tmp |= POWERUP_MASK; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + /* Wait Lock */ + ret = clk_fracn_gppll_wait_lock(pll); + if (ret) + return ret; + + /* Enable output */ + tmp |= CLKMUX_EN; + writel_relaxed(tmp, pll->base + PLL_CTRL); + + ana_mfn = readl_relaxed(pll->base + PLL_STATUS); + ana_mfn = FIELD_GET(PLL_MFN_MASK, ana_mfn); + + WARN(ana_mfn != rate->mfn, "ana_mfn != rate->mfn\n"); + + return 0; +} + +static int clk_fracn_gppll_prepare(struct clk_hw *hw) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); + u32 val; + int ret; + + val = readl_relaxed(pll->base + PLL_CTRL); + if (val & POWERUP_MASK) + return 0; + + val |= CLKMUX_BYPASS; + writel_relaxed(val, pll->base + PLL_CTRL); + + val |= POWERUP_MASK; + writel_relaxed(val, pll->base + PLL_CTRL); + + val |= CLKMUX_EN; + writel_relaxed(val, pll->base + PLL_CTRL); + + ret = clk_fracn_gppll_wait_lock(pll); + if (ret) + return ret; + + val &= ~CLKMUX_BYPASS; + writel_relaxed(val, pll->base + PLL_CTRL); + + return 0; +} + +static int clk_fracn_gppll_is_prepared(struct clk_hw *hw) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); + u32 val; + + val = readl_relaxed(pll->base + PLL_CTRL); + + return (val & POWERUP_MASK) ? 1 : 0; +} + +static void clk_fracn_gppll_unprepare(struct clk_hw *hw) +{ + struct clk_fracn_gppll *pll = to_clk_fracn_gppll(hw); + u32 val; + + val = readl_relaxed(pll->base + PLL_CTRL); + val &= ~POWERUP_MASK; + writel_relaxed(val, pll->base + PLL_CTRL); +} + +static const struct clk_ops clk_fracn_gppll_ops = { + .prepare = clk_fracn_gppll_prepare, + .unprepare = clk_fracn_gppll_unprepare, + .is_prepared = clk_fracn_gppll_is_prepared, + .recalc_rate = clk_fracn_gppll_recalc_rate, + .round_rate = clk_fracn_gppll_round_rate, + .set_rate = clk_fracn_gppll_set_rate, +}; + +struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base, + const struct imx_fracn_gppll_clk *pll_clk) +{ + struct clk_fracn_gppll *pll; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = pll_clk->flags; + init.parent_names = &parent_name; + init.num_parents = 1; + init.ops = &clk_fracn_gppll_ops; + + pll->base = base; + pll->hw.init = &init; + pll->rate_table = pll_clk->rate_table; + pll->rate_count = pll_clk->rate_count; + + hw = &pll->hw; + + ret = clk_hw_register(NULL, hw); + if (ret) { + pr_err("%s: failed to register pll %s %d\n", __func__, name, ret); + kfree(pll); + return ERR_PTR(ret); + } + + return hw; +} +EXPORT_SYMBOL_GPL(imx_clk_fracn_gppll); diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c index c4e0f1c07192..3f6fd7ef2a68 100644 --- a/drivers/clk/imx/clk-imx7d.c +++ b/drivers/clk/imx/clk-imx7d.c @@ -849,7 +849,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node) hws[IMX7D_WDOG4_ROOT_CLK] = imx_clk_hw_gate4("wdog4_root_clk", "wdog_post_div", base + 0x49f0, 0); hws[IMX7D_KPP_ROOT_CLK] = imx_clk_hw_gate4("kpp_root_clk", "ipg_root_clk", base + 0x4aa0, 0); hws[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_hw_gate4("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0); - hws[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_hw_gate4("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0); hws[IMX7D_WRCLK_ROOT_CLK] = imx_clk_hw_gate4("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0); hws[IMX7D_USB_CTRL_CLK] = imx_clk_hw_gate4("usb_ctrl_clk", "ahb_root_clk", base + 0x4680, 0); hws[IMX7D_USB_PHY1_CLK] = imx_clk_hw_gate4("usb_phy1_clk", "pll_usb1_main_clk", base + 0x46a0, 0); diff --git a/drivers/clk/imx/clk-imx8dxl-rsrc.c b/drivers/clk/imx/clk-imx8dxl-rsrc.c new file mode 100644 index 000000000000..69b7aa34fff5 --- /dev/null +++ b/drivers/clk/imx/clk-imx8dxl-rsrc.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019~2020 NXP + */ + +#include <dt-bindings/firmware/imx/rsrc.h> + +#include "clk-scu.h" + +/* Keep sorted in the ascending order */ +static u32 imx8dxl_clk_scu_rsrc_table[] = { + IMX_SC_R_SPI_0, + IMX_SC_R_SPI_1, + IMX_SC_R_SPI_2, + IMX_SC_R_SPI_3, + IMX_SC_R_UART_0, + IMX_SC_R_UART_1, + IMX_SC_R_UART_2, + IMX_SC_R_UART_3, + IMX_SC_R_I2C_0, + IMX_SC_R_I2C_1, + IMX_SC_R_I2C_2, + IMX_SC_R_I2C_3, + IMX_SC_R_ADC_0, + IMX_SC_R_FTM_0, + IMX_SC_R_FTM_1, + IMX_SC_R_CAN_0, + IMX_SC_R_LCD_0, + IMX_SC_R_LCD_0_PWM_0, + IMX_SC_R_PWM_0, + IMX_SC_R_PWM_1, + IMX_SC_R_PWM_2, + IMX_SC_R_PWM_3, + IMX_SC_R_PWM_4, + IMX_SC_R_PWM_5, + IMX_SC_R_PWM_6, + IMX_SC_R_PWM_7, + IMX_SC_R_GPT_0, + IMX_SC_R_GPT_1, + IMX_SC_R_GPT_2, + IMX_SC_R_GPT_3, + IMX_SC_R_GPT_4, + IMX_SC_R_FSPI_0, + IMX_SC_R_FSPI_1, + IMX_SC_R_SDHC_0, + IMX_SC_R_SDHC_1, + IMX_SC_R_SDHC_2, + IMX_SC_R_ENET_0, + IMX_SC_R_ENET_1, + IMX_SC_R_MLB_0, + IMX_SC_R_USB_1, + IMX_SC_R_NAND, + IMX_SC_R_M4_0_I2C, + IMX_SC_R_M4_0_UART, + IMX_SC_R_ELCDIF_PLL, + IMX_SC_R_AUDIO_PLL_0, + IMX_SC_R_AUDIO_PLL_1, + IMX_SC_R_AUDIO_CLK_0, + IMX_SC_R_AUDIO_CLK_1, + IMX_SC_R_A35 +}; + +const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl = { + .rsrc = imx8dxl_clk_scu_rsrc_table, + .num = ARRAY_SIZE(imx8dxl_clk_scu_rsrc_table), +}; diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index e92621fa8b9c..e8cbe181ec06 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -366,45 +366,28 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11); /* SYS PLL1 fixed output */ - hws[IMX8MM_SYS_PLL1_40M_CG] = imx_clk_hw_gate("sys_pll1_40m_cg", "sys_pll1", base + 0x94, 27); - hws[IMX8MM_SYS_PLL1_80M_CG] = imx_clk_hw_gate("sys_pll1_80m_cg", "sys_pll1", base + 0x94, 25); - hws[IMX8MM_SYS_PLL1_100M_CG] = imx_clk_hw_gate("sys_pll1_100m_cg", "sys_pll1", base + 0x94, 23); - hws[IMX8MM_SYS_PLL1_133M_CG] = imx_clk_hw_gate("sys_pll1_133m_cg", "sys_pll1", base + 0x94, 21); - hws[IMX8MM_SYS_PLL1_160M_CG] = imx_clk_hw_gate("sys_pll1_160m_cg", "sys_pll1", base + 0x94, 19); - hws[IMX8MM_SYS_PLL1_200M_CG] = imx_clk_hw_gate("sys_pll1_200m_cg", "sys_pll1", base + 0x94, 17); - hws[IMX8MM_SYS_PLL1_266M_CG] = imx_clk_hw_gate("sys_pll1_266m_cg", "sys_pll1", base + 0x94, 15); - hws[IMX8MM_SYS_PLL1_400M_CG] = imx_clk_hw_gate("sys_pll1_400m_cg", "sys_pll1", base + 0x94, 13); hws[IMX8MM_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1", base + 0x94, 11); - hws[IMX8MM_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_40m_cg", 1, 20); - hws[IMX8MM_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_80m_cg", 1, 10); - hws[IMX8MM_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_100m_cg", 1, 8); - hws[IMX8MM_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_133m_cg", 1, 6); - hws[IMX8MM_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_160m_cg", 1, 5); - hws[IMX8MM_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_200m_cg", 1, 4); - hws[IMX8MM_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_266m_cg", 1, 3); - hws[IMX8MM_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_400m_cg", 1, 2); + hws[IMX8MM_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20); + hws[IMX8MM_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10); + hws[IMX8MM_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8); + hws[IMX8MM_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6); + hws[IMX8MM_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5); + hws[IMX8MM_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4); + hws[IMX8MM_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3); + hws[IMX8MM_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2); hws[IMX8MM_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1); /* SYS PLL2 fixed output */ - hws[IMX8MM_SYS_PLL2_50M_CG] = imx_clk_hw_gate("sys_pll2_50m_cg", "sys_pll2", base + 0x104, 27); - hws[IMX8MM_SYS_PLL2_100M_CG] = imx_clk_hw_gate("sys_pll2_100m_cg", "sys_pll2", base + 0x104, 25); - hws[IMX8MM_SYS_PLL2_125M_CG] = imx_clk_hw_gate("sys_pll2_125m_cg", "sys_pll2", base + 0x104, 23); - hws[IMX8MM_SYS_PLL2_166M_CG] = imx_clk_hw_gate("sys_pll2_166m_cg", "sys_pll2", base + 0x104, 21); - hws[IMX8MM_SYS_PLL2_200M_CG] = imx_clk_hw_gate("sys_pll2_200m_cg", "sys_pll2", base + 0x104, 19); - hws[IMX8MM_SYS_PLL2_250M_CG] = imx_clk_hw_gate("sys_pll2_250m_cg", "sys_pll2", base + 0x104, 17); - hws[IMX8MM_SYS_PLL2_333M_CG] = imx_clk_hw_gate("sys_pll2_333m_cg", "sys_pll2", base + 0x104, 15); - hws[IMX8MM_SYS_PLL2_500M_CG] = imx_clk_hw_gate("sys_pll2_500m_cg", "sys_pll2", base + 0x104, 13); hws[IMX8MM_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2", base + 0x104, 11); - - hws[IMX8MM_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_50m_cg", 1, 20); - hws[IMX8MM_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_100m_cg", 1, 10); - hws[IMX8MM_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_125m_cg", 1, 8); - hws[IMX8MM_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_166m_cg", 1, 6); - hws[IMX8MM_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_200m_cg", 1, 5); - hws[IMX8MM_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_250m_cg", 1, 4); - hws[IMX8MM_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_333m_cg", 1, 3); - hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2); + hws[IMX8MM_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20); + hws[IMX8MM_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10); + hws[IMX8MM_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8); + hws[IMX8MM_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6); + hws[IMX8MM_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5); + hws[IMX8MM_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4); + hws[IMX8MM_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3); + hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2); hws[IMX8MM_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); hws[IMX8MM_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels)); diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 021355a24708..92fcbab4f5be 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -364,45 +364,27 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11); /* SYS PLL1 fixed output */ - hws[IMX8MN_SYS_PLL1_40M_CG] = imx_clk_hw_gate("sys_pll1_40m_cg", "sys_pll1", base + 0x94, 27); - hws[IMX8MN_SYS_PLL1_80M_CG] = imx_clk_hw_gate("sys_pll1_80m_cg", "sys_pll1", base + 0x94, 25); - hws[IMX8MN_SYS_PLL1_100M_CG] = imx_clk_hw_gate("sys_pll1_100m_cg", "sys_pll1", base + 0x94, 23); - hws[IMX8MN_SYS_PLL1_133M_CG] = imx_clk_hw_gate("sys_pll1_133m_cg", "sys_pll1", base + 0x94, 21); - hws[IMX8MN_SYS_PLL1_160M_CG] = imx_clk_hw_gate("sys_pll1_160m_cg", "sys_pll1", base + 0x94, 19); - hws[IMX8MN_SYS_PLL1_200M_CG] = imx_clk_hw_gate("sys_pll1_200m_cg", "sys_pll1", base + 0x94, 17); - hws[IMX8MN_SYS_PLL1_266M_CG] = imx_clk_hw_gate("sys_pll1_266m_cg", "sys_pll1", base + 0x94, 15); - hws[IMX8MN_SYS_PLL1_400M_CG] = imx_clk_hw_gate("sys_pll1_400m_cg", "sys_pll1", base + 0x94, 13); hws[IMX8MN_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1", base + 0x94, 11); - - hws[IMX8MN_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_40m_cg", 1, 20); - hws[IMX8MN_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_80m_cg", 1, 10); - hws[IMX8MN_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_100m_cg", 1, 8); - hws[IMX8MN_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_133m_cg", 1, 6); - hws[IMX8MN_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_160m_cg", 1, 5); - hws[IMX8MN_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_200m_cg", 1, 4); - hws[IMX8MN_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_266m_cg", 1, 3); - hws[IMX8MN_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_400m_cg", 1, 2); + hws[IMX8MN_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20); + hws[IMX8MN_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10); + hws[IMX8MN_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8); + hws[IMX8MN_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6); + hws[IMX8MN_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5); + hws[IMX8MN_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4); + hws[IMX8MN_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3); + hws[IMX8MN_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2); hws[IMX8MN_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1); /* SYS PLL2 fixed output */ - hws[IMX8MN_SYS_PLL2_50M_CG] = imx_clk_hw_gate("sys_pll2_50m_cg", "sys_pll2", base + 0x104, 27); - hws[IMX8MN_SYS_PLL2_100M_CG] = imx_clk_hw_gate("sys_pll2_100m_cg", "sys_pll2", base + 0x104, 25); - hws[IMX8MN_SYS_PLL2_125M_CG] = imx_clk_hw_gate("sys_pll2_125m_cg", "sys_pll2", base + 0x104, 23); - hws[IMX8MN_SYS_PLL2_166M_CG] = imx_clk_hw_gate("sys_pll2_166m_cg", "sys_pll2", base + 0x104, 21); - hws[IMX8MN_SYS_PLL2_200M_CG] = imx_clk_hw_gate("sys_pll2_200m_cg", "sys_pll2", base + 0x104, 19); - hws[IMX8MN_SYS_PLL2_250M_CG] = imx_clk_hw_gate("sys_pll2_250m_cg", "sys_pll2", base + 0x104, 17); - hws[IMX8MN_SYS_PLL2_333M_CG] = imx_clk_hw_gate("sys_pll2_333m_cg", "sys_pll2", base + 0x104, 15); - hws[IMX8MN_SYS_PLL2_500M_CG] = imx_clk_hw_gate("sys_pll2_500m_cg", "sys_pll2", base + 0x104, 13); hws[IMX8MN_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2", base + 0x104, 11); - - hws[IMX8MN_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_50m_cg", 1, 20); - hws[IMX8MN_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_100m_cg", 1, 10); - hws[IMX8MN_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_125m_cg", 1, 8); - hws[IMX8MN_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_166m_cg", 1, 6); - hws[IMX8MN_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_200m_cg", 1, 5); - hws[IMX8MN_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_250m_cg", 1, 4); - hws[IMX8MN_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_333m_cg", 1, 3); - hws[IMX8MN_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2); + hws[IMX8MN_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20); + hws[IMX8MN_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10); + hws[IMX8MN_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8); + hws[IMX8MN_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6); + hws[IMX8MN_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5); + hws[IMX8MN_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4); + hws[IMX8MN_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3); + hws[IMX8MN_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2); hws[IMX8MN_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); hws[IMX8MN_CLK_CLKOUT1_SEL] = imx_clk_hw_mux2("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels)); diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c index c990ad37882b..18f5b7c3ca9d 100644 --- a/drivers/clk/imx/clk-imx8mp.c +++ b/drivers/clk/imx/clk-imx8mp.c @@ -480,44 +480,28 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", anatop_base + 0x84, 11); hws[IMX8MP_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", anatop_base + 0x114, 11); - hws[IMX8MP_SYS_PLL1_40M_CG] = imx_clk_hw_gate("sys_pll1_40m_cg", "sys_pll1_bypass", anatop_base + 0x94, 27); - hws[IMX8MP_SYS_PLL1_80M_CG] = imx_clk_hw_gate("sys_pll1_80m_cg", "sys_pll1_bypass", anatop_base + 0x94, 25); - hws[IMX8MP_SYS_PLL1_100M_CG] = imx_clk_hw_gate("sys_pll1_100m_cg", "sys_pll1_bypass", anatop_base + 0x94, 23); - hws[IMX8MP_SYS_PLL1_133M_CG] = imx_clk_hw_gate("sys_pll1_133m_cg", "sys_pll1_bypass", anatop_base + 0x94, 21); - hws[IMX8MP_SYS_PLL1_160M_CG] = imx_clk_hw_gate("sys_pll1_160m_cg", "sys_pll1_bypass", anatop_base + 0x94, 19); - hws[IMX8MP_SYS_PLL1_200M_CG] = imx_clk_hw_gate("sys_pll1_200m_cg", "sys_pll1_bypass", anatop_base + 0x94, 17); - hws[IMX8MP_SYS_PLL1_266M_CG] = imx_clk_hw_gate("sys_pll1_266m_cg", "sys_pll1_bypass", anatop_base + 0x94, 15); - hws[IMX8MP_SYS_PLL1_400M_CG] = imx_clk_hw_gate("sys_pll1_400m_cg", "sys_pll1_bypass", anatop_base + 0x94, 13); hws[IMX8MP_SYS_PLL1_OUT] = imx_clk_hw_gate("sys_pll1_out", "sys_pll1_bypass", anatop_base + 0x94, 11); - hws[IMX8MP_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_40m_cg", 1, 20); - hws[IMX8MP_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_80m_cg", 1, 10); - hws[IMX8MP_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_100m_cg", 1, 8); - hws[IMX8MP_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_133m_cg", 1, 6); - hws[IMX8MP_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_160m_cg", 1, 5); - hws[IMX8MP_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_200m_cg", 1, 4); - hws[IMX8MP_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_266m_cg", 1, 3); - hws[IMX8MP_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_400m_cg", 1, 2); + hws[IMX8MP_SYS_PLL1_40M] = imx_clk_hw_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20); + hws[IMX8MP_SYS_PLL1_80M] = imx_clk_hw_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10); + hws[IMX8MP_SYS_PLL1_100M] = imx_clk_hw_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8); + hws[IMX8MP_SYS_PLL1_133M] = imx_clk_hw_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6); + hws[IMX8MP_SYS_PLL1_160M] = imx_clk_hw_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5); + hws[IMX8MP_SYS_PLL1_200M] = imx_clk_hw_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4); + hws[IMX8MP_SYS_PLL1_266M] = imx_clk_hw_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3); + hws[IMX8MP_SYS_PLL1_400M] = imx_clk_hw_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2); hws[IMX8MP_SYS_PLL1_800M] = imx_clk_hw_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1); - hws[IMX8MP_SYS_PLL2_50M_CG] = imx_clk_hw_gate("sys_pll2_50m_cg", "sys_pll2_bypass", anatop_base + 0x104, 27); - hws[IMX8MP_SYS_PLL2_100M_CG] = imx_clk_hw_gate("sys_pll2_100m_cg", "sys_pll2_bypass", anatop_base + 0x104, 25); - hws[IMX8MP_SYS_PLL2_125M_CG] = imx_clk_hw_gate("sys_pll2_125m_cg", "sys_pll2_bypass", anatop_base + 0x104, 23); - hws[IMX8MP_SYS_PLL2_166M_CG] = imx_clk_hw_gate("sys_pll2_166m_cg", "sys_pll2_bypass", anatop_base + 0x104, 21); - hws[IMX8MP_SYS_PLL2_200M_CG] = imx_clk_hw_gate("sys_pll2_200m_cg", "sys_pll2_bypass", anatop_base + 0x104, 19); - hws[IMX8MP_SYS_PLL2_250M_CG] = imx_clk_hw_gate("sys_pll2_250m_cg", "sys_pll2_bypass", anatop_base + 0x104, 17); - hws[IMX8MP_SYS_PLL2_333M_CG] = imx_clk_hw_gate("sys_pll2_333m_cg", "sys_pll2_bypass", anatop_base + 0x104, 15); - hws[IMX8MP_SYS_PLL2_500M_CG] = imx_clk_hw_gate("sys_pll2_500m_cg", "sys_pll2_bypass", anatop_base + 0x104, 13); hws[IMX8MP_SYS_PLL2_OUT] = imx_clk_hw_gate("sys_pll2_out", "sys_pll2_bypass", anatop_base + 0x104, 11); - hws[IMX8MP_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_50m_cg", 1, 20); - hws[IMX8MP_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_100m_cg", 1, 10); - hws[IMX8MP_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_125m_cg", 1, 8); - hws[IMX8MP_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_166m_cg", 1, 6); - hws[IMX8MP_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_200m_cg", 1, 5); - hws[IMX8MP_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_250m_cg", 1, 4); - hws[IMX8MP_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_333m_cg", 1, 3); - hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2); + hws[IMX8MP_SYS_PLL2_50M] = imx_clk_hw_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20); + hws[IMX8MP_SYS_PLL2_100M] = imx_clk_hw_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10); + hws[IMX8MP_SYS_PLL2_125M] = imx_clk_hw_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8); + hws[IMX8MP_SYS_PLL2_166M] = imx_clk_hw_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6); + hws[IMX8MP_SYS_PLL2_200M] = imx_clk_hw_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5); + hws[IMX8MP_SYS_PLL2_250M] = imx_clk_hw_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4); + hws[IMX8MP_SYS_PLL2_333M] = imx_clk_hw_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3); + hws[IMX8MP_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2); hws[IMX8MP_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); hws[IMX8MP_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mp_a53_sels, ccm_base + 0x8000); @@ -694,6 +678,7 @@ static int imx8mp_clocks_probe(struct platform_device *pdev) hws[IMX8MP_CLK_MEDIA_CAM2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_cam2_pix_root_clk", "media_cam2_pix", ccm_base + 0x45d0, 0, &share_count_media); hws[IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp1_pix_root_clk", "media_disp1_pix", ccm_base + 0x45d0, 0, &share_count_media); hws[IMX8MP_CLK_MEDIA_DISP2_PIX_ROOT] = imx_clk_hw_gate2_shared2("media_disp2_pix_root_clk", "media_disp2_pix", ccm_base + 0x45d0, 0, &share_count_media); + hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF_ROOT] = imx_clk_hw_gate2_shared2("media_mipi_phy1_ref_root", "media_mipi_phy1_ref", ccm_base + 0x45d0, 0, &share_count_media); hws[IMX8MP_CLK_MEDIA_ISP_ROOT] = imx_clk_hw_gate2_shared2("media_isp_root_clk", "media_isp", ccm_base + 0x45d0, 0, &share_count_media); hws[IMX8MP_CLK_USDHC3_ROOT] = imx_clk_hw_gate4("usdhc3_root_clk", "usdhc3", ccm_base + 0x45e0, 0); diff --git a/drivers/clk/imx/clk-imx8qxp-lpcg.c b/drivers/clk/imx/clk-imx8qxp-lpcg.c index b23758083ce5..5e31a6a24b3a 100644 --- a/drivers/clk/imx/clk-imx8qxp-lpcg.c +++ b/drivers/clk/imx/clk-imx8qxp-lpcg.c @@ -248,7 +248,7 @@ static int imx_lpcg_parse_clks_from_dt(struct platform_device *pdev, for (i = 0; i < count; i++) { idx = bit_offset[i] / 4; - if (idx > IMX_LPCG_MAX_CLKS) { + if (idx >= IMX_LPCG_MAX_CLKS) { dev_warn(&pdev->dev, "invalid bit offset of clock %d\n", i); ret = -EINVAL; diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 40a2efb1329b..546a3703bfeb 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -295,6 +295,7 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) static const struct of_device_id imx8qxp_match[] = { { .compatible = "fsl,scu-clk", }, + { .compatible = "fsl,imx8dxl-clk", &imx_clk_scu_rsrc_imx8dxl, }, { .compatible = "fsl,imx8qxp-clk", &imx_clk_scu_rsrc_imx8qxp, }, { .compatible = "fsl,imx8qm-clk", &imx_clk_scu_rsrc_imx8qm, }, { /* sentinel */ } diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c new file mode 100644 index 000000000000..edcc87661d1f --- /dev/null +++ b/drivers/clk/imx/clk-imx93.c @@ -0,0 +1,341 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 NXP. + */ + +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <dt-bindings/clock/imx93-clock.h> + +#include "clk.h" + +enum clk_sel { + LOW_SPEED_IO_SEL, + NON_IO_SEL, + FAST_SEL, + AUDIO_SEL, + VIDEO_SEL, + TPM_SEL, + CKO1_SEL, + CKO2_SEL, + MISC_SEL, + MAX_SEL +}; + +static const char *parent_names[MAX_SEL][4] = { + {"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "video_pll"}, + {"osc_24m", "sys_pll_pfd0_div2", "sys_pll_pfd1_div2", "sys_pll_pfd2_div2"}, + {"osc_24m", "sys_pll_pfd0", "sys_pll_pfd1", "sys_pll_pfd2"}, + {"osc_24m", "audio_pll", "video_pll", "clk_ext1"}, + {"osc_24m", "audio_pll", "video_pll", "sys_pll_pfd0"}, + {"osc_24m", "sys_pll_pfd0", "audio_pll", "clk_ext1"}, + {"osc_24m", "sys_pll_pfd0", "sys_pll_pfd1", "audio_pll"}, + {"osc_24m", "sys_pll_pfd0", "sys_pll_pfd1", "video_pll"}, + {"osc_24m", "audio_pll", "video_pll", "sys_pll_pfd2"}, +}; + +static const struct imx93_clk_root { + u32 clk; + char *name; + u32 off; + enum clk_sel sel; + unsigned long flags; +} root_array[] = { + /* a55/m33/bus critical clk for system run */ + { IMX93_CLK_A55_PERIPH, "a55_periph_root", 0x0000, FAST_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_A55_MTR_BUS, "a55_mtr_bus_root", 0x0080, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_A55, "a55_root", 0x0100, FAST_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_M33, "m33_root", 0x0180, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_BUS_WAKEUP, "bus_wakeup_root", 0x0280, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_BUS_AON, "bus_aon_root", 0x0300, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_WAKEUP_AXI, "wakeup_axi_root", 0x0380, FAST_SEL, CLK_IS_CRITICAL }, + { IMX93_CLK_SWO_TRACE, "swo_trace_root", 0x0400, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_FLEXIO1, "flexio1_root", 0x0500, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_FLEXIO2, "flexio2_root", 0x0580, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPIT1, "lpit1_root", 0x0600, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPIT2, "lpit2_root", 0x0680, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPTMR1, "lptmr1_root", 0x0700, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPTMR2, "lptmr2_root", 0x0780, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_TPM1, "tpm1_root", 0x0800, TPM_SEL, }, + { IMX93_CLK_TPM2, "tpm2_root", 0x0880, TPM_SEL, }, + { IMX93_CLK_TPM3, "tpm3_root", 0x0900, TPM_SEL, }, + { IMX93_CLK_TPM4, "tpm4_root", 0x0980, TPM_SEL, }, + { IMX93_CLK_TPM5, "tpm5_root", 0x0a00, TPM_SEL, }, + { IMX93_CLK_TPM6, "tpm6_root", 0x0a80, TPM_SEL, }, + { IMX93_CLK_FLEXSPI1, "flexspi1_root", 0x0b00, FAST_SEL, }, + { IMX93_CLK_CAN1, "can1_root", 0x0b80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_CAN2, "can2_root", 0x0c00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART1, "lpuart1_root", 0x0c80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART2, "lpuart2_root", 0x0d00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART3, "lpuart3_root", 0x0d80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART4, "lpuart4_root", 0x0e00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART5, "lpuart5_root", 0x0e80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART6, "lpuart6_root", 0x0f00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART7, "lpuart7_root", 0x0f80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPUART8, "lpuart8_root", 0x1000, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C1, "lpi2c1_root", 0x1080, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C2, "lpi2c2_root", 0x1100, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C3, "lpi2c3_root", 0x1180, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C4, "lpi2c4_root", 0x1200, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C5, "lpi2c5_root", 0x1280, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C6, "lpi2c6_root", 0x1300, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C7, "lpi2c7_root", 0x1380, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPI2C8, "lpi2c8_root", 0x1400, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI1, "lpspi1_root", 0x1480, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI2, "lpspi2_root", 0x1500, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI3, "lpspi3_root", 0x1580, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI4, "lpspi4_root", 0x1600, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI5, "lpspi5_root", 0x1680, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI6, "lpspi6_root", 0x1700, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI7, "lpspi7_root", 0x1780, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_LPSPI8, "lpspi8_root", 0x1800, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C1, "i3c1_root", 0x1880, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C2, "i3c2_root", 0x1900, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_USDHC1, "usdhc1_root", 0x1980, FAST_SEL, }, + { IMX93_CLK_USDHC2, "usdhc2_root", 0x1a00, FAST_SEL, }, + { IMX93_CLK_USDHC3, "usdhc3_root", 0x1a80, FAST_SEL, }, + { IMX93_CLK_SAI1, "sai1_root", 0x1b00, AUDIO_SEL, }, + { IMX93_CLK_SAI2, "sai2_root", 0x1b80, AUDIO_SEL, }, + { IMX93_CLK_SAI3, "sai3_root", 0x1c00, AUDIO_SEL, }, + { IMX93_CLK_CCM_CKO1, "ccm_cko1_root", 0x1c80, CKO1_SEL, }, + { IMX93_CLK_CCM_CKO2, "ccm_cko2_root", 0x1d00, CKO2_SEL, }, + { IMX93_CLK_CCM_CKO3, "ccm_cko3_root", 0x1d80, CKO1_SEL, }, + { IMX93_CLK_CCM_CKO4, "ccm_cko4_root", 0x1e00, CKO2_SEL, }, + { IMX93_CLK_HSIO, "hsio_root", 0x1e80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_HSIO_USB_TEST_60M, "hsio_usb_test_60m_root", 0x1f00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_HSIO_ACSCAN_80M, "hsio_acscan_80m_root", 0x1f80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_HSIO_ACSCAN_480M, "hsio_acscan_480m_root", 0x2000, MISC_SEL, }, + { IMX93_CLK_ML_APB, "ml_apb_root", 0x2180, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_ML, "ml_root", 0x2200, FAST_SEL, }, + { IMX93_CLK_MEDIA_AXI, "media_axi_root", 0x2280, FAST_SEL, }, + { IMX93_CLK_MEDIA_APB, "media_apb_root", 0x2300, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_MEDIA_LDB, "media_ldb_root", 0x2380, VIDEO_SEL, }, + { IMX93_CLK_MEDIA_DISP_PIX, "media_disp_pix_root", 0x2400, VIDEO_SEL, }, + { IMX93_CLK_CAM_PIX, "cam_pix_root", 0x2480, VIDEO_SEL, }, + { IMX93_CLK_MIPI_TEST_BYTE, "mipi_test_byte_root", 0x2500, VIDEO_SEL, }, + { IMX93_CLK_MIPI_PHY_CFG, "mipi_phy_cfg_root", 0x2580, VIDEO_SEL, }, + { IMX93_CLK_ADC, "adc_root", 0x2700, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_PDM, "pdm_root", 0x2780, AUDIO_SEL, }, + { IMX93_CLK_TSTMR1, "tstmr1_root", 0x2800, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_TSTMR2, "tstmr2_root", 0x2880, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_MQS1, "mqs1_root", 0x2900, AUDIO_SEL, }, + { IMX93_CLK_MQS2, "mqs2_root", 0x2980, AUDIO_SEL, }, + { IMX93_CLK_AUDIO_XCVR, "audio_xcvr_root", 0x2a00, NON_IO_SEL, }, + { IMX93_CLK_SPDIF, "spdif_root", 0x2a80, AUDIO_SEL, }, + { IMX93_CLK_ENET, "enet_root", 0x2b00, NON_IO_SEL, }, + { IMX93_CLK_ENET_TIMER1, "enet_timer1_root", 0x2b80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_ENET_TIMER2, "enet_timer2_root", 0x2c00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_ENET_REF, "enet_ref_root", 0x2c80, NON_IO_SEL, }, + { IMX93_CLK_ENET_REF_PHY, "enet_ref_phy_root", 0x2d00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C1_SLOW, "i3c1_slow_root", 0x2d80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_I3C2_SLOW, "i3c2_slow_root", 0x2e00, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_USB_PHY_BURUNIN, "usb_phy_root", 0x2e80, LOW_SPEED_IO_SEL, }, + { IMX93_CLK_PAL_CAME_SCAN, "pal_came_scan_root", 0x2f00, MISC_SEL, } +}; + +static const struct imx93_clk_ccgr { + u32 clk; + char *name; + char *parent_name; + u32 off; + unsigned long flags; +} ccgr_array[] = { + { IMX93_CLK_A55_GATE, "a55", "a55_root", 0x8000, }, + /* M33 critical clk for system run */ + { IMX93_CLK_CM33_GATE, "cm33", "m33_root", 0x8040, CLK_IS_CRITICAL }, + { IMX93_CLK_ADC1_GATE, "adc1", "osc_24m", 0x82c0, }, + { IMX93_CLK_WDOG1_GATE, "wdog1", "osc_24m", 0x8300, }, + { IMX93_CLK_WDOG2_GATE, "wdog2", "osc_24m", 0x8340, }, + { IMX93_CLK_WDOG3_GATE, "wdog3", "osc_24m", 0x8380, }, + { IMX93_CLK_WDOG4_GATE, "wdog4", "osc_24m", 0x83c0, }, + { IMX93_CLK_WDOG5_GATE, "wdog5", "osc_24m", 0x8400, }, + { IMX93_CLK_SEMA1_GATE, "sema1", "bus_aon_root", 0x8440, }, + { IMX93_CLK_SEMA2_GATE, "sema2", "bus_wakeup_root", 0x8480, }, + { IMX93_CLK_MU_A_GATE, "mu_a", "bus_aon_root", 0x84c0, }, + { IMX93_CLK_MU_B_GATE, "mu_b", "bus_aon_root", 0x8500, }, + { IMX93_CLK_EDMA1_GATE, "edma1", "wakeup_axi_root", 0x8540, }, + { IMX93_CLK_EDMA2_GATE, "edma2", "wakeup_axi_root", 0x8580, }, + { IMX93_CLK_FLEXSPI1_GATE, "flexspi", "flexspi_root", 0x8640, }, + { IMX93_CLK_GPIO1_GATE, "gpio1", "m33_root", 0x8880, }, + { IMX93_CLK_GPIO2_GATE, "gpio2", "bus_wakeup_root", 0x88c0, }, + { IMX93_CLK_GPIO3_GATE, "gpio3", "bus_wakeup_root", 0x8900, }, + { IMX93_CLK_GPIO4_GATE, "gpio4", "bus_wakeup_root", 0x8940, }, + { IMX93_CLK_FLEXIO1_GATE, "flexio1", "flexio1_root", 0x8980, }, + { IMX93_CLK_FLEXIO2_GATE, "flexio2", "flexio2_root", 0x89c0, }, + { IMX93_CLK_LPIT1_GATE, "lpit1", "lpit1_root", 0x8a00, }, + { IMX93_CLK_LPIT2_GATE, "lpit2", "lpit2_root", 0x8a40, }, + { IMX93_CLK_LPTMR1_GATE, "lptmr1", "lptmr1_root", 0x8a80, }, + { IMX93_CLK_LPTMR2_GATE, "lptmr2", "lptmr2_root", 0x8ac0, }, + { IMX93_CLK_TPM1_GATE, "tpm1", "tpm1_root", 0x8b00, }, + { IMX93_CLK_TPM2_GATE, "tpm2", "tpm2_root", 0x8b40, }, + { IMX93_CLK_TPM3_GATE, "tpm3", "tpm3_root", 0x8b80, }, + { IMX93_CLK_TPM4_GATE, "tpm4", "tpm4_root", 0x8bc0, }, + { IMX93_CLK_TPM5_GATE, "tpm5", "tpm5_root", 0x8c00, }, + { IMX93_CLK_TPM6_GATE, "tpm6", "tpm6_root", 0x8c40, }, + { IMX93_CLK_CAN1_GATE, "can1", "can1_root", 0x8c80, }, + { IMX93_CLK_CAN2_GATE, "can2", "can2_root", 0x8cc0, }, + { IMX93_CLK_LPUART1_GATE, "lpuart1", "lpuart1_root", 0x8d00, }, + { IMX93_CLK_LPUART2_GATE, "lpuart2", "lpuart2_root", 0x8d40, }, + { IMX93_CLK_LPUART3_GATE, "lpuart3", "lpuart3_root", 0x8d80, }, + { IMX93_CLK_LPUART4_GATE, "lpuart4", "lpuart4_root", 0x8dc0, }, + { IMX93_CLK_LPUART5_GATE, "lpuart5", "lpuart5_root", 0x8e00, }, + { IMX93_CLK_LPUART6_GATE, "lpuart6", "lpuart6_root", 0x8e40, }, + { IMX93_CLK_LPUART7_GATE, "lpuart7", "lpuart7_root", 0x8e80, }, + { IMX93_CLK_LPUART8_GATE, "lpuart8", "lpuart8_root", 0x8ec0, }, + { IMX93_CLK_LPI2C1_GATE, "lpi2c1", "lpi2c1_root", 0x8f00, }, + { IMX93_CLK_LPI2C2_GATE, "lpi2c2", "lpi2c2_root", 0x8f40, }, + { IMX93_CLK_LPI2C3_GATE, "lpi2c3", "lpi2c3_root", 0x8f80, }, + { IMX93_CLK_LPI2C4_GATE, "lpi2c4", "lpi2c4_root", 0x8fc0, }, + { IMX93_CLK_LPI2C5_GATE, "lpi2c5", "lpi2c5_root", 0x9000, }, + { IMX93_CLK_LPI2C6_GATE, "lpi2c6", "lpi2c6_root", 0x9040, }, + { IMX93_CLK_LPI2C7_GATE, "lpi2c7", "lpi2c7_root", 0x9080, }, + { IMX93_CLK_LPI2C8_GATE, "lpi2c8", "lpi2c8_root", 0x90c0, }, + { IMX93_CLK_LPSPI1_GATE, "lpspi1", "lpspi1_root", 0x9100, }, + { IMX93_CLK_LPSPI2_GATE, "lpspi2", "lpspi2_root", 0x9140, }, + { IMX93_CLK_LPSPI3_GATE, "lpspi3", "lpspi3_root", 0x9180, }, + { IMX93_CLK_LPSPI4_GATE, "lpspi4", "lpspi4_root", 0x91c0, }, + { IMX93_CLK_LPSPI5_GATE, "lpspi5", "lpspi5_root", 0x9200, }, + { IMX93_CLK_LPSPI6_GATE, "lpspi6", "lpspi6_root", 0x9240, }, + { IMX93_CLK_LPSPI7_GATE, "lpspi7", "lpspi7_root", 0x9280, }, + { IMX93_CLK_LPSPI8_GATE, "lpspi8", "lpspi8_root", 0x92c0, }, + { IMX93_CLK_I3C1_GATE, "i3c1", "i3c1_root", 0x9300, }, + { IMX93_CLK_I3C2_GATE, "i3c2", "i3c2_root", 0x9340, }, + { IMX93_CLK_USDHC1_GATE, "usdhc1", "usdhc1_root", 0x9380, }, + { IMX93_CLK_USDHC2_GATE, "usdhc2", "usdhc2_root", 0x93c0, }, + { IMX93_CLK_USDHC3_GATE, "usdhc3", "usdhc3_root", 0x9400, }, + { IMX93_CLK_SAI1_GATE, "sai1", "sai1_root", 0x9440, }, + { IMX93_CLK_SAI2_GATE, "sai2", "sai2_root", 0x9480, }, + { IMX93_CLK_SAI3_GATE, "sai3", "sai3_root", 0x94c0, }, + { IMX93_CLK_MIPI_CSI_GATE, "mipi_csi", "media_apb_root", 0x9580, }, + { IMX93_CLK_MIPI_DSI_GATE, "mipi_dsi", "media_apb_root", 0x95c0, }, + { IMX93_CLK_LVDS_GATE, "lvds", "media_ldb_root", 0x9600, }, + { IMX93_CLK_LCDIF_GATE, "lcdif", "media_apb_root", 0x9640, }, + { IMX93_CLK_PXP_GATE, "pxp", "media_apb_root", 0x9680, }, + { IMX93_CLK_ISI_GATE, "isi", "media_apb_root", 0x96c0, }, + { IMX93_CLK_NIC_MEDIA_GATE, "nic_media", "media_apb_root", 0x9700, }, + { IMX93_CLK_USB_CONTROLLER_GATE, "usb_controller", "hsio_root", 0x9a00, }, + { IMX93_CLK_USB_TEST_60M_GATE, "usb_test_60m", "hsio_usb_test_60m_root", 0x9a40, }, + { IMX93_CLK_HSIO_TROUT_24M_GATE, "hsio_trout_24m", "osc_24m", 0x9a80, }, + { IMX93_CLK_PDM_GATE, "pdm", "pdm_root", 0x9ac0, }, + { IMX93_CLK_MQS1_GATE, "mqs1", "sai1_root", 0x9b00, }, + { IMX93_CLK_MQS2_GATE, "mqs2", "sai3_root", 0x9b40, }, + { IMX93_CLK_AUD_XCVR_GATE, "aud_xcvr", "audio_xcvr_root", 0x9b80, }, + { IMX93_CLK_SPDIF_GATE, "spdif", "spdif_root", 0x9c00, }, + { IMX93_CLK_HSIO_32K_GATE, "hsio_32k", "osc_32k", 0x9dc0, }, + { IMX93_CLK_ENET1_GATE, "enet1", "enet_root", 0x9e00, }, + { IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, }, + { IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "osc_24m", 0x9e80, }, + { IMX93_CLK_TSTMR1_GATE, "tstmr1", "bus_aon_root", 0x9ec0, }, + { IMX93_CLK_TSTMR2_GATE, "tstmr2", "bus_wakeup_root", 0x9f00, }, + { IMX93_CLK_TMC_GATE, "tmc", "osc_24m", 0x9f40, }, + { IMX93_CLK_PMRO_GATE, "pmro", "osc_24m", 0x9f80, } +}; + +static struct clk_hw_onecell_data *clk_hw_data; +static struct clk_hw **clks; + +static int imx93_clocks_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + const struct imx93_clk_root *root; + const struct imx93_clk_ccgr *ccgr; + void __iomem *base = NULL; + int i, ret; + + clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, + IMX93_CLK_END), GFP_KERNEL); + if (!clk_hw_data) + return -ENOMEM; + + clk_hw_data->num = IMX93_CLK_END; + clks = clk_hw_data->hws; + + clks[IMX93_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0); + clks[IMX93_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m"); + clks[IMX93_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k"); + clks[IMX93_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1"); + + clks[IMX93_CLK_SYS_PLL_PFD0] = imx_clk_hw_fixed("sys_pll_pfd0", 1000000000); + clks[IMX93_CLK_SYS_PLL_PFD0_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd0_div2", + "sys_pll_pfd0", 1, 2); + clks[IMX93_CLK_SYS_PLL_PFD1] = imx_clk_hw_fixed("sys_pll_pfd1", 800000000); + clks[IMX93_CLK_SYS_PLL_PFD1_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd1_div2", + "sys_pll_pfd1", 1, 2); + clks[IMX93_CLK_SYS_PLL_PFD2] = imx_clk_hw_fixed("sys_pll_pfd2", 625000000); + clks[IMX93_CLK_SYS_PLL_PFD2_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd2_div2", + "sys_pll_pfd2", 1, 2); + + np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop"); + base = of_iomap(np, 0); + of_node_put(np); + if (WARN_ON(!base)) + return -ENOMEM; + + clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", base + 0x1200, + &imx_fracn_gppll); + clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", base + 0x1400, + &imx_fracn_gppll); + + np = dev->of_node; + base = devm_platform_ioremap_resource(pdev, 0); + if (WARN_ON(IS_ERR(base))) + return PTR_ERR(base); + + for (i = 0; i < ARRAY_SIZE(root_array); i++) { + root = &root_array[i]; + clks[root->clk] = imx93_clk_composite_flags(root->name, + parent_names[root->sel], + 4, base + root->off, + root->flags); + } + + for (i = 0; i < ARRAY_SIZE(ccgr_array); i++) { + ccgr = &ccgr_array[i]; + clks[ccgr->clk] = imx_clk_hw_gate4_flags(ccgr->name, + ccgr->parent_name, + base + ccgr->off, 0, + ccgr->flags); + } + + imx_check_clk_hws(clks, IMX93_CLK_END); + + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + if (ret < 0) { + dev_err(dev, "failed to register clks for i.MX93\n"); + goto unregister_hws; + } + + return 0; + +unregister_hws: + imx_unregister_hw_clocks(clks, IMX93_CLK_END); + + return ret; +} + +static const struct of_device_id imx93_clk_of_match[] = { + { .compatible = "fsl,imx93-ccm" }, + { /* Sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, imx93_clk_of_match); + +static struct platform_driver imx93_clk_driver = { + .probe = imx93_clocks_probe, + .driver = { + .name = "imx93-ccm", + .suppress_bind_attrs = true, + .of_match_table = of_match_ptr(imx93_clk_of_match), + }, +}; +module_platform_driver(imx93_clk_driver); + +MODULE_DESCRIPTION("NXP i.MX93 clock driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c new file mode 100644 index 000000000000..9539d35588ee --- /dev/null +++ b/drivers/clk/imx/clk-imxrt1050.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) 2021 + * Author(s): + * Jesse Taube <Mr.Bossman075@gmail.com> + * Giulio Benetti <giulio.benetti@benettiengineering.com> + */ +#include <linux/clk.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/imxrt1050-clock.h> + +#include "clk.h" + +static const char * const pll_ref_sels[] = {"osc", "dummy", }; +static const char * const per_sels[] = {"ipg_pdof", "osc", }; +static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", }; +static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", }; +static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "pll3_usb_otg_ref_sel", }; +static const char * const pll5_bypass_sels[] = {"pll5_video", "pll5_video_ref_sel", }; +static const char *const pre_periph_sels[] = { + "pll2_sys", "pll2_pfd2_396m", "pll2_pfd0_352m", "arm_podf", }; +static const char *const periph_sels[] = { "pre_periph_sel", "todo", }; +static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; +static const char *const lpuart_sels[] = { "pll3_80m", "osc", }; +static const char *const lcdif_sels[] = { + "pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m", + "pll2_pfd1_594m", "pll3_pfd1_664_62m", }; +static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", }; +static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", }; + +static struct clk_hw **hws; +static struct clk_hw_onecell_data *clk_hw_data; + +static int imxrt1050_clocks_probe(struct platform_device *pdev) +{ + void __iomem *ccm_base; + void __iomem *pll_base; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct device_node *anp; + int ret; + + clk_hw_data = kzalloc(struct_size(clk_hw_data, hws, + IMXRT1050_CLK_END), GFP_KERNEL); + if (WARN_ON(!clk_hw_data)) + return -ENOMEM; + + clk_hw_data->num = IMXRT1050_CLK_END; + hws = clk_hw_data->hws; + + hws[IMXRT1050_CLK_OSC] = imx_obtain_fixed_clk_hw(np, "osc"); + + anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop"); + pll_base = of_iomap(anp, 0); + of_node_put(anp); + if (WARN_ON(!pll_base)) + return -ENOMEM; + + /* Anatop clocks */ + hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL); + + hws[IMXRT1050_CLK_PLL1_REF_SEL] = imx_clk_hw_mux("pll1_arm_ref_sel", + pll_base + 0x0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMXRT1050_CLK_PLL2_REF_SEL] = imx_clk_hw_mux("pll2_sys_ref_sel", + pll_base + 0x30, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMXRT1050_CLK_PLL3_REF_SEL] = imx_clk_hw_mux("pll3_usb_otg_ref_sel", + pll_base + 0x10, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + hws[IMXRT1050_CLK_PLL5_REF_SEL] = imx_clk_hw_mux("pll5_video_ref_sel", + pll_base + 0xa0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels)); + + hws[IMXRT1050_CLK_PLL1_ARM] = imx_clk_hw_pllv3(IMX_PLLV3_SYS, "pll1_arm", + "pll1_arm_ref_sel", pll_base + 0x0, 0x7f); + hws[IMXRT1050_CLK_PLL2_SYS] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2_sys", + "pll2_sys_ref_sel", pll_base + 0x30, 0x1); + hws[IMXRT1050_CLK_PLL3_USB_OTG] = imx_clk_hw_pllv3(IMX_PLLV3_USB, "pll3_usb_otg", + "pll3_usb_otg_ref_sel", pll_base + 0x10, 0x1); + hws[IMXRT1050_CLK_PLL5_VIDEO] = imx_clk_hw_pllv3(IMX_PLLV3_AV, "pll5_video", + "pll5_video_ref_sel", pll_base + 0xa0, 0x7f); + + /* PLL bypass out */ + hws[IMXRT1050_CLK_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", pll_base + 0x0, 16, 1, + pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMXRT1050_CLK_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", pll_base + 0x30, 16, 1, + pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMXRT1050_CLK_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", pll_base + 0x10, 16, 1, + pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT); + hws[IMXRT1050_CLK_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", pll_base + 0xa0, 16, 1, + pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT); + + hws[IMXRT1050_CLK_VIDEO_POST_DIV_SEL] = imx_clk_hw_divider("video_post_div_sel", + "pll5_video", pll_base + 0xa0, 19, 2); + hws[IMXRT1050_CLK_VIDEO_DIV] = imx_clk_hw_divider("video_div", + "video_post_div_sel", pll_base + 0x170, 30, 2); + + hws[IMXRT1050_CLK_PLL3_80M] = imx_clk_hw_fixed_factor("pll3_80m", "pll3_usb_otg", 1, 6); + + hws[IMXRT1050_CLK_PLL2_PFD0_352M] = imx_clk_hw_pfd("pll2_pfd0_352m", "pll2_sys", pll_base + 0x100, 0); + hws[IMXRT1050_CLK_PLL2_PFD1_594M] = imx_clk_hw_pfd("pll2_pfd1_594m", "pll2_sys", pll_base + 0x100, 1); + hws[IMXRT1050_CLK_PLL2_PFD2_396M] = imx_clk_hw_pfd("pll2_pfd2_396m", "pll2_sys", pll_base + 0x100, 2); + hws[IMXRT1050_CLK_PLL3_PFD1_664_62M] = imx_clk_hw_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", pll_base + 0xf0, 1); + hws[IMXRT1050_CLK_PLL3_PFD3_454_74M] = imx_clk_hw_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", pll_base + 0xf0, 3); + + /* CCM clocks */ + ccm_base = devm_platform_ioremap_resource(pdev, 0); + if (WARN_ON(IS_ERR(ccm_base))) + return PTR_ERR(ccm_base); + + hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3); + hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2, + pre_periph_sels, ARRAY_SIZE(pre_periph_sels)); + hws[IMXRT1050_CLK_PERIPH_SEL] = imx_clk_hw_mux("periph_sel", ccm_base + 0x14, 25, 1, + periph_sels, ARRAY_SIZE(periph_sels)); + hws[IMXRT1050_CLK_USDHC1_SEL] = imx_clk_hw_mux("usdhc1_sel", ccm_base + 0x1c, 16, 1, + usdhc_sels, ARRAY_SIZE(usdhc_sels)); + hws[IMXRT1050_CLK_USDHC2_SEL] = imx_clk_hw_mux("usdhc2_sel", ccm_base + 0x1c, 17, 1, + usdhc_sels, ARRAY_SIZE(usdhc_sels)); + hws[IMXRT1050_CLK_LPUART_SEL] = imx_clk_hw_mux("lpuart_sel", ccm_base + 0x24, 6, 1, + lpuart_sels, ARRAY_SIZE(lpuart_sels)); + hws[IMXRT1050_CLK_LCDIF_SEL] = imx_clk_hw_mux("lcdif_sel", ccm_base + 0x38, 15, 3, + lcdif_sels, ARRAY_SIZE(lcdif_sels)); + hws[IMXRT1050_CLK_PER_CLK_SEL] = imx_clk_hw_mux("per_sel", ccm_base + 0x1C, 6, 1, + per_sels, ARRAY_SIZE(per_sels)); + hws[IMXRT1050_CLK_SEMC_ALT_SEL] = imx_clk_hw_mux("semc_alt_sel", ccm_base + 0x14, 7, 1, + semc_alt_sels, ARRAY_SIZE(semc_alt_sels)); + hws[IMXRT1050_CLK_SEMC_SEL] = imx_clk_hw_mux_flags("semc_sel", ccm_base + 0x14, 6, 1, + semc_sels, ARRAY_SIZE(semc_sels), CLK_IS_CRITICAL); + + hws[IMXRT1050_CLK_AHB_PODF] = imx_clk_hw_divider("ahb", "periph_sel", ccm_base + 0x14, 10, 3); + hws[IMXRT1050_CLK_IPG_PDOF] = imx_clk_hw_divider("ipg", "ahb", ccm_base + 0x14, 8, 2); + hws[IMXRT1050_CLK_PER_PDOF] = imx_clk_hw_divider("per", "per_sel", ccm_base + 0x1C, 0, 5); + + hws[IMXRT1050_CLK_USDHC1_PODF] = imx_clk_hw_divider("usdhc1_podf", "usdhc1_sel", ccm_base + 0x24, 11, 3); + hws[IMXRT1050_CLK_USDHC2_PODF] = imx_clk_hw_divider("usdhc2_podf", "usdhc2_sel", ccm_base + 0x24, 16, 3); + hws[IMXRT1050_CLK_LPUART_PODF] = imx_clk_hw_divider("lpuart_podf", "lpuart_sel", ccm_base + 0x24, 0, 6); + hws[IMXRT1050_CLK_LCDIF_PRED] = imx_clk_hw_divider("lcdif_pred", "lcdif_sel", ccm_base + 0x38, 12, 3); + hws[IMXRT1050_CLK_LCDIF_PODF] = imx_clk_hw_divider("lcdif_podf", "lcdif_pred", ccm_base + 0x18, 23, 3); + + hws[IMXRT1050_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1", "usdhc1_podf", ccm_base + 0x80, 2); + hws[IMXRT1050_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2", "usdhc2_podf", ccm_base + 0x80, 4); + hws[IMXRT1050_CLK_LPUART1] = imx_clk_hw_gate2("lpuart1", "lpuart_podf", ccm_base + 0x7c, 24); + hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x74, 10); + hws[IMXRT1050_CLK_DMA] = imx_clk_hw_gate("dma", "ipg", ccm_base + 0x7C, 6); + hws[IMXRT1050_CLK_DMA_MUX] = imx_clk_hw_gate("dmamux0", "ipg", ccm_base + 0x7C, 7); + imx_check_clk_hws(hws, IMXRT1050_CLK_END); + + ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data); + if (ret < 0) { + dev_err(dev, "Failed to register clks for i.MXRT1050.\n"); + imx_unregister_hw_clocks(hws, IMXRT1050_CLK_END); + } + return ret; +} +static const struct of_device_id imxrt1050_clk_of_match[] = { + { .compatible = "fsl,imxrt1050-ccm" }, + { /* Sentinel */ } +}; +MODULE_DEVICE_TABLE(of, imxrt1050_clk_of_match); + +static struct platform_driver imxrt1050_clk_driver = { + .probe = imxrt1050_clocks_probe, + .driver = { + .name = "imxrt1050-ccm", + .of_match_table = imxrt1050_clk_of_match, + }, +}; +module_platform_driver(imxrt1050_clk_driver); diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 2b5ed86b9dbb..1d0f79e9c346 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -3,6 +3,9 @@ * Copyright 2017-2018 NXP. */ +#define pr_fmt(fmt) "pll14xx: " fmt + +#include <linux/bitfield.h> #include <linux/bits.h> #include <linux/clk-provider.h> #include <linux/err.h> @@ -15,20 +18,19 @@ #include "clk.h" #define GNRL_CTL 0x0 -#define DIV_CTL 0x4 +#define DIV_CTL0 0x4 +#define DIV_CTL1 0x8 #define LOCK_STATUS BIT(31) #define LOCK_SEL_MASK BIT(29) #define CLKE_MASK BIT(11) #define RST_MASK BIT(9) #define BYPASS_MASK BIT(4) -#define MDIV_SHIFT 12 #define MDIV_MASK GENMASK(21, 12) -#define PDIV_SHIFT 4 #define PDIV_MASK GENMASK(9, 4) -#define SDIV_SHIFT 0 #define SDIV_MASK GENMASK(2, 0) -#define KDIV_SHIFT 0 #define KDIV_MASK GENMASK(15, 0) +#define KDIV_MIN SHRT_MIN +#define KDIV_MAX SHRT_MAX #define LOCK_TIMEOUT_US 10000 @@ -99,62 +101,165 @@ static const struct imx_pll14xx_rate_table *imx_get_pll_settings( return NULL; } -static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate, +static long pll14xx_calc_rate(struct clk_pll14xx *pll, int mdiv, int pdiv, + int sdiv, int kdiv, unsigned long prate) +{ + u64 fvco = prate; + + /* fvco = (m * 65536 + k) * Fin / (p * 65536) */ + fvco *= (mdiv * 65536 + kdiv); + pdiv *= 65536; + + do_div(fvco, pdiv << sdiv); + + return fvco; +} + +static long pll1443x_calc_kdiv(int mdiv, int pdiv, int sdiv, + unsigned long rate, unsigned long prate) +{ + long kdiv; + + /* calc kdiv = round(rate * pdiv * 65536 * 2^sdiv / prate) - (mdiv * 65536) */ + kdiv = ((rate * ((pdiv * 65536) << sdiv) + prate / 2) / prate) - (mdiv * 65536); + + return clamp_t(short, kdiv, KDIV_MIN, KDIV_MAX); +} + +static void imx_pll14xx_calc_settings(struct clk_pll14xx *pll, unsigned long rate, + unsigned long prate, struct imx_pll14xx_rate_table *t) +{ + u32 pll_div_ctl0, pll_div_ctl1; + int mdiv, pdiv, sdiv, kdiv; + long fvco, rate_min, rate_max, dist, best = LONG_MAX; + const struct imx_pll14xx_rate_table *tt; + + /* + * Fractional PLL constrains: + * + * a) 6MHz <= prate <= 25MHz + * b) 1 <= p <= 63 (1 <= p <= 4 prate = 24MHz) + * c) 64 <= m <= 1023 + * d) 0 <= s <= 6 + * e) -32768 <= k <= 32767 + * + * fvco = (m * 65536 + k) * prate / (p * 65536) + */ + + /* First try if we can get the desired rate from one of the static entries */ + tt = imx_get_pll_settings(pll, rate); + if (tt) { + pr_debug("%s: in=%ld, want=%ld, Using PLL setting from table\n", + clk_hw_get_name(&pll->hw), prate, rate); + t->rate = tt->rate; + t->mdiv = tt->mdiv; + t->pdiv = tt->pdiv; + t->sdiv = tt->sdiv; + t->kdiv = tt->kdiv; + return; + } + + pll_div_ctl0 = readl_relaxed(pll->base + DIV_CTL0); + mdiv = FIELD_GET(MDIV_MASK, pll_div_ctl0); + pdiv = FIELD_GET(PDIV_MASK, pll_div_ctl0); + sdiv = FIELD_GET(SDIV_MASK, pll_div_ctl0); + pll_div_ctl1 = readl_relaxed(pll->base + DIV_CTL1); + + /* Then see if we can get the desired rate by only adjusting kdiv (glitch free) */ + rate_min = pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, KDIV_MIN, prate); + rate_max = pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, KDIV_MAX, prate); + + if (rate >= rate_min && rate <= rate_max) { + kdiv = pll1443x_calc_kdiv(mdiv, pdiv, sdiv, rate, prate); + pr_debug("%s: in=%ld, want=%ld Only adjust kdiv %ld -> %d\n", + clk_hw_get_name(&pll->hw), prate, rate, + FIELD_GET(KDIV_MASK, pll_div_ctl1), kdiv); + fvco = pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, kdiv, prate); + t->rate = (unsigned int)fvco; + t->mdiv = mdiv; + t->pdiv = pdiv; + t->sdiv = sdiv; + t->kdiv = kdiv; + return; + } + + /* Finally calculate best values */ + for (pdiv = 1; pdiv <= 7; pdiv++) { + for (sdiv = 0; sdiv <= 6; sdiv++) { + /* calc mdiv = round(rate * pdiv * 2^sdiv) / prate) */ + mdiv = DIV_ROUND_CLOSEST(rate * (pdiv << sdiv), prate); + mdiv = clamp(mdiv, 64, 1023); + + kdiv = pll1443x_calc_kdiv(mdiv, pdiv, sdiv, rate, prate); + fvco = pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, kdiv, prate); + + /* best match */ + dist = abs((long)rate - (long)fvco); + if (dist < best) { + best = dist; + t->rate = (unsigned int)fvco; + t->mdiv = mdiv; + t->pdiv = pdiv; + t->sdiv = sdiv; + t->kdiv = kdiv; + + if (!dist) + goto found; + } + } + } +found: + pr_debug("%s: in=%ld, want=%ld got=%d (pdiv=%d sdiv=%d mdiv=%d kdiv=%d)\n", + clk_hw_get_name(&pll->hw), prate, rate, t->rate, t->pdiv, t->sdiv, + t->mdiv, t->kdiv); +} + +static long clk_pll1416x_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); const struct imx_pll14xx_rate_table *rate_table = pll->rate_table; int i; - /* Assumming rate_table is in descending order */ + /* Assuming rate_table is in descending order */ for (i = 0; i < pll->rate_count; i++) if (rate >= rate_table[i].rate) return rate_table[i].rate; /* return minimum supported value */ - return rate_table[i - 1].rate; + return rate_table[pll->rate_count - 1].rate; } -static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) +static long clk_pll1443x_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); - u32 mdiv, pdiv, sdiv, pll_div; - u64 fvco = parent_rate; + struct imx_pll14xx_rate_table t; - pll_div = readl_relaxed(pll->base + 4); - mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT; - pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT; - sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT; + imx_pll14xx_calc_settings(pll, rate, *prate, &t); - fvco *= mdiv; - do_div(fvco, pdiv << sdiv); - - return fvco; + return t.rate; } -static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw, +static unsigned long clk_pll14xx_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); - u32 mdiv, pdiv, sdiv, pll_div_ctl0, pll_div_ctl1; - short int kdiv; - u64 fvco = parent_rate; - - pll_div_ctl0 = readl_relaxed(pll->base + 4); - pll_div_ctl1 = readl_relaxed(pll->base + 8); - mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT; - pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT; - sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT; - kdiv = pll_div_ctl1 & KDIV_MASK; - - /* fvco = (m * 65536 + k) * Fin / (p * 65536) */ - fvco *= (mdiv * 65536 + kdiv); - pdiv *= 65536; - - do_div(fvco, pdiv << sdiv); + u32 mdiv, pdiv, sdiv, kdiv, pll_div_ctl0, pll_div_ctl1; + + pll_div_ctl0 = readl_relaxed(pll->base + DIV_CTL0); + mdiv = FIELD_GET(MDIV_MASK, pll_div_ctl0); + pdiv = FIELD_GET(PDIV_MASK, pll_div_ctl0); + sdiv = FIELD_GET(SDIV_MASK, pll_div_ctl0); + + if (pll->type == PLL_1443X) { + pll_div_ctl1 = readl_relaxed(pll->base + DIV_CTL1); + kdiv = FIELD_GET(KDIV_MASK, pll_div_ctl1); + } else { + kdiv = 0; + } - return fvco; + return pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, kdiv, parent_rate); } static inline bool clk_pll14xx_mp_change(const struct imx_pll14xx_rate_table *rate, @@ -162,8 +267,8 @@ static inline bool clk_pll14xx_mp_change(const struct imx_pll14xx_rate_table *ra { u32 old_mdiv, old_pdiv; - old_mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT; - old_pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT; + old_mdiv = FIELD_GET(MDIV_MASK, pll_div); + old_pdiv = FIELD_GET(PDIV_MASK, pll_div); return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv; } @@ -172,7 +277,7 @@ static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll) { u32 val; - return readl_poll_timeout(pll->base, val, val & LOCK_STATUS, 0, + return readl_poll_timeout(pll->base + GNRL_CTL, val, val & LOCK_STATUS, 0, LOCK_TIMEOUT_US); } @@ -186,37 +291,37 @@ static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, rate = imx_get_pll_settings(pll, drate); if (!rate) { - pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, - drate, clk_hw_get_name(hw)); + pr_err("Invalid rate %lu for pll clk %s\n", drate, + clk_hw_get_name(hw)); return -EINVAL; } - tmp = readl_relaxed(pll->base + 4); + tmp = readl_relaxed(pll->base + DIV_CTL0); if (!clk_pll14xx_mp_change(rate, tmp)) { - tmp &= ~(SDIV_MASK) << SDIV_SHIFT; - tmp |= rate->sdiv << SDIV_SHIFT; - writel_relaxed(tmp, pll->base + 4); + tmp &= ~SDIV_MASK; + tmp |= FIELD_PREP(SDIV_MASK, rate->sdiv); + writel_relaxed(tmp, pll->base + DIV_CTL0); return 0; } /* Bypass clock and set lock to pll output lock */ - tmp = readl_relaxed(pll->base); + tmp = readl_relaxed(pll->base + GNRL_CTL); tmp |= LOCK_SEL_MASK; - writel_relaxed(tmp, pll->base); + writel_relaxed(tmp, pll->base + GNRL_CTL); /* Enable RST */ tmp &= ~RST_MASK; - writel_relaxed(tmp, pll->base); + writel_relaxed(tmp, pll->base + GNRL_CTL); /* Enable BYPASS */ tmp |= BYPASS_MASK; - writel(tmp, pll->base); + writel(tmp, pll->base + GNRL_CTL); - div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) | - (rate->sdiv << SDIV_SHIFT); - writel_relaxed(div_val, pll->base + 0x4); + div_val = FIELD_PREP(MDIV_MASK, rate->mdiv) | FIELD_PREP(PDIV_MASK, rate->pdiv) | + FIELD_PREP(SDIV_MASK, rate->sdiv); + writel_relaxed(div_val, pll->base + DIV_CTL0); /* * According to SPEC, t3 - t2 need to be greater than @@ -228,7 +333,7 @@ static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, /* Disable RST */ tmp |= RST_MASK; - writel_relaxed(tmp, pll->base); + writel_relaxed(tmp, pll->base + GNRL_CTL); /* Wait Lock */ ret = clk_pll14xx_wait_lock(pll); @@ -237,7 +342,7 @@ static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, /* Bypass */ tmp &= ~BYPASS_MASK; - writel_relaxed(tmp, pll->base); + writel_relaxed(tmp, pll->base + GNRL_CTL); return 0; } @@ -246,43 +351,41 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long prate) { struct clk_pll14xx *pll = to_clk_pll14xx(hw); - const struct imx_pll14xx_rate_table *rate; - u32 tmp, div_val; + struct imx_pll14xx_rate_table rate; + u32 gnrl_ctl, div_ctl0; int ret; - rate = imx_get_pll_settings(pll, drate); - if (!rate) { - pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, - drate, clk_hw_get_name(hw)); - return -EINVAL; - } + imx_pll14xx_calc_settings(pll, drate, prate, &rate); - tmp = readl_relaxed(pll->base + 4); + div_ctl0 = readl_relaxed(pll->base + DIV_CTL0); - if (!clk_pll14xx_mp_change(rate, tmp)) { - tmp &= ~(SDIV_MASK) << SDIV_SHIFT; - tmp |= rate->sdiv << SDIV_SHIFT; - writel_relaxed(tmp, pll->base + 4); + if (!clk_pll14xx_mp_change(&rate, div_ctl0)) { + /* only sdiv and/or kdiv changed - no need to RESET PLL */ + div_ctl0 &= ~SDIV_MASK; + div_ctl0 |= FIELD_PREP(SDIV_MASK, rate.sdiv); + writel_relaxed(div_ctl0, pll->base + DIV_CTL0); - tmp = rate->kdiv << KDIV_SHIFT; - writel_relaxed(tmp, pll->base + 8); + writel_relaxed(FIELD_PREP(KDIV_MASK, rate.kdiv), + pll->base + DIV_CTL1); return 0; } /* Enable RST */ - tmp = readl_relaxed(pll->base); - tmp &= ~RST_MASK; - writel_relaxed(tmp, pll->base); + gnrl_ctl = readl_relaxed(pll->base + GNRL_CTL); + gnrl_ctl &= ~RST_MASK; + writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); /* Enable BYPASS */ - tmp |= BYPASS_MASK; - writel_relaxed(tmp, pll->base); + gnrl_ctl |= BYPASS_MASK; + writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); - div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) | - (rate->sdiv << SDIV_SHIFT); - writel_relaxed(div_val, pll->base + 0x4); - writel_relaxed(rate->kdiv << KDIV_SHIFT, pll->base + 0x8); + div_ctl0 = FIELD_PREP(MDIV_MASK, rate.mdiv) | + FIELD_PREP(PDIV_MASK, rate.pdiv) | + FIELD_PREP(SDIV_MASK, rate.sdiv); + writel_relaxed(div_ctl0, pll->base + DIV_CTL0); + + writel_relaxed(FIELD_PREP(KDIV_MASK, rate.kdiv), pll->base + DIV_CTL1); /* * According to SPEC, t3 - t2 need to be greater than @@ -293,8 +396,8 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate, udelay(3); /* Disable RST */ - tmp |= RST_MASK; - writel_relaxed(tmp, pll->base); + gnrl_ctl |= RST_MASK; + writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); /* Wait Lock*/ ret = clk_pll14xx_wait_lock(pll); @@ -302,8 +405,8 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate, return ret; /* Bypass */ - tmp &= ~BYPASS_MASK; - writel_relaxed(tmp, pll->base); + gnrl_ctl &= ~BYPASS_MASK; + writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); return 0; } @@ -364,21 +467,21 @@ static const struct clk_ops clk_pll1416x_ops = { .prepare = clk_pll14xx_prepare, .unprepare = clk_pll14xx_unprepare, .is_prepared = clk_pll14xx_is_prepared, - .recalc_rate = clk_pll1416x_recalc_rate, - .round_rate = clk_pll14xx_round_rate, + .recalc_rate = clk_pll14xx_recalc_rate, + .round_rate = clk_pll1416x_round_rate, .set_rate = clk_pll1416x_set_rate, }; static const struct clk_ops clk_pll1416x_min_ops = { - .recalc_rate = clk_pll1416x_recalc_rate, + .recalc_rate = clk_pll14xx_recalc_rate, }; static const struct clk_ops clk_pll1443x_ops = { .prepare = clk_pll14xx_prepare, .unprepare = clk_pll14xx_unprepare, .is_prepared = clk_pll14xx_is_prepared, - .recalc_rate = clk_pll1443x_recalc_rate, - .round_rate = clk_pll14xx_round_rate, + .recalc_rate = clk_pll14xx_recalc_rate, + .round_rate = clk_pll1443x_round_rate, .set_rate = clk_pll1443x_set_rate, }; @@ -412,8 +515,7 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, init.ops = &clk_pll1443x_ops; break; default: - pr_err("%s: Unknown pll type for pll clk %s\n", - __func__, name); + pr_err("Unknown pll type for pll clk %s\n", name); kfree(pll); return ERR_PTR(-EINVAL); } @@ -432,8 +534,7 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, ret = clk_hw_register(dev, hw); if (ret) { - pr_err("%s: failed to register pll %s %d\n", - __func__, name, ret); + pr_err("failed to register pll %s %d\n", name, ret); kfree(pll); return ERR_PTR(ret); } diff --git a/drivers/clk/imx/clk-scu.h b/drivers/clk/imx/clk-scu.h index 22156e93b85d..af7b697f51ca 100644 --- a/drivers/clk/imx/clk-scu.h +++ b/drivers/clk/imx/clk-scu.h @@ -21,6 +21,7 @@ struct imx_clk_scu_rsrc_table { extern struct list_head imx_scu_clks[]; extern const struct dev_pm_ops imx_clk_lpcg_scu_pm_ops; +extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8dxl; extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qxp; extern const struct imx_clk_scu_rsrc_table imx_clk_scu_rsrc_imx8qm; diff --git a/drivers/clk/imx/clk-sscg-pll.c b/drivers/clk/imx/clk-sscg-pll.c index 9d6cdff0537f..81f304fae908 100644 --- a/drivers/clk/imx/clk-sscg-pll.c +++ b/drivers/clk/imx/clk-sscg-pll.c @@ -525,7 +525,6 @@ struct clk_hw *imx_clk_hw_sscg_pll(const char *name, init.parent_names = parent_names; init.num_parents = num_parents; - pll->base = base; pll->hw.init = &init; hw = &pll->hw; diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h index 7d220a01de1f..a7cbbcd1a3f4 100644 --- a/drivers/clk/imx/clk.h +++ b/drivers/clk/imx/clk.h @@ -72,6 +72,27 @@ extern struct imx_pll14xx_clk imx_1416x_pll; extern struct imx_pll14xx_clk imx_1443x_pll; extern struct imx_pll14xx_clk imx_1443x_dram_pll; +/* NOTE: Rate table should be kept sorted in descending order. */ +struct imx_fracn_gppll_rate_table { + unsigned int rate; + unsigned int mfi; + unsigned int mfn; + unsigned int mfd; + unsigned int rdiv; + unsigned int odiv; +}; + +struct imx_fracn_gppll_clk { + const struct imx_fracn_gppll_rate_table *rate_table; + int rate_count; + int flags; +}; + +struct clk_hw *imx_clk_fracn_gppll(const char *name, const char *parent_name, void __iomem *base, + const struct imx_fracn_gppll_clk *pll_clk); + +extern struct imx_fracn_gppll_clk imx_fracn_gppll; + #define imx_clk_cpu(name, parent_name, div, mux, pll, step) \ to_clk(imx_clk_hw_cpu(name, parent_name, div, mux, pll, step)) @@ -419,6 +440,15 @@ struct clk_hw *__imx8m_clk_hw_composite(const char *name, IMX_COMPOSITE_FW_MANAGED, \ IMX_COMPOSITE_CLK_FLAGS_CRITICAL_GET_RATE_NO_CACHE) +struct clk_hw *imx93_clk_composite_flags(const char *name, + const char * const *parent_names, + int num_parents, + void __iomem *reg, + unsigned long flags); +#define imx93_clk_composite(name, parent_names, num_parents, reg) \ + imx93_clk_composite_flags(name, parent_names, num_parents, reg, \ + CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE) + struct clk_hw *imx_clk_hw_divider_gate(const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, const struct clk_div_table *table, diff --git a/drivers/clk/loongson1/clk-loongson1c.c b/drivers/clk/loongson1/clk-loongson1c.c index 703f87622cf5..1ebf740380ef 100644 --- a/drivers/clk/loongson1/clk-loongson1c.c +++ b/drivers/clk/loongson1/clk-loongson1c.c @@ -37,6 +37,7 @@ static const struct clk_div_table ahb_div_table[] = { [1] = { .val = 1, .div = 4 }, [2] = { .val = 2, .div = 3 }, [3] = { .val = 3, .div = 3 }, + [4] = { /* sentinel */ } }; void __init ls1x_clk_init(void) diff --git a/drivers/clk/mediatek/clk-apmixed.c b/drivers/clk/mediatek/clk-apmixed.c index caa9119413f1..a29339cc26c4 100644 --- a/drivers/clk/mediatek/clk-apmixed.c +++ b/drivers/clk/mediatek/clk-apmixed.c @@ -92,7 +92,7 @@ struct clk * __init mtk_clk_register_ref2usb_tx(const char *name, clk = clk_register(NULL, &tx->hw); if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk)); + pr_err("Failed to register clk %s: %pe\n", name, clk); kfree(tx); } diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c index e188018bc906..c11b3fae622e 100644 --- a/drivers/clk/mediatek/clk-cpumux.c +++ b/drivers/clk/mediatek/clk-cpumux.c @@ -5,13 +5,24 @@ */ #include <linux/clk-provider.h> +#include <linux/container_of.h> +#include <linux/err.h> #include <linux/mfd/syscon.h> #include <linux/module.h> +#include <linux/regmap.h> #include <linux/slab.h> #include "clk-mtk.h" #include "clk-cpumux.h" +struct mtk_clk_cpumux { + struct clk_hw hw; + struct regmap *regmap; + u32 reg; + u32 mask; + u8 shift; +}; + static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw) { return container_of(_hw, struct mtk_clk_cpumux, hw); @@ -77,6 +88,21 @@ mtk_clk_register_cpumux(const struct mtk_composite *mux, return clk; } +static void mtk_clk_unregister_cpumux(struct clk *clk) +{ + struct mtk_clk_cpumux *cpumux; + struct clk_hw *hw; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + cpumux = to_mtk_clk_cpumux(hw); + + clk_unregister(clk); + kfree(cpumux); +} + int mtk_clk_register_cpumuxes(struct device_node *node, const struct mtk_composite *clks, int num, struct clk_onecell_data *clk_data) @@ -87,25 +113,58 @@ int mtk_clk_register_cpumuxes(struct device_node *node, regmap = device_node_to_regmap(node); if (IS_ERR(regmap)) { - pr_err("Cannot find regmap for %pOF: %ld\n", node, - PTR_ERR(regmap)); + pr_err("Cannot find regmap for %pOF: %pe\n", node, regmap); return PTR_ERR(regmap); } for (i = 0; i < num; i++) { const struct mtk_composite *mux = &clks[i]; + if (!IS_ERR_OR_NULL(clk_data->clks[mux->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, mux->id); + continue; + } + clk = mtk_clk_register_cpumux(mux, regmap); if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - mux->name, PTR_ERR(clk)); - continue; + pr_err("Failed to register clk %s: %pe\n", mux->name, clk); + goto err; } clk_data->clks[mux->id] = clk; } return 0; + +err: + while (--i >= 0) { + const struct mtk_composite *mux = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + continue; + + mtk_clk_unregister_cpumux(clk_data->clks[mux->id]); + clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(clk); +} + +void mtk_clk_unregister_cpumuxes(const struct mtk_composite *clks, int num, + struct clk_onecell_data *clk_data) +{ + int i; + + for (i = num; i > 0; i--) { + const struct mtk_composite *mux = &clks[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + continue; + + mtk_clk_unregister_cpumux(clk_data->clks[mux->id]); + clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + } } MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-cpumux.h b/drivers/clk/mediatek/clk-cpumux.h index 2aaf1afd4e5f..b07e89f7c283 100644 --- a/drivers/clk/mediatek/clk-cpumux.h +++ b/drivers/clk/mediatek/clk-cpumux.h @@ -7,16 +7,15 @@ #ifndef __DRV_CLK_CPUMUX_H #define __DRV_CLK_CPUMUX_H -struct mtk_clk_cpumux { - struct clk_hw hw; - struct regmap *regmap; - u32 reg; - u32 mask; - u8 shift; -}; +struct clk_onecell_data; +struct device_node; +struct mtk_composite; int mtk_clk_register_cpumuxes(struct device_node *node, const struct mtk_composite *clks, int num, struct clk_onecell_data *clk_data); +void mtk_clk_unregister_cpumuxes(const struct mtk_composite *clks, int num, + struct clk_onecell_data *clk_data); + #endif /* __DRV_CLK_CPUMUX_H */ diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c index 5d88b428565b..da52023f8455 100644 --- a/drivers/clk/mediatek/clk-gate.c +++ b/drivers/clk/mediatek/clk-gate.c @@ -4,18 +4,30 @@ * Author: James Liao <jamesjj.liao@mediatek.com> */ -#include <linux/of.h> -#include <linux/of_address.h> - -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/mfd/syscon.h> #include <linux/module.h> +#include <linux/printk.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/types.h> -#include "clk-mtk.h" #include "clk-gate.h" +struct mtk_clk_gate { + struct clk_hw hw; + struct regmap *regmap; + int set_ofs; + int clr_ofs; + int sta_ofs; + u8 bit; +}; + +static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_gate, hw); +} + static u32 mtk_get_clockgating(struct clk_hw *hw) { struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); @@ -140,17 +152,12 @@ const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = { }; EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr_inv); -struct clk *mtk_clk_register_gate( - const char *name, - const char *parent_name, - struct regmap *regmap, - int set_ofs, - int clr_ofs, - int sta_ofs, - u8 bit, - const struct clk_ops *ops, - unsigned long flags, - struct device *dev) +static struct clk *mtk_clk_register_gate(const char *name, + const char *parent_name, + struct regmap *regmap, int set_ofs, + int clr_ofs, int sta_ofs, u8 bit, + const struct clk_ops *ops, + unsigned long flags, struct device *dev) { struct mtk_clk_gate *cg; struct clk *clk; @@ -180,6 +187,107 @@ struct clk *mtk_clk_register_gate( return clk; } -EXPORT_SYMBOL_GPL(mtk_clk_register_gate); + +static void mtk_clk_unregister_gate(struct clk *clk) +{ + struct mtk_clk_gate *cg; + struct clk_hw *hw; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + cg = to_mtk_clk_gate(hw); + + clk_unregister(clk); + kfree(cg); +} + +int mtk_clk_register_gates_with_dev(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data, + struct device *dev) +{ + int i; + struct clk *clk; + struct regmap *regmap; + + if (!clk_data) + return -ENOMEM; + + regmap = device_node_to_regmap(node); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %pOF: %pe\n", node, regmap); + return PTR_ERR(regmap); + } + + for (i = 0; i < num; i++) { + const struct mtk_gate *gate = &clks[i]; + + if (!IS_ERR_OR_NULL(clk_data->clks[gate->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, gate->id); + continue; + } + + clk = mtk_clk_register_gate(gate->name, gate->parent_name, + regmap, + gate->regs->set_ofs, + gate->regs->clr_ofs, + gate->regs->sta_ofs, + gate->shift, gate->ops, + gate->flags, dev); + + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %pe\n", gate->name, clk); + goto err; + } + + clk_data->clks[gate->id] = clk; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_gate *gate = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->clks[gate->id])) + continue; + + mtk_clk_unregister_gate(clk_data->clks[gate->id]); + clk_data->clks[gate->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(clk); +} + +int mtk_clk_register_gates(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data) +{ + return mtk_clk_register_gates_with_dev(node, clks, num, clk_data, NULL); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_gates); + +void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_gate *gate = &clks[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->clks[gate->id])) + continue; + + mtk_clk_unregister_gate(clk_data->clks[gate->id]); + clk_data->clks[gate->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_gates); MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h index 3c3329ec54b7..6b5738826a22 100644 --- a/drivers/clk/mediatek/clk-gate.h +++ b/drivers/clk/mediatek/clk-gate.h @@ -7,41 +7,34 @@ #ifndef __DRV_CLK_GATE_H #define __DRV_CLK_GATE_H -#include <linux/regmap.h> -#include <linux/clk-provider.h> +#include <linux/types.h> struct clk; - -struct mtk_clk_gate { - struct clk_hw hw; - struct regmap *regmap; - int set_ofs; - int clr_ofs; - int sta_ofs; - u8 bit; -}; - -static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw) -{ - return container_of(hw, struct mtk_clk_gate, hw); -} +struct clk_onecell_data; +struct clk_ops; +struct device; +struct device_node; extern const struct clk_ops mtk_clk_gate_ops_setclr; extern const struct clk_ops mtk_clk_gate_ops_setclr_inv; extern const struct clk_ops mtk_clk_gate_ops_no_setclr; extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv; -struct clk *mtk_clk_register_gate( - const char *name, - const char *parent_name, - struct regmap *regmap, - int set_ofs, - int clr_ofs, - int sta_ofs, - u8 bit, - const struct clk_ops *ops, - unsigned long flags, - struct device *dev); +struct mtk_gate_regs { + u32 sta_ofs; + u32 clr_ofs; + u32 set_ofs; +}; + +struct mtk_gate { + int id; + const char *name; + const char *parent_name; + const struct mtk_gate_regs *regs; + int shift; + const struct clk_ops *ops; + unsigned long flags; +}; #define GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, \ _ops, _flags) { \ @@ -57,4 +50,16 @@ struct clk *mtk_clk_register_gate( #define GATE_MTK(_id, _name, _parent, _regs, _shift, _ops) \ GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, _ops, 0) +int mtk_clk_register_gates(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data); + +int mtk_clk_register_gates_with_dev(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data, + struct device *dev); + +void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, + struct clk_onecell_data *clk_data); + #endif /* __DRV_CLK_GATE_H */ diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index 695be0f77427..1eb3e4563c3f 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -10,9 +10,10 @@ #include <linux/of_device.h> #include <linux/platform_device.h> -#include "clk-mtk.h" -#include "clk-gate.h" #include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt2701-clk.h> diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c index a3bd9a107209..ff72b9ab945b 100644 --- a/drivers/clk/mediatek/clk-mt2712.c +++ b/drivers/clk/mediatek/clk-mt2712.c @@ -13,8 +13,9 @@ #include <linux/platform_device.h> #include <linux/slab.h> -#include "clk-mtk.h" #include "clk-gate.h" +#include "clk-pll.h" +#include "clk-mtk.h" #include <dt-bindings/clock/mt2712-clk.h> diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c index d77ea5aff292..24829ca3bd1f 100644 --- a/drivers/clk/mediatek/clk-mt6765.c +++ b/drivers/clk/mediatek/clk-mt6765.c @@ -12,9 +12,10 @@ #include <linux/of_device.h> #include <linux/platform_device.h> -#include "clk-mtk.h" #include "clk-gate.h" +#include "clk-mtk.h" #include "clk-mux.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt6765-clk.h> diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c index 9825385c9f94..7b61664da18f 100644 --- a/drivers/clk/mediatek/clk-mt6779.c +++ b/drivers/clk/mediatek/clk-mt6779.c @@ -10,9 +10,10 @@ #include <linux/of_device.h> #include <linux/platform_device.h> +#include "clk-gate.h" #include "clk-mtk.h" #include "clk-mux.h" -#include "clk-gate.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt6779-clk.h> diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c index 428eb24ffec5..02259e81625a 100644 --- a/drivers/clk/mediatek/clk-mt6797.c +++ b/drivers/clk/mediatek/clk-mt6797.c @@ -9,8 +9,9 @@ #include <linux/of_device.h> #include <linux/platform_device.h> -#include "clk-mtk.h" #include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt6797-clk.h> diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c index ef5947e15c75..0e1fb30a1e98 100644 --- a/drivers/clk/mediatek/clk-mt7622.c +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -11,9 +11,10 @@ #include <linux/of_device.h> #include <linux/platform_device.h> -#include "clk-mtk.h" -#include "clk-gate.h" #include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt7622-clk.h> #include <linux/clk.h> /* for consumer */ diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index a0ee079670c7..c0e023bf31eb 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -12,9 +12,10 @@ #include <linux/of_device.h> #include <linux/platform_device.h> -#include "clk-mtk.h" -#include "clk-gate.h" #include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt7629-clk.h> diff --git a/drivers/clk/mediatek/clk-mt7986-apmixed.c b/drivers/clk/mediatek/clk-mt7986-apmixed.c index 98ec3887585f..21d4c82e782a 100644 --- a/drivers/clk/mediatek/clk-mt7986-apmixed.c +++ b/drivers/clk/mediatek/clk-mt7986-apmixed.c @@ -10,9 +10,11 @@ #include <linux/of_address.h> #include <linux/of_device.h> #include <linux/platform_device.h> -#include "clk-mtk.h" + #include "clk-gate.h" +#include "clk-mtk.h" #include "clk-mux.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt7986-clk.h> #include <linux/clk.h> diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c index 9b4b645aea99..09ad272d51f1 100644 --- a/drivers/clk/mediatek/clk-mt8135.c +++ b/drivers/clk/mediatek/clk-mt8135.c @@ -11,8 +11,9 @@ #include <linux/mfd/syscon.h> #include <dt-bindings/clock/mt8135-clk.h> -#include "clk-mtk.h" #include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" static DEFINE_SPINLOCK(mt8135_clk_lock); diff --git a/drivers/clk/mediatek/clk-mt8167.c b/drivers/clk/mediatek/clk-mt8167.c index e5ea10e31799..812b33a57530 100644 --- a/drivers/clk/mediatek/clk-mt8167.c +++ b/drivers/clk/mediatek/clk-mt8167.c @@ -12,8 +12,9 @@ #include <linux/slab.h> #include <linux/mfd/syscon.h> -#include "clk-mtk.h" #include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt8167-clk.h> diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 8f898ac476c0..46b7655feeaa 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -8,9 +8,10 @@ #include <linux/of.h> #include <linux/of_address.h> -#include "clk-mtk.h" -#include "clk-gate.h" #include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt8173-clk.h> diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c index 5046852eb0fd..68496554dd3d 100644 --- a/drivers/clk/mediatek/clk-mt8183.c +++ b/drivers/clk/mediatek/clk-mt8183.c @@ -11,9 +11,10 @@ #include <linux/platform_device.h> #include <linux/slab.h> +#include "clk-gate.h" #include "clk-mtk.h" #include "clk-mux.h" -#include "clk-gate.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt8183-clk.h> diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c index cbc7c6dbe0f4..ab27cd66b866 100644 --- a/drivers/clk/mediatek/clk-mt8192.c +++ b/drivers/clk/mediatek/clk-mt8192.c @@ -12,9 +12,10 @@ #include <linux/platform_device.h> #include <linux/slab.h> +#include "clk-gate.h" #include "clk-mtk.h" #include "clk-mux.h" -#include "clk-gate.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt8192-clk.h> @@ -1236,9 +1237,17 @@ static int clk_mt8192_infra_probe(struct platform_device *pdev) r = mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); if (r) - return r; + goto free_clk_data; + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + goto free_clk_data; - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + return r; + +free_clk_data: + mtk_free_clk_data(clk_data); + return r; } static int clk_mt8192_peri_probe(struct platform_device *pdev) @@ -1253,9 +1262,17 @@ static int clk_mt8192_peri_probe(struct platform_device *pdev) r = mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), clk_data); if (r) - return r; + goto free_clk_data; + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + goto free_clk_data; + + return r; - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + return r; } static int clk_mt8192_apmixed_probe(struct platform_device *pdev) @@ -1271,9 +1288,17 @@ static int clk_mt8192_apmixed_probe(struct platform_device *pdev) mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); r = mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); if (r) - return r; + goto free_clk_data; - return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + goto free_clk_data; + + return r; + +free_clk_data: + mtk_free_clk_data(clk_data); + return r; } static const struct of_device_id of_match_clk_mt8192[] = { diff --git a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c index 6156ceeed71e..eecc7035a56a 100644 --- a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c +++ b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c @@ -5,6 +5,7 @@ #include "clk-gate.h" #include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt8195-clk.h> #include <linux/of_device.h> @@ -119,24 +120,47 @@ static int clk_mt8195_apmixed_probe(struct platform_device *pdev) if (!clk_data) return -ENOMEM; - mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); - r = mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); + r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); if (r) goto free_apmixed_data; + r = mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); + if (r) + goto unregister_plls; + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) - goto free_apmixed_data; + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); return r; +unregister_gates: + mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); +unregister_plls: + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); free_apmixed_data: mtk_free_clk_data(clk_data); return r; } +static int clk_mt8195_apmixed_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + static struct platform_driver clk_mt8195_apmixed_drv = { .probe = clk_mt8195_apmixed_probe, + .remove = clk_mt8195_apmixed_remove, .driver = { .name = "clk-mt8195-apmixed", .of_match_table = of_match_clk_mt8195_apmixed, diff --git a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c index f1c84186346e..8cd88dfc3283 100644 --- a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c +++ b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c @@ -4,6 +4,7 @@ // Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> #include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt8195-clk.h> #include <linux/clk-provider.h> @@ -65,18 +66,37 @@ static int clk_mt8195_apusys_pll_probe(struct platform_device *pdev) if (!clk_data) return -ENOMEM; - mtk_clk_register_plls(node, apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + r = mtk_clk_register_plls(node, apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); if (r) goto free_apusys_pll_data; + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + goto unregister_plls; + + platform_set_drvdata(pdev, clk_data); + return r; +unregister_plls: + mtk_clk_unregister_plls(apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); free_apusys_pll_data: mtk_free_clk_data(clk_data); return r; } +static int clk_mt8195_apusys_pll_remove(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_plls(apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + static const struct of_device_id of_match_clk_mt8195_apusys_pll[] = { { .compatible = "mediatek,mt8195-apusys_pll", }, {} @@ -84,6 +104,7 @@ static const struct of_device_id of_match_clk_mt8195_apusys_pll[] = { static struct platform_driver clk_mt8195_apusys_pll_drv = { .probe = clk_mt8195_apusys_pll_probe, + .remove = clk_mt8195_apusys_pll_remove, .driver = { .name = "clk-mt8195-apusys_pll", .of_match_table = of_match_clk_mt8195_apusys_pll, diff --git a/drivers/clk/mediatek/clk-mt8195-cam.c b/drivers/clk/mediatek/clk-mt8195-cam.c index 3d261fc3848e..e4d00fe6e757 100644 --- a/drivers/clk/mediatek/clk-mt8195-cam.c +++ b/drivers/clk/mediatek/clk-mt8195-cam.c @@ -134,6 +134,7 @@ static const struct of_device_id of_match_clk_mt8195_cam[] = { static struct platform_driver clk_mt8195_cam_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-cam", .of_match_table = of_match_clk_mt8195_cam, diff --git a/drivers/clk/mediatek/clk-mt8195-ccu.c b/drivers/clk/mediatek/clk-mt8195-ccu.c index f846f1d73605..4e326b6301ba 100644 --- a/drivers/clk/mediatek/clk-mt8195-ccu.c +++ b/drivers/clk/mediatek/clk-mt8195-ccu.c @@ -42,6 +42,7 @@ static const struct of_device_id of_match_clk_mt8195_ccu[] = { static struct platform_driver clk_mt8195_ccu_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-ccu", .of_match_table = of_match_clk_mt8195_ccu, diff --git a/drivers/clk/mediatek/clk-mt8195-img.c b/drivers/clk/mediatek/clk-mt8195-img.c index 22b52a8f15fe..12f5c436d075 100644 --- a/drivers/clk/mediatek/clk-mt8195-img.c +++ b/drivers/clk/mediatek/clk-mt8195-img.c @@ -88,6 +88,7 @@ static const struct of_device_id of_match_clk_mt8195_img[] = { static struct platform_driver clk_mt8195_img_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-img", .of_match_table = of_match_clk_mt8195_img, diff --git a/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c index 4ab312eb26a5..fbc809d05072 100644 --- a/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c +++ b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c @@ -58,6 +58,7 @@ static const struct of_device_id of_match_clk_mt8195_imp_iic_wrap[] = { static struct platform_driver clk_mt8195_imp_iic_wrap_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-imp_iic_wrap", .of_match_table = of_match_clk_mt8195_imp_iic_wrap, diff --git a/drivers/clk/mediatek/clk-mt8195-infra_ao.c b/drivers/clk/mediatek/clk-mt8195-infra_ao.c index 5f9b69967459..8ebe3b9415c4 100644 --- a/drivers/clk/mediatek/clk-mt8195-infra_ao.c +++ b/drivers/clk/mediatek/clk-mt8195-infra_ao.c @@ -198,6 +198,7 @@ static const struct of_device_id of_match_clk_mt8195_infra_ao[] = { static struct platform_driver clk_mt8195_infra_ao_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-infra_ao", .of_match_table = of_match_clk_mt8195_infra_ao, diff --git a/drivers/clk/mediatek/clk-mt8195-ipe.c b/drivers/clk/mediatek/clk-mt8195-ipe.c index fc1d42b6ac84..b0d745cf7752 100644 --- a/drivers/clk/mediatek/clk-mt8195-ipe.c +++ b/drivers/clk/mediatek/clk-mt8195-ipe.c @@ -43,6 +43,7 @@ static const struct of_device_id of_match_clk_mt8195_ipe[] = { static struct platform_driver clk_mt8195_ipe_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-ipe", .of_match_table = of_match_clk_mt8195_ipe, diff --git a/drivers/clk/mediatek/clk-mt8195-mfg.c b/drivers/clk/mediatek/clk-mt8195-mfg.c index aca6d9c0837c..9411c556a5a9 100644 --- a/drivers/clk/mediatek/clk-mt8195-mfg.c +++ b/drivers/clk/mediatek/clk-mt8195-mfg.c @@ -39,6 +39,7 @@ static const struct of_device_id of_match_clk_mt8195_mfg[] = { static struct platform_driver clk_mt8195_mfg_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-mfg", .of_match_table = of_match_clk_mt8195_mfg, diff --git a/drivers/clk/mediatek/clk-mt8195-peri_ao.c b/drivers/clk/mediatek/clk-mt8195-peri_ao.c index 907a92b22de8..2f6b3bb657db 100644 --- a/drivers/clk/mediatek/clk-mt8195-peri_ao.c +++ b/drivers/clk/mediatek/clk-mt8195-peri_ao.c @@ -54,6 +54,7 @@ static const struct of_device_id of_match_clk_mt8195_peri_ao[] = { static struct platform_driver clk_mt8195_peri_ao_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-peri_ao", .of_match_table = of_match_clk_mt8195_peri_ao, diff --git a/drivers/clk/mediatek/clk-mt8195-scp_adsp.c b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c index 26b4846c5894..e16c383f631b 100644 --- a/drivers/clk/mediatek/clk-mt8195-scp_adsp.c +++ b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c @@ -39,6 +39,7 @@ static const struct of_device_id of_match_clk_mt8195_scp_adsp[] = { static struct platform_driver clk_mt8195_scp_adsp_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-scp_adsp", .of_match_table = of_match_clk_mt8195_scp_adsp, diff --git a/drivers/clk/mediatek/clk-mt8195-topckgen.c b/drivers/clk/mediatek/clk-mt8195-topckgen.c index 3e2aba9c40bb..b602fcd7f1d1 100644 --- a/drivers/clk/mediatek/clk-mt8195-topckgen.c +++ b/drivers/clk/mediatek/clk-mt8195-topckgen.c @@ -1239,32 +1239,79 @@ static int clk_mt8195_topck_probe(struct platform_device *pdev) goto free_top_data; } - mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), - top_clk_data); - mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); - mtk_clk_register_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), node, - &mt8195_clk_lock, top_clk_data); - mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, - &mt8195_clk_lock, top_clk_data); - mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, - &mt8195_clk_lock, top_clk_data); - r = mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), top_clk_data); + r = mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + top_clk_data); if (r) goto free_top_data; + r = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + if (r) + goto unregister_fixed_clks; + + r = mtk_clk_register_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), node, + &mt8195_clk_lock, top_clk_data); + if (r) + goto unregister_factors; + + r = mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8195_clk_lock, top_clk_data); + if (r) + goto unregister_muxes; + + r = mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt8195_clk_lock, top_clk_data); + if (r) + goto unregister_composite_muxes; + + r = mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), top_clk_data); + if (r) + goto unregister_composite_divs; + r = of_clk_add_provider(node, of_clk_src_onecell_get, top_clk_data); if (r) - goto free_top_data; + goto unregister_gates; + + platform_set_drvdata(pdev, top_clk_data); return r; +unregister_gates: + mtk_clk_unregister_gates(top_clks, ARRAY_SIZE(top_clks), top_clk_data); +unregister_composite_divs: + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), top_clk_data); +unregister_composite_muxes: + mtk_clk_unregister_composites(top_muxes, ARRAY_SIZE(top_muxes), top_clk_data); +unregister_muxes: + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), top_clk_data); +unregister_factors: + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); +unregister_fixed_clks: + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data); free_top_data: mtk_free_clk_data(top_clk_data); return r; } +static int clk_mt8195_topck_remove(struct platform_device *pdev) +{ + struct clk_onecell_data *top_clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_gates(top_clks, ARRAY_SIZE(top_clks), top_clk_data); + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), top_clk_data); + mtk_clk_unregister_composites(top_muxes, ARRAY_SIZE(top_muxes), top_clk_data); + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), top_clk_data); + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data); + mtk_free_clk_data(top_clk_data); + + return 0; +} + static struct platform_driver clk_mt8195_topck_drv = { .probe = clk_mt8195_topck_probe, + .remove = clk_mt8195_topck_remove, .driver = { .name = "clk-mt8195-topck", .of_match_table = of_match_clk_mt8195_topck, diff --git a/drivers/clk/mediatek/clk-mt8195-vdec.c b/drivers/clk/mediatek/clk-mt8195-vdec.c index a1df04f42a90..a1446b666385 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdec.c +++ b/drivers/clk/mediatek/clk-mt8195-vdec.c @@ -96,6 +96,7 @@ static const struct of_device_id of_match_clk_mt8195_vdec[] = { static struct platform_driver clk_mt8195_vdec_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-vdec", .of_match_table = of_match_clk_mt8195_vdec, diff --git a/drivers/clk/mediatek/clk-mt8195-vdo0.c b/drivers/clk/mediatek/clk-mt8195-vdo0.c index f7ff7618c714..3bc7ed19d550 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdo0.c +++ b/drivers/clk/mediatek/clk-mt8195-vdo0.c @@ -105,17 +105,35 @@ static int clk_mt8195_vdo0_probe(struct platform_device *pdev) r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) - goto free_vdo0_data; + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); return r; +unregister_gates: + mtk_clk_unregister_gates(vdo0_clks, ARRAY_SIZE(vdo0_clks), clk_data); free_vdo0_data: mtk_free_clk_data(clk_data); return r; } +static int clk_mt8195_vdo0_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(vdo0_clks, ARRAY_SIZE(vdo0_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + static struct platform_driver clk_mt8195_vdo0_drv = { .probe = clk_mt8195_vdo0_probe, + .remove = clk_mt8195_vdo0_remove, .driver = { .name = "clk-mt8195-vdo0", }, diff --git a/drivers/clk/mediatek/clk-mt8195-vdo1.c b/drivers/clk/mediatek/clk-mt8195-vdo1.c index 03df8eae8838..90c738a85ff1 100644 --- a/drivers/clk/mediatek/clk-mt8195-vdo1.c +++ b/drivers/clk/mediatek/clk-mt8195-vdo1.c @@ -122,17 +122,35 @@ static int clk_mt8195_vdo1_probe(struct platform_device *pdev) r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) - goto free_vdo1_data; + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); return r; +unregister_gates: + mtk_clk_unregister_gates(vdo1_clks, ARRAY_SIZE(vdo1_clks), clk_data); free_vdo1_data: mtk_free_clk_data(clk_data); return r; } +static int clk_mt8195_vdo1_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(vdo1_clks, ARRAY_SIZE(vdo1_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + static struct platform_driver clk_mt8195_vdo1_drv = { .probe = clk_mt8195_vdo1_probe, + .remove = clk_mt8195_vdo1_remove, .driver = { .name = "clk-mt8195-vdo1", }, diff --git a/drivers/clk/mediatek/clk-mt8195-venc.c b/drivers/clk/mediatek/clk-mt8195-venc.c index 7339851a0856..622f57804f96 100644 --- a/drivers/clk/mediatek/clk-mt8195-venc.c +++ b/drivers/clk/mediatek/clk-mt8195-venc.c @@ -61,6 +61,7 @@ static const struct of_device_id of_match_clk_mt8195_venc[] = { static struct platform_driver clk_mt8195_venc_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-venc", .of_match_table = of_match_clk_mt8195_venc, diff --git a/drivers/clk/mediatek/clk-mt8195-vpp0.c b/drivers/clk/mediatek/clk-mt8195-vpp0.c index c3241466a8d0..bf2939c3a023 100644 --- a/drivers/clk/mediatek/clk-mt8195-vpp0.c +++ b/drivers/clk/mediatek/clk-mt8195-vpp0.c @@ -102,6 +102,7 @@ static const struct of_device_id of_match_clk_mt8195_vpp0[] = { static struct platform_driver clk_mt8195_vpp0_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-vpp0", .of_match_table = of_match_clk_mt8195_vpp0, diff --git a/drivers/clk/mediatek/clk-mt8195-vpp1.c b/drivers/clk/mediatek/clk-mt8195-vpp1.c index ce0b9a40a179..ffd52c762890 100644 --- a/drivers/clk/mediatek/clk-mt8195-vpp1.c +++ b/drivers/clk/mediatek/clk-mt8195-vpp1.c @@ -100,6 +100,7 @@ static const struct of_device_id of_match_clk_mt8195_vpp1[] = { static struct platform_driver clk_mt8195_vpp1_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-vpp1", .of_match_table = of_match_clk_mt8195_vpp1, diff --git a/drivers/clk/mediatek/clk-mt8195-wpe.c b/drivers/clk/mediatek/clk-mt8195-wpe.c index 274d60838d8e..b483fab10e18 100644 --- a/drivers/clk/mediatek/clk-mt8195-wpe.c +++ b/drivers/clk/mediatek/clk-mt8195-wpe.c @@ -135,6 +135,7 @@ static const struct of_device_id of_match_clk_mt8195_wpe[] = { static struct platform_driver clk_mt8195_wpe_drv = { .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, .driver = { .name = "clk-mt8195-wpe", .of_match_table = of_match_clk_mt8195_wpe, diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c index 9d4261ecc760..a37143f920ce 100644 --- a/drivers/clk/mediatek/clk-mt8516.c +++ b/drivers/clk/mediatek/clk-mt8516.c @@ -11,8 +11,9 @@ #include <linux/slab.h> #include <linux/mfd/syscon.h> -#include "clk-mtk.h" #include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" #include <dt-bindings/clock/mt8516-clk.h> diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 8d5791b3f460..b4063261cf56 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -4,17 +4,16 @@ * Author: James Liao <jamesjj.liao@mediatek.com> */ -#include <linux/of.h> -#include <linux/of_address.h> +#include <linux/bitops.h> +#include <linux/clk-provider.h> #include <linux/err.h> #include <linux/io.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/clkdev.h> -#include <linux/module.h> #include <linux/mfd/syscon.h> -#include <linux/device.h> +#include <linux/module.h> +#include <linux/of.h> #include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> #include "clk-mtk.h" #include "clk-gate.h" @@ -54,112 +53,135 @@ void mtk_free_clk_data(struct clk_onecell_data *clk_data) kfree(clk_data); } -void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, - int num, struct clk_onecell_data *clk_data) +int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_onecell_data *clk_data) { int i; struct clk *clk; + if (!clk_data) + return -ENOMEM; + for (i = 0; i < num; i++) { const struct mtk_fixed_clk *rc = &clks[i]; - if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id])) + if (!IS_ERR_OR_NULL(clk_data->clks[rc->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", rc->id); continue; + } clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0, rc->rate); if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - rc->name, PTR_ERR(clk)); - continue; + pr_err("Failed to register clk %s: %pe\n", rc->name, clk); + goto err; } - if (clk_data) - clk_data->clks[rc->id] = clk; + clk_data->clks[rc->id] = clk; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_fixed_clk *rc = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->clks[rc->id])) + continue; + + clk_unregister_fixed_rate(clk_data->clks[rc->id]); + clk_data->clks[rc->id] = ERR_PTR(-ENOENT); } + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(mtk_clk_register_fixed_clks); -void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, - int num, struct clk_onecell_data *clk_data) +void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_onecell_data *clk_data) { int i; - struct clk *clk; - for (i = 0; i < num; i++) { - const struct mtk_fixed_factor *ff = &clks[i]; - - if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id])) - continue; + if (!clk_data) + return; - clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name, - CLK_SET_RATE_PARENT, ff->mult, ff->div); + for (i = num; i > 0; i--) { + const struct mtk_fixed_clk *rc = &clks[i - 1]; - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - ff->name, PTR_ERR(clk)); + if (IS_ERR_OR_NULL(clk_data->clks[rc->id])) continue; - } - if (clk_data) - clk_data->clks[ff->id] = clk; + clk_unregister_fixed_rate(clk_data->clks[rc->id]); + clk_data->clks[rc->id] = ERR_PTR(-ENOENT); } } -EXPORT_SYMBOL_GPL(mtk_clk_register_factors); +EXPORT_SYMBOL_GPL(mtk_clk_unregister_fixed_clks); -int mtk_clk_register_gates_with_dev(struct device_node *node, - const struct mtk_gate *clks, - int num, struct clk_onecell_data *clk_data, - struct device *dev) +int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data) { int i; struct clk *clk; - struct regmap *regmap; if (!clk_data) return -ENOMEM; - regmap = device_node_to_regmap(node); - if (IS_ERR(regmap)) { - pr_err("Cannot find regmap for %pOF: %ld\n", node, - PTR_ERR(regmap)); - return PTR_ERR(regmap); - } - for (i = 0; i < num; i++) { - const struct mtk_gate *gate = &clks[i]; + const struct mtk_fixed_factor *ff = &clks[i]; - if (!IS_ERR_OR_NULL(clk_data->clks[gate->id])) + if (!IS_ERR_OR_NULL(clk_data->clks[ff->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", ff->id); continue; + } - clk = mtk_clk_register_gate(gate->name, gate->parent_name, - regmap, - gate->regs->set_ofs, - gate->regs->clr_ofs, - gate->regs->sta_ofs, - gate->shift, gate->ops, gate->flags, dev); + clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name, + CLK_SET_RATE_PARENT, ff->mult, ff->div); if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - gate->name, PTR_ERR(clk)); - continue; + pr_err("Failed to register clk %s: %pe\n", ff->name, clk); + goto err; } - clk_data->clks[gate->id] = clk; + clk_data->clks[ff->id] = clk; } return 0; + +err: + while (--i >= 0) { + const struct mtk_fixed_factor *ff = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->clks[ff->id])) + continue; + + clk_unregister_fixed_factor(clk_data->clks[ff->id]); + clk_data->clks[ff->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(clk); } +EXPORT_SYMBOL_GPL(mtk_clk_register_factors); -int mtk_clk_register_gates(struct device_node *node, - const struct mtk_gate *clks, - int num, struct clk_onecell_data *clk_data) +void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data) { - return mtk_clk_register_gates_with_dev(node, - clks, num, clk_data, NULL); + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_fixed_factor *ff = &clks[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->clks[ff->id])) + continue; + + clk_unregister_fixed_factor(clk_data->clks[ff->id]); + clk_data->clks[ff->id] = ERR_PTR(-ENOENT); + } } -EXPORT_SYMBOL_GPL(mtk_clk_register_gates); +EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors); struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock) @@ -248,58 +270,161 @@ err_out: return ERR_PTR(ret); } -void mtk_clk_register_composites(const struct mtk_composite *mcs, - int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data) +static void mtk_clk_unregister_composite(struct clk *clk) +{ + struct clk_hw *hw; + struct clk_composite *composite; + struct clk_mux *mux = NULL; + struct clk_gate *gate = NULL; + struct clk_divider *div = NULL; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + composite = to_clk_composite(hw); + if (composite->mux_hw) + mux = to_clk_mux(composite->mux_hw); + if (composite->gate_hw) + gate = to_clk_gate(composite->gate_hw); + if (composite->rate_hw) + div = to_clk_divider(composite->rate_hw); + + clk_unregister_composite(clk); + kfree(div); + kfree(gate); + kfree(mux); +} + +int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, + void __iomem *base, spinlock_t *lock, + struct clk_onecell_data *clk_data) { struct clk *clk; int i; + if (!clk_data) + return -ENOMEM; + for (i = 0; i < num; i++) { const struct mtk_composite *mc = &mcs[i]; - if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id])) + if (!IS_ERR_OR_NULL(clk_data->clks[mc->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", + mc->id); continue; + } clk = mtk_clk_register_composite(mc, base, lock); if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - mc->name, PTR_ERR(clk)); - continue; + pr_err("Failed to register clk %s: %pe\n", mc->name, clk); + goto err; } - if (clk_data) - clk_data->clks[mc->id] = clk; + clk_data->clks[mc->id] = clk; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_composite *mc = &mcs[i]; + + if (IS_ERR_OR_NULL(clk_data->clks[mcs->id])) + continue; + + mtk_clk_unregister_composite(clk_data->clks[mc->id]); + clk_data->clks[mc->id] = ERR_PTR(-ENOENT); } + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(mtk_clk_register_composites); -void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, - int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data) +void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, + struct clk_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_composite *mc = &mcs[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->clks[mc->id])) + continue; + + mtk_clk_unregister_composite(clk_data->clks[mc->id]); + clk_data->clks[mc->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_composites); + +int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, + void __iomem *base, spinlock_t *lock, + struct clk_onecell_data *clk_data) { struct clk *clk; int i; + if (!clk_data) + return -ENOMEM; + for (i = 0; i < num; i++) { const struct mtk_clk_divider *mcd = &mcds[i]; - if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id])) + if (!IS_ERR_OR_NULL(clk_data->clks[mcd->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", + mcd->id); continue; + } clk = clk_register_divider(NULL, mcd->name, mcd->parent_name, mcd->flags, base + mcd->div_reg, mcd->div_shift, mcd->div_width, mcd->clk_divider_flags, lock); if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - mcd->name, PTR_ERR(clk)); - continue; + pr_err("Failed to register clk %s: %pe\n", mcd->name, clk); + goto err; } - if (clk_data) - clk_data->clks[mcd->id] = clk; + clk_data->clks[mcd->id] = clk; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_clk_divider *mcd = &mcds[i]; + + if (IS_ERR_OR_NULL(clk_data->clks[mcd->id])) + continue; + + mtk_clk_unregister_composite(clk_data->clks[mcd->id]); + clk_data->clks[mcd->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(clk); +} + +void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, + struct clk_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_clk_divider *mcd = &mcds[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->clks[mcd->id])) + continue; + + clk_unregister_divider(clk_data->clks[mcd->id]); + clk_data->clks[mcd->id] = ERR_PTR(-ENOENT); } } @@ -324,13 +449,30 @@ int mtk_clk_simple_probe(struct platform_device *pdev) r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) - goto free_data; + goto unregister_clks; + + platform_set_drvdata(pdev, clk_data); return r; +unregister_clks: + mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); free_data: mtk_free_clk_data(clk_data); return r; } +int mtk_clk_simple_remove(struct platform_device *pdev) +{ + const struct mtk_clk_desc *mcd = of_device_get_match_data(&pdev->dev); + struct clk_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 0ff289d93452..bf6565aa7319 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -7,19 +7,19 @@ #ifndef __DRV_CLK_MTK_H #define __DRV_CLK_MTK_H -#include <linux/regmap.h> -#include <linux/bitops.h> #include <linux/clk-provider.h> -#include <linux/platform_device.h> - -struct clk; -struct clk_onecell_data; +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/types.h> #define MAX_MUX_GATE_BIT 31 #define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) #define MHZ (1000 * 1000) +struct platform_device; + struct mtk_fixed_clk { int id; const char *name; @@ -34,8 +34,10 @@ struct mtk_fixed_clk { .rate = _rate, \ } -void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, - int num, struct clk_onecell_data *clk_data); +int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_onecell_data *clk_data); +void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_onecell_data *clk_data); struct mtk_fixed_factor { int id; @@ -53,8 +55,10 @@ struct mtk_fixed_factor { .div = _div, \ } -void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, - int num, struct clk_onecell_data *clk_data); +int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data); +void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_onecell_data *clk_data); struct mtk_composite { int id; @@ -146,34 +150,11 @@ struct mtk_composite { struct clk *mtk_clk_register_composite(const struct mtk_composite *mc, void __iomem *base, spinlock_t *lock); -void mtk_clk_register_composites(const struct mtk_composite *mcs, - int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data); - -struct mtk_gate_regs { - u32 sta_ofs; - u32 clr_ofs; - u32 set_ofs; -}; - -struct mtk_gate { - int id; - const char *name; - const char *parent_name; - const struct mtk_gate_regs *regs; - int shift; - const struct clk_ops *ops; - unsigned long flags; -}; - -int mtk_clk_register_gates(struct device_node *node, - const struct mtk_gate *clks, int num, - struct clk_onecell_data *clk_data); - -int mtk_clk_register_gates_with_dev(struct device_node *node, - const struct mtk_gate *clks, - int num, struct clk_onecell_data *clk_data, - struct device *dev); +int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, + void __iomem *base, spinlock_t *lock, + struct clk_onecell_data *clk_data); +void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, + struct clk_onecell_data *clk_data); struct mtk_clk_divider { int id; @@ -197,52 +178,15 @@ struct mtk_clk_divider { .div_width = _width, \ } -void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, - int num, void __iomem *base, spinlock_t *lock, - struct clk_onecell_data *clk_data); +int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, + void __iomem *base, spinlock_t *lock, + struct clk_onecell_data *clk_data); +void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, + struct clk_onecell_data *clk_data); struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); void mtk_free_clk_data(struct clk_onecell_data *clk_data); -#define HAVE_RST_BAR BIT(0) -#define PLL_AO BIT(1) - -struct mtk_pll_div_table { - u32 div; - unsigned long freq; -}; - -struct mtk_pll_data { - int id; - const char *name; - u32 reg; - u32 pwr_reg; - u32 en_mask; - u32 pd_reg; - u32 tuner_reg; - u32 tuner_en_reg; - u8 tuner_en_bit; - int pd_shift; - unsigned int flags; - const struct clk_ops *ops; - u32 rst_bar_mask; - unsigned long fmin; - unsigned long fmax; - int pcwbits; - int pcwibits; - u32 pcw_reg; - int pcw_shift; - u32 pcw_chg_reg; - const struct mtk_pll_div_table *div_table; - const char *parent_name; - u32 en_reg; - u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ -}; - -void mtk_clk_register_plls(struct device_node *node, - const struct mtk_pll_data *plls, int num_plls, - struct clk_onecell_data *clk_data); - struct clk *mtk_clk_register_ref2usb_tx(const char *name, const char *parent_name, void __iomem *reg); @@ -258,5 +202,6 @@ struct mtk_clk_desc { }; int mtk_clk_simple_probe(struct platform_device *pdev); +int mtk_clk_simple_remove(struct platform_device *pdev); #endif /* __DRV_CLK_MTK_H */ diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c index 6d3a50eb7d6f..21ad5a4afd65 100644 --- a/drivers/clk/mediatek/clk-mux.c +++ b/drivers/clk/mediatek/clk-mux.c @@ -4,15 +4,26 @@ * Author: Owen Chen <owen.chen@mediatek.com> */ -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/slab.h> +#include <linux/clk-provider.h> +#include <linux/compiler_types.h> +#include <linux/container_of.h> +#include <linux/err.h> #include <linux/mfd/syscon.h> #include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spinlock.h> +#include <linux/slab.h> -#include "clk-mtk.h" #include "clk-mux.h" +struct mtk_clk_mux { + struct clk_hw hw; + struct regmap *regmap; + const struct mtk_mux *data; + spinlock_t *lock; + bool reparent; +}; + static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw) { return container_of(hw, struct mtk_clk_mux, hw); @@ -164,6 +175,21 @@ static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux, return clk; } +static void mtk_clk_unregister_mux(struct clk *clk) +{ + struct mtk_clk_mux *mux; + struct clk_hw *hw; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + mux = to_mtk_clk_mux(hw); + + clk_unregister(clk); + kfree(mux); +} + int mtk_clk_register_muxes(const struct mtk_mux *muxes, int num, struct device_node *node, spinlock_t *lock, @@ -175,29 +201,64 @@ int mtk_clk_register_muxes(const struct mtk_mux *muxes, regmap = device_node_to_regmap(node); if (IS_ERR(regmap)) { - pr_err("Cannot find regmap for %pOF: %ld\n", node, - PTR_ERR(regmap)); + pr_err("Cannot find regmap for %pOF: %pe\n", node, regmap); return PTR_ERR(regmap); } for (i = 0; i < num; i++) { const struct mtk_mux *mux = &muxes[i]; - if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) { - clk = mtk_clk_register_mux(mux, regmap, lock); + if (!IS_ERR_OR_NULL(clk_data->clks[mux->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, mux->id); + continue; + } - if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - mux->name, PTR_ERR(clk)); - continue; - } + clk = mtk_clk_register_mux(mux, regmap, lock); - clk_data->clks[mux->id] = clk; + if (IS_ERR(clk)) { + pr_err("Failed to register clk %s: %pe\n", mux->name, clk); + goto err; } + + clk_data->clks[mux->id] = clk; } return 0; + +err: + while (--i >= 0) { + const struct mtk_mux *mux = &muxes[i]; + + if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + continue; + + mtk_clk_unregister_mux(clk_data->clks[mux->id]); + clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(mtk_clk_register_muxes); +void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, + struct clk_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_mux *mux = &muxes[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) + continue; + + mtk_clk_unregister_mux(clk_data->clks[mux->id]); + clk_data->clks[mux->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes); + MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h index 27841d649118..903a3c937959 100644 --- a/drivers/clk/mediatek/clk-mux.h +++ b/drivers/clk/mediatek/clk-mux.h @@ -7,15 +7,13 @@ #ifndef __DRV_CLK_MTK_MUX_H #define __DRV_CLK_MTK_MUX_H -#include <linux/clk-provider.h> +#include <linux/spinlock.h> +#include <linux/types.h> -struct mtk_clk_mux { - struct clk_hw hw; - struct regmap *regmap; - const struct mtk_mux *data; - spinlock_t *lock; - bool reparent; -}; +struct clk; +struct clk_onecell_data; +struct clk_ops; +struct device_node; struct mtk_mux { int id; @@ -88,4 +86,7 @@ int mtk_clk_register_muxes(const struct mtk_mux *muxes, spinlock_t *lock, struct clk_onecell_data *clk_data); +void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, + struct clk_onecell_data *clk_data); + #endif /* __DRV_CLK_MTK_MUX_H */ diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c index 60d7ffa0b924..ccaa2085ab4d 100644 --- a/drivers/clk/mediatek/clk-pll.c +++ b/drivers/clk/mediatek/clk-pll.c @@ -4,15 +4,18 @@ * Author: James Liao <jamesjj.liao@mediatek.com> */ -#include <linux/of.h> -#include <linux/of_address.h> +#include <linux/clk-provider.h> +#include <linux/container_of.h> +#include <linux/delay.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> +#include <linux/of_address.h> #include <linux/slab.h> -#include <linux/clkdev.h> -#include <linux/delay.h> -#include "clk-mtk.h" +#include "clk-pll.h" + +#define MHZ (1000 * 1000) #define REG_CON0 0 #define REG_CON1 4 @@ -359,8 +362,24 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data, return clk; } -void mtk_clk_register_plls(struct device_node *node, - const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data) +static void mtk_clk_unregister_pll(struct clk *clk) +{ + struct clk_hw *hw; + struct mtk_clk_pll *pll; + + hw = __clk_get_hw(clk); + if (!hw) + return; + + pll = to_mtk_clk_pll(hw); + + clk_unregister(clk); + kfree(pll); +} + +int mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, + struct clk_onecell_data *clk_data) { void __iomem *base; int i; @@ -369,23 +388,82 @@ void mtk_clk_register_plls(struct device_node *node, base = of_iomap(node, 0); if (!base) { pr_err("%s(): ioremap failed\n", __func__); - return; + return -EINVAL; } for (i = 0; i < num_plls; i++) { const struct mtk_pll_data *pll = &plls[i]; + if (!IS_ERR_OR_NULL(clk_data->clks[pll->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, pll->id); + continue; + } + clk = mtk_clk_register_pll(pll, base); if (IS_ERR(clk)) { - pr_err("Failed to register clk %s: %ld\n", - pll->name, PTR_ERR(clk)); - continue; + pr_err("Failed to register clk %s: %pe\n", pll->name, clk); + goto err; } clk_data->clks[pll->id] = clk; } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_pll_data *pll = &plls[i]; + + mtk_clk_unregister_pll(clk_data->clks[pll->id]); + clk_data->clks[pll->id] = ERR_PTR(-ENOENT); + } + + iounmap(base); + + return PTR_ERR(clk); } EXPORT_SYMBOL_GPL(mtk_clk_register_plls); +static __iomem void *mtk_clk_pll_get_base(struct clk *clk, + const struct mtk_pll_data *data) +{ + struct clk_hw *hw = __clk_get_hw(clk); + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + return pll->base_addr - data->reg; +} + +void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, + struct clk_onecell_data *clk_data) +{ + __iomem void *base = NULL; + int i; + + if (!clk_data) + return; + + for (i = num_plls; i > 0; i--) { + const struct mtk_pll_data *pll = &plls[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->clks[pll->id])) + continue; + + /* + * This is quite ugly but unfortunately the clks don't have + * any device tied to them, so there's no place to store the + * pointer to the I/O region base address. We have to fetch + * it from one of the registered clks. + */ + base = mtk_clk_pll_get_base(clk_data->clks[pll->id], pll); + + mtk_clk_unregister_pll(clk_data->clks[pll->id]); + clk_data->clks[pll->id] = ERR_PTR(-ENOENT); + } + + iounmap(base); +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_plls); + MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h new file mode 100644 index 000000000000..bf06e44caef9 --- /dev/null +++ b/drivers/clk/mediatek/clk-pll.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#ifndef __DRV_CLK_MTK_PLL_H +#define __DRV_CLK_MTK_PLL_H + +#include <linux/types.h> + +struct clk_ops; +struct clk_onecell_data; +struct device_node; + +struct mtk_pll_div_table { + u32 div; + unsigned long freq; +}; + +#define HAVE_RST_BAR BIT(0) +#define PLL_AO BIT(1) + +struct mtk_pll_data { + int id; + const char *name; + u32 reg; + u32 pwr_reg; + u32 en_mask; + u32 pd_reg; + u32 tuner_reg; + u32 tuner_en_reg; + u8 tuner_en_bit; + int pd_shift; + unsigned int flags; + const struct clk_ops *ops; + u32 rst_bar_mask; + unsigned long fmin; + unsigned long fmax; + int pcwbits; + int pcwibits; + u32 pcw_reg; + int pcw_shift; + u32 pcw_chg_reg; + const struct mtk_pll_div_table *div_table; + const char *parent_name; + u32 en_reg; + u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ +}; + +int mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, + struct clk_onecell_data *clk_data); +void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, + struct clk_onecell_data *clk_data); + +#endif /* __DRV_CLK_MTK_PLL_H */ diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c index ffe464ce7ff8..bcec4b89f449 100644 --- a/drivers/clk/mediatek/reset.c +++ b/drivers/clk/mediatek/reset.c @@ -100,8 +100,7 @@ static void mtk_register_reset_controller_common(struct device_node *np, regmap = device_node_to_regmap(np); if (IS_ERR(regmap)) { - pr_err("Cannot find regmap for %pOF: %ld\n", np, - PTR_ERR(regmap)); + pr_err("Cannot find regmap for %pOF: %pe\n", np, regmap); return; } diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index cd0f5bae24d4..8f3b7a94a667 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -2232,7 +2232,7 @@ static struct clk_regmap meson8b_vpu_1 = { }; /* - * The VPU clock has two two identical clock trees (vpu_0 and vpu_1) + * The VPU clock has two identical clock trees (vpu_0 and vpu_1) * muxed by a glitch-free switch on Meson8b and Meson8m2. The CCF can * actually manage this glitch-free mux because it does top-to-bottom * updates the each clock tree and switches to the "inactive" one when diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig new file mode 100644 index 000000000000..a5a99873c4f5 --- /dev/null +++ b/drivers/clk/microchip/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +config COMMON_CLK_PIC32 + def_bool COMMON_CLK && MACH_PIC32 + +config MCHP_CLK_MPFS + bool "Clk driver for PolarFire SoC" + depends on (RISCV && SOC_MICROCHIP_POLARFIRE) || COMPILE_TEST + help + Supports Clock Configuration for PolarFire SoC diff --git a/drivers/clk/microchip/Makefile b/drivers/clk/microchip/Makefile index f34b247e870f..5fa6dcf30a9a 100644 --- a/drivers/clk/microchip/Makefile +++ b/drivers/clk/microchip/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_COMMON_CLK_PIC32) += clk-core.o obj-$(CONFIG_PIC32MZDA) += clk-pic32mzda.o +obj-$(CONFIG_MCHP_CLK_MPFS) += clk-mpfs.o diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c new file mode 100644 index 000000000000..aa1561b773d6 --- /dev/null +++ b/drivers/clk/microchip/clk-mpfs.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Daire McNamara,<daire.mcnamara@microchip.com> + * Copyright (C) 2020 Microchip Technology Inc. All rights reserved. + */ +#include <linux/clk-provider.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <dt-bindings/clock/microchip,mpfs-clock.h> + +/* address offset of control registers */ +#define REG_CLOCK_CONFIG_CR 0x08u +#define REG_SUBBLK_CLOCK_CR 0x84u +#define REG_SUBBLK_RESET_CR 0x88u + +struct mpfs_clock_data { + void __iomem *base; + struct clk_hw_onecell_data hw_data; +}; + +struct mpfs_cfg_clock { + const struct clk_div_table *table; + unsigned int id; + u8 shift; + u8 width; +}; + +struct mpfs_cfg_hw_clock { + struct mpfs_cfg_clock cfg; + void __iomem *sys_base; + struct clk_hw hw; + struct clk_init_data init; +}; + +#define to_mpfs_cfg_clk(_hw) container_of(_hw, struct mpfs_cfg_hw_clock, hw) + +struct mpfs_periph_clock { + unsigned int id; + u8 shift; +}; + +struct mpfs_periph_hw_clock { + struct mpfs_periph_clock periph; + void __iomem *sys_base; + struct clk_hw hw; +}; + +#define to_mpfs_periph_clk(_hw) container_of(_hw, struct mpfs_periph_hw_clock, hw) + +/* + * mpfs_clk_lock prevents anything else from writing to the + * mpfs clk block while a software locked register is being written. + */ +static DEFINE_SPINLOCK(mpfs_clk_lock); + +static const struct clk_parent_data mpfs_cfg_parent[] = { + { .index = 0 }, +}; + +static const struct clk_div_table mpfs_div_cpu_axi_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 0, 0 } +}; + +static const struct clk_div_table mpfs_div_ahb_table[] = { + { 1, 2 }, { 2, 4}, { 3, 8 }, + { 0, 0 } +}; + +static unsigned long mpfs_cfg_clk_recalc_rate(struct clk_hw *hw, unsigned long prate) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + void __iomem *base_addr = cfg_hw->sys_base; + u32 val; + + val = readl_relaxed(base_addr + REG_CLOCK_CONFIG_CR) >> cfg->shift; + val &= clk_div_mask(cfg->width); + + return prate / (1u << val); +} + +static long mpfs_cfg_clk_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + + return divider_round_rate(hw, rate, prate, cfg->table, cfg->width, 0); +} + +static int mpfs_cfg_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate) +{ + struct mpfs_cfg_hw_clock *cfg_hw = to_mpfs_cfg_clk(hw); + struct mpfs_cfg_clock *cfg = &cfg_hw->cfg; + void __iomem *base_addr = cfg_hw->sys_base; + unsigned long flags; + u32 val; + int divider_setting; + + divider_setting = divider_get_val(rate, prate, cfg->table, cfg->width, 0); + + if (divider_setting < 0) + return divider_setting; + + spin_lock_irqsave(&mpfs_clk_lock, flags); + + val = readl_relaxed(base_addr + REG_CLOCK_CONFIG_CR); + val &= ~(clk_div_mask(cfg->width) << cfg_hw->cfg.shift); + val |= divider_setting << cfg->shift; + writel_relaxed(val, base_addr + REG_CLOCK_CONFIG_CR); + + spin_unlock_irqrestore(&mpfs_clk_lock, flags); + + return 0; +} + +static const struct clk_ops mpfs_clk_cfg_ops = { + .recalc_rate = mpfs_cfg_clk_recalc_rate, + .round_rate = mpfs_cfg_clk_round_rate, + .set_rate = mpfs_cfg_clk_set_rate, +}; + +#define CLK_CFG(_id, _name, _parent, _shift, _width, _table, _flags) { \ + .cfg.id = _id, \ + .cfg.shift = _shift, \ + .cfg.width = _width, \ + .cfg.table = _table, \ + .hw.init = CLK_HW_INIT_PARENTS_DATA(_name, _parent, &mpfs_clk_cfg_ops, \ + _flags), \ +} + +static struct mpfs_cfg_hw_clock mpfs_cfg_clks[] = { + CLK_CFG(CLK_CPU, "clk_cpu", mpfs_cfg_parent, 0, 2, mpfs_div_cpu_axi_table, 0), + CLK_CFG(CLK_AXI, "clk_axi", mpfs_cfg_parent, 2, 2, mpfs_div_cpu_axi_table, 0), + CLK_CFG(CLK_AHB, "clk_ahb", mpfs_cfg_parent, 4, 2, mpfs_div_ahb_table, 0), +}; + +static int mpfs_clk_register_cfg(struct device *dev, struct mpfs_cfg_hw_clock *cfg_hw, + void __iomem *sys_base) +{ + cfg_hw->sys_base = sys_base; + + return devm_clk_hw_register(dev, &cfg_hw->hw); +} + +static int mpfs_clk_register_cfgs(struct device *dev, struct mpfs_cfg_hw_clock *cfg_hws, + unsigned int num_clks, struct mpfs_clock_data *data) +{ + void __iomem *sys_base = data->base; + unsigned int i, id; + int ret; + + for (i = 0; i < num_clks; i++) { + struct mpfs_cfg_hw_clock *cfg_hw = &cfg_hws[i]; + + ret = mpfs_clk_register_cfg(dev, cfg_hw, sys_base); + if (ret) + return dev_err_probe(dev, ret, "failed to register clock id: %d\n", + cfg_hw->cfg.id); + + id = cfg_hws[i].cfg.id; + data->hw_data.hws[id] = &cfg_hw->hw; + } + + return 0; +} + +static int mpfs_periph_clk_enable(struct clk_hw *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + void __iomem *base_addr = periph_hw->sys_base; + u32 reg, val; + unsigned long flags; + + spin_lock_irqsave(&mpfs_clk_lock, flags); + + reg = readl_relaxed(base_addr + REG_SUBBLK_RESET_CR); + val = reg & ~(1u << periph->shift); + writel_relaxed(val, base_addr + REG_SUBBLK_RESET_CR); + + reg = readl_relaxed(base_addr + REG_SUBBLK_CLOCK_CR); + val = reg | (1u << periph->shift); + writel_relaxed(val, base_addr + REG_SUBBLK_CLOCK_CR); + + spin_unlock_irqrestore(&mpfs_clk_lock, flags); + + return 0; +} + +static void mpfs_periph_clk_disable(struct clk_hw *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + void __iomem *base_addr = periph_hw->sys_base; + u32 reg, val; + unsigned long flags; + + spin_lock_irqsave(&mpfs_clk_lock, flags); + + reg = readl_relaxed(base_addr + REG_SUBBLK_RESET_CR); + val = reg | (1u << periph->shift); + writel_relaxed(val, base_addr + REG_SUBBLK_RESET_CR); + + reg = readl_relaxed(base_addr + REG_SUBBLK_CLOCK_CR); + val = reg & ~(1u << periph->shift); + writel_relaxed(val, base_addr + REG_SUBBLK_CLOCK_CR); + + spin_unlock_irqrestore(&mpfs_clk_lock, flags); +} + +static int mpfs_periph_clk_is_enabled(struct clk_hw *hw) +{ + struct mpfs_periph_hw_clock *periph_hw = to_mpfs_periph_clk(hw); + struct mpfs_periph_clock *periph = &periph_hw->periph; + void __iomem *base_addr = periph_hw->sys_base; + u32 reg; + + reg = readl_relaxed(base_addr + REG_SUBBLK_RESET_CR); + if ((reg & (1u << periph->shift)) == 0u) { + reg = readl_relaxed(base_addr + REG_SUBBLK_CLOCK_CR); + if (reg & (1u << periph->shift)) + return 1; + } + + return 0; +} + +static const struct clk_ops mpfs_periph_clk_ops = { + .enable = mpfs_periph_clk_enable, + .disable = mpfs_periph_clk_disable, + .is_enabled = mpfs_periph_clk_is_enabled, +}; + +#define CLK_PERIPH(_id, _name, _parent, _shift, _flags) { \ + .periph.id = _id, \ + .periph.shift = _shift, \ + .hw.init = CLK_HW_INIT_HW(_name, _parent, &mpfs_periph_clk_ops, \ + _flags), \ +} + +#define PARENT_CLK(PARENT) (&mpfs_cfg_clks[CLK_##PARENT].hw) + +/* + * Critical clocks: + * - CLK_ENVM: reserved by hart software services (hss) superloop monitor/m mode interrupt + * trap handler + * - CLK_MMUART0: reserved by the hss + * - CLK_DDRC: provides clock to the ddr subsystem + * - CLK_FICx: these provide clocks for sections of the fpga fabric, disabling them would + * cause the fabric to go into reset + */ + +static struct mpfs_periph_hw_clock mpfs_periph_clks[] = { + CLK_PERIPH(CLK_ENVM, "clk_periph_envm", PARENT_CLK(AHB), 0, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_MAC0, "clk_periph_mac0", PARENT_CLK(AHB), 1, 0), + CLK_PERIPH(CLK_MAC1, "clk_periph_mac1", PARENT_CLK(AHB), 2, 0), + CLK_PERIPH(CLK_MMC, "clk_periph_mmc", PARENT_CLK(AHB), 3, 0), + CLK_PERIPH(CLK_TIMER, "clk_periph_timer", PARENT_CLK(AHB), 4, 0), + CLK_PERIPH(CLK_MMUART0, "clk_periph_mmuart0", PARENT_CLK(AHB), 5, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_MMUART1, "clk_periph_mmuart1", PARENT_CLK(AHB), 6, 0), + CLK_PERIPH(CLK_MMUART2, "clk_periph_mmuart2", PARENT_CLK(AHB), 7, 0), + CLK_PERIPH(CLK_MMUART3, "clk_periph_mmuart3", PARENT_CLK(AHB), 8, 0), + CLK_PERIPH(CLK_MMUART4, "clk_periph_mmuart4", PARENT_CLK(AHB), 9, 0), + CLK_PERIPH(CLK_SPI0, "clk_periph_spi0", PARENT_CLK(AHB), 10, 0), + CLK_PERIPH(CLK_SPI1, "clk_periph_spi1", PARENT_CLK(AHB), 11, 0), + CLK_PERIPH(CLK_I2C0, "clk_periph_i2c0", PARENT_CLK(AHB), 12, 0), + CLK_PERIPH(CLK_I2C1, "clk_periph_i2c1", PARENT_CLK(AHB), 13, 0), + CLK_PERIPH(CLK_CAN0, "clk_periph_can0", PARENT_CLK(AHB), 14, 0), + CLK_PERIPH(CLK_CAN1, "clk_periph_can1", PARENT_CLK(AHB), 15, 0), + CLK_PERIPH(CLK_USB, "clk_periph_usb", PARENT_CLK(AHB), 16, 0), + CLK_PERIPH(CLK_RTC, "clk_periph_rtc", PARENT_CLK(AHB), 18, 0), + CLK_PERIPH(CLK_QSPI, "clk_periph_qspi", PARENT_CLK(AHB), 19, 0), + CLK_PERIPH(CLK_GPIO0, "clk_periph_gpio0", PARENT_CLK(AHB), 20, 0), + CLK_PERIPH(CLK_GPIO1, "clk_periph_gpio1", PARENT_CLK(AHB), 21, 0), + CLK_PERIPH(CLK_GPIO2, "clk_periph_gpio2", PARENT_CLK(AHB), 22, 0), + CLK_PERIPH(CLK_DDRC, "clk_periph_ddrc", PARENT_CLK(AHB), 23, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_FIC0, "clk_periph_fic0", PARENT_CLK(AHB), 24, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_FIC1, "clk_periph_fic1", PARENT_CLK(AHB), 25, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_FIC2, "clk_periph_fic2", PARENT_CLK(AHB), 26, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_FIC3, "clk_periph_fic3", PARENT_CLK(AHB), 27, CLK_IS_CRITICAL), + CLK_PERIPH(CLK_ATHENA, "clk_periph_athena", PARENT_CLK(AHB), 28, 0), + CLK_PERIPH(CLK_CFM, "clk_periph_cfm", PARENT_CLK(AHB), 29, 0), +}; + +static int mpfs_clk_register_periph(struct device *dev, struct mpfs_periph_hw_clock *periph_hw, + void __iomem *sys_base) +{ + periph_hw->sys_base = sys_base; + + return devm_clk_hw_register(dev, &periph_hw->hw); +} + +static int mpfs_clk_register_periphs(struct device *dev, struct mpfs_periph_hw_clock *periph_hws, + int num_clks, struct mpfs_clock_data *data) +{ + void __iomem *sys_base = data->base; + unsigned int i, id; + int ret; + + for (i = 0; i < num_clks; i++) { + struct mpfs_periph_hw_clock *periph_hw = &periph_hws[i]; + + ret = mpfs_clk_register_periph(dev, periph_hw, sys_base); + if (ret) + return dev_err_probe(dev, ret, "failed to register clock id: %d\n", + periph_hw->periph.id); + + id = periph_hws[i].periph.id; + data->hw_data.hws[id] = &periph_hw->hw; + } + + return 0; +} + +static int mpfs_clk_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mpfs_clock_data *clk_data; + unsigned int num_clks; + int ret; + + /* CLK_RESERVED is not part of cfg_clks nor periph_clks, so add 1 */ + num_clks = ARRAY_SIZE(mpfs_cfg_clks) + ARRAY_SIZE(mpfs_periph_clks) + 1; + + clk_data = devm_kzalloc(dev, struct_size(clk_data, hw_data.hws, num_clks), GFP_KERNEL); + if (!clk_data) + return -ENOMEM; + + clk_data->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(clk_data->base)) + return PTR_ERR(clk_data->base); + + clk_data->hw_data.num = num_clks; + + ret = mpfs_clk_register_cfgs(dev, mpfs_cfg_clks, ARRAY_SIZE(mpfs_cfg_clks), clk_data); + if (ret) + return ret; + + ret = mpfs_clk_register_periphs(dev, mpfs_periph_clks, ARRAY_SIZE(mpfs_periph_clks), + clk_data); + if (ret) + return ret; + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, &clk_data->hw_data); + if (ret) + return ret; + + return ret; +} + +static const struct of_device_id mpfs_clk_of_match_table[] = { + { .compatible = "microchip,mpfs-clkcfg", }, + {} +}; +MODULE_DEVICE_TABLE(of, mpfs_clk_match_table); + +static struct platform_driver mpfs_clk_driver = { + .probe = mpfs_clk_probe, + .driver = { + .name = "microchip-mpfs-clkcfg", + .of_match_table = mpfs_clk_of_match_table, + }, +}; + +static int __init clk_mpfs_init(void) +{ + return platform_driver_register(&mpfs_clk_driver); +} +core_initcall(clk_mpfs_init); + +static void __exit clk_mpfs_exit(void) +{ + platform_driver_unregister(&mpfs_clk_driver); +} +module_exit(clk_mpfs_exit); + +MODULE_DESCRIPTION("Microchip PolarFire SoC Clock Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c index 0839fb2049e9..50a780274ba0 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c @@ -317,9 +317,9 @@ static const char * const ccic_parent_names[] = {"pll1_2", "pll1_16", "vctcxo"}; static DEFINE_SPINLOCK(gpu_lock); static const char * const mmp2_gpu_gc_parent_names[] = {"pll1_2", "pll1_3", "pll2_2", "pll2_3", "pll2", "usb_pll"}; -static u32 mmp2_gpu_gc_parent_table[] = { 0x0000, 0x0040, 0x0080, 0x00c0, 0x1000, 0x1040 }; +static const u32 mmp2_gpu_gc_parent_table[] = { 0x0000, 0x0040, 0x0080, 0x00c0, 0x1000, 0x1040 }; static const char * const mmp2_gpu_bus_parent_names[] = {"pll1_4", "pll2", "pll2_2", "usb_pll"}; -static u32 mmp2_gpu_bus_parent_table[] = { 0x0000, 0x0020, 0x0030, 0x4020 }; +static const u32 mmp2_gpu_bus_parent_table[] = { 0x0000, 0x0020, 0x0030, 0x4020 }; static const char * const mmp3_gpu_bus_parent_names[] = {"pll1_4", "pll1_6", "pll1_2", "pll2_2"}; static const char * const mmp3_gpu_gc_parent_names[] = {"pll1", "pll2", "pll1_p", "pll2_p"}; diff --git a/drivers/clk/mmp/pwr-island.c b/drivers/clk/mmp/pwr-island.c index ab57c0e995c1..edaa2433a472 100644 --- a/drivers/clk/mmp/pwr-island.c +++ b/drivers/clk/mmp/pwr-island.c @@ -76,7 +76,7 @@ static int mmp_pm_domain_power_off(struct generic_pm_domain *genpd) if (pm_domain->lock) spin_lock_irqsave(pm_domain->lock, flags); - /* Turn off and isolate the the power island. */ + /* Turn off and isolate the power island. */ val = readl(pm_domain->reg); val &= ~pm_domain->power_on; val &= ~0x100; diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c index 32ac6b6b7530..e3777ca65912 100644 --- a/drivers/clk/mvebu/armada-37xx-periph.c +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -25,6 +25,7 @@ #include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/slab.h> +#include <linux/jiffies.h> #define TBG_SEL 0x0 #define DIV_SEL0 0x4 @@ -541,7 +542,7 @@ static void clk_pm_cpu_set_rate_wa(struct clk_pm_cpu *pm_cpu, * We are going to L0 with rate >= 1GHz. Check whether we have been at * L1 for long enough time. If not, go to L1 for 20ms. */ - if (pm_cpu->l1_expiration && jiffies >= pm_cpu->l1_expiration) + if (pm_cpu->l1_expiration && time_is_before_eq_jiffies(pm_cpu->l1_expiration)) goto invalidate_l1_exp; regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD, diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c index 8b686da5577b..c23ac463ab0f 100644 --- a/drivers/clk/nxp/clk-lpc18xx-cgu.c +++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c @@ -457,9 +457,8 @@ static unsigned long lpc18xx_pll1_recalc_rate(struct clk_hw *hw, struct lpc18xx_pll *pll = to_lpc_pll(hw); u16 msel, nsel, psel; bool direct, fbsel; - u32 stat, ctrl; + u32 ctrl; - stat = readl(pll->reg + LPC18XX_CGU_PLL1_STAT); ctrl = readl(pll->reg + LPC18XX_CGU_PLL1_CTRL); direct = (ctrl & LPC18XX_PLL1_CTRL_DIRECT) ? true : false; @@ -523,7 +522,7 @@ static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = { LPC1XX_CGU_CLK_PLL(PLL1, pll1_src_ids, pll1_ops), }; -static void lpc18xx_fill_parent_names(const char **parent, u32 *id, int size) +static void lpc18xx_fill_parent_names(const char **parent, const u32 *id, int size) { int i; diff --git a/drivers/clk/pistachio/clk-pistachio.c b/drivers/clk/pistachio/clk-pistachio.c index 76f492c7e917..2a6d583237dc 100644 --- a/drivers/clk/pistachio/clk-pistachio.c +++ b/drivers/clk/pistachio/clk-pistachio.c @@ -154,7 +154,7 @@ static struct pistachio_pll pistachio_plls[] __initdata = { PNAME(mux_debug) = { "mips_pll_mux", "rpu_v_pll_mux", "rpu_l_pll_mux", "sys_pll_mux", "wifi_pll_mux", "bt_pll_mux" }; -static u32 mux_debug_idx[] = { 0x0, 0x1, 0x2, 0x4, 0x8, 0x10 }; +static const u32 mux_debug_idx[] = { 0x0, 0x1, 0x2, 0x4, 0x8, 0x10 }; static unsigned int pistachio_critical_clks_core[] __initdata = { CLK_MIPS diff --git a/drivers/clk/qcom/gcc-sm6125.c b/drivers/clk/qcom/gcc-sm6125.c index 431b55bb0d2f..cf3af88d4021 100644 --- a/drivers/clk/qcom/gcc-sm6125.c +++ b/drivers/clk/qcom/gcc-sm6125.c @@ -4151,7 +4151,7 @@ static int gcc_sm6125_probe(struct platform_device *pdev) /* * Enable DUAL_EDGE mode for MCLK RCGs - * This is requierd to enable MND divider mode + * This is required to enable MND divider mode */ regmap_update_bits(regmap, 0x51004, 0x3000, 0x2000); regmap_update_bits(regmap, 0x51020, 0x3000, 0x2000); diff --git a/drivers/clk/qcom/kpss-xcc.c b/drivers/clk/qcom/kpss-xcc.c index 4fec1f9142b8..88d4b33ac0cc 100644 --- a/drivers/clk/qcom/kpss-xcc.c +++ b/drivers/clk/qcom/kpss-xcc.c @@ -17,7 +17,7 @@ static const char *aux_parents[] = { "pxo", }; -static unsigned int aux_parent_map[] = { +static const u32 aux_parent_map[] = { 3, 0, }; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index be6e6ae7448c..c281f3af5716 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -34,6 +34,7 @@ config CLK_RENESAS select CLK_R8A779F0 if ARCH_R8A779F0 select CLK_R9A06G032 if ARCH_R9A06G032 select CLK_R9A07G044 if ARCH_R9A07G044 + select CLK_R9A07G054 if ARCH_R9A07G054 select CLK_SH73A0 if ARCH_SH73A0 if CLK_RENESAS @@ -163,6 +164,10 @@ config CLK_R9A07G044 bool "RZ/G2L clock support" if COMPILE_TEST select CLK_RZG2L +config CLK_R9A07G054 + bool "RZ/V2L clock support" if COMPILE_TEST + select CLK_RZG2L + config CLK_SH73A0 bool "SH-Mobile AG5 clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSTP @@ -195,7 +200,7 @@ config CLK_RCAR_USB2_CLOCK_SEL This is a driver for R-Car USB2 clock selector config CLK_RZG2L - bool "Renesas RZ/G2L family clock support" if COMPILE_TEST + bool "Renesas RZ/{G2L,V2L} family clock support" if COMPILE_TEST select RESET_CONTROLLER # Generic diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index 8b34db1a328c..d5e571699a30 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R8A779F0) += r8a779f0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o obj-$(CONFIG_CLK_R9A07G044) += r9a07g044-cpg.o +obj-$(CONFIG_CLK_R9A07G054) += r9a07g044-cpg.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o # Family diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c index faf60f7adc8d..d34d97baab35 100644 --- a/drivers/clk/renesas/r8a77990-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -200,6 +200,7 @@ static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { DEF_MOD("du0", 724, R8A77990_CLK_S1D1), DEF_MOD("lvds", 727, R8A77990_CLK_S2D1), + DEF_MOD("mlp", 802, R8A77990_CLK_S2D1), DEF_MOD("vin5", 806, R8A77990_CLK_S1D2), DEF_MOD("vin4", 807, R8A77990_CLK_S1D2), DEF_MOD("etheravb", 812, R8A77990_CLK_S3D2), diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 7713cfd99c1d..525eef197fd9 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -160,6 +160,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { DEF_MOD("du1", 723, R8A77995_CLK_S1D1), DEF_MOD("du0", 724, R8A77995_CLK_S1D1), DEF_MOD("lvds", 727, R8A77995_CLK_S2D1), + DEF_MOD("mlp", 802, R8A77995_CLK_S2D1), DEF_MOD("vin4", 807, R8A77995_CLK_S1D2), DEF_MOD("etheravb", 812, R8A77995_CLK_S3D2), DEF_MOD("imr0", 823, R8A77995_CLK_S1D2), diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 1c09d4ebe90f..fadd8a1718c6 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -136,6 +136,7 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2), DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2), DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2), + DEF_MOD("canfd0", 328, R8A779A0_CLK_CANFD), DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0), DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c index e6ec02c2c2a8..76b441965037 100644 --- a/drivers/clk/renesas/r8a779f0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c @@ -103,7 +103,7 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = { DEF_FIXED("s0d12_hsc", R8A779F0_CLK_S0D12_HSC, CLK_S0, 12, 1), DEF_FIXED("cl16m_hsc", R8A779F0_CLK_CL16M_HSC, CLK_S0, 48, 1), DEF_FIXED("s0d2_cc", R8A779F0_CLK_S0D2_CC, CLK_S0, 2, 1), - DEF_FIXED("rsw2", R8A779F0_CLK_RSW2, CLK_PLL5, 2, 1), + DEF_FIXED("rsw2", R8A779F0_CLK_RSW2, CLK_PLL5_DIV2, 5, 1), DEF_FIXED("cbfusa", R8A779F0_CLK_CBFUSA, CLK_EXTAL, 2, 1), DEF_FIXED("cpex", R8A779F0_CLK_CPEX, CLK_EXTAL, 2, 1), @@ -115,10 +115,24 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = { + DEF_MOD("i2c0", 518, R8A779F0_CLK_S0D6_PER), + DEF_MOD("i2c1", 519, R8A779F0_CLK_S0D6_PER), + DEF_MOD("i2c2", 520, R8A779F0_CLK_S0D6_PER), + DEF_MOD("i2c3", 521, R8A779F0_CLK_S0D6_PER), + DEF_MOD("i2c4", 522, R8A779F0_CLK_S0D6_PER), + DEF_MOD("i2c5", 523, R8A779F0_CLK_S0D6_PER), DEF_MOD("scif0", 702, R8A779F0_CLK_S0D12_PER), DEF_MOD("scif1", 703, R8A779F0_CLK_S0D12_PER), DEF_MOD("scif3", 704, R8A779F0_CLK_S0D12_PER), DEF_MOD("scif4", 705, R8A779F0_CLK_S0D12_PER), + DEF_MOD("sys-dmac0", 709, R8A779F0_CLK_S0D3_PER), + DEF_MOD("sys-dmac1", 710, R8A779F0_CLK_S0D3_PER), + DEF_MOD("wdt", 907, R8A779F0_CLK_R), + DEF_MOD("pfc0", 915, R8A779F0_CLK_CL16M), +}; + +static const unsigned int r8a779f0_crit_mod_clks[] __initconst = { + MOD_CLK_ID(907), /* WDT */ }; /* @@ -175,6 +189,10 @@ const struct cpg_mssr_info r8a779f0_cpg_mssr_info __initconst = { .num_mod_clks = ARRAY_SIZE(r8a779f0_mod_clks), .num_hw_mod_clks = 28 * 32, + /* Critical Module Clocks */ + .crit_mod_clks = r8a779f0_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a779f0_crit_mod_clks), + /* Callbacks */ .init = r8a779f0_cpg_mssr_init, .cpg_clk_register = rcar_gen4_cpg_clk_register, diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c index 79042bf46fe8..bdfabb992a20 100644 --- a/drivers/clk/renesas/r9a07g044-cpg.c +++ b/drivers/clk/renesas/r9a07g044-cpg.c @@ -11,12 +11,13 @@ #include <linux/kernel.h> #include <dt-bindings/clock/r9a07g044-cpg.h> +#include <dt-bindings/clock/r9a07g054-cpg.h> #include "rzg2l-cpg.h" enum clk_ids { /* Core Clock Outputs exported to DT */ - LAST_DT_CORE_CLK = R9A07G044_CLK_P0_DIV2, + LAST_DT_CORE_CLK = R9A07G054_CLK_DRP_A, /* External Input Clocks */ CLK_EXTAL, @@ -80,200 +81,222 @@ static const char * const sel_pll6_2[] = { ".pll6_250", ".pll5_250" }; static const char * const sel_shdi[] = { ".clk_533", ".clk_400", ".clk_266" }; static const char * const sel_gpu2[] = { ".pll6", ".pll3_div2_2" }; -static const struct cpg_core_clk r9a07g044_core_clks[] __initconst = { - /* External Clock Inputs */ - DEF_INPUT("extal", CLK_EXTAL), +static const struct { + struct cpg_core_clk common[44]; +#ifdef CONFIG_CLK_R9A07G054 + struct cpg_core_clk drp[0]; +#endif +} core_clks __initconst = { + .common = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), - /* Internal Core Clocks */ - DEF_FIXED(".osc", R9A07G044_OSCCLK, CLK_EXTAL, 1, 1), - DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), - DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)), - DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 133, 2), - DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 133, 2), - DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4), - DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3), + /* Internal Core Clocks */ + DEF_FIXED(".osc", R9A07G044_OSCCLK, CLK_EXTAL, 1, 1), + DEF_FIXED(".osc_div1000", CLK_OSC_DIV1000, CLK_EXTAL, 1, 1000), + DEF_SAMPLL(".pll1", CLK_PLL1, CLK_EXTAL, PLL146_CONF(0)), + DEF_FIXED(".pll2", CLK_PLL2, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll3", CLK_PLL3, CLK_EXTAL, 200, 3), + DEF_FIXED(".pll3_400", CLK_PLL3_400, CLK_PLL3, 1, 4), + DEF_FIXED(".pll3_533", CLK_PLL3_533, CLK_PLL3, 1, 3), - DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1), - DEF_FIXED(".pll5_fout3", CLK_PLL5_FOUT3, CLK_PLL5, 1, 6), + DEF_FIXED(".pll5", CLK_PLL5, CLK_EXTAL, 125, 1), + DEF_FIXED(".pll5_fout3", CLK_PLL5_FOUT3, CLK_PLL5, 1, 6), - DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6), + DEF_FIXED(".pll6", CLK_PLL6, CLK_EXTAL, 125, 6), - DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), - DEF_FIXED(".clk_800", CLK_PLL2_800, CLK_PLL2, 1, 2), - DEF_FIXED(".clk_533", CLK_PLL2_SDHI_533, CLK_PLL2, 1, 3), - DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2), - DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2), + DEF_FIXED(".pll2_div2", CLK_PLL2_DIV2, CLK_PLL2, 1, 2), + DEF_FIXED(".clk_800", CLK_PLL2_800, CLK_PLL2, 1, 2), + DEF_FIXED(".clk_533", CLK_PLL2_SDHI_533, CLK_PLL2, 1, 3), + DEF_FIXED(".clk_400", CLK_PLL2_SDHI_400, CLK_PLL2_800, 1, 2), + DEF_FIXED(".clk_266", CLK_PLL2_SDHI_266, CLK_PLL2_SDHI_533, 1, 2), - DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8), - DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10), + DEF_FIXED(".pll2_div2_8", CLK_PLL2_DIV2_8, CLK_PLL2_DIV2, 1, 8), + DEF_FIXED(".pll2_div2_10", CLK_PLL2_DIV2_10, CLK_PLL2_DIV2, 1, 10), - DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), - DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2), - DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4), - DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2), - DEF_MUX(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, - sel_pll3_3, ARRAY_SIZE(sel_pll3_3), 0, CLK_MUX_READ_ONLY), - DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, - DIVPL3C, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_FIXED(".pll3_div2", CLK_PLL3_DIV2, CLK_PLL3, 1, 2), + DEF_FIXED(".pll3_div2_2", CLK_PLL3_DIV2_2, CLK_PLL3_DIV2, 1, 2), + DEF_FIXED(".pll3_div2_4", CLK_PLL3_DIV2_4, CLK_PLL3_DIV2, 1, 4), + DEF_FIXED(".pll3_div2_4_2", CLK_PLL3_DIV2_4_2, CLK_PLL3_DIV2_4, 1, 2), + DEF_MUX(".sel_pll3_3", CLK_SEL_PLL3_3, SEL_PLL3_3, + sel_pll3_3, ARRAY_SIZE(sel_pll3_3), 0, CLK_MUX_READ_ONLY), + DEF_DIV("divpl3c", CLK_DIV_PLL3_C, CLK_SEL_PLL3_3, + DIVPL3C, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), - DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2), - DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2), - DEF_MUX(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2, - sel_gpu2, ARRAY_SIZE(sel_gpu2), 0, CLK_MUX_READ_ONLY), + DEF_FIXED(".pll5_250", CLK_PLL5_250, CLK_PLL5_FOUT3, 1, 2), + DEF_FIXED(".pll6_250", CLK_PLL6_250, CLK_PLL6, 1, 2), + DEF_MUX(".sel_gpu2", CLK_SEL_GPU2, SEL_GPU2, + sel_gpu2, ARRAY_SIZE(sel_gpu2), 0, CLK_MUX_READ_ONLY), - /* Core output clk */ - DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8, - CLK_DIVIDER_HIWORD_MASK), - DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, - dtable_1_32, CLK_DIVIDER_HIWORD_MASK), - DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2), - DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1), - DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4, - DIVPL3B, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), - DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2), - DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2, - DIVPL3A, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), - DEF_FIXED("M0", R9A07G044_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), - DEF_FIXED("ZT", R9A07G044_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1), - DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, - sel_pll6_2, ARRAY_SIZE(sel_pll6_2), 0, CLK_MUX_HIWORD_MASK), - DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), - DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), - DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, - sel_shdi, ARRAY_SIZE(sel_shdi)), - DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, - sel_shdi, ARRAY_SIZE(sel_shdi)), - DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), - DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), - DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8, - CLK_DIVIDER_HIWORD_MASK), + /* Core output clk */ + DEF_DIV("I", R9A07G044_CLK_I, CLK_PLL1, DIVPL1A, dtable_1_8, + CLK_DIVIDER_HIWORD_MASK), + DEF_DIV("P0", R9A07G044_CLK_P0, CLK_PLL2_DIV2_8, DIVPL2A, + dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_FIXED("P0_DIV2", R9A07G044_CLK_P0_DIV2, R9A07G044_CLK_P0, 1, 2), + DEF_FIXED("TSU", R9A07G044_CLK_TSU, CLK_PLL2_DIV2_10, 1, 1), + DEF_DIV("P1", R9A07G044_CLK_P1, CLK_PLL3_DIV2_4, + DIVPL3B, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_FIXED("P1_DIV2", CLK_P1_DIV2, R9A07G044_CLK_P1, 1, 2), + DEF_DIV("P2", R9A07G044_CLK_P2, CLK_PLL3_DIV2_4_2, + DIVPL3A, dtable_1_32, CLK_DIVIDER_HIWORD_MASK), + DEF_FIXED("M0", R9A07G044_CLK_M0, CLK_PLL3_DIV2_4, 1, 1), + DEF_FIXED("ZT", R9A07G044_CLK_ZT, CLK_PLL3_DIV2_4_2, 1, 1), + DEF_MUX("HP", R9A07G044_CLK_HP, SEL_PLL6_2, + sel_pll6_2, ARRAY_SIZE(sel_pll6_2), 0, CLK_MUX_HIWORD_MASK), + DEF_FIXED("SPI0", R9A07G044_CLK_SPI0, CLK_DIV_PLL3_C, 1, 2), + DEF_FIXED("SPI1", R9A07G044_CLK_SPI1, CLK_DIV_PLL3_C, 1, 4), + DEF_SD_MUX("SD0", R9A07G044_CLK_SD0, SEL_SDHI0, + sel_shdi, ARRAY_SIZE(sel_shdi)), + DEF_SD_MUX("SD1", R9A07G044_CLK_SD1, SEL_SDHI1, + sel_shdi, ARRAY_SIZE(sel_shdi)), + DEF_FIXED("SD0_DIV4", CLK_SD0_DIV4, R9A07G044_CLK_SD0, 1, 4), + DEF_FIXED("SD1_DIV4", CLK_SD1_DIV4, R9A07G044_CLK_SD1, 1, 4), + DEF_DIV("G", R9A07G044_CLK_G, CLK_SEL_GPU2, DIVGPU, dtable_1_8, + CLK_DIVIDER_HIWORD_MASK), + }, +#ifdef CONFIG_CLK_R9A07G054 + .drp = { + }, +#endif }; -static struct rzg2l_mod_clk r9a07g044_mod_clks[] = { - DEF_MOD("gic", R9A07G044_GIC600_GICCLK, R9A07G044_CLK_P1, - 0x514, 0), - DEF_MOD("ia55_pclk", R9A07G044_IA55_PCLK, R9A07G044_CLK_P2, - 0x518, 0), - DEF_MOD("ia55_clk", R9A07G044_IA55_CLK, R9A07G044_CLK_P1, - 0x518, 1), - DEF_MOD("dmac_aclk", R9A07G044_DMAC_ACLK, R9A07G044_CLK_P1, - 0x52c, 0), - DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2, - 0x52c, 1), - DEF_MOD("ostm0_pclk", R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0, - 0x534, 0), - DEF_MOD("ostm1_clk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0, - 0x534, 1), - DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0, - 0x534, 2), - DEF_MOD("wdt0_pclk", R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0, - 0x548, 0), - DEF_MOD("wdt0_clk", R9A07G044_WDT0_CLK, R9A07G044_OSCCLK, - 0x548, 1), - DEF_MOD("wdt1_pclk", R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0, - 0x548, 2), - DEF_MOD("wdt1_clk", R9A07G044_WDT1_CLK, R9A07G044_OSCCLK, - 0x548, 3), - DEF_MOD("wdt2_pclk", R9A07G044_WDT2_PCLK, R9A07G044_CLK_P0, - 0x548, 4), - DEF_MOD("wdt2_clk", R9A07G044_WDT2_CLK, R9A07G044_OSCCLK, - 0x548, 5), - DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1, - 0x550, 0), - DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0, - 0x550, 1), - DEF_MOD("sdhi0_imclk", R9A07G044_SDHI0_IMCLK, CLK_SD0_DIV4, - 0x554, 0), - DEF_MOD("sdhi0_imclk2", R9A07G044_SDHI0_IMCLK2, CLK_SD0_DIV4, - 0x554, 1), - DEF_MOD("sdhi0_clk_hs", R9A07G044_SDHI0_CLK_HS, R9A07G044_CLK_SD0, - 0x554, 2), - DEF_MOD("sdhi0_aclk", R9A07G044_SDHI0_ACLK, R9A07G044_CLK_P1, - 0x554, 3), - DEF_MOD("sdhi1_imclk", R9A07G044_SDHI1_IMCLK, CLK_SD1_DIV4, - 0x554, 4), - DEF_MOD("sdhi1_imclk2", R9A07G044_SDHI1_IMCLK2, CLK_SD1_DIV4, - 0x554, 5), - DEF_MOD("sdhi1_clk_hs", R9A07G044_SDHI1_CLK_HS, R9A07G044_CLK_SD1, - 0x554, 6), - DEF_MOD("sdhi1_aclk", R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1, - 0x554, 7), - DEF_MOD("gpu_clk", R9A07G044_GPU_CLK, R9A07G044_CLK_G, - 0x558, 0), - DEF_MOD("gpu_axi_clk", R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1, - 0x558, 1), - DEF_MOD("gpu_ace_clk", R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1, - 0x558, 2), - DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0, - 0x570, 0), - DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0, - 0x570, 1), - DEF_MOD("ssi1_pclk", R9A07G044_SSI1_PCLK2, R9A07G044_CLK_P0, - 0x570, 2), - DEF_MOD("ssi1_sfr", R9A07G044_SSI1_PCLK_SFR, R9A07G044_CLK_P0, - 0x570, 3), - DEF_MOD("ssi2_pclk", R9A07G044_SSI2_PCLK2, R9A07G044_CLK_P0, - 0x570, 4), - DEF_MOD("ssi2_sfr", R9A07G044_SSI2_PCLK_SFR, R9A07G044_CLK_P0, - 0x570, 5), - DEF_MOD("ssi3_pclk", R9A07G044_SSI3_PCLK2, R9A07G044_CLK_P0, - 0x570, 6), - DEF_MOD("ssi3_sfr", R9A07G044_SSI3_PCLK_SFR, R9A07G044_CLK_P0, - 0x570, 7), - DEF_MOD("usb0_host", R9A07G044_USB_U2H0_HCLK, R9A07G044_CLK_P1, - 0x578, 0), - DEF_MOD("usb1_host", R9A07G044_USB_U2H1_HCLK, R9A07G044_CLK_P1, - 0x578, 1), - DEF_MOD("usb0_func", R9A07G044_USB_U2P_EXR_CPUCLK, R9A07G044_CLK_P1, - 0x578, 2), - DEF_MOD("usb_pclk", R9A07G044_USB_PCLK, R9A07G044_CLK_P1, - 0x578, 3), - DEF_COUPLED("eth0_axi", R9A07G044_ETH0_CLK_AXI, R9A07G044_CLK_M0, - 0x57c, 0), - DEF_COUPLED("eth0_chi", R9A07G044_ETH0_CLK_CHI, R9A07G044_CLK_ZT, - 0x57c, 0), - DEF_COUPLED("eth1_axi", R9A07G044_ETH1_CLK_AXI, R9A07G044_CLK_M0, - 0x57c, 1), - DEF_COUPLED("eth1_chi", R9A07G044_ETH1_CLK_CHI, R9A07G044_CLK_ZT, - 0x57c, 1), - DEF_MOD("i2c0", R9A07G044_I2C0_PCLK, R9A07G044_CLK_P0, - 0x580, 0), - DEF_MOD("i2c1", R9A07G044_I2C1_PCLK, R9A07G044_CLK_P0, - 0x580, 1), - DEF_MOD("i2c2", R9A07G044_I2C2_PCLK, R9A07G044_CLK_P0, - 0x580, 2), - DEF_MOD("i2c3", R9A07G044_I2C3_PCLK, R9A07G044_CLK_P0, - 0x580, 3), - DEF_MOD("scif0", R9A07G044_SCIF0_CLK_PCK, R9A07G044_CLK_P0, - 0x584, 0), - DEF_MOD("scif1", R9A07G044_SCIF1_CLK_PCK, R9A07G044_CLK_P0, - 0x584, 1), - DEF_MOD("scif2", R9A07G044_SCIF2_CLK_PCK, R9A07G044_CLK_P0, - 0x584, 2), - DEF_MOD("scif3", R9A07G044_SCIF3_CLK_PCK, R9A07G044_CLK_P0, - 0x584, 3), - DEF_MOD("scif4", R9A07G044_SCIF4_CLK_PCK, R9A07G044_CLK_P0, - 0x584, 4), - DEF_MOD("sci0", R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0, - 0x588, 0), - DEF_MOD("sci1", R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0, - 0x588, 1), - DEF_MOD("rspi0", R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0, - 0x590, 0), - DEF_MOD("rspi1", R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0, - 0x590, 1), - DEF_MOD("rspi2", R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0, - 0x590, 2), - DEF_MOD("canfd", R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0, - 0x594, 0), - DEF_MOD("gpio", R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK, - 0x598, 0), - DEF_MOD("adc_adclk", R9A07G044_ADC_ADCLK, R9A07G044_CLK_TSU, - 0x5a8, 0), - DEF_MOD("adc_pclk", R9A07G044_ADC_PCLK, R9A07G044_CLK_P0, - 0x5a8, 1), - DEF_MOD("tsu_pclk", R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU, - 0x5ac, 0), +static const struct { + struct rzg2l_mod_clk common[62]; +#ifdef CONFIG_CLK_R9A07G054 + struct rzg2l_mod_clk drp[0]; +#endif +} mod_clks = { + .common = { + DEF_MOD("gic", R9A07G044_GIC600_GICCLK, R9A07G044_CLK_P1, + 0x514, 0), + DEF_MOD("ia55_pclk", R9A07G044_IA55_PCLK, R9A07G044_CLK_P2, + 0x518, 0), + DEF_MOD("ia55_clk", R9A07G044_IA55_CLK, R9A07G044_CLK_P1, + 0x518, 1), + DEF_MOD("dmac_aclk", R9A07G044_DMAC_ACLK, R9A07G044_CLK_P1, + 0x52c, 0), + DEF_MOD("dmac_pclk", R9A07G044_DMAC_PCLK, CLK_P1_DIV2, + 0x52c, 1), + DEF_MOD("ostm0_pclk", R9A07G044_OSTM0_PCLK, R9A07G044_CLK_P0, + 0x534, 0), + DEF_MOD("ostm1_clk", R9A07G044_OSTM1_PCLK, R9A07G044_CLK_P0, + 0x534, 1), + DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0, + 0x534, 2), + DEF_MOD("wdt0_pclk", R9A07G044_WDT0_PCLK, R9A07G044_CLK_P0, + 0x548, 0), + DEF_MOD("wdt0_clk", R9A07G044_WDT0_CLK, R9A07G044_OSCCLK, + 0x548, 1), + DEF_MOD("wdt1_pclk", R9A07G044_WDT1_PCLK, R9A07G044_CLK_P0, + 0x548, 2), + DEF_MOD("wdt1_clk", R9A07G044_WDT1_CLK, R9A07G044_OSCCLK, + 0x548, 3), + DEF_MOD("wdt2_pclk", R9A07G044_WDT2_PCLK, R9A07G044_CLK_P0, + 0x548, 4), + DEF_MOD("wdt2_clk", R9A07G044_WDT2_CLK, R9A07G044_OSCCLK, + 0x548, 5), + DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1, + 0x550, 0), + DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0, + 0x550, 1), + DEF_MOD("sdhi0_imclk", R9A07G044_SDHI0_IMCLK, CLK_SD0_DIV4, + 0x554, 0), + DEF_MOD("sdhi0_imclk2", R9A07G044_SDHI0_IMCLK2, CLK_SD0_DIV4, + 0x554, 1), + DEF_MOD("sdhi0_clk_hs", R9A07G044_SDHI0_CLK_HS, R9A07G044_CLK_SD0, + 0x554, 2), + DEF_MOD("sdhi0_aclk", R9A07G044_SDHI0_ACLK, R9A07G044_CLK_P1, + 0x554, 3), + DEF_MOD("sdhi1_imclk", R9A07G044_SDHI1_IMCLK, CLK_SD1_DIV4, + 0x554, 4), + DEF_MOD("sdhi1_imclk2", R9A07G044_SDHI1_IMCLK2, CLK_SD1_DIV4, + 0x554, 5), + DEF_MOD("sdhi1_clk_hs", R9A07G044_SDHI1_CLK_HS, R9A07G044_CLK_SD1, + 0x554, 6), + DEF_MOD("sdhi1_aclk", R9A07G044_SDHI1_ACLK, R9A07G044_CLK_P1, + 0x554, 7), + DEF_MOD("gpu_clk", R9A07G044_GPU_CLK, R9A07G044_CLK_G, + 0x558, 0), + DEF_MOD("gpu_axi_clk", R9A07G044_GPU_AXI_CLK, R9A07G044_CLK_P1, + 0x558, 1), + DEF_MOD("gpu_ace_clk", R9A07G044_GPU_ACE_CLK, R9A07G044_CLK_P1, + 0x558, 2), + DEF_MOD("ssi0_pclk", R9A07G044_SSI0_PCLK2, R9A07G044_CLK_P0, + 0x570, 0), + DEF_MOD("ssi0_sfr", R9A07G044_SSI0_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 1), + DEF_MOD("ssi1_pclk", R9A07G044_SSI1_PCLK2, R9A07G044_CLK_P0, + 0x570, 2), + DEF_MOD("ssi1_sfr", R9A07G044_SSI1_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 3), + DEF_MOD("ssi2_pclk", R9A07G044_SSI2_PCLK2, R9A07G044_CLK_P0, + 0x570, 4), + DEF_MOD("ssi2_sfr", R9A07G044_SSI2_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 5), + DEF_MOD("ssi3_pclk", R9A07G044_SSI3_PCLK2, R9A07G044_CLK_P0, + 0x570, 6), + DEF_MOD("ssi3_sfr", R9A07G044_SSI3_PCLK_SFR, R9A07G044_CLK_P0, + 0x570, 7), + DEF_MOD("usb0_host", R9A07G044_USB_U2H0_HCLK, R9A07G044_CLK_P1, + 0x578, 0), + DEF_MOD("usb1_host", R9A07G044_USB_U2H1_HCLK, R9A07G044_CLK_P1, + 0x578, 1), + DEF_MOD("usb0_func", R9A07G044_USB_U2P_EXR_CPUCLK, R9A07G044_CLK_P1, + 0x578, 2), + DEF_MOD("usb_pclk", R9A07G044_USB_PCLK, R9A07G044_CLK_P1, + 0x578, 3), + DEF_COUPLED("eth0_axi", R9A07G044_ETH0_CLK_AXI, R9A07G044_CLK_M0, + 0x57c, 0), + DEF_COUPLED("eth0_chi", R9A07G044_ETH0_CLK_CHI, R9A07G044_CLK_ZT, + 0x57c, 0), + DEF_COUPLED("eth1_axi", R9A07G044_ETH1_CLK_AXI, R9A07G044_CLK_M0, + 0x57c, 1), + DEF_COUPLED("eth1_chi", R9A07G044_ETH1_CLK_CHI, R9A07G044_CLK_ZT, + 0x57c, 1), + DEF_MOD("i2c0", R9A07G044_I2C0_PCLK, R9A07G044_CLK_P0, + 0x580, 0), + DEF_MOD("i2c1", R9A07G044_I2C1_PCLK, R9A07G044_CLK_P0, + 0x580, 1), + DEF_MOD("i2c2", R9A07G044_I2C2_PCLK, R9A07G044_CLK_P0, + 0x580, 2), + DEF_MOD("i2c3", R9A07G044_I2C3_PCLK, R9A07G044_CLK_P0, + 0x580, 3), + DEF_MOD("scif0", R9A07G044_SCIF0_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 0), + DEF_MOD("scif1", R9A07G044_SCIF1_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 1), + DEF_MOD("scif2", R9A07G044_SCIF2_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 2), + DEF_MOD("scif3", R9A07G044_SCIF3_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 3), + DEF_MOD("scif4", R9A07G044_SCIF4_CLK_PCK, R9A07G044_CLK_P0, + 0x584, 4), + DEF_MOD("sci0", R9A07G044_SCI0_CLKP, R9A07G044_CLK_P0, + 0x588, 0), + DEF_MOD("sci1", R9A07G044_SCI1_CLKP, R9A07G044_CLK_P0, + 0x588, 1), + DEF_MOD("rspi0", R9A07G044_RSPI0_CLKB, R9A07G044_CLK_P0, + 0x590, 0), + DEF_MOD("rspi1", R9A07G044_RSPI1_CLKB, R9A07G044_CLK_P0, + 0x590, 1), + DEF_MOD("rspi2", R9A07G044_RSPI2_CLKB, R9A07G044_CLK_P0, + 0x590, 2), + DEF_MOD("canfd", R9A07G044_CANFD_PCLK, R9A07G044_CLK_P0, + 0x594, 0), + DEF_MOD("gpio", R9A07G044_GPIO_HCLK, R9A07G044_OSCCLK, + 0x598, 0), + DEF_MOD("adc_adclk", R9A07G044_ADC_ADCLK, R9A07G044_CLK_TSU, + 0x5a8, 0), + DEF_MOD("adc_pclk", R9A07G044_ADC_PCLK, R9A07G044_CLK_P0, + 0x5a8, 1), + DEF_MOD("tsu_pclk", R9A07G044_TSU_PCLK, R9A07G044_CLK_TSU, + 0x5ac, 0), + }, +#ifdef CONFIG_CLK_R9A07G054 + .drp = { + }, +#endif }; static struct rzg2l_reset r9a07g044_resets[] = { @@ -336,8 +359,8 @@ static const unsigned int r9a07g044_crit_mod_clks[] __initconst = { const struct rzg2l_cpg_info r9a07g044_cpg_info = { /* Core Clocks */ - .core_clks = r9a07g044_core_clks, - .num_core_clks = ARRAY_SIZE(r9a07g044_core_clks), + .core_clks = core_clks.common, + .num_core_clks = ARRAY_SIZE(core_clks.common), .last_dt_core_clk = LAST_DT_CORE_CLK, .num_total_core_clks = MOD_CLK_BASE, @@ -346,11 +369,34 @@ const struct rzg2l_cpg_info r9a07g044_cpg_info = { .num_crit_mod_clks = ARRAY_SIZE(r9a07g044_crit_mod_clks), /* Module Clocks */ - .mod_clks = r9a07g044_mod_clks, - .num_mod_clks = ARRAY_SIZE(r9a07g044_mod_clks), + .mod_clks = mod_clks.common, + .num_mod_clks = ARRAY_SIZE(mod_clks.common), .num_hw_mod_clks = R9A07G044_TSU_PCLK + 1, /* Resets */ .resets = r9a07g044_resets, - .num_resets = ARRAY_SIZE(r9a07g044_resets), + .num_resets = R9A07G044_TSU_PRESETN + 1, /* Last reset ID + 1 */ +}; + +#ifdef CONFIG_CLK_R9A07G054 +const struct rzg2l_cpg_info r9a07g054_cpg_info = { + /* Core Clocks */ + .core_clks = core_clks.common, + .num_core_clks = ARRAY_SIZE(core_clks.common) + ARRAY_SIZE(core_clks.drp), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Critical Module Clocks */ + .crit_mod_clks = r9a07g044_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r9a07g044_crit_mod_clks), + + /* Module Clocks */ + .mod_clks = mod_clks.common, + .num_mod_clks = ARRAY_SIZE(mod_clks.common) + ARRAY_SIZE(mod_clks.drp), + .num_hw_mod_clks = R9A07G054_STPAI_ACLK_DRP + 1, + + /* Resets */ + .resets = r9a07g044_resets, + .num_resets = R9A07G054_STPAI_ARESETN + 1, /* Last reset ID + 1 */ }; +#endif diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c index edd0abe34a37..486d0656c58a 100644 --- a/drivers/clk/renesas/rzg2l-cpg.c +++ b/drivers/clk/renesas/rzg2l-cpg.c @@ -953,6 +953,12 @@ static const struct of_device_id rzg2l_cpg_match[] = { .data = &r9a07g044_cpg_info, }, #endif +#ifdef CONFIG_CLK_R9A07G054 + { + .compatible = "renesas,r9a07g054-cpg", + .data = &r9a07g054_cpg_info, + }, +#endif { /* sentinel */ } }; diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h index 5729d102034b..ce657beaf160 100644 --- a/drivers/clk/renesas/rzg2l-cpg.h +++ b/drivers/clk/renesas/rzg2l-cpg.h @@ -203,5 +203,6 @@ struct rzg2l_cpg_info { }; extern const struct rzg2l_cpg_info r9a07g044_cpg_info; +extern const struct rzg2l_cpg_info r9a07g054_cpg_info; #endif diff --git a/drivers/clk/rockchip/clk-rk3568.c b/drivers/clk/rockchip/clk-rk3568.c index 69a9e8069a48..606ae6cd918b 100644 --- a/drivers/clk/rockchip/clk-rk3568.c +++ b/drivers/clk/rockchip/clk-rk3568.c @@ -71,11 +71,17 @@ static struct rockchip_pll_rate_table rk3568_pll_rates[] = { RK3036_PLL_RATE(500000000, 1, 125, 6, 1, 1, 0), RK3036_PLL_RATE(408000000, 1, 68, 2, 2, 1, 0), RK3036_PLL_RATE(312000000, 1, 78, 6, 1, 1, 0), + RK3036_PLL_RATE(297000000, 2, 99, 4, 1, 1, 0), + RK3036_PLL_RATE(241500000, 2, 161, 4, 2, 1, 0), RK3036_PLL_RATE(216000000, 1, 72, 4, 2, 1, 0), RK3036_PLL_RATE(200000000, 1, 100, 3, 4, 1, 0), RK3036_PLL_RATE(148500000, 1, 99, 4, 4, 1, 0), + RK3036_PLL_RATE(135000000, 2, 45, 4, 1, 1, 0), + RK3036_PLL_RATE(119000000, 3, 119, 4, 2, 1, 0), + RK3036_PLL_RATE(108000000, 2, 45, 5, 1, 1, 0), RK3036_PLL_RATE(100000000, 1, 150, 6, 6, 1, 0), RK3036_PLL_RATE(96000000, 1, 96, 6, 4, 1, 0), + RK3036_PLL_RATE(78750000, 1, 96, 6, 4, 1, 0), RK3036_PLL_RATE(74250000, 2, 99, 4, 4, 1, 0), { /* sentinel */ }, }; @@ -1038,13 +1044,13 @@ static struct rockchip_clk_branch rk3568_clk_branches[] __initdata = { RK3568_CLKGATE_CON(20), 8, GFLAGS), GATE(HCLK_VOP, "hclk_vop", "hclk_vo", 0, RK3568_CLKGATE_CON(20), 9, GFLAGS), - COMPOSITE(DCLK_VOP0, "dclk_vop0", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + COMPOSITE(DCLK_VOP0, "dclk_vop0", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_NO_REPARENT, RK3568_CLKSEL_CON(39), 10, 2, MFLAGS, 0, 8, DFLAGS, RK3568_CLKGATE_CON(20), 10, GFLAGS), - COMPOSITE(DCLK_VOP1, "dclk_vop1", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, + COMPOSITE(DCLK_VOP1, "dclk_vop1", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_NO_REPARENT, RK3568_CLKSEL_CON(40), 10, 2, MFLAGS, 0, 8, DFLAGS, RK3568_CLKGATE_CON(20), 11, GFLAGS), - COMPOSITE(DCLK_VOP2, "dclk_vop2", hpll_vpll_gpll_cpll_p, 0, + COMPOSITE(DCLK_VOP2, "dclk_vop2", hpll_vpll_gpll_cpll_p, CLK_SET_RATE_NO_REPARENT, RK3568_CLKSEL_CON(41), 10, 2, MFLAGS, 0, 8, DFLAGS, RK3568_CLKGATE_CON(20), 12, GFLAGS), GATE(CLK_VOP_PWM, "clk_vop_pwm", "xin24m", 0, @@ -1562,7 +1568,7 @@ static struct rockchip_clk_branch rk3568_clk_pmu_branches[] __initdata = { RK3568_PMU_CLKGATE_CON(2), 14, GFLAGS), GATE(XIN_OSC0_EDPPHY_G, "xin_osc0_edpphy_g", "xin24m", 0, RK3568_PMU_CLKGATE_CON(2), 15, GFLAGS), - MUX(CLK_HDMI_REF, "clk_hdmi_ref", clk_hdmi_ref_p, 0, + MUX(CLK_HDMI_REF, "clk_hdmi_ref", clk_hdmi_ref_p, CLK_SET_RATE_PARENT, RK3568_PMU_CLKSEL_CON(8), 7, 1, MFLAGS), }; @@ -1697,14 +1703,12 @@ static const struct of_device_id clk_rk3568_match_table[] = { static int __init clk_rk3568_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - const struct of_device_id *match; const struct clk_rk3568_inits *init_data; - match = of_match_device(clk_rk3568_match_table, &pdev->dev); - if (!match || !match->data) + init_data = (struct clk_rk3568_inits *)of_device_get_match_data(&pdev->dev); + if (!init_data) return -EINVAL; - init_data = match->data; if (init_data->inits) init_data->inits(np); diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index b7be7e11b0df..bb8a844309bf 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -180,6 +180,7 @@ static void rockchip_fractional_approximation(struct clk_hw *hw, unsigned long rate, unsigned long *parent_rate, unsigned long *m, unsigned long *n) { + struct clk_fractional_divider *fd = to_clk_fd(hw); unsigned long p_rate, p_parent_rate; struct clk_hw *p_parent; @@ -190,6 +191,8 @@ static void rockchip_fractional_approximation(struct clk_hw *hw, *parent_rate = p_parent_rate; } + fd->flags |= CLK_FRAC_DIVIDER_POWER_OF_TWO_PS; + clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n); } diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c index 32567795765f..3930d922efb4 100644 --- a/drivers/clk/socfpga/clk-gate-s10.c +++ b/drivers/clk/socfpga/clk-gate-s10.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017, Intel Corporation */ diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c index cbabde2b476b..f5c1ca42b668 100644 --- a/drivers/clk/socfpga/clk-periph-s10.c +++ b/drivers/clk/socfpga/clk-periph-s10.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017, Intel Corporation */ diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c index e444e4a0ee53..1d82737befd3 100644 --- a/drivers/clk/socfpga/clk-pll-s10.c +++ b/drivers/clk/socfpga/clk-pll-s10.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017, Intel Corporation */ diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index 4e508a844b3d..9b2e0275fbf7 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2017, Intel Corporation */ diff --git a/drivers/clk/starfive/Kconfig b/drivers/clk/starfive/Kconfig index c0fa9d5e641f..003bd2d56ce7 100644 --- a/drivers/clk/starfive/Kconfig +++ b/drivers/clk/starfive/Kconfig @@ -7,3 +7,11 @@ config CLK_STARFIVE_JH7100 help Say yes here to support the clock controller on the StarFive JH7100 SoC. + +config CLK_STARFIVE_JH7100_AUDIO + tristate "StarFive JH7100 audio clock support" + depends on CLK_STARFIVE_JH7100 + default m if SOC_STARFIVE + help + Say Y or M here to support the audio clocks on the StarFive JH7100 + SoC. diff --git a/drivers/clk/starfive/Makefile b/drivers/clk/starfive/Makefile index 09759cc73530..0fa8ecb9ec1c 100644 --- a/drivers/clk/starfive/Makefile +++ b/drivers/clk/starfive/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 # StarFive Clock obj-$(CONFIG_CLK_STARFIVE_JH7100) += clk-starfive-jh7100.o +obj-$(CONFIG_CLK_STARFIVE_JH7100_AUDIO) += clk-starfive-jh7100-audio.o diff --git a/drivers/clk/starfive/clk-starfive-jh7100-audio.c b/drivers/clk/starfive/clk-starfive-jh7100-audio.c new file mode 100644 index 000000000000..8473a65e219b --- /dev/null +++ b/drivers/clk/starfive/clk-starfive-jh7100-audio.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * StarFive JH7100 Audio Clock Driver + * + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk> + */ + +#include <linux/bits.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include <dt-bindings/clock/starfive-jh7100-audio.h> + +#include "clk-starfive-jh7100.h" + +/* external clocks */ +#define JH7100_AUDCLK_AUDIO_SRC (JH7100_AUDCLK_END + 0) +#define JH7100_AUDCLK_AUDIO_12288 (JH7100_AUDCLK_END + 1) +#define JH7100_AUDCLK_DOM7AHB_BUS (JH7100_AUDCLK_END + 2) +#define JH7100_AUDCLK_I2SADC_BCLK_IOPAD (JH7100_AUDCLK_END + 3) +#define JH7100_AUDCLK_I2SADC_LRCLK_IOPAD (JH7100_AUDCLK_END + 4) +#define JH7100_AUDCLK_I2SDAC_BCLK_IOPAD (JH7100_AUDCLK_END + 5) +#define JH7100_AUDCLK_I2SDAC_LRCLK_IOPAD (JH7100_AUDCLK_END + 6) +#define JH7100_AUDCLK_VAD_INTMEM (JH7100_AUDCLK_END + 7) + +static const struct jh7100_clk_data jh7100_audclk_data[] = { + JH7100__GMD(JH7100_AUDCLK_ADC_MCLK, "adc_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), + JH7100__GMD(JH7100_AUDCLK_I2S1_MCLK, "i2s1_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), + JH7100_GATE(JH7100_AUDCLK_I2SADC_APB, "i2sadc_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100_MDIV(JH7100_AUDCLK_I2SADC_BCLK, "i2sadc_bclk", 31, 2, + JH7100_AUDCLK_ADC_MCLK, + JH7100_AUDCLK_I2SADC_BCLK_IOPAD), + JH7100__INV(JH7100_AUDCLK_I2SADC_BCLK_N, "i2sadc_bclk_n", JH7100_AUDCLK_I2SADC_BCLK), + JH7100_MDIV(JH7100_AUDCLK_I2SADC_LRCLK, "i2sadc_lrclk", 63, 3, + JH7100_AUDCLK_I2SADC_BCLK_N, + JH7100_AUDCLK_I2SADC_LRCLK_IOPAD, + JH7100_AUDCLK_I2SADC_BCLK), + JH7100_GATE(JH7100_AUDCLK_PDM_APB, "pdm_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100__GMD(JH7100_AUDCLK_PDM_MCLK, "pdm_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), + JH7100_GATE(JH7100_AUDCLK_I2SVAD_APB, "i2svad_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100__GMD(JH7100_AUDCLK_SPDIF, "spdif", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), + JH7100_GATE(JH7100_AUDCLK_SPDIF_APB, "spdif_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100_GATE(JH7100_AUDCLK_PWMDAC_APB, "pwmdac_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100__GMD(JH7100_AUDCLK_DAC_MCLK, "dac_mclk", 0, 15, 2, + JH7100_AUDCLK_AUDIO_SRC, + JH7100_AUDCLK_AUDIO_12288), + JH7100_GATE(JH7100_AUDCLK_I2SDAC_APB, "i2sdac_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100_MDIV(JH7100_AUDCLK_I2SDAC_BCLK, "i2sdac_bclk", 31, 2, + JH7100_AUDCLK_DAC_MCLK, + JH7100_AUDCLK_I2SDAC_BCLK_IOPAD), + JH7100__INV(JH7100_AUDCLK_I2SDAC_BCLK_N, "i2sdac_bclk_n", JH7100_AUDCLK_I2SDAC_BCLK), + JH7100_MDIV(JH7100_AUDCLK_I2SDAC_LRCLK, "i2sdac_lrclk", 31, 2, + JH7100_AUDCLK_I2S1_MCLK, + JH7100_AUDCLK_I2SDAC_BCLK_IOPAD), + JH7100_GATE(JH7100_AUDCLK_I2S1_APB, "i2s1_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100_MDIV(JH7100_AUDCLK_I2S1_BCLK, "i2s1_bclk", 31, 2, + JH7100_AUDCLK_I2S1_MCLK, + JH7100_AUDCLK_I2SDAC_BCLK_IOPAD), + JH7100__INV(JH7100_AUDCLK_I2S1_BCLK_N, "i2s1_bclk_n", JH7100_AUDCLK_I2S1_BCLK), + JH7100_MDIV(JH7100_AUDCLK_I2S1_LRCLK, "i2s1_lrclk", 63, 3, + JH7100_AUDCLK_I2S1_BCLK_N, + JH7100_AUDCLK_I2SDAC_LRCLK_IOPAD), + JH7100_GATE(JH7100_AUDCLK_I2SDAC16K_APB, "i2s1dac16k_apb", 0, JH7100_AUDCLK_APB0_BUS), + JH7100__DIV(JH7100_AUDCLK_APB0_BUS, "apb0_bus", 8, JH7100_AUDCLK_DOM7AHB_BUS), + JH7100_GATE(JH7100_AUDCLK_DMA1P_AHB, "dma1p_ahb", 0, JH7100_AUDCLK_DOM7AHB_BUS), + JH7100_GATE(JH7100_AUDCLK_USB_APB, "usb_apb", CLK_IGNORE_UNUSED, JH7100_AUDCLK_APB_EN), + JH7100_GDIV(JH7100_AUDCLK_USB_LPM, "usb_lpm", CLK_IGNORE_UNUSED, 4, JH7100_AUDCLK_USB_APB), + JH7100_GDIV(JH7100_AUDCLK_USB_STB, "usb_stb", CLK_IGNORE_UNUSED, 3, JH7100_AUDCLK_USB_APB), + JH7100__DIV(JH7100_AUDCLK_APB_EN, "apb_en", 8, JH7100_AUDCLK_DOM7AHB_BUS), + JH7100__MUX(JH7100_AUDCLK_VAD_MEM, "vad_mem", 2, + JH7100_AUDCLK_VAD_INTMEM, + JH7100_AUDCLK_AUDIO_12288), +}; + +static struct clk_hw *jh7100_audclk_get(struct of_phandle_args *clkspec, void *data) +{ + struct jh7100_clk_priv *priv = data; + unsigned int idx = clkspec->args[0]; + + if (idx < JH7100_AUDCLK_END) + return &priv->reg[idx].hw; + + return ERR_PTR(-EINVAL); +} + +static int jh7100_audclk_probe(struct platform_device *pdev) +{ + struct jh7100_clk_priv *priv; + unsigned int idx; + int ret; + + priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg, JH7100_AUDCLK_END), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->rmw_lock); + priv->dev = &pdev->dev; + priv->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + for (idx = 0; idx < JH7100_AUDCLK_END; idx++) { + u32 max = jh7100_audclk_data[idx].max; + struct clk_parent_data parents[4] = {}; + struct clk_init_data init = { + .name = jh7100_audclk_data[idx].name, + .ops = starfive_jh7100_clk_ops(max), + .parent_data = parents, + .num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1, + .flags = jh7100_audclk_data[idx].flags, + }; + struct jh7100_clk *clk = &priv->reg[idx]; + unsigned int i; + + for (i = 0; i < init.num_parents; i++) { + unsigned int pidx = jh7100_audclk_data[idx].parents[i]; + + if (pidx < JH7100_AUDCLK_END) + parents[i].hw = &priv->reg[pidx].hw; + else if (pidx == JH7100_AUDCLK_AUDIO_SRC) + parents[i].fw_name = "audio_src"; + else if (pidx == JH7100_AUDCLK_AUDIO_12288) + parents[i].fw_name = "audio_12288"; + else if (pidx == JH7100_AUDCLK_DOM7AHB_BUS) + parents[i].fw_name = "dom7ahb_bus"; + } + + clk->hw.init = &init; + clk->idx = idx; + clk->max_div = max & JH7100_CLK_DIV_MASK; + + ret = devm_clk_hw_register(priv->dev, &clk->hw); + if (ret) + return ret; + } + + return devm_of_clk_add_hw_provider(priv->dev, jh7100_audclk_get, priv); +} + +static const struct of_device_id jh7100_audclk_match[] = { + { .compatible = "starfive,jh7100-audclk" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, jh7100_audclk_match); + +static struct platform_driver jh7100_audclk_driver = { + .probe = jh7100_audclk_probe, + .driver = { + .name = "clk-starfive-jh7100-audio", + .of_match_table = jh7100_audclk_match, + }, +}; +module_platform_driver(jh7100_audclk_driver); + +MODULE_AUTHOR("Emil Renner Berthing"); +MODULE_DESCRIPTION("StarFive JH7100 audio clock driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/starfive/clk-starfive-jh7100.c b/drivers/clk/starfive/clk-starfive-jh7100.c index 25d31afa0f87..691aeebc7092 100644 --- a/drivers/clk/starfive/clk-starfive-jh7100.c +++ b/drivers/clk/starfive/clk-starfive-jh7100.c @@ -20,69 +20,15 @@ #include <dt-bindings/clock/starfive-jh7100.h> +#include "clk-starfive-jh7100.h" + /* external clocks */ #define JH7100_CLK_OSC_SYS (JH7100_CLK_END + 0) #define JH7100_CLK_OSC_AUD (JH7100_CLK_END + 1) #define JH7100_CLK_GMAC_RMII_REF (JH7100_CLK_END + 2) #define JH7100_CLK_GMAC_GR_MII_RX (JH7100_CLK_END + 3) -/* register fields */ -#define JH7100_CLK_ENABLE BIT(31) -#define JH7100_CLK_INVERT BIT(30) -#define JH7100_CLK_MUX_MASK GENMASK(27, 24) -#define JH7100_CLK_MUX_SHIFT 24 -#define JH7100_CLK_DIV_MASK GENMASK(23, 0) - -/* clock data */ -#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = { \ - .name = _name, \ - .flags = CLK_SET_RATE_PARENT | (_flags), \ - .max = JH7100_CLK_ENABLE, \ - .parents = { [0] = _parent }, \ -} - -#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = { \ - .name = _name, \ - .flags = 0, \ - .max = _max, \ - .parents = { [0] = _parent }, \ -} - -#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = { \ - .name = _name, \ - .flags = _flags, \ - .max = JH7100_CLK_ENABLE | (_max), \ - .parents = { [0] = _parent }, \ -} - -#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = { \ - .name = _name, \ - .flags = 0, \ - .max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT, \ - .parents = { __VA_ARGS__ }, \ -} - -#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = { \ - .name = _name, \ - .flags = _flags, \ - .max = JH7100_CLK_ENABLE | \ - (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT), \ - .parents = { __VA_ARGS__ }, \ -} - -#define JH7100__INV(_idx, _name, _parent) [_idx] = { \ - .name = _name, \ - .flags = CLK_SET_RATE_PARENT, \ - .max = JH7100_CLK_INVERT, \ - .parents = { [0] = _parent }, \ -} - -static const struct { - const char *name; - unsigned long flags; - u32 max; - u8 parents[4]; -} jh7100_clk_data[] __initconst = { +static const struct jh7100_clk_data jh7100_clk_data[] __initconst = { JH7100__MUX(JH7100_CLK_CPUNDBUS_ROOT, "cpundbus_root", 4, JH7100_CLK_OSC_SYS, JH7100_CLK_PLL0_OUT, @@ -225,7 +171,7 @@ static const struct { JH7100__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 2, JH7100_CLK_OSC_SYS, JH7100_CLK_USBPHY_PLLDIV25M), - JH7100__DIV(JH7100_CLK_AUDIO_DIV, "audio_div", 131072, JH7100_CLK_AUDIO_ROOT), + JH7100_FDIV(JH7100_CLK_AUDIO_DIV, "audio_div", JH7100_CLK_AUDIO_ROOT), JH7100_GATE(JH7100_CLK_AUDIO_SRC, "audio_src", 0, JH7100_CLK_AUDIO_DIV), JH7100_GATE(JH7100_CLK_AUDIO_12288, "audio_12288", 0, JH7100_CLK_OSC_AUD), JH7100_GDIV(JH7100_CLK_VIN_SRC, "vin_src", 0, 4, JH7100_CLK_VIN_ROOT), @@ -323,21 +269,6 @@ static const struct { JH7100_GATE(JH7100_CLK_SYSERR_APB, "syserr_apb", 0, JH7100_CLK_APB2_BUS), }; -struct jh7100_clk { - struct clk_hw hw; - unsigned int idx; - unsigned int max_div; -}; - -struct jh7100_clk_priv { - /* protect clk enable and set rate/parent from happening at the same time */ - spinlock_t rmw_lock; - struct device *dev; - void __iomem *base; - struct clk_hw *pll[3]; - struct jh7100_clk reg[JH7100_CLK_PLL0_OUT]; -}; - static struct jh7100_clk *jh7100_clk_from(struct clk_hw *hw) { return container_of(hw, struct jh7100_clk, hw); @@ -399,22 +330,13 @@ static unsigned long jh7100_clk_recalc_rate(struct clk_hw *hw, return div ? parent_rate / div : 0; } -static unsigned long jh7100_clk_bestdiv(struct jh7100_clk *clk, - unsigned long rate, unsigned long parent) -{ - unsigned long max = clk->max_div; - unsigned long div = DIV_ROUND_UP(parent, rate); - - return min(div, max); -} - static int jh7100_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { struct jh7100_clk *clk = jh7100_clk_from(hw); unsigned long parent = req->best_parent_rate; unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); - unsigned long div = jh7100_clk_bestdiv(clk, rate, parent); + unsigned long div = min_t(unsigned long, DIV_ROUND_UP(parent, rate), clk->max_div); unsigned long result = parent / div; /* @@ -442,12 +364,56 @@ static int jh7100_clk_set_rate(struct clk_hw *hw, unsigned long parent_rate) { struct jh7100_clk *clk = jh7100_clk_from(hw); - unsigned long div = jh7100_clk_bestdiv(clk, rate, parent_rate); + unsigned long div = clamp(DIV_ROUND_CLOSEST(parent_rate, rate), + 1UL, (unsigned long)clk->max_div); jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, div); return 0; } +static unsigned long jh7100_clk_frac_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct jh7100_clk *clk = jh7100_clk_from(hw); + u32 reg = jh7100_clk_reg_get(clk); + unsigned long div100 = 100 * (reg & JH7100_CLK_INT_MASK) + + ((reg & JH7100_CLK_FRAC_MASK) >> JH7100_CLK_FRAC_SHIFT); + + return (div100 >= JH7100_CLK_FRAC_MIN) ? 100 * parent_rate / div100 : 0; +} + +static int jh7100_clk_frac_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long parent100 = 100 * req->best_parent_rate; + unsigned long rate = clamp(req->rate, req->min_rate, req->max_rate); + unsigned long div100 = clamp(DIV_ROUND_CLOSEST(parent100, rate), + JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); + unsigned long result = parent100 / div100; + + /* clamp the result as in jh7100_clk_determine_rate() above */ + if (result > req->max_rate && div100 < JH7100_CLK_FRAC_MAX) + result = parent100 / (div100 + 1); + if (result < req->min_rate && div100 > JH7100_CLK_FRAC_MIN) + result = parent100 / (div100 - 1); + + req->rate = result; + return 0; +} + +static int jh7100_clk_frac_set_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long parent_rate) +{ + struct jh7100_clk *clk = jh7100_clk_from(hw); + unsigned long div100 = clamp(DIV_ROUND_CLOSEST(100 * parent_rate, rate), + JH7100_CLK_FRAC_MIN, JH7100_CLK_FRAC_MAX); + u32 value = ((div100 % 100) << JH7100_CLK_FRAC_SHIFT) | (div100 / 100); + + jh7100_clk_reg_rmw(clk, JH7100_CLK_DIV_MASK, value); + return 0; +} + static u8 jh7100_clk_get_parent(struct clk_hw *hw) { struct jh7100_clk *clk = jh7100_clk_from(hw); @@ -534,6 +500,13 @@ static const struct clk_ops jh7100_clk_div_ops = { .debug_init = jh7100_clk_debug_init, }; +static const struct clk_ops jh7100_clk_fdiv_ops = { + .recalc_rate = jh7100_clk_frac_recalc_rate, + .determine_rate = jh7100_clk_frac_determine_rate, + .set_rate = jh7100_clk_frac_set_rate, + .debug_init = jh7100_clk_debug_init, +}; + static const struct clk_ops jh7100_clk_gdiv_ops = { .enable = jh7100_clk_enable, .disable = jh7100_clk_disable, @@ -561,17 +534,45 @@ static const struct clk_ops jh7100_clk_gmux_ops = { .debug_init = jh7100_clk_debug_init, }; +static const struct clk_ops jh7100_clk_mdiv_ops = { + .recalc_rate = jh7100_clk_recalc_rate, + .determine_rate = jh7100_clk_determine_rate, + .get_parent = jh7100_clk_get_parent, + .set_parent = jh7100_clk_set_parent, + .set_rate = jh7100_clk_set_rate, + .debug_init = jh7100_clk_debug_init, +}; + +static const struct clk_ops jh7100_clk_gmd_ops = { + .enable = jh7100_clk_enable, + .disable = jh7100_clk_disable, + .is_enabled = jh7100_clk_is_enabled, + .recalc_rate = jh7100_clk_recalc_rate, + .determine_rate = jh7100_clk_determine_rate, + .get_parent = jh7100_clk_get_parent, + .set_parent = jh7100_clk_set_parent, + .set_rate = jh7100_clk_set_rate, + .debug_init = jh7100_clk_debug_init, +}; + static const struct clk_ops jh7100_clk_inv_ops = { .get_phase = jh7100_clk_get_phase, .set_phase = jh7100_clk_set_phase, .debug_init = jh7100_clk_debug_init, }; -static const struct clk_ops *__init jh7100_clk_ops(u32 max) +const struct clk_ops *starfive_jh7100_clk_ops(u32 max) { if (max & JH7100_CLK_DIV_MASK) { + if (max & JH7100_CLK_MUX_MASK) { + if (max & JH7100_CLK_ENABLE) + return &jh7100_clk_gmd_ops; + return &jh7100_clk_mdiv_ops; + } if (max & JH7100_CLK_ENABLE) return &jh7100_clk_gdiv_ops; + if (max == JH7100_CLK_FRAC_MAX) + return &jh7100_clk_fdiv_ops; return &jh7100_clk_div_ops; } @@ -586,6 +587,7 @@ static const struct clk_ops *__init jh7100_clk_ops(u32 max) return &jh7100_clk_inv_ops; } +EXPORT_SYMBOL_GPL(starfive_jh7100_clk_ops); static struct clk_hw *jh7100_clk_get(struct of_phandle_args *clkspec, void *data) { @@ -607,7 +609,7 @@ static int __init clk_starfive_jh7100_probe(struct platform_device *pdev) unsigned int idx; int ret; - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, struct_size(priv, reg, JH7100_CLK_PLL0_OUT), GFP_KERNEL); if (!priv) return -ENOMEM; @@ -637,7 +639,7 @@ static int __init clk_starfive_jh7100_probe(struct platform_device *pdev) struct clk_parent_data parents[4] = {}; struct clk_init_data init = { .name = jh7100_clk_data[idx].name, - .ops = jh7100_clk_ops(max), + .ops = starfive_jh7100_clk_ops(max), .parent_data = parents, .num_parents = ((max & JH7100_CLK_MUX_MASK) >> JH7100_CLK_MUX_SHIFT) + 1, .flags = jh7100_clk_data[idx].flags, diff --git a/drivers/clk/starfive/clk-starfive-jh7100.h b/drivers/clk/starfive/clk-starfive-jh7100.h new file mode 100644 index 000000000000..f116be5740a5 --- /dev/null +++ b/drivers/clk/starfive/clk-starfive-jh7100.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __CLK_STARFIVE_JH7100_H +#define __CLK_STARFIVE_JH7100_H + +#include <linux/bits.h> +#include <linux/clk-provider.h> + +/* register fields */ +#define JH7100_CLK_ENABLE BIT(31) +#define JH7100_CLK_INVERT BIT(30) +#define JH7100_CLK_MUX_MASK GENMASK(27, 24) +#define JH7100_CLK_MUX_SHIFT 24 +#define JH7100_CLK_DIV_MASK GENMASK(23, 0) +#define JH7100_CLK_FRAC_MASK GENMASK(15, 8) +#define JH7100_CLK_FRAC_SHIFT 8 +#define JH7100_CLK_INT_MASK GENMASK(7, 0) + +/* fractional divider min/max */ +#define JH7100_CLK_FRAC_MIN 100UL +#define JH7100_CLK_FRAC_MAX 25599UL + +/* clock data */ +struct jh7100_clk_data { + const char *name; + unsigned long flags; + u32 max; + u8 parents[4]; +}; + +#define JH7100_GATE(_idx, _name, _flags, _parent) [_idx] = { \ + .name = _name, \ + .flags = CLK_SET_RATE_PARENT | (_flags), \ + .max = JH7100_CLK_ENABLE, \ + .parents = { [0] = _parent }, \ +} + +#define JH7100__DIV(_idx, _name, _max, _parent) [_idx] = { \ + .name = _name, \ + .flags = 0, \ + .max = _max, \ + .parents = { [0] = _parent }, \ +} + +#define JH7100_GDIV(_idx, _name, _flags, _max, _parent) [_idx] = { \ + .name = _name, \ + .flags = _flags, \ + .max = JH7100_CLK_ENABLE | (_max), \ + .parents = { [0] = _parent }, \ +} + +#define JH7100_FDIV(_idx, _name, _parent) [_idx] = { \ + .name = _name, \ + .flags = 0, \ + .max = JH7100_CLK_FRAC_MAX, \ + .parents = { [0] = _parent }, \ +} + +#define JH7100__MUX(_idx, _name, _nparents, ...) [_idx] = { \ + .name = _name, \ + .flags = 0, \ + .max = ((_nparents) - 1) << JH7100_CLK_MUX_SHIFT, \ + .parents = { __VA_ARGS__ }, \ +} + +#define JH7100_GMUX(_idx, _name, _flags, _nparents, ...) [_idx] = { \ + .name = _name, \ + .flags = _flags, \ + .max = JH7100_CLK_ENABLE | \ + (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT), \ + .parents = { __VA_ARGS__ }, \ +} + +#define JH7100_MDIV(_idx, _name, _max, _nparents, ...) [_idx] = { \ + .name = _name, \ + .flags = 0, \ + .max = (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ + .parents = { __VA_ARGS__ }, \ +} + +#define JH7100__GMD(_idx, _name, _flags, _max, _nparents, ...) [_idx] = { \ + .name = _name, \ + .flags = _flags, \ + .max = JH7100_CLK_ENABLE | \ + (((_nparents) - 1) << JH7100_CLK_MUX_SHIFT) | (_max), \ + .parents = { __VA_ARGS__ }, \ +} + +#define JH7100__INV(_idx, _name, _parent) [_idx] = { \ + .name = _name, \ + .flags = CLK_SET_RATE_PARENT, \ + .max = JH7100_CLK_INVERT, \ + .parents = { [0] = _parent }, \ +} + +struct jh7100_clk { + struct clk_hw hw; + unsigned int idx; + unsigned int max_div; +}; + +struct jh7100_clk_priv { + /* protect clk enable and set rate/parent from happening at the same time */ + spinlock_t rmw_lock; + struct device *dev; + void __iomem *base; + struct clk_hw *pll[3]; + struct jh7100_clk reg[]; +}; + +const struct clk_ops *starfive_jh7100_clk_ops(u32 max); + +#endif diff --git a/drivers/clk/tegra/clk-tegra124-emc.c b/drivers/clk/tegra/clk-tegra124-emc.c index 74c1d894cca8..219c80653dbd 100644 --- a/drivers/clk/tegra/clk-tegra124-emc.c +++ b/drivers/clk/tegra/clk-tegra124-emc.c @@ -198,6 +198,7 @@ static struct tegra_emc *emc_ensure_emc_driver(struct tegra_clk_emc *tegra) tegra->emc = platform_get_drvdata(pdev); if (!tegra->emc) { + put_device(&pdev->dev); pr_err("%s: cannot find EMC driver\n", __func__); return NULL; } diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index 792137a06069..064066e9e85b 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -604,7 +604,7 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node) /* * The code below can be removed when all clkctrl nodes use domain - * specific compatible proprerty and standard clock node naming + * specific compatible property and standard clock node naming */ if (legacy_naming) { provider->clkdm_name = kasprintf(GFP_KERNEL, "%pOFnxxx", node->parent); diff --git a/drivers/clk/zynq/clkc.c b/drivers/clk/zynq/clkc.c index 204b83d911b9..7bdeaff2bfd6 100644 --- a/drivers/clk/zynq/clkc.c +++ b/drivers/clk/zynq/clkc.c @@ -349,19 +349,20 @@ static void __init zynq_clk_setup(struct device_node *np) /* Peripheral clocks */ for (i = fclk0; i <= fclk3; i++) { int enable = !!(fclk_enable & BIT(i - fclk0)); + zynq_clk_register_fclk(i, clk_output_name[i], SLCR_FPGA0_CLK_CTRL + 0x10 * (i - fclk0), periph_parents, enable); } - zynq_clk_register_periph_clk(lqspi, 0, clk_output_name[lqspi], NULL, - SLCR_LQSPI_CLK_CTRL, periph_parents, 0); + zynq_clk_register_periph_clk(lqspi, clk_max, clk_output_name[lqspi], NULL, + SLCR_LQSPI_CLK_CTRL, periph_parents, 0); - zynq_clk_register_periph_clk(smc, 0, clk_output_name[smc], NULL, - SLCR_SMC_CLK_CTRL, periph_parents, 0); + zynq_clk_register_periph_clk(smc, clk_max, clk_output_name[smc], NULL, + SLCR_SMC_CLK_CTRL, periph_parents, 0); - zynq_clk_register_periph_clk(pcap, 0, clk_output_name[pcap], NULL, - SLCR_PCAP_CLK_CTRL, periph_parents, 0); + zynq_clk_register_periph_clk(pcap, clk_max, clk_output_name[pcap], NULL, + SLCR_PCAP_CLK_CTRL, periph_parents, 0); zynq_clk_register_periph_clk(sdio0, sdio1, clk_output_name[sdio0], clk_output_name[sdio1], SLCR_SDIO_CLK_CTRL, diff --git a/drivers/clk/zynqmp/clk-gate-zynqmp.c b/drivers/clk/zynqmp/clk-gate-zynqmp.c index 565ed67a0430..b89e55737198 100644 --- a/drivers/clk/zynqmp/clk-gate-zynqmp.c +++ b/drivers/clk/zynqmp/clk-gate-zynqmp.c @@ -41,8 +41,8 @@ static int zynqmp_clk_gate_enable(struct clk_hw *hw) ret = zynqmp_pm_clock_enable(clk_id); if (ret) - pr_warn_once("%s() clock enabled failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() clock enable failed for %s (id %d), ret = %d\n", + __func__, clk_name, clk_id, ret); return ret; } @@ -61,8 +61,8 @@ static void zynqmp_clk_gate_disable(struct clk_hw *hw) ret = zynqmp_pm_clock_disable(clk_id); if (ret) - pr_warn_once("%s() clock disable failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() clock disable failed for %s (id %d), ret = %d\n", + __func__, clk_name, clk_id, ret); } /** @@ -80,8 +80,8 @@ static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw) ret = zynqmp_pm_clock_getstate(clk_id, &state); if (ret) { - pr_warn_once("%s() clock get state failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() clock get state failed for %s, ret = %d\n", + __func__, clk_name, ret); return -EIO; } diff --git a/drivers/clk/zynqmp/clk-mux-zynqmp.c b/drivers/clk/zynqmp/clk-mux-zynqmp.c index 17afce594f28..60359333f26d 100644 --- a/drivers/clk/zynqmp/clk-mux-zynqmp.c +++ b/drivers/clk/zynqmp/clk-mux-zynqmp.c @@ -51,8 +51,8 @@ static u8 zynqmp_clk_mux_get_parent(struct clk_hw *hw) ret = zynqmp_pm_clock_getparent(clk_id, &val); if (ret) { - pr_warn_once("%s() getparent failed for clock: %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() getparent failed for clock: %s, ret = %d\n", + __func__, clk_name, ret); /* * clk_core_get_parent_by_index() takes num_parents as incorrect * index which is exactly what I want to return here @@ -80,8 +80,8 @@ static int zynqmp_clk_mux_set_parent(struct clk_hw *hw, u8 index) ret = zynqmp_pm_clock_setparent(clk_id, index); if (ret) - pr_warn_once("%s() set parent failed for clock: %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() set parent failed for clock: %s, ret = %d\n", + __func__, clk_name, ret); return ret; } diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index cb49281f9cf9..422ea79907dd 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -89,8 +89,8 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, ret = zynqmp_pm_clock_getdivider(clk_id, &div); if (ret) - pr_warn_once("%s() get divider failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() get divider failed for %s, ret = %d\n", + __func__, clk_name, ret); if (div_type == TYPE_DIV1) value = div & 0xFFFF; @@ -177,8 +177,8 @@ static long zynqmp_clk_divider_round_rate(struct clk_hw *hw, ret = zynqmp_pm_clock_getdivider(clk_id, &bestdiv); if (ret) - pr_warn_once("%s() get divider failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() get divider failed for %s, ret = %d\n", + __func__, clk_name, ret); if (div_type == TYPE_DIV1) bestdiv = bestdiv & 0xFFFF; else @@ -244,8 +244,8 @@ static int zynqmp_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, ret = zynqmp_pm_clock_setdivider(clk_id, div); if (ret) - pr_warn_once("%s() set divider failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() set divider failed for %s, ret = %d\n", + __func__, clk_name, ret); return ret; } diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index 036e4ff64a2f..91a6b4cc910e 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -56,8 +56,8 @@ static inline enum pll_mode zynqmp_pll_get_mode(struct clk_hw *hw) ret = zynqmp_pm_get_pll_frac_mode(clk_id, ret_payload); if (ret) { - pr_warn_once("%s() PLL get frac mode failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() PLL get frac mode failed for %s, ret = %d\n", + __func__, clk_name, ret); return PLL_MODE_ERROR; } @@ -84,8 +84,8 @@ static inline void zynqmp_pll_set_mode(struct clk_hw *hw, bool on) ret = zynqmp_pm_set_pll_frac_mode(clk_id, mode); if (ret) - pr_warn_once("%s() PLL set frac mode failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() PLL set frac mode failed for %s, ret = %d\n", + __func__, clk_name, ret); else clk->set_pll_mode = true; } @@ -145,8 +145,8 @@ static unsigned long zynqmp_pll_recalc_rate(struct clk_hw *hw, ret = zynqmp_pm_clock_getdivider(clk_id, &fbdiv); if (ret) { - pr_warn_once("%s() get divider failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() get divider failed for %s, ret = %d\n", + __func__, clk_name, ret); return 0ul; } @@ -200,8 +200,8 @@ static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate, WARN(1, "More than allowed devices are using the %s, which is forbidden\n", clk_name); else if (ret) - pr_warn_once("%s() set divider failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() set divider failed for %s, ret = %d\n", + __func__, clk_name, ret); zynqmp_pm_set_pll_frac_data(clk_id, f); return rate + frac; @@ -211,8 +211,8 @@ static int zynqmp_pll_set_rate(struct clk_hw *hw, unsigned long rate, fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); ret = zynqmp_pm_clock_setdivider(clk_id, fbdiv); if (ret) - pr_warn_once("%s() set divider failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() set divider failed for %s, ret = %d\n", + __func__, clk_name, ret); return parent_rate * fbdiv; } @@ -233,8 +233,8 @@ static int zynqmp_pll_is_enabled(struct clk_hw *hw) ret = zynqmp_pm_clock_getstate(clk_id, &state); if (ret) { - pr_warn_once("%s() clock get state failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() clock get state failed for %s, ret = %d\n", + __func__, clk_name, ret); return -EIO; } @@ -265,8 +265,8 @@ static int zynqmp_pll_enable(struct clk_hw *hw) ret = zynqmp_pm_clock_enable(clk_id); if (ret) - pr_warn_once("%s() clock enable failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() clock enable failed for %s, ret = %d\n", + __func__, clk_name, ret); return ret; } @@ -287,8 +287,8 @@ static void zynqmp_pll_disable(struct clk_hw *hw) ret = zynqmp_pm_clock_disable(clk_id); if (ret) - pr_warn_once("%s() clock disable failed for %s, ret = %d\n", - __func__, clk_name, ret); + pr_debug("%s() clock disable failed for %s, ret = %d\n", + __func__, clk_name, ret); } static const struct clk_ops zynqmp_pll_ops = { diff --git a/include/dt-bindings/clock/at91.h b/include/dt-bindings/clock/at91.h index 98e1b2ab6403..3e3972a814c1 100644 --- a/include/dt-bindings/clock/at91.h +++ b/include/dt-bindings/clock/at91.h @@ -24,6 +24,7 @@ #define PMC_PLLACK 7 #define PMC_PLLBCK 8 #define PMC_AUDIOPLLCK 9 +#define PMC_AUDIOPINCK 10 /* SAMA7G5 */ #define PMC_CPUPLL (PMC_MAIN + 1) @@ -35,6 +36,7 @@ #define PMC_AUDIOIOPLL (PMC_MAIN + 7) #define PMC_ETHPLL (PMC_MAIN + 8) #define PMC_CPU (PMC_MAIN + 9) +#define PMC_MCK1 (PMC_MAIN + 10) #ifndef AT91_PMC_MOSCS #define AT91_PMC_MOSCS 0 /* MOSCS Flag */ diff --git a/include/dt-bindings/clock/cirrus,cs2000-cp.h b/include/dt-bindings/clock/cirrus,cs2000-cp.h new file mode 100644 index 000000000000..fe3ac71750a8 --- /dev/null +++ b/include/dt-bindings/clock/cirrus,cs2000-cp.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Copyright (C) 2021 Daniel Mack + */ + +#ifndef __DT_BINDINGS_CS2000CP_CLK_H +#define __DT_BINDINGS_CS2000CP_CLK_H + +#define CS2000CP_AUX_OUTPUT_REF_CLK 0 +#define CS2000CP_AUX_OUTPUT_CLK_IN 1 +#define CS2000CP_AUX_OUTPUT_CLK_OUT 2 +#define CS2000CP_AUX_OUTPUT_PLL_LOCK 3 + +#endif /* __DT_BINDINGS_CS2000CP_CLK_H */ diff --git a/include/dt-bindings/clock/imx93-clock.h b/include/dt-bindings/clock/imx93-clock.h new file mode 100644 index 000000000000..21fda9c5cb5e --- /dev/null +++ b/include/dt-bindings/clock/imx93-clock.h @@ -0,0 +1,201 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR MIT */ +/* + * Copyright 2022 NXP + */ + +#ifndef __DT_BINDINGS_CLOCK_IMX93_CLK_H +#define __DT_BINDINGS_CLOCK_IMX93_CLK_H + +#define IMX93_CLK_DUMMY 0 +#define IMX93_CLK_24M 1 +#define IMX93_CLK_EXT1 2 +#define IMX93_CLK_SYS_PLL_PFD0 3 +#define IMX93_CLK_SYS_PLL_PFD0_DIV2 4 +#define IMX93_CLK_SYS_PLL_PFD1 5 +#define IMX93_CLK_SYS_PLL_PFD1_DIV2 6 +#define IMX93_CLK_SYS_PLL_PFD2 7 +#define IMX93_CLK_SYS_PLL_PFD2_DIV2 8 +#define IMX93_CLK_AUDIO_PLL 9 +#define IMX93_CLK_VIDEO_PLL 10 +#define IMX93_CLK_A55_PERIPH 11 +#define IMX93_CLK_A55_MTR_BUS 12 +#define IMX93_CLK_A55 13 +#define IMX93_CLK_M33 14 +#define IMX93_CLK_BUS_WAKEUP 15 +#define IMX93_CLK_BUS_AON 16 +#define IMX93_CLK_WAKEUP_AXI 17 +#define IMX93_CLK_SWO_TRACE 18 +#define IMX93_CLK_M33_SYSTICK 19 +#define IMX93_CLK_FLEXIO1 20 +#define IMX93_CLK_FLEXIO2 21 +#define IMX93_CLK_LPIT1 22 +#define IMX93_CLK_LPIT2 23 +#define IMX93_CLK_LPTMR1 24 +#define IMX93_CLK_LPTMR2 25 +#define IMX93_CLK_TPM1 26 +#define IMX93_CLK_TPM2 27 +#define IMX93_CLK_TPM3 28 +#define IMX93_CLK_TPM4 29 +#define IMX93_CLK_TPM5 30 +#define IMX93_CLK_TPM6 31 +#define IMX93_CLK_FLEXSPI1 32 +#define IMX93_CLK_CAN1 33 +#define IMX93_CLK_CAN2 34 +#define IMX93_CLK_LPUART1 35 +#define IMX93_CLK_LPUART2 36 +#define IMX93_CLK_LPUART3 37 +#define IMX93_CLK_LPUART4 38 +#define IMX93_CLK_LPUART5 39 +#define IMX93_CLK_LPUART6 40 +#define IMX93_CLK_LPUART7 41 +#define IMX93_CLK_LPUART8 42 +#define IMX93_CLK_LPI2C1 43 +#define IMX93_CLK_LPI2C2 44 +#define IMX93_CLK_LPI2C3 45 +#define IMX93_CLK_LPI2C4 46 +#define IMX93_CLK_LPI2C5 47 +#define IMX93_CLK_LPI2C6 48 +#define IMX93_CLK_LPI2C7 49 +#define IMX93_CLK_LPI2C8 50 +#define IMX93_CLK_LPSPI1 51 +#define IMX93_CLK_LPSPI2 52 +#define IMX93_CLK_LPSPI3 53 +#define IMX93_CLK_LPSPI4 54 +#define IMX93_CLK_LPSPI5 55 +#define IMX93_CLK_LPSPI6 56 +#define IMX93_CLK_LPSPI7 57 +#define IMX93_CLK_LPSPI8 58 +#define IMX93_CLK_I3C1 59 +#define IMX93_CLK_I3C2 60 +#define IMX93_CLK_USDHC1 61 +#define IMX93_CLK_USDHC2 62 +#define IMX93_CLK_USDHC3 63 +#define IMX93_CLK_SAI1 64 +#define IMX93_CLK_SAI2 65 +#define IMX93_CLK_SAI3 66 +#define IMX93_CLK_CCM_CKO1 67 +#define IMX93_CLK_CCM_CKO2 68 +#define IMX93_CLK_CCM_CKO3 69 +#define IMX93_CLK_CCM_CKO4 70 +#define IMX93_CLK_HSIO 71 +#define IMX93_CLK_HSIO_USB_TEST_60M 72 +#define IMX93_CLK_HSIO_ACSCAN_80M 73 +#define IMX93_CLK_HSIO_ACSCAN_480M 74 +#define IMX93_CLK_ML_APB 75 +#define IMX93_CLK_ML 76 +#define IMX93_CLK_MEDIA_AXI 77 +#define IMX93_CLK_MEDIA_APB 78 +#define IMX93_CLK_MEDIA_LDB 79 +#define IMX93_CLK_MEDIA_DISP_PIX 80 +#define IMX93_CLK_CAM_PIX 81 +#define IMX93_CLK_MIPI_TEST_BYTE 82 +#define IMX93_CLK_MIPI_PHY_CFG 83 +#define IMX93_CLK_ADC 84 +#define IMX93_CLK_PDM 85 +#define IMX93_CLK_TSTMR1 86 +#define IMX93_CLK_TSTMR2 87 +#define IMX93_CLK_MQS1 88 +#define IMX93_CLK_MQS2 89 +#define IMX93_CLK_AUDIO_XCVR 90 +#define IMX93_CLK_SPDIF 91 +#define IMX93_CLK_ENET 92 +#define IMX93_CLK_ENET_TIMER1 93 +#define IMX93_CLK_ENET_TIMER2 94 +#define IMX93_CLK_ENET_REF 95 +#define IMX93_CLK_ENET_REF_PHY 96 +#define IMX93_CLK_I3C1_SLOW 97 +#define IMX93_CLK_I3C2_SLOW 98 +#define IMX93_CLK_USB_PHY_BURUNIN 99 +#define IMX93_CLK_PAL_CAME_SCAN 100 +#define IMX93_CLK_A55_GATE 101 +#define IMX93_CLK_CM33_GATE 102 +#define IMX93_CLK_ADC1_GATE 103 +#define IMX93_CLK_WDOG1_GATE 104 +#define IMX93_CLK_WDOG2_GATE 105 +#define IMX93_CLK_WDOG3_GATE 106 +#define IMX93_CLK_WDOG4_GATE 107 +#define IMX93_CLK_WDOG5_GATE 108 +#define IMX93_CLK_SEMA1_GATE 109 +#define IMX93_CLK_SEMA2_GATE 110 +#define IMX93_CLK_MU_A_GATE 111 +#define IMX93_CLK_MU_B_GATE 112 +#define IMX93_CLK_EDMA1_GATE 113 +#define IMX93_CLK_EDMA2_GATE 114 +#define IMX93_CLK_FLEXSPI1_GATE 115 +#define IMX93_CLK_GPIO1_GATE 116 +#define IMX93_CLK_GPIO2_GATE 117 +#define IMX93_CLK_GPIO3_GATE 118 +#define IMX93_CLK_GPIO4_GATE 119 +#define IMX93_CLK_FLEXIO1_GATE 120 +#define IMX93_CLK_FLEXIO2_GATE 121 +#define IMX93_CLK_LPIT1_GATE 122 +#define IMX93_CLK_LPIT2_GATE 123 +#define IMX93_CLK_LPTMR1_GATE 124 +#define IMX93_CLK_LPTMR2_GATE 125 +#define IMX93_CLK_TPM1_GATE 126 +#define IMX93_CLK_TPM2_GATE 127 +#define IMX93_CLK_TPM3_GATE 128 +#define IMX93_CLK_TPM4_GATE 129 +#define IMX93_CLK_TPM5_GATE 130 +#define IMX93_CLK_TPM6_GATE 131 +#define IMX93_CLK_CAN1_GATE 132 +#define IMX93_CLK_CAN2_GATE 133 +#define IMX93_CLK_LPUART1_GATE 134 +#define IMX93_CLK_LPUART2_GATE 135 +#define IMX93_CLK_LPUART3_GATE 136 +#define IMX93_CLK_LPUART4_GATE 137 +#define IMX93_CLK_LPUART5_GATE 138 +#define IMX93_CLK_LPUART6_GATE 139 +#define IMX93_CLK_LPUART7_GATE 140 +#define IMX93_CLK_LPUART8_GATE 141 +#define IMX93_CLK_LPI2C1_GATE 142 +#define IMX93_CLK_LPI2C2_GATE 143 +#define IMX93_CLK_LPI2C3_GATE 144 +#define IMX93_CLK_LPI2C4_GATE 145 +#define IMX93_CLK_LPI2C5_GATE 146 +#define IMX93_CLK_LPI2C6_GATE 147 +#define IMX93_CLK_LPI2C7_GATE 148 +#define IMX93_CLK_LPI2C8_GATE 149 +#define IMX93_CLK_LPSPI1_GATE 150 +#define IMX93_CLK_LPSPI2_GATE 151 +#define IMX93_CLK_LPSPI3_GATE 152 +#define IMX93_CLK_LPSPI4_GATE 153 +#define IMX93_CLK_LPSPI5_GATE 154 +#define IMX93_CLK_LPSPI6_GATE 155 +#define IMX93_CLK_LPSPI7_GATE 156 +#define IMX93_CLK_LPSPI8_GATE 157 +#define IMX93_CLK_I3C1_GATE 158 +#define IMX93_CLK_I3C2_GATE 159 +#define IMX93_CLK_USDHC1_GATE 160 +#define IMX93_CLK_USDHC2_GATE 161 +#define IMX93_CLK_USDHC3_GATE 162 +#define IMX93_CLK_SAI1_GATE 163 +#define IMX93_CLK_SAI2_GATE 164 +#define IMX93_CLK_SAI3_GATE 165 +#define IMX93_CLK_MIPI_CSI_GATE 166 +#define IMX93_CLK_MIPI_DSI_GATE 167 +#define IMX93_CLK_LVDS_GATE 168 +#define IMX93_CLK_LCDIF_GATE 169 +#define IMX93_CLK_PXP_GATE 170 +#define IMX93_CLK_ISI_GATE 171 +#define IMX93_CLK_NIC_MEDIA_GATE 172 +#define IMX93_CLK_USB_CONTROLLER_GATE 173 +#define IMX93_CLK_USB_TEST_60M_GATE 174 +#define IMX93_CLK_HSIO_TROUT_24M_GATE 175 +#define IMX93_CLK_PDM_GATE 176 +#define IMX93_CLK_MQS1_GATE 177 +#define IMX93_CLK_MQS2_GATE 178 +#define IMX93_CLK_AUD_XCVR_GATE 179 +#define IMX93_CLK_SPDIF_GATE 180 +#define IMX93_CLK_HSIO_32K_GATE 181 +#define IMX93_CLK_ENET1_GATE 182 +#define IMX93_CLK_ENET_QOS_GATE 183 +#define IMX93_CLK_SYS_CNT_GATE 184 +#define IMX93_CLK_TSTMR1_GATE 185 +#define IMX93_CLK_TSTMR2_GATE 186 +#define IMX93_CLK_TMC_GATE 187 +#define IMX93_CLK_PMRO_GATE 188 +#define IMX93_CLK_32K 189 +#define IMX93_CLK_END 190 + +#endif diff --git a/include/dt-bindings/clock/imxrt1050-clock.h b/include/dt-bindings/clock/imxrt1050-clock.h new file mode 100644 index 000000000000..93bef0832d16 --- /dev/null +++ b/include/dt-bindings/clock/imxrt1050-clock.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ +/* + * Copyright(C) 2019 + * Author(s): Giulio Benetti <giulio.benetti@benettiengineering.com> + */ + +#ifndef __DT_BINDINGS_CLOCK_IMXRT1050_H +#define __DT_BINDINGS_CLOCK_IMXRT1050_H + +#define IMXRT1050_CLK_DUMMY 0 +#define IMXRT1050_CLK_CKIL 1 +#define IMXRT1050_CLK_CKIH 2 +#define IMXRT1050_CLK_OSC 3 +#define IMXRT1050_CLK_PLL2_PFD0_352M 4 +#define IMXRT1050_CLK_PLL2_PFD1_594M 5 +#define IMXRT1050_CLK_PLL2_PFD2_396M 6 +#define IMXRT1050_CLK_PLL3_PFD0_720M 7 +#define IMXRT1050_CLK_PLL3_PFD1_664_62M 8 +#define IMXRT1050_CLK_PLL3_PFD2_508_24M 9 +#define IMXRT1050_CLK_PLL3_PFD3_454_74M 10 +#define IMXRT1050_CLK_PLL2_198M 11 +#define IMXRT1050_CLK_PLL3_120M 12 +#define IMXRT1050_CLK_PLL3_80M 13 +#define IMXRT1050_CLK_PLL3_60M 14 +#define IMXRT1050_CLK_PLL1_BYPASS 15 +#define IMXRT1050_CLK_PLL2_BYPASS 16 +#define IMXRT1050_CLK_PLL3_BYPASS 17 +#define IMXRT1050_CLK_PLL5_BYPASS 19 +#define IMXRT1050_CLK_PLL1_REF_SEL 20 +#define IMXRT1050_CLK_PLL2_REF_SEL 21 +#define IMXRT1050_CLK_PLL3_REF_SEL 22 +#define IMXRT1050_CLK_PLL5_REF_SEL 23 +#define IMXRT1050_CLK_PRE_PERIPH_SEL 24 +#define IMXRT1050_CLK_PERIPH_SEL 25 +#define IMXRT1050_CLK_SEMC_ALT_SEL 26 +#define IMXRT1050_CLK_SEMC_SEL 27 +#define IMXRT1050_CLK_USDHC1_SEL 28 +#define IMXRT1050_CLK_USDHC2_SEL 29 +#define IMXRT1050_CLK_LPUART_SEL 30 +#define IMXRT1050_CLK_LCDIF_SEL 31 +#define IMXRT1050_CLK_VIDEO_POST_DIV_SEL 32 +#define IMXRT1050_CLK_VIDEO_DIV 33 +#define IMXRT1050_CLK_ARM_PODF 34 +#define IMXRT1050_CLK_LPUART_PODF 35 +#define IMXRT1050_CLK_USDHC1_PODF 36 +#define IMXRT1050_CLK_USDHC2_PODF 37 +#define IMXRT1050_CLK_SEMC_PODF 38 +#define IMXRT1050_CLK_AHB_PODF 39 +#define IMXRT1050_CLK_LCDIF_PRED 40 +#define IMXRT1050_CLK_LCDIF_PODF 41 +#define IMXRT1050_CLK_USDHC1 42 +#define IMXRT1050_CLK_USDHC2 43 +#define IMXRT1050_CLK_LPUART1 44 +#define IMXRT1050_CLK_SEMC 45 +#define IMXRT1050_CLK_LCDIF_APB 46 +#define IMXRT1050_CLK_PLL1_ARM 47 +#define IMXRT1050_CLK_PLL2_SYS 48 +#define IMXRT1050_CLK_PLL3_USB_OTG 49 +#define IMXRT1050_CLK_PLL4_AUDIO 50 +#define IMXRT1050_CLK_PLL5_VIDEO 51 +#define IMXRT1050_CLK_PLL6_ENET 52 +#define IMXRT1050_CLK_PLL7_USB_HOST 53 +#define IMXRT1050_CLK_LCDIF_PIX 54 +#define IMXRT1050_CLK_USBOH3 55 +#define IMXRT1050_CLK_IPG_PDOF 56 +#define IMXRT1050_CLK_PER_CLK_SEL 57 +#define IMXRT1050_CLK_PER_PDOF 58 +#define IMXRT1050_CLK_DMA 59 +#define IMXRT1050_CLK_DMA_MUX 60 +#define IMXRT1050_CLK_END 61 + +#endif /* __DT_BINDINGS_CLOCK_IMXRT1050_H */ diff --git a/include/dt-bindings/clock/microchip,mpfs-clock.h b/include/dt-bindings/clock/microchip,mpfs-clock.h new file mode 100644 index 000000000000..73f2a9324857 --- /dev/null +++ b/include/dt-bindings/clock/microchip,mpfs-clock.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ +/* + * Daire McNamara,<daire.mcnamara@microchip.com> + * Copyright (C) 2020 Microchip Technology Inc. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_MICROCHIP_MPFS_H_ +#define _DT_BINDINGS_CLK_MICROCHIP_MPFS_H_ + +#define CLK_CPU 0 +#define CLK_AXI 1 +#define CLK_AHB 2 + +#define CLK_ENVM 3 +#define CLK_MAC0 4 +#define CLK_MAC1 5 +#define CLK_MMC 6 +#define CLK_TIMER 7 +#define CLK_MMUART0 8 +#define CLK_MMUART1 9 +#define CLK_MMUART2 10 +#define CLK_MMUART3 11 +#define CLK_MMUART4 12 +#define CLK_SPI0 13 +#define CLK_SPI1 14 +#define CLK_I2C0 15 +#define CLK_I2C1 16 +#define CLK_CAN0 17 +#define CLK_CAN1 18 +#define CLK_USB 19 +#define CLK_RESERVED 20 +#define CLK_RTC 21 +#define CLK_QSPI 22 +#define CLK_GPIO0 23 +#define CLK_GPIO1 24 +#define CLK_GPIO2 25 +#define CLK_DDRC 26 +#define CLK_FIC0 27 +#define CLK_FIC1 28 +#define CLK_FIC2 29 +#define CLK_FIC3 30 +#define CLK_ATHENA 31 +#define CLK_CFM 32 + +#endif /* _DT_BINDINGS_CLK_MICROCHIP_MPFS_H_ */ diff --git a/include/dt-bindings/clock/r9a07g054-cpg.h b/include/dt-bindings/clock/r9a07g054-cpg.h new file mode 100644 index 000000000000..43f4dbda872c --- /dev/null +++ b/include/dt-bindings/clock/r9a07g054-cpg.h @@ -0,0 +1,229 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) + * + * Copyright (C) 2022 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_CLOCK_R9A07G054_CPG_H__ +#define __DT_BINDINGS_CLOCK_R9A07G054_CPG_H__ + +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +/* R9A07G054 CPG Core Clocks */ +#define R9A07G054_CLK_I 0 +#define R9A07G054_CLK_I2 1 +#define R9A07G054_CLK_G 2 +#define R9A07G054_CLK_S0 3 +#define R9A07G054_CLK_S1 4 +#define R9A07G054_CLK_SPI0 5 +#define R9A07G054_CLK_SPI1 6 +#define R9A07G054_CLK_SD0 7 +#define R9A07G054_CLK_SD1 8 +#define R9A07G054_CLK_M0 9 +#define R9A07G054_CLK_M1 10 +#define R9A07G054_CLK_M2 11 +#define R9A07G054_CLK_M3 12 +#define R9A07G054_CLK_M4 13 +#define R9A07G054_CLK_HP 14 +#define R9A07G054_CLK_TSU 15 +#define R9A07G054_CLK_ZT 16 +#define R9A07G054_CLK_P0 17 +#define R9A07G054_CLK_P1 18 +#define R9A07G054_CLK_P2 19 +#define R9A07G054_CLK_AT 20 +#define R9A07G054_OSCCLK 21 +#define R9A07G054_CLK_P0_DIV2 22 +#define R9A07G054_CLK_DRP_M 23 +#define R9A07G054_CLK_DRP_D 24 +#define R9A07G054_CLK_DRP_A 25 + +/* R9A07G054 Module Clocks */ +#define R9A07G054_CA55_SCLK 0 +#define R9A07G054_CA55_PCLK 1 +#define R9A07G054_CA55_ATCLK 2 +#define R9A07G054_CA55_GICCLK 3 +#define R9A07G054_CA55_PERICLK 4 +#define R9A07G054_CA55_ACLK 5 +#define R9A07G054_CA55_TSCLK 6 +#define R9A07G054_GIC600_GICCLK 7 +#define R9A07G054_IA55_CLK 8 +#define R9A07G054_IA55_PCLK 9 +#define R9A07G054_MHU_PCLK 10 +#define R9A07G054_SYC_CNT_CLK 11 +#define R9A07G054_DMAC_ACLK 12 +#define R9A07G054_DMAC_PCLK 13 +#define R9A07G054_OSTM0_PCLK 14 +#define R9A07G054_OSTM1_PCLK 15 +#define R9A07G054_OSTM2_PCLK 16 +#define R9A07G054_MTU_X_MCK_MTU3 17 +#define R9A07G054_POE3_CLKM_POE 18 +#define R9A07G054_GPT_PCLK 19 +#define R9A07G054_POEG_A_CLKP 20 +#define R9A07G054_POEG_B_CLKP 21 +#define R9A07G054_POEG_C_CLKP 22 +#define R9A07G054_POEG_D_CLKP 23 +#define R9A07G054_WDT0_PCLK 24 +#define R9A07G054_WDT0_CLK 25 +#define R9A07G054_WDT1_PCLK 26 +#define R9A07G054_WDT1_CLK 27 +#define R9A07G054_WDT2_PCLK 28 +#define R9A07G054_WDT2_CLK 29 +#define R9A07G054_SPI_CLK2 30 +#define R9A07G054_SPI_CLK 31 +#define R9A07G054_SDHI0_IMCLK 32 +#define R9A07G054_SDHI0_IMCLK2 33 +#define R9A07G054_SDHI0_CLK_HS 34 +#define R9A07G054_SDHI0_ACLK 35 +#define R9A07G054_SDHI1_IMCLK 36 +#define R9A07G054_SDHI1_IMCLK2 37 +#define R9A07G054_SDHI1_CLK_HS 38 +#define R9A07G054_SDHI1_ACLK 39 +#define R9A07G054_GPU_CLK 40 +#define R9A07G054_GPU_AXI_CLK 41 +#define R9A07G054_GPU_ACE_CLK 42 +#define R9A07G054_ISU_ACLK 43 +#define R9A07G054_ISU_PCLK 44 +#define R9A07G054_H264_CLK_A 45 +#define R9A07G054_H264_CLK_P 46 +#define R9A07G054_CRU_SYSCLK 47 +#define R9A07G054_CRU_VCLK 48 +#define R9A07G054_CRU_PCLK 49 +#define R9A07G054_CRU_ACLK 50 +#define R9A07G054_MIPI_DSI_PLLCLK 51 +#define R9A07G054_MIPI_DSI_SYSCLK 52 +#define R9A07G054_MIPI_DSI_ACLK 53 +#define R9A07G054_MIPI_DSI_PCLK 54 +#define R9A07G054_MIPI_DSI_VCLK 55 +#define R9A07G054_MIPI_DSI_LPCLK 56 +#define R9A07G054_LCDC_CLK_A 57 +#define R9A07G054_LCDC_CLK_P 58 +#define R9A07G054_LCDC_CLK_D 59 +#define R9A07G054_SSI0_PCLK2 60 +#define R9A07G054_SSI0_PCLK_SFR 61 +#define R9A07G054_SSI1_PCLK2 62 +#define R9A07G054_SSI1_PCLK_SFR 63 +#define R9A07G054_SSI2_PCLK2 64 +#define R9A07G054_SSI2_PCLK_SFR 65 +#define R9A07G054_SSI3_PCLK2 66 +#define R9A07G054_SSI3_PCLK_SFR 67 +#define R9A07G054_SRC_CLKP 68 +#define R9A07G054_USB_U2H0_HCLK 69 +#define R9A07G054_USB_U2H1_HCLK 70 +#define R9A07G054_USB_U2P_EXR_CPUCLK 71 +#define R9A07G054_USB_PCLK 72 +#define R9A07G054_ETH0_CLK_AXI 73 +#define R9A07G054_ETH0_CLK_CHI 74 +#define R9A07G054_ETH1_CLK_AXI 75 +#define R9A07G054_ETH1_CLK_CHI 76 +#define R9A07G054_I2C0_PCLK 77 +#define R9A07G054_I2C1_PCLK 78 +#define R9A07G054_I2C2_PCLK 79 +#define R9A07G054_I2C3_PCLK 80 +#define R9A07G054_SCIF0_CLK_PCK 81 +#define R9A07G054_SCIF1_CLK_PCK 82 +#define R9A07G054_SCIF2_CLK_PCK 83 +#define R9A07G054_SCIF3_CLK_PCK 84 +#define R9A07G054_SCIF4_CLK_PCK 85 +#define R9A07G054_SCI0_CLKP 86 +#define R9A07G054_SCI1_CLKP 87 +#define R9A07G054_IRDA_CLKP 88 +#define R9A07G054_RSPI0_CLKB 89 +#define R9A07G054_RSPI1_CLKB 90 +#define R9A07G054_RSPI2_CLKB 91 +#define R9A07G054_CANFD_PCLK 92 +#define R9A07G054_GPIO_HCLK 93 +#define R9A07G054_ADC_ADCLK 94 +#define R9A07G054_ADC_PCLK 95 +#define R9A07G054_TSU_PCLK 96 +#define R9A07G054_STPAI_INITCLK 97 +#define R9A07G054_STPAI_ACLK 98 +#define R9A07G054_STPAI_MCLK 99 +#define R9A07G054_STPAI_DCLKIN 100 +#define R9A07G054_STPAI_ACLK_DRP 101 + +/* R9A07G054 Resets */ +#define R9A07G054_CA55_RST_1_0 0 +#define R9A07G054_CA55_RST_1_1 1 +#define R9A07G054_CA55_RST_3_0 2 +#define R9A07G054_CA55_RST_3_1 3 +#define R9A07G054_CA55_RST_4 4 +#define R9A07G054_CA55_RST_5 5 +#define R9A07G054_CA55_RST_6 6 +#define R9A07G054_CA55_RST_7 7 +#define R9A07G054_CA55_RST_8 8 +#define R9A07G054_CA55_RST_9 9 +#define R9A07G054_CA55_RST_10 10 +#define R9A07G054_CA55_RST_11 11 +#define R9A07G054_CA55_RST_12 12 +#define R9A07G054_GIC600_GICRESET_N 13 +#define R9A07G054_GIC600_DBG_GICRESET_N 14 +#define R9A07G054_IA55_RESETN 15 +#define R9A07G054_MHU_RESETN 16 +#define R9A07G054_DMAC_ARESETN 17 +#define R9A07G054_DMAC_RST_ASYNC 18 +#define R9A07G054_SYC_RESETN 19 +#define R9A07G054_OSTM0_PRESETZ 20 +#define R9A07G054_OSTM1_PRESETZ 21 +#define R9A07G054_OSTM2_PRESETZ 22 +#define R9A07G054_MTU_X_PRESET_MTU3 23 +#define R9A07G054_POE3_RST_M_REG 24 +#define R9A07G054_GPT_RST_C 25 +#define R9A07G054_POEG_A_RST 26 +#define R9A07G054_POEG_B_RST 27 +#define R9A07G054_POEG_C_RST 28 +#define R9A07G054_POEG_D_RST 29 +#define R9A07G054_WDT0_PRESETN 30 +#define R9A07G054_WDT1_PRESETN 31 +#define R9A07G054_WDT2_PRESETN 32 +#define R9A07G054_SPI_RST 33 +#define R9A07G054_SDHI0_IXRST 34 +#define R9A07G054_SDHI1_IXRST 35 +#define R9A07G054_GPU_RESETN 36 +#define R9A07G054_GPU_AXI_RESETN 37 +#define R9A07G054_GPU_ACE_RESETN 38 +#define R9A07G054_ISU_ARESETN 39 +#define R9A07G054_ISU_PRESETN 40 +#define R9A07G054_H264_X_RESET_VCP 41 +#define R9A07G054_H264_CP_PRESET_P 42 +#define R9A07G054_CRU_CMN_RSTB 43 +#define R9A07G054_CRU_PRESETN 44 +#define R9A07G054_CRU_ARESETN 45 +#define R9A07G054_MIPI_DSI_CMN_RSTB 46 +#define R9A07G054_MIPI_DSI_ARESET_N 47 +#define R9A07G054_MIPI_DSI_PRESET_N 48 +#define R9A07G054_LCDC_RESET_N 49 +#define R9A07G054_SSI0_RST_M2_REG 50 +#define R9A07G054_SSI1_RST_M2_REG 51 +#define R9A07G054_SSI2_RST_M2_REG 52 +#define R9A07G054_SSI3_RST_M2_REG 53 +#define R9A07G054_SRC_RST 54 +#define R9A07G054_USB_U2H0_HRESETN 55 +#define R9A07G054_USB_U2H1_HRESETN 56 +#define R9A07G054_USB_U2P_EXL_SYSRST 57 +#define R9A07G054_USB_PRESETN 58 +#define R9A07G054_ETH0_RST_HW_N 59 +#define R9A07G054_ETH1_RST_HW_N 60 +#define R9A07G054_I2C0_MRST 61 +#define R9A07G054_I2C1_MRST 62 +#define R9A07G054_I2C2_MRST 63 +#define R9A07G054_I2C3_MRST 64 +#define R9A07G054_SCIF0_RST_SYSTEM_N 65 +#define R9A07G054_SCIF1_RST_SYSTEM_N 66 +#define R9A07G054_SCIF2_RST_SYSTEM_N 67 +#define R9A07G054_SCIF3_RST_SYSTEM_N 68 +#define R9A07G054_SCIF4_RST_SYSTEM_N 69 +#define R9A07G054_SCI0_RST 70 +#define R9A07G054_SCI1_RST 71 +#define R9A07G054_IRDA_RST 72 +#define R9A07G054_RSPI0_RST 73 +#define R9A07G054_RSPI1_RST 74 +#define R9A07G054_RSPI2_RST 75 +#define R9A07G054_CANFD_RSTP_N 76 +#define R9A07G054_CANFD_RSTC_N 77 +#define R9A07G054_GPIO_RSTN 78 +#define R9A07G054_GPIO_PORT_RESETN 79 +#define R9A07G054_GPIO_SPARE_RESETN 80 +#define R9A07G054_ADC_PRESETN 81 +#define R9A07G054_ADC_ADRST_N 82 +#define R9A07G054_TSU_PRESETN 83 +#define R9A07G054_STPAI_ARESETN 84 + +#endif /* __DT_BINDINGS_CLOCK_R9A07G054_CPG_H__ */ diff --git a/include/dt-bindings/clock/starfive-jh7100-audio.h b/include/dt-bindings/clock/starfive-jh7100-audio.h new file mode 100644 index 000000000000..fbb4eae6572b --- /dev/null +++ b/include/dt-bindings/clock/starfive-jh7100-audio.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/* + * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk> + */ + +#ifndef __DT_BINDINGS_CLOCK_STARFIVE_JH7100_AUDIO_H__ +#define __DT_BINDINGS_CLOCK_STARFIVE_JH7100_AUDIO_H__ + +#define JH7100_AUDCLK_ADC_MCLK 0 +#define JH7100_AUDCLK_I2S1_MCLK 1 +#define JH7100_AUDCLK_I2SADC_APB 2 +#define JH7100_AUDCLK_I2SADC_BCLK 3 +#define JH7100_AUDCLK_I2SADC_BCLK_N 4 +#define JH7100_AUDCLK_I2SADC_LRCLK 5 +#define JH7100_AUDCLK_PDM_APB 6 +#define JH7100_AUDCLK_PDM_MCLK 7 +#define JH7100_AUDCLK_I2SVAD_APB 8 +#define JH7100_AUDCLK_SPDIF 9 +#define JH7100_AUDCLK_SPDIF_APB 10 +#define JH7100_AUDCLK_PWMDAC_APB 11 +#define JH7100_AUDCLK_DAC_MCLK 12 +#define JH7100_AUDCLK_I2SDAC_APB 13 +#define JH7100_AUDCLK_I2SDAC_BCLK 14 +#define JH7100_AUDCLK_I2SDAC_BCLK_N 15 +#define JH7100_AUDCLK_I2SDAC_LRCLK 16 +#define JH7100_AUDCLK_I2S1_APB 17 +#define JH7100_AUDCLK_I2S1_BCLK 18 +#define JH7100_AUDCLK_I2S1_BCLK_N 19 +#define JH7100_AUDCLK_I2S1_LRCLK 20 +#define JH7100_AUDCLK_I2SDAC16K_APB 21 +#define JH7100_AUDCLK_APB0_BUS 22 +#define JH7100_AUDCLK_DMA1P_AHB 23 +#define JH7100_AUDCLK_USB_APB 24 +#define JH7100_AUDCLK_USB_LPM 25 +#define JH7100_AUDCLK_USB_STB 26 +#define JH7100_AUDCLK_APB_EN 27 +#define JH7100_AUDCLK_VAD_MEM 28 + +#define JH7100_AUDCLK_END 29 + +#endif /* __DT_BINDINGS_CLOCK_STARFIVE_JH7100_AUDIO_H__ */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 2faa6f7aa8a8..c10dc4c659e2 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -888,7 +888,7 @@ void clk_hw_unregister_divider(struct clk_hw *hw); struct clk_mux { struct clk_hw hw; void __iomem *reg; - u32 *table; + const u32 *table; u32 mask; u8 shift; u8 flags; @@ -913,18 +913,18 @@ struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np, const struct clk_hw **parent_hws, const struct clk_parent_data *parent_data, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock); + u8 clk_mux_flags, const u32 *table, spinlock_t *lock); struct clk_hw *__devm_clk_hw_register_mux(struct device *dev, struct device_node *np, const char *name, u8 num_parents, const char * const *parent_names, const struct clk_hw **parent_hws, const struct clk_parent_data *parent_data, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock); + u8 clk_mux_flags, const u32 *table, spinlock_t *lock); struct clk *clk_register_mux_table(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, - u8 clk_mux_flags, u32 *table, spinlock_t *lock); + u8 clk_mux_flags, const u32 *table, spinlock_t *lock); #define clk_register_mux(dev, name, parent_names, num_parents, flags, reg, \ shift, width, clk_mux_flags, lock) \ @@ -962,9 +962,9 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name, (shift), BIT((width)) - 1, (clk_mux_flags), \ NULL, (lock)) -int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, +int clk_mux_val_to_index(struct clk_hw *hw, const u32 *table, unsigned int flags, unsigned int val); -unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index); +unsigned int clk_mux_index_to_val(const u32 *table, unsigned int flags, u8 index); void clk_unregister_mux(struct clk *clk); void clk_hw_unregister_mux(struct clk_hw *hw); @@ -1003,6 +1003,9 @@ void clk_hw_unregister_fixed_factor(struct clk_hw *hw); struct clk_hw *devm_clk_hw_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div); +struct clk_hw *devm_clk_hw_register_fixed_factor_index(struct device *dev, + const char *name, unsigned int index, unsigned long flags, + unsigned int mult, unsigned int div); /** * struct clk_fractional_divider - adjustable fractional divider clock * |