* [PATCH 0/2] clk: Add basic register clock controller @ 2023-04-14 18:12 David Yang 2023-04-14 18:12 ` [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller David Yang 2023-04-14 18:13 ` [PATCH 2/2] clk: Add basic register clock controller David Yang 0 siblings, 2 replies; 9+ messages in thread From: David Yang @ 2023-04-14 18:12 UTC (permalink / raw) To: linux-clk Cc: David Yang, Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, devicetree, linux-kernel These clocks were provided in `include/linux/clk-provider.h`, but lacks DT bindings. Add a clock controller to avoid operation conflict on same register. *** BLURB HERE *** David Yang (2): dt-bindings: clock: Add reg-clock-controller clk: Add basic register clock controller .../bindings/clock/reg-clock-controller.yaml | 245 +++++++ drivers/clk/Makefile | 1 + drivers/clk/clk-reg.c | 638 ++++++++++++++++++ 3 files changed, 884 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml create mode 100644 drivers/clk/clk-reg.c base-commit: 7a934f4bd7d6f9da84c8812da3ba42ee10f5778e -- 2.39.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller 2023-04-14 18:12 [PATCH 0/2] clk: Add basic register clock controller David Yang @ 2023-04-14 18:12 ` David Yang 2023-04-14 21:08 ` Krzysztof Kozlowski ` (2 more replies) 2023-04-14 18:13 ` [PATCH 2/2] clk: Add basic register clock controller David Yang 1 sibling, 3 replies; 9+ messages in thread From: David Yang @ 2023-04-14 18:12 UTC (permalink / raw) To: linux-clk Cc: David Yang, Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, devicetree, linux-kernel Add DT bindings documentation for reg-clock-controller, collection of basic clocks common to many platforms. Signed-off-by: David Yang <mmyangfl@gmail.com> --- .../bindings/clock/reg-clock-controller.yaml | 245 ++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml diff --git a/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml new file mode 100644 index 000000000000..a6a7e0b05821 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml @@ -0,0 +1,245 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/reg-clock-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Simple straight-forward register-based clocks + +maintainers: + - David Yang <mmyangfl@gmail.com> + +description: | + Basic clocks common to many platforms. + + If your clocks don't fit into these catagories, simply create your clock + controller. This driver normally work well with other controllers as long as + they operate on different registers. + + See linux/clk-provider.h for details about properties for each type of clock. + +properties: + compatible: + enum: + - reg-clock-controller + + ranges: true + + '#address-cells': + const: 1 + + '#size-cells': + const: 1 + +required: + - compatible + - ranges + - '#address-cells' + - '#size-cells' + +patternProperties: + ".*gate-clock@.*": + type: object + + description: | + Clock which can gate its output. + + properties: + compatible: + const: gate-clock + + reg: + maxItems: 1 + + '#clock-cells': + const: 0 + + clocks: + maxItems: 1 + description: + Parent clock. + + clock-output-name: + maxItems: 1 + + bit-index: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Bit index which controls the output. + + required: + - compatible + - reg + - '#clock-cells' + - bit-index + + additionalProperties: false + + ".*divider-clock@.*": + type: object + + description: | + Clock with an adjustable divider affecting its output frequency. + + properties: + compatible: + const: divider-clock + + reg: + maxItems: 1 + + '#clock-cells': + const: 0 + + clocks: + description: + Parent clocks. + + clock-output-name: + maxItems: 1 + + shift: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Shift to the divider bit field. + + width: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Width of the divider bit field. + + dividers: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of value/divider pairs. + + required: + - compatible + - reg + - '#clock-cells' + - shift + - width + + additionalProperties: false + + ".*mux-clock@.*": + type: object + + description: | + Clock with multiple selectable parents. + + properties: + compatible: + const: mux-clock + + reg: + maxItems: 1 + + '#clock-cells': + const: 0 + + clocks: + minItems: 1 + description: + Parent clock. + + clock-output-name: + maxItems: 1 + + shift: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Shift to multiplexer bit field. + + mask: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Mask of mutliplexer bit field. + + table: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Array of register values corresponding to the parent index. + + required: + - compatible + - reg + - '#clock-cells' + - shift + - mask + + additionalProperties: false + + ".*fractional-divider-clock@.*": + type: object + + description: | + Clock with adjustable fractional divider affecting its output frequency. + + properties: + compatible: + const: fractional_divider-clock + + reg: + maxItems: 1 + + '#clock-cells': + const: 0 + + clocks: + maxItems: 1 + description: + Parent clock. + + clock-output-name: + maxItems: 1 + + numerator-shift: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Shift to the numerator bit field. + + numerator-width: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Width of the numerator bit field. + + denominator-shift: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Shift to the denominator bit field. + + denominator-width: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + Width of the denominator bit field. + + required: + - compatible + - reg + - '#clock-cells' + - numerator-shift + - numerator-width + - denominator-shift + - denominator-width + + additionalProperties: false + +additionalProperties: true + +examples: + - | + clks: reg-clk-ctrl@ffff0000 { + compatible = "reg-clock-controller"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0xffff0000 0x1000>; + + my_clk: gate-clock@cc-3 { + compatible = "gate-clock"; + #clock-cells = <0>; + reg = <0xcc 4>; + bit-index = <3>; + clock-output-name = "my-clk"; + }; + }; -- 2.39.2 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller 2023-04-14 18:12 ` [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller David Yang @ 2023-04-14 21:08 ` Krzysztof Kozlowski 2023-04-17 17:47 ` Yangfl 2023-04-17 13:10 ` Rob Herring 2023-04-17 20:49 ` Rob Herring 2 siblings, 1 reply; 9+ messages in thread From: Krzysztof Kozlowski @ 2023-04-14 21:08 UTC (permalink / raw) To: David Yang, linux-clk Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, devicetree, linux-kernel On 14/04/2023 20:12, David Yang wrote: > Add DT bindings documentation for reg-clock-controller, collection of > basic clocks common to many platforms. > > Signed-off-by: David Yang <mmyangfl@gmail.com> > --- > .../bindings/clock/reg-clock-controller.yaml | 245 ++++++++++++++++++ > 1 file changed, 245 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > diff --git a/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > new file mode 100644 > index 000000000000..a6a7e0b05821 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > @@ -0,0 +1,245 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/clock/reg-clock-controller.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Simple straight-forward register-based clocks > + > +maintainers: > + - David Yang <mmyangfl@gmail.com> > + > +description: | > + Basic clocks common to many platforms. > + > + If your clocks don't fit into these catagories, simply create your clock typo: categories > + controller. This driver normally work well with other controllers as long as > + they operate on different registers. > + > + See linux/clk-provider.h for details about properties for each type of clock. Describe here what is this device, what such simple clock controller represents. > + > +properties: > + compatible: > + enum: > + - reg-clock-controller > + > + ranges: true > + > + '#address-cells': > + const: 1 > + > + '#size-cells': > + const: 1 > + > +required: > + - compatible > + - ranges > + - '#address-cells' > + - '#size-cells' required goes after patternProperties. > + > +patternProperties: > + ".*gate-clock@.*": "gate-clock@" should be equivalent. However this should be just "clock". > + type: object > + > + description: | Do not need '|' unless you need to preserve formatting. > + Clock which can gate its output. > + > + properties: > + compatible: > + const: gate-clock > + > + reg: > + maxItems: 1 > + > + '#clock-cells': > + const: 0 > + > + clocks: > + maxItems: 1 > + description: > + Parent clock. > + > + clock-output-name: names Don't create your own properties. > + maxItems: 1 > + > + bit-index: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Bit index which controls the output. I suggest to use same property as nvme, so bits. > + > + required: > + - compatible > + - reg > + - '#clock-cells' > + - bit-index > + > + additionalProperties: false > + > + ".*divider-clock@.*": > + type: object > + > + description: | > + Clock with an adjustable divider affecting its output frequency. > + > + properties: > + compatible: > + const: divider-clock > + > + reg: > + maxItems: 1 > + > + '#clock-cells': > + const: 0 > + > + clocks: > + description: > + Parent clocks. > + > + clock-output-name: > + maxItems: 1 > + > + shift: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Shift to the divider bit field. > + > + width: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Width of the divider bit field. > + > + dividers: > + $ref: /schemas/types.yaml#/definitions/uint32-array > + description: > + Array of value/divider pairs. Then it looks like matrix. > + > + required: > + - compatible > + - reg > + - '#clock-cells' > + - shift > + - width > + > + additionalProperties: false > + > + ".*mux-clock@.*": > + type: object > + > + description: | > + Clock with multiple selectable parents. > + > + properties: > + compatible: > + const: mux-clock > + > + reg: > + maxItems: 1 > + > + '#clock-cells': > + const: 0 > + > + clocks: > + minItems: 1 > + description: > + Parent clock. > + > + clock-output-name: > + maxItems: 1 > + > + shift: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Shift to multiplexer bit field. > + > + mask: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Mask of mutliplexer bit field. > + > + table: > + $ref: /schemas/types.yaml#/definitions/uint32-array > + description: > + Array of register values corresponding to the parent index. > + > + required: > + - compatible > + - reg > + - '#clock-cells' > + - shift > + - mask > + > + additionalProperties: false > + > + ".*fractional-divider-clock@.*": > + type: object > + > + description: | > + Clock with adjustable fractional divider affecting its output frequency. > + > + properties: > + compatible: > + const: fractional_divider-clock > + > + reg: > + maxItems: 1 > + > + '#clock-cells': > + const: 0 > + > + clocks: > + maxItems: 1 > + description: > + Parent clock. > + > + clock-output-name: > + maxItems: 1 > + > + numerator-shift: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Shift to the numerator bit field. > + > + numerator-width: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Width of the numerator bit field. > + > + denominator-shift: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Shift to the denominator bit field. > + > + denominator-width: > + $ref: /schemas/types.yaml#/definitions/uint32 > + description: > + Width of the denominator bit field. > + > + required: > + - compatible > + - reg > + - '#clock-cells' > + - numerator-shift > + - numerator-width > + - denominator-shift > + - denominator-width > + > + additionalProperties: false > + > +additionalProperties: true No, come on. This must be false. > + > +examples: > + - | > + clks: reg-clk-ctrl@ffff0000 { Names should be generic, so clock-controller Drop the label. > + compatible = "reg-clock-controller"; > + #address-cells = <1>; > + #size-cells = <1>; > + ranges = <0 0xffff0000 0x1000>; > + > + my_clk: gate-clock@cc-3 { Drop label. That's a new unit address to me. Did I miss a change in DT spec? > + compatible = "gate-clock"; > + #clock-cells = <0>; > + reg = <0xcc 4>; reg is after compatible. > + bit-index = <3>; > + clock-output-name = "my-clk"; Plus, test your patches. This fails testing... > + }; > + }; Best regards, Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller 2023-04-14 21:08 ` Krzysztof Kozlowski @ 2023-04-17 17:47 ` Yangfl 0 siblings, 0 replies; 9+ messages in thread From: Yangfl @ 2023-04-17 17:47 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: linux-clk, Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, devicetree, linux-kernel Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> 于2023年4月15日周六 05:08写道: > > On 14/04/2023 20:12, David Yang wrote: > > Add DT bindings documentation for reg-clock-controller, collection of > > basic clocks common to many platforms. > > > > Signed-off-by: David Yang <mmyangfl@gmail.com> > > --- > > .../bindings/clock/reg-clock-controller.yaml | 245 ++++++++++++++++++ > > 1 file changed, 245 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > > > diff --git a/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > new file mode 100644 > > index 000000000000..a6a7e0b05821 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > @@ -0,0 +1,245 @@ > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > +%YAML 1.2 > > +--- > > +$id: http://devicetree.org/schemas/clock/reg-clock-controller.yaml# > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > + > > +title: Simple straight-forward register-based clocks > > + > > +maintainers: > > + - David Yang <mmyangfl@gmail.com> > > + > > +description: | > > + Basic clocks common to many platforms. > > + > > + If your clocks don't fit into these catagories, simply create your clock > > typo: categories Fixed in v2. > > > + controller. This driver normally work well with other controllers as long as > > + they operate on different registers. > > + > > + See linux/clk-provider.h for details about properties for each type of clock. > > Describe here what is this device, what such simple clock controller > represents. Description has been rewritten in v3, to describe the device. > > > + > > +properties: > > + compatible: > > + enum: > > + - reg-clock-controller > > + > > + ranges: true > > + > > + '#address-cells': > > + const: 1 > > + > > + '#size-cells': > > + const: 1 > > + > > +required: > > + - compatible > > + - ranges > > + - '#address-cells' > > + - '#size-cells' > > required goes after patternProperties. Fixed in v2. > > > + > > +patternProperties: > > + ".*gate-clock@.*": > > "gate-clock@" should be equivalent. However this should be just "clock". Fixed in v3. > > > + type: object > > + > > + description: | > > Do not need '|' unless you need to preserve formatting. Fixed in v2. > > > + Clock which can gate its output. > > + > > + properties: > > + compatible: > > + const: gate-clock > > + > > + reg: > > + maxItems: 1 > > + > > + '#clock-cells': > > + const: 0 > > + > > + clocks: > > + maxItems: 1 > > + description: > > + Parent clock. > > + > > + clock-output-name: > > names > > Don't create your own properties. Fixed in v2, "clock-output-names". > > > + maxItems: 1 > > + > > + bit-index: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Bit index which controls the output. > > I suggest to use same property as nvme, so bits. Replaced with "bits" in v2. > > > + > > + required: > > + - compatible > > + - reg > > + - '#clock-cells' > > + - bit-index > > + > > + additionalProperties: false > > + > > + ".*divider-clock@.*": > > + type: object > > + > > + description: | > > + Clock with an adjustable divider affecting its output frequency. > > + > > + properties: > > + compatible: > > + const: divider-clock > > + > > + reg: > > + maxItems: 1 > > + > > + '#clock-cells': > > + const: 0 > > + > > + clocks: > > + description: > > + Parent clocks. > > + > > + clock-output-name: > > + maxItems: 1 > > + > > + shift: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Shift to the divider bit field. > > + > > + width: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Width of the divider bit field. > > + > > + dividers: > > + $ref: /schemas/types.yaml#/definitions/uint32-array > > + description: > > + Array of value/divider pairs. > > Then it looks like matrix. This part of bindings has been (temporarily) removed from this series since v2, to make it simpler. > > > + > > + required: > > + - compatible > > + - reg > > + - '#clock-cells' > > + - shift > > + - width > > + > > + additionalProperties: false > > + > > + ".*mux-clock@.*": > > + type: object > > + > > + description: | > > + Clock with multiple selectable parents. > > + > > + properties: > > + compatible: > > + const: mux-clock > > + > > + reg: > > + maxItems: 1 > > + > > + '#clock-cells': > > + const: 0 > > + > > + clocks: > > + minItems: 1 > > + description: > > + Parent clock. > > + > > + clock-output-name: > > + maxItems: 1 > > + > > + shift: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Shift to multiplexer bit field. > > + > > + mask: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Mask of mutliplexer bit field. > > + > > + table: > > + $ref: /schemas/types.yaml#/definitions/uint32-array > > + description: > > + Array of register values corresponding to the parent index. > > + > > + required: > > + - compatible > > + - reg > > + - '#clock-cells' > > + - shift > > + - mask > > + > > + additionalProperties: false > > + > > + ".*fractional-divider-clock@.*": > > + type: object > > + > > + description: | > > + Clock with adjustable fractional divider affecting its output frequency. > > + > > + properties: > > + compatible: > > + const: fractional_divider-clock > > + > > + reg: > > + maxItems: 1 > > + > > + '#clock-cells': > > + const: 0 > > + > > + clocks: > > + maxItems: 1 > > + description: > > + Parent clock. > > + > > + clock-output-name: > > + maxItems: 1 > > + > > + numerator-shift: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Shift to the numerator bit field. > > + > > + numerator-width: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Width of the numerator bit field. > > + > > + denominator-shift: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Shift to the denominator bit field. > > + > > + denominator-width: > > + $ref: /schemas/types.yaml#/definitions/uint32 > > + description: > > + Width of the denominator bit field. > > + > > + required: > > + - compatible > > + - reg > > + - '#clock-cells' > > + - numerator-shift > > + - numerator-width > > + - denominator-shift > > + - denominator-width > > + > > + additionalProperties: false > > + > > +additionalProperties: true > > No, come on. This must be false. Fixed with "false" in v2. > > > + > > +examples: > > + - | > > + clks: reg-clk-ctrl@ffff0000 { > > Names should be generic, so clock-controller > > Drop the label. Dropped in v2. > > > + compatible = "reg-clock-controller"; > > + #address-cells = <1>; > > + #size-cells = <1>; > > + ranges = <0 0xffff0000 0x1000>; > > + > > + my_clk: gate-clock@cc-3 { > > Drop label. > > That's a new unit address to me. Did I miss a change in DT spec? Dropped label in v2. > > > + compatible = "gate-clock"; > > + #clock-cells = <0>; > > + reg = <0xcc 4>; > > reg is after compatible. > > > + bit-index = <3>; > > + clock-output-name = "my-clk"; > > Plus, test your patches. This fails testing... Fix name error in v3. > > > + }; > > + }; > > Best regards, > Krzysztof > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller 2023-04-14 18:12 ` [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller David Yang 2023-04-14 21:08 ` Krzysztof Kozlowski @ 2023-04-17 13:10 ` Rob Herring 2023-04-17 20:49 ` Rob Herring 2 siblings, 0 replies; 9+ messages in thread From: Rob Herring @ 2023-04-17 13:10 UTC (permalink / raw) To: David Yang Cc: Stephen Boyd, Michael Turquette, Krzysztof Kozlowski, devicetree, linux-clk, Rob Herring, linux-kernel On Sat, 15 Apr 2023 02:12:59 +0800, David Yang wrote: > Add DT bindings documentation for reg-clock-controller, collection of > basic clocks common to many platforms. > > Signed-off-by: David Yang <mmyangfl@gmail.com> > --- > .../bindings/clock/reg-clock-controller.yaml | 245 ++++++++++++++++++ > 1 file changed, 245 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13): yamllint warnings/errors: dtschema/dtc warnings/errors: /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/clock/reg-clock-controller.example.dtb: reg-clk-ctrl@ffff0000: 'gate-clock@cc-3' does not match any of the regexes: '.*-names$', '.*-supply$', '^#.*-cells$', '^#[a-zA-Z0-9,+\\-._]{0,63}$', '^[a-zA-Z0-9][a-zA-Z0-9,+\\-._]{0,63}$', '^[a-zA-Z][a-zA-Z0-9,+\\-._]{0,63}@[0-9a-fA-F]+(,[0-9a-fA-F]+)*$', '^__.*__$', 'pinctrl-[0-9]+' From schema: /usr/local/lib/python3.10/dist-packages/dtschema/schemas/dt-core.yaml doc reference errors (make refcheckdocs): See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20230414181302.986271-2-mmyangfl@gmail.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller 2023-04-14 18:12 ` [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller David Yang 2023-04-14 21:08 ` Krzysztof Kozlowski 2023-04-17 13:10 ` Rob Herring @ 2023-04-17 20:49 ` Rob Herring 2023-04-17 21:39 ` Yangfl 2 siblings, 1 reply; 9+ messages in thread From: Rob Herring @ 2023-04-17 20:49 UTC (permalink / raw) To: David Yang Cc: linux-clk, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski, devicetree, linux-kernel On Sat, Apr 15, 2023 at 02:12:59AM +0800, David Yang wrote: > Add DT bindings documentation for reg-clock-controller, collection of > basic clocks common to many platforms. > > Signed-off-by: David Yang <mmyangfl@gmail.com> > --- > .../bindings/clock/reg-clock-controller.yaml | 245 ++++++++++++++++++ > 1 file changed, 245 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > diff --git a/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > new file mode 100644 > index 000000000000..a6a7e0b05821 > --- /dev/null > +++ b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > @@ -0,0 +1,245 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/clock/reg-clock-controller.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Simple straight-forward register-based clocks 'simple' means extended one property at a time with little foresight. In the end, 'simple' bindings are never simple. s/simple/generic/ as well. When we first started the clock binding, we had exactly this. There's still bindings for at least some of it. It turned out to be a bad idea because it was difficult to get correct and complete. So this binding is exactly what we don't want. Rob ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller 2023-04-17 20:49 ` Rob Herring @ 2023-04-17 21:39 ` Yangfl 2023-04-18 0:14 ` Stephen Boyd 0 siblings, 1 reply; 9+ messages in thread From: Yangfl @ 2023-04-17 21:39 UTC (permalink / raw) To: Rob Herring Cc: linux-clk, Michael Turquette, Stephen Boyd, Krzysztof Kozlowski, devicetree, linux-kernel Rob Herring <robh@kernel.org> 于2023年4月18日周二 04:49写道: > > On Sat, Apr 15, 2023 at 02:12:59AM +0800, David Yang wrote: > > Add DT bindings documentation for reg-clock-controller, collection of > > basic clocks common to many platforms. > > > > Signed-off-by: David Yang <mmyangfl@gmail.com> > > --- > > .../bindings/clock/reg-clock-controller.yaml | 245 ++++++++++++++++++ > > 1 file changed, 245 insertions(+) > > create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > > > diff --git a/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > new file mode 100644 > > index 000000000000..a6a7e0b05821 > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > @@ -0,0 +1,245 @@ > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > +%YAML 1.2 > > +--- > > +$id: http://devicetree.org/schemas/clock/reg-clock-controller.yaml# > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > + > > +title: Simple straight-forward register-based clocks > > 'simple' means extended one property at a time with little foresight. In > the end, 'simple' bindings are never simple. s/simple/generic/ as well. > > When we first started the clock binding, we had exactly this. There's > still bindings for at least some of it. It turned out to be a bad > idea because it was difficult to get correct and complete. So this > binding is exactly what we don't want. > > Rob Thanks. So in the next version v2, clock-controller are made merely container of clocks. The real jobs are done by sub clock nodes, so that clocks, with or without hardware-specific clock types "compatible", can be declared independently and individually as dt nodes, instead of hardware clock "controllers" with quite arbitrary clock identifiers listed under include/dt-bindings/clock/. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller 2023-04-17 21:39 ` Yangfl @ 2023-04-18 0:14 ` Stephen Boyd 0 siblings, 0 replies; 9+ messages in thread From: Stephen Boyd @ 2023-04-18 0:14 UTC (permalink / raw) To: Rob Herring, Yangfl Cc: linux-clk, Michael Turquette, Krzysztof Kozlowski, devicetree, linux-kernel Quoting Yangfl (2023-04-17 14:39:23) > Rob Herring <robh@kernel.org> 于2023年4月18日周二 04:49写道: > > > > On Sat, Apr 15, 2023 at 02:12:59AM +0800, David Yang wrote: > > > Add DT bindings documentation for reg-clock-controller, collection of > > > basic clocks common to many platforms. > > > > > > Signed-off-by: David Yang <mmyangfl@gmail.com> > > > --- > > > .../bindings/clock/reg-clock-controller.yaml | 245 ++++++++++++++++++ > > > 1 file changed, 245 insertions(+) > > > create mode 100644 Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > > > > > diff --git a/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > > new file mode 100644 > > > index 000000000000..a6a7e0b05821 > > > --- /dev/null > > > +++ b/Documentation/devicetree/bindings/clock/reg-clock-controller.yaml > > > @@ -0,0 +1,245 @@ > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > > > +%YAML 1.2 > > > +--- > > > +$id: http://devicetree.org/schemas/clock/reg-clock-controller.yaml# > > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > > + > > > +title: Simple straight-forward register-based clocks > > > > 'simple' means extended one property at a time with little foresight. In > > the end, 'simple' bindings are never simple. s/simple/generic/ as well. > > > > When we first started the clock binding, we had exactly this. There's > > still bindings for at least some of it. It turned out to be a bad > > idea because it was difficult to get correct and complete. So this > > binding is exactly what we don't want. > > > > Rob > > Thanks. So in the next version v2, clock-controller are made merely > container of clocks. The real jobs are done by sub clock nodes, so > that clocks, with or without hardware-specific clock types > "compatible", can be declared independently and individually as dt > nodes, instead of hardware clock "controllers" with quite arbitrary > clock identifiers listed under include/dt-bindings/clock/. No. Write actual drivers and actual bindings for real devices. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] clk: Add basic register clock controller 2023-04-14 18:12 [PATCH 0/2] clk: Add basic register clock controller David Yang 2023-04-14 18:12 ` [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller David Yang @ 2023-04-14 18:13 ` David Yang 1 sibling, 0 replies; 9+ messages in thread From: David Yang @ 2023-04-14 18:13 UTC (permalink / raw) To: linux-clk Cc: David Yang, Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski, devicetree, linux-kernel, Philipp Zabel These clocks were provided in `include/linux/clk-provider.h`, but lacks DT bindings. Add a clock controller to avoid operation conflict on same register. Signed-off-by: David Yang <mmyangfl@gmail.com> --- drivers/clk/Makefile | 1 + drivers/clk/clk-reg.c | 638 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 639 insertions(+) create mode 100644 drivers/clk/clk-reg.c diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index e3ca0d058a25..9468b2028a5b 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o obj-$(CONFIG_COMMON_CLK) += clk-gpio.o ifeq ($(CONFIG_OF), y) obj-$(CONFIG_COMMON_CLK) += clk-conf.o +obj-$(CONFIG_COMMON_CLK) += clk-reg.o endif # hardware specific clock types diff --git a/drivers/clk/clk-reg.c b/drivers/clk/clk-reg.c new file mode 100644 index 000000000000..a115921a9cbd --- /dev/null +++ b/drivers/clk/clk-reg.c @@ -0,0 +1,638 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (c) 2023 David Yang + * + * Simple straight-forward register clocks bindings + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_clk.h> +#include <linux/platform_device.h> +#include <linux/reset-controller.h> +#include <linux/slab.h> + +struct regclk_ctrl { + spinlock_t lock; + + void __iomem *base; + struct reset_controller_dev rcdev; + bool rst_set_to_disable; +}; + +struct regclk_flag { + const char *prop; + unsigned long flag; +}; + +static const struct regclk_flag regclk_flags[] = { + { "set-rate-gate", CLK_SET_RATE_GATE }, + { "set-parent-gate", CLK_SET_PARENT_GATE }, + { "set-rate-parent", CLK_SET_RATE_PARENT }, + { "ignore-unused", CLK_IGNORE_UNUSED }, + { "get-rate-nocache", CLK_GET_RATE_NOCACHE }, + { "set-rate-no-reparent", CLK_SET_RATE_NO_REPARENT }, + { "get-accuracy-nocache", CLK_GET_ACCURACY_NOCACHE }, + { "recalc-new-rates", CLK_RECALC_NEW_RATES }, + { "set-rate-ungate", CLK_SET_RATE_UNGATE }, + { "critical", CLK_IS_CRITICAL }, + { "ops-parent-enable", CLK_OPS_PARENT_ENABLE }, + { "duty-cycle-parent", CLK_DUTY_CYCLE_PARENT }, + { } +}; + +static const struct regclk_flag regclk_gate_flags[] = { + { "set-to-disable", CLK_GATE_SET_TO_DISABLE }, + { "hiword-mask", CLK_GATE_HIWORD_MASK }, + { "big-endian", CLK_GATE_BIG_ENDIAN }, + { } +}; + +static const struct regclk_flag regclk_divider_flags[] = { + { "one-based", CLK_DIVIDER_ONE_BASED }, + { "power-of-two", CLK_DIVIDER_POWER_OF_TWO }, + { "allow-zero", CLK_DIVIDER_ALLOW_ZERO }, + { "hiword-mask", CLK_DIVIDER_HIWORD_MASK }, + { "round-closest", CLK_DIVIDER_ROUND_CLOSEST }, + { "read-only", CLK_DIVIDER_READ_ONLY }, + { "max-at-zero", CLK_DIVIDER_MAX_AT_ZERO }, + { "big-endian", CLK_DIVIDER_BIG_ENDIAN }, + { } +}; + +static const struct regclk_flag regclk_mux_flags[] = { + { "index-one", CLK_MUX_INDEX_ONE }, + { "index-bit", CLK_MUX_INDEX_BIT }, + { "hiword-mask", CLK_MUX_HIWORD_MASK }, + { "read-only", CLK_MUX_READ_ONLY }, + { "round-closest", CLK_MUX_ROUND_CLOSEST }, + { "big-endian", CLK_MUX_BIG_ENDIAN }, + { } +}; + +static const struct regclk_flag regclk_fractional_divider_flags[] = { + { "zero-based", CLK_FRAC_DIVIDER_ZERO_BASED }, + { "big-endian", CLK_FRAC_DIVIDER_BIG_ENDIAN }, + { "power-of-two-ps", CLK_FRAC_DIVIDER_POWER_OF_TWO_PS }, + { } +}; + +static unsigned long +regclk_get_flags(struct device_node *np, const struct regclk_flag *defs) +{ + unsigned long flags = 0; + + for (int i = 0; defs[i].prop; i++) + if (of_property_read_bool(np, defs[i].prop)) + flags |= defs[i].flag; + + return flags; +} + +static const char *regclk_name(struct device_node *np) +{ + const char *name; + + if (!of_property_read_string(np, "clock-output-name", &name)) + return name; + + return of_node_full_name(np); +} + +static struct clk_hw * +regclk_register_gate(struct device_node *np, struct regclk_ctrl *priv) +{ + const char *name; + const char *parent_name; + unsigned long flags; + void __iomem *reg; + u32 bit_idx; + unsigned long clk_gate_flags; + + const char *property; + struct clk_hw *hw; + struct clk_hw *retptr; + int ret; + + reg = of_iomap(np, 0); + if (!reg) + return ERR_PTR(-ENOMEM); + name = regclk_name(np); + if (!name) + return ERR_PTR(-EINVAL); + + property = "bit-index"; + if (of_property_read_u32(np, property, &bit_idx)) + goto err_property; + + parent_name = of_clk_get_parent_name(np, 0); + flags = regclk_get_flags(np, regclk_flags); + clk_gate_flags = regclk_get_flags(np, regclk_gate_flags); + + hw = __clk_hw_register_gate(NULL, np, name, parent_name, + NULL, NULL, flags, reg, bit_idx, + clk_gate_flags, &priv->lock); + if (IS_ERR(hw)) + return hw; + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); + if (ret) { + retptr = ERR_PTR(ret); + goto err_register; + } + + return hw; + +err_register: + clk_hw_unregister(hw); + return retptr; + +err_property: + pr_err("%s: clock %s missing required property \"%s\"\n", + __func__, name, property); + return ERR_PTR(-EINVAL); +} + +static struct clk_hw * +regclk_register_divider(struct device_node *np, struct regclk_ctrl *priv) +{ + const char *name; + const char *parent_name; + unsigned long flags; + void __iomem *reg; + u32 shift; + u32 width; + unsigned long clk_divider_flags; + struct clk_div_table *table = NULL; + + struct property *prop; + const char *property; + struct clk_hw *hw; + struct clk_hw *retptr; + int ret; + + reg = of_iomap(np, 0); + if (!reg) + return ERR_PTR(-ENOMEM); + + name = regclk_name(np); + if (!name) + return ERR_PTR(-EINVAL); + + property = "shift"; + if (of_property_read_u32(np, property, &shift)) + goto err_property; + property = "width"; + if (of_property_read_u32(np, property, &width)) + goto err_property; + + prop = of_find_property(np, "dividers", NULL); + if (prop) { + unsigned int len = (prop->length / sizeof(u32) + 1) / 2; + + table = kmalloc_array(len + 1, sizeof(*table), GFP_KERNEL); + if (!table) + return ERR_PTR(-ENOMEM); + + for (unsigned int i = 0; i <= len; i++) { + u32 val; + u32 div; + + if (of_property_read_u32_index(np, "dividers", + 2 * i + 0, &val)) { + retptr = ERR_PTR(-EINVAL); + goto err_table; + } + if (of_property_read_u32_index(np, "dividers", + 2 * i + 1, &div)) { + if (i == len) + div = 0; + retptr = ERR_PTR(-EINVAL); + goto err_table; + } + + table[i].val = val; + table[i].div = div; + } + + memset(&table[len], 0, sizeof(table[len])); + } + + parent_name = of_clk_get_parent_name(np, 0); + flags = regclk_get_flags(np, regclk_flags); + clk_divider_flags = regclk_get_flags(np, regclk_divider_flags); + + hw = __clk_hw_register_divider(NULL, np, name, parent_name, + NULL, NULL, flags, reg, shift, width, + clk_divider_flags, table, &priv->lock); + if (IS_ERR(hw)) { + retptr = hw; + goto err_table; + } + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); + if (ret) { + retptr = ERR_PTR(ret); + goto err_register; + } + + return hw; + +err_register: + clk_hw_unregister(hw); +err_table: + kfree(table); + return retptr; + +err_property: + pr_err("%s: clock %s missing required property \"%s\"\n", + __func__, name, property); + return ERR_PTR(-EINVAL); +} + +static struct clk_hw * +regclk_register_mux(struct device_node *np, struct regclk_ctrl *priv) +{ + const char *name; + u8 num_parents; + const char **parent_names; + unsigned long flags; + void __iomem *reg; + u32 shift; + u32 mask; + unsigned long clk_mux_flags; + u32 *table; + + const char *property; + struct clk_hw *hw; + struct clk_hw *retptr; + int ret; + + reg = of_iomap(np, 0); + if (!reg) + return ERR_PTR(-ENOMEM); + name = regclk_name(np); + if (!name) + return ERR_PTR(-EINVAL); + + property = "shift"; + if (of_property_read_u32(np, property, &shift)) + goto err_property; + property = "mask"; + if (of_property_read_u32(np, property, &mask)) + goto err_property; + + num_parents = of_clk_get_parent_count(np); + + parent_names = kmalloc_array(num_parents, sizeof(*parent_names), + GFP_KERNEL); + if (!parent_names) + return ERR_PTR(-ENOMEM); + for (int i = 0; i < num_parents; i++) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) { + retptr = ERR_PTR(-EINVAL); + goto err_parents; + } + } + + table = kmalloc_array(num_parents, sizeof(*table), GFP_KERNEL); + if (!table) { + retptr = ERR_PTR(-ENOMEM); + goto err_parents; + } + for (int i = 0; i < num_parents; i++) { + if (of_property_read_u32(np, "table", &table[i])) { + retptr = ERR_PTR(-EINVAL); + goto err_table; + } + } + + flags = regclk_get_flags(np, regclk_flags); + clk_mux_flags = regclk_get_flags(np, regclk_mux_flags); + + hw = __clk_hw_register_mux(NULL, np, name, num_parents, parent_names, + NULL, NULL, flags, reg, shift, mask, + clk_mux_flags, table, &priv->lock); + if (IS_ERR(hw)) + goto err_table; + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); + if (ret) { + retptr = ERR_PTR(ret); + goto err_register; + } + + return hw; + +err_register: + clk_hw_unregister(hw); +err_table: + kfree(table); +err_parents: + kfree(parent_names); + return retptr; + +err_property: + pr_err("%s: clock %s missing required property \"%s\"\n", + __func__, name, property); + return ERR_PTR(-EINVAL); +} + +static struct clk_hw * +regclk_register_fractional_divider(struct device_node *np, struct regclk_ctrl *priv) +{ + const char *name; + const char *parent_name; + unsigned long flags; + void __iomem *reg; + u32 mshift; + u32 mwidth; + u32 nshift; + u32 nwidth; + unsigned long clk_divider_flags; + + const char *property; + struct clk_hw *hw; + struct clk_hw *retptr; + int ret; + + reg = of_iomap(np, 0); + if (!reg) + return ERR_PTR(-ENOMEM); + name = regclk_name(np); + if (!name) + return ERR_PTR(-EINVAL); + + property = "numerator-shift"; + if (of_property_read_u32(np, property, &mshift)) + goto err_property; + property = "numerator-width"; + if (of_property_read_u32(np, property, &mwidth)) + goto err_property; + property = "denominator-shift"; + if (of_property_read_u32(np, property, &nshift)) + goto err_property; + property = "denominator-width"; + if (of_property_read_u32(np, property, &nwidth)) + goto err_property; + + parent_name = of_clk_get_parent_name(np, 0); + flags = regclk_get_flags(np, regclk_flags); + clk_divider_flags = regclk_get_flags(np, regclk_fractional_divider_flags); + + hw = clk_hw_register_fractional_divider(NULL, name, parent_name, + flags, reg, mshift, mwidth, + nshift, nwidth, + clk_divider_flags, &priv->lock); + if (IS_ERR(hw)) + return hw; + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); + if (ret) { + retptr = ERR_PTR(ret); + goto err_register; + } + + return hw; + +err_register: + clk_hw_unregister(hw); + return retptr; + +err_property: + pr_err("%s: clock %s missing required property \"%s\"\n", + __func__, name, property); + return ERR_PTR(-EINVAL); +} + +/** regclk **/ + +static void regclk_unsetup(struct device_node *np) +{ + struct clk_hw *hw = np->data; + + if (!hw) + return; + + if (of_device_is_compatible(np, "gate-clock")) + clk_hw_unregister_gate(hw); + else if (of_device_is_compatible(np, "divider-clock")) + clk_hw_unregister_divider(hw); + else if (of_device_is_compatible(np, "mux-clock")) + clk_hw_unregister_mux(hw); + else if (of_device_is_compatible(np, "fractional-divider-clock")) + clk_hw_unregister_fractional_divider(hw); +} + +static int regclk_setup(struct device_node *np, struct regclk_ctrl *priv) +{ + struct clk_hw *hw = np->data; + + if (of_device_is_compatible(np, "gate-clock")) + hw = regclk_register_gate(np, priv); + else if (of_device_is_compatible(np, "divider-clock")) + hw = regclk_register_divider(np, priv); + else if (of_device_is_compatible(np, "mux-clock")) + hw = regclk_register_mux(np, priv); + else if (of_device_is_compatible(np, "fractional-divider-clock")) + hw = regclk_register_fractional_divider(np, priv); + else { + pr_warn("%s: starnge node %s ...\n", + __func__, of_node_full_name(np)); + return 0; + } + + if (IS_ERR(hw)) { + int ret = PTR_ERR(hw); + + pr_err("%s: cannot register clock %s, ret %d\n", + __func__, of_node_full_name(np), ret); + return ret; + } + + np->data = hw; + return 0; +} + +/** regclk_reset **/ + +#if IS_ENABLED(CONFIG_RESET_CONTROLLER) +static int +regclk_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct regclk_ctrl *priv = container_of(rcdev, struct regclk_ctrl, rcdev); + unsigned long flags; + u32 offset = id >> 5; + u8 bit = id & 0x1f; + u32 val; + + if (WARN_ON(!priv->base)) + return 0; + + spin_lock_irqsave(&priv->lock, flags); + + val = readl(priv->base + offset); + if (priv->rst_set_to_disable) + val &= ~BIT(bit); + else + val |= BIT(bit); + writel(val, priv->base + offset); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int +regclk_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct regclk_ctrl *priv = container_of(rcdev, struct regclk_ctrl, rcdev); + unsigned long flags; + u32 offset = id >> 5; + u8 bit = id & 0x1f; + u32 val; + + if (WARN_ON(!priv->base)) + return 0; + + spin_lock_irqsave(&priv->lock, flags); + + val = readl(priv->base + offset); + if (priv->rst_set_to_disable) + val |= BIT(bit); + else + val &= ~BIT(bit); + writel(val, priv->base + offset); + + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static const struct reset_control_ops regclk_reset_ops = { + .assert = regclk_reset_assert, + .deassert = regclk_reset_deassert, +}; + +static int regclk_reset_of_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + return (reset_spec->args[0] << 5) | (reset_spec->args[1] & 0x1f); +} + +static void regclk_reset_unsetup(struct device_node *np) +{ + struct regclk_ctrl *priv = np->data; + + reset_controller_unregister(&priv->rcdev); +} + +static int regclk_reset_setup(struct device_node *np, struct regclk_ctrl *priv) +{ + priv->base = of_iomap(np, 0); + priv->rst_set_to_disable = of_property_read_bool(np, "set-to-disable"); + + /* register no matter whether reg exists, to detect dts bug */ + priv->rcdev.ops = ®clk_reset_ops; + priv->rcdev.of_node = np; + priv->rcdev.of_reset_n_cells = 2; + priv->rcdev.of_xlate = regclk_reset_of_xlate; + return reset_controller_register(&priv->rcdev); +} +#else +static void regclk_reset_unsetup(struct device_node *np) +{ +} + +static int regclk_reset_setup(struct device_node *np, struct regclk_ctrl *priv) +{ + return 0; +} +#endif + +/** regclk_ctrl **/ + +static void regclk_ctrl_unsetup(struct device_node *np) +{ + struct device_node *child; + + regclk_reset_unsetup(np); + + for_each_child_of_node(np, child) + regclk_unsetup(child); + + kfree(np->data); +} + +static int regclk_ctrl_setup(struct device_node *np) +{ + struct regclk_ctrl *priv; + struct device_node *child; + int ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + spin_lock_init(&priv->lock); + np->data = priv; + + for_each_child_of_node(np, child) { + ret = regclk_setup(child, priv); + if (ret) + goto err; + } + + ret = regclk_reset_setup(np, priv); + if (ret) + goto err; + + return 0; + +err: + regclk_ctrl_unsetup(np); + return ret; +} + +/** driver **/ + +static void __init regclk_ctrl_init(struct device_node *np) +{ + regclk_ctrl_setup(np); +} +CLK_OF_DECLARE(regclk_ctrl, "reg-clock-controller", regclk_ctrl_init); + +static int regclk_ctrl_remove(struct platform_device *pdev) +{ + regclk_ctrl_unsetup(pdev->dev.of_node); + + return 0; +} + +/* This function is not executed when regclk_ctrl_init succeeded. */ +static int regclk_ctrl_probe(struct platform_device *pdev) +{ + return regclk_ctrl_setup(pdev->dev.of_node); +} + +static const struct of_device_id regclk_ctrl_ids[] = { + { .compatible = "reg-clock-controller" }, + { } +}; + +static struct platform_driver regclk_ctrl_driver = { + .driver = { + .name = "reg_clk_controller", + .of_match_table = regclk_ctrl_ids, + }, + .probe = regclk_ctrl_probe, + .remove = regclk_ctrl_remove, +}; +builtin_platform_driver(regclk_ctrl_driver); -- 2.39.2 ^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-04-18 0:14 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-04-14 18:12 [PATCH 0/2] clk: Add basic register clock controller David Yang 2023-04-14 18:12 ` [PATCH 1/2] dt-bindings: clock: Add reg-clock-controller David Yang 2023-04-14 21:08 ` Krzysztof Kozlowski 2023-04-17 17:47 ` Yangfl 2023-04-17 13:10 ` Rob Herring 2023-04-17 20:49 ` Rob Herring 2023-04-17 21:39 ` Yangfl 2023-04-18 0:14 ` Stephen Boyd 2023-04-14 18:13 ` [PATCH 2/2] clk: Add basic register clock controller David Yang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).