diff options
30 files changed, 1836 insertions, 265 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt index a5160d8cbb5f..b9ec668bfe62 100644 --- a/Documentation/devicetree/bindings/clock/sunxi.txt +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
| @@ -20,12 +20,15 @@ Required properties: | |||
| 20 | "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 | 20 | "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13 |
| 21 | "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s | 21 | "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s |
| 22 | "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 | 22 | "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20 |
| 23 | "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31 | ||
| 23 | "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 | 24 | "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31 |
| 24 | "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 | 25 | "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31 |
| 25 | "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock | 26 | "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock |
| 27 | "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31 | ||
| 26 | "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 | 28 | "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10 |
| 27 | "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 | 29 | "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13 |
| 28 | "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s | 30 | "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s |
| 31 | "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31 | ||
| 29 | "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 | 32 | "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20 |
| 30 | "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock | 33 | "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock |
| 31 | "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing | 34 | "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing |
| @@ -41,6 +44,7 @@ Required properties: | |||
| 41 | "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 | 44 | "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31 |
| 42 | "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 | 45 | "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20 |
| 43 | "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 | 46 | "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13 |
| 47 | "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31 | ||
| 44 | 48 | ||
| 45 | Required properties for all clocks: | 49 | Required properties for all clocks: |
| 46 | - reg : shall be the control register address for the clock. | 50 | - reg : shall be the control register address for the clock. |
diff --git a/Documentation/devicetree/bindings/clock/ti/apll.txt b/Documentation/devicetree/bindings/clock/ti/apll.txt index 7faf5a68b3be..ade4dd4c30f0 100644 --- a/Documentation/devicetree/bindings/clock/ti/apll.txt +++ b/Documentation/devicetree/bindings/clock/ti/apll.txt | |||
| @@ -14,18 +14,32 @@ a subtype of a DPLL [2], although a simplified one at that. | |||
| 14 | [2] Documentation/devicetree/bindings/clock/ti/dpll.txt | 14 | [2] Documentation/devicetree/bindings/clock/ti/dpll.txt |
| 15 | 15 | ||
| 16 | Required properties: | 16 | Required properties: |
| 17 | - compatible : shall be "ti,dra7-apll-clock" | 17 | - compatible : shall be "ti,dra7-apll-clock" or "ti,omap2-apll-clock" |
| 18 | - #clock-cells : from common clock binding; shall be set to 0. | 18 | - #clock-cells : from common clock binding; shall be set to 0. |
| 19 | - clocks : link phandles of parent clocks (clk-ref and clk-bypass) | 19 | - clocks : link phandles of parent clocks (clk-ref and clk-bypass) |
| 20 | - reg : address and length of the register set for controlling the APLL. | 20 | - reg : address and length of the register set for controlling the APLL. |
| 21 | It contains the information of registers in the following order: | 21 | It contains the information of registers in the following order: |
| 22 | "control" - contains the control register base address | 22 | "control" - contains the control register offset |
| 23 | "idlest" - contains the idlest register base address | 23 | "idlest" - contains the idlest register offset |
| 24 | "autoidle" - contains the autoidle register offset (OMAP2 only) | ||
| 25 | - ti,clock-frequency : static clock frequency for the clock (OMAP2 only) | ||
| 26 | - ti,idlest-shift : bit-shift for the idlest field (OMAP2 only) | ||
| 27 | - ti,bit-shift : bit-shift for enable and autoidle fields (OMAP2 only) | ||
| 24 | 28 | ||
| 25 | Examples: | 29 | Examples: |
| 26 | apll_pcie_ck: apll_pcie_ck@4a008200 { | 30 | apll_pcie_ck: apll_pcie_ck { |
| 27 | #clock-cells = <0>; | 31 | #clock-cells = <0>; |
| 28 | clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>; | 32 | clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>; |
| 29 | reg = <0x4a00821c 0x4>, <0x4a008220 0x4>; | 33 | reg = <0x021c>, <0x0220>; |
| 30 | compatible = "ti,dra7-apll-clock"; | 34 | compatible = "ti,dra7-apll-clock"; |
| 31 | }; | 35 | }; |
| 36 | |||
| 37 | apll96_ck: apll96_ck { | ||
| 38 | #clock-cells = <0>; | ||
| 39 | compatible = "ti,omap2-apll-clock"; | ||
| 40 | clocks = <&sys_ck>; | ||
| 41 | ti,bit-shift = <2>; | ||
| 42 | ti,idlest-shift = <8>; | ||
| 43 | ti,clock-frequency = <96000000>; | ||
| 44 | reg = <0x0500>, <0x0530>, <0x0520>; | ||
| 45 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/ti/dpll.txt b/Documentation/devicetree/bindings/clock/ti/dpll.txt index 30bfdb7c9f18..df57009ff8e7 100644 --- a/Documentation/devicetree/bindings/clock/ti/dpll.txt +++ b/Documentation/devicetree/bindings/clock/ti/dpll.txt | |||
| @@ -24,12 +24,14 @@ Required properties: | |||
| 24 | "ti,omap4-dpll-core-clock", | 24 | "ti,omap4-dpll-core-clock", |
| 25 | "ti,omap4-dpll-m4xen-clock", | 25 | "ti,omap4-dpll-m4xen-clock", |
| 26 | "ti,omap4-dpll-j-type-clock", | 26 | "ti,omap4-dpll-j-type-clock", |
| 27 | "ti,omap5-mpu-dpll-clock", | ||
| 27 | "ti,am3-dpll-no-gate-clock", | 28 | "ti,am3-dpll-no-gate-clock", |
| 28 | "ti,am3-dpll-j-type-clock", | 29 | "ti,am3-dpll-j-type-clock", |
| 29 | "ti,am3-dpll-no-gate-j-type-clock", | 30 | "ti,am3-dpll-no-gate-j-type-clock", |
| 30 | "ti,am3-dpll-clock", | 31 | "ti,am3-dpll-clock", |
| 31 | "ti,am3-dpll-core-clock", | 32 | "ti,am3-dpll-core-clock", |
| 32 | "ti,am3-dpll-x2-clock", | 33 | "ti,am3-dpll-x2-clock", |
| 34 | "ti,omap2-dpll-core-clock", | ||
| 33 | 35 | ||
| 34 | - #clock-cells : from common clock binding; shall be set to 0. | 36 | - #clock-cells : from common clock binding; shall be set to 0. |
| 35 | - clocks : link phandles of parent clocks, first entry lists reference clock | 37 | - clocks : link phandles of parent clocks, first entry lists reference clock |
| @@ -41,6 +43,7 @@ Required properties: | |||
| 41 | "mult-div1" - contains the multiplier / divider register base address | 43 | "mult-div1" - contains the multiplier / divider register base address |
| 42 | "autoidle" - contains the autoidle register base address (optional) | 44 | "autoidle" - contains the autoidle register base address (optional) |
| 43 | ti,am3-* dpll types do not have autoidle register | 45 | ti,am3-* dpll types do not have autoidle register |
| 46 | ti,omap2-* dpll type does not support idlest / autoidle registers | ||
| 44 | 47 | ||
| 45 | Optional properties: | 48 | Optional properties: |
| 46 | - DPLL mode setting - defining any one or more of the following overrides | 49 | - DPLL mode setting - defining any one or more of the following overrides |
| @@ -73,3 +76,10 @@ Examples: | |||
| 73 | clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; | 76 | clocks = <&sys_clkin_ck>, <&sys_clkin_ck>; |
| 74 | reg = <0x90>, <0x5c>, <0x68>; | 77 | reg = <0x90>, <0x5c>, <0x68>; |
| 75 | }; | 78 | }; |
| 79 | |||
| 80 | dpll_ck: dpll_ck { | ||
| 81 | #clock-cells = <0>; | ||
| 82 | compatible = "ti,omap2-dpll-core-clock"; | ||
| 83 | clocks = <&sys_ck>, <&sys_ck>; | ||
| 84 | reg = <0x0500>, <0x0540>; | ||
| 85 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt b/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt new file mode 100644 index 000000000000..585e8c191f50 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | Device Tree Clock bindings for ATL (Audio Tracking Logic) of DRA7 SoC. | ||
| 2 | |||
| 3 | The ATL IP is used to generate clock to be used to synchronize baseband and | ||
| 4 | audio codec. A single ATL IP provides four ATL clock instances sharing the same | ||
| 5 | functional clock but can be configured to provide different clocks. | ||
| 6 | ATL can maintain a clock averages to some desired frequency based on the bws/aws | ||
| 7 | signals - can compensate the drift between the two ws signal. | ||
| 8 | |||
| 9 | In order to provide the support for ATL and it's output clocks (which can be used | ||
| 10 | internally within the SoC or external components) two sets of bindings is needed: | ||
| 11 | |||
| 12 | Clock tree binding: | ||
| 13 | This binding uses the common clock binding[1]. | ||
| 14 | To be able to integrate the ATL clocks with DT clock tree. | ||
| 15 | Provides ccf level representation of the ATL clocks to be used by drivers. | ||
| 16 | Since the clock instances are part of a single IP this binding is used as a node | ||
| 17 | for the DT clock tree, the IP driver is needed to handle the actual configuration | ||
| 18 | of the IP. | ||
| 19 | |||
| 20 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 21 | |||
| 22 | Required properties: | ||
| 23 | - compatible : shall be "ti,dra7-atl-clock" | ||
| 24 | - #clock-cells : from common clock binding; shall be set to 0. | ||
| 25 | - clocks : link phandles to functional clock of ATL | ||
| 26 | |||
| 27 | Binding for the IP driver: | ||
| 28 | This binding is used to configure the IP driver which is going to handle the | ||
| 29 | configuration of the IP for the ATL clock instances. | ||
| 30 | |||
| 31 | Required properties: | ||
| 32 | - compatible : shall be "ti,dra7-atl" | ||
| 33 | - reg : base address for the ATL IP | ||
| 34 | - ti,provided-clocks : List of phandles to the clocks associated with the ATL | ||
| 35 | - clocks : link phandles to functional clock of ATL | ||
| 36 | - clock-names : Shall be set to "fck" | ||
| 37 | - ti,hwmods : Shall be set to "atl" | ||
| 38 | |||
| 39 | Optional properties: | ||
| 40 | Configuration of ATL instances: | ||
| 41 | - atl{0/1/2/3} { | ||
| 42 | - bws : Baseband word select signal selection | ||
| 43 | - aws : Audio word select signal selection | ||
| 44 | }; | ||
| 45 | |||
| 46 | For valid word select signals, see the dt-bindings/clk/ti-dra7-atl.h include | ||
| 47 | file. | ||
| 48 | |||
| 49 | Examples: | ||
| 50 | /* clock bindings for atl provided clocks */ | ||
| 51 | atl_clkin0_ck: atl_clkin0_ck { | ||
| 52 | #clock-cells = <0>; | ||
| 53 | compatible = "ti,dra7-atl-clock"; | ||
| 54 | clocks = <&atl_gfclk_mux>; | ||
| 55 | }; | ||
| 56 | |||
| 57 | atl_clkin1_ck: atl_clkin1_ck { | ||
| 58 | #clock-cells = <0>; | ||
| 59 | compatible = "ti,dra7-atl-clock"; | ||
| 60 | clocks = <&atl_gfclk_mux>; | ||
| 61 | }; | ||
| 62 | |||
| 63 | atl_clkin2_ck: atl_clkin2_ck { | ||
| 64 | #clock-cells = <0>; | ||
| 65 | compatible = "ti,dra7-atl-clock"; | ||
| 66 | clocks = <&atl_gfclk_mux>; | ||
| 67 | }; | ||
| 68 | |||
| 69 | atl_clkin3_ck: atl_clkin3_ck { | ||
| 70 | #clock-cells = <0>; | ||
| 71 | compatible = "ti,dra7-atl-clock"; | ||
| 72 | clocks = <&atl_gfclk_mux>; | ||
| 73 | }; | ||
| 74 | |||
| 75 | /* binding for the IP */ | ||
| 76 | atl: atl@4843c000 { | ||
| 77 | compatible = "ti,dra7-atl"; | ||
| 78 | reg = <0x4843c000 0x3ff>; | ||
| 79 | ti,hwmods = "atl"; | ||
| 80 | ti,provided-clocks = <&atl_clkin0_ck>, <&atl_clkin1_ck>, | ||
| 81 | <&atl_clkin2_ck>, <&atl_clkin3_ck>; | ||
| 82 | clocks = <&atl_gfclk_mux>; | ||
| 83 | clock-names = "fck"; | ||
| 84 | status = "disabled"; | ||
| 85 | }; | ||
| 86 | |||
| 87 | #include <dt-bindings/clk/ti-dra7-atl.h> | ||
| 88 | |||
| 89 | &atl { | ||
| 90 | status = "okay"; | ||
| 91 | |||
| 92 | atl2 { | ||
| 93 | bws = <DRA7_ATL_WS_MCASP2_FSX>; | ||
| 94 | aws = <DRA7_ATL_WS_MCASP3_FSX>; | ||
| 95 | }; | ||
| 96 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt index 125281aaa4ca..03f8fdee62a7 100644 --- a/Documentation/devicetree/bindings/clock/ti/gate.txt +++ b/Documentation/devicetree/bindings/clock/ti/gate.txt | |||
| @@ -25,6 +25,11 @@ Required properties: | |||
| 25 | to map clockdomains properly | 25 | to map clockdomains properly |
| 26 | "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling, | 26 | "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling, |
| 27 | required for a hardware errata | 27 | required for a hardware errata |
| 28 | "ti,composite-gate-clock" - composite gate clock, to be part of composite | ||
| 29 | clock | ||
| 30 | "ti,composite-no-wait-gate-clock" - composite gate clock that does not wait | ||
| 31 | for clock to be active before returning | ||
| 32 | from clk_enable() | ||
| 28 | - #clock-cells : from common clock binding; shall be set to 0 | 33 | - #clock-cells : from common clock binding; shall be set to 0 |
| 29 | - clocks : link to phandle of parent clock | 34 | - clocks : link to phandle of parent clock |
| 30 | - reg : offset for register controlling adjustable gate, not needed for | 35 | - reg : offset for register controlling adjustable gate, not needed for |
| @@ -41,7 +46,7 @@ Examples: | |||
| 41 | #clock-cells = <0>; | 46 | #clock-cells = <0>; |
| 42 | compatible = "ti,gate-clock"; | 47 | compatible = "ti,gate-clock"; |
| 43 | clocks = <&core_96m_fck>; | 48 | clocks = <&core_96m_fck>; |
| 44 | reg = <0x48004a00 0x4>; | 49 | reg = <0x0a00>; |
| 45 | ti,bit-shift = <25>; | 50 | ti,bit-shift = <25>; |
| 46 | }; | 51 | }; |
| 47 | 52 | ||
| @@ -57,7 +62,7 @@ Examples: | |||
| 57 | #clock-cells = <0>; | 62 | #clock-cells = <0>; |
| 58 | compatible = "ti,dss-gate-clock"; | 63 | compatible = "ti,dss-gate-clock"; |
| 59 | clocks = <&dpll4_m4x2_ck>; | 64 | clocks = <&dpll4_m4x2_ck>; |
| 60 | reg = <0x48004e00 0x4>; | 65 | reg = <0x0e00>; |
| 61 | ti,bit-shift = <0>; | 66 | ti,bit-shift = <0>; |
| 62 | }; | 67 | }; |
| 63 | 68 | ||
| @@ -65,7 +70,7 @@ Examples: | |||
| 65 | #clock-cells = <0>; | 70 | #clock-cells = <0>; |
| 66 | compatible = "ti,am35xx-gate-clock"; | 71 | compatible = "ti,am35xx-gate-clock"; |
| 67 | clocks = <&ipss_ick>; | 72 | clocks = <&ipss_ick>; |
| 68 | reg = <0x4800259c 0x4>; | 73 | reg = <0x059c>; |
| 69 | ti,bit-shift = <1>; | 74 | ti,bit-shift = <1>; |
| 70 | }; | 75 | }; |
| 71 | 76 | ||
| @@ -80,6 +85,22 @@ Examples: | |||
| 80 | compatible = "ti,hsdiv-gate-clock"; | 85 | compatible = "ti,hsdiv-gate-clock"; |
| 81 | clocks = <&dpll4_m2x2_mul_ck>; | 86 | clocks = <&dpll4_m2x2_mul_ck>; |
| 82 | ti,bit-shift = <0x1b>; | 87 | ti,bit-shift = <0x1b>; |
| 83 | reg = <0x48004d00 0x4>; | 88 | reg = <0x0d00>; |
| 84 | ti,set-bit-to-disable; | 89 | ti,set-bit-to-disable; |
| 85 | }; | 90 | }; |
| 91 | |||
| 92 | vlynq_gate_fck: vlynq_gate_fck { | ||
| 93 | #clock-cells = <0>; | ||
| 94 | compatible = "ti,composite-gate-clock"; | ||
| 95 | clocks = <&core_ck>; | ||
| 96 | ti,bit-shift = <3>; | ||
| 97 | reg = <0x0200>; | ||
| 98 | }; | ||
| 99 | |||
| 100 | sys_clkout2_src_gate: sys_clkout2_src_gate { | ||
| 101 | #clock-cells = <0>; | ||
| 102 | compatible = "ti,composite-no-wait-gate-clock"; | ||
| 103 | clocks = <&core_ck>; | ||
| 104 | ti,bit-shift = <15>; | ||
| 105 | reg = <0x0070>; | ||
| 106 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt index 064e8caccac3..3111a409fea6 100644 --- a/Documentation/devicetree/bindings/clock/ti/interface.txt +++ b/Documentation/devicetree/bindings/clock/ti/interface.txt | |||
| @@ -21,6 +21,8 @@ Required properties: | |||
| 21 | "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling | 21 | "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling |
| 22 | "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling | 22 | "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling |
| 23 | "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling | 23 | "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling |
| 24 | "ti,omap2430-interface-clock" - interface clock with OMAP2430 specific HW | ||
| 25 | handling | ||
| 24 | - #clock-cells : from common clock binding; shall be set to 0 | 26 | - #clock-cells : from common clock binding; shall be set to 0 |
| 25 | - clocks : link to phandle of parent clock | 27 | - clocks : link to phandle of parent clock |
| 26 | - reg : base address for the control register | 28 | - reg : base address for the control register |
diff --git a/arch/arm/boot/dts/dra7xx-clocks.dtsi b/arch/arm/boot/dts/dra7xx-clocks.dtsi index c7676871d9c0..b03cfe49d22b 100644 --- a/arch/arm/boot/dts/dra7xx-clocks.dtsi +++ b/arch/arm/boot/dts/dra7xx-clocks.dtsi | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | clock-frequency = <0>; | 26 | clock-frequency = <0>; |
| 27 | }; | 27 | }; |
| 28 | 28 | ||
| 29 | atlclkin3_ck: atlclkin3_ck { | 29 | atl_clkin3_ck: atl_clkin3_ck { |
| 30 | #clock-cells = <0>; | 30 | #clock-cells = <0>; |
| 31 | compatible = "fixed-clock"; | 31 | compatible = "fixed-clock"; |
| 32 | clock-frequency = <0>; | 32 | clock-frequency = <0>; |
| @@ -277,7 +277,7 @@ | |||
| 277 | 277 | ||
| 278 | dpll_mpu_ck: dpll_mpu_ck { | 278 | dpll_mpu_ck: dpll_mpu_ck { |
| 279 | #clock-cells = <0>; | 279 | #clock-cells = <0>; |
| 280 | compatible = "ti,omap4-dpll-clock"; | 280 | compatible = "ti,omap5-mpu-dpll-clock"; |
| 281 | clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>; | 281 | clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>; |
| 282 | reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; | 282 | reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; |
| 283 | }; | 283 | }; |
| @@ -730,7 +730,7 @@ | |||
| 730 | mcasp1_ahclkr_mux: mcasp1_ahclkr_mux { | 730 | mcasp1_ahclkr_mux: mcasp1_ahclkr_mux { |
| 731 | #clock-cells = <0>; | 731 | #clock-cells = <0>; |
| 732 | compatible = "ti,mux-clock"; | 732 | compatible = "ti,mux-clock"; |
| 733 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 733 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 734 | ti,bit-shift = <28>; | 734 | ti,bit-shift = <28>; |
| 735 | reg = <0x0550>; | 735 | reg = <0x0550>; |
| 736 | }; | 736 | }; |
| @@ -738,7 +738,7 @@ | |||
| 738 | mcasp1_ahclkx_mux: mcasp1_ahclkx_mux { | 738 | mcasp1_ahclkx_mux: mcasp1_ahclkx_mux { |
| 739 | #clock-cells = <0>; | 739 | #clock-cells = <0>; |
| 740 | compatible = "ti,mux-clock"; | 740 | compatible = "ti,mux-clock"; |
| 741 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 741 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 742 | ti,bit-shift = <24>; | 742 | ti,bit-shift = <24>; |
| 743 | reg = <0x0550>; | 743 | reg = <0x0550>; |
| 744 | }; | 744 | }; |
| @@ -1639,7 +1639,7 @@ | |||
| 1639 | mcasp2_ahclkr_mux: mcasp2_ahclkr_mux { | 1639 | mcasp2_ahclkr_mux: mcasp2_ahclkr_mux { |
| 1640 | #clock-cells = <0>; | 1640 | #clock-cells = <0>; |
| 1641 | compatible = "ti,mux-clock"; | 1641 | compatible = "ti,mux-clock"; |
| 1642 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1642 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1643 | ti,bit-shift = <28>; | 1643 | ti,bit-shift = <28>; |
| 1644 | reg = <0x1860>; | 1644 | reg = <0x1860>; |
| 1645 | }; | 1645 | }; |
| @@ -1647,7 +1647,7 @@ | |||
| 1647 | mcasp2_ahclkx_mux: mcasp2_ahclkx_mux { | 1647 | mcasp2_ahclkx_mux: mcasp2_ahclkx_mux { |
| 1648 | #clock-cells = <0>; | 1648 | #clock-cells = <0>; |
| 1649 | compatible = "ti,mux-clock"; | 1649 | compatible = "ti,mux-clock"; |
| 1650 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1650 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1651 | ti,bit-shift = <24>; | 1651 | ti,bit-shift = <24>; |
| 1652 | reg = <0x1860>; | 1652 | reg = <0x1860>; |
| 1653 | }; | 1653 | }; |
| @@ -1663,7 +1663,7 @@ | |||
| 1663 | mcasp3_ahclkx_mux: mcasp3_ahclkx_mux { | 1663 | mcasp3_ahclkx_mux: mcasp3_ahclkx_mux { |
| 1664 | #clock-cells = <0>; | 1664 | #clock-cells = <0>; |
| 1665 | compatible = "ti,mux-clock"; | 1665 | compatible = "ti,mux-clock"; |
| 1666 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1666 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1667 | ti,bit-shift = <24>; | 1667 | ti,bit-shift = <24>; |
| 1668 | reg = <0x1868>; | 1668 | reg = <0x1868>; |
| 1669 | }; | 1669 | }; |
| @@ -1679,7 +1679,7 @@ | |||
| 1679 | mcasp4_ahclkx_mux: mcasp4_ahclkx_mux { | 1679 | mcasp4_ahclkx_mux: mcasp4_ahclkx_mux { |
| 1680 | #clock-cells = <0>; | 1680 | #clock-cells = <0>; |
| 1681 | compatible = "ti,mux-clock"; | 1681 | compatible = "ti,mux-clock"; |
| 1682 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1682 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1683 | ti,bit-shift = <24>; | 1683 | ti,bit-shift = <24>; |
| 1684 | reg = <0x1898>; | 1684 | reg = <0x1898>; |
| 1685 | }; | 1685 | }; |
| @@ -1695,7 +1695,7 @@ | |||
| 1695 | mcasp5_ahclkx_mux: mcasp5_ahclkx_mux { | 1695 | mcasp5_ahclkx_mux: mcasp5_ahclkx_mux { |
| 1696 | #clock-cells = <0>; | 1696 | #clock-cells = <0>; |
| 1697 | compatible = "ti,mux-clock"; | 1697 | compatible = "ti,mux-clock"; |
| 1698 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1698 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1699 | ti,bit-shift = <24>; | 1699 | ti,bit-shift = <24>; |
| 1700 | reg = <0x1878>; | 1700 | reg = <0x1878>; |
| 1701 | }; | 1701 | }; |
| @@ -1711,7 +1711,7 @@ | |||
| 1711 | mcasp6_ahclkx_mux: mcasp6_ahclkx_mux { | 1711 | mcasp6_ahclkx_mux: mcasp6_ahclkx_mux { |
| 1712 | #clock-cells = <0>; | 1712 | #clock-cells = <0>; |
| 1713 | compatible = "ti,mux-clock"; | 1713 | compatible = "ti,mux-clock"; |
| 1714 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1714 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1715 | ti,bit-shift = <24>; | 1715 | ti,bit-shift = <24>; |
| 1716 | reg = <0x1904>; | 1716 | reg = <0x1904>; |
| 1717 | }; | 1717 | }; |
| @@ -1727,7 +1727,7 @@ | |||
| 1727 | mcasp7_ahclkx_mux: mcasp7_ahclkx_mux { | 1727 | mcasp7_ahclkx_mux: mcasp7_ahclkx_mux { |
| 1728 | #clock-cells = <0>; | 1728 | #clock-cells = <0>; |
| 1729 | compatible = "ti,mux-clock"; | 1729 | compatible = "ti,mux-clock"; |
| 1730 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1730 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1731 | ti,bit-shift = <24>; | 1731 | ti,bit-shift = <24>; |
| 1732 | reg = <0x1908>; | 1732 | reg = <0x1908>; |
| 1733 | }; | 1733 | }; |
| @@ -1743,7 +1743,7 @@ | |||
| 1743 | mcasp8_ahclk_mux: mcasp8_ahclk_mux { | 1743 | mcasp8_ahclk_mux: mcasp8_ahclk_mux { |
| 1744 | #clock-cells = <0>; | 1744 | #clock-cells = <0>; |
| 1745 | compatible = "ti,mux-clock"; | 1745 | compatible = "ti,mux-clock"; |
| 1746 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; | 1746 | clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>; |
| 1747 | ti,bit-shift = <22>; | 1747 | ti,bit-shift = <22>; |
| 1748 | reg = <0x1890>; | 1748 | reg = <0x1890>; |
| 1749 | }; | 1749 | }; |
diff --git a/arch/arm/boot/dts/omap54xx-clocks.dtsi b/arch/arm/boot/dts/omap54xx-clocks.dtsi index aeb142ce8e9d..e67a23b5d788 100644 --- a/arch/arm/boot/dts/omap54xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap54xx-clocks.dtsi | |||
| @@ -335,7 +335,7 @@ | |||
| 335 | 335 | ||
| 336 | dpll_mpu_ck: dpll_mpu_ck { | 336 | dpll_mpu_ck: dpll_mpu_ck { |
| 337 | #clock-cells = <0>; | 337 | #clock-cells = <0>; |
| 338 | compatible = "ti,omap4-dpll-clock"; | 338 | compatible = "ti,omap5-mpu-dpll-clock"; |
| 339 | clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>; | 339 | clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>; |
| 340 | reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; | 340 | reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>; |
| 341 | }; | 341 | }; |
diff --git a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c index b935ed2922d8..85e0b0c06718 100644 --- a/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c +++ b/arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c | |||
| @@ -208,3 +208,56 @@ void omap2xxx_clkt_vps_late_init(void) | |||
| 208 | clk_put(c); | 208 | clk_put(c); |
| 209 | } | 209 | } |
| 210 | } | 210 | } |
| 211 | |||
| 212 | #ifdef CONFIG_OF | ||
| 213 | #include <linux/clk-provider.h> | ||
| 214 | #include <linux/clkdev.h> | ||
| 215 | |||
| 216 | static const struct clk_ops virt_prcm_set_ops = { | ||
| 217 | .recalc_rate = &omap2_table_mpu_recalc, | ||
| 218 | .set_rate = &omap2_select_table_rate, | ||
| 219 | .round_rate = &omap2_round_to_table_rate, | ||
| 220 | }; | ||
| 221 | |||
| 222 | /** | ||
| 223 | * omap2xxx_clkt_vps_init - initialize virt_prcm_set clock | ||
| 224 | * | ||
| 225 | * Does a manual init for the virtual prcm DVFS clock for OMAP2. This | ||
| 226 | * function is called only from omap2 DT clock init, as the virtual | ||
| 227 | * node is not modelled in the DT clock data. | ||
| 228 | */ | ||
| 229 | void omap2xxx_clkt_vps_init(void) | ||
| 230 | { | ||
| 231 | struct clk_init_data init = { NULL }; | ||
| 232 | struct clk_hw_omap *hw = NULL; | ||
| 233 | struct clk *clk; | ||
| 234 | const char *parent_name = "mpu_ck"; | ||
| 235 | struct clk_lookup *lookup = NULL; | ||
| 236 | |||
| 237 | omap2xxx_clkt_vps_late_init(); | ||
| 238 | omap2xxx_clkt_vps_check_bootloader_rates(); | ||
| 239 | |||
| 240 | hw = kzalloc(sizeof(*hw), GFP_KERNEL); | ||
| 241 | lookup = kzalloc(sizeof(*lookup), GFP_KERNEL); | ||
| 242 | if (!hw || !lookup) | ||
| 243 | goto cleanup; | ||
| 244 | init.name = "virt_prcm_set"; | ||
| 245 | init.ops = &virt_prcm_set_ops; | ||
| 246 | init.parent_names = &parent_name; | ||
| 247 | init.num_parents = 1; | ||
| 248 | |||
| 249 | hw->hw.init = &init; | ||
| 250 | |||
| 251 | clk = clk_register(NULL, &hw->hw); | ||
| 252 | |||
| 253 | lookup->dev_id = NULL; | ||
| 254 | lookup->con_id = "cpufreq_ck"; | ||
| 255 | lookup->clk = clk; | ||
| 256 | |||
| 257 | clkdev_add(lookup); | ||
| 258 | return; | ||
| 259 | cleanup: | ||
| 260 | kfree(hw); | ||
| 261 | kfree(lookup); | ||
| 262 | } | ||
| 263 | #endif | ||
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h index bda767a9dea8..12f54d428d7c 100644 --- a/arch/arm/mach-omap2/clock.h +++ b/arch/arm/mach-omap2/clock.h | |||
| @@ -178,17 +178,6 @@ struct clksel { | |||
| 178 | const struct clksel_rate *rates; | 178 | const struct clksel_rate *rates; |
| 179 | }; | 179 | }; |
| 180 | 180 | ||
| 181 | struct clk_hw_omap_ops { | ||
| 182 | void (*find_idlest)(struct clk_hw_omap *oclk, | ||
| 183 | void __iomem **idlest_reg, | ||
| 184 | u8 *idlest_bit, u8 *idlest_val); | ||
| 185 | void (*find_companion)(struct clk_hw_omap *oclk, | ||
| 186 | void __iomem **other_reg, | ||
| 187 | u8 *other_bit); | ||
| 188 | void (*allow_idle)(struct clk_hw_omap *oclk); | ||
| 189 | void (*deny_idle)(struct clk_hw_omap *oclk); | ||
| 190 | }; | ||
| 191 | |||
| 192 | unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw, | 181 | unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw, |
| 193 | unsigned long parent_rate); | 182 | unsigned long parent_rate); |
| 194 | 183 | ||
| @@ -279,8 +268,6 @@ extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait; | |||
| 279 | extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; | 268 | extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait; |
| 280 | extern const struct clk_hw_omap_ops clkhwops_apll54; | 269 | extern const struct clk_hw_omap_ops clkhwops_apll54; |
| 281 | extern const struct clk_hw_omap_ops clkhwops_apll96; | 270 | extern const struct clk_hw_omap_ops clkhwops_apll96; |
| 282 | extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; | ||
| 283 | extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait; | ||
| 284 | 271 | ||
| 285 | /* clksel_rate blocks shared between OMAP44xx and AM33xx */ | 272 | /* clksel_rate blocks shared between OMAP44xx and AM33xx */ |
| 286 | extern const struct clksel_rate div_1_0_rates[]; | 273 | extern const struct clksel_rate div_1_0_rates[]; |
diff --git a/arch/arm/mach-omap2/clock2xxx.h b/arch/arm/mach-omap2/clock2xxx.h index 539dc08afbba..45f41a411603 100644 --- a/arch/arm/mach-omap2/clock2xxx.h +++ b/arch/arm/mach-omap2/clock2xxx.h | |||
| @@ -21,10 +21,6 @@ unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk, | |||
| 21 | unsigned long parent_rate); | 21 | unsigned long parent_rate); |
| 22 | unsigned long omap2_osc_clk_recalc(struct clk_hw *clk, | 22 | unsigned long omap2_osc_clk_recalc(struct clk_hw *clk, |
| 23 | unsigned long parent_rate); | 23 | unsigned long parent_rate); |
| 24 | unsigned long omap2_dpllcore_recalc(struct clk_hw *hw, | ||
| 25 | unsigned long parent_rate); | ||
| 26 | int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate, | ||
| 27 | unsigned long parent_rate); | ||
| 28 | void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); | 24 | void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); |
| 29 | unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw, | 25 | unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw, |
| 30 | unsigned long parent_rate); | 26 | unsigned long parent_rate); |
diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c index fcd8036af910..6d7ba37e2257 100644 --- a/arch/arm/mach-omap2/dpll3xxx.c +++ b/arch/arm/mach-omap2/dpll3xxx.c | |||
| @@ -319,6 +319,15 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel) | |||
| 319 | 319 | ||
| 320 | /* Set DPLL multiplier, divider */ | 320 | /* Set DPLL multiplier, divider */ |
| 321 | v = omap2_clk_readl(clk, dd->mult_div1_reg); | 321 | v = omap2_clk_readl(clk, dd->mult_div1_reg); |
| 322 | |||
| 323 | /* Handle Duty Cycle Correction */ | ||
| 324 | if (dd->dcc_mask) { | ||
| 325 | if (dd->last_rounded_rate >= dd->dcc_rate) | ||
| 326 | v |= dd->dcc_mask; /* Enable DCC */ | ||
| 327 | else | ||
| 328 | v &= ~dd->dcc_mask; /* Disable DCC */ | ||
| 329 | } | ||
| 330 | |||
| 322 | v &= ~(dd->mult_mask | dd->div1_mask); | 331 | v &= ~(dd->mult_mask | dd->div1_mask); |
| 323 | v |= dd->last_rounded_m << __ffs(dd->mult_mask); | 332 | v |= dd->last_rounded_m << __ffs(dd->mult_mask); |
| 324 | v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask); | 333 | v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask); |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile index b5bac917612c..762fd64dbd1f 100644 --- a/drivers/clk/sunxi/Makefile +++ b/drivers/clk/sunxi/Makefile | |||
| @@ -3,3 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-y += clk-sunxi.o clk-factors.o | 5 | obj-y += clk-sunxi.o clk-factors.o |
| 6 | obj-y += clk-a10-hosc.o | ||
| 7 | obj-y += clk-a20-gmac.o | ||
| 8 | |||
| 9 | obj-$(CONFIG_MFD_SUN6I_PRCM) += clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o | ||
diff --git a/drivers/clk/sunxi/clk-a10-hosc.c b/drivers/clk/sunxi/clk-a10-hosc.c new file mode 100644 index 000000000000..0481d5d673d6 --- /dev/null +++ b/drivers/clk/sunxi/clk-a10-hosc.c | |||
| @@ -0,0 +1,73 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2013 Emilio López | ||
| 3 | * | ||
| 4 | * Emilio López <emilio@elopez.com.ar> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/clk-provider.h> | ||
| 18 | #include <linux/clkdev.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_address.h> | ||
| 21 | |||
| 22 | #define SUNXI_OSC24M_GATE 0 | ||
| 23 | |||
| 24 | static DEFINE_SPINLOCK(hosc_lock); | ||
| 25 | |||
| 26 | static void __init sun4i_osc_clk_setup(struct device_node *node) | ||
| 27 | { | ||
| 28 | struct clk *clk; | ||
| 29 | struct clk_fixed_rate *fixed; | ||
| 30 | struct clk_gate *gate; | ||
| 31 | const char *clk_name = node->name; | ||
| 32 | u32 rate; | ||
| 33 | |||
| 34 | if (of_property_read_u32(node, "clock-frequency", &rate)) | ||
| 35 | return; | ||
| 36 | |||
| 37 | /* allocate fixed-rate and gate clock structs */ | ||
| 38 | fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); | ||
| 39 | if (!fixed) | ||
| 40 | return; | ||
| 41 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
| 42 | if (!gate) | ||
| 43 | goto err_free_fixed; | ||
| 44 | |||
| 45 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
| 46 | |||
| 47 | /* set up gate and fixed rate properties */ | ||
| 48 | gate->reg = of_iomap(node, 0); | ||
| 49 | gate->bit_idx = SUNXI_OSC24M_GATE; | ||
| 50 | gate->lock = &hosc_lock; | ||
| 51 | fixed->fixed_rate = rate; | ||
| 52 | |||
| 53 | clk = clk_register_composite(NULL, clk_name, | ||
| 54 | NULL, 0, | ||
| 55 | NULL, NULL, | ||
| 56 | &fixed->hw, &clk_fixed_rate_ops, | ||
| 57 | &gate->hw, &clk_gate_ops, | ||
| 58 | CLK_IS_ROOT); | ||
| 59 | |||
| 60 | if (IS_ERR(clk)) | ||
| 61 | goto err_free_gate; | ||
| 62 | |||
| 63 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 64 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 65 | |||
| 66 | return; | ||
| 67 | |||
| 68 | err_free_gate: | ||
| 69 | kfree(gate); | ||
| 70 | err_free_fixed: | ||
| 71 | kfree(fixed); | ||
| 72 | } | ||
| 73 | CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup); | ||
diff --git a/drivers/clk/sunxi/clk-a20-gmac.c b/drivers/clk/sunxi/clk-a20-gmac.c new file mode 100644 index 000000000000..633ddc4389ef --- /dev/null +++ b/drivers/clk/sunxi/clk-a20-gmac.c | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2013 Emilio López | ||
| 3 | * Emilio López <emilio@elopez.com.ar> | ||
| 4 | * | ||
| 5 | * Copyright 2013 Chen-Yu Tsai | ||
| 6 | * Chen-Yu Tsai <wens@csie.org> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This program is distributed in the hope that it will be useful, | ||
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | * GNU General Public License for more details. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/clk-provider.h> | ||
| 20 | #include <linux/clkdev.h> | ||
| 21 | #include <linux/of.h> | ||
| 22 | #include <linux/of_address.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | |||
| 25 | static DEFINE_SPINLOCK(gmac_lock); | ||
| 26 | |||
| 27 | /** | ||
| 28 | * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module | ||
| 29 | * | ||
| 30 | * This clock looks something like this | ||
| 31 | * ________________________ | ||
| 32 | * MII TX clock from PHY >-----|___________ _________|----> to GMAC core | ||
| 33 | * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY | ||
| 34 | * Ext. 125MHz RGMII TX clk >--|__divider__/ | | ||
| 35 | * |________________________| | ||
| 36 | * | ||
| 37 | * The external 125 MHz reference is optional, i.e. GMAC can use its | ||
| 38 | * internal TX clock just fine. The A31 GMAC clock module does not have | ||
| 39 | * the divider controls for the external reference. | ||
| 40 | * | ||
| 41 | * To keep it simple, let the GMAC use either the MII TX clock for MII mode, | ||
| 42 | * and its internal TX clock for GMII and RGMII modes. The GMAC driver should | ||
| 43 | * select the appropriate source and gate/ungate the output to the PHY. | ||
| 44 | * | ||
| 45 | * Only the GMAC should use this clock. Altering the clock so that it doesn't | ||
| 46 | * match the GMAC's operation parameters will result in the GMAC not being | ||
| 47 | * able to send traffic out. The GMAC driver should set the clock rate and | ||
| 48 | * enable/disable this clock to configure the required state. The clock | ||
| 49 | * driver then responds by auto-reparenting the clock. | ||
| 50 | */ | ||
| 51 | |||
| 52 | #define SUN7I_A20_GMAC_GPIT 2 | ||
| 53 | #define SUN7I_A20_GMAC_MASK 0x3 | ||
| 54 | #define SUN7I_A20_GMAC_PARENTS 2 | ||
| 55 | |||
| 56 | static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) | ||
| 57 | { | ||
| 58 | struct clk *clk; | ||
| 59 | struct clk_mux *mux; | ||
| 60 | struct clk_gate *gate; | ||
| 61 | const char *clk_name = node->name; | ||
| 62 | const char *parents[SUN7I_A20_GMAC_PARENTS]; | ||
| 63 | void *reg; | ||
| 64 | |||
| 65 | if (of_property_read_string(node, "clock-output-names", &clk_name)) | ||
| 66 | return; | ||
| 67 | |||
| 68 | /* allocate mux and gate clock structs */ | ||
| 69 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | ||
| 70 | if (!mux) | ||
| 71 | return; | ||
| 72 | |||
| 73 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
| 74 | if (!gate) | ||
| 75 | goto free_mux; | ||
| 76 | |||
| 77 | /* gmac clock requires exactly 2 parents */ | ||
| 78 | parents[0] = of_clk_get_parent_name(node, 0); | ||
| 79 | parents[1] = of_clk_get_parent_name(node, 1); | ||
| 80 | if (!parents[0] || !parents[1]) | ||
| 81 | goto free_gate; | ||
| 82 | |||
| 83 | reg = of_iomap(node, 0); | ||
| 84 | if (!reg) | ||
| 85 | goto free_gate; | ||
| 86 | |||
| 87 | /* set up gate and fixed rate properties */ | ||
| 88 | gate->reg = reg; | ||
| 89 | gate->bit_idx = SUN7I_A20_GMAC_GPIT; | ||
| 90 | gate->lock = &gmac_lock; | ||
| 91 | mux->reg = reg; | ||
| 92 | mux->mask = SUN7I_A20_GMAC_MASK; | ||
| 93 | mux->flags = CLK_MUX_INDEX_BIT; | ||
| 94 | mux->lock = &gmac_lock; | ||
| 95 | |||
| 96 | clk = clk_register_composite(NULL, clk_name, | ||
| 97 | parents, SUN7I_A20_GMAC_PARENTS, | ||
| 98 | &mux->hw, &clk_mux_ops, | ||
| 99 | NULL, NULL, | ||
| 100 | &gate->hw, &clk_gate_ops, | ||
| 101 | 0); | ||
| 102 | |||
| 103 | if (IS_ERR(clk)) | ||
| 104 | goto iounmap_reg; | ||
| 105 | |||
| 106 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 107 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 108 | |||
| 109 | return; | ||
| 110 | |||
| 111 | iounmap_reg: | ||
| 112 | iounmap(reg); | ||
| 113 | free_gate: | ||
| 114 | kfree(gate); | ||
| 115 | free_mux: | ||
| 116 | kfree(mux); | ||
| 117 | } | ||
| 118 | CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk", | ||
| 119 | sun7i_a20_gmac_clk_setup); | ||
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c new file mode 100644 index 000000000000..44cd27c5c401 --- /dev/null +++ b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c | |||
| @@ -0,0 +1,99 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Free Electrons | ||
| 3 | * | ||
| 4 | * License Terms: GNU General Public License v2 | ||
| 5 | * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> | ||
| 6 | * | ||
| 7 | * Allwinner A31 APB0 clock gates driver | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk-provider.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | |||
| 16 | #define SUN6I_APB0_GATES_MAX_SIZE 32 | ||
| 17 | |||
| 18 | static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev) | ||
| 19 | { | ||
| 20 | struct device_node *np = pdev->dev.of_node; | ||
| 21 | struct clk_onecell_data *clk_data; | ||
| 22 | const char *clk_parent; | ||
| 23 | const char *clk_name; | ||
| 24 | struct resource *r; | ||
| 25 | void __iomem *reg; | ||
| 26 | int gate_id; | ||
| 27 | int ngates; | ||
| 28 | int i; | ||
| 29 | |||
| 30 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 31 | reg = devm_ioremap_resource(&pdev->dev, r); | ||
| 32 | if (!reg) | ||
| 33 | return PTR_ERR(reg); | ||
| 34 | |||
| 35 | clk_parent = of_clk_get_parent_name(np, 0); | ||
| 36 | if (!clk_parent) | ||
| 37 | return -EINVAL; | ||
| 38 | |||
| 39 | ngates = of_property_count_strings(np, "clock-output-names"); | ||
| 40 | if (ngates < 0) | ||
| 41 | return ngates; | ||
| 42 | |||
| 43 | if (!ngates || ngates > SUN6I_APB0_GATES_MAX_SIZE) | ||
| 44 | return -EINVAL; | ||
| 45 | |||
| 46 | clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), | ||
| 47 | GFP_KERNEL); | ||
| 48 | if (!clk_data) | ||
| 49 | return -ENOMEM; | ||
| 50 | |||
| 51 | clk_data->clks = devm_kzalloc(&pdev->dev, | ||
| 52 | SUN6I_APB0_GATES_MAX_SIZE * | ||
| 53 | sizeof(struct clk *), | ||
| 54 | GFP_KERNEL); | ||
| 55 | if (!clk_data->clks) | ||
| 56 | return -ENOMEM; | ||
| 57 | |||
| 58 | for (i = 0; i < ngates; i++) { | ||
| 59 | of_property_read_string_index(np, "clock-output-names", | ||
| 60 | i, &clk_name); | ||
| 61 | |||
| 62 | gate_id = i; | ||
| 63 | of_property_read_u32_index(np, "clock-indices", i, &gate_id); | ||
| 64 | |||
| 65 | WARN_ON(gate_id >= SUN6I_APB0_GATES_MAX_SIZE); | ||
| 66 | if (gate_id >= SUN6I_APB0_GATES_MAX_SIZE) | ||
| 67 | continue; | ||
| 68 | |||
| 69 | clk_data->clks[gate_id] = clk_register_gate(&pdev->dev, | ||
| 70 | clk_name, | ||
| 71 | clk_parent, 0, | ||
| 72 | reg, gate_id, | ||
| 73 | 0, NULL); | ||
| 74 | WARN_ON(IS_ERR(clk_data->clks[gate_id])); | ||
| 75 | } | ||
| 76 | |||
| 77 | clk_data->clk_num = ngates; | ||
| 78 | |||
| 79 | return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); | ||
| 80 | } | ||
| 81 | |||
| 82 | const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = { | ||
| 83 | { .compatible = "allwinner,sun6i-a31-apb0-gates-clk" }, | ||
| 84 | { /* sentinel */ } | ||
| 85 | }; | ||
| 86 | |||
| 87 | static struct platform_driver sun6i_a31_apb0_gates_clk_driver = { | ||
| 88 | .driver = { | ||
| 89 | .name = "sun6i-a31-apb0-gates-clk", | ||
| 90 | .owner = THIS_MODULE, | ||
| 91 | .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids, | ||
| 92 | }, | ||
| 93 | .probe = sun6i_a31_apb0_gates_clk_probe, | ||
| 94 | }; | ||
| 95 | module_platform_driver(sun6i_a31_apb0_gates_clk_driver); | ||
| 96 | |||
| 97 | MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>"); | ||
| 98 | MODULE_DESCRIPTION("Allwinner A31 APB0 gate clocks driver"); | ||
| 99 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c new file mode 100644 index 000000000000..11f17c34c2ae --- /dev/null +++ b/drivers/clk/sunxi/clk-sun6i-apb0.c | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Free Electrons | ||
| 3 | * | ||
| 4 | * License Terms: GNU General Public License v2 | ||
| 5 | * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> | ||
| 6 | * | ||
| 7 | * Allwinner A31 APB0 clock driver | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk-provider.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | |||
| 16 | /* | ||
| 17 | * The APB0 clk has a configurable divisor. | ||
| 18 | * | ||
| 19 | * We must use a clk_div_table and not a regular power of 2 | ||
| 20 | * divisor here, because the first 2 values divide the clock | ||
| 21 | * by 2. | ||
| 22 | */ | ||
| 23 | static const struct clk_div_table sun6i_a31_apb0_divs[] = { | ||
| 24 | { .val = 0, .div = 2, }, | ||
| 25 | { .val = 1, .div = 2, }, | ||
| 26 | { .val = 2, .div = 4, }, | ||
| 27 | { .val = 3, .div = 8, }, | ||
| 28 | { /* sentinel */ }, | ||
| 29 | }; | ||
| 30 | |||
| 31 | static int sun6i_a31_apb0_clk_probe(struct platform_device *pdev) | ||
| 32 | { | ||
| 33 | struct device_node *np = pdev->dev.of_node; | ||
| 34 | const char *clk_name = np->name; | ||
| 35 | const char *clk_parent; | ||
| 36 | struct resource *r; | ||
| 37 | void __iomem *reg; | ||
| 38 | struct clk *clk; | ||
| 39 | |||
| 40 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 41 | reg = devm_ioremap_resource(&pdev->dev, r); | ||
| 42 | if (IS_ERR(reg)) | ||
| 43 | return PTR_ERR(reg); | ||
| 44 | |||
| 45 | clk_parent = of_clk_get_parent_name(np, 0); | ||
| 46 | if (!clk_parent) | ||
| 47 | return -EINVAL; | ||
| 48 | |||
| 49 | of_property_read_string(np, "clock-output-names", &clk_name); | ||
| 50 | |||
| 51 | clk = clk_register_divider_table(&pdev->dev, clk_name, clk_parent, | ||
| 52 | 0, reg, 0, 2, 0, sun6i_a31_apb0_divs, | ||
| 53 | NULL); | ||
| 54 | if (IS_ERR(clk)) | ||
| 55 | return PTR_ERR(clk); | ||
| 56 | |||
| 57 | return of_clk_add_provider(np, of_clk_src_simple_get, clk); | ||
| 58 | } | ||
| 59 | |||
| 60 | const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = { | ||
| 61 | { .compatible = "allwinner,sun6i-a31-apb0-clk" }, | ||
| 62 | { /* sentinel */ } | ||
| 63 | }; | ||
| 64 | |||
| 65 | static struct platform_driver sun6i_a31_apb0_clk_driver = { | ||
| 66 | .driver = { | ||
| 67 | .name = "sun6i-a31-apb0-clk", | ||
| 68 | .owner = THIS_MODULE, | ||
| 69 | .of_match_table = sun6i_a31_apb0_clk_dt_ids, | ||
| 70 | }, | ||
| 71 | .probe = sun6i_a31_apb0_clk_probe, | ||
| 72 | }; | ||
| 73 | module_platform_driver(sun6i_a31_apb0_clk_driver); | ||
| 74 | |||
| 75 | MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>"); | ||
| 76 | MODULE_DESCRIPTION("Allwinner A31 APB0 clock Driver"); | ||
| 77 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c new file mode 100644 index 000000000000..f73cc051f0dd --- /dev/null +++ b/drivers/clk/sunxi/clk-sun6i-ar100.c | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Free Electrons | ||
| 3 | * | ||
| 4 | * License Terms: GNU General Public License v2 | ||
| 5 | * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> | ||
| 6 | * | ||
| 7 | * Allwinner A31 AR100 clock driver | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk-provider.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/of.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | |||
| 16 | #define SUN6I_AR100_MAX_PARENTS 4 | ||
| 17 | #define SUN6I_AR100_SHIFT_MASK 0x3 | ||
| 18 | #define SUN6I_AR100_SHIFT_MAX SUN6I_AR100_SHIFT_MASK | ||
| 19 | #define SUN6I_AR100_SHIFT_SHIFT 4 | ||
| 20 | #define SUN6I_AR100_DIV_MASK 0x1f | ||
| 21 | #define SUN6I_AR100_DIV_MAX (SUN6I_AR100_DIV_MASK + 1) | ||
| 22 | #define SUN6I_AR100_DIV_SHIFT 8 | ||
| 23 | #define SUN6I_AR100_MUX_MASK 0x3 | ||
| 24 | #define SUN6I_AR100_MUX_SHIFT 16 | ||
| 25 | |||
| 26 | struct ar100_clk { | ||
| 27 | struct clk_hw hw; | ||
| 28 | void __iomem *reg; | ||
| 29 | }; | ||
| 30 | |||
| 31 | static inline struct ar100_clk *to_ar100_clk(struct clk_hw *hw) | ||
| 32 | { | ||
| 33 | return container_of(hw, struct ar100_clk, hw); | ||
| 34 | } | ||
| 35 | |||
| 36 | static unsigned long ar100_recalc_rate(struct clk_hw *hw, | ||
| 37 | unsigned long parent_rate) | ||
| 38 | { | ||
| 39 | struct ar100_clk *clk = to_ar100_clk(hw); | ||
| 40 | u32 val = readl(clk->reg); | ||
| 41 | int shift = (val >> SUN6I_AR100_SHIFT_SHIFT) & SUN6I_AR100_SHIFT_MASK; | ||
| 42 | int div = (val >> SUN6I_AR100_DIV_SHIFT) & SUN6I_AR100_DIV_MASK; | ||
| 43 | |||
| 44 | return (parent_rate >> shift) / (div + 1); | ||
| 45 | } | ||
| 46 | |||
| 47 | static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate, | ||
| 48 | unsigned long *best_parent_rate, | ||
| 49 | struct clk **best_parent_clk) | ||
| 50 | { | ||
| 51 | int nparents = __clk_get_num_parents(hw->clk); | ||
| 52 | long best_rate = -EINVAL; | ||
| 53 | int i; | ||
| 54 | |||
| 55 | *best_parent_clk = NULL; | ||
| 56 | |||
| 57 | for (i = 0; i < nparents; i++) { | ||
| 58 | unsigned long parent_rate; | ||
| 59 | unsigned long tmp_rate; | ||
| 60 | struct clk *parent; | ||
| 61 | unsigned long div; | ||
| 62 | int shift; | ||
| 63 | |||
| 64 | parent = clk_get_parent_by_index(hw->clk, i); | ||
| 65 | parent_rate = __clk_get_rate(parent); | ||
| 66 | div = DIV_ROUND_UP(parent_rate, rate); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * The AR100 clk contains 2 divisors: | ||
| 70 | * - one power of 2 divisor | ||
| 71 | * - one regular divisor | ||
| 72 | * | ||
| 73 | * First check if we can safely shift (or divide by a power | ||
| 74 | * of 2) without losing precision on the requested rate. | ||
| 75 | */ | ||
| 76 | shift = ffs(div) - 1; | ||
| 77 | if (shift > SUN6I_AR100_SHIFT_MAX) | ||
| 78 | shift = SUN6I_AR100_SHIFT_MAX; | ||
| 79 | |||
| 80 | div >>= shift; | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Then if the divisor is still bigger than what the HW | ||
| 84 | * actually supports, use a bigger shift (or power of 2 | ||
| 85 | * divider) value and accept to lose some precision. | ||
| 86 | */ | ||
| 87 | while (div > SUN6I_AR100_DIV_MAX) { | ||
| 88 | shift++; | ||
| 89 | div >>= 1; | ||
| 90 | if (shift > SUN6I_AR100_SHIFT_MAX) | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* | ||
| 95 | * If the shift value (or power of 2 divider) is bigger | ||
| 96 | * than what the HW actually support, skip this parent. | ||
| 97 | */ | ||
| 98 | if (shift > SUN6I_AR100_SHIFT_MAX) | ||
| 99 | continue; | ||
| 100 | |||
| 101 | tmp_rate = (parent_rate >> shift) / div; | ||
| 102 | if (!*best_parent_clk || tmp_rate > best_rate) { | ||
| 103 | *best_parent_clk = parent; | ||
| 104 | *best_parent_rate = parent_rate; | ||
| 105 | best_rate = tmp_rate; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | return best_rate; | ||
| 110 | } | ||
| 111 | |||
| 112 | static int ar100_set_parent(struct clk_hw *hw, u8 index) | ||
| 113 | { | ||
| 114 | struct ar100_clk *clk = to_ar100_clk(hw); | ||
| 115 | u32 val = readl(clk->reg); | ||
| 116 | |||
| 117 | if (index >= SUN6I_AR100_MAX_PARENTS) | ||
| 118 | return -EINVAL; | ||
| 119 | |||
| 120 | val &= ~(SUN6I_AR100_MUX_MASK << SUN6I_AR100_MUX_SHIFT); | ||
| 121 | val |= (index << SUN6I_AR100_MUX_SHIFT); | ||
| 122 | writel(val, clk->reg); | ||
| 123 | |||
| 124 | return 0; | ||
| 125 | } | ||
| 126 | |||
| 127 | static u8 ar100_get_parent(struct clk_hw *hw) | ||
| 128 | { | ||
| 129 | struct ar100_clk *clk = to_ar100_clk(hw); | ||
| 130 | return (readl(clk->reg) >> SUN6I_AR100_MUX_SHIFT) & | ||
| 131 | SUN6I_AR100_MUX_MASK; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int ar100_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 135 | unsigned long parent_rate) | ||
| 136 | { | ||
| 137 | unsigned long div = parent_rate / rate; | ||
| 138 | struct ar100_clk *clk = to_ar100_clk(hw); | ||
| 139 | u32 val = readl(clk->reg); | ||
| 140 | int shift; | ||
| 141 | |||
| 142 | if (parent_rate % rate) | ||
| 143 | return -EINVAL; | ||
| 144 | |||
| 145 | shift = ffs(div) - 1; | ||
| 146 | if (shift > SUN6I_AR100_SHIFT_MAX) | ||
| 147 | shift = SUN6I_AR100_SHIFT_MAX; | ||
| 148 | |||
| 149 | div >>= shift; | ||
| 150 | |||
| 151 | if (div > SUN6I_AR100_DIV_MAX) | ||
| 152 | return -EINVAL; | ||
| 153 | |||
| 154 | val &= ~((SUN6I_AR100_SHIFT_MASK << SUN6I_AR100_SHIFT_SHIFT) | | ||
| 155 | (SUN6I_AR100_DIV_MASK << SUN6I_AR100_DIV_SHIFT)); | ||
| 156 | val |= (shift << SUN6I_AR100_SHIFT_SHIFT) | | ||
| 157 | (div << SUN6I_AR100_DIV_SHIFT); | ||
| 158 | writel(val, clk->reg); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | struct clk_ops ar100_ops = { | ||
| 164 | .recalc_rate = ar100_recalc_rate, | ||
| 165 | .determine_rate = ar100_determine_rate, | ||
| 166 | .set_parent = ar100_set_parent, | ||
| 167 | .get_parent = ar100_get_parent, | ||
| 168 | .set_rate = ar100_set_rate, | ||
| 169 | }; | ||
| 170 | |||
| 171 | static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev) | ||
| 172 | { | ||
| 173 | const char *parents[SUN6I_AR100_MAX_PARENTS]; | ||
| 174 | struct device_node *np = pdev->dev.of_node; | ||
| 175 | const char *clk_name = np->name; | ||
| 176 | struct clk_init_data init; | ||
| 177 | struct ar100_clk *ar100; | ||
| 178 | struct resource *r; | ||
| 179 | struct clk *clk; | ||
| 180 | int nparents; | ||
| 181 | int i; | ||
| 182 | |||
| 183 | ar100 = devm_kzalloc(&pdev->dev, sizeof(*ar100), GFP_KERNEL); | ||
| 184 | if (!ar100) | ||
| 185 | return -ENOMEM; | ||
| 186 | |||
| 187 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 188 | ar100->reg = devm_ioremap_resource(&pdev->dev, r); | ||
| 189 | if (IS_ERR(ar100->reg)) | ||
| 190 | return PTR_ERR(ar100->reg); | ||
| 191 | |||
| 192 | nparents = of_clk_get_parent_count(np); | ||
| 193 | if (nparents > SUN6I_AR100_MAX_PARENTS) | ||
| 194 | nparents = SUN6I_AR100_MAX_PARENTS; | ||
| 195 | |||
| 196 | for (i = 0; i < nparents; i++) | ||
| 197 | parents[i] = of_clk_get_parent_name(np, i); | ||
| 198 | |||
| 199 | of_property_read_string(np, "clock-output-names", &clk_name); | ||
| 200 | |||
| 201 | init.name = clk_name; | ||
| 202 | init.ops = &ar100_ops; | ||
| 203 | init.parent_names = parents; | ||
| 204 | init.num_parents = nparents; | ||
| 205 | init.flags = 0; | ||
| 206 | |||
| 207 | ar100->hw.init = &init; | ||
| 208 | |||
| 209 | clk = clk_register(&pdev->dev, &ar100->hw); | ||
| 210 | if (IS_ERR(clk)) | ||
| 211 | return PTR_ERR(clk); | ||
| 212 | |||
| 213 | return of_clk_add_provider(np, of_clk_src_simple_get, clk); | ||
| 214 | } | ||
| 215 | |||
| 216 | const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = { | ||
| 217 | { .compatible = "allwinner,sun6i-a31-ar100-clk" }, | ||
| 218 | { /* sentinel */ } | ||
| 219 | }; | ||
| 220 | |||
| 221 | static struct platform_driver sun6i_a31_ar100_clk_driver = { | ||
| 222 | .driver = { | ||
| 223 | .name = "sun6i-a31-ar100-clk", | ||
| 224 | .owner = THIS_MODULE, | ||
| 225 | .of_match_table = sun6i_a31_ar100_clk_dt_ids, | ||
| 226 | }, | ||
| 227 | .probe = sun6i_a31_ar100_clk_probe, | ||
| 228 | }; | ||
| 229 | module_platform_driver(sun6i_a31_ar100_clk_driver); | ||
| 230 | |||
| 231 | MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>"); | ||
| 232 | MODULE_DESCRIPTION("Allwinner A31 AR100 clock Driver"); | ||
| 233 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index 426483422d3d..fb2ce8440f0e 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
| @@ -28,63 +28,6 @@ static DEFINE_SPINLOCK(clk_lock); | |||
| 28 | #define SUNXI_MAX_PARENTS 5 | 28 | #define SUNXI_MAX_PARENTS 5 |
| 29 | 29 | ||
| 30 | /** | 30 | /** |
| 31 | * sun4i_osc_clk_setup() - Setup function for gatable oscillator | ||
| 32 | */ | ||
| 33 | |||
| 34 | #define SUNXI_OSC24M_GATE 0 | ||
| 35 | |||
| 36 | static void __init sun4i_osc_clk_setup(struct device_node *node) | ||
| 37 | { | ||
| 38 | struct clk *clk; | ||
| 39 | struct clk_fixed_rate *fixed; | ||
| 40 | struct clk_gate *gate; | ||
| 41 | const char *clk_name = node->name; | ||
| 42 | u32 rate; | ||
| 43 | |||
| 44 | if (of_property_read_u32(node, "clock-frequency", &rate)) | ||
| 45 | return; | ||
| 46 | |||
| 47 | /* allocate fixed-rate and gate clock structs */ | ||
| 48 | fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); | ||
| 49 | if (!fixed) | ||
| 50 | return; | ||
| 51 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
| 52 | if (!gate) | ||
| 53 | goto err_free_fixed; | ||
| 54 | |||
| 55 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
| 56 | |||
| 57 | /* set up gate and fixed rate properties */ | ||
| 58 | gate->reg = of_iomap(node, 0); | ||
| 59 | gate->bit_idx = SUNXI_OSC24M_GATE; | ||
| 60 | gate->lock = &clk_lock; | ||
| 61 | fixed->fixed_rate = rate; | ||
| 62 | |||
| 63 | clk = clk_register_composite(NULL, clk_name, | ||
| 64 | NULL, 0, | ||
| 65 | NULL, NULL, | ||
| 66 | &fixed->hw, &clk_fixed_rate_ops, | ||
| 67 | &gate->hw, &clk_gate_ops, | ||
| 68 | CLK_IS_ROOT); | ||
| 69 | |||
| 70 | if (IS_ERR(clk)) | ||
| 71 | goto err_free_gate; | ||
| 72 | |||
| 73 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 74 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 75 | |||
| 76 | return; | ||
| 77 | |||
| 78 | err_free_gate: | ||
| 79 | kfree(gate); | ||
| 80 | err_free_fixed: | ||
| 81 | kfree(fixed); | ||
| 82 | } | ||
| 83 | CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup); | ||
| 84 | |||
| 85 | |||
| 86 | |||
| 87 | /** | ||
| 88 | * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 | 31 | * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 |
| 89 | * PLL1 rate is calculated as follows | 32 | * PLL1 rate is calculated as follows |
| 90 | * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | 33 | * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); |
| @@ -408,104 +351,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate, | |||
| 408 | *p = calcp; | 351 | *p = calcp; |
| 409 | } | 352 | } |
| 410 | 353 | ||
| 411 | |||
| 412 | |||
| 413 | /** | ||
| 414 | * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module | ||
| 415 | * | ||
| 416 | * This clock looks something like this | ||
| 417 | * ________________________ | ||
| 418 | * MII TX clock from PHY >-----|___________ _________|----> to GMAC core | ||
| 419 | * GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY | ||
| 420 | * Ext. 125MHz RGMII TX clk >--|__divider__/ | | ||
| 421 | * |________________________| | ||
| 422 | * | ||
| 423 | * The external 125 MHz reference is optional, i.e. GMAC can use its | ||
| 424 | * internal TX clock just fine. The A31 GMAC clock module does not have | ||
| 425 | * the divider controls for the external reference. | ||
| 426 | * | ||
| 427 | * To keep it simple, let the GMAC use either the MII TX clock for MII mode, | ||
| 428 | * and its internal TX clock for GMII and RGMII modes. The GMAC driver should | ||
| 429 | * select the appropriate source and gate/ungate the output to the PHY. | ||
| 430 | * | ||
| 431 | * Only the GMAC should use this clock. Altering the clock so that it doesn't | ||
| 432 | * match the GMAC's operation parameters will result in the GMAC not being | ||
| 433 | * able to send traffic out. The GMAC driver should set the clock rate and | ||
| 434 | * enable/disable this clock to configure the required state. The clock | ||
| 435 | * driver then responds by auto-reparenting the clock. | ||
| 436 | */ | ||
| 437 | |||
| 438 | #define SUN7I_A20_GMAC_GPIT 2 | ||
| 439 | #define SUN7I_A20_GMAC_MASK 0x3 | ||
| 440 | #define SUN7I_A20_GMAC_PARENTS 2 | ||
| 441 | |||
| 442 | static void __init sun7i_a20_gmac_clk_setup(struct device_node *node) | ||
| 443 | { | ||
| 444 | struct clk *clk; | ||
| 445 | struct clk_mux *mux; | ||
| 446 | struct clk_gate *gate; | ||
| 447 | const char *clk_name = node->name; | ||
| 448 | const char *parents[SUN7I_A20_GMAC_PARENTS]; | ||
| 449 | void *reg; | ||
| 450 | |||
| 451 | if (of_property_read_string(node, "clock-output-names", &clk_name)) | ||
| 452 | return; | ||
| 453 | |||
| 454 | /* allocate mux and gate clock structs */ | ||
| 455 | mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL); | ||
| 456 | if (!mux) | ||
| 457 | return; | ||
| 458 | |||
| 459 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
| 460 | if (!gate) | ||
| 461 | goto free_mux; | ||
| 462 | |||
| 463 | /* gmac clock requires exactly 2 parents */ | ||
| 464 | parents[0] = of_clk_get_parent_name(node, 0); | ||
| 465 | parents[1] = of_clk_get_parent_name(node, 1); | ||
| 466 | if (!parents[0] || !parents[1]) | ||
| 467 | goto free_gate; | ||
| 468 | |||
| 469 | reg = of_iomap(node, 0); | ||
| 470 | if (!reg) | ||
| 471 | goto free_gate; | ||
| 472 | |||
| 473 | /* set up gate and fixed rate properties */ | ||
| 474 | gate->reg = reg; | ||
| 475 | gate->bit_idx = SUN7I_A20_GMAC_GPIT; | ||
| 476 | gate->lock = &clk_lock; | ||
| 477 | mux->reg = reg; | ||
| 478 | mux->mask = SUN7I_A20_GMAC_MASK; | ||
| 479 | mux->flags = CLK_MUX_INDEX_BIT; | ||
| 480 | mux->lock = &clk_lock; | ||
| 481 | |||
| 482 | clk = clk_register_composite(NULL, clk_name, | ||
| 483 | parents, SUN7I_A20_GMAC_PARENTS, | ||
| 484 | &mux->hw, &clk_mux_ops, | ||
| 485 | NULL, NULL, | ||
| 486 | &gate->hw, &clk_gate_ops, | ||
| 487 | 0); | ||
| 488 | |||
| 489 | if (IS_ERR(clk)) | ||
| 490 | goto iounmap_reg; | ||
| 491 | |||
| 492 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 493 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 494 | |||
| 495 | return; | ||
| 496 | |||
| 497 | iounmap_reg: | ||
| 498 | iounmap(reg); | ||
| 499 | free_gate: | ||
| 500 | kfree(gate); | ||
| 501 | free_mux: | ||
| 502 | kfree(mux); | ||
| 503 | } | ||
| 504 | CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk", | ||
| 505 | sun7i_a20_gmac_clk_setup); | ||
| 506 | |||
| 507 | |||
| 508 | |||
| 509 | /** | 354 | /** |
| 510 | * clk_sunxi_mmc_phase_control() - configures MMC clock phase control | 355 | * clk_sunxi_mmc_phase_control() - configures MMC clock phase control |
| 511 | */ | 356 | */ |
| @@ -1009,6 +854,11 @@ static const struct gates_data sun5i_a13_usb_gates_data __initconst = { | |||
| 1009 | .reset_mask = 0x03, | 854 | .reset_mask = 0x03, |
| 1010 | }; | 855 | }; |
| 1011 | 856 | ||
| 857 | static const struct gates_data sun6i_a31_usb_gates_data __initconst = { | ||
| 858 | .mask = { BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8) }, | ||
| 859 | .reset_mask = BIT(2) | BIT(1) | BIT(0), | ||
| 860 | }; | ||
| 861 | |||
| 1012 | static void __init sunxi_gates_clk_setup(struct device_node *node, | 862 | static void __init sunxi_gates_clk_setup(struct device_node *node, |
| 1013 | struct gates_data *data) | 863 | struct gates_data *data) |
| 1014 | { | 864 | { |
| @@ -1304,6 +1154,7 @@ static const struct of_device_id clk_gates_match[] __initconst = { | |||
| 1304 | {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, | 1154 | {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,}, |
| 1305 | {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, | 1155 | {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,}, |
| 1306 | {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,}, | 1156 | {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,}, |
| 1157 | {.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,}, | ||
| 1307 | {} | 1158 | {} |
| 1308 | }; | 1159 | }; |
| 1309 | 1160 | ||
| @@ -1321,33 +1172,10 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat | |||
| 1321 | } | 1172 | } |
| 1322 | } | 1173 | } |
| 1323 | 1174 | ||
| 1324 | /** | 1175 | static void __init sunxi_init_clocks(const char *clocks[], int nclocks) |
| 1325 | * System clock protection | ||
| 1326 | * | ||
| 1327 | * By enabling these critical clocks, we prevent their accidental gating | ||
| 1328 | * by the framework | ||
| 1329 | */ | ||
| 1330 | static void __init sunxi_clock_protect(void) | ||
| 1331 | { | 1176 | { |
| 1332 | struct clk *clk; | 1177 | unsigned int i; |
| 1333 | |||
| 1334 | /* memory bus clock - sun5i+ */ | ||
| 1335 | clk = clk_get(NULL, "mbus"); | ||
| 1336 | if (!IS_ERR(clk)) { | ||
| 1337 | clk_prepare_enable(clk); | ||
| 1338 | clk_put(clk); | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | /* DDR clock - sun4i+ */ | ||
| 1342 | clk = clk_get(NULL, "pll5_ddr"); | ||
| 1343 | if (!IS_ERR(clk)) { | ||
| 1344 | clk_prepare_enable(clk); | ||
| 1345 | clk_put(clk); | ||
| 1346 | } | ||
| 1347 | } | ||
| 1348 | 1178 | ||
| 1349 | static void __init sunxi_init_clocks(struct device_node *np) | ||
| 1350 | { | ||
| 1351 | /* Register factor clocks */ | 1179 | /* Register factor clocks */ |
| 1352 | of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); | 1180 | of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); |
| 1353 | 1181 | ||
| @@ -1363,11 +1191,48 @@ static void __init sunxi_init_clocks(struct device_node *np) | |||
| 1363 | /* Register gate clocks */ | 1191 | /* Register gate clocks */ |
| 1364 | of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); | 1192 | of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); |
| 1365 | 1193 | ||
| 1366 | /* Enable core system clocks */ | 1194 | /* Protect the clocks that needs to stay on */ |
| 1367 | sunxi_clock_protect(); | 1195 | for (i = 0; i < nclocks; i++) { |
| 1196 | struct clk *clk = clk_get(NULL, clocks[i]); | ||
| 1197 | |||
| 1198 | if (!IS_ERR(clk)) | ||
| 1199 | clk_prepare_enable(clk); | ||
| 1200 | } | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | static const char *sun4i_a10_critical_clocks[] __initdata = { | ||
| 1204 | "pll5_ddr", | ||
| 1205 | }; | ||
| 1206 | |||
| 1207 | static void __init sun4i_a10_init_clocks(struct device_node *node) | ||
| 1208 | { | ||
| 1209 | sunxi_init_clocks(sun4i_a10_critical_clocks, | ||
| 1210 | ARRAY_SIZE(sun4i_a10_critical_clocks)); | ||
| 1211 | } | ||
| 1212 | CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks); | ||
| 1213 | |||
| 1214 | static const char *sun5i_critical_clocks[] __initdata = { | ||
| 1215 | "mbus", | ||
| 1216 | "pll5_ddr", | ||
| 1217 | }; | ||
| 1218 | |||
| 1219 | static void __init sun5i_init_clocks(struct device_node *node) | ||
| 1220 | { | ||
| 1221 | sunxi_init_clocks(sun5i_critical_clocks, | ||
| 1222 | ARRAY_SIZE(sun5i_critical_clocks)); | ||
| 1223 | } | ||
| 1224 | CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks); | ||
| 1225 | CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks); | ||
| 1226 | CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks); | ||
| 1227 | |||
| 1228 | static const char *sun6i_critical_clocks[] __initdata = { | ||
| 1229 | "cpu", | ||
| 1230 | "ahb1_sdram", | ||
| 1231 | }; | ||
| 1232 | |||
| 1233 | static void __init sun6i_init_clocks(struct device_node *node) | ||
| 1234 | { | ||
| 1235 | sunxi_init_clocks(sun6i_critical_clocks, | ||
| 1236 | ARRAY_SIZE(sun6i_critical_clocks)); | ||
| 1368 | } | 1237 | } |
| 1369 | CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks); | 1238 | CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks); |
| 1370 | CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks); | ||
| 1371 | CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sunxi_init_clocks); | ||
| 1372 | CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sunxi_init_clocks); | ||
| 1373 | CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sunxi_init_clocks); | ||
diff --git a/drivers/clk/ti/Makefile b/drivers/clk/ti/Makefile index 4319d4031aa3..ed4d0aaf8916 100644 --- a/drivers/clk/ti/Makefile +++ b/drivers/clk/ti/Makefile | |||
| @@ -3,9 +3,11 @@ obj-y += clk.o autoidle.o clockdomain.o | |||
| 3 | clk-common = dpll.o composite.o divider.o gate.o \ | 3 | clk-common = dpll.o composite.o divider.o gate.o \ |
| 4 | fixed-factor.o mux.o apll.o | 4 | fixed-factor.o mux.o apll.o |
| 5 | obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o | 5 | obj-$(CONFIG_SOC_AM33XX) += $(clk-common) clk-33xx.o |
| 6 | obj-$(CONFIG_ARCH_OMAP2) += $(clk-common) interface.o clk-2xxx.o | ||
| 6 | obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o | 7 | obj-$(CONFIG_ARCH_OMAP3) += $(clk-common) interface.o clk-3xxx.o |
| 7 | obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o | 8 | obj-$(CONFIG_ARCH_OMAP4) += $(clk-common) clk-44xx.o |
| 8 | obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o | 9 | obj-$(CONFIG_SOC_OMAP5) += $(clk-common) clk-54xx.o |
| 9 | obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o | 10 | obj-$(CONFIG_SOC_DRA7XX) += $(clk-common) clk-7xx.o \ |
| 11 | clk-dra7-atl.o | ||
| 10 | obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o | 12 | obj-$(CONFIG_SOC_AM43XX) += $(clk-common) clk-43xx.o |
| 11 | endif | 13 | endif |
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c index b986f61f5a77..5428c9c547cd 100644 --- a/drivers/clk/ti/apll.c +++ b/drivers/clk/ti/apll.c | |||
| @@ -221,3 +221,184 @@ cleanup: | |||
| 221 | kfree(init); | 221 | kfree(init); |
| 222 | } | 222 | } |
| 223 | CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup); | 223 | CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup); |
| 224 | |||
| 225 | #define OMAP2_EN_APLL_LOCKED 0x3 | ||
| 226 | #define OMAP2_EN_APLL_STOPPED 0x0 | ||
| 227 | |||
| 228 | static int omap2_apll_is_enabled(struct clk_hw *hw) | ||
| 229 | { | ||
| 230 | struct clk_hw_omap *clk = to_clk_hw_omap(hw); | ||
| 231 | struct dpll_data *ad = clk->dpll_data; | ||
| 232 | u32 v; | ||
| 233 | |||
| 234 | v = ti_clk_ll_ops->clk_readl(ad->control_reg); | ||
| 235 | v &= ad->enable_mask; | ||
| 236 | |||
| 237 | v >>= __ffs(ad->enable_mask); | ||
| 238 | |||
| 239 | return v == OMAP2_EN_APLL_LOCKED ? 1 : 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | static unsigned long omap2_apll_recalc(struct clk_hw *hw, | ||
| 243 | unsigned long parent_rate) | ||
| 244 | { | ||
| 245 | struct clk_hw_omap *clk = to_clk_hw_omap(hw); | ||
| 246 | |||
| 247 | if (omap2_apll_is_enabled(hw)) | ||
| 248 | return clk->fixed_rate; | ||
| 249 | |||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int omap2_apll_enable(struct clk_hw *hw) | ||
| 254 | { | ||
| 255 | struct clk_hw_omap *clk = to_clk_hw_omap(hw); | ||
| 256 | struct dpll_data *ad = clk->dpll_data; | ||
| 257 | u32 v; | ||
| 258 | int i = 0; | ||
| 259 | |||
| 260 | v = ti_clk_ll_ops->clk_readl(ad->control_reg); | ||
| 261 | v &= ~ad->enable_mask; | ||
| 262 | v |= OMAP2_EN_APLL_LOCKED << __ffs(ad->enable_mask); | ||
| 263 | ti_clk_ll_ops->clk_writel(v, ad->control_reg); | ||
| 264 | |||
| 265 | while (1) { | ||
| 266 | v = ti_clk_ll_ops->clk_readl(ad->idlest_reg); | ||
| 267 | if (v & ad->idlest_mask) | ||
| 268 | break; | ||
| 269 | if (i > MAX_APLL_WAIT_TRIES) | ||
| 270 | break; | ||
| 271 | i++; | ||
| 272 | udelay(1); | ||
| 273 | } | ||
| 274 | |||
| 275 | if (i == MAX_APLL_WAIT_TRIES) { | ||
| 276 | pr_warn("%s failed to transition to locked\n", | ||
| 277 | __clk_get_name(clk->hw.clk)); | ||
| 278 | return -EBUSY; | ||
| 279 | } | ||
| 280 | |||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | static void omap2_apll_disable(struct clk_hw *hw) | ||
| 285 | { | ||
| 286 | struct clk_hw_omap *clk = to_clk_hw_omap(hw); | ||
| 287 | struct dpll_data *ad = clk->dpll_data; | ||
| 288 | u32 v; | ||
| 289 | |||
| 290 | v = ti_clk_ll_ops->clk_readl(ad->control_reg); | ||
| 291 | v &= ~ad->enable_mask; | ||
| 292 | v |= OMAP2_EN_APLL_STOPPED << __ffs(ad->enable_mask); | ||
| 293 | ti_clk_ll_ops->clk_writel(v, ad->control_reg); | ||
| 294 | } | ||
| 295 | |||
| 296 | static struct clk_ops omap2_apll_ops = { | ||
| 297 | .enable = &omap2_apll_enable, | ||
| 298 | .disable = &omap2_apll_disable, | ||
| 299 | .is_enabled = &omap2_apll_is_enabled, | ||
| 300 | .recalc_rate = &omap2_apll_recalc, | ||
| 301 | }; | ||
| 302 | |||
| 303 | static void omap2_apll_set_autoidle(struct clk_hw_omap *clk, u32 val) | ||
| 304 | { | ||
| 305 | struct dpll_data *ad = clk->dpll_data; | ||
| 306 | u32 v; | ||
| 307 | |||
| 308 | v = ti_clk_ll_ops->clk_readl(ad->autoidle_reg); | ||
| 309 | v &= ~ad->autoidle_mask; | ||
| 310 | v |= val << __ffs(ad->autoidle_mask); | ||
| 311 | ti_clk_ll_ops->clk_writel(v, ad->control_reg); | ||
| 312 | } | ||
| 313 | |||
| 314 | #define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP 0x3 | ||
| 315 | #define OMAP2_APLL_AUTOIDLE_DISABLE 0x0 | ||
| 316 | |||
| 317 | static void omap2_apll_allow_idle(struct clk_hw_omap *clk) | ||
| 318 | { | ||
| 319 | omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP); | ||
| 320 | } | ||
| 321 | |||
| 322 | static void omap2_apll_deny_idle(struct clk_hw_omap *clk) | ||
| 323 | { | ||
| 324 | omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_DISABLE); | ||
| 325 | } | ||
| 326 | |||
| 327 | static struct clk_hw_omap_ops omap2_apll_hwops = { | ||
| 328 | .allow_idle = &omap2_apll_allow_idle, | ||
| 329 | .deny_idle = &omap2_apll_deny_idle, | ||
| 330 | }; | ||
| 331 | |||
| 332 | static void __init of_omap2_apll_setup(struct device_node *node) | ||
| 333 | { | ||
| 334 | struct dpll_data *ad = NULL; | ||
| 335 | struct clk_hw_omap *clk_hw = NULL; | ||
| 336 | struct clk_init_data *init = NULL; | ||
| 337 | struct clk *clk; | ||
| 338 | const char *parent_name; | ||
| 339 | u32 val; | ||
| 340 | |||
| 341 | ad = kzalloc(sizeof(*clk_hw), GFP_KERNEL); | ||
| 342 | clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); | ||
| 343 | init = kzalloc(sizeof(*init), GFP_KERNEL); | ||
| 344 | |||
| 345 | if (!ad || !clk_hw || !init) | ||
| 346 | goto cleanup; | ||
| 347 | |||
| 348 | clk_hw->dpll_data = ad; | ||
| 349 | clk_hw->hw.init = init; | ||
| 350 | init->ops = &omap2_apll_ops; | ||
| 351 | init->name = node->name; | ||
| 352 | clk_hw->ops = &omap2_apll_hwops; | ||
| 353 | |||
| 354 | init->num_parents = of_clk_get_parent_count(node); | ||
| 355 | if (init->num_parents != 1) { | ||
| 356 | pr_err("%s must have one parent\n", node->name); | ||
| 357 | goto cleanup; | ||
| 358 | } | ||
| 359 | |||
| 360 | parent_name = of_clk_get_parent_name(node, 0); | ||
| 361 | init->parent_names = &parent_name; | ||
| 362 | |||
| 363 | if (of_property_read_u32(node, "ti,clock-frequency", &val)) { | ||
| 364 | pr_err("%s missing clock-frequency\n", node->name); | ||
| 365 | goto cleanup; | ||
| 366 | } | ||
| 367 | clk_hw->fixed_rate = val; | ||
| 368 | |||
| 369 | if (of_property_read_u32(node, "ti,bit-shift", &val)) { | ||
| 370 | pr_err("%s missing bit-shift\n", node->name); | ||
| 371 | goto cleanup; | ||
| 372 | } | ||
| 373 | |||
| 374 | clk_hw->enable_bit = val; | ||
| 375 | ad->enable_mask = 0x3 << val; | ||
| 376 | ad->autoidle_mask = 0x3 << val; | ||
| 377 | |||
| 378 | if (of_property_read_u32(node, "ti,idlest-shift", &val)) { | ||
| 379 | pr_err("%s missing idlest-shift\n", node->name); | ||
| 380 | goto cleanup; | ||
| 381 | } | ||
| 382 | |||
| 383 | ad->idlest_mask = 1 << val; | ||
| 384 | |||
| 385 | ad->control_reg = ti_clk_get_reg_addr(node, 0); | ||
| 386 | ad->autoidle_reg = ti_clk_get_reg_addr(node, 1); | ||
| 387 | ad->idlest_reg = ti_clk_get_reg_addr(node, 2); | ||
| 388 | |||
| 389 | if (!ad->control_reg || !ad->autoidle_reg || !ad->idlest_reg) | ||
| 390 | goto cleanup; | ||
| 391 | |||
| 392 | clk = clk_register(NULL, &clk_hw->hw); | ||
| 393 | if (!IS_ERR(clk)) { | ||
| 394 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 395 | kfree(init); | ||
| 396 | return; | ||
| 397 | } | ||
| 398 | cleanup: | ||
| 399 | kfree(ad); | ||
| 400 | kfree(clk_hw); | ||
| 401 | kfree(init); | ||
| 402 | } | ||
| 403 | CLK_OF_DECLARE(omap2_apll_clock, "ti,omap2-apll-clock", | ||
| 404 | of_omap2_apll_setup); | ||
diff --git a/drivers/clk/ti/clk-2xxx.c b/drivers/clk/ti/clk-2xxx.c new file mode 100644 index 000000000000..c808ab3d2bb2 --- /dev/null +++ b/drivers/clk/ti/clk-2xxx.c | |||
| @@ -0,0 +1,256 @@ | |||
| 1 | /* | ||
| 2 | * OMAP2 Clock init | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Texas Instruments, Inc | ||
| 5 | * Tero Kristo (t-kristo@ti.com) | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or | ||
| 8 | * modify it under the terms of the GNU General Public License as | ||
| 9 | * published by the Free Software Foundation version 2. | ||
| 10 | * | ||
| 11 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 12 | * kind, whether express or implied; without even the implied warranty | ||
| 13 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/list.h> | ||
| 19 | #include <linux/clk-provider.h> | ||
| 20 | #include <linux/clk/ti.h> | ||
| 21 | |||
| 22 | static struct ti_dt_clk omap2xxx_clks[] = { | ||
| 23 | DT_CLK(NULL, "func_32k_ck", "func_32k_ck"), | ||
| 24 | DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"), | ||
| 25 | DT_CLK(NULL, "virt_12m_ck", "virt_12m_ck"), | ||
| 26 | DT_CLK(NULL, "virt_13m_ck", "virt_13m_ck"), | ||
| 27 | DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"), | ||
| 28 | DT_CLK(NULL, "virt_26m_ck", "virt_26m_ck"), | ||
| 29 | DT_CLK(NULL, "aplls_clkin_ck", "aplls_clkin_ck"), | ||
| 30 | DT_CLK(NULL, "aplls_clkin_x2_ck", "aplls_clkin_x2_ck"), | ||
| 31 | DT_CLK(NULL, "osc_ck", "osc_ck"), | ||
| 32 | DT_CLK(NULL, "sys_ck", "sys_ck"), | ||
| 33 | DT_CLK(NULL, "alt_ck", "alt_ck"), | ||
| 34 | DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"), | ||
| 35 | DT_CLK(NULL, "dpll_ck", "dpll_ck"), | ||
| 36 | DT_CLK(NULL, "apll96_ck", "apll96_ck"), | ||
| 37 | DT_CLK(NULL, "apll54_ck", "apll54_ck"), | ||
| 38 | DT_CLK(NULL, "func_54m_ck", "func_54m_ck"), | ||
| 39 | DT_CLK(NULL, "core_ck", "core_ck"), | ||
| 40 | DT_CLK(NULL, "func_96m_ck", "func_96m_ck"), | ||
| 41 | DT_CLK(NULL, "func_48m_ck", "func_48m_ck"), | ||
| 42 | DT_CLK(NULL, "func_12m_ck", "func_12m_ck"), | ||
| 43 | DT_CLK(NULL, "sys_clkout_src", "sys_clkout_src"), | ||
| 44 | DT_CLK(NULL, "sys_clkout", "sys_clkout"), | ||
| 45 | DT_CLK(NULL, "emul_ck", "emul_ck"), | ||
| 46 | DT_CLK(NULL, "mpu_ck", "mpu_ck"), | ||
| 47 | DT_CLK(NULL, "dsp_fck", "dsp_fck"), | ||
| 48 | DT_CLK(NULL, "gfx_3d_fck", "gfx_3d_fck"), | ||
| 49 | DT_CLK(NULL, "gfx_2d_fck", "gfx_2d_fck"), | ||
| 50 | DT_CLK(NULL, "gfx_ick", "gfx_ick"), | ||
| 51 | DT_CLK("omapdss_dss", "ick", "dss_ick"), | ||
| 52 | DT_CLK(NULL, "dss_ick", "dss_ick"), | ||
| 53 | DT_CLK(NULL, "dss1_fck", "dss1_fck"), | ||
| 54 | DT_CLK(NULL, "dss2_fck", "dss2_fck"), | ||
| 55 | DT_CLK(NULL, "dss_54m_fck", "dss_54m_fck"), | ||
| 56 | DT_CLK(NULL, "core_l3_ck", "core_l3_ck"), | ||
| 57 | DT_CLK(NULL, "ssi_fck", "ssi_ssr_sst_fck"), | ||
| 58 | DT_CLK(NULL, "usb_l4_ick", "usb_l4_ick"), | ||
| 59 | DT_CLK(NULL, "l4_ck", "l4_ck"), | ||
| 60 | DT_CLK(NULL, "ssi_l4_ick", "ssi_l4_ick"), | ||
| 61 | DT_CLK(NULL, "gpt1_ick", "gpt1_ick"), | ||
| 62 | DT_CLK(NULL, "gpt1_fck", "gpt1_fck"), | ||
| 63 | DT_CLK(NULL, "gpt2_ick", "gpt2_ick"), | ||
| 64 | DT_CLK(NULL, "gpt2_fck", "gpt2_fck"), | ||
| 65 | DT_CLK(NULL, "gpt3_ick", "gpt3_ick"), | ||
| 66 | DT_CLK(NULL, "gpt3_fck", "gpt3_fck"), | ||
| 67 | DT_CLK(NULL, "gpt4_ick", "gpt4_ick"), | ||
| 68 | DT_CLK(NULL, "gpt4_fck", "gpt4_fck"), | ||
| 69 | DT_CLK(NULL, "gpt5_ick", "gpt5_ick"), | ||
| 70 | DT_CLK(NULL, "gpt5_fck", "gpt5_fck"), | ||
| 71 | DT_CLK(NULL, "gpt6_ick", "gpt6_ick"), | ||
| 72 | DT_CLK(NULL, "gpt6_fck", "gpt6_fck"), | ||
| 73 | DT_CLK(NULL, "gpt7_ick", "gpt7_ick"), | ||
| 74 | DT_CLK(NULL, "gpt7_fck", "gpt7_fck"), | ||
| 75 | DT_CLK(NULL, "gpt8_ick", "gpt8_ick"), | ||
| 76 | DT_CLK(NULL, "gpt8_fck", "gpt8_fck"), | ||
| 77 | DT_CLK(NULL, "gpt9_ick", "gpt9_ick"), | ||
| 78 | DT_CLK(NULL, "gpt9_fck", "gpt9_fck"), | ||
| 79 | DT_CLK(NULL, "gpt10_ick", "gpt10_ick"), | ||
| 80 | DT_CLK(NULL, "gpt10_fck", "gpt10_fck"), | ||
| 81 | DT_CLK(NULL, "gpt11_ick", "gpt11_ick"), | ||
| 82 | DT_CLK(NULL, "gpt11_fck", "gpt11_fck"), | ||
| 83 | DT_CLK(NULL, "gpt12_ick", "gpt12_ick"), | ||
| 84 | DT_CLK(NULL, "gpt12_fck", "gpt12_fck"), | ||
| 85 | DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"), | ||
| 86 | DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"), | ||
| 87 | DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"), | ||
| 88 | DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"), | ||
| 89 | DT_CLK(NULL, "mcbsp2_ick", "mcbsp2_ick"), | ||
| 90 | DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"), | ||
| 91 | DT_CLK("omap2_mcspi.1", "ick", "mcspi1_ick"), | ||
| 92 | DT_CLK(NULL, "mcspi1_ick", "mcspi1_ick"), | ||
| 93 | DT_CLK(NULL, "mcspi1_fck", "mcspi1_fck"), | ||
| 94 | DT_CLK("omap2_mcspi.2", "ick", "mcspi2_ick"), | ||
| 95 | DT_CLK(NULL, "mcspi2_ick", "mcspi2_ick"), | ||
| 96 | DT_CLK(NULL, "mcspi2_fck", "mcspi2_fck"), | ||
| 97 | DT_CLK(NULL, "uart1_ick", "uart1_ick"), | ||
| 98 | DT_CLK(NULL, "uart1_fck", "uart1_fck"), | ||
| 99 | DT_CLK(NULL, "uart2_ick", "uart2_ick"), | ||
| 100 | DT_CLK(NULL, "uart2_fck", "uart2_fck"), | ||
| 101 | DT_CLK(NULL, "uart3_ick", "uart3_ick"), | ||
| 102 | DT_CLK(NULL, "uart3_fck", "uart3_fck"), | ||
| 103 | DT_CLK(NULL, "gpios_ick", "gpios_ick"), | ||
| 104 | DT_CLK(NULL, "gpios_fck", "gpios_fck"), | ||
| 105 | DT_CLK("omap_wdt", "ick", "mpu_wdt_ick"), | ||
| 106 | DT_CLK(NULL, "mpu_wdt_ick", "mpu_wdt_ick"), | ||
| 107 | DT_CLK(NULL, "mpu_wdt_fck", "mpu_wdt_fck"), | ||
| 108 | DT_CLK(NULL, "sync_32k_ick", "sync_32k_ick"), | ||
| 109 | DT_CLK(NULL, "wdt1_ick", "wdt1_ick"), | ||
| 110 | DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"), | ||
| 111 | DT_CLK("omap24xxcam", "fck", "cam_fck"), | ||
| 112 | DT_CLK(NULL, "cam_fck", "cam_fck"), | ||
| 113 | DT_CLK("omap24xxcam", "ick", "cam_ick"), | ||
| 114 | DT_CLK(NULL, "cam_ick", "cam_ick"), | ||
| 115 | DT_CLK(NULL, "mailboxes_ick", "mailboxes_ick"), | ||
| 116 | DT_CLK(NULL, "wdt4_ick", "wdt4_ick"), | ||
| 117 | DT_CLK(NULL, "wdt4_fck", "wdt4_fck"), | ||
| 118 | DT_CLK(NULL, "mspro_ick", "mspro_ick"), | ||
| 119 | DT_CLK(NULL, "mspro_fck", "mspro_fck"), | ||
| 120 | DT_CLK(NULL, "fac_ick", "fac_ick"), | ||
| 121 | DT_CLK(NULL, "fac_fck", "fac_fck"), | ||
| 122 | DT_CLK("omap_hdq.0", "ick", "hdq_ick"), | ||
| 123 | DT_CLK(NULL, "hdq_ick", "hdq_ick"), | ||
| 124 | DT_CLK("omap_hdq.0", "fck", "hdq_fck"), | ||
| 125 | DT_CLK(NULL, "hdq_fck", "hdq_fck"), | ||
| 126 | DT_CLK("omap_i2c.1", "ick", "i2c1_ick"), | ||
| 127 | DT_CLK(NULL, "i2c1_ick", "i2c1_ick"), | ||
| 128 | DT_CLK("omap_i2c.2", "ick", "i2c2_ick"), | ||
| 129 | DT_CLK(NULL, "i2c2_ick", "i2c2_ick"), | ||
| 130 | DT_CLK(NULL, "gpmc_fck", "gpmc_fck"), | ||
| 131 | DT_CLK(NULL, "sdma_fck", "sdma_fck"), | ||
| 132 | DT_CLK(NULL, "sdma_ick", "sdma_ick"), | ||
| 133 | DT_CLK(NULL, "sdrc_ick", "sdrc_ick"), | ||
| 134 | DT_CLK(NULL, "des_ick", "des_ick"), | ||
| 135 | DT_CLK("omap-sham", "ick", "sha_ick"), | ||
| 136 | DT_CLK(NULL, "sha_ick", "sha_ick"), | ||
| 137 | DT_CLK("omap_rng", "ick", "rng_ick"), | ||
| 138 | DT_CLK(NULL, "rng_ick", "rng_ick"), | ||
| 139 | DT_CLK("omap-aes", "ick", "aes_ick"), | ||
| 140 | DT_CLK(NULL, "aes_ick", "aes_ick"), | ||
| 141 | DT_CLK(NULL, "pka_ick", "pka_ick"), | ||
| 142 | DT_CLK(NULL, "usb_fck", "usb_fck"), | ||
| 143 | DT_CLK(NULL, "timer_32k_ck", "func_32k_ck"), | ||
| 144 | DT_CLK(NULL, "timer_sys_ck", "sys_ck"), | ||
| 145 | DT_CLK(NULL, "timer_ext_ck", "alt_ck"), | ||
| 146 | { .node_name = NULL }, | ||
| 147 | }; | ||
| 148 | |||
| 149 | static struct ti_dt_clk omap2420_clks[] = { | ||
| 150 | DT_CLK(NULL, "sys_clkout2_src", "sys_clkout2_src"), | ||
| 151 | DT_CLK(NULL, "sys_clkout2", "sys_clkout2"), | ||
| 152 | DT_CLK(NULL, "dsp_ick", "dsp_ick"), | ||
| 153 | DT_CLK(NULL, "iva1_ifck", "iva1_ifck"), | ||
| 154 | DT_CLK(NULL, "iva1_mpu_int_ifck", "iva1_mpu_int_ifck"), | ||
| 155 | DT_CLK(NULL, "wdt3_ick", "wdt3_ick"), | ||
| 156 | DT_CLK(NULL, "wdt3_fck", "wdt3_fck"), | ||
| 157 | DT_CLK("mmci-omap.0", "ick", "mmc_ick"), | ||
| 158 | DT_CLK(NULL, "mmc_ick", "mmc_ick"), | ||
| 159 | DT_CLK("mmci-omap.0", "fck", "mmc_fck"), | ||
| 160 | DT_CLK(NULL, "mmc_fck", "mmc_fck"), | ||
| 161 | DT_CLK(NULL, "eac_ick", "eac_ick"), | ||
| 162 | DT_CLK(NULL, "eac_fck", "eac_fck"), | ||
| 163 | DT_CLK(NULL, "i2c1_fck", "i2c1_fck"), | ||
| 164 | DT_CLK(NULL, "i2c2_fck", "i2c2_fck"), | ||
| 165 | DT_CLK(NULL, "vlynq_ick", "vlynq_ick"), | ||
| 166 | DT_CLK(NULL, "vlynq_fck", "vlynq_fck"), | ||
| 167 | DT_CLK("musb-hdrc", "fck", "osc_ck"), | ||
| 168 | { .node_name = NULL }, | ||
| 169 | }; | ||
| 170 | |||
| 171 | static struct ti_dt_clk omap2430_clks[] = { | ||
| 172 | DT_CLK("twl", "fck", "osc_ck"), | ||
| 173 | DT_CLK(NULL, "iva2_1_ick", "iva2_1_ick"), | ||
| 174 | DT_CLK(NULL, "mdm_ick", "mdm_ick"), | ||
| 175 | DT_CLK(NULL, "mdm_osc_ck", "mdm_osc_ck"), | ||
| 176 | DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"), | ||
| 177 | DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"), | ||
| 178 | DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"), | ||
| 179 | DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"), | ||
| 180 | DT_CLK(NULL, "mcbsp4_ick", "mcbsp4_ick"), | ||
| 181 | DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"), | ||
| 182 | DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"), | ||
| 183 | DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"), | ||
| 184 | DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"), | ||
| 185 | DT_CLK("omap2_mcspi.3", "ick", "mcspi3_ick"), | ||
| 186 | DT_CLK(NULL, "mcspi3_ick", "mcspi3_ick"), | ||
| 187 | DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"), | ||
| 188 | DT_CLK(NULL, "icr_ick", "icr_ick"), | ||
| 189 | DT_CLK(NULL, "i2chs1_fck", "i2chs1_fck"), | ||
| 190 | DT_CLK(NULL, "i2chs2_fck", "i2chs2_fck"), | ||
| 191 | DT_CLK("musb-omap2430", "ick", "usbhs_ick"), | ||
| 192 | DT_CLK(NULL, "usbhs_ick", "usbhs_ick"), | ||
| 193 | DT_CLK("omap_hsmmc.0", "ick", "mmchs1_ick"), | ||
| 194 | DT_CLK(NULL, "mmchs1_ick", "mmchs1_ick"), | ||
| 195 | DT_CLK(NULL, "mmchs1_fck", "mmchs1_fck"), | ||
| 196 | DT_CLK("omap_hsmmc.1", "ick", "mmchs2_ick"), | ||
| 197 | DT_CLK(NULL, "mmchs2_ick", "mmchs2_ick"), | ||
| 198 | DT_CLK(NULL, "mmchs2_fck", "mmchs2_fck"), | ||
| 199 | DT_CLK(NULL, "gpio5_ick", "gpio5_ick"), | ||
| 200 | DT_CLK(NULL, "gpio5_fck", "gpio5_fck"), | ||
| 201 | DT_CLK(NULL, "mdm_intc_ick", "mdm_intc_ick"), | ||
| 202 | DT_CLK("omap_hsmmc.0", "mmchsdb_fck", "mmchsdb1_fck"), | ||
| 203 | DT_CLK(NULL, "mmchsdb1_fck", "mmchsdb1_fck"), | ||
| 204 | DT_CLK("omap_hsmmc.1", "mmchsdb_fck", "mmchsdb2_fck"), | ||
| 205 | DT_CLK(NULL, "mmchsdb2_fck", "mmchsdb2_fck"), | ||
| 206 | { .node_name = NULL }, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static const char *enable_init_clks[] = { | ||
| 210 | "apll96_ck", | ||
| 211 | "apll54_ck", | ||
| 212 | "sync_32k_ick", | ||
| 213 | "omapctrl_ick", | ||
| 214 | "gpmc_fck", | ||
| 215 | "sdrc_ick", | ||
| 216 | }; | ||
| 217 | |||
| 218 | enum { | ||
| 219 | OMAP2_SOC_OMAP2420, | ||
| 220 | OMAP2_SOC_OMAP2430, | ||
| 221 | }; | ||
| 222 | |||
| 223 | static int __init omap2xxx_dt_clk_init(int soc_type) | ||
| 224 | { | ||
| 225 | ti_dt_clocks_register(omap2xxx_clks); | ||
| 226 | |||
| 227 | if (soc_type == OMAP2_SOC_OMAP2420) | ||
| 228 | ti_dt_clocks_register(omap2420_clks); | ||
| 229 | else | ||
| 230 | ti_dt_clocks_register(omap2430_clks); | ||
| 231 | |||
| 232 | omap2xxx_clkt_vps_init(); | ||
| 233 | |||
| 234 | omap2_clk_disable_autoidle_all(); | ||
| 235 | |||
| 236 | omap2_clk_enable_init_clocks(enable_init_clks, | ||
| 237 | ARRAY_SIZE(enable_init_clks)); | ||
| 238 | |||
| 239 | pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n", | ||
| 240 | (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 1000000), | ||
| 241 | (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 100000) % 10, | ||
| 242 | (clk_get_rate(clk_get_sys(NULL, "dpll_ck")) / 1000000), | ||
| 243 | (clk_get_rate(clk_get_sys(NULL, "mpu_ck")) / 1000000)); | ||
| 244 | |||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 248 | int __init omap2420_dt_clk_init(void) | ||
| 249 | { | ||
| 250 | return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2420); | ||
| 251 | } | ||
| 252 | |||
| 253 | int __init omap2430_dt_clk_init(void) | ||
| 254 | { | ||
| 255 | return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2430); | ||
| 256 | } | ||
diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index 08f3d1b915b3..5e183993e3ec 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c | |||
| @@ -240,6 +240,12 @@ int __init omap5xxx_dt_clk_init(void) | |||
| 240 | if (rc) | 240 | if (rc) |
| 241 | pr_err("%s: failed to configure ABE DPLL!\n", __func__); | 241 | pr_err("%s: failed to configure ABE DPLL!\n", __func__); |
| 242 | 242 | ||
| 243 | abe_dpll = clk_get_sys(NULL, "dpll_abe_m2x2_ck"); | ||
| 244 | if (!rc) | ||
| 245 | rc = clk_set_rate(abe_dpll, OMAP5_DPLL_ABE_DEFFREQ * 2); | ||
| 246 | if (rc) | ||
| 247 | pr_err("%s: failed to configure ABE m2x2 DPLL!\n", __func__); | ||
| 248 | |||
| 243 | usb_dpll = clk_get_sys(NULL, "dpll_usb_ck"); | 249 | usb_dpll = clk_get_sys(NULL, "dpll_usb_ck"); |
| 244 | rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ); | 250 | rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ); |
| 245 | if (rc) | 251 | if (rc) |
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index f7e40734c819..e1581335937d 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c | |||
| @@ -24,7 +24,7 @@ static struct ti_dt_clk dra7xx_clks[] = { | |||
| 24 | DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"), | 24 | DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"), |
| 25 | DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"), | 25 | DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"), |
| 26 | DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"), | 26 | DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"), |
| 27 | DT_CLK(NULL, "atlclkin3_ck", "atlclkin3_ck"), | 27 | DT_CLK(NULL, "atl_clkin3_ck", "atl_clkin3_ck"), |
| 28 | DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"), | 28 | DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"), |
| 29 | DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"), | 29 | DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"), |
| 30 | DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"), | 30 | DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"), |
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c new file mode 100644 index 000000000000..4a65b410e4d5 --- /dev/null +++ b/drivers/clk/ti/clk-dra7-atl.c | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | /* | ||
| 2 | * DRA7 ATL (Audio Tracking Logic) clock driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 Texas Instruments, Inc. | ||
| 5 | * | ||
| 6 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 13 | * kind, whether express or implied; without even the implied warranty | ||
| 14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/clk-provider.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | #include <linux/of.h> | ||
| 23 | #include <linux/of_address.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/pm_runtime.h> | ||
| 26 | |||
| 27 | #define DRA7_ATL_INSTANCES 4 | ||
| 28 | |||
| 29 | #define DRA7_ATL_PPMR_REG(id) (0x200 + (id * 0x80)) | ||
| 30 | #define DRA7_ATL_BBSR_REG(id) (0x204 + (id * 0x80)) | ||
| 31 | #define DRA7_ATL_ATLCR_REG(id) (0x208 + (id * 0x80)) | ||
| 32 | #define DRA7_ATL_SWEN_REG(id) (0x210 + (id * 0x80)) | ||
| 33 | #define DRA7_ATL_BWSMUX_REG(id) (0x214 + (id * 0x80)) | ||
| 34 | #define DRA7_ATL_AWSMUX_REG(id) (0x218 + (id * 0x80)) | ||
| 35 | #define DRA7_ATL_PCLKMUX_REG(id) (0x21c + (id * 0x80)) | ||
| 36 | |||
| 37 | #define DRA7_ATL_SWEN BIT(0) | ||
| 38 | #define DRA7_ATL_DIVIDER_MASK (0x1f) | ||
| 39 | #define DRA7_ATL_PCLKMUX BIT(0) | ||
| 40 | struct dra7_atl_clock_info; | ||
| 41 | |||
| 42 | struct dra7_atl_desc { | ||
| 43 | struct clk *clk; | ||
| 44 | struct clk_hw hw; | ||
| 45 | struct dra7_atl_clock_info *cinfo; | ||
| 46 | int id; | ||
| 47 | |||
| 48 | bool probed; /* the driver for the IP has been loaded */ | ||
| 49 | bool valid; /* configured */ | ||
| 50 | bool enabled; | ||
| 51 | u32 bws; /* Baseband Word Select Mux */ | ||
| 52 | u32 aws; /* Audio Word Select Mux */ | ||
| 53 | u32 divider; /* Cached divider value */ | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct dra7_atl_clock_info { | ||
| 57 | struct device *dev; | ||
| 58 | void __iomem *iobase; | ||
| 59 | |||
| 60 | struct dra7_atl_desc *cdesc; | ||
| 61 | }; | ||
| 62 | |||
| 63 | #define to_atl_desc(_hw) container_of(_hw, struct dra7_atl_desc, hw) | ||
| 64 | |||
| 65 | static inline void atl_write(struct dra7_atl_clock_info *cinfo, u32 reg, | ||
| 66 | u32 val) | ||
| 67 | { | ||
| 68 | __raw_writel(val, cinfo->iobase + reg); | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline int atl_read(struct dra7_atl_clock_info *cinfo, u32 reg) | ||
| 72 | { | ||
| 73 | return __raw_readl(cinfo->iobase + reg); | ||
| 74 | } | ||
| 75 | |||
| 76 | static int atl_clk_enable(struct clk_hw *hw) | ||
| 77 | { | ||
| 78 | struct dra7_atl_desc *cdesc = to_atl_desc(hw); | ||
| 79 | |||
| 80 | if (!cdesc->probed) | ||
| 81 | goto out; | ||
| 82 | |||
| 83 | if (unlikely(!cdesc->valid)) | ||
| 84 | dev_warn(cdesc->cinfo->dev, "atl%d has not been configured\n", | ||
| 85 | cdesc->id); | ||
| 86 | pm_runtime_get_sync(cdesc->cinfo->dev); | ||
| 87 | |||
| 88 | atl_write(cdesc->cinfo, DRA7_ATL_ATLCR_REG(cdesc->id), | ||
| 89 | cdesc->divider - 1); | ||
| 90 | atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), DRA7_ATL_SWEN); | ||
| 91 | |||
| 92 | out: | ||
| 93 | cdesc->enabled = true; | ||
| 94 | |||
| 95 | return 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | static void atl_clk_disable(struct clk_hw *hw) | ||
| 99 | { | ||
| 100 | struct dra7_atl_desc *cdesc = to_atl_desc(hw); | ||
| 101 | |||
| 102 | if (!cdesc->probed) | ||
| 103 | goto out; | ||
| 104 | |||
| 105 | atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), 0); | ||
| 106 | pm_runtime_put_sync(cdesc->cinfo->dev); | ||
| 107 | |||
| 108 | out: | ||
| 109 | cdesc->enabled = false; | ||
| 110 | } | ||
| 111 | |||
| 112 | static int atl_clk_is_enabled(struct clk_hw *hw) | ||
| 113 | { | ||
| 114 | struct dra7_atl_desc *cdesc = to_atl_desc(hw); | ||
| 115 | |||
| 116 | return cdesc->enabled; | ||
| 117 | } | ||
| 118 | |||
| 119 | static unsigned long atl_clk_recalc_rate(struct clk_hw *hw, | ||
| 120 | unsigned long parent_rate) | ||
| 121 | { | ||
| 122 | struct dra7_atl_desc *cdesc = to_atl_desc(hw); | ||
| 123 | |||
| 124 | return parent_rate / cdesc->divider; | ||
| 125 | } | ||
| 126 | |||
| 127 | static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 128 | unsigned long *parent_rate) | ||
| 129 | { | ||
| 130 | unsigned divider; | ||
| 131 | |||
| 132 | divider = (*parent_rate + rate / 2) / rate; | ||
| 133 | if (divider > DRA7_ATL_DIVIDER_MASK + 1) | ||
| 134 | divider = DRA7_ATL_DIVIDER_MASK + 1; | ||
| 135 | |||
| 136 | return *parent_rate / divider; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 140 | unsigned long parent_rate) | ||
| 141 | { | ||
| 142 | struct dra7_atl_desc *cdesc = to_atl_desc(hw); | ||
| 143 | u32 divider; | ||
| 144 | |||
| 145 | divider = ((parent_rate + rate / 2) / rate) - 1; | ||
| 146 | if (divider > DRA7_ATL_DIVIDER_MASK) | ||
| 147 | divider = DRA7_ATL_DIVIDER_MASK; | ||
| 148 | |||
| 149 | cdesc->divider = divider + 1; | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
| 153 | |||
| 154 | const struct clk_ops atl_clk_ops = { | ||
| 155 | .enable = atl_clk_enable, | ||
| 156 | .disable = atl_clk_disable, | ||
| 157 | .is_enabled = atl_clk_is_enabled, | ||
| 158 | .recalc_rate = atl_clk_recalc_rate, | ||
| 159 | .round_rate = atl_clk_round_rate, | ||
| 160 | .set_rate = atl_clk_set_rate, | ||
| 161 | }; | ||
| 162 | |||
| 163 | static void __init of_dra7_atl_clock_setup(struct device_node *node) | ||
| 164 | { | ||
| 165 | struct dra7_atl_desc *clk_hw = NULL; | ||
| 166 | struct clk_init_data init = { 0 }; | ||
| 167 | const char **parent_names = NULL; | ||
| 168 | struct clk *clk; | ||
| 169 | |||
| 170 | clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); | ||
| 171 | if (!clk_hw) { | ||
| 172 | pr_err("%s: could not allocate dra7_atl_desc\n", __func__); | ||
| 173 | return; | ||
| 174 | } | ||
| 175 | |||
| 176 | clk_hw->hw.init = &init; | ||
| 177 | clk_hw->divider = 1; | ||
| 178 | init.name = node->name; | ||
| 179 | init.ops = &atl_clk_ops; | ||
| 180 | init.flags = CLK_IGNORE_UNUSED; | ||
| 181 | init.num_parents = of_clk_get_parent_count(node); | ||
| 182 | |||
| 183 | if (init.num_parents != 1) { | ||
| 184 | pr_err("%s: atl clock %s must have 1 parent\n", __func__, | ||
| 185 | node->name); | ||
| 186 | goto cleanup; | ||
| 187 | } | ||
| 188 | |||
| 189 | parent_names = kzalloc(sizeof(char *), GFP_KERNEL); | ||
| 190 | |||
| 191 | if (!parent_names) | ||
| 192 | goto cleanup; | ||
| 193 | |||
| 194 | parent_names[0] = of_clk_get_parent_name(node, 0); | ||
| 195 | |||
| 196 | init.parent_names = parent_names; | ||
| 197 | |||
| 198 | clk = clk_register(NULL, &clk_hw->hw); | ||
| 199 | |||
| 200 | if (!IS_ERR(clk)) { | ||
| 201 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 202 | return; | ||
| 203 | } | ||
| 204 | cleanup: | ||
| 205 | kfree(parent_names); | ||
| 206 | kfree(clk_hw); | ||
| 207 | } | ||
| 208 | CLK_OF_DECLARE(dra7_atl_clock, "ti,dra7-atl-clock", of_dra7_atl_clock_setup); | ||
| 209 | |||
| 210 | static int of_dra7_atl_clk_probe(struct platform_device *pdev) | ||
| 211 | { | ||
| 212 | struct device_node *node = pdev->dev.of_node; | ||
| 213 | struct dra7_atl_clock_info *cinfo; | ||
| 214 | int i; | ||
| 215 | int ret = 0; | ||
| 216 | |||
| 217 | if (!node) | ||
| 218 | return -ENODEV; | ||
| 219 | |||
| 220 | cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL); | ||
| 221 | if (!cinfo) | ||
| 222 | return -ENOMEM; | ||
| 223 | |||
| 224 | cinfo->iobase = of_iomap(node, 0); | ||
| 225 | cinfo->dev = &pdev->dev; | ||
| 226 | pm_runtime_enable(cinfo->dev); | ||
| 227 | |||
| 228 | pm_runtime_get_sync(cinfo->dev); | ||
| 229 | atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX); | ||
| 230 | |||
| 231 | for (i = 0; i < DRA7_ATL_INSTANCES; i++) { | ||
| 232 | struct device_node *cfg_node; | ||
| 233 | char prop[5]; | ||
| 234 | struct dra7_atl_desc *cdesc; | ||
| 235 | struct of_phandle_args clkspec; | ||
| 236 | struct clk *clk; | ||
| 237 | int rc; | ||
| 238 | |||
| 239 | rc = of_parse_phandle_with_args(node, "ti,provided-clocks", | ||
| 240 | NULL, i, &clkspec); | ||
| 241 | |||
| 242 | if (rc) { | ||
| 243 | pr_err("%s: failed to lookup atl clock %d\n", __func__, | ||
| 244 | i); | ||
| 245 | return -EINVAL; | ||
| 246 | } | ||
| 247 | |||
| 248 | clk = of_clk_get_from_provider(&clkspec); | ||
| 249 | |||
| 250 | cdesc = to_atl_desc(__clk_get_hw(clk)); | ||
| 251 | cdesc->cinfo = cinfo; | ||
| 252 | cdesc->id = i; | ||
| 253 | |||
| 254 | /* Get configuration for the ATL instances */ | ||
| 255 | snprintf(prop, sizeof(prop), "atl%u", i); | ||
| 256 | cfg_node = of_find_node_by_name(node, prop); | ||
| 257 | if (cfg_node) { | ||
| 258 | ret = of_property_read_u32(cfg_node, "bws", | ||
| 259 | &cdesc->bws); | ||
| 260 | ret |= of_property_read_u32(cfg_node, "aws", | ||
| 261 | &cdesc->aws); | ||
| 262 | if (!ret) { | ||
| 263 | cdesc->valid = true; | ||
| 264 | atl_write(cinfo, DRA7_ATL_BWSMUX_REG(i), | ||
| 265 | cdesc->bws); | ||
| 266 | atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i), | ||
| 267 | cdesc->aws); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 271 | cdesc->probed = true; | ||
| 272 | /* | ||
| 273 | * Enable the clock if it has been asked prior to loading the | ||
| 274 | * hw driver | ||
| 275 | */ | ||
| 276 | if (cdesc->enabled) | ||
| 277 | atl_clk_enable(__clk_get_hw(clk)); | ||
| 278 | } | ||
| 279 | pm_runtime_put_sync(cinfo->dev); | ||
| 280 | |||
| 281 | return ret; | ||
| 282 | } | ||
| 283 | |||
| 284 | static int of_dra7_atl_clk_remove(struct platform_device *pdev) | ||
| 285 | { | ||
| 286 | pm_runtime_disable(&pdev->dev); | ||
| 287 | |||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | static struct of_device_id of_dra7_atl_clk_match_tbl[] = { | ||
| 292 | { .compatible = "ti,dra7-atl", }, | ||
| 293 | {}, | ||
| 294 | }; | ||
| 295 | MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl); | ||
| 296 | |||
| 297 | static struct platform_driver dra7_atl_clk_driver = { | ||
| 298 | .driver = { | ||
| 299 | .name = "dra7-atl", | ||
| 300 | .owner = THIS_MODULE, | ||
| 301 | .of_match_table = of_dra7_atl_clk_match_tbl, | ||
| 302 | }, | ||
| 303 | .probe = of_dra7_atl_clk_probe, | ||
| 304 | .remove = of_dra7_atl_clk_remove, | ||
| 305 | }; | ||
| 306 | |||
| 307 | module_platform_driver(dra7_atl_clk_driver); | ||
| 308 | |||
| 309 | MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic"); | ||
| 310 | MODULE_ALIAS("platform:dra7-atl-clock"); | ||
| 311 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | ||
| 312 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c index 7e498a44f97d..abd956d5f838 100644 --- a/drivers/clk/ti/dpll.c +++ b/drivers/clk/ti/dpll.c | |||
| @@ -25,8 +25,6 @@ | |||
| 25 | #undef pr_fmt | 25 | #undef pr_fmt |
| 26 | #define pr_fmt(fmt) "%s: " fmt, __func__ | 26 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
| 27 | 27 | ||
| 28 | #define DPLL_HAS_AUTOIDLE 0x1 | ||
| 29 | |||
| 30 | #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \ | 28 | #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \ |
| 31 | defined(CONFIG_SOC_DRA7XX) | 29 | defined(CONFIG_SOC_DRA7XX) |
| 32 | static const struct clk_ops dpll_m4xen_ck_ops = { | 30 | static const struct clk_ops dpll_m4xen_ck_ops = { |
| @@ -37,21 +35,18 @@ static const struct clk_ops dpll_m4xen_ck_ops = { | |||
| 37 | .set_rate = &omap3_noncore_dpll_set_rate, | 35 | .set_rate = &omap3_noncore_dpll_set_rate, |
| 38 | .get_parent = &omap2_init_dpll_parent, | 36 | .get_parent = &omap2_init_dpll_parent, |
| 39 | }; | 37 | }; |
| 38 | #else | ||
| 39 | static const struct clk_ops dpll_m4xen_ck_ops = {}; | ||
| 40 | #endif | 40 | #endif |
| 41 | 41 | ||
| 42 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) || \ | ||
| 43 | defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) || \ | ||
| 44 | defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX) | ||
| 42 | static const struct clk_ops dpll_core_ck_ops = { | 45 | static const struct clk_ops dpll_core_ck_ops = { |
| 43 | .recalc_rate = &omap3_dpll_recalc, | 46 | .recalc_rate = &omap3_dpll_recalc, |
| 44 | .get_parent = &omap2_init_dpll_parent, | 47 | .get_parent = &omap2_init_dpll_parent, |
| 45 | }; | 48 | }; |
| 46 | 49 | ||
| 47 | #ifdef CONFIG_ARCH_OMAP3 | ||
| 48 | static const struct clk_ops omap3_dpll_core_ck_ops = { | ||
| 49 | .get_parent = &omap2_init_dpll_parent, | ||
| 50 | .recalc_rate = &omap3_dpll_recalc, | ||
| 51 | .round_rate = &omap2_dpll_round_rate, | ||
| 52 | }; | ||
| 53 | #endif | ||
| 54 | |||
| 55 | static const struct clk_ops dpll_ck_ops = { | 50 | static const struct clk_ops dpll_ck_ops = { |
| 56 | .enable = &omap3_noncore_dpll_enable, | 51 | .enable = &omap3_noncore_dpll_enable, |
| 57 | .disable = &omap3_noncore_dpll_disable, | 52 | .disable = &omap3_noncore_dpll_disable, |
| @@ -67,6 +62,33 @@ static const struct clk_ops dpll_no_gate_ck_ops = { | |||
| 67 | .round_rate = &omap2_dpll_round_rate, | 62 | .round_rate = &omap2_dpll_round_rate, |
| 68 | .set_rate = &omap3_noncore_dpll_set_rate, | 63 | .set_rate = &omap3_noncore_dpll_set_rate, |
| 69 | }; | 64 | }; |
| 65 | #else | ||
| 66 | static const struct clk_ops dpll_core_ck_ops = {}; | ||
| 67 | static const struct clk_ops dpll_ck_ops = {}; | ||
| 68 | static const struct clk_ops dpll_no_gate_ck_ops = {}; | ||
| 69 | const struct clk_hw_omap_ops clkhwops_omap3_dpll = {}; | ||
| 70 | #endif | ||
| 71 | |||
| 72 | #ifdef CONFIG_ARCH_OMAP2 | ||
| 73 | static const struct clk_ops omap2_dpll_core_ck_ops = { | ||
| 74 | .get_parent = &omap2_init_dpll_parent, | ||
| 75 | .recalc_rate = &omap2_dpllcore_recalc, | ||
| 76 | .round_rate = &omap2_dpll_round_rate, | ||
| 77 | .set_rate = &omap2_reprogram_dpllcore, | ||
| 78 | }; | ||
| 79 | #else | ||
| 80 | static const struct clk_ops omap2_dpll_core_ck_ops = {}; | ||
| 81 | #endif | ||
| 82 | |||
| 83 | #ifdef CONFIG_ARCH_OMAP3 | ||
| 84 | static const struct clk_ops omap3_dpll_core_ck_ops = { | ||
| 85 | .get_parent = &omap2_init_dpll_parent, | ||
| 86 | .recalc_rate = &omap3_dpll_recalc, | ||
| 87 | .round_rate = &omap2_dpll_round_rate, | ||
| 88 | }; | ||
| 89 | #else | ||
| 90 | static const struct clk_ops omap3_dpll_core_ck_ops = {}; | ||
| 91 | #endif | ||
| 70 | 92 | ||
| 71 | #ifdef CONFIG_ARCH_OMAP3 | 93 | #ifdef CONFIG_ARCH_OMAP3 |
| 72 | static const struct clk_ops omap3_dpll_ck_ops = { | 94 | static const struct clk_ops omap3_dpll_ck_ops = { |
| @@ -193,14 +215,12 @@ static void ti_clk_register_dpll_x2(struct device_node *node, | |||
| 193 | * @node: device node containing the DPLL info | 215 | * @node: device node containing the DPLL info |
| 194 | * @ops: ops for the DPLL | 216 | * @ops: ops for the DPLL |
| 195 | * @ddt: DPLL data template to use | 217 | * @ddt: DPLL data template to use |
| 196 | * @init_flags: flags for controlling init types | ||
| 197 | * | 218 | * |
| 198 | * Initializes a DPLL clock from device tree data. | 219 | * Initializes a DPLL clock from device tree data. |
| 199 | */ | 220 | */ |
| 200 | static void __init of_ti_dpll_setup(struct device_node *node, | 221 | static void __init of_ti_dpll_setup(struct device_node *node, |
| 201 | const struct clk_ops *ops, | 222 | const struct clk_ops *ops, |
| 202 | const struct dpll_data *ddt, | 223 | const struct dpll_data *ddt) |
| 203 | u8 init_flags) | ||
| 204 | { | 224 | { |
| 205 | struct clk_hw_omap *clk_hw = NULL; | 225 | struct clk_hw_omap *clk_hw = NULL; |
| 206 | struct clk_init_data *init = NULL; | 226 | struct clk_init_data *init = NULL; |
| @@ -241,13 +261,30 @@ static void __init of_ti_dpll_setup(struct device_node *node, | |||
| 241 | init->parent_names = parent_names; | 261 | init->parent_names = parent_names; |
| 242 | 262 | ||
| 243 | dd->control_reg = ti_clk_get_reg_addr(node, 0); | 263 | dd->control_reg = ti_clk_get_reg_addr(node, 0); |
| 244 | dd->idlest_reg = ti_clk_get_reg_addr(node, 1); | ||
| 245 | dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); | ||
| 246 | 264 | ||
| 247 | if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg) | 265 | /* |
| 266 | * Special case for OMAP2 DPLL, register order is different due to | ||
| 267 | * missing idlest_reg, also clkhwops is different. Detected from | ||
| 268 | * missing idlest_mask. | ||
| 269 | */ | ||
| 270 | if (!dd->idlest_mask) { | ||
| 271 | dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1); | ||
| 272 | #ifdef CONFIG_ARCH_OMAP2 | ||
| 273 | clk_hw->ops = &clkhwops_omap2xxx_dpll; | ||
| 274 | omap2xxx_clkt_dpllcore_init(&clk_hw->hw); | ||
| 275 | #endif | ||
| 276 | } else { | ||
| 277 | dd->idlest_reg = ti_clk_get_reg_addr(node, 1); | ||
| 278 | if (!dd->idlest_reg) | ||
| 279 | goto cleanup; | ||
| 280 | |||
| 281 | dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); | ||
| 282 | } | ||
| 283 | |||
| 284 | if (!dd->control_reg || !dd->mult_div1_reg) | ||
| 248 | goto cleanup; | 285 | goto cleanup; |
| 249 | 286 | ||
| 250 | if (init_flags & DPLL_HAS_AUTOIDLE) { | 287 | if (dd->autoidle_mask) { |
| 251 | dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); | 288 | dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); |
| 252 | if (!dd->autoidle_reg) | 289 | if (!dd->autoidle_reg) |
| 253 | goto cleanup; | 290 | goto cleanup; |
| @@ -310,7 +347,7 @@ static void __init of_ti_omap3_dpll_setup(struct device_node *node) | |||
| 310 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 347 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 311 | }; | 348 | }; |
| 312 | 349 | ||
| 313 | of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 350 | of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd); |
| 314 | } | 351 | } |
| 315 | CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock", | 352 | CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock", |
| 316 | of_ti_omap3_dpll_setup); | 353 | of_ti_omap3_dpll_setup); |
| @@ -329,7 +366,7 @@ static void __init of_ti_omap3_core_dpll_setup(struct device_node *node) | |||
| 329 | .freqsel_mask = 0xf0, | 366 | .freqsel_mask = 0xf0, |
| 330 | }; | 367 | }; |
| 331 | 368 | ||
| 332 | of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 369 | of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd); |
| 333 | } | 370 | } |
| 334 | CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock", | 371 | CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock", |
| 335 | of_ti_omap3_core_dpll_setup); | 372 | of_ti_omap3_core_dpll_setup); |
| @@ -349,7 +386,7 @@ static void __init of_ti_omap3_per_dpll_setup(struct device_node *node) | |||
| 349 | .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), | 386 | .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), |
| 350 | }; | 387 | }; |
| 351 | 388 | ||
| 352 | of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 389 | of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd); |
| 353 | } | 390 | } |
| 354 | CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock", | 391 | CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock", |
| 355 | of_ti_omap3_per_dpll_setup); | 392 | of_ti_omap3_per_dpll_setup); |
| @@ -371,7 +408,7 @@ static void __init of_ti_omap3_per_jtype_dpll_setup(struct device_node *node) | |||
| 371 | .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), | 408 | .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED), |
| 372 | }; | 409 | }; |
| 373 | 410 | ||
| 374 | of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 411 | of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd); |
| 375 | } | 412 | } |
| 376 | CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock", | 413 | CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock", |
| 377 | of_ti_omap3_per_jtype_dpll_setup); | 414 | of_ti_omap3_per_jtype_dpll_setup); |
| @@ -391,11 +428,32 @@ static void __init of_ti_omap4_dpll_setup(struct device_node *node) | |||
| 391 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 428 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 392 | }; | 429 | }; |
| 393 | 430 | ||
| 394 | of_ti_dpll_setup(node, &dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 431 | of_ti_dpll_setup(node, &dpll_ck_ops, &dd); |
| 395 | } | 432 | } |
| 396 | CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock", | 433 | CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock", |
| 397 | of_ti_omap4_dpll_setup); | 434 | of_ti_omap4_dpll_setup); |
| 398 | 435 | ||
| 436 | static void __init of_ti_omap5_mpu_dpll_setup(struct device_node *node) | ||
| 437 | { | ||
| 438 | const struct dpll_data dd = { | ||
| 439 | .idlest_mask = 0x1, | ||
| 440 | .enable_mask = 0x7, | ||
| 441 | .autoidle_mask = 0x7, | ||
| 442 | .mult_mask = 0x7ff << 8, | ||
| 443 | .div1_mask = 0x7f, | ||
| 444 | .max_multiplier = 2047, | ||
| 445 | .max_divider = 128, | ||
| 446 | .dcc_mask = BIT(22), | ||
| 447 | .dcc_rate = 1400000000, /* DCC beyond 1.4GHz */ | ||
| 448 | .min_divider = 1, | ||
| 449 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | ||
| 450 | }; | ||
| 451 | |||
| 452 | of_ti_dpll_setup(node, &dpll_ck_ops, &dd); | ||
| 453 | } | ||
| 454 | CLK_OF_DECLARE(of_ti_omap5_mpu_dpll_clock, "ti,omap5-mpu-dpll-clock", | ||
| 455 | of_ti_omap5_mpu_dpll_setup); | ||
| 456 | |||
| 399 | static void __init of_ti_omap4_core_dpll_setup(struct device_node *node) | 457 | static void __init of_ti_omap4_core_dpll_setup(struct device_node *node) |
| 400 | { | 458 | { |
| 401 | const struct dpll_data dd = { | 459 | const struct dpll_data dd = { |
| @@ -410,7 +468,7 @@ static void __init of_ti_omap4_core_dpll_setup(struct device_node *node) | |||
| 410 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 468 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 411 | }; | 469 | }; |
| 412 | 470 | ||
| 413 | of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 471 | of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd); |
| 414 | } | 472 | } |
| 415 | CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock", | 473 | CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock", |
| 416 | of_ti_omap4_core_dpll_setup); | 474 | of_ti_omap4_core_dpll_setup); |
| @@ -433,7 +491,7 @@ static void __init of_ti_omap4_m4xen_dpll_setup(struct device_node *node) | |||
| 433 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 491 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 434 | }; | 492 | }; |
| 435 | 493 | ||
| 436 | of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 494 | of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd); |
| 437 | } | 495 | } |
| 438 | CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock", | 496 | CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock", |
| 439 | of_ti_omap4_m4xen_dpll_setup); | 497 | of_ti_omap4_m4xen_dpll_setup); |
| @@ -454,7 +512,7 @@ static void __init of_ti_omap4_jtype_dpll_setup(struct device_node *node) | |||
| 454 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 512 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 455 | }; | 513 | }; |
| 456 | 514 | ||
| 457 | of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE); | 515 | of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd); |
| 458 | } | 516 | } |
| 459 | CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock", | 517 | CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock", |
| 460 | of_ti_omap4_jtype_dpll_setup); | 518 | of_ti_omap4_jtype_dpll_setup); |
| @@ -465,7 +523,6 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node) | |||
| 465 | const struct dpll_data dd = { | 523 | const struct dpll_data dd = { |
| 466 | .idlest_mask = 0x1, | 524 | .idlest_mask = 0x1, |
| 467 | .enable_mask = 0x7, | 525 | .enable_mask = 0x7, |
| 468 | .autoidle_mask = 0x7, | ||
| 469 | .mult_mask = 0x7ff << 8, | 526 | .mult_mask = 0x7ff << 8, |
| 470 | .div1_mask = 0x7f, | 527 | .div1_mask = 0x7f, |
| 471 | .max_multiplier = 2047, | 528 | .max_multiplier = 2047, |
| @@ -474,7 +531,7 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node) | |||
| 474 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 531 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 475 | }; | 532 | }; |
| 476 | 533 | ||
| 477 | of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0); | 534 | of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd); |
| 478 | } | 535 | } |
| 479 | CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock", | 536 | CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock", |
| 480 | of_ti_am3_no_gate_dpll_setup); | 537 | of_ti_am3_no_gate_dpll_setup); |
| @@ -484,7 +541,6 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node) | |||
| 484 | const struct dpll_data dd = { | 541 | const struct dpll_data dd = { |
| 485 | .idlest_mask = 0x1, | 542 | .idlest_mask = 0x1, |
| 486 | .enable_mask = 0x7, | 543 | .enable_mask = 0x7, |
| 487 | .autoidle_mask = 0x7, | ||
| 488 | .mult_mask = 0x7ff << 8, | 544 | .mult_mask = 0x7ff << 8, |
| 489 | .div1_mask = 0x7f, | 545 | .div1_mask = 0x7f, |
| 490 | .max_multiplier = 4095, | 546 | .max_multiplier = 4095, |
| @@ -494,7 +550,7 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node) | |||
| 494 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 550 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 495 | }; | 551 | }; |
| 496 | 552 | ||
| 497 | of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0); | 553 | of_ti_dpll_setup(node, &dpll_ck_ops, &dd); |
| 498 | } | 554 | } |
| 499 | CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock", | 555 | CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock", |
| 500 | of_ti_am3_jtype_dpll_setup); | 556 | of_ti_am3_jtype_dpll_setup); |
| @@ -504,7 +560,6 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node) | |||
| 504 | const struct dpll_data dd = { | 560 | const struct dpll_data dd = { |
| 505 | .idlest_mask = 0x1, | 561 | .idlest_mask = 0x1, |
| 506 | .enable_mask = 0x7, | 562 | .enable_mask = 0x7, |
| 507 | .autoidle_mask = 0x7, | ||
| 508 | .mult_mask = 0x7ff << 8, | 563 | .mult_mask = 0x7ff << 8, |
| 509 | .div1_mask = 0x7f, | 564 | .div1_mask = 0x7f, |
| 510 | .max_multiplier = 2047, | 565 | .max_multiplier = 2047, |
| @@ -514,7 +569,7 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node) | |||
| 514 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 569 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 515 | }; | 570 | }; |
| 516 | 571 | ||
| 517 | of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0); | 572 | of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd); |
| 518 | } | 573 | } |
| 519 | CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock, | 574 | CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock, |
| 520 | "ti,am3-dpll-no-gate-j-type-clock", | 575 | "ti,am3-dpll-no-gate-j-type-clock", |
| @@ -525,7 +580,6 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node) | |||
| 525 | const struct dpll_data dd = { | 580 | const struct dpll_data dd = { |
| 526 | .idlest_mask = 0x1, | 581 | .idlest_mask = 0x1, |
| 527 | .enable_mask = 0x7, | 582 | .enable_mask = 0x7, |
| 528 | .autoidle_mask = 0x7, | ||
| 529 | .mult_mask = 0x7ff << 8, | 583 | .mult_mask = 0x7ff << 8, |
| 530 | .div1_mask = 0x7f, | 584 | .div1_mask = 0x7f, |
| 531 | .max_multiplier = 2047, | 585 | .max_multiplier = 2047, |
| @@ -534,7 +588,7 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node) | |||
| 534 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 588 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 535 | }; | 589 | }; |
| 536 | 590 | ||
| 537 | of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0); | 591 | of_ti_dpll_setup(node, &dpll_ck_ops, &dd); |
| 538 | } | 592 | } |
| 539 | CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup); | 593 | CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup); |
| 540 | 594 | ||
| @@ -543,7 +597,6 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node) | |||
| 543 | const struct dpll_data dd = { | 597 | const struct dpll_data dd = { |
| 544 | .idlest_mask = 0x1, | 598 | .idlest_mask = 0x1, |
| 545 | .enable_mask = 0x7, | 599 | .enable_mask = 0x7, |
| 546 | .autoidle_mask = 0x7, | ||
| 547 | .mult_mask = 0x7ff << 8, | 600 | .mult_mask = 0x7ff << 8, |
| 548 | .div1_mask = 0x7f, | 601 | .div1_mask = 0x7f, |
| 549 | .max_multiplier = 2047, | 602 | .max_multiplier = 2047, |
| @@ -552,7 +605,22 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node) | |||
| 552 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), | 605 | .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED), |
| 553 | }; | 606 | }; |
| 554 | 607 | ||
| 555 | of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, 0); | 608 | of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd); |
| 556 | } | 609 | } |
| 557 | CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock", | 610 | CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock", |
| 558 | of_ti_am3_core_dpll_setup); | 611 | of_ti_am3_core_dpll_setup); |
| 612 | |||
| 613 | static void __init of_ti_omap2_core_dpll_setup(struct device_node *node) | ||
| 614 | { | ||
| 615 | const struct dpll_data dd = { | ||
| 616 | .enable_mask = 0x3, | ||
| 617 | .mult_mask = 0x3ff << 12, | ||
| 618 | .div1_mask = 0xf << 8, | ||
| 619 | .max_divider = 16, | ||
| 620 | .min_divider = 1, | ||
| 621 | }; | ||
| 622 | |||
| 623 | of_ti_dpll_setup(node, &omap2_dpll_core_ck_ops, &dd); | ||
| 624 | } | ||
| 625 | CLK_OF_DECLARE(ti_omap2_core_dpll_clock, "ti,omap2-dpll-core-clock", | ||
| 626 | of_ti_omap2_core_dpll_setup); | ||
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c index 58734817d502..b326d2797feb 100644 --- a/drivers/clk/ti/gate.c +++ b/drivers/clk/ti/gate.c | |||
| @@ -185,7 +185,7 @@ of_ti_composite_no_wait_gate_clk_setup(struct device_node *node) | |||
| 185 | CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock", | 185 | CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock", |
| 186 | of_ti_composite_no_wait_gate_clk_setup); | 186 | of_ti_composite_no_wait_gate_clk_setup); |
| 187 | 187 | ||
| 188 | #ifdef CONFIG_ARCH_OMAP3 | 188 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
| 189 | static void __init of_ti_composite_interface_clk_setup(struct device_node *node) | 189 | static void __init of_ti_composite_interface_clk_setup(struct device_node *node) |
| 190 | { | 190 | { |
| 191 | _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait); | 191 | _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait); |
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c index 320a2b168bb2..9c3e8c4aaa40 100644 --- a/drivers/clk/ti/interface.c +++ b/drivers/clk/ti/interface.c | |||
| @@ -94,6 +94,7 @@ static void __init of_ti_no_wait_interface_clk_setup(struct device_node *node) | |||
| 94 | CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock", | 94 | CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock", |
| 95 | of_ti_no_wait_interface_clk_setup); | 95 | of_ti_no_wait_interface_clk_setup); |
| 96 | 96 | ||
| 97 | #ifdef CONFIG_ARCH_OMAP3 | ||
| 97 | static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node) | 98 | static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node) |
| 98 | { | 99 | { |
| 99 | _of_ti_interface_clk_setup(node, | 100 | _of_ti_interface_clk_setup(node, |
| @@ -123,3 +124,13 @@ static void __init of_ti_am35xx_interface_clk_setup(struct device_node *node) | |||
| 123 | } | 124 | } |
| 124 | CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock", | 125 | CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock", |
| 125 | of_ti_am35xx_interface_clk_setup); | 126 | of_ti_am35xx_interface_clk_setup); |
| 127 | #endif | ||
| 128 | |||
| 129 | #ifdef CONFIG_SOC_OMAP2430 | ||
| 130 | static void __init of_ti_omap2430_interface_clk_setup(struct device_node *node) | ||
| 131 | { | ||
| 132 | _of_ti_interface_clk_setup(node, &clkhwops_omap2430_i2chs_wait); | ||
| 133 | } | ||
| 134 | CLK_OF_DECLARE(ti_omap2430_interface_clk, "ti,omap2430-interface-clock", | ||
| 135 | of_ti_omap2430_interface_clk_setup); | ||
| 136 | #endif | ||
diff --git a/include/dt-bindings/clk/ti-dra7-atl.h b/include/dt-bindings/clk/ti-dra7-atl.h new file mode 100644 index 000000000000..42dd4164f6f4 --- /dev/null +++ b/include/dt-bindings/clk/ti-dra7-atl.h | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | /* | ||
| 2 | * This header provides constants for DRA7 ATL (Audio Tracking Logic) | ||
| 3 | * | ||
| 4 | * The constants defined in this header are used in dts files | ||
| 5 | * | ||
| 6 | * Copyright (C) 2013 Texas Instruments, Inc. | ||
| 7 | * | ||
| 8 | * Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 15 | * kind, whether express or implied; without even the implied warranty | ||
| 16 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef _DT_BINDINGS_CLK_DRA7_ATL_H | ||
| 21 | #define _DT_BINDINGS_CLK_DRA7_ATL_H | ||
| 22 | |||
| 23 | #define DRA7_ATL_WS_MCASP1_FSR 0 | ||
| 24 | #define DRA7_ATL_WS_MCASP1_FSX 1 | ||
| 25 | #define DRA7_ATL_WS_MCASP2_FSR 2 | ||
| 26 | #define DRA7_ATL_WS_MCASP2_FSX 3 | ||
| 27 | #define DRA7_ATL_WS_MCASP3_FSX 4 | ||
| 28 | #define DRA7_ATL_WS_MCASP4_FSX 5 | ||
| 29 | #define DRA7_ATL_WS_MCASP5_FSX 6 | ||
| 30 | #define DRA7_ATL_WS_MCASP6_FSX 7 | ||
| 31 | #define DRA7_ATL_WS_MCASP7_FSX 8 | ||
| 32 | #define DRA7_ATL_WS_MCASP8_FSX 9 | ||
| 33 | #define DRA7_ATL_WS_MCASP8_AHCLKX 10 | ||
| 34 | #define DRA7_ATL_WS_XREF_CLK3 11 | ||
| 35 | #define DRA7_ATL_WS_XREF_CLK0 12 | ||
| 36 | #define DRA7_ATL_WS_XREF_CLK1 13 | ||
| 37 | #define DRA7_ATL_WS_XREF_CLK2 14 | ||
| 38 | #define DRA7_ATL_WS_OSC1_X1 15 | ||
| 39 | |||
| 40 | #endif | ||
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h index 4a21a872dbbd..e8d8a35034a5 100644 --- a/include/linux/clk/ti.h +++ b/include/linux/clk/ti.h | |||
| @@ -41,6 +41,8 @@ | |||
| 41 | * @idlest_reg: register containing the DPLL idle status bitfield | 41 | * @idlest_reg: register containing the DPLL idle status bitfield |
| 42 | * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg | 42 | * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg |
| 43 | * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg | 43 | * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg |
| 44 | * @dcc_mask: mask of the DPLL DCC correction bitfield @mult_div1_reg | ||
| 45 | * @dcc_rate: rate atleast which DCC @dcc_mask must be set | ||
| 44 | * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg | 46 | * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg |
| 45 | * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg | 47 | * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg |
| 46 | * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg | 48 | * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg |
| @@ -86,6 +88,8 @@ struct dpll_data { | |||
| 86 | u32 idlest_mask; | 88 | u32 idlest_mask; |
| 87 | u32 dco_mask; | 89 | u32 dco_mask; |
| 88 | u32 sddiv_mask; | 90 | u32 sddiv_mask; |
| 91 | u32 dcc_mask; | ||
| 92 | unsigned long dcc_rate; | ||
| 89 | u32 lpmode_mask; | 93 | u32 lpmode_mask; |
| 90 | u32 m4xen_mask; | 94 | u32 m4xen_mask; |
| 91 | u8 auto_recal_bit; | 95 | u8 auto_recal_bit; |
| @@ -94,7 +98,26 @@ struct dpll_data { | |||
| 94 | u8 flags; | 98 | u8 flags; |
| 95 | }; | 99 | }; |
| 96 | 100 | ||
| 97 | struct clk_hw_omap_ops; | 101 | struct clk_hw_omap; |
| 102 | |||
| 103 | /** | ||
| 104 | * struct clk_hw_omap_ops - OMAP clk ops | ||
| 105 | * @find_idlest: find idlest register information for a clock | ||
| 106 | * @find_companion: find companion clock register information for a clock, | ||
| 107 | * basically converts CM_ICLKEN* <-> CM_FCLKEN* | ||
| 108 | * @allow_idle: enables autoidle hardware functionality for a clock | ||
| 109 | * @deny_idle: prevent autoidle hardware functionality for a clock | ||
| 110 | */ | ||
| 111 | struct clk_hw_omap_ops { | ||
| 112 | void (*find_idlest)(struct clk_hw_omap *oclk, | ||
| 113 | void __iomem **idlest_reg, | ||
| 114 | u8 *idlest_bit, u8 *idlest_val); | ||
| 115 | void (*find_companion)(struct clk_hw_omap *oclk, | ||
| 116 | void __iomem **other_reg, | ||
| 117 | u8 *other_bit); | ||
| 118 | void (*allow_idle)(struct clk_hw_omap *oclk); | ||
| 119 | void (*deny_idle)(struct clk_hw_omap *oclk); | ||
| 120 | }; | ||
| 98 | 121 | ||
| 99 | /** | 122 | /** |
| 100 | * struct clk_hw_omap - OMAP struct clk | 123 | * struct clk_hw_omap - OMAP struct clk |
| @@ -259,6 +282,12 @@ int omap2_dflt_clk_enable(struct clk_hw *hw); | |||
| 259 | void omap2_dflt_clk_disable(struct clk_hw *hw); | 282 | void omap2_dflt_clk_disable(struct clk_hw *hw); |
| 260 | int omap2_dflt_clk_is_enabled(struct clk_hw *hw); | 283 | int omap2_dflt_clk_is_enabled(struct clk_hw *hw); |
| 261 | void omap3_clk_lock_dpll5(void); | 284 | void omap3_clk_lock_dpll5(void); |
| 285 | unsigned long omap2_dpllcore_recalc(struct clk_hw *hw, | ||
| 286 | unsigned long parent_rate); | ||
| 287 | int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate, | ||
| 288 | unsigned long parent_rate); | ||
| 289 | void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw); | ||
| 290 | void omap2xxx_clkt_vps_init(void); | ||
| 262 | 291 | ||
| 263 | void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index); | 292 | void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index); |
| 264 | void ti_dt_clocks_register(struct ti_dt_clk *oclks); | 293 | void ti_dt_clocks_register(struct ti_dt_clk *oclks); |
| @@ -278,6 +307,8 @@ int omap5xxx_dt_clk_init(void); | |||
| 278 | int dra7xx_dt_clk_init(void); | 307 | int dra7xx_dt_clk_init(void); |
| 279 | int am33xx_dt_clk_init(void); | 308 | int am33xx_dt_clk_init(void); |
| 280 | int am43xx_dt_clk_init(void); | 309 | int am43xx_dt_clk_init(void); |
| 310 | int omap2420_dt_clk_init(void); | ||
| 311 | int omap2430_dt_clk_init(void); | ||
| 281 | 312 | ||
| 282 | #ifdef CONFIG_OF | 313 | #ifdef CONFIG_OF |
| 283 | void of_ti_clk_allow_autoidle_all(void); | 314 | void of_ti_clk_allow_autoidle_all(void); |
| @@ -287,6 +318,8 @@ static inline void of_ti_clk_allow_autoidle_all(void) { } | |||
| 287 | static inline void of_ti_clk_deny_autoidle_all(void) { } | 318 | static inline void of_ti_clk_deny_autoidle_all(void) { } |
| 288 | #endif | 319 | #endif |
| 289 | 320 | ||
| 321 | extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll; | ||
| 322 | extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait; | ||
| 290 | extern const struct clk_hw_omap_ops clkhwops_omap3_dpll; | 323 | extern const struct clk_hw_omap_ops clkhwops_omap3_dpll; |
| 291 | extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; | 324 | extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx; |
| 292 | extern const struct clk_hw_omap_ops clkhwops_wait; | 325 | extern const struct clk_hw_omap_ops clkhwops_wait; |
