diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 19:43:54 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-29 19:43:54 -0400 |
| commit | 362ed48dee509abe24cf84b7e137c7a29a8f4d2d (patch) | |
| tree | f2c2397afa517becf3ff3d8ac4c5c542dfed9795 | |
| parent | 61f3d0a9883d965b498edeb673235bddc92770fd (diff) | |
| parent | 1e435256d625c203660f0105f1155cd2af283051 (diff) | |
Merge tag 'clk-for-linus-3.10' of git://git.linaro.org/people/mturquette/linux
Pull clock framework update from Michael Turquette:
"The common clock framework changes for 3.10 include many fixes for
existing platforms, as well as adoption of the framework by new
platforms and devices.
Some long-needed fixes to the core framework are here as well as new
features such as improved initialization of clocks from DT as well as
framework reentrancy for nested clock operations."
* tag 'clk-for-linus-3.10' of git://git.linaro.org/people/mturquette/linux: (44 commits)
clk: add clk_ignore_unused option to keep boot clocks on
clk: ux500: fix mismatched types
clk: vexpress: Add separate SP810 driver
clk: si5351: make clk-si5351 depend on CONFIG_OF
clk: export __clk_get_flags for modular clock providers
clk: vt8500: Missing breaks in vtwm_pll_round_rate/_set_rate.
clk: sunxi: Unify oscillator clock
clk: composite: allow fixed rates & fixed dividers
clk: composite: rename 'div' references to 'rate'
clk: add si5351 i2c common clock driver
clk: add device tree fixed-factor-clock binding support
clk: Properly handle notifier return values
clk: ux500: abx500: Define clock tree for ab850x
clk: ux500: Add support for sysctrl clocks
clk: mvebu: Fix valid value range checking for cpu_freq_select
clk: Fixup locking issues for clk_set_parent
clk: Fixup errorhandling for clk_set_parent
clk: Restructure code for __clk_reparent
clk: sunxi: drop an unnecesary kmalloc
clk: sunxi: drop CLK_IGNORE_UNUSED
...
48 files changed, 4518 insertions, 304 deletions
diff --git a/Documentation/arm/sunxi/clocks.txt b/Documentation/arm/sunxi/clocks.txt new file mode 100644 index 000000000000..e09a88aa3136 --- /dev/null +++ b/Documentation/arm/sunxi/clocks.txt | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | Frequently asked questions about the sunxi clock system | ||
| 2 | ======================================================= | ||
| 3 | |||
| 4 | This document contains useful bits of information that people tend to ask | ||
| 5 | about the sunxi clock system, as well as accompanying ASCII art when adequate. | ||
| 6 | |||
| 7 | Q: Why is the main 24MHz oscillator gatable? Wouldn't that break the | ||
| 8 | system? | ||
| 9 | |||
| 10 | A: The 24MHz oscillator allows gating to save power. Indeed, if gated | ||
| 11 | carelessly the system would stop functioning, but with the right | ||
| 12 | steps, one can gate it and keep the system running. Consider this | ||
| 13 | simplified suspend example: | ||
| 14 | |||
| 15 | While the system is operational, you would see something like | ||
| 16 | |||
| 17 | 24MHz 32kHz | ||
| 18 | | | ||
| 19 | PLL1 | ||
| 20 | \ | ||
| 21 | \_ CPU Mux | ||
| 22 | | | ||
| 23 | [CPU] | ||
| 24 | |||
| 25 | When you are about to suspend, you switch the CPU Mux to the 32kHz | ||
| 26 | oscillator: | ||
| 27 | |||
| 28 | 24Mhz 32kHz | ||
| 29 | | | | ||
| 30 | PLL1 | | ||
| 31 | / | ||
| 32 | CPU Mux _/ | ||
| 33 | | | ||
| 34 | [CPU] | ||
| 35 | |||
| 36 | Finally you can gate the main oscillator | ||
| 37 | |||
| 38 | 32kHz | ||
| 39 | | | ||
| 40 | | | ||
| 41 | / | ||
| 42 | CPU Mux _/ | ||
| 43 | | | ||
| 44 | [CPU] | ||
| 45 | |||
| 46 | Q: Were can I learn more about the sunxi clocks? | ||
| 47 | |||
| 48 | A: The linux-sunxi wiki contains a page documenting the clock registers, | ||
| 49 | you can find it at | ||
| 50 | |||
| 51 | http://linux-sunxi.org/A10/CCM | ||
| 52 | |||
| 53 | The authoritative source for information at this time is the ccmu driver | ||
| 54 | released by Allwinner, you can find it at | ||
| 55 | |||
| 56 | https://github.com/linux-sunxi/linux-sunxi/tree/sunxi-3.0/arch/arm/mach-sun4i/clock/ccmu | ||
diff --git a/Documentation/clk.txt b/Documentation/clk.txt index 1943fae014fd..b9911c27f496 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt | |||
| @@ -174,9 +174,9 @@ int clk_foo_enable(struct clk_hw *hw) | |||
| 174 | }; | 174 | }; |
| 175 | 175 | ||
| 176 | Below is a matrix detailing which clk_ops are mandatory based upon the | 176 | Below is a matrix detailing which clk_ops are mandatory based upon the |
| 177 | hardware capbilities of that clock. A cell marked as "y" means | 177 | hardware capabilities of that clock. A cell marked as "y" means |
| 178 | mandatory, a cell marked as "n" implies that either including that | 178 | mandatory, a cell marked as "n" implies that either including that |
| 179 | callback is invalid or otherwise uneccesary. Empty cells are either | 179 | callback is invalid or otherwise unnecessary. Empty cells are either |
| 180 | optional or must be evaluated on a case-by-case basis. | 180 | optional or must be evaluated on a case-by-case basis. |
| 181 | 181 | ||
| 182 | clock hardware characteristics | 182 | clock hardware characteristics |
| @@ -231,3 +231,14 @@ To better enforce this policy, always follow this simple rule: any | |||
| 231 | statically initialized clock data MUST be defined in a separate file | 231 | statically initialized clock data MUST be defined in a separate file |
| 232 | from the logic that implements its ops. Basically separate the logic | 232 | from the logic that implements its ops. Basically separate the logic |
| 233 | from the data and all is well. | 233 | from the data and all is well. |
| 234 | |||
| 235 | Part 6 - Disabling clock gating of unused clocks | ||
| 236 | |||
| 237 | Sometimes during development it can be useful to be able to bypass the | ||
| 238 | default disabling of unused clocks. For example, if drivers aren't enabling | ||
| 239 | clocks properly but rely on them being on from the bootloader, bypassing | ||
| 240 | the disabling means that the driver will remain functional while the issues | ||
| 241 | are sorted out. | ||
| 242 | |||
| 243 | To bypass this disabling, include "clk_ignore_unused" in the bootargs to the | ||
| 244 | kernel. | ||
diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt new file mode 100644 index 000000000000..028b493e97ff --- /dev/null +++ b/Documentation/devicetree/bindings/clock/axi-clkgen.txt | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | Binding for the axi-clkgen clock generator | ||
| 2 | |||
| 3 | This binding uses the common clock binding[1]. | ||
| 4 | |||
| 5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible : shall be "adi,axi-clkgen". | ||
| 9 | - #clock-cells : from common clock binding; Should always be set to 0. | ||
| 10 | - reg : Address and length of the axi-clkgen register set. | ||
| 11 | - clocks : Phandle and clock specifier for the parent clock. | ||
| 12 | |||
| 13 | Optional properties: | ||
| 14 | - clock-output-names : From common clock binding. | ||
| 15 | |||
| 16 | Example: | ||
| 17 | clock@0xff000000 { | ||
| 18 | compatible = "adi,axi-clkgen"; | ||
| 19 | #clock-cells = <0>; | ||
| 20 | reg = <0xff000000 0x1000>; | ||
| 21 | clocks = <&osc 1>; | ||
| 22 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/fixed-factor-clock.txt b/Documentation/devicetree/bindings/clock/fixed-factor-clock.txt new file mode 100644 index 000000000000..5757f9abfc26 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/fixed-factor-clock.txt | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | Binding for simple fixed factor rate clock sources. | ||
| 2 | |||
| 3 | This binding uses the common clock binding[1]. | ||
| 4 | |||
| 5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible : shall be "fixed-factor-clock". | ||
| 9 | - #clock-cells : from common clock binding; shall be set to 0. | ||
| 10 | - clock-div: fixed divider. | ||
| 11 | - clock-mult: fixed multiplier. | ||
| 12 | - clocks: parent clock. | ||
| 13 | |||
| 14 | Optional properties: | ||
| 15 | - clock-output-names : From common clock binding. | ||
| 16 | |||
| 17 | Example: | ||
| 18 | clock { | ||
| 19 | compatible = "fixed-factor-clock"; | ||
| 20 | clocks = <&parentclk>; | ||
| 21 | #clock-cells = <0>; | ||
| 22 | div = <2>; | ||
| 23 | mult = <1>; | ||
| 24 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/silabs,si5351.txt b/Documentation/devicetree/bindings/clock/silabs,si5351.txt new file mode 100644 index 000000000000..cc374651662c --- /dev/null +++ b/Documentation/devicetree/bindings/clock/silabs,si5351.txt | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | Binding for Silicon Labs Si5351a/b/c programmable i2c clock generator. | ||
| 2 | |||
| 3 | Reference | ||
| 4 | [1] Si5351A/B/C Data Sheet | ||
| 5 | http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf | ||
| 6 | |||
| 7 | The Si5351a/b/c are programmable i2c clock generators with upto 8 output | ||
| 8 | clocks. Si5351a also has a reduced pin-count package (MSOP10) where only | ||
| 9 | 3 output clocks are accessible. The internal structure of the clock | ||
| 10 | generators can be found in [1]. | ||
| 11 | |||
| 12 | ==I2C device node== | ||
| 13 | |||
| 14 | Required properties: | ||
| 15 | - compatible: shall be one of "silabs,si5351{a,a-msop,b,c}". | ||
| 16 | - reg: i2c device address, shall be 0x60 or 0x61. | ||
| 17 | - #clock-cells: from common clock binding; shall be set to 1. | ||
| 18 | - clocks: from common clock binding; list of parent clock | ||
| 19 | handles, shall be xtal reference clock or xtal and clkin for | ||
| 20 | si5351c only. | ||
| 21 | - #address-cells: shall be set to 1. | ||
| 22 | - #size-cells: shall be set to 0. | ||
| 23 | |||
| 24 | Optional properties: | ||
| 25 | - silabs,pll-source: pair of (number, source) for each pll. Allows | ||
| 26 | to overwrite clock source of pll A (number=0) or B (number=1). | ||
| 27 | |||
| 28 | ==Child nodes== | ||
| 29 | |||
| 30 | Each of the clock outputs can be overwritten individually by | ||
| 31 | using a child node to the I2C device node. If a child node for a clock | ||
| 32 | output is not set, the eeprom configuration is not overwritten. | ||
| 33 | |||
| 34 | Required child node properties: | ||
| 35 | - reg: number of clock output. | ||
| 36 | |||
| 37 | Optional child node properties: | ||
| 38 | - silabs,clock-source: source clock of the output divider stage N, shall be | ||
| 39 | 0 = multisynth N | ||
| 40 | 1 = multisynth 0 for output clocks 0-3, else multisynth4 | ||
| 41 | 2 = xtal | ||
| 42 | 3 = clkin (si5351c only) | ||
| 43 | - silabs,drive-strength: output drive strength in mA, shall be one of {2,4,6,8}. | ||
| 44 | - silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth | ||
| 45 | divider. | ||
| 46 | - silabs,pll-master: boolean, multisynth can change pll frequency. | ||
| 47 | |||
| 48 | ==Example== | ||
| 49 | |||
| 50 | /* 25MHz reference crystal */ | ||
| 51 | ref25: ref25M { | ||
| 52 | compatible = "fixed-clock"; | ||
| 53 | #clock-cells = <0>; | ||
| 54 | clock-frequency = <25000000>; | ||
| 55 | }; | ||
| 56 | |||
| 57 | i2c-master-node { | ||
| 58 | |||
| 59 | /* Si5351a msop10 i2c clock generator */ | ||
| 60 | si5351a: clock-generator@60 { | ||
| 61 | compatible = "silabs,si5351a-msop"; | ||
| 62 | reg = <0x60>; | ||
| 63 | #address-cells = <1>; | ||
| 64 | #size-cells = <0>; | ||
| 65 | #clock-cells = <1>; | ||
| 66 | |||
| 67 | /* connect xtal input to 25MHz reference */ | ||
| 68 | clocks = <&ref25>; | ||
| 69 | |||
| 70 | /* connect xtal input as source of pll0 and pll1 */ | ||
| 71 | silabs,pll-source = <0 0>, <1 0>; | ||
| 72 | |||
| 73 | /* | ||
| 74 | * overwrite clkout0 configuration with: | ||
| 75 | * - 8mA output drive strength | ||
| 76 | * - pll0 as clock source of multisynth0 | ||
| 77 | * - multisynth0 as clock source of output divider | ||
| 78 | * - multisynth0 can change pll0 | ||
| 79 | * - set initial clock frequency of 74.25MHz | ||
| 80 | */ | ||
| 81 | clkout0 { | ||
| 82 | reg = <0>; | ||
| 83 | silabs,drive-strength = <8>; | ||
| 84 | silabs,multisynth-source = <0>; | ||
| 85 | silabs,clock-source = <0>; | ||
| 86 | silabs,pll-master; | ||
| 87 | clock-frequency = <74250000>; | ||
| 88 | }; | ||
| 89 | |||
| 90 | /* | ||
| 91 | * overwrite clkout1 configuration with: | ||
| 92 | * - 4mA output drive strength | ||
| 93 | * - pll1 as clock source of multisynth1 | ||
| 94 | * - multisynth1 as clock source of output divider | ||
| 95 | * - multisynth1 can change pll1 | ||
| 96 | */ | ||
| 97 | clkout1 { | ||
| 98 | reg = <1>; | ||
| 99 | silabs,drive-strength = <4>; | ||
| 100 | silabs,multisynth-source = <1>; | ||
| 101 | silabs,clock-source = <0>; | ||
| 102 | pll-master; | ||
| 103 | }; | ||
| 104 | |||
| 105 | /* | ||
| 106 | * overwrite clkout2 configuration with: | ||
| 107 | * - xtal as clock source of output divider | ||
| 108 | */ | ||
| 109 | clkout2 { | ||
| 110 | reg = <2>; | ||
| 111 | silabs,clock-source = <2>; | ||
| 112 | }; | ||
| 113 | }; | ||
| 114 | }; | ||
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt new file mode 100644 index 000000000000..729f52426fe1 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/sunxi.txt | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | Device Tree Clock bindings for arch-sunxi | ||
| 2 | |||
| 3 | This binding uses the common clock binding[1]. | ||
| 4 | |||
| 5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible : shall be one of the following: | ||
| 9 | "allwinner,sun4i-osc-clk" - for a gatable oscillator | ||
| 10 | "allwinner,sun4i-pll1-clk" - for the main PLL clock | ||
| 11 | "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock | ||
| 12 | "allwinner,sun4i-axi-clk" - for the AXI clock | ||
| 13 | "allwinner,sun4i-axi-gates-clk" - for the AXI gates | ||
| 14 | "allwinner,sun4i-ahb-clk" - for the AHB clock | ||
| 15 | "allwinner,sun4i-ahb-gates-clk" - for the AHB gates | ||
| 16 | "allwinner,sun4i-apb0-clk" - for the APB0 clock | ||
| 17 | "allwinner,sun4i-apb0-gates-clk" - for the APB0 gates | ||
| 18 | "allwinner,sun4i-apb1-clk" - for the APB1 clock | ||
| 19 | "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing | ||
| 20 | "allwinner,sun4i-apb1-gates-clk" - for the APB1 gates | ||
| 21 | |||
| 22 | Required properties for all clocks: | ||
| 23 | - reg : shall be the control register address for the clock. | ||
| 24 | - clocks : shall be the input parent clock(s) phandle for the clock | ||
| 25 | - #clock-cells : from common clock binding; shall be set to 0 except for | ||
| 26 | "allwinner,sun4i-*-gates-clk" where it shall be set to 1 | ||
| 27 | |||
| 28 | Additionally, "allwinner,sun4i-*-gates-clk" clocks require: | ||
| 29 | - clock-output-names : the corresponding gate names that the clock controls | ||
| 30 | |||
| 31 | For example: | ||
| 32 | |||
| 33 | osc24M: osc24M@01c20050 { | ||
| 34 | #clock-cells = <0>; | ||
| 35 | compatible = "allwinner,sun4i-osc-clk"; | ||
| 36 | reg = <0x01c20050 0x4>; | ||
| 37 | clocks = <&osc24M_fixed>; | ||
| 38 | }; | ||
| 39 | |||
| 40 | pll1: pll1@01c20000 { | ||
| 41 | #clock-cells = <0>; | ||
| 42 | compatible = "allwinner,sun4i-pll1-clk"; | ||
| 43 | reg = <0x01c20000 0x4>; | ||
| 44 | clocks = <&osc24M>; | ||
| 45 | }; | ||
| 46 | |||
| 47 | cpu: cpu@01c20054 { | ||
| 48 | #clock-cells = <0>; | ||
| 49 | compatible = "allwinner,sun4i-cpu-clk"; | ||
| 50 | reg = <0x01c20054 0x4>; | ||
| 51 | clocks = <&osc32k>, <&osc24M>, <&pll1>; | ||
| 52 | }; | ||
| 53 | |||
| 54 | |||
| 55 | |||
| 56 | Gate clock outputs | ||
| 57 | |||
| 58 | The "allwinner,sun4i-*-gates-clk" clocks provide several gatable outputs; | ||
| 59 | their corresponding offsets as present on sun4i are listed below. Note that | ||
| 60 | some of these gates are not present on sun5i. | ||
| 61 | |||
| 62 | * AXI gates ("allwinner,sun4i-axi-gates-clk") | ||
| 63 | |||
| 64 | DRAM 0 | ||
| 65 | |||
| 66 | * AHB gates ("allwinner,sun4i-ahb-gates-clk") | ||
| 67 | |||
| 68 | USB0 0 | ||
| 69 | EHCI0 1 | ||
| 70 | OHCI0 2* | ||
| 71 | EHCI1 3 | ||
| 72 | OHCI1 4* | ||
| 73 | SS 5 | ||
| 74 | DMA 6 | ||
| 75 | BIST 7 | ||
| 76 | MMC0 8 | ||
| 77 | MMC1 9 | ||
| 78 | MMC2 10 | ||
| 79 | MMC3 11 | ||
| 80 | MS 12** | ||
| 81 | NAND 13 | ||
| 82 | SDRAM 14 | ||
| 83 | |||
| 84 | ACE 16 | ||
| 85 | EMAC 17 | ||
| 86 | TS 18 | ||
| 87 | |||
| 88 | SPI0 20 | ||
| 89 | SPI1 21 | ||
| 90 | SPI2 22 | ||
| 91 | SPI3 23 | ||
| 92 | PATA 24 | ||
| 93 | SATA 25** | ||
| 94 | GPS 26* | ||
| 95 | |||
| 96 | VE 32 | ||
| 97 | TVD 33 | ||
| 98 | TVE0 34 | ||
| 99 | TVE1 35 | ||
| 100 | LCD0 36 | ||
| 101 | LCD1 37 | ||
| 102 | |||
| 103 | CSI0 40 | ||
| 104 | CSI1 41 | ||
| 105 | |||
| 106 | HDMI 43 | ||
| 107 | DE_BE0 44 | ||
| 108 | DE_BE1 45 | ||
| 109 | DE_FE0 46 | ||
| 110 | DE_FE1 47 | ||
| 111 | |||
| 112 | MP 50 | ||
| 113 | |||
| 114 | MALI400 52 | ||
| 115 | |||
| 116 | * APB0 gates ("allwinner,sun4i-apb0-gates-clk") | ||
| 117 | |||
| 118 | CODEC 0 | ||
| 119 | SPDIF 1* | ||
| 120 | AC97 2 | ||
| 121 | IIS 3 | ||
| 122 | |||
| 123 | PIO 5 | ||
| 124 | IR0 6 | ||
| 125 | IR1 7 | ||
| 126 | |||
| 127 | KEYPAD 10 | ||
| 128 | |||
| 129 | * APB1 gates ("allwinner,sun4i-apb1-gates-clk") | ||
| 130 | |||
| 131 | I2C0 0 | ||
| 132 | I2C1 1 | ||
| 133 | I2C2 2 | ||
| 134 | |||
| 135 | CAN 4 | ||
| 136 | SCR 5 | ||
| 137 | PS20 6 | ||
| 138 | PS21 7 | ||
| 139 | |||
| 140 | UART0 16 | ||
| 141 | UART1 17 | ||
| 142 | UART2 18 | ||
| 143 | UART3 19 | ||
| 144 | UART4 20 | ||
| 145 | UART5 21 | ||
| 146 | UART6 22 | ||
| 147 | UART7 23 | ||
| 148 | |||
| 149 | Notation: | ||
| 150 | [*]: The datasheet didn't mention these, but they are present on AW code | ||
| 151 | [**]: The datasheet had this marked as "NC" but they are used on AW code | ||
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 3b3b0194adfe..4d1919bf2332 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt | |||
| @@ -49,6 +49,7 @@ samsung Samsung Semiconductor | |||
| 49 | sbs Smart Battery System | 49 | sbs Smart Battery System |
| 50 | schindler Schindler | 50 | schindler Schindler |
| 51 | sil Silicon Image | 51 | sil Silicon Image |
| 52 | silabs Silicon Laboratories | ||
| 52 | simtek | 53 | simtek |
| 53 | sirf SiRF Technology, Inc. | 54 | sirf SiRF Technology, Inc. |
| 54 | snps Synopsys, Inc. | 55 | snps Synopsys, Inc. |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 5abc09a93bc2..365f7bd40eeb 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -44,6 +44,7 @@ parameter is applicable: | |||
| 44 | AVR32 AVR32 architecture is enabled. | 44 | AVR32 AVR32 architecture is enabled. |
| 45 | AX25 Appropriate AX.25 support is enabled. | 45 | AX25 Appropriate AX.25 support is enabled. |
| 46 | BLACKFIN Blackfin architecture is enabled. | 46 | BLACKFIN Blackfin architecture is enabled. |
| 47 | CLK Common clock infrastructure is enabled. | ||
| 47 | DRM Direct Rendering Management support is enabled. | 48 | DRM Direct Rendering Management support is enabled. |
| 48 | DYNAMIC_DEBUG Build in debug messages and enable them at runtime | 49 | DYNAMIC_DEBUG Build in debug messages and enable them at runtime |
| 49 | EDD BIOS Enhanced Disk Drive Services (EDD) is enabled | 50 | EDD BIOS Enhanced Disk Drive Services (EDD) is enabled |
| @@ -472,6 +473,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 472 | 473 | ||
| 473 | cio_ignore= [S390] | 474 | cio_ignore= [S390] |
| 474 | See Documentation/s390/CommonIO for details. | 475 | See Documentation/s390/CommonIO for details. |
| 476 | clk_ignore_unused | ||
| 477 | [CLK] | ||
| 478 | Keep all clocks already enabled by bootloader on, | ||
| 479 | even if no driver has claimed them. This is useful | ||
| 480 | for debug and development, but should not be | ||
| 481 | needed on a platform with proper driver support. | ||
| 482 | For more information, see Documentation/clk.txt. | ||
| 475 | 483 | ||
| 476 | clock= [BUGS=X86-32, HW] gettimeofday clocksource override. | 484 | clock= [BUGS=X86-32, HW] gettimeofday clocksource override. |
| 477 | [Deprecated] | 485 | [Deprecated] |
diff --git a/arch/arm/mach-imx/clk-busy.c b/arch/arm/mach-imx/clk-busy.c index 1ab91b5209e6..85b728cc27ab 100644 --- a/arch/arm/mach-imx/clk-busy.c +++ b/arch/arm/mach-imx/clk-busy.c | |||
| @@ -169,7 +169,7 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift, | |||
| 169 | 169 | ||
| 170 | busy->mux.reg = reg; | 170 | busy->mux.reg = reg; |
| 171 | busy->mux.shift = shift; | 171 | busy->mux.shift = shift; |
| 172 | busy->mux.width = width; | 172 | busy->mux.mask = BIT(width) - 1; |
| 173 | busy->mux.lock = &imx_ccm_lock; | 173 | busy->mux.lock = &imx_ccm_lock; |
| 174 | busy->mux_ops = &clk_mux_ops; | 174 | busy->mux_ops = &clk_mux_ops; |
| 175 | 175 | ||
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c index 915683cb67d6..c5e20b52e3b7 100644 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #include <linux/regulator/fixed.h> | 21 | #include <linux/regulator/fixed.h> |
| 22 | #include <linux/regulator/machine.h> | 22 | #include <linux/regulator/machine.h> |
| 23 | #include <linux/vexpress.h> | 23 | #include <linux/vexpress.h> |
| 24 | #include <linux/clk-provider.h> | ||
| 25 | #include <linux/clkdev.h> | ||
| 24 | 26 | ||
| 25 | #include <asm/arch_timer.h> | 27 | #include <asm/arch_timer.h> |
| 26 | #include <asm/mach-types.h> | 28 | #include <asm/mach-types.h> |
| @@ -433,7 +435,7 @@ static void __init v2m_dt_timer_init(void) | |||
| 433 | { | 435 | { |
| 434 | struct device_node *node = NULL; | 436 | struct device_node *node = NULL; |
| 435 | 437 | ||
| 436 | vexpress_clk_of_init(); | 438 | of_clk_init(NULL); |
| 437 | 439 | ||
| 438 | do { | 440 | do { |
| 439 | node = of_find_compatible_node(node, NULL, "arm,sp804"); | 441 | node = of_find_compatible_node(node, NULL, "arm,sp804"); |
| @@ -441,6 +443,10 @@ static void __init v2m_dt_timer_init(void) | |||
| 441 | if (node) { | 443 | if (node) { |
| 442 | pr_info("Using SP804 '%s' as a clock & events source\n", | 444 | pr_info("Using SP804 '%s' as a clock & events source\n", |
| 443 | node->full_name); | 445 | node->full_name); |
| 446 | WARN_ON(clk_register_clkdev(of_clk_get_by_name(node, | ||
| 447 | "timclken1"), "v2m-timer0", "sp804")); | ||
| 448 | WARN_ON(clk_register_clkdev(of_clk_get_by_name(node, | ||
| 449 | "timclken2"), "v2m-timer1", "sp804")); | ||
| 444 | v2m_sp804_init(of_iomap(node, 0), | 450 | v2m_sp804_init(of_iomap(node, 0), |
| 445 | irq_of_parse_and_map(node, 0)); | 451 | irq_of_parse_and_map(node, 0)); |
| 446 | } | 452 | } |
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index a47e6ee98b8c..0357ac44638b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
| @@ -55,6 +55,16 @@ config COMMON_CLK_MAX77686 | |||
| 55 | ---help--- | 55 | ---help--- |
| 56 | This driver supports Maxim 77686 crystal oscillator clock. | 56 | This driver supports Maxim 77686 crystal oscillator clock. |
| 57 | 57 | ||
| 58 | config COMMON_CLK_SI5351 | ||
| 59 | tristate "Clock driver for SiLabs 5351A/B/C" | ||
| 60 | depends on I2C | ||
| 61 | depends on OF | ||
| 62 | select REGMAP_I2C | ||
| 63 | select RATIONAL | ||
| 64 | ---help--- | ||
| 65 | This driver supports Silicon Labs 5351A/B/C programmable clock | ||
| 66 | generators. | ||
| 67 | |||
| 58 | config CLK_TWL6040 | 68 | config CLK_TWL6040 |
| 59 | tristate "External McPDM functional clock from twl6040" | 69 | tristate "External McPDM functional clock from twl6040" |
| 60 | depends on TWL6040_CORE | 70 | depends on TWL6040_CORE |
| @@ -63,6 +73,14 @@ config CLK_TWL6040 | |||
| 63 | McPDM. McPDM module is using the external bit clock on the McPDM bus | 73 | McPDM. McPDM module is using the external bit clock on the McPDM bus |
| 64 | as functional clock. | 74 | as functional clock. |
| 65 | 75 | ||
| 76 | config COMMON_CLK_AXI_CLKGEN | ||
| 77 | tristate "AXI clkgen driver" | ||
| 78 | depends on ARCH_ZYNQ || MICROBLAZE | ||
| 79 | help | ||
| 80 | ---help--- | ||
| 81 | Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx | ||
| 82 | FPGAs. It is commonly used in Analog Devices' reference designs. | ||
| 83 | |||
| 66 | endmenu | 84 | endmenu |
| 67 | 85 | ||
| 68 | source "drivers/clk/mvebu/Kconfig" | 86 | source "drivers/clk/mvebu/Kconfig" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 300d4775d926..e7f7fe9b2f09 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
| @@ -7,6 +7,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o | |||
| 7 | obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o | 7 | obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o |
| 8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o | 8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o |
| 9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o | 9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o |
| 10 | obj-$(CONFIG_COMMON_CLK) += clk-composite.o | ||
| 10 | 11 | ||
| 11 | # SoCs specific | 12 | # SoCs specific |
| 12 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o | 13 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o |
| @@ -23,6 +24,7 @@ ifeq ($(CONFIG_COMMON_CLK), y) | |||
| 23 | obj-$(CONFIG_ARCH_MMP) += mmp/ | 24 | obj-$(CONFIG_ARCH_MMP) += mmp/ |
| 24 | endif | 25 | endif |
| 25 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o | 26 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o |
| 27 | obj-$(CONFIG_ARCH_SUNXI) += sunxi/ | ||
| 26 | obj-$(CONFIG_ARCH_U8500) += ux500/ | 28 | obj-$(CONFIG_ARCH_U8500) += ux500/ |
| 27 | obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o | 29 | obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o |
| 28 | obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o | 30 | obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o |
| @@ -31,6 +33,8 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ | |||
| 31 | obj-$(CONFIG_X86) += x86/ | 33 | obj-$(CONFIG_X86) += x86/ |
| 32 | 34 | ||
| 33 | # Chip specific | 35 | # Chip specific |
| 36 | obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o | ||
| 34 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o | 37 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o |
| 35 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o | 38 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
| 39 | obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o | ||
| 36 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o | 40 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o |
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c new file mode 100644 index 000000000000..8137327847c3 --- /dev/null +++ b/drivers/clk/clk-axi-clkgen.c | |||
| @@ -0,0 +1,331 @@ | |||
| 1 | /* | ||
| 2 | * AXI clkgen driver | ||
| 3 | * | ||
| 4 | * Copyright 2012-2013 Analog Devices Inc. | ||
| 5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
| 6 | * | ||
| 7 | * Licensed under the GPL-2. | ||
| 8 | * | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/clk-provider.h> | ||
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/slab.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/of.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/err.h> | ||
| 19 | |||
| 20 | #define AXI_CLKGEN_REG_UPDATE_ENABLE 0x04 | ||
| 21 | #define AXI_CLKGEN_REG_CLK_OUT1 0x08 | ||
| 22 | #define AXI_CLKGEN_REG_CLK_OUT2 0x0c | ||
| 23 | #define AXI_CLKGEN_REG_CLK_DIV 0x10 | ||
| 24 | #define AXI_CLKGEN_REG_CLK_FB1 0x14 | ||
| 25 | #define AXI_CLKGEN_REG_CLK_FB2 0x18 | ||
| 26 | #define AXI_CLKGEN_REG_LOCK1 0x1c | ||
| 27 | #define AXI_CLKGEN_REG_LOCK2 0x20 | ||
| 28 | #define AXI_CLKGEN_REG_LOCK3 0x24 | ||
| 29 | #define AXI_CLKGEN_REG_FILTER1 0x28 | ||
| 30 | #define AXI_CLKGEN_REG_FILTER2 0x2c | ||
| 31 | |||
| 32 | struct axi_clkgen { | ||
| 33 | void __iomem *base; | ||
| 34 | struct clk_hw clk_hw; | ||
| 35 | }; | ||
| 36 | |||
| 37 | static uint32_t axi_clkgen_lookup_filter(unsigned int m) | ||
| 38 | { | ||
| 39 | switch (m) { | ||
| 40 | case 0: | ||
| 41 | return 0x01001990; | ||
| 42 | case 1: | ||
| 43 | return 0x01001190; | ||
| 44 | case 2: | ||
| 45 | return 0x01009890; | ||
| 46 | case 3: | ||
| 47 | return 0x01001890; | ||
| 48 | case 4: | ||
| 49 | return 0x01008890; | ||
| 50 | case 5 ... 8: | ||
| 51 | return 0x01009090; | ||
| 52 | case 9 ... 11: | ||
| 53 | return 0x01000890; | ||
| 54 | case 12: | ||
| 55 | return 0x08009090; | ||
| 56 | case 13 ... 22: | ||
| 57 | return 0x01001090; | ||
| 58 | case 23 ... 36: | ||
| 59 | return 0x01008090; | ||
| 60 | case 37 ... 46: | ||
| 61 | return 0x08001090; | ||
| 62 | default: | ||
| 63 | return 0x08008090; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | static const uint32_t axi_clkgen_lock_table[] = { | ||
| 68 | 0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8, | ||
| 69 | 0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8, | ||
| 70 | 0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339, | ||
| 71 | 0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271, | ||
| 72 | 0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4, | ||
| 73 | 0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190, | ||
| 74 | 0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e, | ||
| 75 | 0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c, | ||
| 76 | 0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113, | ||
| 77 | }; | ||
| 78 | |||
| 79 | static uint32_t axi_clkgen_lookup_lock(unsigned int m) | ||
| 80 | { | ||
| 81 | if (m < ARRAY_SIZE(axi_clkgen_lock_table)) | ||
| 82 | return axi_clkgen_lock_table[m]; | ||
| 83 | return 0x1f1f00fa; | ||
| 84 | } | ||
| 85 | |||
| 86 | static const unsigned int fpfd_min = 10000; | ||
| 87 | static const unsigned int fpfd_max = 300000; | ||
| 88 | static const unsigned int fvco_min = 600000; | ||
| 89 | static const unsigned int fvco_max = 1200000; | ||
| 90 | |||
| 91 | static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout, | ||
| 92 | unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout) | ||
| 93 | { | ||
| 94 | unsigned long d, d_min, d_max, _d_min, _d_max; | ||
| 95 | unsigned long m, m_min, m_max; | ||
| 96 | unsigned long f, dout, best_f, fvco; | ||
| 97 | |||
| 98 | fin /= 1000; | ||
| 99 | fout /= 1000; | ||
| 100 | |||
| 101 | best_f = ULONG_MAX; | ||
| 102 | *best_d = 0; | ||
| 103 | *best_m = 0; | ||
| 104 | *best_dout = 0; | ||
| 105 | |||
| 106 | d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1); | ||
| 107 | d_max = min_t(unsigned long, fin / fpfd_min, 80); | ||
| 108 | |||
| 109 | m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1); | ||
| 110 | m_max = min_t(unsigned long, fvco_max * d_max / fin, 64); | ||
| 111 | |||
| 112 | for (m = m_min; m <= m_max; m++) { | ||
| 113 | _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max)); | ||
| 114 | _d_max = min(d_max, fin * m / fvco_min); | ||
| 115 | |||
| 116 | for (d = _d_min; d <= _d_max; d++) { | ||
| 117 | fvco = fin * m / d; | ||
| 118 | |||
| 119 | dout = DIV_ROUND_CLOSEST(fvco, fout); | ||
| 120 | dout = clamp_t(unsigned long, dout, 1, 128); | ||
| 121 | f = fvco / dout; | ||
| 122 | if (abs(f - fout) < abs(best_f - fout)) { | ||
| 123 | best_f = f; | ||
| 124 | *best_d = d; | ||
| 125 | *best_m = m; | ||
| 126 | *best_dout = dout; | ||
| 127 | if (best_f == fout) | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low, | ||
| 135 | unsigned int *high, unsigned int *edge, unsigned int *nocount) | ||
| 136 | { | ||
| 137 | if (divider == 1) | ||
| 138 | *nocount = 1; | ||
| 139 | else | ||
| 140 | *nocount = 0; | ||
| 141 | |||
| 142 | *high = divider / 2; | ||
| 143 | *edge = divider % 2; | ||
| 144 | *low = divider - *high; | ||
| 145 | } | ||
| 146 | |||
| 147 | static void axi_clkgen_write(struct axi_clkgen *axi_clkgen, | ||
| 148 | unsigned int reg, unsigned int val) | ||
| 149 | { | ||
| 150 | writel(val, axi_clkgen->base + reg); | ||
| 151 | } | ||
| 152 | |||
| 153 | static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, | ||
| 154 | unsigned int reg, unsigned int *val) | ||
| 155 | { | ||
| 156 | *val = readl(axi_clkgen->base + reg); | ||
| 157 | } | ||
| 158 | |||
| 159 | static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) | ||
| 160 | { | ||
| 161 | return container_of(clk_hw, struct axi_clkgen, clk_hw); | ||
| 162 | } | ||
| 163 | |||
| 164 | static int axi_clkgen_set_rate(struct clk_hw *clk_hw, | ||
| 165 | unsigned long rate, unsigned long parent_rate) | ||
| 166 | { | ||
| 167 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
| 168 | unsigned int d, m, dout; | ||
| 169 | unsigned int nocount; | ||
| 170 | unsigned int high; | ||
| 171 | unsigned int edge; | ||
| 172 | unsigned int low; | ||
| 173 | uint32_t filter; | ||
| 174 | uint32_t lock; | ||
| 175 | |||
| 176 | if (parent_rate == 0 || rate == 0) | ||
| 177 | return -EINVAL; | ||
| 178 | |||
| 179 | axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout); | ||
| 180 | |||
| 181 | if (d == 0 || dout == 0 || m == 0) | ||
| 182 | return -EINVAL; | ||
| 183 | |||
| 184 | filter = axi_clkgen_lookup_filter(m - 1); | ||
| 185 | lock = axi_clkgen_lookup_lock(m - 1); | ||
| 186 | |||
| 187 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0); | ||
| 188 | |||
| 189 | axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); | ||
| 190 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, | ||
| 191 | (high << 6) | low); | ||
| 192 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2, | ||
| 193 | (edge << 7) | (nocount << 6)); | ||
| 194 | |||
| 195 | axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); | ||
| 196 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, | ||
| 197 | (edge << 13) | (nocount << 12) | (high << 6) | low); | ||
| 198 | |||
| 199 | axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); | ||
| 200 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, | ||
| 201 | (high << 6) | low); | ||
| 202 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2, | ||
| 203 | (edge << 7) | (nocount << 6)); | ||
| 204 | |||
| 205 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff); | ||
| 206 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2, | ||
| 207 | (((lock >> 16) & 0x1f) << 10) | 0x1); | ||
| 208 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3, | ||
| 209 | (((lock >> 24) & 0x1f) << 10) | 0x3e9); | ||
| 210 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16); | ||
| 211 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter); | ||
| 212 | |||
| 213 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1); | ||
| 214 | |||
| 215 | return 0; | ||
| 216 | } | ||
| 217 | |||
| 218 | static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 219 | unsigned long *parent_rate) | ||
| 220 | { | ||
| 221 | unsigned int d, m, dout; | ||
| 222 | |||
| 223 | axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout); | ||
| 224 | |||
| 225 | if (d == 0 || dout == 0 || m == 0) | ||
| 226 | return -EINVAL; | ||
| 227 | |||
| 228 | return *parent_rate / d * m / dout; | ||
| 229 | } | ||
| 230 | |||
| 231 | static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, | ||
| 232 | unsigned long parent_rate) | ||
| 233 | { | ||
| 234 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
| 235 | unsigned int d, m, dout; | ||
| 236 | unsigned int reg; | ||
| 237 | unsigned long long tmp; | ||
| 238 | |||
| 239 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, ®); | ||
| 240 | dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
| 241 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, ®); | ||
| 242 | d = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
| 243 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, ®); | ||
| 244 | m = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
| 245 | |||
| 246 | if (d == 0 || dout == 0) | ||
| 247 | return 0; | ||
| 248 | |||
| 249 | tmp = (unsigned long long)(parent_rate / d) * m; | ||
| 250 | do_div(tmp, dout); | ||
| 251 | |||
| 252 | if (tmp > ULONG_MAX) | ||
| 253 | return ULONG_MAX; | ||
| 254 | |||
| 255 | return tmp; | ||
| 256 | } | ||
| 257 | |||
| 258 | static const struct clk_ops axi_clkgen_ops = { | ||
| 259 | .recalc_rate = axi_clkgen_recalc_rate, | ||
| 260 | .round_rate = axi_clkgen_round_rate, | ||
| 261 | .set_rate = axi_clkgen_set_rate, | ||
| 262 | }; | ||
| 263 | |||
| 264 | static int axi_clkgen_probe(struct platform_device *pdev) | ||
| 265 | { | ||
| 266 | struct axi_clkgen *axi_clkgen; | ||
| 267 | struct clk_init_data init; | ||
| 268 | const char *parent_name; | ||
| 269 | const char *clk_name; | ||
| 270 | struct resource *mem; | ||
| 271 | struct clk *clk; | ||
| 272 | |||
| 273 | axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); | ||
| 274 | if (!axi_clkgen) | ||
| 275 | return -ENOMEM; | ||
| 276 | |||
| 277 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 278 | axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); | ||
| 279 | if (IS_ERR(axi_clkgen->base)) | ||
| 280 | return PTR_ERR(axi_clkgen->base); | ||
| 281 | |||
| 282 | parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0); | ||
| 283 | if (!parent_name) | ||
| 284 | return -EINVAL; | ||
| 285 | |||
| 286 | clk_name = pdev->dev.of_node->name; | ||
| 287 | of_property_read_string(pdev->dev.of_node, "clock-output-names", | ||
| 288 | &clk_name); | ||
| 289 | |||
| 290 | init.name = clk_name; | ||
| 291 | init.ops = &axi_clkgen_ops; | ||
| 292 | init.flags = 0; | ||
| 293 | init.parent_names = &parent_name; | ||
| 294 | init.num_parents = 1; | ||
| 295 | |||
| 296 | axi_clkgen->clk_hw.init = &init; | ||
| 297 | clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); | ||
| 298 | if (IS_ERR(clk)) | ||
| 299 | return PTR_ERR(clk); | ||
| 300 | |||
| 301 | return of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, | ||
| 302 | clk); | ||
| 303 | } | ||
| 304 | |||
| 305 | static int axi_clkgen_remove(struct platform_device *pdev) | ||
| 306 | { | ||
| 307 | of_clk_del_provider(pdev->dev.of_node); | ||
| 308 | |||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | static const struct of_device_id axi_clkgen_ids[] = { | ||
| 313 | { .compatible = "adi,axi-clkgen-1.00.a" }, | ||
| 314 | { }, | ||
| 315 | }; | ||
| 316 | MODULE_DEVICE_TABLE(of, axi_clkgen_ids); | ||
| 317 | |||
| 318 | static struct platform_driver axi_clkgen_driver = { | ||
| 319 | .driver = { | ||
| 320 | .name = "adi-axi-clkgen", | ||
| 321 | .owner = THIS_MODULE, | ||
| 322 | .of_match_table = axi_clkgen_ids, | ||
| 323 | }, | ||
| 324 | .probe = axi_clkgen_probe, | ||
| 325 | .remove = axi_clkgen_remove, | ||
| 326 | }; | ||
| 327 | module_platform_driver(axi_clkgen_driver); | ||
| 328 | |||
| 329 | MODULE_LICENSE("GPL v2"); | ||
| 330 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
| 331 | MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator"); | ||
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c new file mode 100644 index 000000000000..a33f46f20a41 --- /dev/null +++ b/drivers/clk/clk-composite.c | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify it | ||
| 5 | * under the terms and conditions of the GNU General Public License, | ||
| 6 | * version 2, as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 11 | * more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/clk.h> | ||
| 18 | #include <linux/clk-provider.h> | ||
| 19 | #include <linux/err.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | |||
| 22 | #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) | ||
| 23 | |||
| 24 | static u8 clk_composite_get_parent(struct clk_hw *hw) | ||
| 25 | { | ||
| 26 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 27 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
| 28 | struct clk_hw *mux_hw = composite->mux_hw; | ||
| 29 | |||
| 30 | mux_hw->clk = hw->clk; | ||
| 31 | |||
| 32 | return mux_ops->get_parent(mux_hw); | ||
| 33 | } | ||
| 34 | |||
| 35 | static int clk_composite_set_parent(struct clk_hw *hw, u8 index) | ||
| 36 | { | ||
| 37 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 38 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
| 39 | struct clk_hw *mux_hw = composite->mux_hw; | ||
| 40 | |||
| 41 | mux_hw->clk = hw->clk; | ||
| 42 | |||
| 43 | return mux_ops->set_parent(mux_hw, index); | ||
| 44 | } | ||
| 45 | |||
| 46 | static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, | ||
| 47 | unsigned long parent_rate) | ||
| 48 | { | ||
| 49 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 50 | const struct clk_ops *rate_ops = composite->rate_ops; | ||
| 51 | struct clk_hw *rate_hw = composite->rate_hw; | ||
| 52 | |||
| 53 | rate_hw->clk = hw->clk; | ||
| 54 | |||
| 55 | return rate_ops->recalc_rate(rate_hw, parent_rate); | ||
| 56 | } | ||
| 57 | |||
| 58 | static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 59 | unsigned long *prate) | ||
| 60 | { | ||
| 61 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 62 | const struct clk_ops *rate_ops = composite->rate_ops; | ||
| 63 | struct clk_hw *rate_hw = composite->rate_hw; | ||
| 64 | |||
| 65 | rate_hw->clk = hw->clk; | ||
| 66 | |||
| 67 | return rate_ops->round_rate(rate_hw, rate, prate); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 71 | unsigned long parent_rate) | ||
| 72 | { | ||
| 73 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 74 | const struct clk_ops *rate_ops = composite->rate_ops; | ||
| 75 | struct clk_hw *rate_hw = composite->rate_hw; | ||
| 76 | |||
| 77 | rate_hw->clk = hw->clk; | ||
| 78 | |||
| 79 | return rate_ops->set_rate(rate_hw, rate, parent_rate); | ||
| 80 | } | ||
| 81 | |||
| 82 | static int clk_composite_is_enabled(struct clk_hw *hw) | ||
| 83 | { | ||
| 84 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 85 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
| 86 | struct clk_hw *gate_hw = composite->gate_hw; | ||
| 87 | |||
| 88 | gate_hw->clk = hw->clk; | ||
| 89 | |||
| 90 | return gate_ops->is_enabled(gate_hw); | ||
| 91 | } | ||
| 92 | |||
| 93 | static int clk_composite_enable(struct clk_hw *hw) | ||
| 94 | { | ||
| 95 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 96 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
| 97 | struct clk_hw *gate_hw = composite->gate_hw; | ||
| 98 | |||
| 99 | gate_hw->clk = hw->clk; | ||
| 100 | |||
| 101 | return gate_ops->enable(gate_hw); | ||
| 102 | } | ||
| 103 | |||
| 104 | static void clk_composite_disable(struct clk_hw *hw) | ||
| 105 | { | ||
| 106 | struct clk_composite *composite = to_clk_composite(hw); | ||
| 107 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
| 108 | struct clk_hw *gate_hw = composite->gate_hw; | ||
| 109 | |||
| 110 | gate_hw->clk = hw->clk; | ||
| 111 | |||
| 112 | gate_ops->disable(gate_hw); | ||
| 113 | } | ||
| 114 | |||
| 115 | struct clk *clk_register_composite(struct device *dev, const char *name, | ||
| 116 | const char **parent_names, int num_parents, | ||
| 117 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | ||
| 118 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, | ||
| 119 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | ||
| 120 | unsigned long flags) | ||
| 121 | { | ||
| 122 | struct clk *clk; | ||
| 123 | struct clk_init_data init; | ||
| 124 | struct clk_composite *composite; | ||
| 125 | struct clk_ops *clk_composite_ops; | ||
| 126 | |||
| 127 | composite = kzalloc(sizeof(*composite), GFP_KERNEL); | ||
| 128 | if (!composite) { | ||
| 129 | pr_err("%s: could not allocate composite clk\n", __func__); | ||
| 130 | return ERR_PTR(-ENOMEM); | ||
| 131 | } | ||
| 132 | |||
| 133 | init.name = name; | ||
| 134 | init.flags = flags | CLK_IS_BASIC; | ||
| 135 | init.parent_names = parent_names; | ||
| 136 | init.num_parents = num_parents; | ||
| 137 | |||
| 138 | clk_composite_ops = &composite->ops; | ||
| 139 | |||
| 140 | if (mux_hw && mux_ops) { | ||
| 141 | if (!mux_ops->get_parent || !mux_ops->set_parent) { | ||
| 142 | clk = ERR_PTR(-EINVAL); | ||
| 143 | goto err; | ||
| 144 | } | ||
| 145 | |||
| 146 | composite->mux_hw = mux_hw; | ||
| 147 | composite->mux_ops = mux_ops; | ||
| 148 | clk_composite_ops->get_parent = clk_composite_get_parent; | ||
| 149 | clk_composite_ops->set_parent = clk_composite_set_parent; | ||
| 150 | } | ||
| 151 | |||
| 152 | if (rate_hw && rate_ops) { | ||
| 153 | if (!rate_ops->recalc_rate) { | ||
| 154 | clk = ERR_PTR(-EINVAL); | ||
| 155 | goto err; | ||
| 156 | } | ||
| 157 | |||
| 158 | /* .round_rate is a prerequisite for .set_rate */ | ||
| 159 | if (rate_ops->round_rate) { | ||
| 160 | clk_composite_ops->round_rate = clk_composite_round_rate; | ||
| 161 | if (rate_ops->set_rate) { | ||
| 162 | clk_composite_ops->set_rate = clk_composite_set_rate; | ||
| 163 | } | ||
| 164 | } else { | ||
| 165 | WARN(rate_ops->set_rate, | ||
| 166 | "%s: missing round_rate op is required\n", | ||
| 167 | __func__); | ||
| 168 | } | ||
| 169 | |||
| 170 | composite->rate_hw = rate_hw; | ||
| 171 | composite->rate_ops = rate_ops; | ||
| 172 | clk_composite_ops->recalc_rate = clk_composite_recalc_rate; | ||
| 173 | } | ||
| 174 | |||
| 175 | if (gate_hw && gate_ops) { | ||
| 176 | if (!gate_ops->is_enabled || !gate_ops->enable || | ||
| 177 | !gate_ops->disable) { | ||
| 178 | clk = ERR_PTR(-EINVAL); | ||
| 179 | goto err; | ||
| 180 | } | ||
| 181 | |||
| 182 | composite->gate_hw = gate_hw; | ||
| 183 | composite->gate_ops = gate_ops; | ||
| 184 | clk_composite_ops->is_enabled = clk_composite_is_enabled; | ||
| 185 | clk_composite_ops->enable = clk_composite_enable; | ||
| 186 | clk_composite_ops->disable = clk_composite_disable; | ||
| 187 | } | ||
| 188 | |||
| 189 | init.ops = clk_composite_ops; | ||
| 190 | composite->hw.init = &init; | ||
| 191 | |||
| 192 | clk = clk_register(dev, &composite->hw); | ||
| 193 | if (IS_ERR(clk)) | ||
| 194 | goto err; | ||
| 195 | |||
| 196 | if (composite->mux_hw) | ||
| 197 | composite->mux_hw->clk = clk; | ||
| 198 | |||
| 199 | if (composite->rate_hw) | ||
| 200 | composite->rate_hw->clk = clk; | ||
| 201 | |||
| 202 | if (composite->gate_hw) | ||
| 203 | composite->gate_hw->clk = clk; | ||
| 204 | |||
| 205 | return clk; | ||
| 206 | |||
| 207 | err: | ||
| 208 | kfree(composite); | ||
| 209 | return clk; | ||
| 210 | } | ||
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 68b402101170..6d9674160430 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c | |||
| @@ -109,8 +109,9 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, | |||
| 109 | 109 | ||
| 110 | div = _get_div(divider, val); | 110 | div = _get_div(divider, val); |
| 111 | if (!div) { | 111 | if (!div) { |
| 112 | WARN(1, "%s: Invalid divisor for clock %s\n", __func__, | 112 | WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), |
| 113 | __clk_get_name(hw->clk)); | 113 | "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n", |
| 114 | __clk_get_name(hw->clk)); | ||
| 114 | return parent_rate; | 115 | return parent_rate; |
| 115 | } | 116 | } |
| 116 | 117 | ||
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 1ef271e47594..9ff7d510faa3 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/clk-provider.h> | 11 | #include <linux/clk-provider.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
| 14 | #include <linux/of.h> | ||
| 14 | 15 | ||
| 15 | /* | 16 | /* |
| 16 | * DOC: basic fixed multiplier and divider clock that cannot gate | 17 | * DOC: basic fixed multiplier and divider clock that cannot gate |
| @@ -96,3 +97,38 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | |||
| 96 | 97 | ||
| 97 | return clk; | 98 | return clk; |
| 98 | } | 99 | } |
| 100 | #ifdef CONFIG_OF | ||
| 101 | /** | ||
| 102 | * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock | ||
| 103 | */ | ||
| 104 | void __init of_fixed_factor_clk_setup(struct device_node *node) | ||
| 105 | { | ||
| 106 | struct clk *clk; | ||
| 107 | const char *clk_name = node->name; | ||
| 108 | const char *parent_name; | ||
| 109 | u32 div, mult; | ||
| 110 | |||
| 111 | if (of_property_read_u32(node, "clock-div", &div)) { | ||
| 112 | pr_err("%s Fixed factor clock <%s> must have a clock-div property\n", | ||
| 113 | __func__, node->name); | ||
| 114 | return; | ||
| 115 | } | ||
| 116 | |||
| 117 | if (of_property_read_u32(node, "clock-mult", &mult)) { | ||
| 118 | pr_err("%s Fixed factor clock <%s> must have a clokc-mult property\n", | ||
| 119 | __func__, node->name); | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | |||
| 123 | of_property_read_string(node, "clock-output-names", &clk_name); | ||
| 124 | parent_name = of_clk_get_parent_name(node, 0); | ||
| 125 | |||
| 126 | clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0, | ||
| 127 | mult, div); | ||
| 128 | if (!IS_ERR(clk)) | ||
| 129 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 130 | } | ||
| 131 | EXPORT_SYMBOL_GPL(of_fixed_factor_clk_setup); | ||
| 132 | CLK_OF_DECLARE(fixed_factor_clk, "fixed-factor-clock", | ||
| 133 | of_fixed_factor_clk_setup); | ||
| 134 | #endif | ||
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 508c032edce4..25b1734560d0 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | static u8 clk_mux_get_parent(struct clk_hw *hw) | 32 | static u8 clk_mux_get_parent(struct clk_hw *hw) |
| 33 | { | 33 | { |
| 34 | struct clk_mux *mux = to_clk_mux(hw); | 34 | struct clk_mux *mux = to_clk_mux(hw); |
| 35 | int num_parents = __clk_get_num_parents(hw->clk); | ||
| 35 | u32 val; | 36 | u32 val; |
| 36 | 37 | ||
| 37 | /* | 38 | /* |
| @@ -42,7 +43,16 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) | |||
| 42 | * val = 0x4 really means "bit 2, index starts at bit 0" | 43 | * val = 0x4 really means "bit 2, index starts at bit 0" |
| 43 | */ | 44 | */ |
| 44 | val = readl(mux->reg) >> mux->shift; | 45 | val = readl(mux->reg) >> mux->shift; |
| 45 | val &= (1 << mux->width) - 1; | 46 | val &= mux->mask; |
| 47 | |||
| 48 | if (mux->table) { | ||
| 49 | int i; | ||
| 50 | |||
| 51 | for (i = 0; i < num_parents; i++) | ||
| 52 | if (mux->table[i] == val) | ||
| 53 | return i; | ||
| 54 | return -EINVAL; | ||
| 55 | } | ||
| 46 | 56 | ||
| 47 | if (val && (mux->flags & CLK_MUX_INDEX_BIT)) | 57 | if (val && (mux->flags & CLK_MUX_INDEX_BIT)) |
| 48 | val = ffs(val) - 1; | 58 | val = ffs(val) - 1; |
| @@ -50,7 +60,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) | |||
| 50 | if (val && (mux->flags & CLK_MUX_INDEX_ONE)) | 60 | if (val && (mux->flags & CLK_MUX_INDEX_ONE)) |
| 51 | val--; | 61 | val--; |
| 52 | 62 | ||
| 53 | if (val >= __clk_get_num_parents(hw->clk)) | 63 | if (val >= num_parents) |
| 54 | return -EINVAL; | 64 | return -EINVAL; |
| 55 | 65 | ||
| 56 | return val; | 66 | return val; |
| @@ -62,17 +72,22 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | |||
| 62 | u32 val; | 72 | u32 val; |
| 63 | unsigned long flags = 0; | 73 | unsigned long flags = 0; |
| 64 | 74 | ||
| 65 | if (mux->flags & CLK_MUX_INDEX_BIT) | 75 | if (mux->table) |
| 66 | index = (1 << ffs(index)); | 76 | index = mux->table[index]; |
| 67 | 77 | ||
| 68 | if (mux->flags & CLK_MUX_INDEX_ONE) | 78 | else { |
| 69 | index++; | 79 | if (mux->flags & CLK_MUX_INDEX_BIT) |
| 80 | index = (1 << ffs(index)); | ||
| 81 | |||
| 82 | if (mux->flags & CLK_MUX_INDEX_ONE) | ||
| 83 | index++; | ||
| 84 | } | ||
| 70 | 85 | ||
| 71 | if (mux->lock) | 86 | if (mux->lock) |
| 72 | spin_lock_irqsave(mux->lock, flags); | 87 | spin_lock_irqsave(mux->lock, flags); |
| 73 | 88 | ||
| 74 | val = readl(mux->reg); | 89 | val = readl(mux->reg); |
| 75 | val &= ~(((1 << mux->width) - 1) << mux->shift); | 90 | val &= ~(mux->mask << mux->shift); |
| 76 | val |= index << mux->shift; | 91 | val |= index << mux->shift; |
| 77 | writel(val, mux->reg); | 92 | writel(val, mux->reg); |
| 78 | 93 | ||
| @@ -88,10 +103,10 @@ const struct clk_ops clk_mux_ops = { | |||
| 88 | }; | 103 | }; |
| 89 | EXPORT_SYMBOL_GPL(clk_mux_ops); | 104 | EXPORT_SYMBOL_GPL(clk_mux_ops); |
| 90 | 105 | ||
| 91 | struct clk *clk_register_mux(struct device *dev, const char *name, | 106 | struct clk *clk_register_mux_table(struct device *dev, const char *name, |
| 92 | const char **parent_names, u8 num_parents, unsigned long flags, | 107 | const char **parent_names, u8 num_parents, unsigned long flags, |
| 93 | void __iomem *reg, u8 shift, u8 width, | 108 | void __iomem *reg, u8 shift, u32 mask, |
| 94 | u8 clk_mux_flags, spinlock_t *lock) | 109 | u8 clk_mux_flags, u32 *table, spinlock_t *lock) |
| 95 | { | 110 | { |
| 96 | struct clk_mux *mux; | 111 | struct clk_mux *mux; |
| 97 | struct clk *clk; | 112 | struct clk *clk; |
| @@ -113,9 +128,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
| 113 | /* struct clk_mux assignments */ | 128 | /* struct clk_mux assignments */ |
| 114 | mux->reg = reg; | 129 | mux->reg = reg; |
| 115 | mux->shift = shift; | 130 | mux->shift = shift; |
| 116 | mux->width = width; | 131 | mux->mask = mask; |
| 117 | mux->flags = clk_mux_flags; | 132 | mux->flags = clk_mux_flags; |
| 118 | mux->lock = lock; | 133 | mux->lock = lock; |
| 134 | mux->table = table; | ||
| 119 | mux->hw.init = &init; | 135 | mux->hw.init = &init; |
| 120 | 136 | ||
| 121 | clk = clk_register(dev, &mux->hw); | 137 | clk = clk_register(dev, &mux->hw); |
| @@ -125,3 +141,15 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
| 125 | 141 | ||
| 126 | return clk; | 142 | return clk; |
| 127 | } | 143 | } |
| 144 | |||
| 145 | struct clk *clk_register_mux(struct device *dev, const char *name, | ||
| 146 | const char **parent_names, u8 num_parents, unsigned long flags, | ||
| 147 | void __iomem *reg, u8 shift, u8 width, | ||
| 148 | u8 clk_mux_flags, spinlock_t *lock) | ||
| 149 | { | ||
| 150 | u32 mask = BIT(width) - 1; | ||
| 151 | |||
| 152 | return clk_register_mux_table(dev, name, parent_names, num_parents, | ||
| 153 | flags, reg, shift, mask, clk_mux_flags, | ||
| 154 | NULL, lock); | ||
| 155 | } | ||
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c index f8e9d0c27be2..643ca653fef0 100644 --- a/drivers/clk/clk-prima2.c +++ b/drivers/clk/clk-prima2.c | |||
| @@ -1113,7 +1113,7 @@ void __init sirfsoc_of_clk_init(void) | |||
| 1113 | 1113 | ||
| 1114 | for (i = pll1; i < maxclk; i++) { | 1114 | for (i = pll1; i < maxclk; i++) { |
| 1115 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); | 1115 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); |
| 1116 | BUG_ON(!prima2_clks[i]); | 1116 | BUG_ON(IS_ERR(prima2_clks[i])); |
| 1117 | } | 1117 | } |
| 1118 | clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); | 1118 | clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); |
| 1119 | clk_register_clkdev(prima2_clks[io], NULL, "io"); | 1119 | clk_register_clkdev(prima2_clks[io], NULL, "io"); |
diff --git a/drivers/clk/clk-si5351.c b/drivers/clk/clk-si5351.c new file mode 100644 index 000000000000..892728412e9d --- /dev/null +++ b/drivers/clk/clk-si5351.c | |||
| @@ -0,0 +1,1510 @@ | |||
| 1 | /* | ||
| 2 | * clk-si5351.c: Silicon Laboratories Si5351A/B/C I2C Clock Generator | ||
| 3 | * | ||
| 4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
| 5 | * Rabeeh Khoury <rabeeh@solid-run.com> | ||
| 6 | * | ||
| 7 | * References: | ||
| 8 | * [1] "Si5351A/B/C Data Sheet" | ||
| 9 | * http://www.silabs.com/Support%20Documents/TechnicalDocs/Si5351.pdf | ||
| 10 | * [2] "Manually Generating an Si5351 Register Map" | ||
| 11 | * http://www.silabs.com/Support%20Documents/TechnicalDocs/AN619.pdf | ||
| 12 | * | ||
| 13 | * This program is free software; you can redistribute it and/or modify it | ||
| 14 | * under the terms of the GNU General Public License as published by the | ||
| 15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 16 | * option) any later version. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/kernel.h> | ||
| 21 | #include <linux/clkdev.h> | ||
| 22 | #include <linux/clk-provider.h> | ||
| 23 | #include <linux/delay.h> | ||
| 24 | #include <linux/err.h> | ||
| 25 | #include <linux/errno.h> | ||
| 26 | #include <linux/rational.h> | ||
| 27 | #include <linux/i2c.h> | ||
| 28 | #include <linux/of_platform.h> | ||
| 29 | #include <linux/platform_data/si5351.h> | ||
| 30 | #include <linux/regmap.h> | ||
| 31 | #include <linux/slab.h> | ||
| 32 | #include <linux/string.h> | ||
| 33 | #include <asm/div64.h> | ||
| 34 | |||
| 35 | #include "clk-si5351.h" | ||
| 36 | |||
| 37 | struct si5351_driver_data; | ||
| 38 | |||
| 39 | struct si5351_parameters { | ||
| 40 | unsigned long p1; | ||
| 41 | unsigned long p2; | ||
| 42 | unsigned long p3; | ||
| 43 | int valid; | ||
| 44 | }; | ||
| 45 | |||
| 46 | struct si5351_hw_data { | ||
| 47 | struct clk_hw hw; | ||
| 48 | struct si5351_driver_data *drvdata; | ||
| 49 | struct si5351_parameters params; | ||
| 50 | unsigned char num; | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct si5351_driver_data { | ||
| 54 | enum si5351_variant variant; | ||
| 55 | struct i2c_client *client; | ||
| 56 | struct regmap *regmap; | ||
| 57 | struct clk_onecell_data onecell; | ||
| 58 | |||
| 59 | struct clk *pxtal; | ||
| 60 | const char *pxtal_name; | ||
| 61 | struct clk_hw xtal; | ||
| 62 | struct clk *pclkin; | ||
| 63 | const char *pclkin_name; | ||
| 64 | struct clk_hw clkin; | ||
| 65 | |||
| 66 | struct si5351_hw_data pll[2]; | ||
| 67 | struct si5351_hw_data *msynth; | ||
| 68 | struct si5351_hw_data *clkout; | ||
| 69 | }; | ||
| 70 | |||
| 71 | static const char const *si5351_input_names[] = { | ||
| 72 | "xtal", "clkin" | ||
| 73 | }; | ||
| 74 | static const char const *si5351_pll_names[] = { | ||
| 75 | "plla", "pllb", "vxco" | ||
| 76 | }; | ||
| 77 | static const char const *si5351_msynth_names[] = { | ||
| 78 | "ms0", "ms1", "ms2", "ms3", "ms4", "ms5", "ms6", "ms7" | ||
| 79 | }; | ||
| 80 | static const char const *si5351_clkout_names[] = { | ||
| 81 | "clk0", "clk1", "clk2", "clk3", "clk4", "clk5", "clk6", "clk7" | ||
| 82 | }; | ||
| 83 | |||
| 84 | /* | ||
| 85 | * Si5351 i2c regmap | ||
| 86 | */ | ||
| 87 | static inline u8 si5351_reg_read(struct si5351_driver_data *drvdata, u8 reg) | ||
| 88 | { | ||
| 89 | u32 val; | ||
| 90 | int ret; | ||
| 91 | |||
| 92 | ret = regmap_read(drvdata->regmap, reg, &val); | ||
| 93 | if (ret) { | ||
| 94 | dev_err(&drvdata->client->dev, | ||
| 95 | "unable to read from reg%02x\n", reg); | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | return (u8)val; | ||
| 100 | } | ||
| 101 | |||
| 102 | static inline int si5351_bulk_read(struct si5351_driver_data *drvdata, | ||
| 103 | u8 reg, u8 count, u8 *buf) | ||
| 104 | { | ||
| 105 | return regmap_bulk_read(drvdata->regmap, reg, buf, count); | ||
| 106 | } | ||
| 107 | |||
| 108 | static inline int si5351_reg_write(struct si5351_driver_data *drvdata, | ||
| 109 | u8 reg, u8 val) | ||
| 110 | { | ||
| 111 | return regmap_write(drvdata->regmap, reg, val); | ||
| 112 | } | ||
| 113 | |||
| 114 | static inline int si5351_bulk_write(struct si5351_driver_data *drvdata, | ||
| 115 | u8 reg, u8 count, const u8 *buf) | ||
| 116 | { | ||
| 117 | return regmap_raw_write(drvdata->regmap, reg, buf, count); | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline int si5351_set_bits(struct si5351_driver_data *drvdata, | ||
| 121 | u8 reg, u8 mask, u8 val) | ||
| 122 | { | ||
| 123 | return regmap_update_bits(drvdata->regmap, reg, mask, val); | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline u8 si5351_msynth_params_address(int num) | ||
| 127 | { | ||
| 128 | if (num > 5) | ||
| 129 | return SI5351_CLK6_PARAMETERS + (num - 6); | ||
| 130 | return SI5351_CLK0_PARAMETERS + (SI5351_PARAMETERS_LENGTH * num); | ||
| 131 | } | ||
| 132 | |||
| 133 | static void si5351_read_parameters(struct si5351_driver_data *drvdata, | ||
| 134 | u8 reg, struct si5351_parameters *params) | ||
| 135 | { | ||
| 136 | u8 buf[SI5351_PARAMETERS_LENGTH]; | ||
| 137 | |||
| 138 | switch (reg) { | ||
| 139 | case SI5351_CLK6_PARAMETERS: | ||
| 140 | case SI5351_CLK7_PARAMETERS: | ||
| 141 | buf[0] = si5351_reg_read(drvdata, reg); | ||
| 142 | params->p1 = buf[0]; | ||
| 143 | params->p2 = 0; | ||
| 144 | params->p3 = 1; | ||
| 145 | break; | ||
| 146 | default: | ||
| 147 | si5351_bulk_read(drvdata, reg, SI5351_PARAMETERS_LENGTH, buf); | ||
| 148 | params->p1 = ((buf[2] & 0x03) << 16) | (buf[3] << 8) | buf[4]; | ||
| 149 | params->p2 = ((buf[5] & 0x0f) << 16) | (buf[6] << 8) | buf[7]; | ||
| 150 | params->p3 = ((buf[5] & 0xf0) << 12) | (buf[0] << 8) | buf[1]; | ||
| 151 | } | ||
| 152 | params->valid = 1; | ||
| 153 | } | ||
| 154 | |||
| 155 | static void si5351_write_parameters(struct si5351_driver_data *drvdata, | ||
| 156 | u8 reg, struct si5351_parameters *params) | ||
| 157 | { | ||
| 158 | u8 buf[SI5351_PARAMETERS_LENGTH]; | ||
| 159 | |||
| 160 | switch (reg) { | ||
| 161 | case SI5351_CLK6_PARAMETERS: | ||
| 162 | case SI5351_CLK7_PARAMETERS: | ||
| 163 | buf[0] = params->p1 & 0xff; | ||
| 164 | si5351_reg_write(drvdata, reg, buf[0]); | ||
| 165 | break; | ||
| 166 | default: | ||
| 167 | buf[0] = ((params->p3 & 0x0ff00) >> 8) & 0xff; | ||
| 168 | buf[1] = params->p3 & 0xff; | ||
| 169 | /* save rdiv and divby4 */ | ||
| 170 | buf[2] = si5351_reg_read(drvdata, reg + 2) & ~0x03; | ||
| 171 | buf[2] |= ((params->p1 & 0x30000) >> 16) & 0x03; | ||
| 172 | buf[3] = ((params->p1 & 0x0ff00) >> 8) & 0xff; | ||
| 173 | buf[4] = params->p1 & 0xff; | ||
| 174 | buf[5] = ((params->p3 & 0xf0000) >> 12) | | ||
| 175 | ((params->p2 & 0xf0000) >> 16); | ||
| 176 | buf[6] = ((params->p2 & 0x0ff00) >> 8) & 0xff; | ||
| 177 | buf[7] = params->p2 & 0xff; | ||
| 178 | si5351_bulk_write(drvdata, reg, SI5351_PARAMETERS_LENGTH, buf); | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | static bool si5351_regmap_is_volatile(struct device *dev, unsigned int reg) | ||
| 183 | { | ||
| 184 | switch (reg) { | ||
| 185 | case SI5351_DEVICE_STATUS: | ||
| 186 | case SI5351_INTERRUPT_STATUS: | ||
| 187 | case SI5351_PLL_RESET: | ||
| 188 | return true; | ||
| 189 | } | ||
| 190 | return false; | ||
| 191 | } | ||
| 192 | |||
| 193 | static bool si5351_regmap_is_writeable(struct device *dev, unsigned int reg) | ||
| 194 | { | ||
| 195 | /* reserved registers */ | ||
| 196 | if (reg >= 4 && reg <= 8) | ||
| 197 | return false; | ||
| 198 | if (reg >= 10 && reg <= 14) | ||
| 199 | return false; | ||
| 200 | if (reg >= 173 && reg <= 176) | ||
| 201 | return false; | ||
| 202 | if (reg >= 178 && reg <= 182) | ||
| 203 | return false; | ||
| 204 | /* read-only */ | ||
| 205 | if (reg == SI5351_DEVICE_STATUS) | ||
| 206 | return false; | ||
| 207 | return true; | ||
| 208 | } | ||
| 209 | |||
| 210 | static struct regmap_config si5351_regmap_config = { | ||
| 211 | .reg_bits = 8, | ||
| 212 | .val_bits = 8, | ||
| 213 | .cache_type = REGCACHE_RBTREE, | ||
| 214 | .max_register = 187, | ||
| 215 | .writeable_reg = si5351_regmap_is_writeable, | ||
| 216 | .volatile_reg = si5351_regmap_is_volatile, | ||
| 217 | }; | ||
| 218 | |||
| 219 | /* | ||
| 220 | * Si5351 xtal clock input | ||
| 221 | */ | ||
| 222 | static int si5351_xtal_prepare(struct clk_hw *hw) | ||
| 223 | { | ||
| 224 | struct si5351_driver_data *drvdata = | ||
| 225 | container_of(hw, struct si5351_driver_data, xtal); | ||
| 226 | si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, | ||
| 227 | SI5351_XTAL_ENABLE, SI5351_XTAL_ENABLE); | ||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static void si5351_xtal_unprepare(struct clk_hw *hw) | ||
| 232 | { | ||
| 233 | struct si5351_driver_data *drvdata = | ||
| 234 | container_of(hw, struct si5351_driver_data, xtal); | ||
| 235 | si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, | ||
| 236 | SI5351_XTAL_ENABLE, 0); | ||
| 237 | } | ||
| 238 | |||
| 239 | static const struct clk_ops si5351_xtal_ops = { | ||
| 240 | .prepare = si5351_xtal_prepare, | ||
| 241 | .unprepare = si5351_xtal_unprepare, | ||
| 242 | }; | ||
| 243 | |||
| 244 | /* | ||
| 245 | * Si5351 clkin clock input (Si5351C only) | ||
| 246 | */ | ||
| 247 | static int si5351_clkin_prepare(struct clk_hw *hw) | ||
| 248 | { | ||
| 249 | struct si5351_driver_data *drvdata = | ||
| 250 | container_of(hw, struct si5351_driver_data, clkin); | ||
| 251 | si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, | ||
| 252 | SI5351_CLKIN_ENABLE, SI5351_CLKIN_ENABLE); | ||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static void si5351_clkin_unprepare(struct clk_hw *hw) | ||
| 257 | { | ||
| 258 | struct si5351_driver_data *drvdata = | ||
| 259 | container_of(hw, struct si5351_driver_data, clkin); | ||
| 260 | si5351_set_bits(drvdata, SI5351_FANOUT_ENABLE, | ||
| 261 | SI5351_CLKIN_ENABLE, 0); | ||
| 262 | } | ||
| 263 | |||
| 264 | /* | ||
| 265 | * CMOS clock source constraints: | ||
| 266 | * The input frequency range of the PLL is 10Mhz to 40MHz. | ||
| 267 | * If CLKIN is >40MHz, the input divider must be used. | ||
| 268 | */ | ||
| 269 | static unsigned long si5351_clkin_recalc_rate(struct clk_hw *hw, | ||
| 270 | unsigned long parent_rate) | ||
| 271 | { | ||
| 272 | struct si5351_driver_data *drvdata = | ||
| 273 | container_of(hw, struct si5351_driver_data, clkin); | ||
| 274 | unsigned long rate; | ||
| 275 | unsigned char idiv; | ||
| 276 | |||
| 277 | rate = parent_rate; | ||
| 278 | if (parent_rate > 160000000) { | ||
| 279 | idiv = SI5351_CLKIN_DIV_8; | ||
| 280 | rate /= 8; | ||
| 281 | } else if (parent_rate > 80000000) { | ||
| 282 | idiv = SI5351_CLKIN_DIV_4; | ||
| 283 | rate /= 4; | ||
| 284 | } else if (parent_rate > 40000000) { | ||
| 285 | idiv = SI5351_CLKIN_DIV_2; | ||
| 286 | rate /= 2; | ||
| 287 | } else { | ||
| 288 | idiv = SI5351_CLKIN_DIV_1; | ||
| 289 | } | ||
| 290 | |||
| 291 | si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE, | ||
| 292 | SI5351_CLKIN_DIV_MASK, idiv); | ||
| 293 | |||
| 294 | dev_dbg(&drvdata->client->dev, "%s - clkin div = %d, rate = %lu\n", | ||
| 295 | __func__, (1 << (idiv >> 6)), rate); | ||
| 296 | |||
| 297 | return rate; | ||
| 298 | } | ||
| 299 | |||
| 300 | static const struct clk_ops si5351_clkin_ops = { | ||
| 301 | .prepare = si5351_clkin_prepare, | ||
| 302 | .unprepare = si5351_clkin_unprepare, | ||
| 303 | .recalc_rate = si5351_clkin_recalc_rate, | ||
| 304 | }; | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Si5351 vxco clock input (Si5351B only) | ||
| 308 | */ | ||
| 309 | |||
| 310 | static int si5351_vxco_prepare(struct clk_hw *hw) | ||
| 311 | { | ||
| 312 | struct si5351_hw_data *hwdata = | ||
| 313 | container_of(hw, struct si5351_hw_data, hw); | ||
| 314 | |||
| 315 | dev_warn(&hwdata->drvdata->client->dev, "VXCO currently unsupported\n"); | ||
| 316 | |||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | static void si5351_vxco_unprepare(struct clk_hw *hw) | ||
| 321 | { | ||
| 322 | } | ||
| 323 | |||
| 324 | static unsigned long si5351_vxco_recalc_rate(struct clk_hw *hw, | ||
| 325 | unsigned long parent_rate) | ||
| 326 | { | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | static int si5351_vxco_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 331 | unsigned long parent) | ||
| 332 | { | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | static const struct clk_ops si5351_vxco_ops = { | ||
| 337 | .prepare = si5351_vxco_prepare, | ||
| 338 | .unprepare = si5351_vxco_unprepare, | ||
| 339 | .recalc_rate = si5351_vxco_recalc_rate, | ||
| 340 | .set_rate = si5351_vxco_set_rate, | ||
| 341 | }; | ||
| 342 | |||
| 343 | /* | ||
| 344 | * Si5351 pll a/b | ||
| 345 | * | ||
| 346 | * Feedback Multisynth Divider Equations [2] | ||
| 347 | * | ||
| 348 | * fVCO = fIN * (a + b/c) | ||
| 349 | * | ||
| 350 | * with 15 + 0/1048575 <= (a + b/c) <= 90 + 0/1048575 and | ||
| 351 | * fIN = fXTAL or fIN = fCLKIN/CLKIN_DIV | ||
| 352 | * | ||
| 353 | * Feedback Multisynth Register Equations | ||
| 354 | * | ||
| 355 | * (1) MSNx_P1[17:0] = 128 * a + floor(128 * b/c) - 512 | ||
| 356 | * (2) MSNx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c | ||
| 357 | * (3) MSNx_P3[19:0] = c | ||
| 358 | * | ||
| 359 | * Transposing (2) yields: (4) floor(128 * b/c) = (128 * b / MSNx_P2)/c | ||
| 360 | * | ||
| 361 | * Using (4) on (1) yields: | ||
| 362 | * MSNx_P1 = 128 * a + (128 * b/MSNx_P2)/c - 512 | ||
| 363 | * MSNx_P1 + 512 + MSNx_P2/c = 128 * a + 128 * b/c | ||
| 364 | * | ||
| 365 | * a + b/c = (MSNx_P1 + MSNx_P2/MSNx_P3 + 512)/128 | ||
| 366 | * = (MSNx_P1*MSNx_P3 + MSNx_P2 + 512*MSNx_P3)/(128*MSNx_P3) | ||
| 367 | * | ||
| 368 | */ | ||
| 369 | static int _si5351_pll_reparent(struct si5351_driver_data *drvdata, | ||
| 370 | int num, enum si5351_pll_src parent) | ||
| 371 | { | ||
| 372 | u8 mask = (num == 0) ? SI5351_PLLA_SOURCE : SI5351_PLLB_SOURCE; | ||
| 373 | |||
| 374 | if (parent == SI5351_PLL_SRC_DEFAULT) | ||
| 375 | return 0; | ||
| 376 | |||
| 377 | if (num > 2) | ||
| 378 | return -EINVAL; | ||
| 379 | |||
| 380 | if (drvdata->variant != SI5351_VARIANT_C && | ||
| 381 | parent != SI5351_PLL_SRC_XTAL) | ||
| 382 | return -EINVAL; | ||
| 383 | |||
| 384 | si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE, mask, | ||
| 385 | (parent == SI5351_PLL_SRC_XTAL) ? 0 : mask); | ||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | static unsigned char si5351_pll_get_parent(struct clk_hw *hw) | ||
| 390 | { | ||
| 391 | struct si5351_hw_data *hwdata = | ||
| 392 | container_of(hw, struct si5351_hw_data, hw); | ||
| 393 | u8 mask = (hwdata->num == 0) ? SI5351_PLLA_SOURCE : SI5351_PLLB_SOURCE; | ||
| 394 | u8 val; | ||
| 395 | |||
| 396 | val = si5351_reg_read(hwdata->drvdata, SI5351_PLL_INPUT_SOURCE); | ||
| 397 | |||
| 398 | return (val & mask) ? 1 : 0; | ||
| 399 | } | ||
| 400 | |||
| 401 | static int si5351_pll_set_parent(struct clk_hw *hw, u8 index) | ||
| 402 | { | ||
| 403 | struct si5351_hw_data *hwdata = | ||
| 404 | container_of(hw, struct si5351_hw_data, hw); | ||
| 405 | |||
| 406 | if (hwdata->drvdata->variant != SI5351_VARIANT_C && | ||
| 407 | index > 0) | ||
| 408 | return -EPERM; | ||
| 409 | |||
| 410 | if (index > 1) | ||
| 411 | return -EINVAL; | ||
| 412 | |||
| 413 | return _si5351_pll_reparent(hwdata->drvdata, hwdata->num, | ||
| 414 | (index == 0) ? SI5351_PLL_SRC_XTAL : | ||
| 415 | SI5351_PLL_SRC_CLKIN); | ||
| 416 | } | ||
| 417 | |||
| 418 | static unsigned long si5351_pll_recalc_rate(struct clk_hw *hw, | ||
| 419 | unsigned long parent_rate) | ||
| 420 | { | ||
| 421 | struct si5351_hw_data *hwdata = | ||
| 422 | container_of(hw, struct si5351_hw_data, hw); | ||
| 423 | u8 reg = (hwdata->num == 0) ? SI5351_PLLA_PARAMETERS : | ||
| 424 | SI5351_PLLB_PARAMETERS; | ||
| 425 | unsigned long long rate; | ||
| 426 | |||
| 427 | if (!hwdata->params.valid) | ||
| 428 | si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params); | ||
| 429 | |||
| 430 | if (hwdata->params.p3 == 0) | ||
| 431 | return parent_rate; | ||
| 432 | |||
| 433 | /* fVCO = fIN * (P1*P3 + 512*P3 + P2)/(128*P3) */ | ||
| 434 | rate = hwdata->params.p1 * hwdata->params.p3; | ||
| 435 | rate += 512 * hwdata->params.p3; | ||
| 436 | rate += hwdata->params.p2; | ||
| 437 | rate *= parent_rate; | ||
| 438 | do_div(rate, 128 * hwdata->params.p3); | ||
| 439 | |||
| 440 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 441 | "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n", | ||
| 442 | __func__, __clk_get_name(hwdata->hw.clk), | ||
| 443 | hwdata->params.p1, hwdata->params.p2, hwdata->params.p3, | ||
| 444 | parent_rate, (unsigned long)rate); | ||
| 445 | |||
| 446 | return (unsigned long)rate; | ||
| 447 | } | ||
| 448 | |||
| 449 | static long si5351_pll_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 450 | unsigned long *parent_rate) | ||
| 451 | { | ||
| 452 | struct si5351_hw_data *hwdata = | ||
| 453 | container_of(hw, struct si5351_hw_data, hw); | ||
| 454 | unsigned long rfrac, denom, a, b, c; | ||
| 455 | unsigned long long lltmp; | ||
| 456 | |||
| 457 | if (rate < SI5351_PLL_VCO_MIN) | ||
| 458 | rate = SI5351_PLL_VCO_MIN; | ||
| 459 | if (rate > SI5351_PLL_VCO_MAX) | ||
| 460 | rate = SI5351_PLL_VCO_MAX; | ||
| 461 | |||
| 462 | /* determine integer part of feedback equation */ | ||
| 463 | a = rate / *parent_rate; | ||
| 464 | |||
| 465 | if (a < SI5351_PLL_A_MIN) | ||
| 466 | rate = *parent_rate * SI5351_PLL_A_MIN; | ||
| 467 | if (a > SI5351_PLL_A_MAX) | ||
| 468 | rate = *parent_rate * SI5351_PLL_A_MAX; | ||
| 469 | |||
| 470 | /* find best approximation for b/c = fVCO mod fIN */ | ||
| 471 | denom = 1000 * 1000; | ||
| 472 | lltmp = rate % (*parent_rate); | ||
| 473 | lltmp *= denom; | ||
| 474 | do_div(lltmp, *parent_rate); | ||
| 475 | rfrac = (unsigned long)lltmp; | ||
| 476 | |||
| 477 | b = 0; | ||
| 478 | c = 1; | ||
| 479 | if (rfrac) | ||
| 480 | rational_best_approximation(rfrac, denom, | ||
| 481 | SI5351_PLL_B_MAX, SI5351_PLL_C_MAX, &b, &c); | ||
| 482 | |||
| 483 | /* calculate parameters */ | ||
| 484 | hwdata->params.p3 = c; | ||
| 485 | hwdata->params.p2 = (128 * b) % c; | ||
| 486 | hwdata->params.p1 = 128 * a; | ||
| 487 | hwdata->params.p1 += (128 * b / c); | ||
| 488 | hwdata->params.p1 -= 512; | ||
| 489 | |||
| 490 | /* recalculate rate by fIN * (a + b/c) */ | ||
| 491 | lltmp = *parent_rate; | ||
| 492 | lltmp *= b; | ||
| 493 | do_div(lltmp, c); | ||
| 494 | |||
| 495 | rate = (unsigned long)lltmp; | ||
| 496 | rate += *parent_rate * a; | ||
| 497 | |||
| 498 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 499 | "%s - %s: a = %lu, b = %lu, c = %lu, parent_rate = %lu, rate = %lu\n", | ||
| 500 | __func__, __clk_get_name(hwdata->hw.clk), a, b, c, | ||
| 501 | *parent_rate, rate); | ||
| 502 | |||
| 503 | return rate; | ||
| 504 | } | ||
| 505 | |||
| 506 | static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 507 | unsigned long parent_rate) | ||
| 508 | { | ||
| 509 | struct si5351_hw_data *hwdata = | ||
| 510 | container_of(hw, struct si5351_hw_data, hw); | ||
| 511 | u8 reg = (hwdata->num == 0) ? SI5351_PLLA_PARAMETERS : | ||
| 512 | SI5351_PLLB_PARAMETERS; | ||
| 513 | |||
| 514 | /* write multisynth parameters */ | ||
| 515 | si5351_write_parameters(hwdata->drvdata, reg, &hwdata->params); | ||
| 516 | |||
| 517 | /* plla/pllb ctrl is in clk6/clk7 ctrl registers */ | ||
| 518 | si5351_set_bits(hwdata->drvdata, SI5351_CLK6_CTRL + hwdata->num, | ||
| 519 | SI5351_CLK_INTEGER_MODE, | ||
| 520 | (hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0); | ||
| 521 | |||
| 522 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 523 | "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n", | ||
| 524 | __func__, __clk_get_name(hwdata->hw.clk), | ||
| 525 | hwdata->params.p1, hwdata->params.p2, hwdata->params.p3, | ||
| 526 | parent_rate, rate); | ||
| 527 | |||
| 528 | return 0; | ||
| 529 | } | ||
| 530 | |||
| 531 | static const struct clk_ops si5351_pll_ops = { | ||
| 532 | .set_parent = si5351_pll_set_parent, | ||
| 533 | .get_parent = si5351_pll_get_parent, | ||
| 534 | .recalc_rate = si5351_pll_recalc_rate, | ||
| 535 | .round_rate = si5351_pll_round_rate, | ||
| 536 | .set_rate = si5351_pll_set_rate, | ||
| 537 | }; | ||
| 538 | |||
| 539 | /* | ||
| 540 | * Si5351 multisync divider | ||
| 541 | * | ||
| 542 | * for fOUT <= 150 MHz: | ||
| 543 | * | ||
| 544 | * fOUT = (fIN * (a + b/c)) / CLKOUTDIV | ||
| 545 | * | ||
| 546 | * with 6 + 0/1048575 <= (a + b/c) <= 1800 + 0/1048575 and | ||
| 547 | * fIN = fVCO0, fVCO1 | ||
| 548 | * | ||
| 549 | * Output Clock Multisynth Register Equations | ||
| 550 | * | ||
| 551 | * MSx_P1[17:0] = 128 * a + floor(128 * b/c) - 512 | ||
| 552 | * MSx_P2[19:0] = 128 * b - c * floor(128 * b/c) = (128*b) mod c | ||
| 553 | * MSx_P3[19:0] = c | ||
| 554 | * | ||
| 555 | * MS[6,7] are integer (P1) divide only, P2 = 0, P3 = 0 | ||
| 556 | * | ||
| 557 | * for 150MHz < fOUT <= 160MHz: | ||
| 558 | * | ||
| 559 | * MSx_P1 = 0, MSx_P2 = 0, MSx_P3 = 1, MSx_INT = 1, MSx_DIVBY4 = 11b | ||
| 560 | */ | ||
| 561 | static int _si5351_msynth_reparent(struct si5351_driver_data *drvdata, | ||
| 562 | int num, enum si5351_multisynth_src parent) | ||
| 563 | { | ||
| 564 | if (parent == SI5351_MULTISYNTH_SRC_DEFAULT) | ||
| 565 | return 0; | ||
| 566 | |||
| 567 | if (num > 8) | ||
| 568 | return -EINVAL; | ||
| 569 | |||
| 570 | si5351_set_bits(drvdata, SI5351_CLK0_CTRL + num, SI5351_CLK_PLL_SELECT, | ||
| 571 | (parent == SI5351_MULTISYNTH_SRC_VCO0) ? 0 : | ||
| 572 | SI5351_CLK_PLL_SELECT); | ||
| 573 | return 0; | ||
| 574 | } | ||
| 575 | |||
| 576 | static unsigned char si5351_msynth_get_parent(struct clk_hw *hw) | ||
| 577 | { | ||
| 578 | struct si5351_hw_data *hwdata = | ||
| 579 | container_of(hw, struct si5351_hw_data, hw); | ||
| 580 | u8 val; | ||
| 581 | |||
| 582 | val = si5351_reg_read(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num); | ||
| 583 | |||
| 584 | return (val & SI5351_CLK_PLL_SELECT) ? 1 : 0; | ||
| 585 | } | ||
| 586 | |||
| 587 | static int si5351_msynth_set_parent(struct clk_hw *hw, u8 index) | ||
| 588 | { | ||
| 589 | struct si5351_hw_data *hwdata = | ||
| 590 | container_of(hw, struct si5351_hw_data, hw); | ||
| 591 | |||
| 592 | return _si5351_msynth_reparent(hwdata->drvdata, hwdata->num, | ||
| 593 | (index == 0) ? SI5351_MULTISYNTH_SRC_VCO0 : | ||
| 594 | SI5351_MULTISYNTH_SRC_VCO1); | ||
| 595 | } | ||
| 596 | |||
| 597 | static unsigned long si5351_msynth_recalc_rate(struct clk_hw *hw, | ||
| 598 | unsigned long parent_rate) | ||
| 599 | { | ||
| 600 | struct si5351_hw_data *hwdata = | ||
| 601 | container_of(hw, struct si5351_hw_data, hw); | ||
| 602 | u8 reg = si5351_msynth_params_address(hwdata->num); | ||
| 603 | unsigned long long rate; | ||
| 604 | unsigned long m; | ||
| 605 | |||
| 606 | if (!hwdata->params.valid) | ||
| 607 | si5351_read_parameters(hwdata->drvdata, reg, &hwdata->params); | ||
| 608 | |||
| 609 | if (hwdata->params.p3 == 0) | ||
| 610 | return parent_rate; | ||
| 611 | |||
| 612 | /* | ||
| 613 | * multisync0-5: fOUT = (128 * P3 * fIN) / (P1*P3 + P2 + 512*P3) | ||
| 614 | * multisync6-7: fOUT = fIN / P1 | ||
| 615 | */ | ||
| 616 | rate = parent_rate; | ||
| 617 | if (hwdata->num > 5) { | ||
| 618 | m = hwdata->params.p1; | ||
| 619 | } else if ((si5351_reg_read(hwdata->drvdata, reg + 2) & | ||
| 620 | SI5351_OUTPUT_CLK_DIVBY4) == SI5351_OUTPUT_CLK_DIVBY4) { | ||
| 621 | m = 4; | ||
| 622 | } else { | ||
| 623 | rate *= 128 * hwdata->params.p3; | ||
| 624 | m = hwdata->params.p1 * hwdata->params.p3; | ||
| 625 | m += hwdata->params.p2; | ||
| 626 | m += 512 * hwdata->params.p3; | ||
| 627 | } | ||
| 628 | |||
| 629 | if (m == 0) | ||
| 630 | return 0; | ||
| 631 | do_div(rate, m); | ||
| 632 | |||
| 633 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 634 | "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, m = %lu, parent_rate = %lu, rate = %lu\n", | ||
| 635 | __func__, __clk_get_name(hwdata->hw.clk), | ||
| 636 | hwdata->params.p1, hwdata->params.p2, hwdata->params.p3, | ||
| 637 | m, parent_rate, (unsigned long)rate); | ||
| 638 | |||
| 639 | return (unsigned long)rate; | ||
| 640 | } | ||
| 641 | |||
| 642 | static long si5351_msynth_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 643 | unsigned long *parent_rate) | ||
| 644 | { | ||
| 645 | struct si5351_hw_data *hwdata = | ||
| 646 | container_of(hw, struct si5351_hw_data, hw); | ||
| 647 | unsigned long long lltmp; | ||
| 648 | unsigned long a, b, c; | ||
| 649 | int divby4; | ||
| 650 | |||
| 651 | /* multisync6-7 can only handle freqencies < 150MHz */ | ||
| 652 | if (hwdata->num >= 6 && rate > SI5351_MULTISYNTH67_MAX_FREQ) | ||
| 653 | rate = SI5351_MULTISYNTH67_MAX_FREQ; | ||
| 654 | |||
| 655 | /* multisync frequency is 1MHz .. 160MHz */ | ||
| 656 | if (rate > SI5351_MULTISYNTH_MAX_FREQ) | ||
| 657 | rate = SI5351_MULTISYNTH_MAX_FREQ; | ||
| 658 | if (rate < SI5351_MULTISYNTH_MIN_FREQ) | ||
| 659 | rate = SI5351_MULTISYNTH_MIN_FREQ; | ||
| 660 | |||
| 661 | divby4 = 0; | ||
| 662 | if (rate > SI5351_MULTISYNTH_DIVBY4_FREQ) | ||
| 663 | divby4 = 1; | ||
| 664 | |||
| 665 | /* multisync can set pll */ | ||
| 666 | if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) { | ||
| 667 | /* | ||
| 668 | * find largest integer divider for max | ||
| 669 | * vco frequency and given target rate | ||
| 670 | */ | ||
| 671 | if (divby4 == 0) { | ||
| 672 | lltmp = SI5351_PLL_VCO_MAX; | ||
| 673 | do_div(lltmp, rate); | ||
| 674 | a = (unsigned long)lltmp; | ||
| 675 | } else | ||
| 676 | a = 4; | ||
| 677 | |||
| 678 | b = 0; | ||
| 679 | c = 1; | ||
| 680 | |||
| 681 | *parent_rate = a * rate; | ||
| 682 | } else { | ||
| 683 | unsigned long rfrac, denom; | ||
| 684 | |||
| 685 | /* disable divby4 */ | ||
| 686 | if (divby4) { | ||
| 687 | rate = SI5351_MULTISYNTH_DIVBY4_FREQ; | ||
| 688 | divby4 = 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | /* determine integer part of divider equation */ | ||
| 692 | a = *parent_rate / rate; | ||
| 693 | if (a < SI5351_MULTISYNTH_A_MIN) | ||
| 694 | a = SI5351_MULTISYNTH_A_MIN; | ||
| 695 | if (hwdata->num >= 6 && a > SI5351_MULTISYNTH67_A_MAX) | ||
| 696 | a = SI5351_MULTISYNTH67_A_MAX; | ||
| 697 | else if (a > SI5351_MULTISYNTH_A_MAX) | ||
| 698 | a = SI5351_MULTISYNTH_A_MAX; | ||
| 699 | |||
| 700 | /* find best approximation for b/c = fVCO mod fOUT */ | ||
| 701 | denom = 1000 * 1000; | ||
| 702 | lltmp = (*parent_rate) % rate; | ||
| 703 | lltmp *= denom; | ||
| 704 | do_div(lltmp, rate); | ||
| 705 | rfrac = (unsigned long)lltmp; | ||
| 706 | |||
| 707 | b = 0; | ||
| 708 | c = 1; | ||
| 709 | if (rfrac) | ||
| 710 | rational_best_approximation(rfrac, denom, | ||
| 711 | SI5351_MULTISYNTH_B_MAX, SI5351_MULTISYNTH_C_MAX, | ||
| 712 | &b, &c); | ||
| 713 | } | ||
| 714 | |||
| 715 | /* recalculate rate by fOUT = fIN / (a + b/c) */ | ||
| 716 | lltmp = *parent_rate; | ||
| 717 | lltmp *= c; | ||
| 718 | do_div(lltmp, a * c + b); | ||
| 719 | rate = (unsigned long)lltmp; | ||
| 720 | |||
| 721 | /* calculate parameters */ | ||
| 722 | if (divby4) { | ||
| 723 | hwdata->params.p3 = 1; | ||
| 724 | hwdata->params.p2 = 0; | ||
| 725 | hwdata->params.p1 = 0; | ||
| 726 | } else { | ||
| 727 | hwdata->params.p3 = c; | ||
| 728 | hwdata->params.p2 = (128 * b) % c; | ||
| 729 | hwdata->params.p1 = 128 * a; | ||
| 730 | hwdata->params.p1 += (128 * b / c); | ||
| 731 | hwdata->params.p1 -= 512; | ||
| 732 | } | ||
| 733 | |||
| 734 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 735 | "%s - %s: a = %lu, b = %lu, c = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n", | ||
| 736 | __func__, __clk_get_name(hwdata->hw.clk), a, b, c, divby4, | ||
| 737 | *parent_rate, rate); | ||
| 738 | |||
| 739 | return rate; | ||
| 740 | } | ||
| 741 | |||
| 742 | static int si5351_msynth_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 743 | unsigned long parent_rate) | ||
| 744 | { | ||
| 745 | struct si5351_hw_data *hwdata = | ||
| 746 | container_of(hw, struct si5351_hw_data, hw); | ||
| 747 | u8 reg = si5351_msynth_params_address(hwdata->num); | ||
| 748 | int divby4 = 0; | ||
| 749 | |||
| 750 | /* write multisynth parameters */ | ||
| 751 | si5351_write_parameters(hwdata->drvdata, reg, &hwdata->params); | ||
| 752 | |||
| 753 | if (rate > SI5351_MULTISYNTH_DIVBY4_FREQ) | ||
| 754 | divby4 = 1; | ||
| 755 | |||
| 756 | /* enable/disable integer mode and divby4 on multisynth0-5 */ | ||
| 757 | if (hwdata->num < 6) { | ||
| 758 | si5351_set_bits(hwdata->drvdata, reg + 2, | ||
| 759 | SI5351_OUTPUT_CLK_DIVBY4, | ||
| 760 | (divby4) ? SI5351_OUTPUT_CLK_DIVBY4 : 0); | ||
| 761 | si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, | ||
| 762 | SI5351_CLK_INTEGER_MODE, | ||
| 763 | (hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0); | ||
| 764 | } | ||
| 765 | |||
| 766 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 767 | "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, divby4 = %d, parent_rate = %lu, rate = %lu\n", | ||
| 768 | __func__, __clk_get_name(hwdata->hw.clk), | ||
| 769 | hwdata->params.p1, hwdata->params.p2, hwdata->params.p3, | ||
| 770 | divby4, parent_rate, rate); | ||
| 771 | |||
| 772 | return 0; | ||
| 773 | } | ||
| 774 | |||
| 775 | static const struct clk_ops si5351_msynth_ops = { | ||
| 776 | .set_parent = si5351_msynth_set_parent, | ||
| 777 | .get_parent = si5351_msynth_get_parent, | ||
| 778 | .recalc_rate = si5351_msynth_recalc_rate, | ||
| 779 | .round_rate = si5351_msynth_round_rate, | ||
| 780 | .set_rate = si5351_msynth_set_rate, | ||
| 781 | }; | ||
| 782 | |||
| 783 | /* | ||
| 784 | * Si5351 clkout divider | ||
| 785 | */ | ||
| 786 | static int _si5351_clkout_reparent(struct si5351_driver_data *drvdata, | ||
| 787 | int num, enum si5351_clkout_src parent) | ||
| 788 | { | ||
| 789 | u8 val; | ||
| 790 | |||
| 791 | if (num > 8) | ||
| 792 | return -EINVAL; | ||
| 793 | |||
| 794 | switch (parent) { | ||
| 795 | case SI5351_CLKOUT_SRC_MSYNTH_N: | ||
| 796 | val = SI5351_CLK_INPUT_MULTISYNTH_N; | ||
| 797 | break; | ||
| 798 | case SI5351_CLKOUT_SRC_MSYNTH_0_4: | ||
| 799 | /* clk0/clk4 can only connect to its own multisync */ | ||
| 800 | if (num == 0 || num == 4) | ||
| 801 | val = SI5351_CLK_INPUT_MULTISYNTH_N; | ||
| 802 | else | ||
| 803 | val = SI5351_CLK_INPUT_MULTISYNTH_0_4; | ||
| 804 | break; | ||
| 805 | case SI5351_CLKOUT_SRC_XTAL: | ||
| 806 | val = SI5351_CLK_INPUT_XTAL; | ||
| 807 | break; | ||
| 808 | case SI5351_CLKOUT_SRC_CLKIN: | ||
| 809 | if (drvdata->variant != SI5351_VARIANT_C) | ||
| 810 | return -EINVAL; | ||
| 811 | |||
| 812 | val = SI5351_CLK_INPUT_CLKIN; | ||
| 813 | break; | ||
| 814 | default: | ||
| 815 | return 0; | ||
| 816 | } | ||
| 817 | |||
| 818 | si5351_set_bits(drvdata, SI5351_CLK0_CTRL + num, | ||
| 819 | SI5351_CLK_INPUT_MASK, val); | ||
| 820 | return 0; | ||
| 821 | } | ||
| 822 | |||
| 823 | static int _si5351_clkout_set_drive_strength( | ||
| 824 | struct si5351_driver_data *drvdata, int num, | ||
| 825 | enum si5351_drive_strength drive) | ||
| 826 | { | ||
| 827 | u8 mask; | ||
| 828 | |||
| 829 | if (num > 8) | ||
| 830 | return -EINVAL; | ||
| 831 | |||
| 832 | switch (drive) { | ||
| 833 | case SI5351_DRIVE_2MA: | ||
| 834 | mask = SI5351_CLK_DRIVE_STRENGTH_2MA; | ||
| 835 | break; | ||
| 836 | case SI5351_DRIVE_4MA: | ||
| 837 | mask = SI5351_CLK_DRIVE_STRENGTH_4MA; | ||
| 838 | break; | ||
| 839 | case SI5351_DRIVE_6MA: | ||
| 840 | mask = SI5351_CLK_DRIVE_STRENGTH_6MA; | ||
| 841 | break; | ||
| 842 | case SI5351_DRIVE_8MA: | ||
| 843 | mask = SI5351_CLK_DRIVE_STRENGTH_8MA; | ||
| 844 | break; | ||
| 845 | default: | ||
| 846 | return 0; | ||
| 847 | } | ||
| 848 | |||
| 849 | si5351_set_bits(drvdata, SI5351_CLK0_CTRL + num, | ||
| 850 | SI5351_CLK_DRIVE_STRENGTH_MASK, mask); | ||
| 851 | return 0; | ||
| 852 | } | ||
| 853 | |||
| 854 | static int si5351_clkout_prepare(struct clk_hw *hw) | ||
| 855 | { | ||
| 856 | struct si5351_hw_data *hwdata = | ||
| 857 | container_of(hw, struct si5351_hw_data, hw); | ||
| 858 | |||
| 859 | si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, | ||
| 860 | SI5351_CLK_POWERDOWN, 0); | ||
| 861 | si5351_set_bits(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL, | ||
| 862 | (1 << hwdata->num), 0); | ||
| 863 | return 0; | ||
| 864 | } | ||
| 865 | |||
| 866 | static void si5351_clkout_unprepare(struct clk_hw *hw) | ||
| 867 | { | ||
| 868 | struct si5351_hw_data *hwdata = | ||
| 869 | container_of(hw, struct si5351_hw_data, hw); | ||
| 870 | |||
| 871 | si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, | ||
| 872 | SI5351_CLK_POWERDOWN, SI5351_CLK_POWERDOWN); | ||
| 873 | si5351_set_bits(hwdata->drvdata, SI5351_OUTPUT_ENABLE_CTRL, | ||
| 874 | (1 << hwdata->num), (1 << hwdata->num)); | ||
| 875 | } | ||
| 876 | |||
| 877 | static u8 si5351_clkout_get_parent(struct clk_hw *hw) | ||
| 878 | { | ||
| 879 | struct si5351_hw_data *hwdata = | ||
| 880 | container_of(hw, struct si5351_hw_data, hw); | ||
| 881 | int index = 0; | ||
| 882 | unsigned char val; | ||
| 883 | |||
| 884 | val = si5351_reg_read(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num); | ||
| 885 | switch (val & SI5351_CLK_INPUT_MASK) { | ||
| 886 | case SI5351_CLK_INPUT_MULTISYNTH_N: | ||
| 887 | index = 0; | ||
| 888 | break; | ||
| 889 | case SI5351_CLK_INPUT_MULTISYNTH_0_4: | ||
| 890 | index = 1; | ||
| 891 | break; | ||
| 892 | case SI5351_CLK_INPUT_XTAL: | ||
| 893 | index = 2; | ||
| 894 | break; | ||
| 895 | case SI5351_CLK_INPUT_CLKIN: | ||
| 896 | index = 3; | ||
| 897 | break; | ||
| 898 | } | ||
| 899 | |||
| 900 | return index; | ||
| 901 | } | ||
| 902 | |||
| 903 | static int si5351_clkout_set_parent(struct clk_hw *hw, u8 index) | ||
| 904 | { | ||
| 905 | struct si5351_hw_data *hwdata = | ||
| 906 | container_of(hw, struct si5351_hw_data, hw); | ||
| 907 | enum si5351_clkout_src parent = SI5351_CLKOUT_SRC_DEFAULT; | ||
| 908 | |||
| 909 | switch (index) { | ||
| 910 | case 0: | ||
| 911 | parent = SI5351_CLKOUT_SRC_MSYNTH_N; | ||
| 912 | break; | ||
| 913 | case 1: | ||
| 914 | parent = SI5351_CLKOUT_SRC_MSYNTH_0_4; | ||
| 915 | break; | ||
| 916 | case 2: | ||
| 917 | parent = SI5351_CLKOUT_SRC_XTAL; | ||
| 918 | break; | ||
| 919 | case 3: | ||
| 920 | parent = SI5351_CLKOUT_SRC_CLKIN; | ||
| 921 | break; | ||
| 922 | } | ||
| 923 | |||
| 924 | return _si5351_clkout_reparent(hwdata->drvdata, hwdata->num, parent); | ||
| 925 | } | ||
| 926 | |||
| 927 | static unsigned long si5351_clkout_recalc_rate(struct clk_hw *hw, | ||
| 928 | unsigned long parent_rate) | ||
| 929 | { | ||
| 930 | struct si5351_hw_data *hwdata = | ||
| 931 | container_of(hw, struct si5351_hw_data, hw); | ||
| 932 | unsigned char reg; | ||
| 933 | unsigned char rdiv; | ||
| 934 | |||
| 935 | if (hwdata->num > 5) | ||
| 936 | reg = si5351_msynth_params_address(hwdata->num) + 2; | ||
| 937 | else | ||
| 938 | reg = SI5351_CLK6_7_OUTPUT_DIVIDER; | ||
| 939 | |||
| 940 | rdiv = si5351_reg_read(hwdata->drvdata, reg); | ||
| 941 | if (hwdata->num == 6) { | ||
| 942 | rdiv &= SI5351_OUTPUT_CLK6_DIV_MASK; | ||
| 943 | } else { | ||
| 944 | rdiv &= SI5351_OUTPUT_CLK_DIV_MASK; | ||
| 945 | rdiv >>= SI5351_OUTPUT_CLK_DIV_SHIFT; | ||
| 946 | } | ||
| 947 | |||
| 948 | return parent_rate >> rdiv; | ||
| 949 | } | ||
| 950 | |||
| 951 | static long si5351_clkout_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 952 | unsigned long *parent_rate) | ||
| 953 | { | ||
| 954 | struct si5351_hw_data *hwdata = | ||
| 955 | container_of(hw, struct si5351_hw_data, hw); | ||
| 956 | unsigned char rdiv; | ||
| 957 | |||
| 958 | /* clkout6/7 can only handle output freqencies < 150MHz */ | ||
| 959 | if (hwdata->num >= 6 && rate > SI5351_CLKOUT67_MAX_FREQ) | ||
| 960 | rate = SI5351_CLKOUT67_MAX_FREQ; | ||
| 961 | |||
| 962 | /* clkout freqency is 8kHz - 160MHz */ | ||
| 963 | if (rate > SI5351_CLKOUT_MAX_FREQ) | ||
| 964 | rate = SI5351_CLKOUT_MAX_FREQ; | ||
| 965 | if (rate < SI5351_CLKOUT_MIN_FREQ) | ||
| 966 | rate = SI5351_CLKOUT_MIN_FREQ; | ||
| 967 | |||
| 968 | /* request frequency if multisync master */ | ||
| 969 | if (__clk_get_flags(hwdata->hw.clk) & CLK_SET_RATE_PARENT) { | ||
| 970 | /* use r divider for frequencies below 1MHz */ | ||
| 971 | rdiv = SI5351_OUTPUT_CLK_DIV_1; | ||
| 972 | while (rate < SI5351_MULTISYNTH_MIN_FREQ && | ||
| 973 | rdiv < SI5351_OUTPUT_CLK_DIV_128) { | ||
| 974 | rdiv += 1; | ||
| 975 | rate *= 2; | ||
| 976 | } | ||
| 977 | *parent_rate = rate; | ||
| 978 | } else { | ||
| 979 | unsigned long new_rate, new_err, err; | ||
| 980 | |||
| 981 | /* round to closed rdiv */ | ||
| 982 | rdiv = SI5351_OUTPUT_CLK_DIV_1; | ||
| 983 | new_rate = *parent_rate; | ||
| 984 | err = abs(new_rate - rate); | ||
| 985 | do { | ||
| 986 | new_rate >>= 1; | ||
| 987 | new_err = abs(new_rate - rate); | ||
| 988 | if (new_err > err || rdiv == SI5351_OUTPUT_CLK_DIV_128) | ||
| 989 | break; | ||
| 990 | rdiv++; | ||
| 991 | err = new_err; | ||
| 992 | } while (1); | ||
| 993 | } | ||
| 994 | rate = *parent_rate >> rdiv; | ||
| 995 | |||
| 996 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 997 | "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", | ||
| 998 | __func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv), | ||
| 999 | *parent_rate, rate); | ||
| 1000 | |||
| 1001 | return rate; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 1005 | unsigned long parent_rate) | ||
| 1006 | { | ||
| 1007 | struct si5351_hw_data *hwdata = | ||
| 1008 | container_of(hw, struct si5351_hw_data, hw); | ||
| 1009 | unsigned long new_rate, new_err, err; | ||
| 1010 | unsigned char rdiv; | ||
| 1011 | |||
| 1012 | /* round to closed rdiv */ | ||
| 1013 | rdiv = SI5351_OUTPUT_CLK_DIV_1; | ||
| 1014 | new_rate = parent_rate; | ||
| 1015 | err = abs(new_rate - rate); | ||
| 1016 | do { | ||
| 1017 | new_rate >>= 1; | ||
| 1018 | new_err = abs(new_rate - rate); | ||
| 1019 | if (new_err > err || rdiv == SI5351_OUTPUT_CLK_DIV_128) | ||
| 1020 | break; | ||
| 1021 | rdiv++; | ||
| 1022 | err = new_err; | ||
| 1023 | } while (1); | ||
| 1024 | |||
| 1025 | /* write output divider */ | ||
| 1026 | switch (hwdata->num) { | ||
| 1027 | case 6: | ||
| 1028 | si5351_set_bits(hwdata->drvdata, SI5351_CLK6_7_OUTPUT_DIVIDER, | ||
| 1029 | SI5351_OUTPUT_CLK6_DIV_MASK, rdiv); | ||
| 1030 | break; | ||
| 1031 | case 7: | ||
| 1032 | si5351_set_bits(hwdata->drvdata, SI5351_CLK6_7_OUTPUT_DIVIDER, | ||
| 1033 | SI5351_OUTPUT_CLK_DIV_MASK, | ||
| 1034 | rdiv << SI5351_OUTPUT_CLK_DIV_SHIFT); | ||
| 1035 | break; | ||
| 1036 | default: | ||
| 1037 | si5351_set_bits(hwdata->drvdata, | ||
| 1038 | si5351_msynth_params_address(hwdata->num) + 2, | ||
| 1039 | SI5351_OUTPUT_CLK_DIV_MASK, | ||
| 1040 | rdiv << SI5351_OUTPUT_CLK_DIV_SHIFT); | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | /* powerup clkout */ | ||
| 1044 | si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, | ||
| 1045 | SI5351_CLK_POWERDOWN, 0); | ||
| 1046 | |||
| 1047 | dev_dbg(&hwdata->drvdata->client->dev, | ||
| 1048 | "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", | ||
| 1049 | __func__, __clk_get_name(hwdata->hw.clk), (1 << rdiv), | ||
| 1050 | parent_rate, rate); | ||
| 1051 | |||
| 1052 | return 0; | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | static const struct clk_ops si5351_clkout_ops = { | ||
| 1056 | .prepare = si5351_clkout_prepare, | ||
| 1057 | .unprepare = si5351_clkout_unprepare, | ||
| 1058 | .set_parent = si5351_clkout_set_parent, | ||
| 1059 | .get_parent = si5351_clkout_get_parent, | ||
| 1060 | .recalc_rate = si5351_clkout_recalc_rate, | ||
| 1061 | .round_rate = si5351_clkout_round_rate, | ||
| 1062 | .set_rate = si5351_clkout_set_rate, | ||
| 1063 | }; | ||
| 1064 | |||
| 1065 | /* | ||
| 1066 | * Si5351 i2c probe and DT | ||
| 1067 | */ | ||
| 1068 | #ifdef CONFIG_OF | ||
| 1069 | static const struct of_device_id si5351_dt_ids[] = { | ||
| 1070 | { .compatible = "silabs,si5351a", .data = (void *)SI5351_VARIANT_A, }, | ||
| 1071 | { .compatible = "silabs,si5351a-msop", | ||
| 1072 | .data = (void *)SI5351_VARIANT_A3, }, | ||
| 1073 | { .compatible = "silabs,si5351b", .data = (void *)SI5351_VARIANT_B, }, | ||
| 1074 | { .compatible = "silabs,si5351c", .data = (void *)SI5351_VARIANT_C, }, | ||
| 1075 | { } | ||
| 1076 | }; | ||
| 1077 | MODULE_DEVICE_TABLE(of, si5351_dt_ids); | ||
| 1078 | |||
| 1079 | static int si5351_dt_parse(struct i2c_client *client) | ||
| 1080 | { | ||
| 1081 | struct device_node *child, *np = client->dev.of_node; | ||
| 1082 | struct si5351_platform_data *pdata; | ||
| 1083 | const struct of_device_id *match; | ||
| 1084 | struct property *prop; | ||
| 1085 | const __be32 *p; | ||
| 1086 | int num = 0; | ||
| 1087 | u32 val; | ||
| 1088 | |||
| 1089 | if (np == NULL) | ||
| 1090 | return 0; | ||
| 1091 | |||
| 1092 | match = of_match_node(si5351_dt_ids, np); | ||
| 1093 | if (match == NULL) | ||
| 1094 | return -EINVAL; | ||
| 1095 | |||
| 1096 | pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 1097 | if (!pdata) | ||
| 1098 | return -ENOMEM; | ||
| 1099 | |||
| 1100 | pdata->variant = (enum si5351_variant)match->data; | ||
| 1101 | pdata->clk_xtal = of_clk_get(np, 0); | ||
| 1102 | if (!IS_ERR(pdata->clk_xtal)) | ||
| 1103 | clk_put(pdata->clk_xtal); | ||
| 1104 | pdata->clk_clkin = of_clk_get(np, 1); | ||
| 1105 | if (!IS_ERR(pdata->clk_clkin)) | ||
| 1106 | clk_put(pdata->clk_clkin); | ||
| 1107 | |||
| 1108 | /* | ||
| 1109 | * property silabs,pll-source : <num src>, [<..>] | ||
| 1110 | * allow to selectively set pll source | ||
| 1111 | */ | ||
| 1112 | of_property_for_each_u32(np, "silabs,pll-source", prop, p, num) { | ||
| 1113 | if (num >= 2) { | ||
| 1114 | dev_err(&client->dev, | ||
| 1115 | "invalid pll %d on pll-source prop\n", num); | ||
| 1116 | return -EINVAL; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | p = of_prop_next_u32(prop, p, &val); | ||
| 1120 | if (!p) { | ||
| 1121 | dev_err(&client->dev, | ||
| 1122 | "missing pll-source for pll %d\n", num); | ||
| 1123 | return -EINVAL; | ||
| 1124 | } | ||
| 1125 | |||
| 1126 | switch (val) { | ||
| 1127 | case 0: | ||
| 1128 | pdata->pll_src[num] = SI5351_PLL_SRC_XTAL; | ||
| 1129 | break; | ||
| 1130 | case 1: | ||
| 1131 | if (pdata->variant != SI5351_VARIANT_C) { | ||
| 1132 | dev_err(&client->dev, | ||
| 1133 | "invalid parent %d for pll %d\n", | ||
| 1134 | val, num); | ||
| 1135 | return -EINVAL; | ||
| 1136 | } | ||
| 1137 | pdata->pll_src[num] = SI5351_PLL_SRC_CLKIN; | ||
| 1138 | break; | ||
| 1139 | default: | ||
| 1140 | dev_err(&client->dev, | ||
| 1141 | "invalid parent %d for pll %d\n", val, num); | ||
| 1142 | return -EINVAL; | ||
| 1143 | } | ||
| 1144 | } | ||
| 1145 | |||
| 1146 | /* per clkout properties */ | ||
| 1147 | for_each_child_of_node(np, child) { | ||
| 1148 | if (of_property_read_u32(child, "reg", &num)) { | ||
| 1149 | dev_err(&client->dev, "missing reg property of %s\n", | ||
| 1150 | child->name); | ||
| 1151 | return -EINVAL; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | if (num >= 8 || | ||
| 1155 | (pdata->variant == SI5351_VARIANT_A3 && num >= 3)) { | ||
| 1156 | dev_err(&client->dev, "invalid clkout %d\n", num); | ||
| 1157 | return -EINVAL; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | if (!of_property_read_u32(child, "silabs,multisynth-source", | ||
| 1161 | &val)) { | ||
| 1162 | switch (val) { | ||
| 1163 | case 0: | ||
| 1164 | pdata->clkout[num].multisynth_src = | ||
| 1165 | SI5351_MULTISYNTH_SRC_VCO0; | ||
| 1166 | break; | ||
| 1167 | case 1: | ||
| 1168 | pdata->clkout[num].multisynth_src = | ||
| 1169 | SI5351_MULTISYNTH_SRC_VCO1; | ||
| 1170 | break; | ||
| 1171 | default: | ||
| 1172 | dev_err(&client->dev, | ||
| 1173 | "invalid parent %d for multisynth %d\n", | ||
| 1174 | val, num); | ||
| 1175 | return -EINVAL; | ||
| 1176 | } | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | if (!of_property_read_u32(child, "silabs,clock-source", &val)) { | ||
| 1180 | switch (val) { | ||
| 1181 | case 0: | ||
| 1182 | pdata->clkout[num].clkout_src = | ||
| 1183 | SI5351_CLKOUT_SRC_MSYNTH_N; | ||
| 1184 | break; | ||
| 1185 | case 1: | ||
| 1186 | pdata->clkout[num].clkout_src = | ||
| 1187 | SI5351_CLKOUT_SRC_MSYNTH_0_4; | ||
| 1188 | break; | ||
| 1189 | case 2: | ||
| 1190 | pdata->clkout[num].clkout_src = | ||
| 1191 | SI5351_CLKOUT_SRC_XTAL; | ||
| 1192 | break; | ||
| 1193 | case 3: | ||
| 1194 | if (pdata->variant != SI5351_VARIANT_C) { | ||
| 1195 | dev_err(&client->dev, | ||
| 1196 | "invalid parent %d for clkout %d\n", | ||
| 1197 | val, num); | ||
| 1198 | return -EINVAL; | ||
| 1199 | } | ||
| 1200 | pdata->clkout[num].clkout_src = | ||
| 1201 | SI5351_CLKOUT_SRC_CLKIN; | ||
| 1202 | break; | ||
| 1203 | default: | ||
| 1204 | dev_err(&client->dev, | ||
| 1205 | "invalid parent %d for clkout %d\n", | ||
| 1206 | val, num); | ||
| 1207 | return -EINVAL; | ||
| 1208 | } | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | if (!of_property_read_u32(child, "silabs,drive-strength", | ||
| 1212 | &val)) { | ||
| 1213 | switch (val) { | ||
| 1214 | case SI5351_DRIVE_2MA: | ||
| 1215 | case SI5351_DRIVE_4MA: | ||
| 1216 | case SI5351_DRIVE_6MA: | ||
| 1217 | case SI5351_DRIVE_8MA: | ||
| 1218 | pdata->clkout[num].drive = val; | ||
| 1219 | break; | ||
| 1220 | default: | ||
| 1221 | dev_err(&client->dev, | ||
| 1222 | "invalid drive strength %d for clkout %d\n", | ||
| 1223 | val, num); | ||
| 1224 | return -EINVAL; | ||
| 1225 | } | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | if (!of_property_read_u32(child, "clock-frequency", &val)) | ||
| 1229 | pdata->clkout[num].rate = val; | ||
| 1230 | |||
| 1231 | pdata->clkout[num].pll_master = | ||
| 1232 | of_property_read_bool(child, "silabs,pll-master"); | ||
| 1233 | } | ||
| 1234 | client->dev.platform_data = pdata; | ||
| 1235 | |||
| 1236 | return 0; | ||
| 1237 | } | ||
| 1238 | #else | ||
| 1239 | static int si5351_dt_parse(struct i2c_client *client) | ||
| 1240 | { | ||
| 1241 | return 0; | ||
| 1242 | } | ||
| 1243 | #endif /* CONFIG_OF */ | ||
| 1244 | |||
| 1245 | static int si5351_i2c_probe(struct i2c_client *client, | ||
| 1246 | const struct i2c_device_id *id) | ||
| 1247 | { | ||
| 1248 | struct si5351_platform_data *pdata; | ||
| 1249 | struct si5351_driver_data *drvdata; | ||
| 1250 | struct clk_init_data init; | ||
| 1251 | struct clk *clk; | ||
| 1252 | const char *parent_names[4]; | ||
| 1253 | u8 num_parents, num_clocks; | ||
| 1254 | int ret, n; | ||
| 1255 | |||
| 1256 | ret = si5351_dt_parse(client); | ||
| 1257 | if (ret) | ||
| 1258 | return ret; | ||
| 1259 | |||
| 1260 | pdata = client->dev.platform_data; | ||
| 1261 | if (!pdata) | ||
| 1262 | return -EINVAL; | ||
| 1263 | |||
| 1264 | drvdata = devm_kzalloc(&client->dev, sizeof(*drvdata), GFP_KERNEL); | ||
| 1265 | if (drvdata == NULL) { | ||
| 1266 | dev_err(&client->dev, "unable to allocate driver data\n"); | ||
| 1267 | return -ENOMEM; | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | i2c_set_clientdata(client, drvdata); | ||
| 1271 | drvdata->client = client; | ||
| 1272 | drvdata->variant = pdata->variant; | ||
| 1273 | drvdata->pxtal = pdata->clk_xtal; | ||
| 1274 | drvdata->pclkin = pdata->clk_clkin; | ||
| 1275 | |||
| 1276 | drvdata->regmap = devm_regmap_init_i2c(client, &si5351_regmap_config); | ||
| 1277 | if (IS_ERR(drvdata->regmap)) { | ||
| 1278 | dev_err(&client->dev, "failed to allocate register map\n"); | ||
| 1279 | return PTR_ERR(drvdata->regmap); | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | /* Disable interrupts */ | ||
| 1283 | si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0); | ||
| 1284 | /* Set disabled output drivers to drive low */ | ||
| 1285 | si5351_reg_write(drvdata, SI5351_CLK3_0_DISABLE_STATE, 0x00); | ||
| 1286 | si5351_reg_write(drvdata, SI5351_CLK7_4_DISABLE_STATE, 0x00); | ||
| 1287 | /* Ensure pll select is on XTAL for Si5351A/B */ | ||
| 1288 | if (drvdata->variant != SI5351_VARIANT_C) | ||
| 1289 | si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE, | ||
| 1290 | SI5351_PLLA_SOURCE | SI5351_PLLB_SOURCE, 0); | ||
| 1291 | |||
| 1292 | /* setup clock configuration */ | ||
| 1293 | for (n = 0; n < 2; n++) { | ||
| 1294 | ret = _si5351_pll_reparent(drvdata, n, pdata->pll_src[n]); | ||
| 1295 | if (ret) { | ||
| 1296 | dev_err(&client->dev, | ||
| 1297 | "failed to reparent pll %d to %d\n", | ||
| 1298 | n, pdata->pll_src[n]); | ||
| 1299 | return ret; | ||
| 1300 | } | ||
| 1301 | } | ||
| 1302 | |||
| 1303 | for (n = 0; n < 8; n++) { | ||
| 1304 | ret = _si5351_msynth_reparent(drvdata, n, | ||
| 1305 | pdata->clkout[n].multisynth_src); | ||
| 1306 | if (ret) { | ||
| 1307 | dev_err(&client->dev, | ||
| 1308 | "failed to reparent multisynth %d to %d\n", | ||
| 1309 | n, pdata->clkout[n].multisynth_src); | ||
| 1310 | return ret; | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | ret = _si5351_clkout_reparent(drvdata, n, | ||
| 1314 | pdata->clkout[n].clkout_src); | ||
| 1315 | if (ret) { | ||
| 1316 | dev_err(&client->dev, | ||
| 1317 | "failed to reparent clkout %d to %d\n", | ||
| 1318 | n, pdata->clkout[n].clkout_src); | ||
| 1319 | return ret; | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | ret = _si5351_clkout_set_drive_strength(drvdata, n, | ||
| 1323 | pdata->clkout[n].drive); | ||
| 1324 | if (ret) { | ||
| 1325 | dev_err(&client->dev, | ||
| 1326 | "failed set drive strength of clkout%d to %d\n", | ||
| 1327 | n, pdata->clkout[n].drive); | ||
| 1328 | return ret; | ||
| 1329 | } | ||
| 1330 | } | ||
| 1331 | |||
| 1332 | /* register xtal input clock gate */ | ||
| 1333 | memset(&init, 0, sizeof(init)); | ||
| 1334 | init.name = si5351_input_names[0]; | ||
| 1335 | init.ops = &si5351_xtal_ops; | ||
| 1336 | init.flags = 0; | ||
| 1337 | if (!IS_ERR(drvdata->pxtal)) { | ||
| 1338 | drvdata->pxtal_name = __clk_get_name(drvdata->pxtal); | ||
| 1339 | init.parent_names = &drvdata->pxtal_name; | ||
| 1340 | init.num_parents = 1; | ||
| 1341 | } | ||
| 1342 | drvdata->xtal.init = &init; | ||
| 1343 | clk = devm_clk_register(&client->dev, &drvdata->xtal); | ||
| 1344 | if (IS_ERR(clk)) { | ||
| 1345 | dev_err(&client->dev, "unable to register %s\n", init.name); | ||
| 1346 | return PTR_ERR(clk); | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | /* register clkin input clock gate */ | ||
| 1350 | if (drvdata->variant == SI5351_VARIANT_C) { | ||
| 1351 | memset(&init, 0, sizeof(init)); | ||
| 1352 | init.name = si5351_input_names[1]; | ||
| 1353 | init.ops = &si5351_clkin_ops; | ||
| 1354 | if (!IS_ERR(drvdata->pclkin)) { | ||
| 1355 | drvdata->pclkin_name = __clk_get_name(drvdata->pclkin); | ||
| 1356 | init.parent_names = &drvdata->pclkin_name; | ||
| 1357 | init.num_parents = 1; | ||
| 1358 | } | ||
| 1359 | drvdata->clkin.init = &init; | ||
| 1360 | clk = devm_clk_register(&client->dev, &drvdata->clkin); | ||
| 1361 | if (IS_ERR(clk)) { | ||
| 1362 | dev_err(&client->dev, "unable to register %s\n", | ||
| 1363 | init.name); | ||
| 1364 | return PTR_ERR(clk); | ||
| 1365 | } | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | /* Si5351C allows to mux either xtal or clkin to PLL input */ | ||
| 1369 | num_parents = (drvdata->variant == SI5351_VARIANT_C) ? 2 : 1; | ||
| 1370 | parent_names[0] = si5351_input_names[0]; | ||
| 1371 | parent_names[1] = si5351_input_names[1]; | ||
| 1372 | |||
| 1373 | /* register PLLA */ | ||
| 1374 | drvdata->pll[0].num = 0; | ||
| 1375 | drvdata->pll[0].drvdata = drvdata; | ||
| 1376 | drvdata->pll[0].hw.init = &init; | ||
| 1377 | memset(&init, 0, sizeof(init)); | ||
| 1378 | init.name = si5351_pll_names[0]; | ||
| 1379 | init.ops = &si5351_pll_ops; | ||
| 1380 | init.flags = 0; | ||
| 1381 | init.parent_names = parent_names; | ||
| 1382 | init.num_parents = num_parents; | ||
| 1383 | clk = devm_clk_register(&client->dev, &drvdata->pll[0].hw); | ||
| 1384 | if (IS_ERR(clk)) { | ||
| 1385 | dev_err(&client->dev, "unable to register %s\n", init.name); | ||
| 1386 | return -EINVAL; | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | /* register PLLB or VXCO (Si5351B) */ | ||
| 1390 | drvdata->pll[1].num = 1; | ||
| 1391 | drvdata->pll[1].drvdata = drvdata; | ||
| 1392 | drvdata->pll[1].hw.init = &init; | ||
| 1393 | memset(&init, 0, sizeof(init)); | ||
| 1394 | if (drvdata->variant == SI5351_VARIANT_B) { | ||
| 1395 | init.name = si5351_pll_names[2]; | ||
| 1396 | init.ops = &si5351_vxco_ops; | ||
| 1397 | init.flags = CLK_IS_ROOT; | ||
| 1398 | init.parent_names = NULL; | ||
| 1399 | init.num_parents = 0; | ||
| 1400 | } else { | ||
| 1401 | init.name = si5351_pll_names[1]; | ||
| 1402 | init.ops = &si5351_pll_ops; | ||
| 1403 | init.flags = 0; | ||
| 1404 | init.parent_names = parent_names; | ||
| 1405 | init.num_parents = num_parents; | ||
| 1406 | } | ||
| 1407 | clk = devm_clk_register(&client->dev, &drvdata->pll[1].hw); | ||
| 1408 | if (IS_ERR(clk)) { | ||
| 1409 | dev_err(&client->dev, "unable to register %s\n", init.name); | ||
| 1410 | return -EINVAL; | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | /* register clk multisync and clk out divider */ | ||
| 1414 | num_clocks = (drvdata->variant == SI5351_VARIANT_A3) ? 3 : 8; | ||
| 1415 | parent_names[0] = si5351_pll_names[0]; | ||
| 1416 | if (drvdata->variant == SI5351_VARIANT_B) | ||
| 1417 | parent_names[1] = si5351_pll_names[2]; | ||
| 1418 | else | ||
| 1419 | parent_names[1] = si5351_pll_names[1]; | ||
| 1420 | |||
| 1421 | drvdata->msynth = devm_kzalloc(&client->dev, num_clocks * | ||
| 1422 | sizeof(*drvdata->msynth), GFP_KERNEL); | ||
| 1423 | drvdata->clkout = devm_kzalloc(&client->dev, num_clocks * | ||
| 1424 | sizeof(*drvdata->clkout), GFP_KERNEL); | ||
| 1425 | |||
| 1426 | drvdata->onecell.clk_num = num_clocks; | ||
| 1427 | drvdata->onecell.clks = devm_kzalloc(&client->dev, | ||
| 1428 | num_clocks * sizeof(*drvdata->onecell.clks), GFP_KERNEL); | ||
| 1429 | |||
| 1430 | if (WARN_ON(!drvdata->msynth || !drvdata->clkout || | ||
| 1431 | !drvdata->onecell.clks)) | ||
| 1432 | return -ENOMEM; | ||
| 1433 | |||
| 1434 | for (n = 0; n < num_clocks; n++) { | ||
| 1435 | drvdata->msynth[n].num = n; | ||
| 1436 | drvdata->msynth[n].drvdata = drvdata; | ||
| 1437 | drvdata->msynth[n].hw.init = &init; | ||
| 1438 | memset(&init, 0, sizeof(init)); | ||
| 1439 | init.name = si5351_msynth_names[n]; | ||
| 1440 | init.ops = &si5351_msynth_ops; | ||
| 1441 | init.flags = 0; | ||
| 1442 | if (pdata->clkout[n].pll_master) | ||
| 1443 | init.flags |= CLK_SET_RATE_PARENT; | ||
| 1444 | init.parent_names = parent_names; | ||
| 1445 | init.num_parents = 2; | ||
| 1446 | clk = devm_clk_register(&client->dev, &drvdata->msynth[n].hw); | ||
| 1447 | if (IS_ERR(clk)) { | ||
| 1448 | dev_err(&client->dev, "unable to register %s\n", | ||
| 1449 | init.name); | ||
| 1450 | return -EINVAL; | ||
| 1451 | } | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | num_parents = (drvdata->variant == SI5351_VARIANT_C) ? 4 : 3; | ||
| 1455 | parent_names[2] = si5351_input_names[0]; | ||
| 1456 | parent_names[3] = si5351_input_names[1]; | ||
| 1457 | for (n = 0; n < num_clocks; n++) { | ||
| 1458 | parent_names[0] = si5351_msynth_names[n]; | ||
| 1459 | parent_names[1] = (n < 4) ? si5351_msynth_names[0] : | ||
| 1460 | si5351_msynth_names[4]; | ||
| 1461 | |||
| 1462 | drvdata->clkout[n].num = n; | ||
| 1463 | drvdata->clkout[n].drvdata = drvdata; | ||
| 1464 | drvdata->clkout[n].hw.init = &init; | ||
| 1465 | memset(&init, 0, sizeof(init)); | ||
| 1466 | init.name = si5351_clkout_names[n]; | ||
| 1467 | init.ops = &si5351_clkout_ops; | ||
| 1468 | init.flags = 0; | ||
| 1469 | if (pdata->clkout[n].clkout_src == SI5351_CLKOUT_SRC_MSYNTH_N) | ||
| 1470 | init.flags |= CLK_SET_RATE_PARENT; | ||
| 1471 | init.parent_names = parent_names; | ||
| 1472 | init.num_parents = num_parents; | ||
| 1473 | clk = devm_clk_register(&client->dev, &drvdata->clkout[n].hw); | ||
| 1474 | if (IS_ERR(clk)) { | ||
| 1475 | dev_err(&client->dev, "unable to register %s\n", | ||
| 1476 | init.name); | ||
| 1477 | return -EINVAL; | ||
| 1478 | } | ||
| 1479 | drvdata->onecell.clks[n] = clk; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | ret = of_clk_add_provider(client->dev.of_node, of_clk_src_onecell_get, | ||
| 1483 | &drvdata->onecell); | ||
| 1484 | if (ret) { | ||
| 1485 | dev_err(&client->dev, "unable to add clk provider\n"); | ||
| 1486 | return ret; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | return 0; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | static const struct i2c_device_id si5351_i2c_ids[] = { | ||
| 1493 | { "silabs,si5351", 0 }, | ||
| 1494 | { } | ||
| 1495 | }; | ||
| 1496 | MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids); | ||
| 1497 | |||
| 1498 | static struct i2c_driver si5351_driver = { | ||
| 1499 | .driver = { | ||
| 1500 | .name = "si5351", | ||
| 1501 | .of_match_table = of_match_ptr(si5351_dt_ids), | ||
| 1502 | }, | ||
| 1503 | .probe = si5351_i2c_probe, | ||
| 1504 | .id_table = si5351_i2c_ids, | ||
| 1505 | }; | ||
| 1506 | module_i2c_driver(si5351_driver); | ||
| 1507 | |||
| 1508 | MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com"); | ||
| 1509 | MODULE_DESCRIPTION("Silicon Labs Si5351A/B/C clock generator driver"); | ||
| 1510 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/clk/clk-si5351.h b/drivers/clk/clk-si5351.h new file mode 100644 index 000000000000..af41b5080f43 --- /dev/null +++ b/drivers/clk/clk-si5351.h | |||
| @@ -0,0 +1,155 @@ | |||
| 1 | /* | ||
| 2 | * clk-si5351.h: Silicon Laboratories Si5351A/B/C I2C Clock Generator | ||
| 3 | * | ||
| 4 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
| 5 | * Rabeeh Khoury <rabeeh@solid-run.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify it | ||
| 8 | * under the terms of the GNU General Public License as published by the | ||
| 9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 10 | * option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef _CLK_SI5351_H_ | ||
| 14 | #define _CLK_SI5351_H_ | ||
| 15 | |||
| 16 | #define SI5351_BUS_BASE_ADDR 0x60 | ||
| 17 | |||
| 18 | #define SI5351_PLL_VCO_MIN 600000000 | ||
| 19 | #define SI5351_PLL_VCO_MAX 900000000 | ||
| 20 | #define SI5351_MULTISYNTH_MIN_FREQ 1000000 | ||
| 21 | #define SI5351_MULTISYNTH_DIVBY4_FREQ 150000000 | ||
| 22 | #define SI5351_MULTISYNTH_MAX_FREQ 160000000 | ||
| 23 | #define SI5351_MULTISYNTH67_MAX_FREQ SI5351_MULTISYNTH_DIVBY4_FREQ | ||
| 24 | #define SI5351_CLKOUT_MIN_FREQ 8000 | ||
| 25 | #define SI5351_CLKOUT_MAX_FREQ SI5351_MULTISYNTH_MAX_FREQ | ||
| 26 | #define SI5351_CLKOUT67_MAX_FREQ SI5351_MULTISYNTH67_MAX_FREQ | ||
| 27 | |||
| 28 | #define SI5351_PLL_A_MIN 15 | ||
| 29 | #define SI5351_PLL_A_MAX 90 | ||
| 30 | #define SI5351_PLL_B_MAX (SI5351_PLL_C_MAX-1) | ||
| 31 | #define SI5351_PLL_C_MAX 1048575 | ||
| 32 | #define SI5351_MULTISYNTH_A_MIN 6 | ||
| 33 | #define SI5351_MULTISYNTH_A_MAX 1800 | ||
| 34 | #define SI5351_MULTISYNTH67_A_MAX 254 | ||
| 35 | #define SI5351_MULTISYNTH_B_MAX (SI5351_MULTISYNTH_C_MAX-1) | ||
| 36 | #define SI5351_MULTISYNTH_C_MAX 1048575 | ||
| 37 | #define SI5351_MULTISYNTH_P1_MAX ((1<<18)-1) | ||
| 38 | #define SI5351_MULTISYNTH_P2_MAX ((1<<20)-1) | ||
| 39 | #define SI5351_MULTISYNTH_P3_MAX ((1<<20)-1) | ||
| 40 | |||
| 41 | #define SI5351_DEVICE_STATUS 0 | ||
| 42 | #define SI5351_INTERRUPT_STATUS 1 | ||
| 43 | #define SI5351_INTERRUPT_MASK 2 | ||
| 44 | #define SI5351_STATUS_SYS_INIT (1<<7) | ||
| 45 | #define SI5351_STATUS_LOL_B (1<<6) | ||
| 46 | #define SI5351_STATUS_LOL_A (1<<5) | ||
| 47 | #define SI5351_STATUS_LOS (1<<4) | ||
| 48 | #define SI5351_OUTPUT_ENABLE_CTRL 3 | ||
| 49 | #define SI5351_OEB_PIN_ENABLE_CTRL 9 | ||
| 50 | #define SI5351_PLL_INPUT_SOURCE 15 | ||
| 51 | #define SI5351_CLKIN_DIV_MASK (3<<6) | ||
| 52 | #define SI5351_CLKIN_DIV_1 (0<<6) | ||
| 53 | #define SI5351_CLKIN_DIV_2 (1<<6) | ||
| 54 | #define SI5351_CLKIN_DIV_4 (2<<6) | ||
| 55 | #define SI5351_CLKIN_DIV_8 (3<<6) | ||
| 56 | #define SI5351_PLLB_SOURCE (1<<3) | ||
| 57 | #define SI5351_PLLA_SOURCE (1<<2) | ||
| 58 | |||
| 59 | #define SI5351_CLK0_CTRL 16 | ||
| 60 | #define SI5351_CLK1_CTRL 17 | ||
| 61 | #define SI5351_CLK2_CTRL 18 | ||
| 62 | #define SI5351_CLK3_CTRL 19 | ||
| 63 | #define SI5351_CLK4_CTRL 20 | ||
| 64 | #define SI5351_CLK5_CTRL 21 | ||
| 65 | #define SI5351_CLK6_CTRL 22 | ||
| 66 | #define SI5351_CLK7_CTRL 23 | ||
| 67 | #define SI5351_CLK_POWERDOWN (1<<7) | ||
| 68 | #define SI5351_CLK_INTEGER_MODE (1<<6) | ||
| 69 | #define SI5351_CLK_PLL_SELECT (1<<5) | ||
| 70 | #define SI5351_CLK_INVERT (1<<4) | ||
| 71 | #define SI5351_CLK_INPUT_MASK (3<<2) | ||
| 72 | #define SI5351_CLK_INPUT_XTAL (0<<2) | ||
| 73 | #define SI5351_CLK_INPUT_CLKIN (1<<2) | ||
| 74 | #define SI5351_CLK_INPUT_MULTISYNTH_0_4 (2<<2) | ||
| 75 | #define SI5351_CLK_INPUT_MULTISYNTH_N (3<<2) | ||
| 76 | #define SI5351_CLK_DRIVE_STRENGTH_MASK (3<<0) | ||
| 77 | #define SI5351_CLK_DRIVE_STRENGTH_2MA (0<<0) | ||
| 78 | #define SI5351_CLK_DRIVE_STRENGTH_4MA (1<<0) | ||
| 79 | #define SI5351_CLK_DRIVE_STRENGTH_6MA (2<<0) | ||
| 80 | #define SI5351_CLK_DRIVE_STRENGTH_8MA (3<<0) | ||
| 81 | |||
| 82 | #define SI5351_CLK3_0_DISABLE_STATE 24 | ||
| 83 | #define SI5351_CLK7_4_DISABLE_STATE 25 | ||
| 84 | #define SI5351_CLK_DISABLE_STATE_LOW 0 | ||
| 85 | #define SI5351_CLK_DISABLE_STATE_HIGH 1 | ||
| 86 | #define SI5351_CLK_DISABLE_STATE_FLOAT 2 | ||
| 87 | #define SI5351_CLK_DISABLE_STATE_NEVER 3 | ||
| 88 | |||
| 89 | #define SI5351_PARAMETERS_LENGTH 8 | ||
| 90 | #define SI5351_PLLA_PARAMETERS 26 | ||
| 91 | #define SI5351_PLLB_PARAMETERS 34 | ||
| 92 | #define SI5351_CLK0_PARAMETERS 42 | ||
| 93 | #define SI5351_CLK1_PARAMETERS 50 | ||
| 94 | #define SI5351_CLK2_PARAMETERS 58 | ||
| 95 | #define SI5351_CLK3_PARAMETERS 66 | ||
| 96 | #define SI5351_CLK4_PARAMETERS 74 | ||
| 97 | #define SI5351_CLK5_PARAMETERS 82 | ||
| 98 | #define SI5351_CLK6_PARAMETERS 90 | ||
| 99 | #define SI5351_CLK7_PARAMETERS 91 | ||
| 100 | #define SI5351_CLK6_7_OUTPUT_DIVIDER 92 | ||
| 101 | #define SI5351_OUTPUT_CLK_DIV_MASK (7 << 4) | ||
| 102 | #define SI5351_OUTPUT_CLK6_DIV_MASK (7 << 0) | ||
| 103 | #define SI5351_OUTPUT_CLK_DIV_SHIFT 4 | ||
| 104 | #define SI5351_OUTPUT_CLK_DIV6_SHIFT 0 | ||
| 105 | #define SI5351_OUTPUT_CLK_DIV_1 0 | ||
| 106 | #define SI5351_OUTPUT_CLK_DIV_2 1 | ||
| 107 | #define SI5351_OUTPUT_CLK_DIV_4 2 | ||
| 108 | #define SI5351_OUTPUT_CLK_DIV_8 3 | ||
| 109 | #define SI5351_OUTPUT_CLK_DIV_16 4 | ||
| 110 | #define SI5351_OUTPUT_CLK_DIV_32 5 | ||
| 111 | #define SI5351_OUTPUT_CLK_DIV_64 6 | ||
| 112 | #define SI5351_OUTPUT_CLK_DIV_128 7 | ||
| 113 | #define SI5351_OUTPUT_CLK_DIVBY4 (3<<2) | ||
| 114 | |||
| 115 | #define SI5351_SSC_PARAM0 149 | ||
| 116 | #define SI5351_SSC_PARAM1 150 | ||
| 117 | #define SI5351_SSC_PARAM2 151 | ||
| 118 | #define SI5351_SSC_PARAM3 152 | ||
| 119 | #define SI5351_SSC_PARAM4 153 | ||
| 120 | #define SI5351_SSC_PARAM5 154 | ||
| 121 | #define SI5351_SSC_PARAM6 155 | ||
| 122 | #define SI5351_SSC_PARAM7 156 | ||
| 123 | #define SI5351_SSC_PARAM8 157 | ||
| 124 | #define SI5351_SSC_PARAM9 158 | ||
| 125 | #define SI5351_SSC_PARAM10 159 | ||
| 126 | #define SI5351_SSC_PARAM11 160 | ||
| 127 | #define SI5351_SSC_PARAM12 161 | ||
| 128 | |||
| 129 | #define SI5351_VXCO_PARAMETERS_LOW 162 | ||
| 130 | #define SI5351_VXCO_PARAMETERS_MID 163 | ||
| 131 | #define SI5351_VXCO_PARAMETERS_HIGH 164 | ||
| 132 | |||
| 133 | #define SI5351_CLK0_PHASE_OFFSET 165 | ||
| 134 | #define SI5351_CLK1_PHASE_OFFSET 166 | ||
| 135 | #define SI5351_CLK2_PHASE_OFFSET 167 | ||
| 136 | #define SI5351_CLK3_PHASE_OFFSET 168 | ||
| 137 | #define SI5351_CLK4_PHASE_OFFSET 169 | ||
| 138 | #define SI5351_CLK5_PHASE_OFFSET 170 | ||
| 139 | |||
| 140 | #define SI5351_PLL_RESET 177 | ||
| 141 | #define SI5351_PLL_RESET_B (1<<7) | ||
| 142 | #define SI5351_PLL_RESET_A (1<<5) | ||
| 143 | |||
| 144 | #define SI5351_CRYSTAL_LOAD 183 | ||
| 145 | #define SI5351_CRYSTAL_LOAD_MASK (3<<6) | ||
| 146 | #define SI5351_CRYSTAL_LOAD_6PF (1<<6) | ||
| 147 | #define SI5351_CRYSTAL_LOAD_8PF (2<<6) | ||
| 148 | #define SI5351_CRYSTAL_LOAD_10PF (3<<6) | ||
| 149 | |||
| 150 | #define SI5351_FANOUT_ENABLE 187 | ||
| 151 | #define SI5351_CLKIN_ENABLE (1<<7) | ||
| 152 | #define SI5351_XTAL_ENABLE (1<<6) | ||
| 153 | #define SI5351_MULTISYNTH_ENABLE (1<<4) | ||
| 154 | |||
| 155 | #endif | ||
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index 09c63315e579..debf688afa8e 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c | |||
| @@ -488,6 +488,7 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 488 | case PLL_TYPE_WM8750: | 488 | case PLL_TYPE_WM8750: |
| 489 | wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2); | 489 | wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2); |
| 490 | pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2); | 490 | pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2); |
| 491 | break; | ||
| 491 | default: | 492 | default: |
| 492 | pr_err("%s: invalid pll type\n", __func__); | 493 | pr_err("%s: invalid pll type\n", __func__); |
| 493 | return 0; | 494 | return 0; |
| @@ -523,6 +524,7 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate, | |||
| 523 | case PLL_TYPE_WM8750: | 524 | case PLL_TYPE_WM8750: |
| 524 | wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2); | 525 | wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2); |
| 525 | round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2); | 526 | round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2); |
| 527 | break; | ||
| 526 | default: | 528 | default: |
| 527 | round_rate = 0; | 529 | round_rate = 0; |
| 528 | } | 530 | } |
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c index b14a25f39255..32062977f453 100644 --- a/drivers/clk/clk-zynq.c +++ b/drivers/clk/clk-zynq.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/clk-provider.h> | 22 | #include <linux/clk-provider.h> |
| 23 | #include <linux/clk/zynq.h> | ||
| 23 | 24 | ||
| 24 | static void __iomem *slcr_base; | 25 | static void __iomem *slcr_base; |
| 25 | 26 | ||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ed87b2405806..934cfd18f72d 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
| @@ -19,14 +19,77 @@ | |||
| 19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
| 20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 22 | #include <linux/sched.h> | ||
| 22 | 23 | ||
| 23 | static DEFINE_SPINLOCK(enable_lock); | 24 | static DEFINE_SPINLOCK(enable_lock); |
| 24 | static DEFINE_MUTEX(prepare_lock); | 25 | static DEFINE_MUTEX(prepare_lock); |
| 25 | 26 | ||
| 27 | static struct task_struct *prepare_owner; | ||
| 28 | static struct task_struct *enable_owner; | ||
| 29 | |||
| 30 | static int prepare_refcnt; | ||
| 31 | static int enable_refcnt; | ||
| 32 | |||
| 26 | static HLIST_HEAD(clk_root_list); | 33 | static HLIST_HEAD(clk_root_list); |
| 27 | static HLIST_HEAD(clk_orphan_list); | 34 | static HLIST_HEAD(clk_orphan_list); |
| 28 | static LIST_HEAD(clk_notifier_list); | 35 | static LIST_HEAD(clk_notifier_list); |
| 29 | 36 | ||
| 37 | /*** locking ***/ | ||
| 38 | static void clk_prepare_lock(void) | ||
| 39 | { | ||
| 40 | if (!mutex_trylock(&prepare_lock)) { | ||
| 41 | if (prepare_owner == current) { | ||
| 42 | prepare_refcnt++; | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | mutex_lock(&prepare_lock); | ||
| 46 | } | ||
| 47 | WARN_ON_ONCE(prepare_owner != NULL); | ||
| 48 | WARN_ON_ONCE(prepare_refcnt != 0); | ||
| 49 | prepare_owner = current; | ||
| 50 | prepare_refcnt = 1; | ||
| 51 | } | ||
| 52 | |||
| 53 | static void clk_prepare_unlock(void) | ||
| 54 | { | ||
| 55 | WARN_ON_ONCE(prepare_owner != current); | ||
| 56 | WARN_ON_ONCE(prepare_refcnt == 0); | ||
| 57 | |||
| 58 | if (--prepare_refcnt) | ||
| 59 | return; | ||
| 60 | prepare_owner = NULL; | ||
| 61 | mutex_unlock(&prepare_lock); | ||
| 62 | } | ||
| 63 | |||
| 64 | static unsigned long clk_enable_lock(void) | ||
| 65 | { | ||
| 66 | unsigned long flags; | ||
| 67 | |||
| 68 | if (!spin_trylock_irqsave(&enable_lock, flags)) { | ||
| 69 | if (enable_owner == current) { | ||
| 70 | enable_refcnt++; | ||
| 71 | return flags; | ||
| 72 | } | ||
| 73 | spin_lock_irqsave(&enable_lock, flags); | ||
| 74 | } | ||
| 75 | WARN_ON_ONCE(enable_owner != NULL); | ||
| 76 | WARN_ON_ONCE(enable_refcnt != 0); | ||
| 77 | enable_owner = current; | ||
| 78 | enable_refcnt = 1; | ||
| 79 | return flags; | ||
| 80 | } | ||
| 81 | |||
| 82 | static void clk_enable_unlock(unsigned long flags) | ||
| 83 | { | ||
| 84 | WARN_ON_ONCE(enable_owner != current); | ||
| 85 | WARN_ON_ONCE(enable_refcnt == 0); | ||
| 86 | |||
| 87 | if (--enable_refcnt) | ||
| 88 | return; | ||
| 89 | enable_owner = NULL; | ||
| 90 | spin_unlock_irqrestore(&enable_lock, flags); | ||
| 91 | } | ||
| 92 | |||
| 30 | /*** debugfs support ***/ | 93 | /*** debugfs support ***/ |
| 31 | 94 | ||
| 32 | #ifdef CONFIG_COMMON_CLK_DEBUG | 95 | #ifdef CONFIG_COMMON_CLK_DEBUG |
| @@ -69,7 +132,7 @@ static int clk_summary_show(struct seq_file *s, void *data) | |||
| 69 | seq_printf(s, " clock enable_cnt prepare_cnt rate\n"); | 132 | seq_printf(s, " clock enable_cnt prepare_cnt rate\n"); |
| 70 | seq_printf(s, "---------------------------------------------------------------------\n"); | 133 | seq_printf(s, "---------------------------------------------------------------------\n"); |
| 71 | 134 | ||
| 72 | mutex_lock(&prepare_lock); | 135 | clk_prepare_lock(); |
| 73 | 136 | ||
| 74 | hlist_for_each_entry(c, &clk_root_list, child_node) | 137 | hlist_for_each_entry(c, &clk_root_list, child_node) |
| 75 | clk_summary_show_subtree(s, c, 0); | 138 | clk_summary_show_subtree(s, c, 0); |
| @@ -77,7 +140,7 @@ static int clk_summary_show(struct seq_file *s, void *data) | |||
| 77 | hlist_for_each_entry(c, &clk_orphan_list, child_node) | 140 | hlist_for_each_entry(c, &clk_orphan_list, child_node) |
| 78 | clk_summary_show_subtree(s, c, 0); | 141 | clk_summary_show_subtree(s, c, 0); |
| 79 | 142 | ||
| 80 | mutex_unlock(&prepare_lock); | 143 | clk_prepare_unlock(); |
| 81 | 144 | ||
| 82 | return 0; | 145 | return 0; |
| 83 | } | 146 | } |
| @@ -130,7 +193,7 @@ static int clk_dump(struct seq_file *s, void *data) | |||
| 130 | 193 | ||
| 131 | seq_printf(s, "{"); | 194 | seq_printf(s, "{"); |
| 132 | 195 | ||
| 133 | mutex_lock(&prepare_lock); | 196 | clk_prepare_lock(); |
| 134 | 197 | ||
| 135 | hlist_for_each_entry(c, &clk_root_list, child_node) { | 198 | hlist_for_each_entry(c, &clk_root_list, child_node) { |
| 136 | if (!first_node) | 199 | if (!first_node) |
| @@ -144,7 +207,7 @@ static int clk_dump(struct seq_file *s, void *data) | |||
| 144 | clk_dump_subtree(s, c, 0); | 207 | clk_dump_subtree(s, c, 0); |
| 145 | } | 208 | } |
| 146 | 209 | ||
| 147 | mutex_unlock(&prepare_lock); | 210 | clk_prepare_unlock(); |
| 148 | 211 | ||
| 149 | seq_printf(s, "}"); | 212 | seq_printf(s, "}"); |
| 150 | return 0; | 213 | return 0; |
| @@ -280,6 +343,39 @@ out: | |||
| 280 | } | 343 | } |
| 281 | 344 | ||
| 282 | /** | 345 | /** |
| 346 | * clk_debug_reparent - reparent clk node in the debugfs clk tree | ||
| 347 | * @clk: the clk being reparented | ||
| 348 | * @new_parent: the new clk parent, may be NULL | ||
| 349 | * | ||
| 350 | * Rename clk entry in the debugfs clk tree if debugfs has been | ||
| 351 | * initialized. Otherwise it bails out early since the debugfs clk tree | ||
| 352 | * will be created lazily by clk_debug_init as part of a late_initcall. | ||
| 353 | * | ||
| 354 | * Caller must hold prepare_lock. | ||
| 355 | */ | ||
| 356 | static void clk_debug_reparent(struct clk *clk, struct clk *new_parent) | ||
| 357 | { | ||
| 358 | struct dentry *d; | ||
| 359 | struct dentry *new_parent_d; | ||
| 360 | |||
| 361 | if (!inited) | ||
| 362 | return; | ||
| 363 | |||
| 364 | if (new_parent) | ||
| 365 | new_parent_d = new_parent->dentry; | ||
| 366 | else | ||
| 367 | new_parent_d = orphandir; | ||
| 368 | |||
| 369 | d = debugfs_rename(clk->dentry->d_parent, clk->dentry, | ||
| 370 | new_parent_d, clk->name); | ||
| 371 | if (d) | ||
| 372 | clk->dentry = d; | ||
| 373 | else | ||
| 374 | pr_debug("%s: failed to rename debugfs entry for %s\n", | ||
| 375 | __func__, clk->name); | ||
| 376 | } | ||
| 377 | |||
| 378 | /** | ||
| 283 | * clk_debug_init - lazily create the debugfs clk tree visualization | 379 | * clk_debug_init - lazily create the debugfs clk tree visualization |
| 284 | * | 380 | * |
| 285 | * clks are often initialized very early during boot before memory can | 381 | * clks are often initialized very early during boot before memory can |
| @@ -316,7 +412,7 @@ static int __init clk_debug_init(void) | |||
| 316 | if (!orphandir) | 412 | if (!orphandir) |
| 317 | return -ENOMEM; | 413 | return -ENOMEM; |
| 318 | 414 | ||
| 319 | mutex_lock(&prepare_lock); | 415 | clk_prepare_lock(); |
| 320 | 416 | ||
| 321 | hlist_for_each_entry(clk, &clk_root_list, child_node) | 417 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
| 322 | clk_debug_create_subtree(clk, rootdir); | 418 | clk_debug_create_subtree(clk, rootdir); |
| @@ -326,16 +422,45 @@ static int __init clk_debug_init(void) | |||
| 326 | 422 | ||
| 327 | inited = 1; | 423 | inited = 1; |
| 328 | 424 | ||
| 329 | mutex_unlock(&prepare_lock); | 425 | clk_prepare_unlock(); |
| 330 | 426 | ||
| 331 | return 0; | 427 | return 0; |
| 332 | } | 428 | } |
| 333 | late_initcall(clk_debug_init); | 429 | late_initcall(clk_debug_init); |
| 334 | #else | 430 | #else |
| 335 | static inline int clk_debug_register(struct clk *clk) { return 0; } | 431 | static inline int clk_debug_register(struct clk *clk) { return 0; } |
| 432 | static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent) | ||
| 433 | { | ||
| 434 | } | ||
| 336 | #endif | 435 | #endif |
| 337 | 436 | ||
| 338 | /* caller must hold prepare_lock */ | 437 | /* caller must hold prepare_lock */ |
| 438 | static void clk_unprepare_unused_subtree(struct clk *clk) | ||
| 439 | { | ||
| 440 | struct clk *child; | ||
| 441 | |||
| 442 | if (!clk) | ||
| 443 | return; | ||
| 444 | |||
| 445 | hlist_for_each_entry(child, &clk->children, child_node) | ||
| 446 | clk_unprepare_unused_subtree(child); | ||
| 447 | |||
| 448 | if (clk->prepare_count) | ||
| 449 | return; | ||
| 450 | |||
| 451 | if (clk->flags & CLK_IGNORE_UNUSED) | ||
| 452 | return; | ||
| 453 | |||
| 454 | if (__clk_is_prepared(clk)) { | ||
| 455 | if (clk->ops->unprepare_unused) | ||
| 456 | clk->ops->unprepare_unused(clk->hw); | ||
| 457 | else if (clk->ops->unprepare) | ||
| 458 | clk->ops->unprepare(clk->hw); | ||
| 459 | } | ||
| 460 | } | ||
| 461 | EXPORT_SYMBOL_GPL(__clk_get_flags); | ||
| 462 | |||
| 463 | /* caller must hold prepare_lock */ | ||
| 339 | static void clk_disable_unused_subtree(struct clk *clk) | 464 | static void clk_disable_unused_subtree(struct clk *clk) |
| 340 | { | 465 | { |
| 341 | struct clk *child; | 466 | struct clk *child; |
| @@ -347,7 +472,7 @@ static void clk_disable_unused_subtree(struct clk *clk) | |||
| 347 | hlist_for_each_entry(child, &clk->children, child_node) | 472 | hlist_for_each_entry(child, &clk->children, child_node) |
| 348 | clk_disable_unused_subtree(child); | 473 | clk_disable_unused_subtree(child); |
| 349 | 474 | ||
| 350 | spin_lock_irqsave(&enable_lock, flags); | 475 | flags = clk_enable_lock(); |
| 351 | 476 | ||
| 352 | if (clk->enable_count) | 477 | if (clk->enable_count) |
| 353 | goto unlock_out; | 478 | goto unlock_out; |
| @@ -368,17 +493,30 @@ static void clk_disable_unused_subtree(struct clk *clk) | |||
| 368 | } | 493 | } |
| 369 | 494 | ||
| 370 | unlock_out: | 495 | unlock_out: |
| 371 | spin_unlock_irqrestore(&enable_lock, flags); | 496 | clk_enable_unlock(flags); |
| 372 | 497 | ||
| 373 | out: | 498 | out: |
| 374 | return; | 499 | return; |
| 375 | } | 500 | } |
| 376 | 501 | ||
| 502 | static bool clk_ignore_unused; | ||
| 503 | static int __init clk_ignore_unused_setup(char *__unused) | ||
| 504 | { | ||
| 505 | clk_ignore_unused = true; | ||
| 506 | return 1; | ||
| 507 | } | ||
| 508 | __setup("clk_ignore_unused", clk_ignore_unused_setup); | ||
| 509 | |||
| 377 | static int clk_disable_unused(void) | 510 | static int clk_disable_unused(void) |
| 378 | { | 511 | { |
| 379 | struct clk *clk; | 512 | struct clk *clk; |
| 380 | 513 | ||
| 381 | mutex_lock(&prepare_lock); | 514 | if (clk_ignore_unused) { |
| 515 | pr_warn("clk: Not disabling unused clocks\n"); | ||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | clk_prepare_lock(); | ||
| 382 | 520 | ||
| 383 | hlist_for_each_entry(clk, &clk_root_list, child_node) | 521 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
| 384 | clk_disable_unused_subtree(clk); | 522 | clk_disable_unused_subtree(clk); |
| @@ -386,7 +524,13 @@ static int clk_disable_unused(void) | |||
| 386 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) | 524 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) |
| 387 | clk_disable_unused_subtree(clk); | 525 | clk_disable_unused_subtree(clk); |
| 388 | 526 | ||
| 389 | mutex_unlock(&prepare_lock); | 527 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
| 528 | clk_unprepare_unused_subtree(clk); | ||
| 529 | |||
| 530 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) | ||
| 531 | clk_unprepare_unused_subtree(clk); | ||
| 532 | |||
| 533 | clk_prepare_unlock(); | ||
| 390 | 534 | ||
| 391 | return 0; | 535 | return 0; |
| 392 | } | 536 | } |
| @@ -451,6 +595,27 @@ unsigned long __clk_get_flags(struct clk *clk) | |||
| 451 | return !clk ? 0 : clk->flags; | 595 | return !clk ? 0 : clk->flags; |
| 452 | } | 596 | } |
| 453 | 597 | ||
| 598 | bool __clk_is_prepared(struct clk *clk) | ||
| 599 | { | ||
| 600 | int ret; | ||
| 601 | |||
| 602 | if (!clk) | ||
| 603 | return false; | ||
| 604 | |||
| 605 | /* | ||
| 606 | * .is_prepared is optional for clocks that can prepare | ||
| 607 | * fall back to software usage counter if it is missing | ||
| 608 | */ | ||
| 609 | if (!clk->ops->is_prepared) { | ||
| 610 | ret = clk->prepare_count ? 1 : 0; | ||
| 611 | goto out; | ||
| 612 | } | ||
| 613 | |||
| 614 | ret = clk->ops->is_prepared(clk->hw); | ||
| 615 | out: | ||
| 616 | return !!ret; | ||
| 617 | } | ||
| 618 | |||
| 454 | bool __clk_is_enabled(struct clk *clk) | 619 | bool __clk_is_enabled(struct clk *clk) |
| 455 | { | 620 | { |
| 456 | int ret; | 621 | int ret; |
| @@ -548,9 +713,9 @@ void __clk_unprepare(struct clk *clk) | |||
| 548 | */ | 713 | */ |
| 549 | void clk_unprepare(struct clk *clk) | 714 | void clk_unprepare(struct clk *clk) |
| 550 | { | 715 | { |
| 551 | mutex_lock(&prepare_lock); | 716 | clk_prepare_lock(); |
| 552 | __clk_unprepare(clk); | 717 | __clk_unprepare(clk); |
| 553 | mutex_unlock(&prepare_lock); | 718 | clk_prepare_unlock(); |
| 554 | } | 719 | } |
| 555 | EXPORT_SYMBOL_GPL(clk_unprepare); | 720 | EXPORT_SYMBOL_GPL(clk_unprepare); |
| 556 | 721 | ||
| @@ -596,9 +761,9 @@ int clk_prepare(struct clk *clk) | |||
| 596 | { | 761 | { |
| 597 | int ret; | 762 | int ret; |
| 598 | 763 | ||
| 599 | mutex_lock(&prepare_lock); | 764 | clk_prepare_lock(); |
| 600 | ret = __clk_prepare(clk); | 765 | ret = __clk_prepare(clk); |
| 601 | mutex_unlock(&prepare_lock); | 766 | clk_prepare_unlock(); |
| 602 | 767 | ||
| 603 | return ret; | 768 | return ret; |
| 604 | } | 769 | } |
| @@ -640,9 +805,9 @@ void clk_disable(struct clk *clk) | |||
| 640 | { | 805 | { |
| 641 | unsigned long flags; | 806 | unsigned long flags; |
| 642 | 807 | ||
| 643 | spin_lock_irqsave(&enable_lock, flags); | 808 | flags = clk_enable_lock(); |
| 644 | __clk_disable(clk); | 809 | __clk_disable(clk); |
| 645 | spin_unlock_irqrestore(&enable_lock, flags); | 810 | clk_enable_unlock(flags); |
| 646 | } | 811 | } |
| 647 | EXPORT_SYMBOL_GPL(clk_disable); | 812 | EXPORT_SYMBOL_GPL(clk_disable); |
| 648 | 813 | ||
| @@ -693,9 +858,9 @@ int clk_enable(struct clk *clk) | |||
| 693 | unsigned long flags; | 858 | unsigned long flags; |
| 694 | int ret; | 859 | int ret; |
| 695 | 860 | ||
| 696 | spin_lock_irqsave(&enable_lock, flags); | 861 | flags = clk_enable_lock(); |
| 697 | ret = __clk_enable(clk); | 862 | ret = __clk_enable(clk); |
| 698 | spin_unlock_irqrestore(&enable_lock, flags); | 863 | clk_enable_unlock(flags); |
| 699 | 864 | ||
| 700 | return ret; | 865 | return ret; |
| 701 | } | 866 | } |
| @@ -740,9 +905,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
| 740 | { | 905 | { |
| 741 | unsigned long ret; | 906 | unsigned long ret; |
| 742 | 907 | ||
| 743 | mutex_lock(&prepare_lock); | 908 | clk_prepare_lock(); |
| 744 | ret = __clk_round_rate(clk, rate); | 909 | ret = __clk_round_rate(clk, rate); |
| 745 | mutex_unlock(&prepare_lock); | 910 | clk_prepare_unlock(); |
| 746 | 911 | ||
| 747 | return ret; | 912 | return ret; |
| 748 | } | 913 | } |
| @@ -837,13 +1002,13 @@ unsigned long clk_get_rate(struct clk *clk) | |||
| 837 | { | 1002 | { |
| 838 | unsigned long rate; | 1003 | unsigned long rate; |
| 839 | 1004 | ||
| 840 | mutex_lock(&prepare_lock); | 1005 | clk_prepare_lock(); |
| 841 | 1006 | ||
| 842 | if (clk && (clk->flags & CLK_GET_RATE_NOCACHE)) | 1007 | if (clk && (clk->flags & CLK_GET_RATE_NOCACHE)) |
| 843 | __clk_recalc_rates(clk, 0); | 1008 | __clk_recalc_rates(clk, 0); |
| 844 | 1009 | ||
| 845 | rate = __clk_get_rate(clk); | 1010 | rate = __clk_get_rate(clk); |
| 846 | mutex_unlock(&prepare_lock); | 1011 | clk_prepare_unlock(); |
| 847 | 1012 | ||
| 848 | return rate; | 1013 | return rate; |
| 849 | } | 1014 | } |
| @@ -876,16 +1041,16 @@ static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate) | |||
| 876 | else | 1041 | else |
| 877 | new_rate = parent_rate; | 1042 | new_rate = parent_rate; |
| 878 | 1043 | ||
| 879 | /* abort the rate change if a driver returns NOTIFY_BAD */ | 1044 | /* abort rate change if a driver returns NOTIFY_BAD or NOTIFY_STOP */ |
| 880 | if (clk->notifier_count) | 1045 | if (clk->notifier_count) |
| 881 | ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); | 1046 | ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); |
| 882 | 1047 | ||
| 883 | if (ret == NOTIFY_BAD) | 1048 | if (ret & NOTIFY_STOP_MASK) |
| 884 | goto out; | 1049 | goto out; |
| 885 | 1050 | ||
| 886 | hlist_for_each_entry(child, &clk->children, child_node) { | 1051 | hlist_for_each_entry(child, &clk->children, child_node) { |
| 887 | ret = __clk_speculate_rates(child, new_rate); | 1052 | ret = __clk_speculate_rates(child, new_rate); |
| 888 | if (ret == NOTIFY_BAD) | 1053 | if (ret & NOTIFY_STOP_MASK) |
| 889 | break; | 1054 | break; |
| 890 | } | 1055 | } |
| 891 | 1056 | ||
| @@ -974,11 +1139,11 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even | |||
| 974 | int ret = NOTIFY_DONE; | 1139 | int ret = NOTIFY_DONE; |
| 975 | 1140 | ||
| 976 | if (clk->rate == clk->new_rate) | 1141 | if (clk->rate == clk->new_rate) |
| 977 | return 0; | 1142 | return NULL; |
| 978 | 1143 | ||
| 979 | if (clk->notifier_count) { | 1144 | if (clk->notifier_count) { |
| 980 | ret = __clk_notify(clk, event, clk->rate, clk->new_rate); | 1145 | ret = __clk_notify(clk, event, clk->rate, clk->new_rate); |
| 981 | if (ret == NOTIFY_BAD) | 1146 | if (ret & NOTIFY_STOP_MASK) |
| 982 | fail_clk = clk; | 1147 | fail_clk = clk; |
| 983 | } | 1148 | } |
| 984 | 1149 | ||
| @@ -1048,7 +1213,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
| 1048 | int ret = 0; | 1213 | int ret = 0; |
| 1049 | 1214 | ||
| 1050 | /* prevent racing with updates to the clock topology */ | 1215 | /* prevent racing with updates to the clock topology */ |
| 1051 | mutex_lock(&prepare_lock); | 1216 | clk_prepare_lock(); |
| 1052 | 1217 | ||
| 1053 | /* bail early if nothing to do */ | 1218 | /* bail early if nothing to do */ |
| 1054 | if (rate == clk->rate) | 1219 | if (rate == clk->rate) |
| @@ -1080,7 +1245,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
| 1080 | clk_change_rate(top); | 1245 | clk_change_rate(top); |
| 1081 | 1246 | ||
| 1082 | out: | 1247 | out: |
| 1083 | mutex_unlock(&prepare_lock); | 1248 | clk_prepare_unlock(); |
| 1084 | 1249 | ||
| 1085 | return ret; | 1250 | return ret; |
| 1086 | } | 1251 | } |
| @@ -1096,9 +1261,9 @@ struct clk *clk_get_parent(struct clk *clk) | |||
| 1096 | { | 1261 | { |
| 1097 | struct clk *parent; | 1262 | struct clk *parent; |
| 1098 | 1263 | ||
| 1099 | mutex_lock(&prepare_lock); | 1264 | clk_prepare_lock(); |
| 1100 | parent = __clk_get_parent(clk); | 1265 | parent = __clk_get_parent(clk); |
| 1101 | mutex_unlock(&prepare_lock); | 1266 | clk_prepare_unlock(); |
| 1102 | 1267 | ||
| 1103 | return parent; | 1268 | return parent; |
| 1104 | } | 1269 | } |
| @@ -1162,16 +1327,8 @@ out: | |||
| 1162 | return ret; | 1327 | return ret; |
| 1163 | } | 1328 | } |
| 1164 | 1329 | ||
| 1165 | void __clk_reparent(struct clk *clk, struct clk *new_parent) | 1330 | static void clk_reparent(struct clk *clk, struct clk *new_parent) |
| 1166 | { | 1331 | { |
| 1167 | #ifdef CONFIG_COMMON_CLK_DEBUG | ||
| 1168 | struct dentry *d; | ||
| 1169 | struct dentry *new_parent_d; | ||
| 1170 | #endif | ||
| 1171 | |||
| 1172 | if (!clk || !new_parent) | ||
| 1173 | return; | ||
| 1174 | |||
| 1175 | hlist_del(&clk->child_node); | 1332 | hlist_del(&clk->child_node); |
| 1176 | 1333 | ||
| 1177 | if (new_parent) | 1334 | if (new_parent) |
| @@ -1179,39 +1336,20 @@ void __clk_reparent(struct clk *clk, struct clk *new_parent) | |||
| 1179 | else | 1336 | else |
| 1180 | hlist_add_head(&clk->child_node, &clk_orphan_list); | 1337 | hlist_add_head(&clk->child_node, &clk_orphan_list); |
| 1181 | 1338 | ||
| 1182 | #ifdef CONFIG_COMMON_CLK_DEBUG | ||
| 1183 | if (!inited) | ||
| 1184 | goto out; | ||
| 1185 | |||
| 1186 | if (new_parent) | ||
| 1187 | new_parent_d = new_parent->dentry; | ||
| 1188 | else | ||
| 1189 | new_parent_d = orphandir; | ||
| 1190 | |||
| 1191 | d = debugfs_rename(clk->dentry->d_parent, clk->dentry, | ||
| 1192 | new_parent_d, clk->name); | ||
| 1193 | if (d) | ||
| 1194 | clk->dentry = d; | ||
| 1195 | else | ||
| 1196 | pr_debug("%s: failed to rename debugfs entry for %s\n", | ||
| 1197 | __func__, clk->name); | ||
| 1198 | out: | ||
| 1199 | #endif | ||
| 1200 | |||
| 1201 | clk->parent = new_parent; | 1339 | clk->parent = new_parent; |
| 1340 | } | ||
| 1202 | 1341 | ||
| 1342 | void __clk_reparent(struct clk *clk, struct clk *new_parent) | ||
| 1343 | { | ||
| 1344 | clk_reparent(clk, new_parent); | ||
| 1345 | clk_debug_reparent(clk, new_parent); | ||
| 1203 | __clk_recalc_rates(clk, POST_RATE_CHANGE); | 1346 | __clk_recalc_rates(clk, POST_RATE_CHANGE); |
| 1204 | } | 1347 | } |
| 1205 | 1348 | ||
| 1206 | static int __clk_set_parent(struct clk *clk, struct clk *parent) | 1349 | static u8 clk_fetch_parent_index(struct clk *clk, struct clk *parent) |
| 1207 | { | 1350 | { |
| 1208 | struct clk *old_parent; | ||
| 1209 | unsigned long flags; | ||
| 1210 | int ret = -EINVAL; | ||
| 1211 | u8 i; | 1351 | u8 i; |
| 1212 | 1352 | ||
| 1213 | old_parent = clk->parent; | ||
| 1214 | |||
| 1215 | if (!clk->parents) | 1353 | if (!clk->parents) |
| 1216 | clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), | 1354 | clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), |
| 1217 | GFP_KERNEL); | 1355 | GFP_KERNEL); |
| @@ -1231,36 +1369,79 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent) | |||
| 1231 | } | 1369 | } |
| 1232 | } | 1370 | } |
| 1233 | 1371 | ||
| 1234 | if (i == clk->num_parents) { | 1372 | return i; |
| 1235 | pr_debug("%s: clock %s is not a possible parent of clock %s\n", | 1373 | } |
| 1236 | __func__, parent->name, clk->name); | ||
| 1237 | goto out; | ||
| 1238 | } | ||
| 1239 | 1374 | ||
| 1240 | /* migrate prepare and enable */ | 1375 | static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index) |
| 1376 | { | ||
| 1377 | unsigned long flags; | ||
| 1378 | int ret = 0; | ||
| 1379 | struct clk *old_parent = clk->parent; | ||
| 1380 | bool migrated_enable = false; | ||
| 1381 | |||
| 1382 | /* migrate prepare */ | ||
| 1241 | if (clk->prepare_count) | 1383 | if (clk->prepare_count) |
| 1242 | __clk_prepare(parent); | 1384 | __clk_prepare(parent); |
| 1243 | 1385 | ||
| 1244 | /* FIXME replace with clk_is_enabled(clk) someday */ | 1386 | flags = clk_enable_lock(); |
| 1245 | spin_lock_irqsave(&enable_lock, flags); | 1387 | |
| 1246 | if (clk->enable_count) | 1388 | /* migrate enable */ |
| 1389 | if (clk->enable_count) { | ||
| 1247 | __clk_enable(parent); | 1390 | __clk_enable(parent); |
| 1248 | spin_unlock_irqrestore(&enable_lock, flags); | 1391 | migrated_enable = true; |
| 1392 | } | ||
| 1393 | |||
| 1394 | /* update the clk tree topology */ | ||
| 1395 | clk_reparent(clk, parent); | ||
| 1396 | |||
| 1397 | clk_enable_unlock(flags); | ||
| 1249 | 1398 | ||
| 1250 | /* change clock input source */ | 1399 | /* change clock input source */ |
| 1251 | ret = clk->ops->set_parent(clk->hw, i); | 1400 | if (parent && clk->ops->set_parent) |
| 1401 | ret = clk->ops->set_parent(clk->hw, p_index); | ||
| 1252 | 1402 | ||
| 1253 | /* clean up old prepare and enable */ | 1403 | if (ret) { |
| 1254 | spin_lock_irqsave(&enable_lock, flags); | 1404 | /* |
| 1255 | if (clk->enable_count) | 1405 | * The error handling is tricky due to that we need to release |
| 1406 | * the spinlock while issuing the .set_parent callback. This | ||
| 1407 | * means the new parent might have been enabled/disabled in | ||
| 1408 | * between, which must be considered when doing rollback. | ||
| 1409 | */ | ||
| 1410 | flags = clk_enable_lock(); | ||
| 1411 | |||
| 1412 | clk_reparent(clk, old_parent); | ||
| 1413 | |||
| 1414 | if (migrated_enable && clk->enable_count) { | ||
| 1415 | __clk_disable(parent); | ||
| 1416 | } else if (migrated_enable && (clk->enable_count == 0)) { | ||
| 1417 | __clk_disable(old_parent); | ||
| 1418 | } else if (!migrated_enable && clk->enable_count) { | ||
| 1419 | __clk_disable(parent); | ||
| 1420 | __clk_enable(old_parent); | ||
| 1421 | } | ||
| 1422 | |||
| 1423 | clk_enable_unlock(flags); | ||
| 1424 | |||
| 1425 | if (clk->prepare_count) | ||
| 1426 | __clk_unprepare(parent); | ||
| 1427 | |||
| 1428 | return ret; | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | /* clean up enable for old parent if migration was done */ | ||
| 1432 | if (migrated_enable) { | ||
| 1433 | flags = clk_enable_lock(); | ||
| 1256 | __clk_disable(old_parent); | 1434 | __clk_disable(old_parent); |
| 1257 | spin_unlock_irqrestore(&enable_lock, flags); | 1435 | clk_enable_unlock(flags); |
| 1436 | } | ||
| 1258 | 1437 | ||
| 1438 | /* clean up prepare for old parent if migration was done */ | ||
| 1259 | if (clk->prepare_count) | 1439 | if (clk->prepare_count) |
| 1260 | __clk_unprepare(old_parent); | 1440 | __clk_unprepare(old_parent); |
| 1261 | 1441 | ||
| 1262 | out: | 1442 | /* update debugfs with new clk tree topology */ |
| 1263 | return ret; | 1443 | clk_debug_reparent(clk, parent); |
| 1444 | return 0; | ||
| 1264 | } | 1445 | } |
| 1265 | 1446 | ||
| 1266 | /** | 1447 | /** |
| @@ -1278,44 +1459,59 @@ out: | |||
| 1278 | int clk_set_parent(struct clk *clk, struct clk *parent) | 1459 | int clk_set_parent(struct clk *clk, struct clk *parent) |
| 1279 | { | 1460 | { |
| 1280 | int ret = 0; | 1461 | int ret = 0; |
| 1462 | u8 p_index = 0; | ||
| 1463 | unsigned long p_rate = 0; | ||
| 1281 | 1464 | ||
| 1282 | if (!clk || !clk->ops) | 1465 | if (!clk || !clk->ops) |
| 1283 | return -EINVAL; | 1466 | return -EINVAL; |
| 1284 | 1467 | ||
| 1285 | if (!clk->ops->set_parent) | 1468 | /* verify ops for for multi-parent clks */ |
| 1469 | if ((clk->num_parents > 1) && (!clk->ops->set_parent)) | ||
| 1286 | return -ENOSYS; | 1470 | return -ENOSYS; |
| 1287 | 1471 | ||
| 1288 | /* prevent racing with updates to the clock topology */ | 1472 | /* prevent racing with updates to the clock topology */ |
| 1289 | mutex_lock(&prepare_lock); | 1473 | clk_prepare_lock(); |
| 1290 | 1474 | ||
| 1291 | if (clk->parent == parent) | 1475 | if (clk->parent == parent) |
| 1292 | goto out; | 1476 | goto out; |
| 1293 | 1477 | ||
| 1478 | /* check that we are allowed to re-parent if the clock is in use */ | ||
| 1479 | if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) { | ||
| 1480 | ret = -EBUSY; | ||
| 1481 | goto out; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | /* try finding the new parent index */ | ||
| 1485 | if (parent) { | ||
| 1486 | p_index = clk_fetch_parent_index(clk, parent); | ||
| 1487 | p_rate = parent->rate; | ||
| 1488 | if (p_index == clk->num_parents) { | ||
| 1489 | pr_debug("%s: clk %s can not be parent of clk %s\n", | ||
| 1490 | __func__, parent->name, clk->name); | ||
| 1491 | ret = -EINVAL; | ||
| 1492 | goto out; | ||
| 1493 | } | ||
| 1494 | } | ||
| 1495 | |||
| 1294 | /* propagate PRE_RATE_CHANGE notifications */ | 1496 | /* propagate PRE_RATE_CHANGE notifications */ |
| 1295 | if (clk->notifier_count) | 1497 | if (clk->notifier_count) |
| 1296 | ret = __clk_speculate_rates(clk, parent->rate); | 1498 | ret = __clk_speculate_rates(clk, p_rate); |
| 1297 | 1499 | ||
| 1298 | /* abort if a driver objects */ | 1500 | /* abort if a driver objects */ |
| 1299 | if (ret == NOTIFY_STOP) | 1501 | if (ret & NOTIFY_STOP_MASK) |
| 1300 | goto out; | 1502 | goto out; |
| 1301 | 1503 | ||
| 1302 | /* only re-parent if the clock is not in use */ | 1504 | /* do the re-parent */ |
| 1303 | if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) | 1505 | ret = __clk_set_parent(clk, parent, p_index); |
| 1304 | ret = -EBUSY; | ||
| 1305 | else | ||
| 1306 | ret = __clk_set_parent(clk, parent); | ||
| 1307 | 1506 | ||
| 1308 | /* propagate ABORT_RATE_CHANGE if .set_parent failed */ | 1507 | /* propagate rate recalculation accordingly */ |
| 1309 | if (ret) { | 1508 | if (ret) |
| 1310 | __clk_recalc_rates(clk, ABORT_RATE_CHANGE); | 1509 | __clk_recalc_rates(clk, ABORT_RATE_CHANGE); |
| 1311 | goto out; | 1510 | else |
| 1312 | } | 1511 | __clk_recalc_rates(clk, POST_RATE_CHANGE); |
| 1313 | |||
| 1314 | /* propagate rate recalculation downstream */ | ||
| 1315 | __clk_reparent(clk, parent); | ||
| 1316 | 1512 | ||
| 1317 | out: | 1513 | out: |
| 1318 | mutex_unlock(&prepare_lock); | 1514 | clk_prepare_unlock(); |
| 1319 | 1515 | ||
| 1320 | return ret; | 1516 | return ret; |
| 1321 | } | 1517 | } |
| @@ -1338,7 +1534,7 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
| 1338 | if (!clk) | 1534 | if (!clk) |
| 1339 | return -EINVAL; | 1535 | return -EINVAL; |
| 1340 | 1536 | ||
| 1341 | mutex_lock(&prepare_lock); | 1537 | clk_prepare_lock(); |
| 1342 | 1538 | ||
| 1343 | /* check to see if a clock with this name is already registered */ | 1539 | /* check to see if a clock with this name is already registered */ |
| 1344 | if (__clk_lookup(clk->name)) { | 1540 | if (__clk_lookup(clk->name)) { |
| @@ -1462,7 +1658,7 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
| 1462 | clk_debug_register(clk); | 1658 | clk_debug_register(clk); |
| 1463 | 1659 | ||
| 1464 | out: | 1660 | out: |
| 1465 | mutex_unlock(&prepare_lock); | 1661 | clk_prepare_unlock(); |
| 1466 | 1662 | ||
| 1467 | return ret; | 1663 | return ret; |
| 1468 | } | 1664 | } |
| @@ -1696,7 +1892,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) | |||
| 1696 | if (!clk || !nb) | 1892 | if (!clk || !nb) |
| 1697 | return -EINVAL; | 1893 | return -EINVAL; |
| 1698 | 1894 | ||
| 1699 | mutex_lock(&prepare_lock); | 1895 | clk_prepare_lock(); |
| 1700 | 1896 | ||
| 1701 | /* search the list of notifiers for this clk */ | 1897 | /* search the list of notifiers for this clk */ |
| 1702 | list_for_each_entry(cn, &clk_notifier_list, node) | 1898 | list_for_each_entry(cn, &clk_notifier_list, node) |
| @@ -1720,7 +1916,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) | |||
| 1720 | clk->notifier_count++; | 1916 | clk->notifier_count++; |
| 1721 | 1917 | ||
| 1722 | out: | 1918 | out: |
| 1723 | mutex_unlock(&prepare_lock); | 1919 | clk_prepare_unlock(); |
| 1724 | 1920 | ||
| 1725 | return ret; | 1921 | return ret; |
| 1726 | } | 1922 | } |
| @@ -1745,7 +1941,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) | |||
| 1745 | if (!clk || !nb) | 1941 | if (!clk || !nb) |
| 1746 | return -EINVAL; | 1942 | return -EINVAL; |
| 1747 | 1943 | ||
| 1748 | mutex_lock(&prepare_lock); | 1944 | clk_prepare_lock(); |
| 1749 | 1945 | ||
| 1750 | list_for_each_entry(cn, &clk_notifier_list, node) | 1946 | list_for_each_entry(cn, &clk_notifier_list, node) |
| 1751 | if (cn->clk == clk) | 1947 | if (cn->clk == clk) |
| @@ -1766,7 +1962,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) | |||
| 1766 | ret = -ENOENT; | 1962 | ret = -ENOENT; |
| 1767 | } | 1963 | } |
| 1768 | 1964 | ||
| 1769 | mutex_unlock(&prepare_lock); | 1965 | clk_prepare_unlock(); |
| 1770 | 1966 | ||
| 1771 | return ret; | 1967 | return ret; |
| 1772 | } | 1968 | } |
diff --git a/drivers/clk/mvebu/clk-core.c b/drivers/clk/mvebu/clk-core.c index 69056a7479e8..2628610c1929 100644 --- a/drivers/clk/mvebu/clk-core.c +++ b/drivers/clk/mvebu/clk-core.c | |||
| @@ -156,7 +156,7 @@ static u32 __init armada_370_get_cpu_freq(void __iomem *sar) | |||
| 156 | 156 | ||
| 157 | cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) & | 157 | cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) & |
| 158 | SARL_A370_PCLK_FREQ_OPT_MASK); | 158 | SARL_A370_PCLK_FREQ_OPT_MASK); |
| 159 | if (cpu_freq_select > ARRAY_SIZE(armada_370_cpu_frequencies)) { | 159 | if (cpu_freq_select >= ARRAY_SIZE(armada_370_cpu_frequencies)) { |
| 160 | pr_err("CPU freq select unsuported %d\n", cpu_freq_select); | 160 | pr_err("CPU freq select unsuported %d\n", cpu_freq_select); |
| 161 | cpu_freq = 0; | 161 | cpu_freq = 0; |
| 162 | } else | 162 | } else |
| @@ -278,7 +278,7 @@ static u32 __init armada_xp_get_cpu_freq(void __iomem *sar) | |||
| 278 | cpu_freq_select |= (((readl(sar+4) >> SARH_AXP_PCLK_FREQ_OPT) & | 278 | cpu_freq_select |= (((readl(sar+4) >> SARH_AXP_PCLK_FREQ_OPT) & |
| 279 | SARH_AXP_PCLK_FREQ_OPT_MASK) | 279 | SARH_AXP_PCLK_FREQ_OPT_MASK) |
| 280 | << SARH_AXP_PCLK_FREQ_OPT_SHIFT); | 280 | << SARH_AXP_PCLK_FREQ_OPT_SHIFT); |
| 281 | if (cpu_freq_select > ARRAY_SIZE(armada_xp_cpu_frequencies)) { | 281 | if (cpu_freq_select >= ARRAY_SIZE(armada_xp_cpu_frequencies)) { |
| 282 | pr_err("CPU freq select unsuported: %d\n", cpu_freq_select); | 282 | pr_err("CPU freq select unsuported: %d\n", cpu_freq_select); |
| 283 | cpu_freq = 0; | 283 | cpu_freq = 0; |
| 284 | } else | 284 | } else |
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index 9dd2551a0a41..b0fbc0715491 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
| 17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include "clk-cpu.h" | ||
| 20 | 19 | ||
| 21 | #define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0 | 20 | #define SYS_CTRL_CLK_DIVIDER_CTRL_OFFSET 0x0 |
| 22 | #define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC | 21 | #define SYS_CTRL_CLK_DIVIDER_VALUE_OFFSET 0xC |
| @@ -173,17 +172,5 @@ clks_out: | |||
| 173 | kfree(cpuclk); | 172 | kfree(cpuclk); |
| 174 | } | 173 | } |
| 175 | 174 | ||
| 176 | static const __initconst struct of_device_id clk_cpu_match[] = { | 175 | CLK_OF_DECLARE(armada_xp_cpu_clock, "marvell,armada-xp-cpu-clock", |
| 177 | { | 176 | of_cpu_clk_setup); |
| 178 | .compatible = "marvell,armada-xp-cpu-clock", | ||
| 179 | .data = of_cpu_clk_setup, | ||
| 180 | }, | ||
| 181 | { | ||
| 182 | /* sentinel */ | ||
| 183 | }, | ||
| 184 | }; | ||
| 185 | |||
| 186 | void __init mvebu_cpu_clk_init(void) | ||
| 187 | { | ||
| 188 | of_clk_init(clk_cpu_match); | ||
| 189 | } | ||
diff --git a/drivers/clk/mvebu/clk-cpu.h b/drivers/clk/mvebu/clk-cpu.h deleted file mode 100644 index 08e2affba4e6..000000000000 --- a/drivers/clk/mvebu/clk-cpu.h +++ /dev/null | |||
| @@ -1,22 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Marvell MVEBU CPU clock handling. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Gregory CLEMENT <gregory.clement@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __MVEBU_CLK_CPU_H | ||
| 14 | #define __MVEBU_CLK_CPU_H | ||
| 15 | |||
| 16 | #ifdef CONFIG_MVEBU_CLK_CPU | ||
| 17 | void __init mvebu_cpu_clk_init(void); | ||
| 18 | #else | ||
| 19 | static inline void mvebu_cpu_clk_init(void) {} | ||
| 20 | #endif | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/drivers/clk/mvebu/clk.c b/drivers/clk/mvebu/clk.c index 855681b8a9dc..29f10fb3006c 100644 --- a/drivers/clk/mvebu/clk.c +++ b/drivers/clk/mvebu/clk.c | |||
| @@ -10,18 +10,14 @@ | |||
| 10 | * warranty of any kind, whether express or implied. | 10 | * warranty of any kind, whether express or implied. |
| 11 | */ | 11 | */ |
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/clk-provider.h> | 13 | #include <linux/clk-provider.h> |
| 15 | #include <linux/of_address.h> | ||
| 16 | #include <linux/clk/mvebu.h> | ||
| 17 | #include <linux/of.h> | 14 | #include <linux/of.h> |
| 18 | #include "clk-core.h" | 15 | #include "clk-core.h" |
| 19 | #include "clk-cpu.h" | ||
| 20 | #include "clk-gating-ctrl.h" | 16 | #include "clk-gating-ctrl.h" |
| 21 | 17 | ||
| 22 | void __init mvebu_clocks_init(void) | 18 | void __init mvebu_clocks_init(void) |
| 23 | { | 19 | { |
| 24 | mvebu_core_clk_init(); | 20 | mvebu_core_clk_init(); |
| 25 | mvebu_gating_clk_init(); | 21 | mvebu_gating_clk_init(); |
| 26 | mvebu_cpu_clk_init(); | 22 | of_clk_init(NULL); |
| 27 | } | 23 | } |
diff --git a/drivers/clk/mxs/clk.c b/drivers/clk/mxs/clk.c index b24d56067c80..5301bce8957b 100644 --- a/drivers/clk/mxs/clk.c +++ b/drivers/clk/mxs/clk.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
| 14 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
| 15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
| 16 | #include "clk.h" | ||
| 16 | 17 | ||
| 17 | DEFINE_SPINLOCK(mxs_lock); | 18 | DEFINE_SPINLOCK(mxs_lock); |
| 18 | 19 | ||
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index 82abea366b78..35e7e2698e10 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c | |||
| @@ -960,47 +960,47 @@ void __init spear1340_clk_init(void) | |||
| 960 | SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock); | 960 | SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock); |
| 961 | clk_register_clkdev(clk, NULL, "d0100000.spdif-in"); | 961 | clk_register_clkdev(clk, NULL, "d0100000.spdif-in"); |
| 962 | 962 | ||
| 963 | clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0, | 963 | clk = clk_register_gate(NULL, "acp_clk", "ahb_clk", 0, |
| 964 | SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0, | 964 | SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0, |
| 965 | &_lock); | 965 | &_lock); |
| 966 | clk_register_clkdev(clk, NULL, "acp_clk"); | 966 | clk_register_clkdev(clk, NULL, "acp_clk"); |
| 967 | 967 | ||
| 968 | clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0, | 968 | clk = clk_register_gate(NULL, "plgpio_clk", "ahb_clk", 0, |
| 969 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0, | 969 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0, |
| 970 | &_lock); | 970 | &_lock); |
| 971 | clk_register_clkdev(clk, NULL, "e2800000.gpio"); | 971 | clk_register_clkdev(clk, NULL, "e2800000.gpio"); |
| 972 | 972 | ||
| 973 | clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0, | 973 | clk = clk_register_gate(NULL, "video_dec_clk", "ahb_clk", 0, |
| 974 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB, | 974 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB, |
| 975 | 0, &_lock); | 975 | 0, &_lock); |
| 976 | clk_register_clkdev(clk, NULL, "video_dec"); | 976 | clk_register_clkdev(clk, NULL, "video_dec"); |
| 977 | 977 | ||
| 978 | clk = clk_register_gate(NULL, "video_enc_clk", "video_enc_mclk", 0, | 978 | clk = clk_register_gate(NULL, "video_enc_clk", "ahb_clk", 0, |
| 979 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB, | 979 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB, |
| 980 | 0, &_lock); | 980 | 0, &_lock); |
| 981 | clk_register_clkdev(clk, NULL, "video_enc"); | 981 | clk_register_clkdev(clk, NULL, "video_enc"); |
| 982 | 982 | ||
| 983 | clk = clk_register_gate(NULL, "video_in_clk", "video_in_mclk", 0, | 983 | clk = clk_register_gate(NULL, "video_in_clk", "ahb_clk", 0, |
| 984 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0, | 984 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0, |
| 985 | &_lock); | 985 | &_lock); |
| 986 | clk_register_clkdev(clk, NULL, "spear_vip"); | 986 | clk_register_clkdev(clk, NULL, "spear_vip"); |
| 987 | 987 | ||
| 988 | clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0, | 988 | clk = clk_register_gate(NULL, "cam0_clk", "ahb_clk", 0, |
| 989 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0, | 989 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0, |
| 990 | &_lock); | 990 | &_lock); |
| 991 | clk_register_clkdev(clk, NULL, "d0200000.cam0"); | 991 | clk_register_clkdev(clk, NULL, "d0200000.cam0"); |
| 992 | 992 | ||
| 993 | clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0, | 993 | clk = clk_register_gate(NULL, "cam1_clk", "ahb_clk", 0, |
| 994 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0, | 994 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0, |
| 995 | &_lock); | 995 | &_lock); |
| 996 | clk_register_clkdev(clk, NULL, "d0300000.cam1"); | 996 | clk_register_clkdev(clk, NULL, "d0300000.cam1"); |
| 997 | 997 | ||
| 998 | clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0, | 998 | clk = clk_register_gate(NULL, "cam2_clk", "ahb_clk", 0, |
| 999 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0, | 999 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0, |
| 1000 | &_lock); | 1000 | &_lock); |
| 1001 | clk_register_clkdev(clk, NULL, "d0400000.cam2"); | 1001 | clk_register_clkdev(clk, NULL, "d0400000.cam2"); |
| 1002 | 1002 | ||
| 1003 | clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0, | 1003 | clk = clk_register_gate(NULL, "cam3_clk", "ahb_clk", 0, |
| 1004 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0, | 1004 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0, |
| 1005 | &_lock); | 1005 | &_lock); |
| 1006 | clk_register_clkdev(clk, NULL, "d0500000.cam3"); | 1006 | clk_register_clkdev(clk, NULL, "d0500000.cam3"); |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile new file mode 100644 index 000000000000..b5bac917612c --- /dev/null +++ b/drivers/clk/sunxi/Makefile | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | # | ||
| 2 | # Makefile for sunxi specific clk | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-y += clk-sunxi.o clk-factors.o | ||
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c new file mode 100644 index 000000000000..88523f91d9b7 --- /dev/null +++ b/drivers/clk/sunxi/clk-factors.c | |||
| @@ -0,0 +1,180 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2013 Emilio López <emilio@elopez.com.ar> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * Adjustable factor-based clock implementation | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/clk-provider.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/string.h> | ||
| 17 | |||
| 18 | #include <linux/delay.h> | ||
| 19 | |||
| 20 | #include "clk-factors.h" | ||
| 21 | |||
| 22 | /* | ||
| 23 | * DOC: basic adjustable factor-based clock that cannot gate | ||
| 24 | * | ||
| 25 | * Traits of this clock: | ||
| 26 | * prepare - clk_prepare only ensures that parents are prepared | ||
| 27 | * enable - clk_enable only ensures that parents are enabled | ||
| 28 | * rate - rate is adjustable. | ||
| 29 | * clk->rate = (parent->rate * N * (K + 1) >> P) / (M + 1) | ||
| 30 | * parent - fixed parent. No clk_set_parent support | ||
| 31 | */ | ||
| 32 | |||
| 33 | struct clk_factors { | ||
| 34 | struct clk_hw hw; | ||
| 35 | void __iomem *reg; | ||
| 36 | struct clk_factors_config *config; | ||
| 37 | void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); | ||
| 38 | spinlock_t *lock; | ||
| 39 | }; | ||
| 40 | |||
| 41 | #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) | ||
| 42 | |||
| 43 | #define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) | ||
| 44 | #define CLRMASK(len, pos) (~(SETMASK(len, pos))) | ||
| 45 | #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) | ||
| 46 | |||
| 47 | #define FACTOR_SET(bit, len, reg, val) \ | ||
| 48 | (((reg) & CLRMASK(len, bit)) | (val << (bit))) | ||
| 49 | |||
| 50 | static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, | ||
| 51 | unsigned long parent_rate) | ||
| 52 | { | ||
| 53 | u8 n = 1, k = 0, p = 0, m = 0; | ||
| 54 | u32 reg; | ||
| 55 | unsigned long rate; | ||
| 56 | struct clk_factors *factors = to_clk_factors(hw); | ||
| 57 | struct clk_factors_config *config = factors->config; | ||
| 58 | |||
| 59 | /* Fetch the register value */ | ||
| 60 | reg = readl(factors->reg); | ||
| 61 | |||
| 62 | /* Get each individual factor if applicable */ | ||
| 63 | if (config->nwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
| 64 | n = FACTOR_GET(config->nshift, config->nwidth, reg); | ||
| 65 | if (config->kwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
| 66 | k = FACTOR_GET(config->kshift, config->kwidth, reg); | ||
| 67 | if (config->mwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
| 68 | m = FACTOR_GET(config->mshift, config->mwidth, reg); | ||
| 69 | if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
| 70 | p = FACTOR_GET(config->pshift, config->pwidth, reg); | ||
| 71 | |||
| 72 | /* Calculate the rate */ | ||
| 73 | rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | ||
| 74 | |||
| 75 | return rate; | ||
| 76 | } | ||
| 77 | |||
| 78 | static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, | ||
| 79 | unsigned long *parent_rate) | ||
| 80 | { | ||
| 81 | struct clk_factors *factors = to_clk_factors(hw); | ||
| 82 | factors->get_factors((u32 *)&rate, (u32)*parent_rate, | ||
| 83 | NULL, NULL, NULL, NULL); | ||
| 84 | |||
| 85 | return rate; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, | ||
| 89 | unsigned long parent_rate) | ||
| 90 | { | ||
| 91 | u8 n, k, m, p; | ||
| 92 | u32 reg; | ||
| 93 | struct clk_factors *factors = to_clk_factors(hw); | ||
| 94 | struct clk_factors_config *config = factors->config; | ||
| 95 | unsigned long flags = 0; | ||
| 96 | |||
| 97 | factors->get_factors((u32 *)&rate, (u32)parent_rate, &n, &k, &m, &p); | ||
| 98 | |||
| 99 | if (factors->lock) | ||
| 100 | spin_lock_irqsave(factors->lock, flags); | ||
| 101 | |||
| 102 | /* Fetch the register value */ | ||
| 103 | reg = readl(factors->reg); | ||
| 104 | |||
| 105 | /* Set up the new factors - macros do not do anything if width is 0 */ | ||
| 106 | reg = FACTOR_SET(config->nshift, config->nwidth, reg, n); | ||
| 107 | reg = FACTOR_SET(config->kshift, config->kwidth, reg, k); | ||
| 108 | reg = FACTOR_SET(config->mshift, config->mwidth, reg, m); | ||
| 109 | reg = FACTOR_SET(config->pshift, config->pwidth, reg, p); | ||
| 110 | |||
| 111 | /* Apply them now */ | ||
| 112 | writel(reg, factors->reg); | ||
| 113 | |||
| 114 | /* delay 500us so pll stabilizes */ | ||
| 115 | __delay((rate >> 20) * 500 / 2); | ||
| 116 | |||
| 117 | if (factors->lock) | ||
| 118 | spin_unlock_irqrestore(factors->lock, flags); | ||
| 119 | |||
| 120 | return 0; | ||
| 121 | } | ||
| 122 | |||
| 123 | static const struct clk_ops clk_factors_ops = { | ||
| 124 | .recalc_rate = clk_factors_recalc_rate, | ||
| 125 | .round_rate = clk_factors_round_rate, | ||
| 126 | .set_rate = clk_factors_set_rate, | ||
| 127 | }; | ||
| 128 | |||
| 129 | /** | ||
| 130 | * clk_register_factors - register a factors clock with | ||
| 131 | * the clock framework | ||
| 132 | * @dev: device registering this clock | ||
| 133 | * @name: name of this clock | ||
| 134 | * @parent_name: name of clock's parent | ||
| 135 | * @flags: framework-specific flags | ||
| 136 | * @reg: register address to adjust factors | ||
| 137 | * @config: shift and width of factors n, k, m and p | ||
| 138 | * @get_factors: function to calculate the factors for a given frequency | ||
| 139 | * @lock: shared register lock for this clock | ||
| 140 | */ | ||
| 141 | struct clk *clk_register_factors(struct device *dev, const char *name, | ||
| 142 | const char *parent_name, | ||
| 143 | unsigned long flags, void __iomem *reg, | ||
| 144 | struct clk_factors_config *config, | ||
| 145 | void (*get_factors)(u32 *rate, u32 parent, | ||
| 146 | u8 *n, u8 *k, u8 *m, u8 *p), | ||
| 147 | spinlock_t *lock) | ||
| 148 | { | ||
| 149 | struct clk_factors *factors; | ||
| 150 | struct clk *clk; | ||
| 151 | struct clk_init_data init; | ||
| 152 | |||
| 153 | /* allocate the factors */ | ||
| 154 | factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); | ||
| 155 | if (!factors) { | ||
| 156 | pr_err("%s: could not allocate factors clk\n", __func__); | ||
| 157 | return ERR_PTR(-ENOMEM); | ||
| 158 | } | ||
| 159 | |||
| 160 | init.name = name; | ||
| 161 | init.ops = &clk_factors_ops; | ||
| 162 | init.flags = flags; | ||
| 163 | init.parent_names = (parent_name ? &parent_name : NULL); | ||
| 164 | init.num_parents = (parent_name ? 1 : 0); | ||
| 165 | |||
| 166 | /* struct clk_factors assignments */ | ||
| 167 | factors->reg = reg; | ||
| 168 | factors->config = config; | ||
| 169 | factors->lock = lock; | ||
| 170 | factors->hw.init = &init; | ||
| 171 | factors->get_factors = get_factors; | ||
| 172 | |||
| 173 | /* register the clock */ | ||
| 174 | clk = clk_register(dev, &factors->hw); | ||
| 175 | |||
| 176 | if (IS_ERR(clk)) | ||
| 177 | kfree(factors); | ||
| 178 | |||
| 179 | return clk; | ||
| 180 | } | ||
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h new file mode 100644 index 000000000000..f49851cc4380 --- /dev/null +++ b/drivers/clk/sunxi/clk-factors.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #ifndef __MACH_SUNXI_CLK_FACTORS_H | ||
| 2 | #define __MACH_SUNXI_CLK_FACTORS_H | ||
| 3 | |||
| 4 | #include <linux/clk-provider.h> | ||
| 5 | #include <linux/clkdev.h> | ||
| 6 | |||
| 7 | #define SUNXI_FACTORS_NOT_APPLICABLE (0) | ||
| 8 | |||
| 9 | struct clk_factors_config { | ||
| 10 | u8 nshift; | ||
| 11 | u8 nwidth; | ||
| 12 | u8 kshift; | ||
| 13 | u8 kwidth; | ||
| 14 | u8 mshift; | ||
| 15 | u8 mwidth; | ||
| 16 | u8 pshift; | ||
| 17 | u8 pwidth; | ||
| 18 | }; | ||
| 19 | |||
| 20 | struct clk *clk_register_factors(struct device *dev, const char *name, | ||
| 21 | const char *parent_name, | ||
| 22 | unsigned long flags, void __iomem *reg, | ||
| 23 | struct clk_factors_config *config, | ||
| 24 | void (*get_factors) (u32 *rate, u32 parent_rate, | ||
| 25 | u8 *n, u8 *k, u8 *m, u8 *p), | ||
| 26 | spinlock_t *lock); | ||
| 27 | #endif | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c new file mode 100644 index 000000000000..8492ad1d5360 --- /dev/null +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
| @@ -0,0 +1,469 @@ | |||
| 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/clk/sunxi.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/of_address.h> | ||
| 22 | |||
| 23 | #include "clk-factors.h" | ||
| 24 | |||
| 25 | static DEFINE_SPINLOCK(clk_lock); | ||
| 26 | |||
| 27 | /** | ||
| 28 | * sunxi_osc_clk_setup() - Setup function for gatable oscillator | ||
| 29 | */ | ||
| 30 | |||
| 31 | #define SUNXI_OSC24M_GATE 0 | ||
| 32 | |||
| 33 | static void __init sunxi_osc_clk_setup(struct device_node *node) | ||
| 34 | { | ||
| 35 | struct clk *clk; | ||
| 36 | struct clk_fixed_rate *fixed; | ||
| 37 | struct clk_gate *gate; | ||
| 38 | const char *clk_name = node->name; | ||
| 39 | u32 rate; | ||
| 40 | |||
| 41 | /* allocate fixed-rate and gate clock structs */ | ||
| 42 | fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); | ||
| 43 | if (!fixed) | ||
| 44 | return; | ||
| 45 | gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); | ||
| 46 | if (!gate) { | ||
| 47 | kfree(fixed); | ||
| 48 | return; | ||
| 49 | } | ||
| 50 | |||
| 51 | if (of_property_read_u32(node, "clock-frequency", &rate)) | ||
| 52 | return; | ||
| 53 | |||
| 54 | /* set up gate and fixed rate properties */ | ||
| 55 | gate->reg = of_iomap(node, 0); | ||
| 56 | gate->bit_idx = SUNXI_OSC24M_GATE; | ||
| 57 | gate->lock = &clk_lock; | ||
| 58 | fixed->fixed_rate = rate; | ||
| 59 | |||
| 60 | clk = clk_register_composite(NULL, clk_name, | ||
| 61 | NULL, 0, | ||
| 62 | NULL, NULL, | ||
| 63 | &fixed->hw, &clk_fixed_rate_ops, | ||
| 64 | &gate->hw, &clk_gate_ops, | ||
| 65 | CLK_IS_ROOT); | ||
| 66 | |||
| 67 | if (clk) { | ||
| 68 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 69 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 70 | } | ||
| 71 | } | ||
| 72 | |||
| 73 | |||
| 74 | |||
| 75 | /** | ||
| 76 | * sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1 | ||
| 77 | * PLL1 rate is calculated as follows | ||
| 78 | * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | ||
| 79 | * parent_rate is always 24Mhz | ||
| 80 | */ | ||
| 81 | |||
| 82 | static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate, | ||
| 83 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
| 84 | { | ||
| 85 | u8 div; | ||
| 86 | |||
| 87 | /* Normalize value to a 6M multiple */ | ||
| 88 | div = *freq / 6000000; | ||
| 89 | *freq = 6000000 * div; | ||
| 90 | |||
| 91 | /* we were called to round the frequency, we can now return */ | ||
| 92 | if (n == NULL) | ||
| 93 | return; | ||
| 94 | |||
| 95 | /* m is always zero for pll1 */ | ||
| 96 | *m = 0; | ||
| 97 | |||
| 98 | /* k is 1 only on these cases */ | ||
| 99 | if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000) | ||
| 100 | *k = 1; | ||
| 101 | else | ||
| 102 | *k = 0; | ||
| 103 | |||
| 104 | /* p will be 3 for divs under 10 */ | ||
| 105 | if (div < 10) | ||
| 106 | *p = 3; | ||
| 107 | |||
| 108 | /* p will be 2 for divs between 10 - 20 and odd divs under 32 */ | ||
| 109 | else if (div < 20 || (div < 32 && (div & 1))) | ||
| 110 | *p = 2; | ||
| 111 | |||
| 112 | /* p will be 1 for even divs under 32, divs under 40 and odd pairs | ||
| 113 | * of divs between 40-62 */ | ||
| 114 | else if (div < 40 || (div < 64 && (div & 2))) | ||
| 115 | *p = 1; | ||
| 116 | |||
| 117 | /* any other entries have p = 0 */ | ||
| 118 | else | ||
| 119 | *p = 0; | ||
| 120 | |||
| 121 | /* calculate a suitable n based on k and p */ | ||
| 122 | div <<= *p; | ||
| 123 | div /= (*k + 1); | ||
| 124 | *n = div / 4; | ||
| 125 | } | ||
| 126 | |||
| 127 | |||
| 128 | |||
| 129 | /** | ||
| 130 | * sunxi_get_apb1_factors() - calculates m, p factors for APB1 | ||
| 131 | * APB1 rate is calculated as follows | ||
| 132 | * rate = (parent_rate >> p) / (m + 1); | ||
| 133 | */ | ||
| 134 | |||
| 135 | static void sunxi_get_apb1_factors(u32 *freq, u32 parent_rate, | ||
| 136 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
| 137 | { | ||
| 138 | u8 calcm, calcp; | ||
| 139 | |||
| 140 | if (parent_rate < *freq) | ||
| 141 | *freq = parent_rate; | ||
| 142 | |||
| 143 | parent_rate = (parent_rate + (*freq - 1)) / *freq; | ||
| 144 | |||
| 145 | /* Invalid rate! */ | ||
| 146 | if (parent_rate > 32) | ||
| 147 | return; | ||
| 148 | |||
| 149 | if (parent_rate <= 4) | ||
| 150 | calcp = 0; | ||
| 151 | else if (parent_rate <= 8) | ||
| 152 | calcp = 1; | ||
| 153 | else if (parent_rate <= 16) | ||
| 154 | calcp = 2; | ||
| 155 | else | ||
| 156 | calcp = 3; | ||
| 157 | |||
| 158 | calcm = (parent_rate >> calcp) - 1; | ||
| 159 | |||
| 160 | *freq = (parent_rate >> calcp) / (calcm + 1); | ||
| 161 | |||
| 162 | /* we were called to round the frequency, we can now return */ | ||
| 163 | if (n == NULL) | ||
| 164 | return; | ||
| 165 | |||
| 166 | *m = calcm; | ||
| 167 | *p = calcp; | ||
| 168 | } | ||
| 169 | |||
| 170 | |||
| 171 | |||
| 172 | /** | ||
| 173 | * sunxi_factors_clk_setup() - Setup function for factor clocks | ||
| 174 | */ | ||
| 175 | |||
| 176 | struct factors_data { | ||
| 177 | struct clk_factors_config *table; | ||
| 178 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); | ||
| 179 | }; | ||
| 180 | |||
| 181 | static struct clk_factors_config pll1_config = { | ||
| 182 | .nshift = 8, | ||
| 183 | .nwidth = 5, | ||
| 184 | .kshift = 4, | ||
| 185 | .kwidth = 2, | ||
| 186 | .mshift = 0, | ||
| 187 | .mwidth = 2, | ||
| 188 | .pshift = 16, | ||
| 189 | .pwidth = 2, | ||
| 190 | }; | ||
| 191 | |||
| 192 | static struct clk_factors_config apb1_config = { | ||
| 193 | .mshift = 0, | ||
| 194 | .mwidth = 5, | ||
| 195 | .pshift = 16, | ||
| 196 | .pwidth = 2, | ||
| 197 | }; | ||
| 198 | |||
| 199 | static const __initconst struct factors_data pll1_data = { | ||
| 200 | .table = &pll1_config, | ||
| 201 | .getter = sunxi_get_pll1_factors, | ||
| 202 | }; | ||
| 203 | |||
| 204 | static const __initconst struct factors_data apb1_data = { | ||
| 205 | .table = &apb1_config, | ||
| 206 | .getter = sunxi_get_apb1_factors, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static void __init sunxi_factors_clk_setup(struct device_node *node, | ||
| 210 | struct factors_data *data) | ||
| 211 | { | ||
| 212 | struct clk *clk; | ||
| 213 | const char *clk_name = node->name; | ||
| 214 | const char *parent; | ||
| 215 | void *reg; | ||
| 216 | |||
| 217 | reg = of_iomap(node, 0); | ||
| 218 | |||
| 219 | parent = of_clk_get_parent_name(node, 0); | ||
| 220 | |||
| 221 | clk = clk_register_factors(NULL, clk_name, parent, 0, reg, | ||
| 222 | data->table, data->getter, &clk_lock); | ||
| 223 | |||
| 224 | if (clk) { | ||
| 225 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 226 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 230 | |||
| 231 | |||
| 232 | /** | ||
| 233 | * sunxi_mux_clk_setup() - Setup function for muxes | ||
| 234 | */ | ||
| 235 | |||
| 236 | #define SUNXI_MUX_GATE_WIDTH 2 | ||
| 237 | |||
| 238 | struct mux_data { | ||
| 239 | u8 shift; | ||
| 240 | }; | ||
| 241 | |||
| 242 | static const __initconst struct mux_data cpu_data = { | ||
| 243 | .shift = 16, | ||
| 244 | }; | ||
| 245 | |||
| 246 | static const __initconst struct mux_data apb1_mux_data = { | ||
| 247 | .shift = 24, | ||
| 248 | }; | ||
| 249 | |||
| 250 | static void __init sunxi_mux_clk_setup(struct device_node *node, | ||
| 251 | struct mux_data *data) | ||
| 252 | { | ||
| 253 | struct clk *clk; | ||
| 254 | const char *clk_name = node->name; | ||
| 255 | const char *parents[5]; | ||
| 256 | void *reg; | ||
| 257 | int i = 0; | ||
| 258 | |||
| 259 | reg = of_iomap(node, 0); | ||
| 260 | |||
| 261 | while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | ||
| 262 | i++; | ||
| 263 | |||
| 264 | clk = clk_register_mux(NULL, clk_name, parents, i, 0, reg, | ||
| 265 | data->shift, SUNXI_MUX_GATE_WIDTH, | ||
| 266 | 0, &clk_lock); | ||
| 267 | |||
| 268 | if (clk) { | ||
| 269 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 270 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | |||
| 275 | |||
| 276 | /** | ||
| 277 | * sunxi_divider_clk_setup() - Setup function for simple divider clocks | ||
| 278 | */ | ||
| 279 | |||
| 280 | #define SUNXI_DIVISOR_WIDTH 2 | ||
| 281 | |||
| 282 | struct div_data { | ||
| 283 | u8 shift; | ||
| 284 | u8 pow; | ||
| 285 | }; | ||
| 286 | |||
| 287 | static const __initconst struct div_data axi_data = { | ||
| 288 | .shift = 0, | ||
| 289 | .pow = 0, | ||
| 290 | }; | ||
| 291 | |||
| 292 | static const __initconst struct div_data ahb_data = { | ||
| 293 | .shift = 4, | ||
| 294 | .pow = 1, | ||
| 295 | }; | ||
| 296 | |||
| 297 | static const __initconst struct div_data apb0_data = { | ||
| 298 | .shift = 8, | ||
| 299 | .pow = 1, | ||
| 300 | }; | ||
| 301 | |||
| 302 | static void __init sunxi_divider_clk_setup(struct device_node *node, | ||
| 303 | struct div_data *data) | ||
| 304 | { | ||
| 305 | struct clk *clk; | ||
| 306 | const char *clk_name = node->name; | ||
| 307 | const char *clk_parent; | ||
| 308 | void *reg; | ||
| 309 | |||
| 310 | reg = of_iomap(node, 0); | ||
| 311 | |||
| 312 | clk_parent = of_clk_get_parent_name(node, 0); | ||
| 313 | |||
| 314 | clk = clk_register_divider(NULL, clk_name, clk_parent, 0, | ||
| 315 | reg, data->shift, SUNXI_DIVISOR_WIDTH, | ||
| 316 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, | ||
| 317 | &clk_lock); | ||
| 318 | if (clk) { | ||
| 319 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
| 320 | clk_register_clkdev(clk, clk_name, NULL); | ||
| 321 | } | ||
| 322 | } | ||
| 323 | |||
| 324 | |||
| 325 | |||
| 326 | /** | ||
| 327 | * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks | ||
| 328 | */ | ||
| 329 | |||
| 330 | #define SUNXI_GATES_MAX_SIZE 64 | ||
| 331 | |||
| 332 | struct gates_data { | ||
| 333 | DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); | ||
| 334 | }; | ||
| 335 | |||
| 336 | static const __initconst struct gates_data axi_gates_data = { | ||
| 337 | .mask = {1}, | ||
| 338 | }; | ||
| 339 | |||
| 340 | static const __initconst struct gates_data ahb_gates_data = { | ||
| 341 | .mask = {0x7F77FFF, 0x14FB3F}, | ||
| 342 | }; | ||
| 343 | |||
| 344 | static const __initconst struct gates_data apb0_gates_data = { | ||
| 345 | .mask = {0x4EF}, | ||
| 346 | }; | ||
| 347 | |||
| 348 | static const __initconst struct gates_data apb1_gates_data = { | ||
| 349 | .mask = {0xFF00F7}, | ||
| 350 | }; | ||
| 351 | |||
| 352 | static void __init sunxi_gates_clk_setup(struct device_node *node, | ||
| 353 | struct gates_data *data) | ||
| 354 | { | ||
| 355 | struct clk_onecell_data *clk_data; | ||
| 356 | const char *clk_parent; | ||
| 357 | const char *clk_name; | ||
| 358 | void *reg; | ||
| 359 | int qty; | ||
| 360 | int i = 0; | ||
| 361 | int j = 0; | ||
| 362 | int ignore; | ||
| 363 | |||
| 364 | reg = of_iomap(node, 0); | ||
| 365 | |||
| 366 | clk_parent = of_clk_get_parent_name(node, 0); | ||
| 367 | |||
| 368 | /* Worst-case size approximation and memory allocation */ | ||
| 369 | qty = find_last_bit(data->mask, SUNXI_GATES_MAX_SIZE); | ||
| 370 | clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL); | ||
| 371 | if (!clk_data) | ||
| 372 | return; | ||
| 373 | clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL); | ||
| 374 | if (!clk_data->clks) { | ||
| 375 | kfree(clk_data); | ||
| 376 | return; | ||
| 377 | } | ||
| 378 | |||
| 379 | for_each_set_bit(i, data->mask, SUNXI_GATES_MAX_SIZE) { | ||
| 380 | of_property_read_string_index(node, "clock-output-names", | ||
| 381 | j, &clk_name); | ||
| 382 | |||
| 383 | /* No driver claims this clock, but it should remain gated */ | ||
| 384 | ignore = !strcmp("ahb_sdram", clk_name) ? CLK_IGNORE_UNUSED : 0; | ||
| 385 | |||
| 386 | clk_data->clks[i] = clk_register_gate(NULL, clk_name, | ||
| 387 | clk_parent, ignore, | ||
| 388 | reg + 4 * (i/32), i % 32, | ||
| 389 | 0, &clk_lock); | ||
| 390 | WARN_ON(IS_ERR(clk_data->clks[i])); | ||
| 391 | |||
| 392 | j++; | ||
| 393 | } | ||
| 394 | |||
| 395 | /* Adjust to the real max */ | ||
| 396 | clk_data->clk_num = i; | ||
| 397 | |||
| 398 | of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | ||
| 399 | } | ||
| 400 | |||
| 401 | /* Matches for of_clk_init */ | ||
| 402 | static const __initconst struct of_device_id clk_match[] = { | ||
| 403 | {.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,}, | ||
| 404 | {} | ||
| 405 | }; | ||
| 406 | |||
| 407 | /* Matches for factors clocks */ | ||
| 408 | static const __initconst struct of_device_id clk_factors_match[] = { | ||
| 409 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,}, | ||
| 410 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &apb1_data,}, | ||
| 411 | {} | ||
| 412 | }; | ||
| 413 | |||
| 414 | /* Matches for divider clocks */ | ||
| 415 | static const __initconst struct of_device_id clk_div_match[] = { | ||
| 416 | {.compatible = "allwinner,sun4i-axi-clk", .data = &axi_data,}, | ||
| 417 | {.compatible = "allwinner,sun4i-ahb-clk", .data = &ahb_data,}, | ||
| 418 | {.compatible = "allwinner,sun4i-apb0-clk", .data = &apb0_data,}, | ||
| 419 | {} | ||
| 420 | }; | ||
| 421 | |||
| 422 | /* Matches for mux clocks */ | ||
| 423 | static const __initconst struct of_device_id clk_mux_match[] = { | ||
| 424 | {.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_data,}, | ||
| 425 | {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,}, | ||
| 426 | {} | ||
| 427 | }; | ||
| 428 | |||
| 429 | /* Matches for gate clocks */ | ||
| 430 | static const __initconst struct of_device_id clk_gates_match[] = { | ||
| 431 | {.compatible = "allwinner,sun4i-axi-gates-clk", .data = &axi_gates_data,}, | ||
| 432 | {.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &ahb_gates_data,}, | ||
| 433 | {.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &apb0_gates_data,}, | ||
| 434 | {.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &apb1_gates_data,}, | ||
| 435 | {} | ||
| 436 | }; | ||
| 437 | |||
| 438 | static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match, | ||
| 439 | void *function) | ||
| 440 | { | ||
| 441 | struct device_node *np; | ||
| 442 | const struct div_data *data; | ||
| 443 | const struct of_device_id *match; | ||
| 444 | void (*setup_function)(struct device_node *, const void *) = function; | ||
| 445 | |||
| 446 | for_each_matching_node(np, clk_match) { | ||
| 447 | match = of_match_node(clk_match, np); | ||
| 448 | data = match->data; | ||
| 449 | setup_function(np, data); | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | void __init sunxi_init_clocks(void) | ||
| 454 | { | ||
| 455 | /* Register all the simple sunxi clocks on DT */ | ||
| 456 | of_clk_init(clk_match); | ||
| 457 | |||
| 458 | /* Register factor clocks */ | ||
| 459 | of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); | ||
| 460 | |||
| 461 | /* Register divider clocks */ | ||
| 462 | of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup); | ||
| 463 | |||
| 464 | /* Register mux clocks */ | ||
| 465 | of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup); | ||
| 466 | |||
| 467 | /* Register gate clocks */ | ||
| 468 | of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); | ||
| 469 | } | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 0744731c6229..a09d7dcaf183 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
| @@ -355,15 +355,16 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, | |||
| 355 | struct tegra_clk_periph *periph, void __iomem *clk_base, | 355 | struct tegra_clk_periph *periph, void __iomem *clk_base, |
| 356 | u32 offset); | 356 | u32 offset); |
| 357 | 357 | ||
| 358 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags, \ | 358 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \ |
| 359 | _div_shift, _div_width, _div_frac_width, \ | 359 | _div_shift, _div_width, _div_frac_width, \ |
| 360 | _div_flags, _clk_num, _enb_refcnt, _regs, \ | 360 | _div_flags, _clk_num, _enb_refcnt, _regs, \ |
| 361 | _gate_flags) \ | 361 | _gate_flags, _table) \ |
| 362 | { \ | 362 | { \ |
| 363 | .mux = { \ | 363 | .mux = { \ |
| 364 | .flags = _mux_flags, \ | 364 | .flags = _mux_flags, \ |
| 365 | .shift = _mux_shift, \ | 365 | .shift = _mux_shift, \ |
| 366 | .width = _mux_width, \ | 366 | .mask = _mux_mask, \ |
| 367 | .table = _table, \ | ||
| 367 | }, \ | 368 | }, \ |
| 368 | .divider = { \ | 369 | .divider = { \ |
| 369 | .flags = _div_flags, \ | 370 | .flags = _div_flags, \ |
| @@ -393,26 +394,36 @@ struct tegra_periph_init_data { | |||
| 393 | const char *dev_id; | 394 | const char *dev_id; |
| 394 | }; | 395 | }; |
| 395 | 396 | ||
| 396 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \ | 397 | #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ |
| 397 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | 398 | _mux_shift, _mux_mask, _mux_flags, _div_shift, \ |
| 398 | _div_width, _div_frac_width, _div_flags, _regs, \ | 399 | _div_width, _div_frac_width, _div_flags, _regs, \ |
| 399 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | 400 | _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table) \ |
| 400 | { \ | 401 | { \ |
| 401 | .name = _name, \ | 402 | .name = _name, \ |
| 402 | .clk_id = _clk_id, \ | 403 | .clk_id = _clk_id, \ |
| 403 | .parent_names = _parent_names, \ | 404 | .parent_names = _parent_names, \ |
| 404 | .num_parents = ARRAY_SIZE(_parent_names), \ | 405 | .num_parents = ARRAY_SIZE(_parent_names), \ |
| 405 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width, \ | 406 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \ |
| 406 | _mux_flags, _div_shift, \ | 407 | _mux_flags, _div_shift, \ |
| 407 | _div_width, _div_frac_width, \ | 408 | _div_width, _div_frac_width, \ |
| 408 | _div_flags, _clk_num, \ | 409 | _div_flags, _clk_num, \ |
| 409 | _enb_refcnt, _regs, \ | 410 | _enb_refcnt, _regs, \ |
| 410 | _gate_flags), \ | 411 | _gate_flags, _table), \ |
| 411 | .offset = _offset, \ | 412 | .offset = _offset, \ |
| 412 | .con_id = _con_id, \ | 413 | .con_id = _con_id, \ |
| 413 | .dev_id = _dev_id, \ | 414 | .dev_id = _dev_id, \ |
| 414 | } | 415 | } |
| 415 | 416 | ||
| 417 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
| 418 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | ||
| 419 | _div_width, _div_frac_width, _div_flags, _regs, \ | ||
| 420 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | ||
| 421 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
| 422 | _mux_shift, BIT(_mux_width) - 1, _mux_flags, \ | ||
| 423 | _div_shift, _div_width, _div_frac_width, _div_flags, \ | ||
| 424 | _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\ | ||
| 425 | NULL) | ||
| 426 | |||
| 416 | /** | 427 | /** |
| 417 | * struct clk_super_mux - super clock | 428 | * struct clk_super_mux - super clock |
| 418 | * | 429 | * |
diff --git a/drivers/clk/ux500/Makefile b/drivers/clk/ux500/Makefile index bcc0c11a507c..c6a806ed0e8c 100644 --- a/drivers/clk/ux500/Makefile +++ b/drivers/clk/ux500/Makefile | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | # Clock types | 5 | # Clock types |
| 6 | obj-y += clk-prcc.o | 6 | obj-y += clk-prcc.o |
| 7 | obj-y += clk-prcmu.o | 7 | obj-y += clk-prcmu.o |
| 8 | obj-y += clk-sysctrl.o | ||
| 8 | 9 | ||
| 9 | # Clock definitions | 10 | # Clock definitions |
| 10 | obj-y += u8500_clk.o | 11 | obj-y += u8500_clk.o |
diff --git a/drivers/clk/ux500/abx500-clk.c b/drivers/clk/ux500/abx500-clk.c index 9f7400d74fa7..a0fca004abc1 100644 --- a/drivers/clk/ux500/abx500-clk.c +++ b/drivers/clk/ux500/abx500-clk.c | |||
| @@ -12,13 +12,78 @@ | |||
| 12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
| 13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
| 14 | #include <linux/mfd/abx500/ab8500.h> | 14 | #include <linux/mfd/abx500/ab8500.h> |
| 15 | 15 | #include <linux/mfd/abx500/ab8500-sysctrl.h> | |
| 16 | /* TODO: Add clock implementations here */ | 16 | #include <linux/clk.h> |
| 17 | 17 | #include <linux/clkdev.h> | |
| 18 | #include <linux/clk-provider.h> | ||
| 19 | #include <linux/mfd/dbx500-prcmu.h> | ||
| 20 | #include "clk.h" | ||
| 18 | 21 | ||
| 19 | /* Clock definitions for ab8500 */ | 22 | /* Clock definitions for ab8500 */ |
| 20 | static int ab8500_reg_clks(struct device *dev) | 23 | static int ab8500_reg_clks(struct device *dev) |
| 21 | { | 24 | { |
| 25 | int ret; | ||
| 26 | struct clk *clk; | ||
| 27 | |||
| 28 | const char *intclk_parents[] = {"ab8500_sysclk", "ulpclk"}; | ||
| 29 | u16 intclk_reg_sel[] = {0 , AB8500_SYSULPCLKCTRL1}; | ||
| 30 | u8 intclk_reg_mask[] = {0 , AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_MASK}; | ||
| 31 | u8 intclk_reg_bits[] = { | ||
| 32 | 0 , | ||
| 33 | (1 << AB8500_SYSULPCLKCTRL1_SYSULPCLKINTSEL_SHIFT) | ||
| 34 | }; | ||
| 35 | |||
| 36 | dev_info(dev, "register clocks for ab850x\n"); | ||
| 37 | |||
| 38 | /* Enable SWAT */ | ||
| 39 | ret = ab8500_sysctrl_set(AB8500_SWATCTRL, AB8500_SWATCTRL_SWATENABLE); | ||
| 40 | if (ret) | ||
| 41 | return ret; | ||
| 42 | |||
| 43 | /* ab8500_sysclk */ | ||
| 44 | clk = clk_reg_prcmu_gate("ab8500_sysclk", NULL, PRCMU_SYSCLK, | ||
| 45 | CLK_IS_ROOT); | ||
| 46 | clk_register_clkdev(clk, "sysclk", "ab8500-usb.0"); | ||
| 47 | clk_register_clkdev(clk, "sysclk", "ab-iddet.0"); | ||
| 48 | clk_register_clkdev(clk, "sysclk", "ab85xx-codec.0"); | ||
| 49 | clk_register_clkdev(clk, "sysclk", "shrm_bus"); | ||
| 50 | |||
| 51 | /* ab8500_sysclk2 */ | ||
| 52 | clk = clk_reg_sysctrl_gate(dev , "ab8500_sysclk2", "ab8500_sysclk", | ||
| 53 | AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ, | ||
| 54 | AB8500_SYSULPCLKCTRL1_SYSCLKBUF2REQ, 0, 0); | ||
| 55 | clk_register_clkdev(clk, "sysclk", "0-0070"); | ||
| 56 | |||
| 57 | /* ab8500_sysclk3 */ | ||
| 58 | clk = clk_reg_sysctrl_gate(dev , "ab8500_sysclk3", "ab8500_sysclk", | ||
| 59 | AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ, | ||
| 60 | AB8500_SYSULPCLKCTRL1_SYSCLKBUF3REQ, 0, 0); | ||
| 61 | clk_register_clkdev(clk, "sysclk", "cg1960_core.0"); | ||
| 62 | |||
| 63 | /* ab8500_sysclk4 */ | ||
| 64 | clk = clk_reg_sysctrl_gate(dev , "ab8500_sysclk4", "ab8500_sysclk", | ||
| 65 | AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ, | ||
| 66 | AB8500_SYSULPCLKCTRL1_SYSCLKBUF4REQ, 0, 0); | ||
| 67 | |||
| 68 | /* ab_ulpclk */ | ||
| 69 | clk = clk_reg_sysctrl_gate_fixed_rate(dev, "ulpclk", NULL, | ||
| 70 | AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_ULPCLKREQ, | ||
| 71 | AB8500_SYSULPCLKCTRL1_ULPCLKREQ, | ||
| 72 | 38400000, 9000, CLK_IS_ROOT); | ||
| 73 | clk_register_clkdev(clk, "ulpclk", "ab85xx-codec.0"); | ||
| 74 | |||
| 75 | /* ab8500_intclk */ | ||
| 76 | clk = clk_reg_sysctrl_set_parent(dev , "intclk", intclk_parents, 2, | ||
| 77 | intclk_reg_sel, intclk_reg_mask, intclk_reg_bits, 0); | ||
| 78 | clk_register_clkdev(clk, "intclk", "ab85xx-codec.0"); | ||
| 79 | clk_register_clkdev(clk, NULL, "ab8500-pwm.1"); | ||
| 80 | |||
| 81 | /* ab8500_audioclk */ | ||
| 82 | clk = clk_reg_sysctrl_gate(dev , "audioclk", "intclk", | ||
| 83 | AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_AUDIOCLKENA, | ||
| 84 | AB8500_SYSULPCLKCTRL1_AUDIOCLKENA, 0, 0); | ||
| 85 | clk_register_clkdev(clk, "audioclk", "ab85xx-codec.0"); | ||
| 86 | |||
| 22 | return 0; | 87 | return 0; |
| 23 | } | 88 | } |
| 24 | 89 | ||
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index 74faa7e3cf59..293a28854417 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c | |||
| @@ -20,15 +20,23 @@ | |||
| 20 | struct clk_prcmu { | 20 | struct clk_prcmu { |
| 21 | struct clk_hw hw; | 21 | struct clk_hw hw; |
| 22 | u8 cg_sel; | 22 | u8 cg_sel; |
| 23 | int is_prepared; | ||
| 23 | int is_enabled; | 24 | int is_enabled; |
| 25 | int opp_requested; | ||
| 24 | }; | 26 | }; |
| 25 | 27 | ||
| 26 | /* PRCMU clock operations. */ | 28 | /* PRCMU clock operations. */ |
| 27 | 29 | ||
| 28 | static int clk_prcmu_prepare(struct clk_hw *hw) | 30 | static int clk_prcmu_prepare(struct clk_hw *hw) |
| 29 | { | 31 | { |
| 32 | int ret; | ||
| 30 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 33 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
| 31 | return prcmu_request_clock(clk->cg_sel, true); | 34 | |
| 35 | ret = prcmu_request_clock(clk->cg_sel, true); | ||
| 36 | if (!ret) | ||
| 37 | clk->is_prepared = 1; | ||
| 38 | |||
| 39 | return ret;; | ||
| 32 | } | 40 | } |
| 33 | 41 | ||
| 34 | static void clk_prcmu_unprepare(struct clk_hw *hw) | 42 | static void clk_prcmu_unprepare(struct clk_hw *hw) |
| @@ -36,7 +44,15 @@ static void clk_prcmu_unprepare(struct clk_hw *hw) | |||
| 36 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 44 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
| 37 | if (prcmu_request_clock(clk->cg_sel, false)) | 45 | if (prcmu_request_clock(clk->cg_sel, false)) |
| 38 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 46 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
| 39 | hw->init->name); | 47 | __clk_get_name(hw->clk)); |
| 48 | else | ||
| 49 | clk->is_prepared = 0; | ||
| 50 | } | ||
| 51 | |||
| 52 | static int clk_prcmu_is_prepared(struct clk_hw *hw) | ||
| 53 | { | ||
| 54 | struct clk_prcmu *clk = to_clk_prcmu(hw); | ||
| 55 | return clk->is_prepared; | ||
| 40 | } | 56 | } |
| 41 | 57 | ||
| 42 | static int clk_prcmu_enable(struct clk_hw *hw) | 58 | static int clk_prcmu_enable(struct clk_hw *hw) |
| @@ -79,58 +95,52 @@ static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 79 | return prcmu_set_clock_rate(clk->cg_sel, rate); | 95 | return prcmu_set_clock_rate(clk->cg_sel, rate); |
| 80 | } | 96 | } |
| 81 | 97 | ||
| 82 | static int request_ape_opp100(bool enable) | ||
| 83 | { | ||
| 84 | static int reqs; | ||
| 85 | int err = 0; | ||
| 86 | |||
| 87 | if (enable) { | ||
| 88 | if (!reqs) | ||
| 89 | err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, | ||
| 90 | "clock", 100); | ||
| 91 | if (!err) | ||
| 92 | reqs++; | ||
| 93 | } else { | ||
| 94 | reqs--; | ||
| 95 | if (!reqs) | ||
| 96 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, | ||
| 97 | "clock"); | ||
| 98 | } | ||
| 99 | return err; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int clk_prcmu_opp_prepare(struct clk_hw *hw) | 98 | static int clk_prcmu_opp_prepare(struct clk_hw *hw) |
| 103 | { | 99 | { |
| 104 | int err; | 100 | int err; |
| 105 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 101 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
| 106 | 102 | ||
| 107 | err = request_ape_opp100(true); | 103 | if (!clk->opp_requested) { |
| 108 | if (err) { | 104 | err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, |
| 109 | pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n", | 105 | (char *)__clk_get_name(hw->clk), |
| 110 | __func__, hw->init->name); | 106 | 100); |
| 111 | return err; | 107 | if (err) { |
| 108 | pr_err("clk_prcmu: %s fail req APE OPP for %s.\n", | ||
| 109 | __func__, __clk_get_name(hw->clk)); | ||
| 110 | return err; | ||
| 111 | } | ||
| 112 | clk->opp_requested = 1; | ||
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | err = prcmu_request_clock(clk->cg_sel, true); | 115 | err = prcmu_request_clock(clk->cg_sel, true); |
| 115 | if (err) | 116 | if (err) { |
| 116 | request_ape_opp100(false); | 117 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, |
| 118 | (char *)__clk_get_name(hw->clk)); | ||
| 119 | clk->opp_requested = 0; | ||
| 120 | return err; | ||
| 121 | } | ||
| 117 | 122 | ||
| 118 | return err; | 123 | clk->is_prepared = 1; |
| 124 | return 0; | ||
| 119 | } | 125 | } |
| 120 | 126 | ||
| 121 | static void clk_prcmu_opp_unprepare(struct clk_hw *hw) | 127 | static void clk_prcmu_opp_unprepare(struct clk_hw *hw) |
| 122 | { | 128 | { |
| 123 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 129 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
| 124 | 130 | ||
| 125 | if (prcmu_request_clock(clk->cg_sel, false)) | 131 | if (prcmu_request_clock(clk->cg_sel, false)) { |
| 126 | goto out_error; | 132 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
| 127 | if (request_ape_opp100(false)) | 133 | __clk_get_name(hw->clk)); |
| 128 | goto out_error; | 134 | return; |
| 129 | return; | 135 | } |
| 130 | 136 | ||
| 131 | out_error: | 137 | if (clk->opp_requested) { |
| 132 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 138 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, |
| 133 | hw->init->name); | 139 | (char *)__clk_get_name(hw->clk)); |
| 140 | clk->opp_requested = 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | clk->is_prepared = 0; | ||
| 134 | } | 144 | } |
| 135 | 145 | ||
| 136 | static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) | 146 | static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) |
| @@ -138,38 +148,49 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) | |||
| 138 | int err; | 148 | int err; |
| 139 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 149 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
| 140 | 150 | ||
| 141 | err = prcmu_request_ape_opp_100_voltage(true); | 151 | if (!clk->opp_requested) { |
| 142 | if (err) { | 152 | err = prcmu_request_ape_opp_100_voltage(true); |
| 143 | pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n", | 153 | if (err) { |
| 144 | __func__, hw->init->name); | 154 | pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n", |
| 145 | return err; | 155 | __func__, __clk_get_name(hw->clk)); |
| 156 | return err; | ||
| 157 | } | ||
| 158 | clk->opp_requested = 1; | ||
| 146 | } | 159 | } |
| 147 | 160 | ||
| 148 | err = prcmu_request_clock(clk->cg_sel, true); | 161 | err = prcmu_request_clock(clk->cg_sel, true); |
| 149 | if (err) | 162 | if (err) { |
| 150 | prcmu_request_ape_opp_100_voltage(false); | 163 | prcmu_request_ape_opp_100_voltage(false); |
| 164 | clk->opp_requested = 0; | ||
| 165 | return err; | ||
| 166 | } | ||
| 151 | 167 | ||
| 152 | return err; | 168 | clk->is_prepared = 1; |
| 169 | return 0; | ||
| 153 | } | 170 | } |
| 154 | 171 | ||
| 155 | static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) | 172 | static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) |
| 156 | { | 173 | { |
| 157 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 174 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
| 158 | 175 | ||
| 159 | if (prcmu_request_clock(clk->cg_sel, false)) | 176 | if (prcmu_request_clock(clk->cg_sel, false)) { |
| 160 | goto out_error; | 177 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
| 161 | if (prcmu_request_ape_opp_100_voltage(false)) | 178 | __clk_get_name(hw->clk)); |
| 162 | goto out_error; | 179 | return; |
| 163 | return; | 180 | } |
| 164 | 181 | ||
| 165 | out_error: | 182 | if (clk->opp_requested) { |
| 166 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 183 | prcmu_request_ape_opp_100_voltage(false); |
| 167 | hw->init->name); | 184 | clk->opp_requested = 0; |
| 185 | } | ||
| 186 | |||
| 187 | clk->is_prepared = 0; | ||
| 168 | } | 188 | } |
| 169 | 189 | ||
| 170 | static struct clk_ops clk_prcmu_scalable_ops = { | 190 | static struct clk_ops clk_prcmu_scalable_ops = { |
| 171 | .prepare = clk_prcmu_prepare, | 191 | .prepare = clk_prcmu_prepare, |
| 172 | .unprepare = clk_prcmu_unprepare, | 192 | .unprepare = clk_prcmu_unprepare, |
| 193 | .is_prepared = clk_prcmu_is_prepared, | ||
| 173 | .enable = clk_prcmu_enable, | 194 | .enable = clk_prcmu_enable, |
| 174 | .disable = clk_prcmu_disable, | 195 | .disable = clk_prcmu_disable, |
| 175 | .is_enabled = clk_prcmu_is_enabled, | 196 | .is_enabled = clk_prcmu_is_enabled, |
| @@ -181,6 +202,7 @@ static struct clk_ops clk_prcmu_scalable_ops = { | |||
| 181 | static struct clk_ops clk_prcmu_gate_ops = { | 202 | static struct clk_ops clk_prcmu_gate_ops = { |
| 182 | .prepare = clk_prcmu_prepare, | 203 | .prepare = clk_prcmu_prepare, |
| 183 | .unprepare = clk_prcmu_unprepare, | 204 | .unprepare = clk_prcmu_unprepare, |
| 205 | .is_prepared = clk_prcmu_is_prepared, | ||
| 184 | .enable = clk_prcmu_enable, | 206 | .enable = clk_prcmu_enable, |
| 185 | .disable = clk_prcmu_disable, | 207 | .disable = clk_prcmu_disable, |
| 186 | .is_enabled = clk_prcmu_is_enabled, | 208 | .is_enabled = clk_prcmu_is_enabled, |
| @@ -202,6 +224,7 @@ static struct clk_ops clk_prcmu_rate_ops = { | |||
| 202 | static struct clk_ops clk_prcmu_opp_gate_ops = { | 224 | static struct clk_ops clk_prcmu_opp_gate_ops = { |
| 203 | .prepare = clk_prcmu_opp_prepare, | 225 | .prepare = clk_prcmu_opp_prepare, |
| 204 | .unprepare = clk_prcmu_opp_unprepare, | 226 | .unprepare = clk_prcmu_opp_unprepare, |
| 227 | .is_prepared = clk_prcmu_is_prepared, | ||
| 205 | .enable = clk_prcmu_enable, | 228 | .enable = clk_prcmu_enable, |
| 206 | .disable = clk_prcmu_disable, | 229 | .disable = clk_prcmu_disable, |
| 207 | .is_enabled = clk_prcmu_is_enabled, | 230 | .is_enabled = clk_prcmu_is_enabled, |
| @@ -211,6 +234,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = { | |||
| 211 | static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { | 234 | static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { |
| 212 | .prepare = clk_prcmu_opp_volt_prepare, | 235 | .prepare = clk_prcmu_opp_volt_prepare, |
| 213 | .unprepare = clk_prcmu_opp_volt_unprepare, | 236 | .unprepare = clk_prcmu_opp_volt_unprepare, |
| 237 | .is_prepared = clk_prcmu_is_prepared, | ||
| 214 | .enable = clk_prcmu_enable, | 238 | .enable = clk_prcmu_enable, |
| 215 | .disable = clk_prcmu_disable, | 239 | .disable = clk_prcmu_disable, |
| 216 | .is_enabled = clk_prcmu_is_enabled, | 240 | .is_enabled = clk_prcmu_is_enabled, |
| @@ -242,7 +266,9 @@ static struct clk *clk_reg_prcmu(const char *name, | |||
| 242 | } | 266 | } |
| 243 | 267 | ||
| 244 | clk->cg_sel = cg_sel; | 268 | clk->cg_sel = cg_sel; |
| 269 | clk->is_prepared = 1; | ||
| 245 | clk->is_enabled = 1; | 270 | clk->is_enabled = 1; |
| 271 | clk->opp_requested = 0; | ||
| 246 | /* "rate" can be used for changing the initial frequency */ | 272 | /* "rate" can be used for changing the initial frequency */ |
| 247 | if (rate) | 273 | if (rate) |
| 248 | prcmu_set_clock_rate(cg_sel, rate); | 274 | prcmu_set_clock_rate(cg_sel, rate); |
diff --git a/drivers/clk/ux500/clk-sysctrl.c b/drivers/clk/ux500/clk-sysctrl.c new file mode 100644 index 000000000000..bc7e9bde792b --- /dev/null +++ b/drivers/clk/ux500/clk-sysctrl.c | |||
| @@ -0,0 +1,221 @@ | |||
| 1 | /* | ||
| 2 | * Sysctrl clock implementation for ux500 platform. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2013 ST-Ericsson SA | ||
| 5 | * Author: Ulf Hansson <ulf.hansson@linaro.org> | ||
| 6 | * | ||
| 7 | * License terms: GNU General Public License (GPL) version 2 | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/clk-provider.h> | ||
| 11 | #include <linux/mfd/abx500/ab8500-sysctrl.h> | ||
| 12 | #include <linux/device.h> | ||
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/io.h> | ||
| 16 | #include <linux/err.h> | ||
| 17 | #include "clk.h" | ||
| 18 | |||
| 19 | #define SYSCTRL_MAX_NUM_PARENTS 4 | ||
| 20 | |||
| 21 | #define to_clk_sysctrl(_hw) container_of(_hw, struct clk_sysctrl, hw) | ||
| 22 | |||
| 23 | struct clk_sysctrl { | ||
| 24 | struct clk_hw hw; | ||
| 25 | struct device *dev; | ||
| 26 | u8 parent_index; | ||
| 27 | u16 reg_sel[SYSCTRL_MAX_NUM_PARENTS]; | ||
| 28 | u8 reg_mask[SYSCTRL_MAX_NUM_PARENTS]; | ||
| 29 | u8 reg_bits[SYSCTRL_MAX_NUM_PARENTS]; | ||
| 30 | unsigned long rate; | ||
| 31 | unsigned long enable_delay_us; | ||
| 32 | }; | ||
| 33 | |||
| 34 | /* Sysctrl clock operations. */ | ||
| 35 | |||
| 36 | static int clk_sysctrl_prepare(struct clk_hw *hw) | ||
| 37 | { | ||
| 38 | int ret; | ||
| 39 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); | ||
| 40 | |||
| 41 | ret = ab8500_sysctrl_write(clk->reg_sel[0], clk->reg_mask[0], | ||
| 42 | clk->reg_bits[0]); | ||
| 43 | |||
| 44 | if (!ret && clk->enable_delay_us) | ||
| 45 | usleep_range(clk->enable_delay_us, clk->enable_delay_us); | ||
| 46 | |||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | static void clk_sysctrl_unprepare(struct clk_hw *hw) | ||
| 51 | { | ||
| 52 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); | ||
| 53 | if (ab8500_sysctrl_clear(clk->reg_sel[0], clk->reg_mask[0])) | ||
| 54 | dev_err(clk->dev, "clk_sysctrl: %s fail to clear %s.\n", | ||
| 55 | __func__, __clk_get_name(hw->clk)); | ||
| 56 | } | ||
| 57 | |||
| 58 | static unsigned long clk_sysctrl_recalc_rate(struct clk_hw *hw, | ||
| 59 | unsigned long parent_rate) | ||
| 60 | { | ||
| 61 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); | ||
| 62 | return clk->rate; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int clk_sysctrl_set_parent(struct clk_hw *hw, u8 index) | ||
| 66 | { | ||
| 67 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); | ||
| 68 | u8 old_index = clk->parent_index; | ||
| 69 | int ret = 0; | ||
| 70 | |||
| 71 | if (clk->reg_sel[old_index]) { | ||
| 72 | ret = ab8500_sysctrl_clear(clk->reg_sel[old_index], | ||
| 73 | clk->reg_mask[old_index]); | ||
| 74 | if (ret) | ||
| 75 | return ret; | ||
| 76 | } | ||
| 77 | |||
| 78 | if (clk->reg_sel[index]) { | ||
| 79 | ret = ab8500_sysctrl_write(clk->reg_sel[index], | ||
| 80 | clk->reg_mask[index], | ||
| 81 | clk->reg_bits[index]); | ||
| 82 | if (ret) { | ||
| 83 | if (clk->reg_sel[old_index]) | ||
| 84 | ab8500_sysctrl_write(clk->reg_sel[old_index], | ||
| 85 | clk->reg_mask[old_index], | ||
| 86 | clk->reg_bits[old_index]); | ||
| 87 | return ret; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | clk->parent_index = index; | ||
| 91 | |||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | |||
| 95 | static u8 clk_sysctrl_get_parent(struct clk_hw *hw) | ||
| 96 | { | ||
| 97 | struct clk_sysctrl *clk = to_clk_sysctrl(hw); | ||
| 98 | return clk->parent_index; | ||
| 99 | } | ||
| 100 | |||
| 101 | static struct clk_ops clk_sysctrl_gate_ops = { | ||
| 102 | .prepare = clk_sysctrl_prepare, | ||
| 103 | .unprepare = clk_sysctrl_unprepare, | ||
| 104 | }; | ||
| 105 | |||
| 106 | static struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { | ||
| 107 | .prepare = clk_sysctrl_prepare, | ||
| 108 | .unprepare = clk_sysctrl_unprepare, | ||
| 109 | .recalc_rate = clk_sysctrl_recalc_rate, | ||
| 110 | }; | ||
| 111 | |||
| 112 | static struct clk_ops clk_sysctrl_set_parent_ops = { | ||
| 113 | .set_parent = clk_sysctrl_set_parent, | ||
| 114 | .get_parent = clk_sysctrl_get_parent, | ||
| 115 | }; | ||
| 116 | |||
| 117 | static struct clk *clk_reg_sysctrl(struct device *dev, | ||
| 118 | const char *name, | ||
| 119 | const char **parent_names, | ||
| 120 | u8 num_parents, | ||
| 121 | u16 *reg_sel, | ||
| 122 | u8 *reg_mask, | ||
| 123 | u8 *reg_bits, | ||
| 124 | unsigned long rate, | ||
| 125 | unsigned long enable_delay_us, | ||
| 126 | unsigned long flags, | ||
| 127 | struct clk_ops *clk_sysctrl_ops) | ||
| 128 | { | ||
| 129 | struct clk_sysctrl *clk; | ||
| 130 | struct clk_init_data clk_sysctrl_init; | ||
| 131 | struct clk *clk_reg; | ||
| 132 | int i; | ||
| 133 | |||
| 134 | if (!dev) | ||
| 135 | return ERR_PTR(-EINVAL); | ||
| 136 | |||
| 137 | if (!name || (num_parents > SYSCTRL_MAX_NUM_PARENTS)) { | ||
| 138 | dev_err(dev, "clk_sysctrl: invalid arguments passed\n"); | ||
| 139 | return ERR_PTR(-EINVAL); | ||
| 140 | } | ||
| 141 | |||
| 142 | clk = devm_kzalloc(dev, sizeof(struct clk_sysctrl), GFP_KERNEL); | ||
| 143 | if (!clk) { | ||
| 144 | dev_err(dev, "clk_sysctrl: could not allocate clk\n"); | ||
| 145 | return ERR_PTR(-ENOMEM); | ||
| 146 | } | ||
| 147 | |||
| 148 | for (i = 0; i < num_parents; i++) { | ||
| 149 | clk->reg_sel[i] = reg_sel[i]; | ||
| 150 | clk->reg_bits[i] = reg_bits[i]; | ||
| 151 | clk->reg_mask[i] = reg_mask[i]; | ||
| 152 | } | ||
| 153 | |||
| 154 | clk->parent_index = 0; | ||
| 155 | clk->rate = rate; | ||
| 156 | clk->enable_delay_us = enable_delay_us; | ||
| 157 | clk->dev = dev; | ||
| 158 | |||
| 159 | clk_sysctrl_init.name = name; | ||
| 160 | clk_sysctrl_init.ops = clk_sysctrl_ops; | ||
| 161 | clk_sysctrl_init.flags = flags; | ||
| 162 | clk_sysctrl_init.parent_names = parent_names; | ||
| 163 | clk_sysctrl_init.num_parents = num_parents; | ||
| 164 | clk->hw.init = &clk_sysctrl_init; | ||
| 165 | |||
| 166 | clk_reg = devm_clk_register(clk->dev, &clk->hw); | ||
| 167 | if (IS_ERR(clk_reg)) | ||
| 168 | dev_err(dev, "clk_sysctrl: clk_register failed\n"); | ||
| 169 | |||
| 170 | return clk_reg; | ||
| 171 | } | ||
| 172 | |||
| 173 | struct clk *clk_reg_sysctrl_gate(struct device *dev, | ||
| 174 | const char *name, | ||
| 175 | const char *parent_name, | ||
| 176 | u16 reg_sel, | ||
| 177 | u8 reg_mask, | ||
| 178 | u8 reg_bits, | ||
| 179 | unsigned long enable_delay_us, | ||
| 180 | unsigned long flags) | ||
| 181 | { | ||
| 182 | const char **parent_names = (parent_name ? &parent_name : NULL); | ||
| 183 | u8 num_parents = (parent_name ? 1 : 0); | ||
| 184 | |||
| 185 | return clk_reg_sysctrl(dev, name, parent_names, num_parents, | ||
| 186 | ®_sel, ®_mask, ®_bits, 0, enable_delay_us, | ||
| 187 | flags, &clk_sysctrl_gate_ops); | ||
| 188 | } | ||
| 189 | |||
| 190 | struct clk *clk_reg_sysctrl_gate_fixed_rate(struct device *dev, | ||
| 191 | const char *name, | ||
| 192 | const char *parent_name, | ||
| 193 | u16 reg_sel, | ||
| 194 | u8 reg_mask, | ||
| 195 | u8 reg_bits, | ||
| 196 | unsigned long rate, | ||
| 197 | unsigned long enable_delay_us, | ||
| 198 | unsigned long flags) | ||
| 199 | { | ||
| 200 | const char **parent_names = (parent_name ? &parent_name : NULL); | ||
| 201 | u8 num_parents = (parent_name ? 1 : 0); | ||
| 202 | |||
| 203 | return clk_reg_sysctrl(dev, name, parent_names, num_parents, | ||
| 204 | ®_sel, ®_mask, ®_bits, | ||
| 205 | rate, enable_delay_us, flags, | ||
| 206 | &clk_sysctrl_gate_fixed_rate_ops); | ||
| 207 | } | ||
| 208 | |||
| 209 | struct clk *clk_reg_sysctrl_set_parent(struct device *dev, | ||
| 210 | const char *name, | ||
| 211 | const char **parent_names, | ||
| 212 | u8 num_parents, | ||
| 213 | u16 *reg_sel, | ||
| 214 | u8 *reg_mask, | ||
| 215 | u8 *reg_bits, | ||
| 216 | unsigned long flags) | ||
| 217 | { | ||
| 218 | return clk_reg_sysctrl(dev, name, parent_names, num_parents, | ||
| 219 | reg_sel, reg_mask, reg_bits, 0, 0, flags, | ||
| 220 | &clk_sysctrl_set_parent_ops); | ||
| 221 | } | ||
diff --git a/drivers/clk/ux500/clk.h b/drivers/clk/ux500/clk.h index c3e449169a83..a2bb92d85ee0 100644 --- a/drivers/clk/ux500/clk.h +++ b/drivers/clk/ux500/clk.h | |||
| @@ -11,16 +11,18 @@ | |||
| 11 | #define __UX500_CLK_H | 11 | #define __UX500_CLK_H |
| 12 | 12 | ||
| 13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/types.h> | ||
| 14 | 16 | ||
| 15 | struct clk *clk_reg_prcc_pclk(const char *name, | 17 | struct clk *clk_reg_prcc_pclk(const char *name, |
| 16 | const char *parent_name, | 18 | const char *parent_name, |
| 17 | unsigned int phy_base, | 19 | resource_size_t phy_base, |
| 18 | u32 cg_sel, | 20 | u32 cg_sel, |
| 19 | unsigned long flags); | 21 | unsigned long flags); |
| 20 | 22 | ||
| 21 | struct clk *clk_reg_prcc_kclk(const char *name, | 23 | struct clk *clk_reg_prcc_kclk(const char *name, |
| 22 | const char *parent_name, | 24 | const char *parent_name, |
| 23 | unsigned int phy_base, | 25 | resource_size_t phy_base, |
| 24 | u32 cg_sel, | 26 | u32 cg_sel, |
| 25 | unsigned long flags); | 27 | unsigned long flags); |
| 26 | 28 | ||
| @@ -57,4 +59,32 @@ struct clk *clk_reg_prcmu_opp_volt_scalable(const char *name, | |||
| 57 | unsigned long rate, | 59 | unsigned long rate, |
| 58 | unsigned long flags); | 60 | unsigned long flags); |
| 59 | 61 | ||
| 62 | struct clk *clk_reg_sysctrl_gate(struct device *dev, | ||
| 63 | const char *name, | ||
| 64 | const char *parent_name, | ||
| 65 | u16 reg_sel, | ||
| 66 | u8 reg_mask, | ||
| 67 | u8 reg_bits, | ||
| 68 | unsigned long enable_delay_us, | ||
| 69 | unsigned long flags); | ||
| 70 | |||
| 71 | struct clk *clk_reg_sysctrl_gate_fixed_rate(struct device *dev, | ||
| 72 | const char *name, | ||
| 73 | const char *parent_name, | ||
| 74 | u16 reg_sel, | ||
| 75 | u8 reg_mask, | ||
| 76 | u8 reg_bits, | ||
| 77 | unsigned long rate, | ||
| 78 | unsigned long enable_delay_us, | ||
| 79 | unsigned long flags); | ||
| 80 | |||
| 81 | struct clk *clk_reg_sysctrl_set_parent(struct device *dev, | ||
| 82 | const char *name, | ||
| 83 | const char **parent_names, | ||
| 84 | u8 num_parents, | ||
| 85 | u16 *reg_sel, | ||
| 86 | u8 *reg_mask, | ||
| 87 | u8 *reg_bits, | ||
| 88 | unsigned long flags); | ||
| 89 | |||
| 60 | #endif /* __UX500_CLK_H */ | 90 | #endif /* __UX500_CLK_H */ |
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile index ec3b88fe3e6d..c16ca787170a 100644 --- a/drivers/clk/versatile/Makefile +++ b/drivers/clk/versatile/Makefile | |||
| @@ -3,5 +3,5 @@ obj-$(CONFIG_ICST) += clk-icst.o | |||
| 3 | obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o | 3 | obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o |
| 4 | obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o | 4 | obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o |
| 5 | obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o | 5 | obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o |
| 6 | obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o | 6 | obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o clk-sp810.o |
| 7 | obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o | 7 | obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o |
diff --git a/drivers/clk/versatile/clk-sp810.c b/drivers/clk/versatile/clk-sp810.c new file mode 100644 index 000000000000..bf9b15a585e1 --- /dev/null +++ b/drivers/clk/versatile/clk-sp810.c | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | /* | ||
| 2 | * This program is free software; you can redistribute it and/or modify | ||
| 3 | * it under the terms of the GNU General Public License version 2 as | ||
| 4 | * published by the Free Software Foundation. | ||
| 5 | * | ||
| 6 | * This program is distributed in the hope that it will be useful, | ||
| 7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 9 | * GNU General Public License for more details. | ||
| 10 | * | ||
| 11 | * Copyright (C) 2013 ARM Limited | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/amba/sp810.h> | ||
| 15 | #include <linux/clkdev.h> | ||
| 16 | #include <linux/clk-provider.h> | ||
| 17 | #include <linux/err.h> | ||
| 18 | #include <linux/of.h> | ||
| 19 | #include <linux/of_address.h> | ||
| 20 | |||
| 21 | #define to_clk_sp810_timerclken(_hw) \ | ||
| 22 | container_of(_hw, struct clk_sp810_timerclken, hw) | ||
| 23 | |||
| 24 | struct clk_sp810; | ||
| 25 | |||
| 26 | struct clk_sp810_timerclken { | ||
| 27 | struct clk_hw hw; | ||
| 28 | struct clk *clk; | ||
| 29 | struct clk_sp810 *sp810; | ||
| 30 | int channel; | ||
| 31 | }; | ||
| 32 | |||
| 33 | struct clk_sp810 { | ||
| 34 | struct device_node *node; | ||
| 35 | int refclk_index, timclk_index; | ||
| 36 | void __iomem *base; | ||
| 37 | spinlock_t lock; | ||
| 38 | struct clk_sp810_timerclken timerclken[4]; | ||
| 39 | struct clk *refclk; | ||
| 40 | struct clk *timclk; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static u8 clk_sp810_timerclken_get_parent(struct clk_hw *hw) | ||
| 44 | { | ||
| 45 | struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); | ||
| 46 | u32 val = readl(timerclken->sp810->base + SCCTRL); | ||
| 47 | |||
| 48 | return !!(val & (1 << SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel))); | ||
| 49 | } | ||
| 50 | |||
| 51 | static int clk_sp810_timerclken_set_parent(struct clk_hw *hw, u8 index) | ||
| 52 | { | ||
| 53 | struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); | ||
| 54 | struct clk_sp810 *sp810 = timerclken->sp810; | ||
| 55 | u32 val, shift = SCCTRL_TIMERENnSEL_SHIFT(timerclken->channel); | ||
| 56 | unsigned long flags = 0; | ||
| 57 | |||
| 58 | if (WARN_ON(index > 1)) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | spin_lock_irqsave(&sp810->lock, flags); | ||
| 62 | |||
| 63 | val = readl(sp810->base + SCCTRL); | ||
| 64 | val &= ~(1 << shift); | ||
| 65 | val |= index << shift; | ||
| 66 | writel(val, sp810->base + SCCTRL); | ||
| 67 | |||
| 68 | spin_unlock_irqrestore(&sp810->lock, flags); | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | /* | ||
| 74 | * FIXME - setting the parent every time .prepare is invoked is inefficient. | ||
| 75 | * This is better handled by a dedicated clock tree configuration mechanism at | ||
| 76 | * init-time. Revisit this later when such a mechanism exists | ||
| 77 | */ | ||
| 78 | static int clk_sp810_timerclken_prepare(struct clk_hw *hw) | ||
| 79 | { | ||
| 80 | struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); | ||
| 81 | struct clk_sp810 *sp810 = timerclken->sp810; | ||
| 82 | struct clk *old_parent = __clk_get_parent(hw->clk); | ||
| 83 | struct clk *new_parent; | ||
| 84 | |||
| 85 | if (!sp810->refclk) | ||
| 86 | sp810->refclk = of_clk_get(sp810->node, sp810->refclk_index); | ||
| 87 | |||
| 88 | if (!sp810->timclk) | ||
| 89 | sp810->timclk = of_clk_get(sp810->node, sp810->timclk_index); | ||
| 90 | |||
| 91 | if (WARN_ON(IS_ERR(sp810->refclk) || IS_ERR(sp810->timclk))) | ||
| 92 | return -ENOENT; | ||
| 93 | |||
| 94 | /* Select fastest parent */ | ||
| 95 | if (clk_get_rate(sp810->refclk) > clk_get_rate(sp810->timclk)) | ||
| 96 | new_parent = sp810->refclk; | ||
| 97 | else | ||
| 98 | new_parent = sp810->timclk; | ||
| 99 | |||
| 100 | /* Switch the parent if necessary */ | ||
| 101 | if (old_parent != new_parent) { | ||
| 102 | clk_prepare(new_parent); | ||
| 103 | clk_set_parent(hw->clk, new_parent); | ||
| 104 | clk_unprepare(old_parent); | ||
| 105 | } | ||
| 106 | |||
| 107 | return 0; | ||
| 108 | } | ||
| 109 | |||
| 110 | static void clk_sp810_timerclken_unprepare(struct clk_hw *hw) | ||
| 111 | { | ||
| 112 | struct clk_sp810_timerclken *timerclken = to_clk_sp810_timerclken(hw); | ||
| 113 | struct clk_sp810 *sp810 = timerclken->sp810; | ||
| 114 | |||
| 115 | clk_put(sp810->timclk); | ||
| 116 | clk_put(sp810->refclk); | ||
| 117 | } | ||
| 118 | |||
| 119 | static const struct clk_ops clk_sp810_timerclken_ops = { | ||
| 120 | .prepare = clk_sp810_timerclken_prepare, | ||
| 121 | .unprepare = clk_sp810_timerclken_unprepare, | ||
| 122 | .get_parent = clk_sp810_timerclken_get_parent, | ||
| 123 | .set_parent = clk_sp810_timerclken_set_parent, | ||
| 124 | }; | ||
| 125 | |||
| 126 | struct clk *clk_sp810_timerclken_of_get(struct of_phandle_args *clkspec, | ||
| 127 | void *data) | ||
| 128 | { | ||
| 129 | struct clk_sp810 *sp810 = data; | ||
| 130 | |||
| 131 | if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] > | ||
| 132 | ARRAY_SIZE(sp810->timerclken))) | ||
| 133 | return NULL; | ||
| 134 | |||
| 135 | return sp810->timerclken[clkspec->args[0]].clk; | ||
| 136 | } | ||
| 137 | |||
| 138 | void __init clk_sp810_of_setup(struct device_node *node) | ||
| 139 | { | ||
| 140 | struct clk_sp810 *sp810 = kzalloc(sizeof(*sp810), GFP_KERNEL); | ||
| 141 | const char *parent_names[2]; | ||
| 142 | char name[12]; | ||
| 143 | struct clk_init_data init; | ||
| 144 | int i; | ||
| 145 | |||
| 146 | if (!sp810) { | ||
| 147 | pr_err("Failed to allocate memory for SP810!\n"); | ||
| 148 | return; | ||
| 149 | } | ||
| 150 | |||
| 151 | sp810->refclk_index = of_property_match_string(node, "clock-names", | ||
| 152 | "refclk"); | ||
| 153 | parent_names[0] = of_clk_get_parent_name(node, sp810->refclk_index); | ||
| 154 | |||
| 155 | sp810->timclk_index = of_property_match_string(node, "clock-names", | ||
| 156 | "timclk"); | ||
| 157 | parent_names[1] = of_clk_get_parent_name(node, sp810->timclk_index); | ||
| 158 | |||
| 159 | if (parent_names[0] <= 0 || parent_names[1] <= 0) { | ||
| 160 | pr_warn("Failed to obtain parent clocks for SP810!\n"); | ||
| 161 | return; | ||
| 162 | } | ||
| 163 | |||
| 164 | sp810->node = node; | ||
| 165 | sp810->base = of_iomap(node, 0); | ||
| 166 | spin_lock_init(&sp810->lock); | ||
| 167 | |||
| 168 | init.name = name; | ||
| 169 | init.ops = &clk_sp810_timerclken_ops; | ||
| 170 | init.flags = CLK_IS_BASIC; | ||
| 171 | init.parent_names = parent_names; | ||
| 172 | init.num_parents = ARRAY_SIZE(parent_names); | ||
| 173 | |||
| 174 | for (i = 0; i < ARRAY_SIZE(sp810->timerclken); i++) { | ||
| 175 | snprintf(name, ARRAY_SIZE(name), "timerclken%d", i); | ||
| 176 | |||
| 177 | sp810->timerclken[i].sp810 = sp810; | ||
| 178 | sp810->timerclken[i].channel = i; | ||
| 179 | sp810->timerclken[i].hw.init = &init; | ||
| 180 | |||
| 181 | sp810->timerclken[i].clk = clk_register(NULL, | ||
| 182 | &sp810->timerclken[i].hw); | ||
| 183 | WARN_ON(IS_ERR(sp810->timerclken[i].clk)); | ||
| 184 | } | ||
| 185 | |||
| 186 | of_clk_add_provider(node, clk_sp810_timerclken_of_get, sp810); | ||
| 187 | } | ||
| 188 | CLK_OF_DECLARE(sp810, "arm,sp810", clk_sp810_of_setup); | ||
diff --git a/drivers/clk/versatile/clk-vexpress.c b/drivers/clk/versatile/clk-vexpress.c index 82b45aad8ccf..a4a728d05092 100644 --- a/drivers/clk/versatile/clk-vexpress.c +++ b/drivers/clk/versatile/clk-vexpress.c | |||
| @@ -15,8 +15,6 @@ | |||
| 15 | #include <linux/clkdev.h> | 15 | #include <linux/clkdev.h> |
| 16 | #include <linux/clk-provider.h> | 16 | #include <linux/clk-provider.h> |
| 17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
| 18 | #include <linux/of.h> | ||
| 19 | #include <linux/of_address.h> | ||
| 20 | #include <linux/vexpress.h> | 18 | #include <linux/vexpress.h> |
| 21 | 19 | ||
| 22 | static struct clk *vexpress_sp810_timerclken[4]; | 20 | static struct clk *vexpress_sp810_timerclken[4]; |
| @@ -86,50 +84,3 @@ void __init vexpress_clk_init(void __iomem *sp810_base) | |||
| 86 | WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1], | 84 | WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1], |
| 87 | "v2m-timer1", "sp804")); | 85 | "v2m-timer1", "sp804")); |
| 88 | } | 86 | } |
| 89 | |||
| 90 | #if defined(CONFIG_OF) | ||
| 91 | |||
| 92 | struct clk *vexpress_sp810_of_get(struct of_phandle_args *clkspec, void *data) | ||
| 93 | { | ||
| 94 | if (WARN_ON(clkspec->args_count != 1 || clkspec->args[0] > | ||
| 95 | ARRAY_SIZE(vexpress_sp810_timerclken))) | ||
| 96 | return NULL; | ||
| 97 | |||
| 98 | return vexpress_sp810_timerclken[clkspec->args[0]]; | ||
| 99 | } | ||
| 100 | |||
| 101 | void __init vexpress_clk_of_init(void) | ||
| 102 | { | ||
| 103 | struct device_node *node; | ||
| 104 | struct clk *clk; | ||
| 105 | struct clk *refclk, *timclk; | ||
| 106 | |||
| 107 | of_clk_init(NULL); | ||
| 108 | |||
| 109 | node = of_find_compatible_node(NULL, NULL, "arm,sp810"); | ||
| 110 | vexpress_sp810_init(of_iomap(node, 0)); | ||
| 111 | of_clk_add_provider(node, vexpress_sp810_of_get, NULL); | ||
| 112 | |||
| 113 | /* Select "better" (faster) parent for SP804 timers */ | ||
| 114 | refclk = of_clk_get_by_name(node, "refclk"); | ||
| 115 | timclk = of_clk_get_by_name(node, "timclk"); | ||
| 116 | if (!WARN_ON(IS_ERR(refclk) || IS_ERR(timclk))) { | ||
| 117 | int i = 0; | ||
| 118 | |||
| 119 | if (clk_get_rate(refclk) > clk_get_rate(timclk)) | ||
| 120 | clk = refclk; | ||
| 121 | else | ||
| 122 | clk = timclk; | ||
| 123 | |||
| 124 | for (i = 0; i < ARRAY_SIZE(vexpress_sp810_timerclken); i++) | ||
| 125 | WARN_ON(clk_set_parent(vexpress_sp810_timerclken[i], | ||
| 126 | clk)); | ||
| 127 | } | ||
| 128 | |||
| 129 | WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[0], | ||
| 130 | "v2m-timer0", "sp804")); | ||
| 131 | WARN_ON(clk_register_clkdev(vexpress_sp810_timerclken[1], | ||
| 132 | "v2m-timer1", "sp804")); | ||
| 133 | } | ||
| 134 | |||
| 135 | #endif | ||
diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c index 4086b9167159..0ce85e29769b 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sunxi_timer.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
| 24 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
| 25 | #include <linux/sunxi_timer.h> | 25 | #include <linux/sunxi_timer.h> |
| 26 | #include <linux/clk-provider.h> | 26 | #include <linux/clk/sunxi.h> |
| 27 | 27 | ||
| 28 | #define TIMER_CTL_REG 0x00 | 28 | #define TIMER_CTL_REG 0x00 |
| 29 | #define TIMER_CTL_ENABLE (1 << 0) | 29 | #define TIMER_CTL_ENABLE (1 << 0) |
| @@ -123,7 +123,7 @@ void __init sunxi_timer_init(void) | |||
| 123 | if (irq <= 0) | 123 | if (irq <= 0) |
| 124 | panic("Can't parse IRQ"); | 124 | panic("Can't parse IRQ"); |
| 125 | 125 | ||
| 126 | of_clk_init(NULL); | 126 | sunxi_init_clocks(); |
| 127 | 127 | ||
| 128 | clk = of_clk_get(node, 0); | 128 | clk = of_clk_get(node, 0); |
| 129 | if (IS_ERR(clk)) | 129 | if (IS_ERR(clk)) |
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h index 9c7f5807824b..dd7adff76e81 100644 --- a/include/linux/clk-private.h +++ b/include/linux/clk-private.h | |||
| @@ -152,7 +152,7 @@ struct clk { | |||
| 152 | }, \ | 152 | }, \ |
| 153 | .reg = _reg, \ | 153 | .reg = _reg, \ |
| 154 | .shift = _shift, \ | 154 | .shift = _shift, \ |
| 155 | .width = _width, \ | 155 | .mask = BIT(_width) - 1, \ |
| 156 | .flags = _mux_flags, \ | 156 | .flags = _mux_flags, \ |
| 157 | .lock = _lock, \ | 157 | .lock = _lock, \ |
| 158 | }; \ | 158 | }; \ |
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 7f197d7addb0..11860985fecb 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h | |||
| @@ -45,6 +45,14 @@ struct clk_hw; | |||
| 45 | * undo any work done in the @prepare callback. Called with | 45 | * undo any work done in the @prepare callback. Called with |
| 46 | * prepare_lock held. | 46 | * prepare_lock held. |
| 47 | * | 47 | * |
| 48 | * @is_prepared: Queries the hardware to determine if the clock is prepared. | ||
| 49 | * This function is allowed to sleep. Optional, if this op is not | ||
| 50 | * set then the prepare count will be used. | ||
| 51 | * | ||
| 52 | * @unprepare_unused: Unprepare the clock atomically. Only called from | ||
| 53 | * clk_disable_unused for prepare clocks with special needs. | ||
| 54 | * Called with prepare mutex held. This function may sleep. | ||
| 55 | * | ||
| 48 | * @enable: Enable the clock atomically. This must not return until the | 56 | * @enable: Enable the clock atomically. This must not return until the |
| 49 | * clock is generating a valid clock signal, usable by consumer | 57 | * clock is generating a valid clock signal, usable by consumer |
| 50 | * devices. Called with enable_lock held. This function must not | 58 | * devices. Called with enable_lock held. This function must not |
| @@ -108,6 +116,8 @@ struct clk_hw; | |||
| 108 | struct clk_ops { | 116 | struct clk_ops { |
| 109 | int (*prepare)(struct clk_hw *hw); | 117 | int (*prepare)(struct clk_hw *hw); |
| 110 | void (*unprepare)(struct clk_hw *hw); | 118 | void (*unprepare)(struct clk_hw *hw); |
| 119 | int (*is_prepared)(struct clk_hw *hw); | ||
| 120 | void (*unprepare_unused)(struct clk_hw *hw); | ||
| 111 | int (*enable)(struct clk_hw *hw); | 121 | int (*enable)(struct clk_hw *hw); |
| 112 | void (*disable)(struct clk_hw *hw); | 122 | void (*disable)(struct clk_hw *hw); |
| 113 | int (*is_enabled)(struct clk_hw *hw); | 123 | int (*is_enabled)(struct clk_hw *hw); |
| @@ -239,9 +249,14 @@ struct clk_div_table { | |||
| 239 | * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the | 249 | * CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the |
| 240 | * register plus one. If CLK_DIVIDER_ONE_BASED is set then the divider is | 250 | * register plus one. If CLK_DIVIDER_ONE_BASED is set then the divider is |
| 241 | * the raw value read from the register, with the value of zero considered | 251 | * the raw value read from the register, with the value of zero considered |
| 242 | * invalid | 252 | * invalid, unless CLK_DIVIDER_ALLOW_ZERO is set. |
| 243 | * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from | 253 | * CLK_DIVIDER_POWER_OF_TWO - clock divisor is 2 raised to the value read from |
| 244 | * the hardware register | 254 | * the hardware register |
| 255 | * CLK_DIVIDER_ALLOW_ZERO - Allow zero divisors. For dividers which have | ||
| 256 | * CLK_DIVIDER_ONE_BASED set, it is possible to end up with a zero divisor. | ||
| 257 | * Some hardware implementations gracefully handle this case and allow a | ||
| 258 | * zero divisor by not modifying their input clock | ||
| 259 | * (divide by one / bypass). | ||
| 245 | */ | 260 | */ |
| 246 | struct clk_divider { | 261 | struct clk_divider { |
| 247 | struct clk_hw hw; | 262 | struct clk_hw hw; |
| @@ -255,6 +270,7 @@ struct clk_divider { | |||
| 255 | 270 | ||
| 256 | #define CLK_DIVIDER_ONE_BASED BIT(0) | 271 | #define CLK_DIVIDER_ONE_BASED BIT(0) |
| 257 | #define CLK_DIVIDER_POWER_OF_TWO BIT(1) | 272 | #define CLK_DIVIDER_POWER_OF_TWO BIT(1) |
| 273 | #define CLK_DIVIDER_ALLOW_ZERO BIT(2) | ||
| 258 | 274 | ||
| 259 | extern const struct clk_ops clk_divider_ops; | 275 | extern const struct clk_ops clk_divider_ops; |
| 260 | struct clk *clk_register_divider(struct device *dev, const char *name, | 276 | struct clk *clk_register_divider(struct device *dev, const char *name, |
| @@ -274,7 +290,7 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, | |||
| 274 | * @reg: register controlling multiplexer | 290 | * @reg: register controlling multiplexer |
| 275 | * @shift: shift to multiplexer bit field | 291 | * @shift: shift to multiplexer bit field |
| 276 | * @width: width of mutliplexer bit field | 292 | * @width: width of mutliplexer bit field |
| 277 | * @num_clks: number of parent clocks | 293 | * @flags: hardware-specific flags |
| 278 | * @lock: register lock | 294 | * @lock: register lock |
| 279 | * | 295 | * |
| 280 | * Clock with multiple selectable parents. Implements .get_parent, .set_parent | 296 | * Clock with multiple selectable parents. Implements .get_parent, .set_parent |
| @@ -287,8 +303,9 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name, | |||
| 287 | struct clk_mux { | 303 | struct clk_mux { |
| 288 | struct clk_hw hw; | 304 | struct clk_hw hw; |
| 289 | void __iomem *reg; | 305 | void __iomem *reg; |
| 306 | u32 *table; | ||
| 307 | u32 mask; | ||
| 290 | u8 shift; | 308 | u8 shift; |
| 291 | u8 width; | ||
| 292 | u8 flags; | 309 | u8 flags; |
| 293 | spinlock_t *lock; | 310 | spinlock_t *lock; |
| 294 | }; | 311 | }; |
| @@ -297,11 +314,19 @@ struct clk_mux { | |||
| 297 | #define CLK_MUX_INDEX_BIT BIT(1) | 314 | #define CLK_MUX_INDEX_BIT BIT(1) |
| 298 | 315 | ||
| 299 | extern const struct clk_ops clk_mux_ops; | 316 | extern const struct clk_ops clk_mux_ops; |
| 317 | |||
| 300 | struct clk *clk_register_mux(struct device *dev, const char *name, | 318 | struct clk *clk_register_mux(struct device *dev, const char *name, |
| 301 | const char **parent_names, u8 num_parents, unsigned long flags, | 319 | const char **parent_names, u8 num_parents, unsigned long flags, |
| 302 | void __iomem *reg, u8 shift, u8 width, | 320 | void __iomem *reg, u8 shift, u8 width, |
| 303 | u8 clk_mux_flags, spinlock_t *lock); | 321 | u8 clk_mux_flags, spinlock_t *lock); |
| 304 | 322 | ||
| 323 | struct clk *clk_register_mux_table(struct device *dev, const char *name, | ||
| 324 | const char **parent_names, u8 num_parents, unsigned long flags, | ||
| 325 | void __iomem *reg, u8 shift, u32 mask, | ||
| 326 | u8 clk_mux_flags, u32 *table, spinlock_t *lock); | ||
| 327 | |||
| 328 | void of_fixed_factor_clk_setup(struct device_node *node); | ||
| 329 | |||
| 305 | /** | 330 | /** |
| 306 | * struct clk_fixed_factor - fixed multiplier and divider clock | 331 | * struct clk_fixed_factor - fixed multiplier and divider clock |
| 307 | * | 332 | * |
| @@ -325,6 +350,37 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name, | |||
| 325 | const char *parent_name, unsigned long flags, | 350 | const char *parent_name, unsigned long flags, |
| 326 | unsigned int mult, unsigned int div); | 351 | unsigned int mult, unsigned int div); |
| 327 | 352 | ||
| 353 | /*** | ||
| 354 | * struct clk_composite - aggregate clock of mux, divider and gate clocks | ||
| 355 | * | ||
| 356 | * @hw: handle between common and hardware-specific interfaces | ||
| 357 | * @mux_hw: handle between composite and hardware-specific mux clock | ||
| 358 | * @rate_hw: handle between composite and hardware-specific rate clock | ||
| 359 | * @gate_hw: handle between composite and hardware-specific gate clock | ||
| 360 | * @mux_ops: clock ops for mux | ||
| 361 | * @rate_ops: clock ops for rate | ||
| 362 | * @gate_ops: clock ops for gate | ||
| 363 | */ | ||
| 364 | struct clk_composite { | ||
| 365 | struct clk_hw hw; | ||
| 366 | struct clk_ops ops; | ||
| 367 | |||
| 368 | struct clk_hw *mux_hw; | ||
| 369 | struct clk_hw *rate_hw; | ||
| 370 | struct clk_hw *gate_hw; | ||
| 371 | |||
| 372 | const struct clk_ops *mux_ops; | ||
| 373 | const struct clk_ops *rate_ops; | ||
| 374 | const struct clk_ops *gate_ops; | ||
| 375 | }; | ||
| 376 | |||
| 377 | struct clk *clk_register_composite(struct device *dev, const char *name, | ||
| 378 | const char **parent_names, int num_parents, | ||
| 379 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | ||
| 380 | struct clk_hw *rate_hw, const struct clk_ops *rate_ops, | ||
| 381 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | ||
| 382 | unsigned long flags); | ||
| 383 | |||
| 328 | /** | 384 | /** |
| 329 | * clk_register - allocate a new clock, register it and return an opaque cookie | 385 | * clk_register - allocate a new clock, register it and return an opaque cookie |
| 330 | * @dev: device that is registering this clock | 386 | * @dev: device that is registering this clock |
| @@ -351,6 +407,7 @@ unsigned int __clk_get_enable_count(struct clk *clk); | |||
| 351 | unsigned int __clk_get_prepare_count(struct clk *clk); | 407 | unsigned int __clk_get_prepare_count(struct clk *clk); |
| 352 | unsigned long __clk_get_rate(struct clk *clk); | 408 | unsigned long __clk_get_rate(struct clk *clk); |
| 353 | unsigned long __clk_get_flags(struct clk *clk); | 409 | unsigned long __clk_get_flags(struct clk *clk); |
| 410 | bool __clk_is_prepared(struct clk *clk); | ||
| 354 | bool __clk_is_enabled(struct clk *clk); | 411 | bool __clk_is_enabled(struct clk *clk); |
| 355 | struct clk *__clk_lookup(const char *name); | 412 | struct clk *__clk_lookup(const char *name); |
| 356 | 413 | ||
diff --git a/include/linux/clk.h b/include/linux/clk.h index b3ac22d0fc1f..9a6d04524b1a 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h | |||
| @@ -28,16 +28,16 @@ struct clk; | |||
| 28 | * PRE_RATE_CHANGE - called immediately before the clk rate is changed, | 28 | * PRE_RATE_CHANGE - called immediately before the clk rate is changed, |
| 29 | * to indicate that the rate change will proceed. Drivers must | 29 | * to indicate that the rate change will proceed. Drivers must |
| 30 | * immediately terminate any operations that will be affected by the | 30 | * immediately terminate any operations that will be affected by the |
| 31 | * rate change. Callbacks may either return NOTIFY_DONE or | 31 | * rate change. Callbacks may either return NOTIFY_DONE, NOTIFY_OK, |
| 32 | * NOTIFY_STOP. | 32 | * NOTIFY_STOP or NOTIFY_BAD. |
| 33 | * | 33 | * |
| 34 | * ABORT_RATE_CHANGE: called if the rate change failed for some reason | 34 | * ABORT_RATE_CHANGE: called if the rate change failed for some reason |
| 35 | * after PRE_RATE_CHANGE. In this case, all registered notifiers on | 35 | * after PRE_RATE_CHANGE. In this case, all registered notifiers on |
| 36 | * the clk will be called with ABORT_RATE_CHANGE. Callbacks must | 36 | * the clk will be called with ABORT_RATE_CHANGE. Callbacks must |
| 37 | * always return NOTIFY_DONE. | 37 | * always return NOTIFY_DONE or NOTIFY_OK. |
| 38 | * | 38 | * |
| 39 | * POST_RATE_CHANGE - called after the clk rate change has successfully | 39 | * POST_RATE_CHANGE - called after the clk rate change has successfully |
| 40 | * completed. Callbacks must always return NOTIFY_DONE. | 40 | * completed. Callbacks must always return NOTIFY_DONE or NOTIFY_OK. |
| 41 | * | 41 | * |
| 42 | */ | 42 | */ |
| 43 | #define PRE_RATE_CHANGE BIT(0) | 43 | #define PRE_RATE_CHANGE BIT(0) |
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h new file mode 100644 index 000000000000..e074fdd5a236 --- /dev/null +++ b/include/linux/clk/sunxi.h | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2012 Maxime Ripard | ||
| 3 | * | ||
| 4 | * Maxime Ripard <maxime.ripard@free-electrons.com> | ||
| 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 | #ifndef __LINUX_CLK_SUNXI_H_ | ||
| 18 | #define __LINUX_CLK_SUNXI_H_ | ||
| 19 | |||
| 20 | void __init sunxi_init_clocks(void); | ||
| 21 | |||
| 22 | #endif | ||
diff --git a/include/linux/platform_data/si5351.h b/include/linux/platform_data/si5351.h new file mode 100644 index 000000000000..92dabcaf6499 --- /dev/null +++ b/include/linux/platform_data/si5351.h | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | * Si5351A/B/C programmable clock generator platform_data. | ||
| 3 | */ | ||
| 4 | |||
| 5 | #ifndef __LINUX_PLATFORM_DATA_SI5351_H__ | ||
| 6 | #define __LINUX_PLATFORM_DATA_SI5351_H__ | ||
| 7 | |||
| 8 | struct clk; | ||
| 9 | |||
| 10 | /** | ||
| 11 | * enum si5351_variant - SiLabs Si5351 chip variant | ||
| 12 | * @SI5351_VARIANT_A: Si5351A (8 output clocks, XTAL input) | ||
| 13 | * @SI5351_VARIANT_A3: Si5351A MSOP10 (3 output clocks, XTAL input) | ||
| 14 | * @SI5351_VARIANT_B: Si5351B (8 output clocks, XTAL/VXCO input) | ||
| 15 | * @SI5351_VARIANT_C: Si5351C (8 output clocks, XTAL/CLKIN input) | ||
| 16 | */ | ||
| 17 | enum si5351_variant { | ||
| 18 | SI5351_VARIANT_A = 1, | ||
| 19 | SI5351_VARIANT_A3 = 2, | ||
| 20 | SI5351_VARIANT_B = 3, | ||
| 21 | SI5351_VARIANT_C = 4, | ||
| 22 | }; | ||
| 23 | |||
| 24 | /** | ||
| 25 | * enum si5351_pll_src - Si5351 pll clock source | ||
| 26 | * @SI5351_PLL_SRC_DEFAULT: default, do not change eeprom config | ||
| 27 | * @SI5351_PLL_SRC_XTAL: pll source clock is XTAL input | ||
| 28 | * @SI5351_PLL_SRC_CLKIN: pll source clock is CLKIN input (Si5351C only) | ||
| 29 | */ | ||
| 30 | enum si5351_pll_src { | ||
| 31 | SI5351_PLL_SRC_DEFAULT = 0, | ||
| 32 | SI5351_PLL_SRC_XTAL = 1, | ||
| 33 | SI5351_PLL_SRC_CLKIN = 2, | ||
| 34 | }; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * enum si5351_multisynth_src - Si5351 multisynth clock source | ||
| 38 | * @SI5351_MULTISYNTH_SRC_DEFAULT: default, do not change eeprom config | ||
| 39 | * @SI5351_MULTISYNTH_SRC_VCO0: multisynth source clock is VCO0 | ||
| 40 | * @SI5351_MULTISYNTH_SRC_VCO1: multisynth source clock is VCO1/VXCO | ||
| 41 | */ | ||
| 42 | enum si5351_multisynth_src { | ||
| 43 | SI5351_MULTISYNTH_SRC_DEFAULT = 0, | ||
| 44 | SI5351_MULTISYNTH_SRC_VCO0 = 1, | ||
| 45 | SI5351_MULTISYNTH_SRC_VCO1 = 2, | ||
| 46 | }; | ||
| 47 | |||
| 48 | /** | ||
| 49 | * enum si5351_clkout_src - Si5351 clock output clock source | ||
| 50 | * @SI5351_CLKOUT_SRC_DEFAULT: default, do not change eeprom config | ||
| 51 | * @SI5351_CLKOUT_SRC_MSYNTH_N: clkout N source clock is multisynth N | ||
| 52 | * @SI5351_CLKOUT_SRC_MSYNTH_0_4: clkout N source clock is multisynth 0 (N<4) | ||
| 53 | * or 4 (N>=4) | ||
| 54 | * @SI5351_CLKOUT_SRC_XTAL: clkout N source clock is XTAL | ||
| 55 | * @SI5351_CLKOUT_SRC_CLKIN: clkout N source clock is CLKIN (Si5351C only) | ||
| 56 | */ | ||
| 57 | enum si5351_clkout_src { | ||
| 58 | SI5351_CLKOUT_SRC_DEFAULT = 0, | ||
| 59 | SI5351_CLKOUT_SRC_MSYNTH_N = 1, | ||
| 60 | SI5351_CLKOUT_SRC_MSYNTH_0_4 = 2, | ||
| 61 | SI5351_CLKOUT_SRC_XTAL = 3, | ||
| 62 | SI5351_CLKOUT_SRC_CLKIN = 4, | ||
| 63 | }; | ||
| 64 | |||
| 65 | /** | ||
| 66 | * enum si5351_drive_strength - Si5351 clock output drive strength | ||
| 67 | * @SI5351_DRIVE_DEFAULT: default, do not change eeprom config | ||
| 68 | * @SI5351_DRIVE_2MA: 2mA clock output drive strength | ||
| 69 | * @SI5351_DRIVE_4MA: 4mA clock output drive strength | ||
| 70 | * @SI5351_DRIVE_6MA: 6mA clock output drive strength | ||
| 71 | * @SI5351_DRIVE_8MA: 8mA clock output drive strength | ||
| 72 | */ | ||
| 73 | enum si5351_drive_strength { | ||
| 74 | SI5351_DRIVE_DEFAULT = 0, | ||
| 75 | SI5351_DRIVE_2MA = 2, | ||
| 76 | SI5351_DRIVE_4MA = 4, | ||
| 77 | SI5351_DRIVE_6MA = 6, | ||
| 78 | SI5351_DRIVE_8MA = 8, | ||
| 79 | }; | ||
| 80 | |||
| 81 | /** | ||
| 82 | * struct si5351_clkout_config - Si5351 clock output configuration | ||
| 83 | * @clkout: clkout number | ||
| 84 | * @multisynth_src: multisynth source clock | ||
| 85 | * @clkout_src: clkout source clock | ||
| 86 | * @pll_master: if true, clkout can also change pll rate | ||
| 87 | * @drive: output drive strength | ||
| 88 | * @rate: initial clkout rate, or default if 0 | ||
| 89 | */ | ||
| 90 | struct si5351_clkout_config { | ||
| 91 | enum si5351_multisynth_src multisynth_src; | ||
| 92 | enum si5351_clkout_src clkout_src; | ||
| 93 | enum si5351_drive_strength drive; | ||
| 94 | bool pll_master; | ||
| 95 | unsigned long rate; | ||
| 96 | }; | ||
| 97 | |||
| 98 | /** | ||
| 99 | * struct si5351_platform_data - Platform data for the Si5351 clock driver | ||
| 100 | * @variant: Si5351 chip variant | ||
| 101 | * @clk_xtal: xtal input clock | ||
| 102 | * @clk_clkin: clkin input clock | ||
| 103 | * @pll_src: array of pll source clock setting | ||
| 104 | * @clkout: array of clkout configuration | ||
| 105 | */ | ||
| 106 | struct si5351_platform_data { | ||
| 107 | enum si5351_variant variant; | ||
| 108 | struct clk *clk_xtal; | ||
| 109 | struct clk *clk_clkin; | ||
| 110 | enum si5351_pll_src pll_src[2]; | ||
| 111 | struct si5351_clkout_config clkout[8]; | ||
| 112 | }; | ||
| 113 | |||
| 114 | #endif | ||
