1
0
Fork 0

This time it looks like a quieter release cycle in the clk tree. I guess that's

because of summer time holidays/vacations. The biggest change in the diffstat
 is in the Qualcomm clk driver, where they got support for CPUs and handful of
 SoCs. After that, the at91 driver got a major rewrite for newer DT bindings
 that should make things easier going forward and the TI code moved to a
 clockdomain based design. The long tail is mostly small driver updates for
 newer clks and some simpler SoC clock drivers such as the Hisilicon and imx
 support.
 
 In the core framework, we only have two small changes this time. One is a new
 clk API to get all clks for a device with the bulk clk APIs. This allows
 drivers that don't care about doing anything besides turning on all the clks to
 just clk_get() them all and turn them on. The other change is the beginning of
 a way to support save and restore of clk settings in the clk framework. TI is
 the only user right now, but we will want to expand upon this design in the
 future to support more save and restore of clk registers.  At least this gets
 us started and works well enough for one SoC, but there's more work in the
 future.
 
 Core:
  - clk_bulk_get_all() API and friends to get all the clks for a device
  - Basic clk state save/restore hooks
 
 New Drivers:
  - Renesas RZ/A2 (R7S9210) SoC, including early clocks
  - Rensas RZ/G1N (R8A7744) and RZ/G2E (R8A774C0) SoCs
  - Rensas RZ/G2M (r8a774a1) SoC
  - Qualcomm Krait CPU clk support
  - Qualcomm QCS404 GCC support
  - Qualcomm SDM660 GCC support
  - Qualcomm SDM845 camera clock controller
  - Ingenic jz4725b CGU
  - Hisilicon 3670 SoC support
  - TI SCI clks on K3 SoCs
  - iMX6 MMDC clks
  - Reset Controller (RMU) support for Actions Semi Owl S900 and S700 SoCs
 
 Updates:
  - Rework at91 PMC clock driver for new DT bindings
  - Nvidia Tegra clk driver MBIST workaround fix
  - S2RAM support for Marvell mvebu periph clks
  - Use updated printk format for OF node names
  - Fix TI code to only search DT subnodes
  - Various static analysis finds
  - Tag various drivers with SPDX license tags
  - Support dynamic frequency switching (DFS) on qcom SDM845 GCC
  - Only use s2mps11 dt-binding defines instead of redefining them in the driver
  - Add some more missing clks to qcom MSM8996 GCC
  - Quad SPI clks on qcom SDM845
  - Add support for CMT timer clocks on R-Car V3H
  - Add support for SHDI and various timer clocks on R-Car V3M
  - Improve OSC and RCLK (watchdog) handling on R-Car Gen3 SoCs
  - Amlogic clk-pll driver improvements and updates
  - Amlogic axg audio controller system clocks
  - Register Amlogic meson8b clock controller early
  - Add support for SATA and Fine Display Processor (FDP) clocks on R-Car M3-N
  - Consolidation of system suspend related code in Exynos, S5P, S3C SoC clk drivers
  - Fixes for system suspend support on Exynos542x (Odroid boards) and Exynos5433 SoC
  - Remove obsoleted Exynos4212 ISP clock definitions
  - Migrated TI am3/4/5 and dra7 SoCs to clockdomain based design
  - TI RTC+DDR sleep mode support for clock save/restore
  - Allwinner A64 display engine support and fixes
  - Allwinner A83t display engine support and fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAlvY4ysRHHNib3lkQGtl
 cm5lbC5vcmcACgkQrQKIl8bklSVaDBAA3Wv/rsCn4FJ2ZgIWYWQqr69lAWDcBVVe
 4nNbFqzEmRoml8e+XOfVFwnbsai4B5ALVxyMnRlkDyxQ5TFQtF957U12Pf8upPa5
 R447YBt4tw40NCj8u5KNAaBmYYHdmXXDvsBPXyQn+1iy/9R8Is8AcDmv+D2ucuJF
 PPBXOwb+2CstUQhuwlXyvsAw/tqq/rJDVyAZVJUoqXJwlNMjr76V0m0ZXHN6NcyC
 F2SfnzIO4srRteTeKXVFcMU/3uHC3zofEfammSJjGZkk4WHULuPpkD17RMEyBul1
 Ju1S1nzGiKvYME/mmbIcRPNcpry65EVo/wn6IjAcG2m4GaWSq3F6qIttnoc6dnra
 R2VylIEy7HnNcAf8fkQdkd/l+h/TDp3iVrXg0p/rRxRk4Jlc86n2PWO6jtsZv4S+
 NySeRhTb51KrTl72J76LP+dfDWdbeZfkAqr0Qx6QM04OznVYSTHlnQaeM1Nx2SZR
 5+k126NdxDp7xgoJNfq18wzufrlefjuRTg2Kck1YuFuhV4Fjmq7ZC81bSSaakYPh
 /t073TcSZ+VfEYP5hVsl/pjMdFzHcj8pbavhs0UNIYLQNXe494Bm9PyYJOzQKnwz
 Zpbf7V6eplh8J1I03VI8RHviNp340iv2hhz9vp4mNP1vIhgdNiz7R2gn5sLSoFt+
 vei0J0vEzCA=
 =V5aK
 -----END PGP SIGNATURE-----

Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk updates from Stephen Boyd:
 "This time it looks like a quieter release cycle in the clk tree. I
  guess that's because of summer time holidays/vacations. The biggest
  change in the diffstat is in the Qualcomm clk driver, where they got
  support for CPUs and handful of SoCs. After that, the at91 driver got
  a major rewrite for newer DT bindings that should make things easier
  going forward and the TI code moved to a clockdomain based design.

  The long tail is mostly small driver updates for newer clks and some
  simpler SoC clock drivers such as the Hisilicon and imx support.

  In the core framework, we only have two small changes this time.

  One is a new clk API to get all clks for a device with the bulk clk
  APIs. This allows drivers that don't care about doing anything besides
  turning on all the clks to just clk_get() them all and turn them on.

  The other change is the beginning of a way to support save and restore
  of clk settings in the clk framework. TI is the only user right now,
  but we will want to expand upon this design in the future to support
  more save and restore of clk registers. At least this gets us started
  and works well enough for one SoC, but there's more work in the
  future.

  Core:
   - clk_bulk_get_all() API and friends to get all the clks for a device
   - Basic clk state save/restore hooks

  New Drivers:
   - Renesas RZ/A2 (R7S9210) SoC, including early clocks
   - Rensas RZ/G1N (R8A7744) and RZ/G2E (R8A774C0) SoCs
   - Rensas RZ/G2M (r8a774a1) SoC
   - Qualcomm Krait CPU clk support
   - Qualcomm QCS404 GCC support
   - Qualcomm SDM660 GCC support
   - Qualcomm SDM845 camera clock controller
   - Ingenic jz4725b CGU
   - Hisilicon 3670 SoC support
   - TI SCI clks on K3 SoCs
   - iMX6 MMDC clks
   - Reset Controller (RMU) support for Actions Semi Owl S900 and S700 SoCs

  Updates:
   - Rework at91 PMC clock driver for new DT bindings
   - Nvidia Tegra clk driver MBIST workaround fix
   - S2RAM support for Marvell mvebu periph clks
   - Use updated printk format for OF node names
   - Fix TI code to only search DT subnodes
   - Various static analysis finds
   - Tag various drivers with SPDX license tags
   - Support dynamic frequency switching (DFS) on qcom SDM845 GCC
   - Only use s2mps11 dt-binding defines instead of redefining them in the driver
   - Add some more missing clks to qcom MSM8996 GCC
   - Quad SPI clks on qcom SDM845
   - Add support for CMT timer clocks on R-Car V3H
   - Add support for SHDI and various timer clocks on R-Car V3M
   - Improve OSC and RCLK (watchdog) handling on R-Car Gen3 SoCs
   - Amlogic clk-pll driver improvements and updates
   - Amlogic axg audio controller system clocks
   - Register Amlogic meson8b clock controller early
   - Add support for SATA and Fine Display Processor (FDP) clocks on R-Car M3-N
   - Consolidation of system suspend related code in Exynos, S5P, S3C SoC clk drivers
   - Fixes for system suspend support on Exynos542x (Odroid boards) and Exynos5433 SoC
   - Remove obsoleted Exynos4212 ISP clock definitions
   - Migrated TI am3/4/5 and dra7 SoCs to clockdomain based design
   - TI RTC+DDR sleep mode support for clock save/restore
   - Allwinner A64 display engine support and fixes
   - Allwinner A83t display engine support and fixes"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (186 commits)
  clk: qcom: Remove unused arrays in SDM845 GCC
  clk: fixed-rate: fix of_node_get-put imbalance
  clk: s2mps11: Add used attribute to s2mps11_dt_match
  clk: qcom: gcc-sdm660: Add MODULE_LICENSE
  clk: qcom: Add safe switch hook for krait mux clocks
  dt-bindings: clock: Document qcom,krait-cc
  clk: qcom: Add Krait clock controller driver
  dt-bindings: arm: Document qcom,kpss-gcc
  clk: qcom: Add KPSS ACC/GCC driver
  clk: qcom: Add support for Krait clocks
  clk: qcom: Add IPQ806X's HFPLLs
  clk: qcom: Add MSM8960/APQ8064's HFPLLs
  dt-bindings: clock: Document qcom,hfpll
  clk: qcom: Add HFPLL driver
  clk: qcom: Add support for High-Frequency PLLs (HFPLLs)
  ARM: Add Krait L2 register accessor functions
  clk: imx6q: add mmdc0 ipg clock
  clk: imx6sl: add mmdc ipg clocks
  clk: imx6sll: add mmdc1 ipg clock
  clk: imx6sx: add mmdc1 ipg clock
  ...
hifive-unleashed-5.1
Linus Torvalds 2018-10-31 11:08:30 -07:00
commit 519f64bf15
284 changed files with 20513 additions and 4254 deletions

View File

@ -21,10 +21,29 @@ PROPERTIES
the register region. An optional second element specifies
the base address and size of the alias register region.
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the pll parents.
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "pll8_vote", "pxo".
- clock-output-names:
Usage: optional
Value type: <string>
Definition: Name of the output clock. Typically acpuX_aux where X is a
CPU number starting at 0.
Example:
clock-controller@2088000 {
compatible = "qcom,kpss-acc-v2";
reg = <0x02088000 0x1000>,
<0x02008000 0x1000>;
clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
clock-names = "pll8_vote", "pxo";
clock-output-names = "acpu0_aux";
};

View File

@ -0,0 +1,44 @@
Krait Processor Sub-system (KPSS) Global Clock Controller (GCC)
PROPERTIES
- compatible:
Usage: required
Value type: <string>
Definition: should be one of the following. The generic compatible
"qcom,kpss-gcc" should also be included.
"qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc"
"qcom,kpss-gcc-apq8064", "qcom,kpss-gcc"
"qcom,kpss-gcc-msm8974", "qcom,kpss-gcc"
"qcom,kpss-gcc-msm8960", "qcom,kpss-gcc"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: base address and size of the register region
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the pll parents.
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "pll8_vote", "pxo".
- clock-output-names:
Usage: required
Value type: <string>
Definition: Name of the output clock. Typically acpu_l2_aux indicating
an L2 cache auxiliary clock.
Example:
l2cc: clock-controller@2011000 {
compatible = "qcom,kpss-gcc-ipq8064", "qcom,kpss-gcc";
reg = <0x2011000 0x1000>;
clocks = <&gcc PLL8_VOTE>, <&gcc PXO_SRC>;
clock-names = "pll8_vote", "pxo";
clock-output-names = "acpu_l2_aux";
};

View File

@ -13,6 +13,7 @@ Required Properties:
region.
- clocks: Reference to the parent clocks ("hosc", "losc")
- #clock-cells: should be 1.
- #reset-cells: should be 1.
Each clock is assigned an identifier, and client nodes can use this identifier
to specify the clock which they consume.
@ -36,6 +37,7 @@ Example: Clock Management Unit node:
reg = <0x0 0xe0160000 0x0 0x1000>;
clocks = <&hosc>, <&losc>;
#clock-cells = <1>;
#reset-cells = <1>;
};
Example: UART controller node that consumes clock generated by the clock

View File

@ -4,6 +4,8 @@ This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Slow Clock controller:
Required properties:
- compatible : shall be one of the following:
"atmel,at91sam9x5-sckc" or
@ -16,84 +18,6 @@ Required properties:
"atmel,at91sam9x5-clk-slow-rc-osc":
at91 internal slow RC oscillator
"atmel,<chip>-pmc":
at91 PMC (Power Management Controller)
All at91 specific clocks (clocks defined below) must be child
node of the PMC node.
<chip> can be: at91rm9200, at91sam9260, at91sam9261,
at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9x5,
sama5d2, sama5d3 or sama5d4.
"atmel,at91sam9x5-clk-slow" (under sckc node)
or
"atmel,at91sam9260-clk-slow" (under pmc node):
at91 slow clk
"atmel,at91rm9200-clk-main-osc"
"atmel,at91sam9x5-clk-main-rc-osc"
at91 main clk sources
"atmel,at91sam9x5-clk-main"
"atmel,at91rm9200-clk-main":
at91 main clock
"atmel,at91rm9200-clk-master" or
"atmel,at91sam9x5-clk-master":
at91 master clock
"atmel,at91sam9x5-clk-peripheral" or
"atmel,at91rm9200-clk-peripheral":
at91 peripheral clocks
"atmel,at91rm9200-clk-pll" or
"atmel,at91sam9g45-clk-pll" or
"atmel,at91sam9g20-clk-pllb" or
"atmel,sama5d3-clk-pll":
at91 pll clocks
"atmel,at91sam9x5-clk-plldiv":
at91 plla divisor
"atmel,at91rm9200-clk-programmable" or
"atmel,at91sam9g45-clk-programmable" or
"atmel,at91sam9x5-clk-programmable":
at91 programmable clocks
"atmel,at91sam9x5-clk-smd":
at91 SMD (Soft Modem) clock
"atmel,at91rm9200-clk-system":
at91 system clocks
"atmel,at91rm9200-clk-usb" or
"atmel,at91sam9x5-clk-usb" or
"atmel,at91sam9n12-clk-usb":
at91 usb clock
"atmel,at91sam9x5-clk-utmi":
at91 utmi clock
"atmel,sama5d4-clk-h32mx":
at91 h32mx clock
"atmel,sama5d2-clk-generated":
at91 generated clock
"atmel,sama5d2-clk-audio-pll-frac":
at91 audio fractional pll
"atmel,sama5d2-clk-audio-pll-pad":
at91 audio pll CLK_AUDIO output pin
"atmel,sama5d2-clk-audio-pll-pmc"
at91 audio pll output on AUDIOPLLCLK that feeds the PMC
and can be used by peripheral clock or generic clock
"atmel,sama5d2-clk-i2s-mux" (under pmc node):
at91 I2S clock source selection
Required properties for SCKC node:
- reg : defines the IO memory reserved for the SCKC.
- #size-cells : shall be 0 (reg is used to encode clk id).
- #address-cells : shall be 1 (reg is used to encode clk id).
@ -109,428 +33,30 @@ For example:
/* put at91 slow clocks here */
};
Power Management Controller (PMC):
Required properties for internal slow RC oscillator:
- #clock-cells : from common clock binding; shall be set to 0.
- clock-frequency : define the internal RC oscillator frequency.
Optional properties:
- clock-accuracy : define the internal RC oscillator accuracy.
For example:
slow_rc_osc: slow_rc_osc {
compatible = "atmel,at91sam9x5-clk-slow-rc-osc";
clock-frequency = <32768>;
clock-accuracy = <50000000>;
};
Required properties for slow oscillator:
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall encode the main osc source clk sources (see atmel datasheet).
Required properties:
- compatible : shall be "atmel,<chip>-pmc", "syscon":
<chip> can be: at91rm9200, at91sam9260, at91sam9261,
at91sam9263, at91sam9g45, at91sam9n12, at91sam9rl, at91sam9g15,
at91sam9g25, at91sam9g35, at91sam9x25, at91sam9x35, at91sam9x5,
sama5d2, sama5d3 or sama5d4.
- #clock-cells : from common clock binding; shall be set to 2. The first entry
is the type of the clock (core, system, peripheral or generated) and the
second entry its index as provided by the datasheet
- clocks : Must contain an entry for each entry in clock-names.
- clock-names: Must include the following entries: "slow_clk", "main_xtal"
Optional properties:
- atmel,osc-bypass : boolean property. Set this when a clock signal is directly
provided on XIN.
For example:
slow_osc: slow_osc {
compatible = "atmel,at91rm9200-clk-slow-osc";
#clock-cells = <0>;
clocks = <&slow_xtal>;
};
Required properties for slow clock:
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall encode the slow clk sources (see atmel datasheet).
For example:
clk32k: slck {
compatible = "atmel,at91sam9x5-clk-slow";
#clock-cells = <0>;
clocks = <&slow_rc_osc &slow_osc>;
};
Required properties for PMC node:
- reg : defines the IO memory reserved for the PMC.
- #size-cells : shall be 0 (reg is used to encode clk id).
- #address-cells : shall be 1 (reg is used to encode clk id).
- interrupts : shall be set to PMC interrupt line.
- interrupt-controller : tell that the PMC is an interrupt controller.
- #interrupt-cells : must be set to 1. The first cell encodes the interrupt id,
and reflect the bit position in the PMC_ER/DR/SR registers.
You can use the dt macros defined in dt-bindings/clock/at91.h.
0 (AT91_PMC_MOSCS) -> main oscillator ready
1 (AT91_PMC_LOCKA) -> PLL A ready
2 (AT91_PMC_LOCKB) -> PLL B ready
3 (AT91_PMC_MCKRDY) -> master clock ready
6 (AT91_PMC_LOCKU) -> UTMI PLL clock ready
8 .. 15 (AT91_PMC_PCKRDY(id)) -> programmable clock ready
16 (AT91_PMC_MOSCSELS) -> main oscillator selected
17 (AT91_PMC_MOSCRCS) -> RC main oscillator stabilized
18 (AT91_PMC_CFDEV) -> clock failure detected
For example:
pmc: pmc@fffffc00 {
compatible = "atmel,sama5d3-pmc";
interrupts = <1 4 7>;
interrupt-controller;
#interrupt-cells = <2>;
#size-cells = <0>;
#address-cells = <1>;
/* put at91 clocks here */
};
Required properties for main clock internal RC oscillator:
- interrupts : shall be set to "<0>".
- clock-frequency : define the internal RC oscillator frequency.
Optional properties:
- clock-accuracy : define the internal RC oscillator accuracy.
For example:
main_rc_osc: main_rc_osc {
compatible = "atmel,at91sam9x5-clk-main-rc-osc";
interrupt-parent = <&pmc>;
interrupts = <0>;
clock-frequency = <12000000>;
clock-accuracy = <50000000>;
};
Required properties for main clock oscillator:
- interrupts : shall be set to "<0>".
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall encode the main osc source clk sources (see atmel datasheet).
Optional properties:
- atmel,osc-bypass : boolean property. Specified if a clock signal is provided
on XIN.
clock signal is directly provided on XIN pin.
For example:
main_osc: main_osc {
compatible = "atmel,at91rm9200-clk-main-osc";
interrupt-parent = <&pmc>;
interrupts = <0>;
#clock-cells = <0>;
clocks = <&main_xtal>;
};
Required properties for main clock:
- interrupts : shall be set to "<0>".
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall encode the main clk sources (see atmel datasheet).
For example:
main: mainck {
compatible = "atmel,at91sam9x5-clk-main";
interrupt-parent = <&pmc>;
interrupts = <0>;
#clock-cells = <0>;
clocks = <&main_rc_osc &main_osc>;
};
Required properties for master clock:
- interrupts : shall be set to "<3>".
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall be the master clock sources (see atmel datasheet) phandles.
e.g. "<&ck32k>, <&main>, <&plla>, <&pllb>".
- atmel,clk-output-range : minimum and maximum clock frequency (two u32
fields).
e.g. output = <0 133000000>; <=> 0 to 133MHz.
- atmel,clk-divisors : master clock divisors table (four u32 fields).
0 <=> reserved value.
e.g. divisors = <1 2 4 6>;
- atmel,master-clk-have-div3-pres : some SoC use the reserved value 7 in the
PRES field as CLOCK_DIV3 (e.g sam9x5).
For example:
mck: mck {
compatible = "atmel,at91rm9200-clk-master";
interrupt-parent = <&pmc>;
interrupts = <3>;
#clock-cells = <0>;
atmel,clk-output-range = <0 133000000>;
atmel,clk-divisors = <1 2 4 0>;
};
Required properties for peripheral clocks:
- #size-cells : shall be 0 (reg is used to encode clk id).
- #address-cells : shall be 1 (reg is used to encode clk id).
- clocks : shall be the master clock phandle.
e.g. clocks = <&mck>;
- name: device tree node describing a specific peripheral clock.
* #clock-cells : from common clock binding; shall be set to 0.
* reg: peripheral id. See Atmel's datasheets to get a full
list of peripheral ids.
* atmel,clk-output-range : minimum and maximum clock frequency
(two u32 fields). Only valid on at91sam9x5-clk-peripheral
compatible IPs.
For example:
periph: periphck {
compatible = "atmel,at91sam9x5-clk-peripheral";
#size-cells = <0>;
#address-cells = <1>;
clocks = <&mck>;
ssc0_clk {
#clock-cells = <0>;
reg = <2>;
atmel,clk-output-range = <0 133000000>;
};
usart0_clk {
#clock-cells = <0>;
reg = <3>;
atmel,clk-output-range = <0 66000000>;
};
};
Required properties for pll clocks:
- interrupts : shall be set to "<1>".
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall be the main clock phandle.
- reg : pll id.
0 -> PLL A
1 -> PLL B
- atmel,clk-input-range : minimum and maximum source clock frequency (two u32
fields).
e.g. input = <1 32000000>; <=> 1 to 32MHz.
- #atmel,pll-clk-output-range-cells : number of cells reserved for pll output
range description. Sould be set to 2, 3
or 4.
* 1st and 2nd cells represent the frequency range (min-max).
* 3rd cell is optional and represents the OUT field value for the given
range.
* 4th cell is optional and represents the ICPLL field (PLLICPR
register)
- atmel,pll-clk-output-ranges : pll output frequency ranges + optional parameter
depending on #atmel,pll-output-range-cells
property value.
For example:
plla: pllack {
compatible = "atmel,at91sam9g45-clk-pll";
interrupt-parent = <&pmc>;
interrupts = <1>;
#clock-cells = <0>;
clocks = <&main>;
reg = <0>;
atmel,clk-input-range = <2000000 32000000>;
#atmel,pll-clk-output-range-cells = <4>;
atmel,pll-clk-output-ranges = <74500000 800000000 0 0
69500000 750000000 1 0
64500000 700000000 2 0
59500000 650000000 3 0
54500000 600000000 0 1
49500000 550000000 1 1
44500000 500000000 2 1
40000000 450000000 3 1>;
};
Required properties for plldiv clocks (plldiv = pll / 2):
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall be the plla clock phandle.
The pll divisor is equal to 2 and cannot be changed.
For example:
plladiv: plladivck {
compatible = "atmel,at91sam9x5-clk-plldiv";
#clock-cells = <0>;
clocks = <&plla>;
};
Required properties for programmable clocks:
- #size-cells : shall be 0 (reg is used to encode clk id).
- #address-cells : shall be 1 (reg is used to encode clk id).
- clocks : shall be the programmable clock source phandles.
e.g. clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
- name: device tree node describing a specific prog clock.
* #clock-cells : from common clock binding; shall be set to 0.
* reg : programmable clock id (register offset from PCKx
register).
* interrupts : shall be set to "<(8 + id)>".
For example:
prog: progck {
compatible = "atmel,at91sam9g45-clk-programmable";
#size-cells = <0>;
#address-cells = <1>;
interrupt-parent = <&pmc>;
clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>;
prog0 {
#clock-cells = <0>;
reg = <0>;
interrupts = <8>;
};
prog1 {
#clock-cells = <0>;
reg = <1>;
interrupts = <9>;
};
};
Required properties for smd clock:
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall be the smd clock source phandles.
e.g. clocks = <&plladiv>, <&utmi>;
For example:
smd: smdck {
compatible = "atmel,at91sam9x5-clk-smd";
#clock-cells = <0>;
clocks = <&plladiv>, <&utmi>;
};
Required properties for system clocks:
- #size-cells : shall be 0 (reg is used to encode clk id).
- #address-cells : shall be 1 (reg is used to encode clk id).
- name: device tree node describing a specific system clock.
* #clock-cells : from common clock binding; shall be set to 0.
* reg: system clock id (bit position in SCER/SCDR/SCSR registers).
See Atmel's datasheet to get a full list of system clock ids.
For example:
system: systemck {
compatible = "atmel,at91rm9200-clk-system";
#address-cells = <1>;
#size-cells = <0>;
ddrck {
#clock-cells = <0>;
reg = <2>;
clocks = <&mck>;
};
uhpck {
#clock-cells = <0>;
reg = <6>;
clocks = <&usb>;
};
udpck {
#clock-cells = <0>;
reg = <7>;
clocks = <&usb>;
};
};
Required properties for usb clock:
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall be the smd clock source phandles.
e.g. clocks = <&pllb>;
- atmel,clk-divisors (only available for "atmel,at91rm9200-clk-usb"):
usb clock divisor table.
e.g. divisors = <1 2 4 0>;
For example:
usb: usbck {
compatible = "atmel,at91sam9x5-clk-usb";
#clock-cells = <0>;
clocks = <&plladiv>, <&utmi>;
};
usb: usbck {
compatible = "atmel,at91rm9200-clk-usb";
#clock-cells = <0>;
clocks = <&pllb>;
atmel,clk-divisors = <1 2 4 0>;
};
Required properties for utmi clock:
- interrupts : shall be set to "<AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>".
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall be the main clock source phandle.
For example:
utmi: utmick {
compatible = "atmel,at91sam9x5-clk-utmi";
interrupt-parent = <&pmc>;
interrupts = <AT91_PMC_LOCKU IRQ_TYPE_LEVEL_HIGH>;
#clock-cells = <0>;
clocks = <&main>;
};
Required properties for 32 bits bus Matrix clock (h32mx clock):
- #clock-cells : from common clock binding; shall be set to 0.
- clocks : shall be the master clock source phandle.
For example:
h32ck: h32mxck {
#clock-cells = <0>;
compatible = "atmel,sama5d4-clk-h32mx";
clocks = <&mck>;
};
Required properties for generated clocks:
- #size-cells : shall be 0 (reg is used to encode clk id).
- #address-cells : shall be 1 (reg is used to encode clk id).
- clocks : shall be the generated clock source phandles.
e.g. clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
- name: device tree node describing a specific generated clock.
* #clock-cells : from common clock binding; shall be set to 0.
* reg: peripheral id. See Atmel's datasheets to get a full
list of peripheral ids.
* atmel,clk-output-range : minimum and maximum clock frequency
(two u32 fields).
For example:
gck {
compatible = "atmel,sama5d2-clk-generated";
#address-cells = <1>;
#size-cells = <0>;
clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
tcb0_gclk: tcb0_gclk {
#clock-cells = <0>;
reg = <35>;
atmel,clk-output-range = <0 83000000>;
};
pwm_gclk: pwm_gclk {
#clock-cells = <0>;
reg = <38>;
atmel,clk-output-range = <0 83000000>;
};
};
Required properties for I2S mux clocks:
- #size-cells : shall be 0 (reg is used to encode I2S bus id).
- #address-cells : shall be 1 (reg is used to encode I2S bus id).
- name: device tree node describing a specific mux clock.
* #clock-cells : from common clock binding; shall be set to 0.
* clocks : shall be the mux clock parent phandles; shall be 2 phandles:
peripheral and generated clock; the first phandle shall belong to the
peripheral clock and the second one shall belong to the generated
clock; "clock-indices" property can be user to specify
the correct order.
* reg: I2S bus id of the corresponding mux clock.
e.g. reg = <0>; for i2s0, reg = <1>; for i2s1
For example:
i2s_clkmux {
compatible = "atmel,sama5d2-clk-i2s-mux";
#address-cells = <1>;
#size-cells = <0>;
i2s0muxck: i2s0_muxclk {
clocks = <&i2s0_clk>, <&i2s0_gclk>;
#clock-cells = <0>;
reg = <0>;
};
i2s1muxck: i2s1_muxclk {
clocks = <&i2s1_clk>, <&i2s1_gclk>;
#clock-cells = <0>;
reg = <1>;
};
pmc: pmc@f0018000 {
compatible = "atmel,sama5d4-pmc", "syscon";
reg = <0xf0018000 0x120>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH 7>;
#clock-cells = <2>;
clocks = <&clk32k>, <&main_xtal>;
clock-names = "slow_clk", "main_xtal";
};

View File

@ -0,0 +1,43 @@
* Hisilicon Hi3670 Clock Controller
The Hi3670 clock controller generates and supplies clock to various
controllers within the Hi3670 SoC.
Required Properties:
- compatible: the compatible should be one of the following strings to
indicate the clock controller functionality.
- "hisilicon,hi3670-crgctrl"
- "hisilicon,hi3670-pctrl"
- "hisilicon,hi3670-pmuctrl"
- "hisilicon,hi3670-sctrl"
- "hisilicon,hi3670-iomcu"
- "hisilicon,hi3670-media1-crg"
- "hisilicon,hi3670-media2-crg"
- reg: physical base address of the controller and length of memory mapped
region.
- #clock-cells: should be 1.
Each clock is assigned an identifier and client nodes use this identifier
to specify the clock which they consume.
All these identifier could be found in <dt-bindings/clock/hi3670-clock.h>.
Examples:
crg_ctrl: clock-controller@fff35000 {
compatible = "hisilicon,hi3670-crgctrl", "syscon";
reg = <0x0 0xfff35000 0x0 0x1000>;
#clock-cells = <1>;
};
uart0: serial@fdf02000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x0 0xfdf02000 0x0 0x1000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&crg_ctrl HI3670_CLK_GATE_UART0>,
<&crg_ctrl HI3670_PCLK>;
clock-names = "uartclk", "apb_pclk";
};

View File

@ -6,8 +6,11 @@ to provide many different clock signals derived from only 2 external source
clocks.
Required properties:
- compatible : Should be "ingenic,<soctype>-cgu".
For example "ingenic,jz4740-cgu" or "ingenic,jz4780-cgu".
- compatible : Should be one of:
* ingenic,jz4740-cgu
* ingenic,jz4725b-cgu
* ingenic,jz4770-cgu
* ingenic,jz4780-cgu
- reg : The address & length of the CGU registers.
- clocks : List of phandle & clock specifiers for clocks external to the CGU.
Two such external clocks should be specified - first the external crystal

View File

@ -0,0 +1,18 @@
Qualcomm Camera Clock & Reset Controller Binding
------------------------------------------------
Required properties :
- compatible : shall contain "qcom,sdm845-camcc".
- reg : shall contain base register location and length.
- #clock-cells : from common clock binding, shall contain 1.
- #reset-cells : from common reset binding, shall contain 1.
- #power-domain-cells : from generic power domain binding, shall contain 1.
Example:
camcc: clock-controller@ad00000 {
compatible = "qcom,sdm845-camcc";
reg = <0xad00000 0x10000>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};

View File

@ -19,6 +19,9 @@ Required properties :
"qcom,gcc-msm8996"
"qcom,gcc-msm8998"
"qcom,gcc-mdm9615"
"qcom,gcc-qcs404"
"qcom,gcc-sdm630"
"qcom,gcc-sdm660"
"qcom,gcc-sdm845"
- reg : shall contain base register location and length

View File

@ -0,0 +1,60 @@
High-Frequency PLL (HFPLL)
PROPERTIES
- compatible:
Usage: required
Value type: <string>:
shall contain only one of the following. The generic
compatible "qcom,hfpll" should be also included.
"qcom,hfpll-ipq8064", "qcom,hfpll"
"qcom,hfpll-apq8064", "qcom,hfpll"
"qcom,hfpll-msm8974", "qcom,hfpll"
"qcom,hfpll-msm8960", "qcom,hfpll"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: address and size of HPLL registers. An optional second
element specifies the address and size of the alias
register region.
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the xo clock.
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "xo".
- clock-output-names:
Usage: required
Value type: <string>
Definition: Name of the PLL. Typically hfpllX where X is a CPU number
starting at 0. Otherwise hfpll_Y where Y is more specific
such as "l2".
Example:
1) An HFPLL for the L2 cache.
clock-controller@f9016000 {
compatible = "qcom,hfpll-ipq8064", "qcom,hfpll";
reg = <0xf9016000 0x30>;
clocks = <&xo_board>;
clock-names = "xo";
clock-output-names = "hfpll_l2";
};
2) An HFPLL for CPU0. This HFPLL has the alias register region.
clock-controller@f908a000 {
compatible = "qcom,hfpll-ipq8064", "qcom,hfpll";
reg = <0xf908a000 0x30>, <0xf900a000 0x30>;
clocks = <&xo_board>;
clock-names = "xo";
clock-output-names = "hfpll0";
};

View File

@ -0,0 +1,34 @@
Krait Clock Controller
PROPERTIES
- compatible:
Usage: required
Value type: <string>
Definition: must be one of:
"qcom,krait-cc-v1"
"qcom,krait-cc-v2"
- #clock-cells:
Usage: required
Value type: <u32>
Definition: must be 1
- clocks:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the clock parents of hfpll, secondary muxes.
- clock-names:
Usage: required
Value type: <stringlist>
Definition: must be "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb".
Example:
kraitcc: clock-controller {
compatible = "qcom,krait-cc-v1";
clocks = <&hfpll0>, <&hfpll1>, <&acpu0_aux>, <&acpu1_aux>, <qsb>;
clock-names = "hfpll0", "hfpll1", "acpu0_aux", "acpu1_aux", "qsb";
#clock-cells = <1>;
};

View File

@ -13,9 +13,13 @@ They provide the following functionalities:
Required Properties:
- compatible: Must be one of:
- "renesas,r7s9210-cpg-mssr" for the r7s9210 SoC (RZ/A2)
- "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
- "renesas,r8a7744-cpg-mssr" for the r8a7744 SoC (RZ/G1N)
- "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
- "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C)
- "renesas,r8a774a1-cpg-mssr" for the r8a774a1 SoC (RZ/G2M)
- "renesas,r8a774c0-cpg-mssr" for the r8a774c0 SoC (RZ/G2E)
- "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2)
- "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W)
- "renesas,r8a7792-cpg-mssr" for the r8a7792 SoC (R-Car V2H)
@ -35,12 +39,13 @@ Required Properties:
- clocks: References to external parent clocks, one entry for each entry in
clock-names
- clock-names: List of external parent clock names. Valid names are:
- "extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7792,
r8a7793, r8a7794, r8a7795, r8a7796, r8a77965, r8a77970,
r8a77980, r8a77990, r8a77995)
- "extalr" (r8a7795, r8a7796, r8a77965, r8a77970, r8a77980)
- "usb_extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7793,
r8a7794)
- "extal" (r7s9210, r8a7743, r8a7744, r8a7745, r8a77470, r8a774a1,
r8a774c0, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
r8a7795, r8a7796, r8a77965, r8a77970, r8a77980, r8a77990,
r8a77995)
- "extalr" (r8a774a1, r8a7795, r8a7796, r8a77965, r8a77970, r8a77980)
- "usb_extal" (r8a7743, r8a7744, r8a7745, r8a77470, r8a7790, r8a7791,
r8a7793, r8a7794)
- #clock-cells: Must be 2
- For CPG core clocks, the two clock specifier cells must be "CPG_CORE"

View File

@ -7,6 +7,9 @@ config DMABOUNCE
bool
select ZONE_DMA
config KRAIT_L2_ACCESSORS
bool
config SHARP_LOCOMO
bool

View File

@ -7,6 +7,7 @@ obj-y += firmware.o
obj-$(CONFIG_SA1111) += sa1111.o
obj-$(CONFIG_DMABOUNCE) += dmabounce.o
obj-$(CONFIG_KRAIT_L2_ACCESSORS) += krait-l2-accessors.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o

View File

@ -0,0 +1,48 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
#include <linux/spinlock.h>
#include <linux/export.h>
#include <asm/barrier.h>
#include <asm/krait-l2-accessors.h>
static DEFINE_RAW_SPINLOCK(krait_l2_lock);
void krait_set_l2_indirect_reg(u32 addr, u32 val)
{
unsigned long flags;
raw_spin_lock_irqsave(&krait_l2_lock, flags);
/*
* Select the L2 window by poking l2cpselr, then write to the window
* via l2cpdr.
*/
asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
isb();
asm volatile ("mcr p15, 3, %0, c15, c0, 7 @ l2cpdr" : : "r" (val));
isb();
raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
}
EXPORT_SYMBOL(krait_set_l2_indirect_reg);
u32 krait_get_l2_indirect_reg(u32 addr)
{
u32 val;
unsigned long flags;
raw_spin_lock_irqsave(&krait_l2_lock, flags);
/*
* Select the L2 window by poking l2cpselr, then read from the window
* via l2cpdr.
*/
asm volatile ("mcr p15, 3, %0, c15, c0, 6 @ l2cpselr" : : "r" (addr));
isb();
asm volatile ("mrc p15, 3, %0, c15, c0, 7 @ l2cpdr" : "=r" (val));
raw_spin_unlock_irqrestore(&krait_l2_lock, flags);
return val;
}
EXPORT_SYMBOL(krait_get_l2_indirect_reg);

View File

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASMARM_KRAIT_L2_ACCESSORS_H
#define __ASMARM_KRAIT_L2_ACCESSORS_H
extern void krait_set_l2_indirect_reg(u32 addr, u32 val);
extern u32 krait_get_l2_indirect_reg(u32 addr);
#endif

View File

@ -1,21 +0,0 @@
/*
* arch/arm/mach-davinci/include/mach/clock.h
*
* Clock control driver for DaVinci - header file
*
* Authors: Vladimir Barinov <source@mvista.com>
*
* 2007 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#ifndef __ASM_ARCH_DAVINCI_CLOCK_H
#define __ASM_ARCH_DAVINCI_CLOCK_H
struct clk;
int davinci_clk_reset_assert(struct clk *c);
int davinci_clk_reset_deassert(struct clk *c);
#endif

View File

@ -287,6 +287,7 @@ source "drivers/clk/actions/Kconfig"
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/imgtec/Kconfig"
source "drivers/clk/ingenic/Kconfig"
source "drivers/clk/keystone/Kconfig"
source "drivers/clk/mediatek/Kconfig"
source "drivers/clk/meson/Kconfig"

View File

@ -72,7 +72,8 @@ obj-$(CONFIG_H8300) += h8300/
obj-$(CONFIG_ARCH_HISI) += hisilicon/
obj-y += imgtec/
obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_MACH_INGENIC) += ingenic/
obj-y += ingenic/
obj-$(CONFIG_ARCH_K3) += keystone/
obj-$(CONFIG_ARCH_KEYSTONE) += keystone/
obj-$(CONFIG_MACH_LOONGSON32) += loongson1/
obj-y += mediatek/

View File

@ -2,6 +2,7 @@ config CLK_ACTIONS
bool "Clock driver for Actions Semi SoCs"
depends on ARCH_ACTIONS || COMPILE_TEST
select REGMAP_MMIO
select RESET_CONTROLLER
default ARCH_ACTIONS
if CLK_ACTIONS

View File

@ -7,6 +7,7 @@ clk-owl-y += owl-divider.o
clk-owl-y += owl-factor.o
clk-owl-y += owl-composite.o
clk-owl-y += owl-pll.o
clk-owl-y += owl-reset.o
# SoC support
obj-$(CONFIG_CLK_OWL_S700) += owl-s700.o

View File

@ -39,7 +39,7 @@ static void owl_clk_set_regmap(const struct owl_clk_desc *desc,
}
int owl_clk_regmap_init(struct platform_device *pdev,
const struct owl_clk_desc *desc)
struct owl_clk_desc *desc)
{
void __iomem *base;
struct regmap *regmap;
@ -57,6 +57,7 @@ int owl_clk_regmap_init(struct platform_device *pdev,
}
owl_clk_set_regmap(desc, regmap);
desc->regmap = regmap;
return 0;
}

View File

@ -26,6 +26,9 @@ struct owl_clk_desc {
struct owl_clk_common **clks;
unsigned long num_clks;
struct clk_hw_onecell_data *hw_clks;
const struct owl_reset_map *resets;
unsigned long num_resets;
struct regmap *regmap;
};
static inline struct owl_clk_common *
@ -35,7 +38,7 @@ static inline struct owl_clk_common *
}
int owl_clk_regmap_init(struct platform_device *pdev,
const struct owl_clk_desc *desc);
struct owl_clk_desc *desc);
int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks);
#endif /* _OWL_COMMON_H_ */

View File

@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Actions Semi Owl SoCs Reset Management Unit driver
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include "owl-reset.h"
static int owl_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct owl_reset *reset = to_owl_reset(rcdev);
const struct owl_reset_map *map = &reset->reset_map[id];
return regmap_update_bits(reset->regmap, map->reg, map->bit, 0);
}
static int owl_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct owl_reset *reset = to_owl_reset(rcdev);
const struct owl_reset_map *map = &reset->reset_map[id];
return regmap_update_bits(reset->regmap, map->reg, map->bit, map->bit);
}
static int owl_reset_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
owl_reset_assert(rcdev, id);
udelay(1);
owl_reset_deassert(rcdev, id);
return 0;
}
static int owl_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct owl_reset *reset = to_owl_reset(rcdev);
const struct owl_reset_map *map = &reset->reset_map[id];
u32 reg;
int ret;
ret = regmap_read(reset->regmap, map->reg, &reg);
if (ret)
return ret;
/*
* The reset control API expects 0 if reset is not asserted,
* which is the opposite of what our hardware uses.
*/
return !(map->bit & reg);
}
const struct reset_control_ops owl_reset_ops = {
.assert = owl_reset_assert,
.deassert = owl_reset_deassert,
.reset = owl_reset_reset,
.status = owl_reset_status,
};

View File

@ -0,0 +1,31 @@
// SPDX-License-Identifier: GPL-2.0-or-later
//
// Actions Semi Owl SoCs Reset Management Unit driver
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_RESET_H_
#define _OWL_RESET_H_
#include <linux/reset-controller.h>
struct owl_reset_map {
u32 reg;
u32 bit;
};
struct owl_reset {
struct reset_controller_dev rcdev;
const struct owl_reset_map *reset_map;
struct regmap *regmap;
};
static inline struct owl_reset *to_owl_reset(struct reset_controller_dev *rcdev)
{
return container_of(rcdev, struct owl_reset, rcdev);
}
extern const struct reset_control_ops owl_reset_ops;
#endif /* _OWL_RESET_H_ */

View File

@ -20,8 +20,10 @@
#include "owl-gate.h"
#include "owl-mux.h"
#include "owl-pll.h"
#include "owl-reset.h"
#include <dt-bindings/clock/actions,s700-cmu.h>
#include <dt-bindings/reset/actions,s700-reset.h>
#define CMU_COREPLL (0x0000)
#define CMU_DEVPLL (0x0004)
@ -569,20 +571,69 @@ static struct clk_hw_onecell_data s700_hw_clks = {
.num = CLK_NR_CLKS,
};
static const struct owl_clk_desc s700_clk_desc = {
static const struct owl_reset_map s700_resets[] = {
[RESET_DE] = { CMU_DEVRST0, BIT(0) },
[RESET_LCD0] = { CMU_DEVRST0, BIT(1) },
[RESET_DSI] = { CMU_DEVRST0, BIT(2) },
[RESET_CSI] = { CMU_DEVRST0, BIT(13) },
[RESET_SI] = { CMU_DEVRST0, BIT(14) },
[RESET_I2C0] = { CMU_DEVRST1, BIT(0) },
[RESET_I2C1] = { CMU_DEVRST1, BIT(1) },
[RESET_I2C2] = { CMU_DEVRST1, BIT(2) },
[RESET_I2C3] = { CMU_DEVRST1, BIT(3) },
[RESET_SPI0] = { CMU_DEVRST1, BIT(4) },
[RESET_SPI1] = { CMU_DEVRST1, BIT(5) },
[RESET_SPI2] = { CMU_DEVRST1, BIT(6) },
[RESET_SPI3] = { CMU_DEVRST1, BIT(7) },
[RESET_UART0] = { CMU_DEVRST1, BIT(8) },
[RESET_UART1] = { CMU_DEVRST1, BIT(9) },
[RESET_UART2] = { CMU_DEVRST1, BIT(10) },
[RESET_UART3] = { CMU_DEVRST1, BIT(11) },
[RESET_UART4] = { CMU_DEVRST1, BIT(12) },
[RESET_UART5] = { CMU_DEVRST1, BIT(13) },
[RESET_UART6] = { CMU_DEVRST1, BIT(14) },
[RESET_KEY] = { CMU_DEVRST1, BIT(24) },
[RESET_GPIO] = { CMU_DEVRST1, BIT(25) },
[RESET_AUDIO] = { CMU_DEVRST1, BIT(29) },
};
static struct owl_clk_desc s700_clk_desc = {
.clks = s700_clks,
.num_clks = ARRAY_SIZE(s700_clks),
.hw_clks = &s700_hw_clks,
.resets = s700_resets,
.num_resets = ARRAY_SIZE(s700_resets),
};
static int s700_clk_probe(struct platform_device *pdev)
{
const struct owl_clk_desc *desc;
struct owl_clk_desc *desc;
struct owl_reset *reset;
int ret;
desc = &s700_clk_desc;
owl_clk_regmap_init(pdev, desc);
/*
* FIXME: Reset controller registration should be moved to
* common code, once all SoCs of Owl family supports it.
*/
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
if (!reset)
return -ENOMEM;
reset->rcdev.of_node = pdev->dev.of_node;
reset->rcdev.ops = &owl_reset_ops;
reset->rcdev.nr_resets = desc->num_resets;
reset->reset_map = desc->resets;
reset->regmap = desc->regmap;
ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
if (ret)
dev_err(&pdev->dev, "Failed to register reset controller\n");
return owl_clk_probe(&pdev->dev, desc->hw_clks);
}

View File

@ -19,8 +19,10 @@
#include "owl-gate.h"
#include "owl-mux.h"
#include "owl-pll.h"
#include "owl-reset.h"
#include <dt-bindings/clock/actions,s900-cmu.h>
#include <dt-bindings/reset/actions,s900-reset.h>
#define CMU_COREPLL (0x0000)
#define CMU_DEVPLL (0x0004)
@ -684,20 +686,100 @@ static struct clk_hw_onecell_data s900_hw_clks = {
.num = CLK_NR_CLKS,
};
static const struct owl_clk_desc s900_clk_desc = {
static const struct owl_reset_map s900_resets[] = {
[RESET_DMAC] = { CMU_DEVRST0, BIT(0) },
[RESET_SRAMI] = { CMU_DEVRST0, BIT(1) },
[RESET_DDR_CTL_PHY] = { CMU_DEVRST0, BIT(2) },
[RESET_NANDC0] = { CMU_DEVRST0, BIT(3) },
[RESET_SD0] = { CMU_DEVRST0, BIT(4) },
[RESET_SD1] = { CMU_DEVRST0, BIT(5) },
[RESET_PCM1] = { CMU_DEVRST0, BIT(6) },
[RESET_DE] = { CMU_DEVRST0, BIT(7) },
[RESET_LVDS] = { CMU_DEVRST0, BIT(8) },
[RESET_SD2] = { CMU_DEVRST0, BIT(9) },
[RESET_DSI] = { CMU_DEVRST0, BIT(10) },
[RESET_CSI0] = { CMU_DEVRST0, BIT(11) },
[RESET_BISP_AXI] = { CMU_DEVRST0, BIT(12) },
[RESET_CSI1] = { CMU_DEVRST0, BIT(13) },
[RESET_GPIO] = { CMU_DEVRST0, BIT(15) },
[RESET_EDP] = { CMU_DEVRST0, BIT(16) },
[RESET_AUDIO] = { CMU_DEVRST0, BIT(17) },
[RESET_PCM0] = { CMU_DEVRST0, BIT(18) },
[RESET_HDE] = { CMU_DEVRST0, BIT(21) },
[RESET_GPU3D_PA] = { CMU_DEVRST0, BIT(22) },
[RESET_IMX] = { CMU_DEVRST0, BIT(23) },
[RESET_SE] = { CMU_DEVRST0, BIT(24) },
[RESET_NANDC1] = { CMU_DEVRST0, BIT(25) },
[RESET_SD3] = { CMU_DEVRST0, BIT(26) },
[RESET_GIC] = { CMU_DEVRST0, BIT(27) },
[RESET_GPU3D_PB] = { CMU_DEVRST0, BIT(28) },
[RESET_DDR_CTL_PHY_AXI] = { CMU_DEVRST0, BIT(29) },
[RESET_CMU_DDR] = { CMU_DEVRST0, BIT(30) },
[RESET_DMM] = { CMU_DEVRST0, BIT(31) },
[RESET_USB2HUB] = { CMU_DEVRST1, BIT(0) },
[RESET_USB2HSIC] = { CMU_DEVRST1, BIT(1) },
[RESET_HDMI] = { CMU_DEVRST1, BIT(2) },
[RESET_HDCP2TX] = { CMU_DEVRST1, BIT(3) },
[RESET_UART6] = { CMU_DEVRST1, BIT(4) },
[RESET_UART0] = { CMU_DEVRST1, BIT(5) },
[RESET_UART1] = { CMU_DEVRST1, BIT(6) },
[RESET_UART2] = { CMU_DEVRST1, BIT(7) },
[RESET_SPI0] = { CMU_DEVRST1, BIT(8) },
[RESET_SPI1] = { CMU_DEVRST1, BIT(9) },
[RESET_SPI2] = { CMU_DEVRST1, BIT(10) },
[RESET_SPI3] = { CMU_DEVRST1, BIT(11) },
[RESET_I2C0] = { CMU_DEVRST1, BIT(12) },
[RESET_I2C1] = { CMU_DEVRST1, BIT(13) },
[RESET_USB3] = { CMU_DEVRST1, BIT(14) },
[RESET_UART3] = { CMU_DEVRST1, BIT(15) },
[RESET_UART4] = { CMU_DEVRST1, BIT(16) },
[RESET_UART5] = { CMU_DEVRST1, BIT(17) },
[RESET_I2C2] = { CMU_DEVRST1, BIT(18) },
[RESET_I2C3] = { CMU_DEVRST1, BIT(19) },
[RESET_ETHERNET] = { CMU_DEVRST1, BIT(20) },
[RESET_CHIPID] = { CMU_DEVRST1, BIT(21) },
[RESET_I2C4] = { CMU_DEVRST1, BIT(22) },
[RESET_I2C5] = { CMU_DEVRST1, BIT(23) },
[RESET_CPU_SCNT] = { CMU_DEVRST1, BIT(30) }
};
static struct owl_clk_desc s900_clk_desc = {
.clks = s900_clks,
.num_clks = ARRAY_SIZE(s900_clks),
.hw_clks = &s900_hw_clks,
.resets = s900_resets,
.num_resets = ARRAY_SIZE(s900_resets),
};
static int s900_clk_probe(struct platform_device *pdev)
{
const struct owl_clk_desc *desc;
struct owl_clk_desc *desc;
struct owl_reset *reset;
int ret;
desc = &s900_clk_desc;
owl_clk_regmap_init(pdev, desc);
/*
* FIXME: Reset controller registration should be moved to
* common code, once all SoCs of Owl family supports it.
*/
reset = devm_kzalloc(&pdev->dev, sizeof(*reset), GFP_KERNEL);
if (!reset)
return -ENOMEM;
reset->rcdev.of_node = pdev->dev.of_node;
reset->rcdev.ops = &owl_reset_ops;
reset->rcdev.nr_resets = desc->num_resets;
reset->reset_map = desc->resets;
reset->regmap = desc->regmap;
ret = devm_reset_controller_register(&pdev->dev, &reset->rcdev);
if (ret)
dev_err(&pdev->dev, "Failed to register reset controller\n");
return owl_clk_probe(&pdev->dev, desc->hw_clks);
}

View File

@ -3,7 +3,7 @@
# Makefile for at91 specific clk
#
obj-y += pmc.o sckc.o
obj-y += pmc.o sckc.o dt-compat.o
obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o
obj-y += clk-system.o clk-peripheral.o clk-programmable.o
@ -14,3 +14,6 @@ obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
obj-$(CONFIG_HAVE_AT91_I2S_MUX_CLK) += clk-i2s-mux.o
obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o at91sam9rl.o at91sam9x5.o
obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o

View File

@ -0,0 +1,494 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
struct sck {
char *n;
char *p;
u8 id;
};
struct pck {
char *n;
u8 id;
};
struct at91sam926x_data {
const struct clk_pll_layout *plla_layout;
const struct clk_pll_characteristics *plla_characteristics;
const struct clk_pll_layout *pllb_layout;
const struct clk_pll_characteristics *pllb_characteristics;
const struct clk_master_characteristics *mck_characteristics;
const struct sck *sck;
const struct pck *pck;
u8 num_sck;
u8 num_pck;
u8 num_progck;
bool has_slck;
};
static const struct clk_master_characteristics sam9260_mck_characteristics = {
.output = { .min = 0, .max = 105000000 },
.divisors = { 1, 2, 4, 0 },
};
static u8 sam9260_plla_out[] = { 0, 2 };
static u16 sam9260_plla_icpll[] = { 1, 1 };
static struct clk_range sam9260_plla_outputs[] = {
{ .min = 80000000, .max = 160000000 },
{ .min = 150000000, .max = 240000000 },
};
static const struct clk_pll_characteristics sam9260_plla_characteristics = {
.input = { .min = 1000000, .max = 32000000 },
.num_output = ARRAY_SIZE(sam9260_plla_outputs),
.output = sam9260_plla_outputs,
.icpll = sam9260_plla_icpll,
.out = sam9260_plla_out,
};
static u8 sam9260_pllb_out[] = { 1 };
static u16 sam9260_pllb_icpll[] = { 1 };
static struct clk_range sam9260_pllb_outputs[] = {
{ .min = 70000000, .max = 130000000 },
};
static const struct clk_pll_characteristics sam9260_pllb_characteristics = {
.input = { .min = 1000000, .max = 5000000 },
.num_output = ARRAY_SIZE(sam9260_pllb_outputs),
.output = sam9260_pllb_outputs,
.icpll = sam9260_pllb_icpll,
.out = sam9260_pllb_out,
};
static const struct sck at91sam9260_systemck[] = {
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
};
static const struct pck at91sam9260_periphck[] = {
{ .n = "pioA_clk", .id = 2 },
{ .n = "pioB_clk", .id = 3 },
{ .n = "pioC_clk", .id = 4 },
{ .n = "adc_clk", .id = 5 },
{ .n = "usart0_clk", .id = 6 },
{ .n = "usart1_clk", .id = 7 },
{ .n = "usart2_clk", .id = 8 },
{ .n = "mci0_clk", .id = 9 },
{ .n = "udc_clk", .id = 10 },
{ .n = "twi0_clk", .id = 11 },
{ .n = "spi0_clk", .id = 12 },
{ .n = "spi1_clk", .id = 13 },
{ .n = "ssc0_clk", .id = 14 },
{ .n = "tc0_clk", .id = 17 },
{ .n = "tc1_clk", .id = 18 },
{ .n = "tc2_clk", .id = 19 },
{ .n = "ohci_clk", .id = 20 },
{ .n = "macb0_clk", .id = 21 },
{ .n = "isi_clk", .id = 22 },
{ .n = "usart3_clk", .id = 23 },
{ .n = "uart0_clk", .id = 24 },
{ .n = "uart1_clk", .id = 25 },
{ .n = "tc3_clk", .id = 26 },
{ .n = "tc4_clk", .id = 27 },
{ .n = "tc5_clk", .id = 28 },
};
static struct at91sam926x_data at91sam9260_data = {
.plla_layout = &at91rm9200_pll_layout,
.plla_characteristics = &sam9260_plla_characteristics,
.pllb_layout = &at91rm9200_pll_layout,
.pllb_characteristics = &sam9260_pllb_characteristics,
.mck_characteristics = &sam9260_mck_characteristics,
.sck = at91sam9260_systemck,
.num_sck = ARRAY_SIZE(at91sam9260_systemck),
.pck = at91sam9260_periphck,
.num_pck = ARRAY_SIZE(at91sam9260_periphck),
.num_progck = 2,
.has_slck = true,
};
static const struct clk_master_characteristics sam9g20_mck_characteristics = {
.output = { .min = 0, .max = 133000000 },
.divisors = { 1, 2, 4, 6 },
};
static u8 sam9g20_plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
static u16 sam9g20_plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
static struct clk_range sam9g20_plla_outputs[] = {
{ .min = 745000000, .max = 800000000 },
{ .min = 695000000, .max = 750000000 },
{ .min = 645000000, .max = 700000000 },
{ .min = 595000000, .max = 650000000 },
{ .min = 545000000, .max = 600000000 },
{ .min = 495000000, .max = 550000000 },
{ .min = 445000000, .max = 500000000 },
{ .min = 400000000, .max = 450000000 },
};
static const struct clk_pll_characteristics sam9g20_plla_characteristics = {
.input = { .min = 2000000, .max = 32000000 },
.num_output = ARRAY_SIZE(sam9g20_plla_outputs),
.output = sam9g20_plla_outputs,
.icpll = sam9g20_plla_icpll,
.out = sam9g20_plla_out,
};
static u8 sam9g20_pllb_out[] = { 0 };
static u16 sam9g20_pllb_icpll[] = { 0 };
static struct clk_range sam9g20_pllb_outputs[] = {
{ .min = 30000000, .max = 100000000 },
};
static const struct clk_pll_characteristics sam9g20_pllb_characteristics = {
.input = { .min = 2000000, .max = 32000000 },
.num_output = ARRAY_SIZE(sam9g20_pllb_outputs),
.output = sam9g20_pllb_outputs,
.icpll = sam9g20_pllb_icpll,
.out = sam9g20_pllb_out,
};
static struct at91sam926x_data at91sam9g20_data = {
.plla_layout = &at91sam9g45_pll_layout,
.plla_characteristics = &sam9g20_plla_characteristics,
.pllb_layout = &at91sam9g20_pllb_layout,
.pllb_characteristics = &sam9g20_pllb_characteristics,
.mck_characteristics = &sam9g20_mck_characteristics,
.sck = at91sam9260_systemck,
.num_sck = ARRAY_SIZE(at91sam9260_systemck),
.pck = at91sam9260_periphck,
.num_pck = ARRAY_SIZE(at91sam9260_periphck),
.num_progck = 2,
.has_slck = true,
};
static const struct clk_master_characteristics sam9261_mck_characteristics = {
.output = { .min = 0, .max = 94000000 },
.divisors = { 1, 2, 4, 0 },
};
static struct clk_range sam9261_plla_outputs[] = {
{ .min = 80000000, .max = 200000000 },
{ .min = 190000000, .max = 240000000 },
};
static const struct clk_pll_characteristics sam9261_plla_characteristics = {
.input = { .min = 1000000, .max = 32000000 },
.num_output = ARRAY_SIZE(sam9261_plla_outputs),
.output = sam9261_plla_outputs,
.icpll = sam9260_plla_icpll,
.out = sam9260_plla_out,
};
static u8 sam9261_pllb_out[] = { 1 };
static u16 sam9261_pllb_icpll[] = { 1 };
static struct clk_range sam9261_pllb_outputs[] = {
{ .min = 70000000, .max = 130000000 },
};
static const struct clk_pll_characteristics sam9261_pllb_characteristics = {
.input = { .min = 1000000, .max = 5000000 },
.num_output = ARRAY_SIZE(sam9261_pllb_outputs),
.output = sam9261_pllb_outputs,
.icpll = sam9261_pllb_icpll,
.out = sam9261_pllb_out,
};
static const struct sck at91sam9261_systemck[] = {
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "pck3", .p = "prog3", .id = 11 },
{ .n = "hclk0", .p = "masterck", .id = 16 },
{ .n = "hclk1", .p = "masterck", .id = 17 },
};
static const struct pck at91sam9261_periphck[] = {
{ .n = "pioA_clk", .id = 2, },
{ .n = "pioB_clk", .id = 3, },
{ .n = "pioC_clk", .id = 4, },
{ .n = "usart0_clk", .id = 6, },
{ .n = "usart1_clk", .id = 7, },
{ .n = "usart2_clk", .id = 8, },
{ .n = "mci0_clk", .id = 9, },
{ .n = "udc_clk", .id = 10, },
{ .n = "twi0_clk", .id = 11, },
{ .n = "spi0_clk", .id = 12, },
{ .n = "spi1_clk", .id = 13, },
{ .n = "ssc0_clk", .id = 14, },
{ .n = "ssc1_clk", .id = 15, },
{ .n = "ssc2_clk", .id = 16, },
{ .n = "tc0_clk", .id = 17, },
{ .n = "tc1_clk", .id = 18, },
{ .n = "tc2_clk", .id = 19, },
{ .n = "ohci_clk", .id = 20, },
{ .n = "lcd_clk", .id = 21, },
};
static struct at91sam926x_data at91sam9261_data = {
.plla_layout = &at91rm9200_pll_layout,
.plla_characteristics = &sam9261_plla_characteristics,
.pllb_layout = &at91rm9200_pll_layout,
.pllb_characteristics = &sam9261_pllb_characteristics,
.mck_characteristics = &sam9261_mck_characteristics,
.sck = at91sam9261_systemck,
.num_sck = ARRAY_SIZE(at91sam9261_systemck),
.pck = at91sam9261_periphck,
.num_pck = ARRAY_SIZE(at91sam9261_periphck),
.num_progck = 4,
};
static const struct clk_master_characteristics sam9263_mck_characteristics = {
.output = { .min = 0, .max = 120000000 },
.divisors = { 1, 2, 4, 0 },
};
static struct clk_range sam9263_pll_outputs[] = {
{ .min = 80000000, .max = 200000000 },
{ .min = 190000000, .max = 240000000 },
};
static const struct clk_pll_characteristics sam9263_pll_characteristics = {
.input = { .min = 1000000, .max = 32000000 },
.num_output = ARRAY_SIZE(sam9263_pll_outputs),
.output = sam9263_pll_outputs,
.icpll = sam9260_plla_icpll,
.out = sam9260_plla_out,
};
static const struct sck at91sam9263_systemck[] = {
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "pck3", .p = "prog3", .id = 11 },
};
static const struct pck at91sam9263_periphck[] = {
{ .n = "pioA_clk", .id = 2, },
{ .n = "pioB_clk", .id = 3, },
{ .n = "pioCDE_clk", .id = 4, },
{ .n = "usart0_clk", .id = 7, },
{ .n = "usart1_clk", .id = 8, },
{ .n = "usart2_clk", .id = 9, },
{ .n = "mci0_clk", .id = 10, },
{ .n = "mci1_clk", .id = 11, },
{ .n = "can_clk", .id = 12, },
{ .n = "twi0_clk", .id = 13, },
{ .n = "spi0_clk", .id = 14, },
{ .n = "spi1_clk", .id = 15, },
{ .n = "ssc0_clk", .id = 16, },
{ .n = "ssc1_clk", .id = 17, },
{ .n = "ac97_clk", .id = 18, },
{ .n = "tcb_clk", .id = 19, },
{ .n = "pwm_clk", .id = 20, },
{ .n = "macb0_clk", .id = 21, },
{ .n = "g2de_clk", .id = 23, },
{ .n = "udc_clk", .id = 24, },
{ .n = "isi_clk", .id = 25, },
{ .n = "lcd_clk", .id = 26, },
{ .n = "dma_clk", .id = 27, },
{ .n = "ohci_clk", .id = 29, },
};
static struct at91sam926x_data at91sam9263_data = {
.plla_layout = &at91rm9200_pll_layout,
.plla_characteristics = &sam9263_pll_characteristics,
.pllb_layout = &at91rm9200_pll_layout,
.pllb_characteristics = &sam9263_pll_characteristics,
.mck_characteristics = &sam9263_mck_characteristics,
.sck = at91sam9263_systemck,
.num_sck = ARRAY_SIZE(at91sam9263_systemck),
.pck = at91sam9263_periphck,
.num_pck = ARRAY_SIZE(at91sam9263_periphck),
.num_progck = 4,
};
static void __init at91sam926x_pmc_setup(struct device_node *np,
struct at91sam926x_data *data)
{
const char *slowxtal_name, *mainxtal_name;
struct pmc_data *at91sam9260_pmc;
u32 usb_div[] = { 1, 2, 4, 0 };
const char *parent_names[6];
const char *slck_name;
struct regmap *regmap;
struct clk_hw *hw;
int i;
bool bypass;
i = of_property_match_string(np, "clock-names", "slow_xtal");
if (i < 0)
return;
slowxtal_name = of_clk_get_parent_name(np, i);
i = of_property_match_string(np, "clock-names", "main_xtal");
if (i < 0)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap))
return;
at91sam9260_pmc = pmc_data_allocate(PMC_MAIN + 1,
ndck(data->sck, data->num_sck),
ndck(data->pck, data->num_pck), 0);
if (!at91sam9260_pmc)
return;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
bypass);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_rm9200_main(regmap, "mainck", "main_osc");
if (IS_ERR(hw))
goto err_free;
at91sam9260_pmc->chws[PMC_MAIN] = hw;
if (data->has_slck) {
hw = clk_hw_register_fixed_rate_with_accuracy(NULL,
"slow_rc_osc",
NULL, 0, 32768,
50000000);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "slow_rc_osc";
parent_names[1] = "slow_xtal";
hw = at91_clk_register_sam9260_slow(regmap, "slck",
parent_names, 2);
if (IS_ERR(hw))
goto err_free;
at91sam9260_pmc->chws[PMC_SLOW] = hw;
slck_name = "slck";
} else {
slck_name = slowxtal_name;
}
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
data->plla_layout,
data->plla_characteristics);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_pll(regmap, "pllbck", "mainck", 1,
data->pllb_layout,
data->pllb_characteristics);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91rm9200_master_layout,
data->mck_characteristics);
if (IS_ERR(hw))
goto err_free;
at91sam9260_pmc->chws[PMC_MCK] = hw;
hw = at91rm9200_clk_register_usb(regmap, "usbck", "pllbck", usb_div);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "pllbck";
for (i = 0; i < data->num_progck; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 4, i,
&at91rm9200_programmable_layout);
if (IS_ERR(hw))
goto err_free;
}
for (i = 0; i < data->num_sck; i++) {
hw = at91_clk_register_system(regmap, data->sck[i].n,
data->sck[i].p,
data->sck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9260_pmc->shws[data->sck[i].id] = hw;
}
for (i = 0; i < data->num_pck; i++) {
hw = at91_clk_register_peripheral(regmap,
data->pck[i].n,
"masterck",
data->pck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9260_pmc->phws[data->pck[i].id] = hw;
}
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9260_pmc);
return;
err_free:
pmc_data_free(at91sam9260_pmc);
}
static void __init at91sam9260_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9260_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9260_pmc, "atmel,at91sam9260-pmc",
at91sam9260_pmc_setup);
static void __init at91sam9261_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9261_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9261_pmc, "atmel,at91sam9261-pmc",
at91sam9261_pmc_setup);
static void __init at91sam9263_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9263_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9263_pmc, "atmel,at91sam9263-pmc",
at91sam9263_pmc_setup);
static void __init at91sam9g20_pmc_setup(struct device_node *np)
{
at91sam926x_pmc_setup(np, &at91sam9g20_data);
}
CLK_OF_DECLARE_DRIVER(at91sam9g20_pmc, "atmel,at91sam9g20-pmc",
at91sam9g20_pmc_setup);

View File

@ -0,0 +1,171 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
static const struct clk_master_characteristics sam9rl_mck_characteristics = {
.output = { .min = 0, .max = 94000000 },
.divisors = { 1, 2, 4, 0 },
};
static u8 sam9rl_plla_out[] = { 0, 2 };
static struct clk_range sam9rl_plla_outputs[] = {
{ .min = 80000000, .max = 200000000 },
{ .min = 190000000, .max = 240000000 },
};
static const struct clk_pll_characteristics sam9rl_plla_characteristics = {
.input = { .min = 1000000, .max = 32000000 },
.num_output = ARRAY_SIZE(sam9rl_plla_outputs),
.output = sam9rl_plla_outputs,
.out = sam9rl_plla_out,
};
static const struct {
char *n;
char *p;
u8 id;
} at91sam9rl_systemck[] = {
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
};
static const struct {
char *n;
u8 id;
} at91sam9rl_periphck[] = {
{ .n = "pioA_clk", .id = 2, },
{ .n = "pioB_clk", .id = 3, },
{ .n = "pioC_clk", .id = 4, },
{ .n = "pioD_clk", .id = 5, },
{ .n = "usart0_clk", .id = 6, },
{ .n = "usart1_clk", .id = 7, },
{ .n = "usart2_clk", .id = 8, },
{ .n = "usart3_clk", .id = 9, },
{ .n = "mci0_clk", .id = 10, },
{ .n = "twi0_clk", .id = 11, },
{ .n = "twi1_clk", .id = 12, },
{ .n = "spi0_clk", .id = 13, },
{ .n = "ssc0_clk", .id = 14, },
{ .n = "ssc1_clk", .id = 15, },
{ .n = "tc0_clk", .id = 16, },
{ .n = "tc1_clk", .id = 17, },
{ .n = "tc2_clk", .id = 18, },
{ .n = "pwm_clk", .id = 19, },
{ .n = "adc_clk", .id = 20, },
{ .n = "dma0_clk", .id = 21, },
{ .n = "udphs_clk", .id = 22, },
{ .n = "lcd_clk", .id = 23, },
};
static void __init at91sam9rl_pmc_setup(struct device_node *np)
{
const char *slck_name, *mainxtal_name;
struct pmc_data *at91sam9rl_pmc;
const char *parent_names[6];
struct regmap *regmap;
struct clk_hw *hw;
int i;
i = of_property_match_string(np, "clock-names", "slow_clk");
if (i < 0)
return;
slck_name = of_clk_get_parent_name(np, i);
i = of_property_match_string(np, "clock-names", "main_xtal");
if (i < 0)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap))
return;
at91sam9rl_pmc = pmc_data_allocate(PMC_MAIN + 1,
nck(at91sam9rl_systemck),
nck(at91sam9rl_periphck), 0);
if (!at91sam9rl_pmc)
return;
hw = at91_clk_register_rm9200_main(regmap, "mainck", mainxtal_name);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->chws[PMC_MAIN] = hw;
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
&at91rm9200_pll_layout,
&sam9rl_plla_characteristics);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->chws[PMC_UTMI] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91rm9200_master_layout,
&sam9rl_mck_characteristics);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->chws[PMC_MCK] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "pllack";
parent_names[3] = "utmick";
parent_names[4] = "masterck";
for (i = 0; i < 2; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
&at91rm9200_programmable_layout);
if (IS_ERR(hw))
goto err_free;
}
for (i = 0; i < ARRAY_SIZE(at91sam9rl_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9rl_systemck[i].n,
at91sam9rl_systemck[i].p,
at91sam9rl_systemck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->shws[at91sam9rl_systemck[i].id] = hw;
}
for (i = 0; i < ARRAY_SIZE(at91sam9rl_periphck); i++) {
hw = at91_clk_register_peripheral(regmap,
at91sam9rl_periphck[i].n,
"masterck",
at91sam9rl_periphck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9rl_pmc->phws[at91sam9rl_periphck[i].id] = hw;
}
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9rl_pmc);
return;
err_free:
pmc_data_free(at91sam9rl_pmc);
}
CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup);

View File

@ -0,0 +1,309 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 0, .max = 133333333 },
.divisors = { 1, 2, 4, 3 },
.have_div3_pres = 1,
};
static u8 plla_out[] = { 0, 1, 2, 3, 0, 1, 2, 3 };
static u16 plla_icpll[] = { 0, 0, 0, 0, 1, 1, 1, 1 };
static struct clk_range plla_outputs[] = {
{ .min = 745000000, .max = 800000000 },
{ .min = 695000000, .max = 750000000 },
{ .min = 645000000, .max = 700000000 },
{ .min = 595000000, .max = 650000000 },
{ .min = 545000000, .max = 600000000 },
{ .min = 495000000, .max = 555000000 },
{ .min = 445000000, .max = 500000000 },
{ .min = 400000000, .max = 450000000 },
};
static const struct clk_pll_characteristics plla_characteristics = {
.input = { .min = 2000000, .max = 32000000 },
.num_output = ARRAY_SIZE(plla_outputs),
.output = plla_outputs,
.icpll = plla_icpll,
.out = plla_out,
};
static const struct {
char *n;
char *p;
u8 id;
} at91sam9x5_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
};
struct pck {
char *n;
u8 id;
};
static const struct pck at91sam9x5_periphck[] = {
{ .n = "pioAB_clk", .id = 2, },
{ .n = "pioCD_clk", .id = 3, },
{ .n = "smd_clk", .id = 4, },
{ .n = "usart0_clk", .id = 5, },
{ .n = "usart1_clk", .id = 6, },
{ .n = "usart2_clk", .id = 7, },
{ .n = "twi0_clk", .id = 9, },
{ .n = "twi1_clk", .id = 10, },
{ .n = "twi2_clk", .id = 11, },
{ .n = "mci0_clk", .id = 12, },
{ .n = "spi0_clk", .id = 13, },
{ .n = "spi1_clk", .id = 14, },
{ .n = "uart0_clk", .id = 15, },
{ .n = "uart1_clk", .id = 16, },
{ .n = "tcb0_clk", .id = 17, },
{ .n = "pwm_clk", .id = 18, },
{ .n = "adc_clk", .id = 19, },
{ .n = "dma0_clk", .id = 20, },
{ .n = "dma1_clk", .id = 21, },
{ .n = "uhphs_clk", .id = 22, },
{ .n = "udphs_clk", .id = 23, },
{ .n = "mci1_clk", .id = 26, },
{ .n = "ssc0_clk", .id = 28, },
};
static const struct pck at91sam9g15_periphck[] = {
{ .n = "lcdc_clk", .id = 25, },
{ /* sentinel */}
};
static const struct pck at91sam9g25_periphck[] = {
{ .n = "usart3_clk", .id = 8, },
{ .n = "macb0_clk", .id = 24, },
{ .n = "isi_clk", .id = 25, },
{ /* sentinel */}
};
static const struct pck at91sam9g35_periphck[] = {
{ .n = "macb0_clk", .id = 24, },
{ .n = "lcdc_clk", .id = 25, },
{ /* sentinel */}
};
static const struct pck at91sam9x25_periphck[] = {
{ .n = "usart3_clk", .id = 8, },
{ .n = "macb0_clk", .id = 24, },
{ .n = "macb1_clk", .id = 27, },
{ .n = "can0_clk", .id = 29, },
{ .n = "can1_clk", .id = 30, },
{ /* sentinel */}
};
static const struct pck at91sam9x35_periphck[] = {
{ .n = "macb0_clk", .id = 24, },
{ .n = "lcdc_clk", .id = 25, },
{ .n = "can0_clk", .id = 29, },
{ .n = "can1_clk", .id = 30, },
{ /* sentinel */}
};
static void __init at91sam9x5_pmc_setup(struct device_node *np,
const struct pck *extra_pcks,
bool has_lcdck)
{
struct clk_range range = CLK_RANGE(0, 0);
const char *slck_name, *mainxtal_name;
struct pmc_data *at91sam9x5_pmc;
const char *parent_names[6];
struct regmap *regmap;
struct clk_hw *hw;
int i;
bool bypass;
i = of_property_match_string(np, "clock-names", "slow_clk");
if (i < 0)
return;
slck_name = of_clk_get_parent_name(np, i);
i = of_property_match_string(np, "clock-names", "main_xtal");
if (i < 0)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap))
return;
at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
nck(at91sam9x5_systemck),
nck(at91sam9x35_periphck), 0);
if (!at91sam9x5_pmc)
return;
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
50000000);
if (IS_ERR(hw))
goto err_free;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->chws[PMC_MAIN] = hw;
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
&at91rm9200_pll_layout, &plla_characteristics);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->chws[PMC_UTMI] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->chws[PMC_MCK] = hw;
parent_names[0] = "plladivck";
parent_names[1] = "utmick";
hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "mck";
for (i = 0; i < 2; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
&at91sam9x5_programmable_layout);
if (IS_ERR(hw))
goto err_free;
}
for (i = 0; i < ARRAY_SIZE(at91sam9x5_systemck); i++) {
hw = at91_clk_register_system(regmap, at91sam9x5_systemck[i].n,
at91sam9x5_systemck[i].p,
at91sam9x5_systemck[i].id);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->shws[at91sam9x5_systemck[i].id] = hw;
}
if (has_lcdck) {
hw = at91_clk_register_system(regmap, "lcdck", "masterck", 3);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->shws[3] = hw;
}
for (i = 0; i < ARRAY_SIZE(at91sam9x5_periphck); i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
at91sam9x5_periphck[i].n,
"masterck",
at91sam9x5_periphck[i].id,
&range);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->phws[at91sam9x5_periphck[i].id] = hw;
}
for (i = 0; extra_pcks[i].id; i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
extra_pcks[i].n,
"masterck",
extra_pcks[i].id,
&range);
if (IS_ERR(hw))
goto err_free;
at91sam9x5_pmc->phws[extra_pcks[i].id] = hw;
}
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, at91sam9x5_pmc);
return;
err_free:
pmc_data_free(at91sam9x5_pmc);
}
static void __init at91sam9g15_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9g15_pmc, "atmel,at91sam9g15-pmc",
at91sam9g15_pmc_setup);
static void __init at91sam9g25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false);
}
CLK_OF_DECLARE_DRIVER(at91sam9g25_pmc, "atmel,at91sam9g25-pmc",
at91sam9g25_pmc_setup);
static void __init at91sam9g35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9g35_pmc, "atmel,at91sam9g35-pmc",
at91sam9g35_pmc_setup);
static void __init at91sam9x25_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false);
}
CLK_OF_DECLARE_DRIVER(at91sam9x25_pmc, "atmel,at91sam9x25-pmc",
at91sam9x25_pmc_setup);
static void __init at91sam9x35_pmc_setup(struct device_node *np)
{
at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true);
}
CLK_OF_DECLARE_DRIVER(at91sam9x35_pmc, "atmel,at91sam9x35-pmc",
at91sam9x35_pmc_setup);

View File

@ -43,6 +43,8 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include "pmc.h"
#define AUDIO_PLL_DIV_FRAC BIT(22)
#define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \
AT91_PMC_AUDIO_PLL_ND_OFFSET)
@ -444,93 +446,94 @@ static const struct clk_ops audio_pll_pmc_ops = {
.set_rate = clk_audio_pll_pmc_set_rate,
};
static int of_sama5d2_clk_audio_pll_setup(struct device_node *np,
struct clk_init_data *init,
struct clk_hw *hw,
struct regmap **clk_audio_regmap)
{
struct regmap *regmap;
const char *parent_names[1];
int ret;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return PTR_ERR(regmap);
init->name = np->name;
of_clk_parent_fill(np, parent_names, 1);
init->parent_names = parent_names;
init->num_parents = 1;
hw->init = init;
*clk_audio_regmap = regmap;
ret = clk_hw_register(NULL, hw);
if (ret)
return ret;
return of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
struct clk_hw * __init
at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_audio_frac *frac_ck;
struct clk_init_data init = {};
int ret;
frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL);
if (!frac_ck)
return;
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &audio_pll_frac_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_GATE;
if (of_sama5d2_clk_audio_pll_setup(np, &init, &frac_ck->hw,
&frac_ck->regmap))
frac_ck->hw.init = &init;
frac_ck->regmap = regmap;
ret = clk_hw_register(NULL, &frac_ck->hw);
if (ret) {
kfree(frac_ck);
return ERR_PTR(ret);
}
return &frac_ck->hw;
}
static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
struct clk_hw * __init
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_audio_pad *apad_ck;
struct clk_init_data init = {};
struct clk_init_data init;
int ret;
apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL);
if (!apad_ck)
return;
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &audio_pll_pad_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
CLK_SET_RATE_PARENT;
if (of_sama5d2_clk_audio_pll_setup(np, &init, &apad_ck->hw,
&apad_ck->regmap))
apad_ck->hw.init = &init;
apad_ck->regmap = regmap;
ret = clk_hw_register(NULL, &apad_ck->hw);
if (ret) {
kfree(apad_ck);
return ERR_PTR(ret);
}
return &apad_ck->hw;
}
static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
struct clk_hw * __init
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_audio_pad *apmc_ck;
struct clk_init_data init = {};
struct clk_audio_pmc *apmc_ck;
struct clk_init_data init;
int ret;
apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL);
if (!apmc_ck)
return;
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &audio_pll_pmc_ops;
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE |
CLK_SET_RATE_PARENT;
if (of_sama5d2_clk_audio_pll_setup(np, &init, &apmc_ck->hw,
&apmc_ck->regmap))
kfree(apmc_ck);
}
apmc_ck->hw.init = &init;
apmc_ck->regmap = regmap;
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
"atmel,sama5d2-clk-audio-pll-frac",
of_sama5d2_clk_audio_pll_frac_setup);
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
"atmel,sama5d2-clk-audio-pll-pad",
of_sama5d2_clk_audio_pll_pad_setup);
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
"atmel,sama5d2-clk-audio-pll-pmc",
of_sama5d2_clk_audio_pll_pmc_setup);
ret = clk_hw_register(NULL, &apmc_ck->hw);
if (ret) {
kfree(apmc_ck);
return ERR_PTR(ret);
}
return &apmc_ck->hw;
}

View File

@ -20,17 +20,8 @@
#include "pmc.h"
#define PERIPHERAL_MAX 64
#define PERIPHERAL_ID_MIN 2
#define GENERATED_SOURCE_MAX 6
#define GENERATED_MAX_DIV 255
#define GCK_ID_SSC0 43
#define GCK_ID_SSC1 44
#define GCK_ID_I2S0 54
#define GCK_ID_I2S1 55
#define GCK_ID_CLASSD 59
#define GCK_INDEX_DT_AUDIO_PLL 5
struct clk_generated {
@ -279,10 +270,10 @@ static void clk_generated_startup(struct clk_generated *gck)
>> AT91_PMC_PCR_GCKDIV_OFFSET;
}
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const char *name, const char **parent_names,
u8 num_parents, u8 id,
u8 num_parents, u8 id, bool pll_audio,
const struct clk_range *range)
{
struct clk_generated *gck;
@ -306,6 +297,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
gck->regmap = regmap;
gck->lock = lock;
gck->range = *range;
gck->audio_pll_allowed = pll_audio;
clk_generated_startup(gck);
hw = &gck->hw;
@ -319,70 +311,3 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
return hw;
}
static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
{
int num;
u32 id;
const char *name;
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[GENERATED_SOURCE_MAX];
struct device_node *gcknp;
struct clk_range range = CLK_RANGE(0, 0);
struct regmap *regmap;
struct clk_generated *gck;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
num = of_get_child_count(np);
if (!num || num > PERIPHERAL_MAX)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, gcknp) {
if (of_property_read_u32(gcknp, "reg", &id))
continue;
if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = gcknp->name;
of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
&range);
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
parent_names, num_parents,
id, &range);
gck = to_clk_generated(hw);
if (of_device_is_compatible(np,
"atmel,sama5d2-clk-generated")) {
if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 ||
gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 ||
gck->id == GCK_ID_CLASSD)
gck->audio_pll_allowed = true;
else
gck->audio_pll_allowed = false;
} else {
gck->audio_pll_allowed = false;
}
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
of_sama5d2_clk_generated_setup);

View File

@ -86,25 +86,19 @@ static const struct clk_ops h32mx_ops = {
.set_rate = clk_sama5d4_h32mx_set_rate,
};
static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
struct clk_hw * __init
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
const char *parent_name)
{
struct clk_sama5d4_h32mx *h32mxclk;
struct clk_init_data init;
const char *parent_name;
struct regmap *regmap;
int ret;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL);
if (!h32mxclk)
return;
return ERR_PTR(-ENOMEM);
parent_name = of_clk_get_parent_name(np, 0);
init.name = np->name;
init.name = name;
init.ops = &h32mx_ops;
init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0;
@ -116,10 +110,8 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
ret = clk_hw_register(NULL, &h32mxclk->hw);
if (ret) {
kfree(h32mxclk);
return;
return ERR_PTR(ret);
}
of_clk_add_hw_provider(np, of_clk_hw_simple_get, &h32mxclk->hw);
return &h32mxclk->hw;
}
CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
of_sama5d4_clk_h32mx_setup);

View File

@ -14,7 +14,7 @@
#include <soc/at91/atmel-sfr.h>
#define I2S_BUS_NR 2
#include "pmc.h"
struct clk_i2s_mux {
struct clk_hw hw;
@ -48,7 +48,7 @@ static const struct clk_ops clk_i2s_mux_ops = {
.determine_rate = __clk_mux_determine_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
const char * const *parent_names,
unsigned int num_parents, u8 bus_id)
@ -78,39 +78,3 @@ at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
return &i2s_ck->hw;
}
static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
{
struct regmap *regmap_sfr;
u8 bus_id;
const char *parent_names[2];
struct device_node *i2s_mux_np;
struct clk_hw *hw;
int ret;
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
return;
for_each_child_of_node(np, i2s_mux_np) {
if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
continue;
if (bus_id > I2S_BUS_NR)
continue;
ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
if (ret != 2)
continue;
hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
parent_names, 2, bus_id);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
of_sama5d2_clk_i2s_mux_setup);

View File

@ -12,7 +12,6 @@
#include <linux/clkdev.h>
#include <linux/clk/at91_pmc.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
@ -128,7 +127,7 @@ static const struct clk_ops main_osc_ops = {
.is_prepared = clk_main_osc_is_prepared,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap,
const char *name,
const char *parent_name,
@ -171,31 +170,6 @@ at91_clk_register_main_osc(struct regmap *regmap,
return hw;
}
static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *name = np->name;
const char *parent_name;
struct regmap *regmap;
bool bypass;
of_property_read_string(np, "clock-output-names", &name);
bypass = of_property_read_bool(np, "atmel,osc-bypass");
parent_name = of_clk_get_parent_name(np, 0);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
of_at91rm9200_clk_main_osc_setup);
static bool clk_main_rc_osc_ready(struct regmap *regmap)
{
unsigned int status;
@ -275,7 +249,7 @@ static const struct clk_ops main_rc_osc_ops = {
.recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_main_rc_osc(struct regmap *regmap,
const char *name,
u32 frequency, u32 accuracy)
@ -313,32 +287,6 @@ at91_clk_register_main_rc_osc(struct regmap *regmap,
return hw;
}
static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
{
struct clk_hw *hw;
u32 frequency = 0;
u32 accuracy = 0;
const char *name = np->name;
struct regmap *regmap;
of_property_read_string(np, "clock-output-names", &name);
of_property_read_u32(np, "clock-frequency", &frequency);
of_property_read_u32(np, "clock-accuracy", &accuracy);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
of_at91sam9x5_clk_main_rc_osc_setup);
static int clk_main_probe_frequency(struct regmap *regmap)
{
unsigned long prep_time, timeout;
@ -403,7 +351,7 @@ static const struct clk_ops rm9200_main_ops = {
.recalc_rate = clk_rm9200_main_recalc_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name,
const char *parent_name)
@ -442,29 +390,6 @@ at91_clk_register_rm9200_main(struct regmap *regmap,
return hw;
}
static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
of_at91rm9200_clk_main_setup);
static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
{
unsigned int status;
@ -541,7 +466,7 @@ static const struct clk_ops sam9x5_main_ops = {
.get_parent = clk_sam9x5_main_get_parent,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap,
const char *name,
const char **parent_names,
@ -583,32 +508,3 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
return hw;
}
static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_names[2];
unsigned int num_parents;
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > 2)
return;
of_clk_parent_fill(np, parent_names, num_parents);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
of_property_read_string(np, "clock-output-names", &name);
hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
of_at91sam9x5_clk_main_setup);

View File

@ -17,24 +17,11 @@
#include "pmc.h"
#define MASTER_SOURCE_MAX 4
#define MASTER_PRES_MASK 0x7
#define MASTER_PRES_MAX MASTER_PRES_MASK
#define MASTER_DIV_SHIFT 8
#define MASTER_DIV_MASK 0x3
struct clk_master_characteristics {
struct clk_range output;
u32 divisors[4];
u8 have_div3_pres;
};
struct clk_master_layout {
u32 mask;
u8 pres_shift;
};
#define to_clk_master(hw) container_of(hw, struct clk_master, hw)
struct clk_master {
@ -120,7 +107,7 @@ static const struct clk_ops master_ops = {
.get_parent = clk_master_get_parent,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_master(struct regmap *regmap,
const char *name, int num_parents,
const char **parent_names,
@ -161,92 +148,12 @@ at91_clk_register_master(struct regmap *regmap,
}
static const struct clk_master_layout at91rm9200_master_layout = {
const struct clk_master_layout at91rm9200_master_layout = {
.mask = 0x31F,
.pres_shift = 2,
};
static const struct clk_master_layout at91sam9x5_master_layout = {
const struct clk_master_layout at91sam9x5_master_layout = {
.mask = 0x373,
.pres_shift = 4,
};
static struct clk_master_characteristics * __init
of_at91_clk_master_get_characteristics(struct device_node *np)
{
struct clk_master_characteristics *characteristics;
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
if (!characteristics)
return NULL;
if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
goto out_free_characteristics;
of_property_read_u32_array(np, "atmel,clk-divisors",
characteristics->divisors, 4);
characteristics->have_div3_pres =
of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
return characteristics;
out_free_characteristics:
kfree(characteristics);
return NULL;
}
static void __init
of_at91_clk_master_setup(struct device_node *np,
const struct clk_master_layout *layout)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[MASTER_SOURCE_MAX];
const char *name = np->name;
struct clk_master_characteristics *characteristics;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
characteristics = of_at91_clk_master_get_characteristics(np);
if (!characteristics)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_master(regmap, name, num_parents,
parent_names, layout,
characteristics);
if (IS_ERR(hw))
goto out_free_characteristics;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
out_free_characteristics:
kfree(characteristics);
}
static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
{
of_at91_clk_master_setup(np, &at91rm9200_master_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
of_at91rm9200_clk_master_setup);
static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
{
of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
}
CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
of_at91sam9x5_clk_master_setup);

View File

@ -19,11 +19,6 @@
DEFINE_SPINLOCK(pmc_pcr_lock);
#define PERIPHERAL_MAX 64
#define PERIPHERAL_AT91RM9200 0
#define PERIPHERAL_AT91SAM9X5 1
#define PERIPHERAL_ID_MIN 2
#define PERIPHERAL_ID_MAX 31
#define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX))
@ -104,7 +99,7 @@ static const struct clk_ops peripheral_ops = {
.is_enabled = clk_peripheral_is_enabled,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
const char *parent_name, u32 id)
{
@ -331,7 +326,7 @@ static const struct clk_ops sam9x5_peripheral_ops = {
.set_rate = clk_sam9x5_peripheral_set_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name,
u32 id, const struct clk_range *range)
@ -374,75 +369,3 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
return hw;
}
static void __init
of_at91_clk_periph_setup(struct device_node *np, u8 type)
{
int num;
u32 id;
struct clk_hw *hw;
const char *parent_name;
const char *name;
struct device_node *periphclknp;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
num = of_get_child_count(np);
if (!num || num > PERIPHERAL_MAX)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, periphclknp) {
if (of_property_read_u32(periphclknp, "reg", &id))
continue;
if (id >= PERIPHERAL_MAX)
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = periphclknp->name;
if (type == PERIPHERAL_AT91RM9200) {
hw = at91_clk_register_peripheral(regmap, name,
parent_name, id);
} else {
struct clk_range range = CLK_RANGE(0, 0);
of_at91_get_clk_range(periphclknp,
"atmel,clk-output-range",
&range);
hw = at91_clk_register_sam9x5_peripheral(regmap,
&pmc_pcr_lock,
name,
parent_name,
id, &range);
}
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
}
}
static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
{
of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
}
CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
of_at91rm9200_clk_periph_setup);
static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
{
of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
}
CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
of_at91sam9x5_clk_periph_setup);

View File

@ -34,20 +34,6 @@
#define PLL_OUT_SHIFT 14
#define PLL_MAX_ID 1
struct clk_pll_characteristics {
struct clk_range input;
int num_output;
struct clk_range *output;
u16 *icpll;
u8 *out;
};
struct clk_pll_layout {
u32 pllr_mask;
u16 mul_mask;
u8 mul_shift;
};
#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw)
struct clk_pll {
@ -133,6 +119,9 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
{
struct clk_pll *pll = to_clk_pll(hw);
if (!pll->div || !pll->mul)
return 0;
return (parent_rate / pll->div) * (pll->mul + 1);
}
@ -285,7 +274,7 @@ static const struct clk_ops pll_ops = {
.set_rate = clk_pll_set_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_pll(struct regmap *regmap, const char *name,
const char *parent_name, u8 id,
const struct clk_pll_layout *layout,
@ -331,189 +320,26 @@ at91_clk_register_pll(struct regmap *regmap, const char *name,
}
static const struct clk_pll_layout at91rm9200_pll_layout = {
const struct clk_pll_layout at91rm9200_pll_layout = {
.pllr_mask = 0x7FFFFFF,
.mul_shift = 16,
.mul_mask = 0x7FF,
};
static const struct clk_pll_layout at91sam9g45_pll_layout = {
const struct clk_pll_layout at91sam9g45_pll_layout = {
.pllr_mask = 0xFFFFFF,
.mul_shift = 16,
.mul_mask = 0xFF,
};
static const struct clk_pll_layout at91sam9g20_pllb_layout = {
const struct clk_pll_layout at91sam9g20_pllb_layout = {
.pllr_mask = 0x3FFFFF,
.mul_shift = 16,
.mul_mask = 0x3F,
};
static const struct clk_pll_layout sama5d3_pll_layout = {
const struct clk_pll_layout sama5d3_pll_layout = {
.pllr_mask = 0x1FFFFFF,
.mul_shift = 18,
.mul_mask = 0x7F,
};
static struct clk_pll_characteristics * __init
of_at91_clk_pll_get_characteristics(struct device_node *np)
{
int i;
int offset;
u32 tmp;
int num_output;
u32 num_cells;
struct clk_range input;
struct clk_range *output;
u8 *out = NULL;
u16 *icpll = NULL;
struct clk_pll_characteristics *characteristics;
if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
return NULL;
if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
&num_cells))
return NULL;
if (num_cells < 2 || num_cells > 4)
return NULL;
if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
return NULL;
num_output = tmp / (sizeof(u32) * num_cells);
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
if (!characteristics)
return NULL;
output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
if (!output)
goto out_free_characteristics;
if (num_cells > 2) {
out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
if (!out)
goto out_free_output;
}
if (num_cells > 3) {
icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
if (!icpll)
goto out_free_output;
}
for (i = 0; i < num_output; i++) {
offset = i * num_cells;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset, &tmp))
goto out_free_output;
output[i].min = tmp;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 1, &tmp))
goto out_free_output;
output[i].max = tmp;
if (num_cells == 2)
continue;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 2, &tmp))
goto out_free_output;
out[i] = tmp;
if (num_cells == 3)
continue;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 3, &tmp))
goto out_free_output;
icpll[i] = tmp;
}
characteristics->input = input;
characteristics->num_output = num_output;
characteristics->output = output;
characteristics->out = out;
characteristics->icpll = icpll;
return characteristics;
out_free_output:
kfree(icpll);
kfree(out);
kfree(output);
out_free_characteristics:
kfree(characteristics);
return NULL;
}
static void __init
of_at91_clk_pll_setup(struct device_node *np,
const struct clk_pll_layout *layout)
{
u32 id;
struct clk_hw *hw;
struct regmap *regmap;
const char *parent_name;
const char *name = np->name;
struct clk_pll_characteristics *characteristics;
if (of_property_read_u32(np, "reg", &id))
return;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
characteristics = of_at91_clk_pll_get_characteristics(np);
if (!characteristics)
return;
hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
characteristics);
if (IS_ERR(hw))
goto out_free_characteristics;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
out_free_characteristics:
kfree(characteristics);
}
static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
of_at91rm9200_clk_pll_setup);
static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
}
CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
of_at91sam9g45_clk_pll_setup);
static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
}
CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
of_at91sam9g20_clk_pllb_setup);
static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
}
CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
of_sama5d3_clk_pll_setup);

View File

@ -75,7 +75,7 @@ static const struct clk_ops plldiv_ops = {
.set_rate = clk_plldiv_set_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_plldiv(struct regmap *regmap, const char *name,
const char *parent_name)
{
@ -106,28 +106,3 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name,
return hw;
}
static void __init
of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_plldiv(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
of_at91sam9x5_clk_plldiv_setup);

View File

@ -17,7 +17,6 @@
#include "pmc.h"
#define PROG_SOURCE_MAX 5
#define PROG_ID_MAX 7
#define PROG_STATUS_MASK(id) (1 << ((id) + 8))
@ -25,12 +24,6 @@
#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
#define PROG_MAX_RM9200_CSS 3
struct clk_programmable_layout {
u8 pres_shift;
u8 css_mask;
u8 have_slck_mck;
};
struct clk_programmable {
struct clk_hw hw;
struct regmap *regmap;
@ -170,7 +163,7 @@ static const struct clk_ops programmable_ops = {
.set_rate = clk_programmable_set_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap,
const char *name, const char **parent_names,
u8 num_parents, u8 id,
@ -211,86 +204,20 @@ at91_clk_register_programmable(struct regmap *regmap,
return hw;
}
static const struct clk_programmable_layout at91rm9200_programmable_layout = {
const struct clk_programmable_layout at91rm9200_programmable_layout = {
.pres_shift = 2,
.css_mask = 0x3,
.have_slck_mck = 0,
};
static const struct clk_programmable_layout at91sam9g45_programmable_layout = {
const struct clk_programmable_layout at91sam9g45_programmable_layout = {
.pres_shift = 2,
.css_mask = 0x3,
.have_slck_mck = 1,
};
static const struct clk_programmable_layout at91sam9x5_programmable_layout = {
const struct clk_programmable_layout at91sam9x5_programmable_layout = {
.pres_shift = 4,
.css_mask = 0x7,
.have_slck_mck = 0,
};
static void __init
of_at91_clk_prog_setup(struct device_node *np,
const struct clk_programmable_layout *layout)
{
int num;
u32 id;
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[PROG_SOURCE_MAX];
const char *name;
struct device_node *progclknp;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
num = of_get_child_count(np);
if (!num || num > (PROG_ID_MAX + 1))
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, progclknp) {
if (of_property_read_u32(progclknp, "reg", &id))
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = progclknp->name;
hw = at91_clk_register_programmable(regmap, name,
parent_names, num_parents,
id, layout);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
}
}
static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
of_at91rm9200_clk_prog_setup);
static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
}
CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
of_at91sam9g45_clk_prog_setup);
static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
}
CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
of_at91sam9x5_clk_prog_setup);

View File

@ -40,7 +40,7 @@ static const struct clk_ops sam9260_slow_ops = {
.get_parent = clk_sam9260_slow_get_parent,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_sam9260_slow(struct regmap *regmap,
const char *name,
const char **parent_names,
@ -79,33 +79,3 @@ at91_clk_register_sam9260_slow(struct regmap *regmap,
return hw;
}
static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_names[2];
unsigned int num_parents;
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents != 2)
return;
of_clk_parent_fill(np, parent_names, num_parents);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
of_property_read_string(np, "clock-output-names", &name);
hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
of_at91sam9260_clk_slow_setup);

View File

@ -17,8 +17,6 @@
#include "pmc.h"
#define SMD_SOURCE_MAX 2
#define SMD_DIV_SHIFT 8
#define SMD_MAX_DIV 0xf
@ -111,7 +109,7 @@ static const struct clk_ops at91sam9x5_smd_ops = {
.set_rate = at91sam9x5_clk_smd_set_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents)
{
@ -142,33 +140,3 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
return hw;
}
static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[SMD_SOURCE_MAX];
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
of_at91sam9x5_clk_smd_setup);

View File

@ -88,7 +88,7 @@ static const struct clk_ops system_ops = {
.is_prepared = clk_system_is_prepared,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name,
const char *parent_name, u8 id)
{
@ -123,40 +123,3 @@ at91_clk_register_system(struct regmap *regmap, const char *name,
return hw;
}
static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
{
int num;
u32 id;
struct clk_hw *hw;
const char *name;
struct device_node *sysclknp;
const char *parent_name;
struct regmap *regmap;
num = of_get_child_count(np);
if (num > (SYSTEM_MAX_ID + 1))
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, sysclknp) {
if (of_property_read_u32(sysclknp, "reg", &id))
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = sysclknp->name;
parent_name = of_clk_get_parent_name(sysclknp, 0);
hw = at91_clk_register_system(regmap, name, parent_name, id);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
of_at91rm9200_clk_sys_setup);

View File

@ -17,8 +17,6 @@
#include "pmc.h"
#define USB_SOURCE_MAX 2
#define SAM9X5_USB_DIV_SHIFT 8
#define SAM9X5_USB_MAX_DIV 0xf
@ -192,7 +190,7 @@ static const struct clk_ops at91sam9n12_usb_ops = {
.set_rate = at91sam9x5_clk_usb_set_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents)
{
@ -225,7 +223,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
return hw;
}
static struct clk_hw * __init
struct clk_hw * __init
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name)
{
@ -342,7 +340,7 @@ static const struct clk_ops at91rm9200_usb_ops = {
.set_rate = at91rm9200_clk_usb_set_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name, const u32 *divisors)
{
@ -374,89 +372,3 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
return hw;
}
static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[USB_SOURCE_MAX];
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
of_at91sam9x5_clk_usb_setup);
static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
of_at91sam9n12_clk_usb_setup);
static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
u32 divisors[4] = {0, 0, 0, 0};
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
if (!divisors[0])
return;
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
of_at91rm9200_clk_usb_setup);

View File

@ -125,7 +125,7 @@ static const struct clk_ops utmi_ops = {
.recalc_rate = clk_utmi_recalc_rate,
};
static struct clk_hw * __init
struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
const char *name, const char *parent_name)
{
@ -157,46 +157,3 @@ at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
return hw;
}
static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap_pmc, *regmap_sfr;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap_pmc))
return;
/*
* If the device supports different mainck rates, this value has to be
* set in the UTMI Clock Trimming register.
* - 9x5: mainck supports several rates but it is indicated that a
* 12 MHz is needed in case of USB.
* - sama5d3 and sama5d2: mainck supports several rates. Configuring
* the FREQ field of the UTMI Clock Trimming register is mandatory.
* - sama5d4: mainck is at 12 MHz.
*
* We only need to retrieve sama5d3 or sama5d2 sfr regmap.
*/
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
if (IS_ERR(regmap_sfr)) {
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
regmap_sfr = NULL;
}
hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
}
CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
of_at91sam9x5_clk_utmi_setup);

View File

@ -0,0 +1,961 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/clk/at91_pmc.h>
#include <linux/of.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include "pmc.h"
#define MASTER_SOURCE_MAX 4
#define PERIPHERAL_AT91RM9200 0
#define PERIPHERAL_AT91SAM9X5 1
#define PERIPHERAL_MAX 64
#define PERIPHERAL_ID_MIN 2
#define PROG_SOURCE_MAX 5
#define PROG_ID_MAX 7
#define SYSTEM_MAX_ID 31
#ifdef CONFIG_HAVE_AT91_AUDIO_PLL
static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *name = np->name;
const char *parent_name;
struct regmap *regmap;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
parent_name = of_clk_get_parent_name(np, 0);
hw = at91_clk_register_audio_pll_frac(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup,
"atmel,sama5d2-clk-audio-pll-frac",
of_sama5d2_clk_audio_pll_frac_setup);
static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *name = np->name;
const char *parent_name;
struct regmap *regmap;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
parent_name = of_clk_get_parent_name(np, 0);
hw = at91_clk_register_audio_pll_pad(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup,
"atmel,sama5d2-clk-audio-pll-pad",
of_sama5d2_clk_audio_pll_pad_setup);
static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *name = np->name;
const char *parent_name;
struct regmap *regmap;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
parent_name = of_clk_get_parent_name(np, 0);
hw = at91_clk_register_audio_pll_pmc(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup,
"atmel,sama5d2-clk-audio-pll-pmc",
of_sama5d2_clk_audio_pll_pmc_setup);
#endif /* CONFIG_HAVE_AT91_AUDIO_PLL */
#ifdef CONFIG_HAVE_AT91_GENERATED_CLK
#define GENERATED_SOURCE_MAX 6
#define GCK_ID_I2S0 54
#define GCK_ID_I2S1 55
#define GCK_ID_CLASSD 59
static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
{
int num;
u32 id;
const char *name;
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[GENERATED_SOURCE_MAX];
struct device_node *gcknp;
struct clk_range range = CLK_RANGE(0, 0);
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
num = of_get_child_count(np);
if (!num || num > PERIPHERAL_MAX)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, gcknp) {
bool pll_audio = false;
if (of_property_read_u32(gcknp, "reg", &id))
continue;
if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = gcknp->name;
of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
&range);
if (of_device_is_compatible(np, "atmel,sama5d2-clk-generated") &&
(id == GCK_ID_I2S0 || id == GCK_ID_I2S1 ||
id == GCK_ID_CLASSD))
pll_audio = true;
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
parent_names, num_parents,
id, pll_audio, &range);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
of_sama5d2_clk_generated_setup);
#endif /* CONFIG_HAVE_AT91_GENERATED_CLK */
#ifdef CONFIG_HAVE_AT91_H32MX
static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *name = np->name;
const char *parent_name;
struct regmap *regmap;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
parent_name = of_clk_get_parent_name(np, 0);
hw = at91_clk_register_h32mx(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
of_sama5d4_clk_h32mx_setup);
#endif /* CONFIG_HAVE_AT91_H32MX */
#ifdef CONFIG_HAVE_AT91_I2S_MUX_CLK
#define I2S_BUS_NR 2
static void __init of_sama5d2_clk_i2s_mux_setup(struct device_node *np)
{
struct regmap *regmap_sfr;
u8 bus_id;
const char *parent_names[2];
struct device_node *i2s_mux_np;
struct clk_hw *hw;
int ret;
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
return;
for_each_child_of_node(np, i2s_mux_np) {
if (of_property_read_u8(i2s_mux_np, "reg", &bus_id))
continue;
if (bus_id > I2S_BUS_NR)
continue;
ret = of_clk_parent_fill(i2s_mux_np, parent_names, 2);
if (ret != 2)
continue;
hw = at91_clk_i2s_mux_register(regmap_sfr, i2s_mux_np->name,
parent_names, 2, bus_id);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(i2s_mux_np, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(sama5d2_clk_i2s_mux, "atmel,sama5d2-clk-i2s-mux",
of_sama5d2_clk_i2s_mux_setup);
#endif /* CONFIG_HAVE_AT91_I2S_MUX_CLK */
static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *name = np->name;
const char *parent_name;
struct regmap *regmap;
bool bypass;
of_property_read_string(np, "clock-output-names", &name);
bypass = of_property_read_bool(np, "atmel,osc-bypass");
parent_name = of_clk_get_parent_name(np, 0);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
of_at91rm9200_clk_main_osc_setup);
static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
{
struct clk_hw *hw;
u32 frequency = 0;
u32 accuracy = 0;
const char *name = np->name;
struct regmap *regmap;
of_property_read_string(np, "clock-output-names", &name);
of_property_read_u32(np, "clock-frequency", &frequency);
of_property_read_u32(np, "clock-accuracy", &accuracy);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_main_rc_osc(regmap, name, frequency, accuracy);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
of_at91sam9x5_clk_main_rc_osc_setup);
static void __init of_at91rm9200_clk_main_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_rm9200_main(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
of_at91rm9200_clk_main_setup);
static void __init of_at91sam9x5_clk_main_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_names[2];
unsigned int num_parents;
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > 2)
return;
of_clk_parent_fill(np, parent_names, num_parents);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
of_property_read_string(np, "clock-output-names", &name);
hw = at91_clk_register_sam9x5_main(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
of_at91sam9x5_clk_main_setup);
static struct clk_master_characteristics * __init
of_at91_clk_master_get_characteristics(struct device_node *np)
{
struct clk_master_characteristics *characteristics;
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
if (!characteristics)
return NULL;
if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
goto out_free_characteristics;
of_property_read_u32_array(np, "atmel,clk-divisors",
characteristics->divisors, 4);
characteristics->have_div3_pres =
of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
return characteristics;
out_free_characteristics:
kfree(characteristics);
return NULL;
}
static void __init
of_at91_clk_master_setup(struct device_node *np,
const struct clk_master_layout *layout)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[MASTER_SOURCE_MAX];
const char *name = np->name;
struct clk_master_characteristics *characteristics;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
characteristics = of_at91_clk_master_get_characteristics(np);
if (!characteristics)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_master(regmap, name, num_parents,
parent_names, layout,
characteristics);
if (IS_ERR(hw))
goto out_free_characteristics;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
out_free_characteristics:
kfree(characteristics);
}
static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
{
of_at91_clk_master_setup(np, &at91rm9200_master_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
of_at91rm9200_clk_master_setup);
static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
{
of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
}
CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
of_at91sam9x5_clk_master_setup);
static void __init
of_at91_clk_periph_setup(struct device_node *np, u8 type)
{
int num;
u32 id;
struct clk_hw *hw;
const char *parent_name;
const char *name;
struct device_node *periphclknp;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
num = of_get_child_count(np);
if (!num || num > PERIPHERAL_MAX)
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, periphclknp) {
if (of_property_read_u32(periphclknp, "reg", &id))
continue;
if (id >= PERIPHERAL_MAX)
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = periphclknp->name;
if (type == PERIPHERAL_AT91RM9200) {
hw = at91_clk_register_peripheral(regmap, name,
parent_name, id);
} else {
struct clk_range range = CLK_RANGE(0, 0);
of_at91_get_clk_range(periphclknp,
"atmel,clk-output-range",
&range);
hw = at91_clk_register_sam9x5_peripheral(regmap,
&pmc_pcr_lock,
name,
parent_name,
id, &range);
}
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(periphclknp, of_clk_hw_simple_get, hw);
}
}
static void __init of_at91rm9200_clk_periph_setup(struct device_node *np)
{
of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
}
CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
of_at91rm9200_clk_periph_setup);
static void __init of_at91sam9x5_clk_periph_setup(struct device_node *np)
{
of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
}
CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
of_at91sam9x5_clk_periph_setup);
static struct clk_pll_characteristics * __init
of_at91_clk_pll_get_characteristics(struct device_node *np)
{
int i;
int offset;
u32 tmp;
int num_output;
u32 num_cells;
struct clk_range input;
struct clk_range *output;
u8 *out = NULL;
u16 *icpll = NULL;
struct clk_pll_characteristics *characteristics;
if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
return NULL;
if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
&num_cells))
return NULL;
if (num_cells < 2 || num_cells > 4)
return NULL;
if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
return NULL;
num_output = tmp / (sizeof(u32) * num_cells);
characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
if (!characteristics)
return NULL;
output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
if (!output)
goto out_free_characteristics;
if (num_cells > 2) {
out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
if (!out)
goto out_free_output;
}
if (num_cells > 3) {
icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
if (!icpll)
goto out_free_output;
}
for (i = 0; i < num_output; i++) {
offset = i * num_cells;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset, &tmp))
goto out_free_output;
output[i].min = tmp;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 1, &tmp))
goto out_free_output;
output[i].max = tmp;
if (num_cells == 2)
continue;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 2, &tmp))
goto out_free_output;
out[i] = tmp;
if (num_cells == 3)
continue;
if (of_property_read_u32_index(np,
"atmel,pll-clk-output-ranges",
offset + 3, &tmp))
goto out_free_output;
icpll[i] = tmp;
}
characteristics->input = input;
characteristics->num_output = num_output;
characteristics->output = output;
characteristics->out = out;
characteristics->icpll = icpll;
return characteristics;
out_free_output:
kfree(icpll);
kfree(out);
kfree(output);
out_free_characteristics:
kfree(characteristics);
return NULL;
}
static void __init
of_at91_clk_pll_setup(struct device_node *np,
const struct clk_pll_layout *layout)
{
u32 id;
struct clk_hw *hw;
struct regmap *regmap;
const char *parent_name;
const char *name = np->name;
struct clk_pll_characteristics *characteristics;
if (of_property_read_u32(np, "reg", &id))
return;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
characteristics = of_at91_clk_pll_get_characteristics(np);
if (!characteristics)
return;
hw = at91_clk_register_pll(regmap, name, parent_name, id, layout,
characteristics);
if (IS_ERR(hw))
goto out_free_characteristics;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
return;
out_free_characteristics:
kfree(characteristics);
}
static void __init of_at91rm9200_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
of_at91rm9200_clk_pll_setup);
static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
}
CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
of_at91sam9g45_clk_pll_setup);
static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
}
CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
of_at91sam9g20_clk_pllb_setup);
static void __init of_sama5d3_clk_pll_setup(struct device_node *np)
{
of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
}
CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
of_sama5d3_clk_pll_setup);
static void __init
of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91_clk_register_plldiv(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
of_at91sam9x5_clk_plldiv_setup);
static void __init
of_at91_clk_prog_setup(struct device_node *np,
const struct clk_programmable_layout *layout)
{
int num;
u32 id;
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[PROG_SOURCE_MAX];
const char *name;
struct device_node *progclknp;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
num = of_get_child_count(np);
if (!num || num > (PROG_ID_MAX + 1))
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, progclknp) {
if (of_property_read_u32(progclknp, "reg", &id))
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = progclknp->name;
hw = at91_clk_register_programmable(regmap, name,
parent_names, num_parents,
id, layout);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(progclknp, of_clk_hw_simple_get, hw);
}
}
static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
}
CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
of_at91rm9200_clk_prog_setup);
static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
}
CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
of_at91sam9g45_clk_prog_setup);
static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np)
{
of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
}
CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
of_at91sam9x5_clk_prog_setup);
static void __init of_at91sam9260_clk_slow_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_names[2];
unsigned int num_parents;
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents != 2)
return;
of_clk_parent_fill(np, parent_names, num_parents);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
of_property_read_string(np, "clock-output-names", &name);
hw = at91_clk_register_sam9260_slow(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
of_at91sam9260_clk_slow_setup);
#ifdef CONFIG_HAVE_AT91_SMD
#define SMD_SOURCE_MAX 2
static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[SMD_SOURCE_MAX];
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9x5_clk_register_smd(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
of_at91sam9x5_clk_smd_setup);
#endif /* CONFIG_HAVE_AT91_SMD */
static void __init of_at91rm9200_clk_sys_setup(struct device_node *np)
{
int num;
u32 id;
struct clk_hw *hw;
const char *name;
struct device_node *sysclknp;
const char *parent_name;
struct regmap *regmap;
num = of_get_child_count(np);
if (num > (SYSTEM_MAX_ID + 1))
return;
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
for_each_child_of_node(np, sysclknp) {
if (of_property_read_u32(sysclknp, "reg", &id))
continue;
if (of_property_read_string(np, "clock-output-names", &name))
name = sysclknp->name;
parent_name = of_clk_get_parent_name(sysclknp, 0);
hw = at91_clk_register_system(regmap, name, parent_name, id);
if (IS_ERR(hw))
continue;
of_clk_add_hw_provider(sysclknp, of_clk_hw_simple_get, hw);
}
}
CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
of_at91rm9200_clk_sys_setup);
#ifdef CONFIG_HAVE_AT91_USB_CLK
#define USB_SOURCE_MAX 2
static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
unsigned int num_parents;
const char *parent_names[USB_SOURCE_MAX];
const char *name = np->name;
struct regmap *regmap;
num_parents = of_clk_get_parent_count(np);
if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
return;
of_clk_parent_fill(np, parent_names, num_parents);
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9x5_clk_register_usb(regmap, name, parent_names,
num_parents);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
of_at91sam9x5_clk_usb_setup);
static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91sam9n12_clk_register_usb(regmap, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
of_at91sam9n12_clk_usb_setup);
static void __init of_at91rm9200_clk_usb_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
u32 divisors[4] = {0, 0, 0, 0};
struct regmap *regmap;
parent_name = of_clk_get_parent_name(np, 0);
if (!parent_name)
return;
of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
if (!divisors[0])
return;
of_property_read_string(np, "clock-output-names", &name);
regmap = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
return;
hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
of_at91rm9200_clk_usb_setup);
#endif /* CONFIG_HAVE_AT91_USB_CLK */
#ifdef CONFIG_HAVE_AT91_UTMI
static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
{
struct clk_hw *hw;
const char *parent_name;
const char *name = np->name;
struct regmap *regmap_pmc, *regmap_sfr;
parent_name = of_clk_get_parent_name(np, 0);
of_property_read_string(np, "clock-output-names", &name);
regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap_pmc))
return;
/*
* If the device supports different mainck rates, this value has to be
* set in the UTMI Clock Trimming register.
* - 9x5: mainck supports several rates but it is indicated that a
* 12 MHz is needed in case of USB.
* - sama5d3 and sama5d2: mainck supports several rates. Configuring
* the FREQ field of the UTMI Clock Trimming register is mandatory.
* - sama5d4: mainck is at 12 MHz.
*
* We only need to retrieve sama5d3 or sama5d2 sfr regmap.
*/
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d3-sfr");
if (IS_ERR(regmap_sfr)) {
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
regmap_sfr = NULL;
}
hw = at91_clk_register_utmi(regmap_pmc, regmap_sfr, name, parent_name);
if (IS_ERR(hw))
return;
of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
}
CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
of_at91sam9x5_clk_utmi_setup);
#endif /* CONFIG_HAVE_AT91_UTMI */

View File

@ -19,6 +19,8 @@
#include <asm/proc-fns.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
#define PMC_MAX_IDS 128
@ -47,6 +49,82 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
}
EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
{
unsigned int type = clkspec->args[0];
unsigned int idx = clkspec->args[1];
struct pmc_data *pmc_data = data;
switch (type) {
case PMC_TYPE_CORE:
if (idx < pmc_data->ncore)
return pmc_data->chws[idx];
break;
case PMC_TYPE_SYSTEM:
if (idx < pmc_data->nsystem)
return pmc_data->shws[idx];
break;
case PMC_TYPE_PERIPHERAL:
if (idx < pmc_data->nperiph)
return pmc_data->phws[idx];
break;
case PMC_TYPE_GCK:
if (idx < pmc_data->ngck)
return pmc_data->ghws[idx];
break;
default:
break;
}
pr_err("%s: invalid type (%u) or index (%u)\n", __func__, type, idx);
return ERR_PTR(-EINVAL);
}
void pmc_data_free(struct pmc_data *pmc_data)
{
kfree(pmc_data->chws);
kfree(pmc_data->shws);
kfree(pmc_data->phws);
kfree(pmc_data->ghws);
}
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
unsigned int nperiph, unsigned int ngck)
{
struct pmc_data *pmc_data = kzalloc(sizeof(*pmc_data), GFP_KERNEL);
if (!pmc_data)
return NULL;
pmc_data->ncore = ncore;
pmc_data->chws = kcalloc(ncore, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->chws)
goto err;
pmc_data->nsystem = nsystem;
pmc_data->shws = kcalloc(nsystem, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->shws)
goto err;
pmc_data->nperiph = nperiph;
pmc_data->phws = kcalloc(nperiph, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->phws)
goto err;
pmc_data->ngck = ngck;
pmc_data->ghws = kcalloc(ngck, sizeof(struct clk_hw *), GFP_KERNEL);
if (!pmc_data->ghws)
goto err;
return pmc_data;
err:
pmc_data_free(pmc_data);
return NULL;
}
#ifdef CONFIG_PM
static struct regmap *pmcreg;

View File

@ -19,6 +19,17 @@
extern spinlock_t pmc_pcr_lock;
struct pmc_data {
unsigned int ncore;
struct clk_hw **chws;
unsigned int nsystem;
struct clk_hw **shws;
unsigned int nperiph;
struct clk_hw **phws;
unsigned int ngck;
struct clk_hw **ghws;
};
struct clk_range {
unsigned long min;
unsigned long max;
@ -26,9 +37,157 @@ struct clk_range {
#define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
struct clk_master_layout {
u32 mask;
u8 pres_shift;
};
extern const struct clk_master_layout at91rm9200_master_layout;
extern const struct clk_master_layout at91sam9x5_master_layout;
struct clk_master_characteristics {
struct clk_range output;
u32 divisors[4];
u8 have_div3_pres;
};
struct clk_pll_layout {
u32 pllr_mask;
u16 mul_mask;
u8 mul_shift;
};
extern const struct clk_pll_layout at91rm9200_pll_layout;
extern const struct clk_pll_layout at91sam9g45_pll_layout;
extern const struct clk_pll_layout at91sam9g20_pllb_layout;
extern const struct clk_pll_layout sama5d3_pll_layout;
struct clk_pll_characteristics {
struct clk_range input;
int num_output;
struct clk_range *output;
u16 *icpll;
u8 *out;
};
struct clk_programmable_layout {
u8 pres_shift;
u8 css_mask;
u8 have_slck_mck;
};
extern const struct clk_programmable_layout at91rm9200_programmable_layout;
extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
#define ndck(a, s) (a[s - 1].id + 1)
#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
unsigned int nperiph, unsigned int ngck);
void pmc_data_free(struct pmc_data *pmc_data);
int of_at91_get_clk_range(struct device_node *np, const char *propname,
struct clk_range *range);
struct clk_hw *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data);
struct clk_hw * __init
at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
const char *name, const char **parent_names,
u8 num_parents, u8 id, bool pll_audio,
const struct clk_range *range);
struct clk_hw * __init
at91_clk_register_h32mx(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
const char * const *parent_names,
unsigned int num_parents, u8 bus_id);
struct clk_hw * __init
at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name,
u32 frequency, u32 accuracy);
struct clk_hw * __init
at91_clk_register_main_osc(struct regmap *regmap, const char *name,
const char *parent_name, bool bypass);
struct clk_hw * __init
at91_clk_register_rm9200_main(struct regmap *regmap,
const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
const char **parent_names, int num_parents);
struct clk_hw * __init
at91_clk_register_master(struct regmap *regmap, const char *name,
int num_parents, const char **parent_names,
const struct clk_master_layout *layout,
const struct clk_master_characteristics *characteristics);
struct clk_hw * __init
at91_clk_register_peripheral(struct regmap *regmap, const char *name,
const char *parent_name, u32 id);
struct clk_hw * __init
at91_clk_register_sam9x5_peripheral(struct regmap *regmap, spinlock_t *lock,
const char *name, const char *parent_name,
u32 id, const struct clk_range *range);
struct clk_hw * __init
at91_clk_register_pll(struct regmap *regmap, const char *name,
const char *parent_name, u8 id,
const struct clk_pll_layout *layout,
const struct clk_pll_characteristics *characteristics);
struct clk_hw * __init
at91_clk_register_plldiv(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91_clk_register_programmable(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents, u8 id,
const struct clk_programmable_layout *layout);
struct clk_hw * __init
at91_clk_register_sam9260_slow(struct regmap *regmap,
const char *name,
const char **parent_names,
int num_parents);
struct clk_hw * __init
at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents);
struct clk_hw * __init
at91_clk_register_system(struct regmap *regmap, const char *name,
const char *parent_name, u8 id);
struct clk_hw * __init
at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
const char **parent_names, u8 num_parents);
struct clk_hw * __init
at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name);
struct clk_hw * __init
at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
const char *parent_name, const u32 *divisors);
struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
const char *name, const char *parent_name);
#ifdef CONFIG_PM
void pmc_register_id(u8 id);
void pmc_register_pck(u8 pck);

View File

@ -0,0 +1,336 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 124000000, .max = 166000000 },
.divisors = { 1, 2, 4, 3 },
};
static u8 plla_out[] = { 0 };
static u16 plla_icpll[] = { 0 };
static struct clk_range plla_outputs[] = {
{ .min = 600000000, .max = 1200000000 },
};
static const struct clk_pll_characteristics plla_characteristics = {
.input = { .min = 12000000, .max = 12000000 },
.num_output = ARRAY_SIZE(plla_outputs),
.output = plla_outputs,
.icpll = plla_icpll,
.out = plla_out,
};
static const struct {
char *n;
char *p;
u8 id;
} sama5d2_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "lcdck", .p = "masterck", .id = 3 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
{ .n = "iscck", .p = "masterck", .id = 18 },
};
static const struct {
char *n;
u8 id;
struct clk_range r;
} sama5d2_periph32ck[] = {
{ .n = "macb0_clk", .id = 5, .r = { .min = 0, .max = 83000000 }, },
{ .n = "tdes_clk", .id = 11, .r = { .min = 0, .max = 83000000 }, },
{ .n = "matrix1_clk", .id = 14, },
{ .n = "hsmc_clk", .id = 17, },
{ .n = "pioA_clk", .id = 18, .r = { .min = 0, .max = 83000000 }, },
{ .n = "flx0_clk", .id = 19, .r = { .min = 0, .max = 83000000 }, },
{ .n = "flx1_clk", .id = 20, .r = { .min = 0, .max = 83000000 }, },
{ .n = "flx2_clk", .id = 21, .r = { .min = 0, .max = 83000000 }, },
{ .n = "flx3_clk", .id = 22, .r = { .min = 0, .max = 83000000 }, },
{ .n = "flx4_clk", .id = 23, .r = { .min = 0, .max = 83000000 }, },
{ .n = "uart0_clk", .id = 24, .r = { .min = 0, .max = 83000000 }, },
{ .n = "uart1_clk", .id = 25, .r = { .min = 0, .max = 83000000 }, },
{ .n = "uart2_clk", .id = 26, .r = { .min = 0, .max = 83000000 }, },
{ .n = "uart3_clk", .id = 27, .r = { .min = 0, .max = 83000000 }, },
{ .n = "uart4_clk", .id = 28, .r = { .min = 0, .max = 83000000 }, },
{ .n = "twi0_clk", .id = 29, .r = { .min = 0, .max = 83000000 }, },
{ .n = "twi1_clk", .id = 30, .r = { .min = 0, .max = 83000000 }, },
{ .n = "spi0_clk", .id = 33, .r = { .min = 0, .max = 83000000 }, },
{ .n = "spi1_clk", .id = 34, .r = { .min = 0, .max = 83000000 }, },
{ .n = "tcb0_clk", .id = 35, .r = { .min = 0, .max = 83000000 }, },
{ .n = "tcb1_clk", .id = 36, .r = { .min = 0, .max = 83000000 }, },
{ .n = "pwm_clk", .id = 38, .r = { .min = 0, .max = 83000000 }, },
{ .n = "adc_clk", .id = 40, .r = { .min = 0, .max = 83000000 }, },
{ .n = "uhphs_clk", .id = 41, .r = { .min = 0, .max = 83000000 }, },
{ .n = "udphs_clk", .id = 42, .r = { .min = 0, .max = 83000000 }, },
{ .n = "ssc0_clk", .id = 43, .r = { .min = 0, .max = 83000000 }, },
{ .n = "ssc1_clk", .id = 44, .r = { .min = 0, .max = 83000000 }, },
{ .n = "trng_clk", .id = 47, .r = { .min = 0, .max = 83000000 }, },
{ .n = "pdmic_clk", .id = 48, .r = { .min = 0, .max = 83000000 }, },
{ .n = "securam_clk", .id = 51, },
{ .n = "i2s0_clk", .id = 54, .r = { .min = 0, .max = 83000000 }, },
{ .n = "i2s1_clk", .id = 55, .r = { .min = 0, .max = 83000000 }, },
{ .n = "can0_clk", .id = 56, .r = { .min = 0, .max = 83000000 }, },
{ .n = "can1_clk", .id = 57, .r = { .min = 0, .max = 83000000 }, },
{ .n = "classd_clk", .id = 59, .r = { .min = 0, .max = 83000000 }, },
};
static const struct {
char *n;
u8 id;
} sama5d2_periphck[] = {
{ .n = "dma0_clk", .id = 6, },
{ .n = "dma1_clk", .id = 7, },
{ .n = "aes_clk", .id = 9, },
{ .n = "aesb_clk", .id = 10, },
{ .n = "sha_clk", .id = 12, },
{ .n = "mpddr_clk", .id = 13, },
{ .n = "matrix0_clk", .id = 15, },
{ .n = "sdmmc0_hclk", .id = 31, },
{ .n = "sdmmc1_hclk", .id = 32, },
{ .n = "lcdc_clk", .id = 45, },
{ .n = "isc_clk", .id = 46, },
{ .n = "qspi0_clk", .id = 52, },
{ .n = "qspi1_clk", .id = 53, },
};
static const struct {
char *n;
u8 id;
struct clk_range r;
bool pll;
} sama5d2_gck[] = {
{ .n = "sdmmc0_gclk", .id = 31, },
{ .n = "sdmmc1_gclk", .id = 32, },
{ .n = "tcb0_gclk", .id = 35, .r = { .min = 0, .max = 83000000 }, },
{ .n = "tcb1_gclk", .id = 36, .r = { .min = 0, .max = 83000000 }, },
{ .n = "pwm_gclk", .id = 38, .r = { .min = 0, .max = 83000000 }, },
{ .n = "isc_gclk", .id = 46, },
{ .n = "pdmic_gclk", .id = 48, },
{ .n = "i2s0_gclk", .id = 54, .pll = true },
{ .n = "i2s1_gclk", .id = 55, .pll = true },
{ .n = "can0_gclk", .id = 56, .r = { .min = 0, .max = 80000000 }, },
{ .n = "can1_gclk", .id = 57, .r = { .min = 0, .max = 80000000 }, },
{ .n = "classd_gclk", .id = 59, .r = { .min = 0, .max = 100000000 },
.pll = true },
};
static void __init sama5d2_pmc_setup(struct device_node *np)
{
struct clk_range range = CLK_RANGE(0, 0);
const char *slck_name, *mainxtal_name;
struct pmc_data *sama5d2_pmc;
const char *parent_names[6];
struct regmap *regmap, *regmap_sfr;
struct clk_hw *hw;
int i;
bool bypass;
i = of_property_match_string(np, "clock-names", "slow_clk");
if (i < 0)
return;
slck_name = of_clk_get_parent_name(np, i);
i = of_property_match_string(np, "clock-names", "main_xtal");
if (i < 0)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap))
return;
sama5d2_pmc = pmc_data_allocate(PMC_I2S1_MUX + 1,
nck(sama5d2_systemck),
nck(sama5d2_periph32ck),
nck(sama5d2_gck));
if (!sama5d2_pmc)
return;
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
100000000);
if (IS_ERR(hw))
goto err_free;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_MAIN] = hw;
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
&sama5d3_pll_layout, &plla_characteristics);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_audio_pll_frac(regmap, "audiopll_fracck",
"mainck");
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_audio_pll_pad(regmap, "audiopll_padck",
"audiopll_fracck");
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_audio_pll_pmc(regmap, "audiopll_pmcck",
"audiopll_fracck");
if (IS_ERR(hw))
goto err_free;
regmap_sfr = syscon_regmap_lookup_by_compatible("atmel,sama5d2-sfr");
if (IS_ERR(regmap_sfr))
regmap_sfr = NULL;
hw = at91_clk_register_utmi(regmap, regmap_sfr, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_UTMI] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_MCK] = hw;
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_MCK2] = hw;
parent_names[0] = "plladivck";
parent_names[1] = "utmick";
hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "mck";
for (i = 0; i < 3; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
&at91sam9x5_programmable_layout);
if (IS_ERR(hw))
goto err_free;
}
for (i = 0; i < ARRAY_SIZE(sama5d2_systemck); i++) {
hw = at91_clk_register_system(regmap, sama5d2_systemck[i].n,
sama5d2_systemck[i].p,
sama5d2_systemck[i].id);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->shws[sama5d2_systemck[i].id] = hw;
}
for (i = 0; i < ARRAY_SIZE(sama5d2_periphck); i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
sama5d2_periphck[i].n,
"masterck",
sama5d2_periphck[i].id,
&range);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->phws[sama5d2_periphck[i].id] = hw;
}
for (i = 0; i < ARRAY_SIZE(sama5d2_periph32ck); i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
sama5d2_periph32ck[i].n,
"h32mxck",
sama5d2_periph32ck[i].id,
&sama5d2_periph32ck[i].r);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->phws[sama5d2_periph32ck[i].id] = hw;
}
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "mck";
parent_names[5] = "audiopll_pmcck";
for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
sama5d2_gck[i].n,
parent_names, 6,
sama5d2_gck[i].id,
sama5d2_gck[i].pll,
&sama5d2_gck[i].r);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->ghws[sama5d2_gck[i].id] = hw;
}
if (regmap_sfr) {
parent_names[0] = "i2s0_clk";
parent_names[1] = "i2s0_gclk";
hw = at91_clk_i2s_mux_register(regmap_sfr, "i2s0_muxclk",
parent_names, 2, 0);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_I2S0_MUX] = hw;
parent_names[0] = "i2s1_clk";
parent_names[1] = "i2s1_gclk";
hw = at91_clk_i2s_mux_register(regmap_sfr, "i2s1_muxclk",
parent_names, 2, 1);
if (IS_ERR(hw))
goto err_free;
sama5d2_pmc->chws[PMC_I2S1_MUX] = hw;
}
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d2_pmc);
return;
err_free:
pmc_data_free(sama5d2_pmc);
}
CLK_OF_DECLARE_DRIVER(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup);

View File

@ -0,0 +1,264 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <dt-bindings/clock/at91.h>
#include "pmc.h"
static const struct clk_master_characteristics mck_characteristics = {
.output = { .min = 125000000, .max = 200000000 },
.divisors = { 1, 2, 4, 3 },
};
static u8 plla_out[] = { 0 };
static u16 plla_icpll[] = { 0 };
static struct clk_range plla_outputs[] = {
{ .min = 600000000, .max = 1200000000 },
};
static const struct clk_pll_characteristics plla_characteristics = {
.input = { .min = 12000000, .max = 12000000 },
.num_output = ARRAY_SIZE(plla_outputs),
.output = plla_outputs,
.icpll = plla_icpll,
.out = plla_out,
};
static const struct {
char *n;
char *p;
u8 id;
} sama5d4_systemck[] = {
{ .n = "ddrck", .p = "masterck", .id = 2 },
{ .n = "lcdck", .p = "masterck", .id = 3 },
{ .n = "smdck", .p = "smdclk", .id = 4 },
{ .n = "uhpck", .p = "usbck", .id = 6 },
{ .n = "udpck", .p = "usbck", .id = 7 },
{ .n = "pck0", .p = "prog0", .id = 8 },
{ .n = "pck1", .p = "prog1", .id = 9 },
{ .n = "pck2", .p = "prog2", .id = 10 },
};
static const struct {
char *n;
u8 id;
} sama5d4_periph32ck[] = {
{ .n = "pioD_clk", .id = 5 },
{ .n = "usart0_clk", .id = 6 },
{ .n = "usart1_clk", .id = 7 },
{ .n = "icm_clk", .id = 9 },
{ .n = "aes_clk", .id = 12 },
{ .n = "tdes_clk", .id = 14 },
{ .n = "sha_clk", .id = 15 },
{ .n = "matrix1_clk", .id = 17 },
{ .n = "hsmc_clk", .id = 22 },
{ .n = "pioA_clk", .id = 23 },
{ .n = "pioB_clk", .id = 24 },
{ .n = "pioC_clk", .id = 25 },
{ .n = "pioE_clk", .id = 26 },
{ .n = "uart0_clk", .id = 27 },
{ .n = "uart1_clk", .id = 28 },
{ .n = "usart2_clk", .id = 29 },
{ .n = "usart3_clk", .id = 30 },
{ .n = "usart4_clk", .id = 31 },
{ .n = "twi0_clk", .id = 32 },
{ .n = "twi1_clk", .id = 33 },
{ .n = "twi2_clk", .id = 34 },
{ .n = "mci0_clk", .id = 35 },
{ .n = "mci1_clk", .id = 36 },
{ .n = "spi0_clk", .id = 37 },
{ .n = "spi1_clk", .id = 38 },
{ .n = "spi2_clk", .id = 39 },
{ .n = "tcb0_clk", .id = 40 },
{ .n = "tcb1_clk", .id = 41 },
{ .n = "tcb2_clk", .id = 42 },
{ .n = "pwm_clk", .id = 43 },
{ .n = "adc_clk", .id = 44 },
{ .n = "dbgu_clk", .id = 45 },
{ .n = "uhphs_clk", .id = 46 },
{ .n = "udphs_clk", .id = 47 },
{ .n = "ssc0_clk", .id = 48 },
{ .n = "ssc1_clk", .id = 49 },
{ .n = "trng_clk", .id = 53 },
{ .n = "macb0_clk", .id = 54 },
{ .n = "macb1_clk", .id = 55 },
{ .n = "fuse_clk", .id = 57 },
{ .n = "securam_clk", .id = 59 },
{ .n = "smd_clk", .id = 61 },
{ .n = "twi3_clk", .id = 62 },
{ .n = "catb_clk", .id = 63 },
};
static const struct {
char *n;
u8 id;
} sama5d4_periphck[] = {
{ .n = "dma0_clk", .id = 8 },
{ .n = "cpkcc_clk", .id = 10 },
{ .n = "aesb_clk", .id = 13 },
{ .n = "mpddr_clk", .id = 16 },
{ .n = "matrix0_clk", .id = 18 },
{ .n = "vdec_clk", .id = 19 },
{ .n = "dma1_clk", .id = 50 },
{ .n = "lcdc_clk", .id = 51 },
{ .n = "isi_clk", .id = 52 },
};
static void __init sama5d4_pmc_setup(struct device_node *np)
{
struct clk_range range = CLK_RANGE(0, 0);
const char *slck_name, *mainxtal_name;
struct pmc_data *sama5d4_pmc;
const char *parent_names[5];
struct regmap *regmap;
struct clk_hw *hw;
int i;
bool bypass;
i = of_property_match_string(np, "clock-names", "slow_clk");
if (i < 0)
return;
slck_name = of_clk_get_parent_name(np, i);
i = of_property_match_string(np, "clock-names", "main_xtal");
if (i < 0)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
if (IS_ERR(regmap))
return;
sama5d4_pmc = pmc_data_allocate(PMC_MCK2 + 1,
nck(sama5d4_systemck),
nck(sama5d4_periph32ck), 0);
if (!sama5d4_pmc)
return;
hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000,
100000000);
if (IS_ERR(hw))
goto err_free;
bypass = of_property_read_bool(np, "atmel,osc-bypass");
hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name,
bypass);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "main_rc_osc";
parent_names[1] = "main_osc";
hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0,
&sama5d3_pll_layout, &plla_characteristics);
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack");
if (IS_ERR(hw))
goto err_free;
hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck");
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->chws[PMC_UTMI] = hw;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
hw = at91_clk_register_master(regmap, "masterck", 4, parent_names,
&at91sam9x5_master_layout,
&mck_characteristics);
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->chws[PMC_MCK] = hw;
hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck");
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->chws[PMC_MCK2] = hw;
parent_names[0] = "plladivck";
parent_names[1] = "utmick";
hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = "plladivck";
parent_names[1] = "utmick";
hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2);
if (IS_ERR(hw))
goto err_free;
parent_names[0] = slck_name;
parent_names[1] = "mainck";
parent_names[2] = "plladivck";
parent_names[3] = "utmick";
parent_names[4] = "mck";
for (i = 0; i < 3; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);
hw = at91_clk_register_programmable(regmap, name,
parent_names, 5, i,
&at91sam9x5_programmable_layout);
if (IS_ERR(hw))
goto err_free;
}
for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) {
hw = at91_clk_register_system(regmap, sama5d4_systemck[i].n,
sama5d4_systemck[i].p,
sama5d4_systemck[i].id);
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->shws[sama5d4_systemck[i].id] = hw;
}
for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
sama5d4_periphck[i].n,
"masterck",
sama5d4_periphck[i].id,
&range);
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->phws[sama5d4_periphck[i].id] = hw;
}
for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) {
hw = at91_clk_register_sam9x5_peripheral(regmap, &pmc_pcr_lock,
sama5d4_periph32ck[i].n,
"h32mxck",
sama5d4_periph32ck[i].id,
&range);
if (IS_ERR(hw))
goto err_free;
sama5d4_pmc->phws[sama5d4_periph32ck[i].id] = hw;
}
of_clk_add_hw_provider(np, of_clk_hw_pmc_get, sama5d4_pmc);
return;
err_free:
pmc_data_free(sama5d4_pmc);
}
CLK_OF_DECLARE_DRIVER(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup);

View File

@ -301,13 +301,13 @@ static void __init of_axs10x_pll_clk_setup(struct device_node *node)
ret = clk_hw_register(NULL, &pll_clk->hw);
if (ret) {
pr_err("failed to register %s clock\n", node->name);
pr_err("failed to register %pOFn clock\n", node);
goto err_unmap_lock;
}
ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw);
if (ret) {
pr_err("failed to add hw provider for %s clock\n", node->name);
pr_err("failed to add hw provider for %pOFn clock\n", node);
goto err_unregister_clk;
}

View File

@ -808,29 +808,29 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu,
ret = of_address_to_resource(node, 0, &res);
if (ret) {
pr_err("%s: no valid CCU registers found for %s\n", __func__,
node->name);
pr_err("%s: no valid CCU registers found for %pOFn\n", __func__,
node);
goto out_err;
}
range = resource_size(&res);
if (range > (resource_size_t)U32_MAX) {
pr_err("%s: address range too large for %s\n", __func__,
node->name);
pr_err("%s: address range too large for %pOFn\n", __func__,
node);
goto out_err;
}
ccu->range = (u32)range;
if (!ccu_data_valid(ccu)) {
pr_err("%s: ccu data not valid for %s\n", __func__, node->name);
pr_err("%s: ccu data not valid for %pOFn\n", __func__, node);
goto out_err;
}
ccu->base = ioremap(res.start, ccu->range);
if (!ccu->base) {
pr_err("%s: unable to map CCU registers for %s\n", __func__,
node->name);
pr_err("%s: unable to map CCU registers for %pOFn\n", __func__,
node);
goto out_err;
}
ccu->node = of_node_get(node);
@ -848,16 +848,16 @@ void __init kona_dt_ccu_setup(struct ccu_data *ccu,
ret = of_clk_add_hw_provider(node, of_clk_kona_onecell_get, ccu);
if (ret) {
pr_err("%s: error adding ccu %s as provider (%d)\n", __func__,
node->name, ret);
pr_err("%s: error adding ccu %pOFn as provider (%d)\n", __func__,
node, ret);
goto out_err;
}
if (!kona_ccu_init(ccu))
pr_err("Broadcom %s initialization had errors\n", node->name);
pr_err("Broadcom %pOFn initialization had errors\n", node);
return;
out_err:
kona_ccu_teardown(ccu);
pr_err("Broadcom %s setup aborted\n", node->name);
pr_err("Broadcom %pOFn setup aborted\n", node);
}

View File

@ -281,7 +281,7 @@ static void __init asm9260_acc_init(struct device_node *np)
base = of_io_request_and_map(np, 0, np->name);
if (IS_ERR(base))
panic("%s: unable to map resource", np->name);
panic("%pOFn: unable to map resource", np);
/* register pll */
rate = (ioread32(base + HW_SYSPLLCTRL) & 0xffff) * 1000000;
@ -292,7 +292,7 @@ static void __init asm9260_acc_init(struct device_node *np)
ref_clk, 0, rate, accuracy);
if (IS_ERR(hw))
panic("%s: can't register REFCLK. Check DT!", np->name);
panic("%pOFn: can't register REFCLK. Check DT!", np);
for (n = 0; n < ARRAY_SIZE(asm9260_mux_clks); n++) {
const struct asm9260_mux_clock *mc = &asm9260_mux_clks[n];

View File

@ -17,8 +17,65 @@
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/of.h>
#include <linux/slab.h>
static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
struct clk_bulk_data *clks)
{
int ret;
int i;
for (i = 0; i < num_clks; i++)
clks[i].clk = NULL;
for (i = 0; i < num_clks; i++) {
clks[i].clk = of_clk_get(np, i);
if (IS_ERR(clks[i].clk)) {
ret = PTR_ERR(clks[i].clk);
pr_err("%pOF: Failed to get clk index: %d ret: %d\n",
np, i, ret);
clks[i].clk = NULL;
goto err;
}
}
return 0;
err:
clk_bulk_put(i, clks);
return ret;
}
static int __must_check of_clk_bulk_get_all(struct device_node *np,
struct clk_bulk_data **clks)
{
struct clk_bulk_data *clk_bulk;
int num_clks;
int ret;
num_clks = of_clk_get_parent_count(np);
if (!num_clks)
return 0;
clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);
if (!clk_bulk)
return -ENOMEM;
ret = of_clk_bulk_get(np, num_clks, clk_bulk);
if (ret) {
kfree(clk_bulk);
return ret;
}
*clks = clk_bulk;
return num_clks;
}
void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
{
@ -59,6 +116,29 @@ err:
}
EXPORT_SYMBOL(clk_bulk_get);
void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
{
if (IS_ERR_OR_NULL(clks))
return;
clk_bulk_put(num_clks, clks);
kfree(clks);
}
EXPORT_SYMBOL(clk_bulk_put_all);
int __must_check clk_bulk_get_all(struct device *dev,
struct clk_bulk_data **clks)
{
struct device_node *np = dev_of_node(dev);
if (!np)
return 0;
return of_clk_bulk_get_all(np, clks);
}
EXPORT_SYMBOL(clk_bulk_get_all);
#ifdef CONFIG_HAVE_CLK_PREPARE
/**

View File

@ -669,8 +669,8 @@ static int cdce925_probe(struct i2c_client *client,
/* Register PLL clocks */
for (i = 0; i < data->chip_info->num_plls; ++i) {
pll_clk_name[i] = kasprintf(GFP_KERNEL, "%s.pll%d",
client->dev.of_node->name, i);
pll_clk_name[i] = kasprintf(GFP_KERNEL, "%pOFn.pll%d",
client->dev.of_node, i);
init.name = pll_clk_name[i];
data->pll[i].chip = data;
data->pll[i].hw.init = &init;
@ -703,6 +703,7 @@ static int cdce925_probe(struct i2c_client *client,
0x12 + (i*CDCE925_OFFSET_PLL),
0x07, value & 0x07);
}
of_node_put(np_output);
}
/* Register output clock Y1 */
@ -710,7 +711,7 @@ static int cdce925_probe(struct i2c_client *client,
init.flags = 0;
init.num_parents = 1;
init.parent_names = &parent_name; /* Mux Y1 to input */
init.name = kasprintf(GFP_KERNEL, "%s.Y1", client->dev.of_node->name);
init.name = kasprintf(GFP_KERNEL, "%pOFn.Y1", client->dev.of_node);
data->clk[0].chip = data;
data->clk[0].hw.init = &init;
data->clk[0].index = 0;
@ -727,8 +728,8 @@ static int cdce925_probe(struct i2c_client *client,
init.flags = CLK_SET_RATE_PARENT;
init.num_parents = 1;
for (i = 1; i < data->chip_info->num_outputs; ++i) {
init.name = kasprintf(GFP_KERNEL, "%s.Y%d",
client->dev.of_node->name, i+1);
init.name = kasprintf(GFP_KERNEL, "%pOFn.Y%d",
client->dev.of_node, i+1);
data->clk[i].chip = data;
data->clk[i].hw.init = &init;
data->clk[i].index = i;

View File

@ -70,6 +70,30 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
}
EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
int __must_check devm_clk_bulk_get_all(struct device *dev,
struct clk_bulk_data **clks)
{
struct clk_bulk_devres *devres;
int ret;
devres = devres_alloc(devm_clk_bulk_release,
sizeof(*devres), GFP_KERNEL);
if (!devres)
return -ENOMEM;
ret = clk_bulk_get_all(dev, &devres->clks);
if (ret > 0) {
*clks = devres->clks;
devres->num_clks = ret;
devres_add(dev, devres);
} else {
devres_free(devres);
}
return ret;
}
EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
static int devm_clk_match(struct device *dev, void *res, void *data)
{
struct clk **c = res;

View File

@ -158,14 +158,14 @@ static struct clk *_of_fixed_factor_clk_setup(struct device_node *node)
int ret;
if (of_property_read_u32(node, "clock-div", &div)) {
pr_err("%s Fixed factor clock <%s> must have a clock-div property\n",
__func__, node->name);
pr_err("%s Fixed factor clock <%pOFn> must have a clock-div property\n",
__func__, node);
return ERR_PTR(-EIO);
}
if (of_property_read_u32(node, "clock-mult", &mult)) {
pr_err("%s Fixed factor clock <%s> must have a clock-mult property\n",
__func__, node->name);
pr_err("%s Fixed factor clock <%pOFn> must have a clock-mult property\n",
__func__, node);
return ERR_PTR(-EIO);
}

View File

@ -200,6 +200,7 @@ static int of_fixed_clk_remove(struct platform_device *pdev)
{
struct clk *clk = platform_get_drvdata(pdev);
of_clk_del_provider(pdev->dev.of_node);
clk_unregister_fixed_rate(clk);
return 0;

View File

@ -233,11 +233,11 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
if (IS_ERR(gpiod)) {
ret = PTR_ERR(gpiod);
if (ret == -EPROBE_DEFER)
pr_debug("%s: %s: GPIOs not yet available, retry later\n",
node->name, __func__);
pr_debug("%pOFn: %s: GPIOs not yet available, retry later\n",
node, __func__);
else
pr_err("%s: %s: Can't get '%s' named GPIO property\n",
node->name, __func__,
pr_err("%pOFn: %s: Can't get '%s' named GPIO property\n",
node, __func__,
gpio_name);
return ret;
}

View File

@ -390,13 +390,13 @@ static void __init of_hsdk_pll_clk_setup(struct device_node *node)
ret = clk_hw_register(NULL, &pll_clk->hw);
if (ret) {
pr_err("failed to register %s clock\n", node->name);
pr_err("failed to register %pOFn clock\n", node);
goto err_unmap_spec_regs;
}
ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw);
if (ret) {
pr_err("failed to add hw provider for %s clock\n", node->name);
pr_err("failed to add hw provider for %pOFn clock\n", node);
goto err_unmap_spec_regs;
}

View File

@ -1,24 +1,9 @@
/*
* clk-max77686.c - Clock driver for Maxim 77686/MAX77802
*
* Copyright (C) 2012 Samsung Electornics
* Jonghwa Lee <jonghwa3.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
// SPDX-License-Identifier: GPL-2.0+
//
// clk-max77686.c - Clock driver for Maxim 77686/MAX77802
//
// Copyright (C) 2012 Samsung Electornics
// Jonghwa Lee <jonghwa3.lee@samsung.com>
#include <linux/kernel.h>
#include <linux/slab.h>

View File

@ -97,8 +97,8 @@ static void __init nomadik_src_init(void)
}
src_base = of_iomap(np, 0);
if (!src_base) {
pr_err("%s: must have src parent node with REGS (%s)\n",
__func__, np->name);
pr_err("%s: must have src parent node with REGS (%pOFn)\n",
__func__, np);
return;
}

View File

@ -549,7 +549,7 @@ static void __init npcm7xx_clk_init(struct device_node *clk_np)
ret = of_address_to_resource(clk_np, 0, &res);
if (ret) {
pr_err("%s: failed to get resource, ret %d\n", clk_np->name,
pr_err("%pOFn: failed to get resource, ret %d\n", clk_np,
ret);
return;
}

View File

@ -195,8 +195,8 @@ static void palmas_clks_get_clk_data(struct platform_device *pdev,
prop = PALMAS_EXT_CONTROL_NSLEEP;
break;
default:
dev_warn(&pdev->dev, "%s: Invalid ext control option: %u\n",
node->name, prop);
dev_warn(&pdev->dev, "%pOFn: Invalid ext control option: %u\n",
node, prop);
prop = 0;
break;
}

View File

@ -945,8 +945,8 @@ static void __init core_mux_init(struct device_node *np)
rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
if (rc) {
pr_err("%s: Couldn't register clk provider for node %s: %d\n",
__func__, np->name, rc);
pr_err("%s: Couldn't register clk provider for node %pOFn: %d\n",
__func__, np, rc);
return;
}
}
@ -1199,8 +1199,8 @@ static void __init legacy_pll_init(struct device_node *np, int idx)
rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
if (rc) {
pr_err("%s: Couldn't register clk provider for node %s: %d\n",
__func__, np->name, rc);
pr_err("%s: Couldn't register clk provider for node %pOFn: %d\n",
__func__, np, rc);
goto err_cell;
}
@ -1360,7 +1360,7 @@ static void __init clockgen_init(struct device_node *np)
is_old_ls1021a = true;
}
if (!clockgen.regs) {
pr_err("%s(): %s: of_iomap() failed\n", __func__, np->name);
pr_err("%s(): %pOFn: of_iomap() failed\n", __func__, np);
return;
}
@ -1406,8 +1406,8 @@ static void __init clockgen_init(struct device_node *np)
ret = of_clk_add_provider(np, clockgen_clk_get, &clockgen);
if (ret) {
pr_err("%s: Couldn't register clk provider for node %s: %d\n",
__func__, np->name, ret);
pr_err("%s: Couldn't register clk provider for node %pOFn: %d\n",
__func__, np, ret);
}
return;

View File

@ -1,19 +1,8 @@
/*
* clk-s2mps11.c - Clock driver for S2MPS11.
*
* Copyright (C) 2013,2014 Samsung Electornics
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
// SPDX-License-Identifier: GPL-2.0+
//
// clk-s2mps11.c - Clock driver for S2MPS11.
//
// Copyright (C) 2013,2014 Samsung Electornics
#include <linux/module.h>
#include <linux/err.h>
@ -28,12 +17,7 @@
#include <linux/mfd/samsung/s5m8767.h>
#include <linux/mfd/samsung/core.h>
enum {
S2MPS11_CLK_AP = 0,
S2MPS11_CLK_CP,
S2MPS11_CLK_BT,
S2MPS11_CLKS_NUM,
};
#include <dt-bindings/clock/samsung,s2mps11.h>
struct s2mps11_clk {
struct sec_pmic_dev *iodev;
@ -245,6 +229,36 @@ static const struct platform_device_id s2mps11_clk_id[] = {
};
MODULE_DEVICE_TABLE(platform, s2mps11_clk_id);
#ifdef CONFIG_OF
/*
* Device is instantiated through parent MFD device and device matching is done
* through platform_device_id.
*
* However if device's DT node contains proper clock compatible and driver is
* built as a module, then the *module* matching will be done trough DT aliases.
* This requires of_device_id table. In the same time this will not change the
* actual *device* matching so do not add .of_match_table.
*/
static const struct of_device_id s2mps11_dt_match[] __used = {
{
.compatible = "samsung,s2mps11-clk",
.data = (void *)S2MPS11X,
}, {
.compatible = "samsung,s2mps13-clk",
.data = (void *)S2MPS13X,
}, {
.compatible = "samsung,s2mps14-clk",
.data = (void *)S2MPS14X,
}, {
.compatible = "samsung,s5m8767-clk",
.data = (void *)S5M8767X,
}, {
/* Sentinel */
},
};
MODULE_DEVICE_TABLE(of, s2mps11_dt_match);
#endif
static struct platform_driver s2mps11_clk_driver = {
.driver = {
.name = "s2mps11-clk",

View File

@ -132,7 +132,7 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
count = handle->clk_ops->count_get(handle);
if (count < 0) {
dev_err(dev, "%s: invalid clock output count\n", np->name);
dev_err(dev, "%pOFn: invalid clock output count\n", np);
return -EINVAL;
}

View File

@ -207,7 +207,7 @@ static int scpi_clk_add(struct device *dev, struct device_node *np,
count = of_property_count_strings(np, "clock-output-names");
if (count < 0) {
dev_err(dev, "%s: invalid clock output count\n", np->name);
dev_err(dev, "%pOFn: invalid clock output count\n", np);
return -EINVAL;
}
@ -232,13 +232,13 @@ static int scpi_clk_add(struct device *dev, struct device_node *np,
if (of_property_read_string_index(np, "clock-output-names",
idx, &name)) {
dev_err(dev, "invalid clock name @ %s\n", np->name);
dev_err(dev, "invalid clock name @ %pOFn\n", np);
return -EINVAL;
}
if (of_property_read_u32_index(np, "clock-indices",
idx, &val)) {
dev_err(dev, "invalid clock index @ %s\n", np->name);
dev_err(dev, "invalid clock index @ %pOFn\n", np);
return -EINVAL;
}

View File

@ -1215,8 +1215,8 @@ static int si5351_dt_parse(struct i2c_client *client,
/* per clkout properties */
for_each_child_of_node(np, child) {
if (of_property_read_u32(child, "reg", &num)) {
dev_err(&client->dev, "missing reg property of %s\n",
child->name);
dev_err(&client->dev, "missing reg property of %pOFn\n",
child);
goto put_child;
}

View File

@ -1433,7 +1433,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
base = of_iomap(np, 0);
if (!base) {
pr_err("%s: unable to map resource\n", np->name);
pr_err("%pOFn: unable to map resource\n", np);
return;
}

View File

@ -1216,7 +1216,7 @@ static void __init stm32h7_rcc_init(struct device_node *np)
/* get RCC base @ from DT */
base = of_iomap(np, 0);
if (!base) {
pr_err("%s: unable to map resource", np->name);
pr_err("%pOFn: unable to map resource", np);
goto err_free_clks;
}

View File

@ -2088,7 +2088,7 @@ static void stm32mp1_rcc_init(struct device_node *np)
base = of_iomap(np, 0);
if (!base) {
pr_err("%s: unable to map resource", np->name);
pr_err("%pOFn: unable to map resource", np);
of_node_put(np);
return;
}

View File

@ -54,13 +54,13 @@ static void __init tango4_clkgen_setup(struct device_node *np)
const char *parent = of_clk_get_parent_name(np, 0);
if (!base)
panic("%s: invalid address\n", np->name);
panic("%pOFn: invalid address\n", np);
if (readl(base + CPUCLK_DIV) & DIV_BYPASS)
panic("%s: unsupported cpuclk setup\n", np->name);
panic("%pOFn: unsupported cpuclk setup\n", np);
if (readl(base + SYSCLK_DIV) & DIV_BYPASS)
panic("%s: unsupported sysclk setup\n", np->name);
panic("%pOFn: unsupported sysclk setup\n", np);
writel(0x100, base + CPUCLK_DIV); /* disable frequency ramping */
@ -77,9 +77,9 @@ static void __init tango4_clkgen_setup(struct device_node *np)
pp[3] = clk_register_fixed_factor(NULL, "sdio_clk", "cd6", 0, 1, 2);
if (IS_ERR(pp[0]) || IS_ERR(pp[1]) || IS_ERR(pp[2]) || IS_ERR(pp[3]))
panic("%s: clk registration failed\n", np->name);
panic("%pOFn: clk registration failed\n", np);
if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data))
panic("%s: clk provider registration failed\n", np->name);
panic("%pOFn: clk provider registration failed\n", np);
}
CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup);

View File

@ -923,6 +923,101 @@ static int clk_core_enable_lock(struct clk_core *core)
return ret;
}
/**
* clk_gate_restore_context - restore context for poweroff
* @hw: the clk_hw pointer of clock whose state is to be restored
*
* The clock gate restore context function enables or disables
* the gate clocks based on the enable_count. This is done in cases
* where the clock context is lost and based on the enable_count
* the clock either needs to be enabled/disabled. This
* helps restore the state of gate clocks.
*/
void clk_gate_restore_context(struct clk_hw *hw)
{
struct clk_core *core = hw->core;
if (core->enable_count)
core->ops->enable(hw);
else
core->ops->disable(hw);
}
EXPORT_SYMBOL_GPL(clk_gate_restore_context);
static int clk_core_save_context(struct clk_core *core)
{
struct clk_core *child;
int ret = 0;
hlist_for_each_entry(child, &core->children, child_node) {
ret = clk_core_save_context(child);
if (ret < 0)
return ret;
}
if (core->ops && core->ops->save_context)
ret = core->ops->save_context(core->hw);
return ret;
}
static void clk_core_restore_context(struct clk_core *core)
{
struct clk_core *child;
if (core->ops && core->ops->restore_context)
core->ops->restore_context(core->hw);
hlist_for_each_entry(child, &core->children, child_node)
clk_core_restore_context(child);
}
/**
* clk_save_context - save clock context for poweroff
*
* Saves the context of the clock register for powerstates in which the
* contents of the registers will be lost. Occurs deep within the suspend
* code. Returns 0 on success.
*/
int clk_save_context(void)
{
struct clk_core *clk;
int ret;
hlist_for_each_entry(clk, &clk_root_list, child_node) {
ret = clk_core_save_context(clk);
if (ret < 0)
return ret;
}
hlist_for_each_entry(clk, &clk_orphan_list, child_node) {
ret = clk_core_save_context(clk);
if (ret < 0)
return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(clk_save_context);
/**
* clk_restore_context - restore clock context after poweroff
*
* Restore the saved clock context upon resume.
*
*/
void clk_restore_context(void)
{
struct clk_core *core;
hlist_for_each_entry(core, &clk_root_list, child_node)
clk_core_restore_context(core);
hlist_for_each_entry(core, &clk_orphan_list, child_node)
clk_core_restore_context(core);
}
EXPORT_SYMBOL_GPL(clk_restore_context);
/**
* clk_enable - ungate a clock
* @clk: the clk being ungated

View File

@ -303,24 +303,6 @@ static int davinci_lpsc_clk_reset(struct clk *clk, bool reset)
return 0;
}
/*
* REVISIT: These exported functions can be removed after a non-DT lookup is
* added to the reset controller framework and the davinci-rproc driver is
* updated to use the generic reset controller framework.
*/
int davinci_clk_reset_assert(struct clk *clk)
{
return davinci_lpsc_clk_reset(clk, true);
}
EXPORT_SYMBOL(davinci_clk_reset_assert);
int davinci_clk_reset_deassert(struct clk *clk)
{
return davinci_lpsc_clk_reset(clk, false);
}
EXPORT_SYMBOL(davinci_clk_reset_deassert);
static int davinci_psc_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{

View File

@ -21,6 +21,13 @@ config COMMON_CLK_HI3660
help
Build the clock driver for hi3660.
config COMMON_CLK_HI3670
bool "Hi3670 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST
default ARCH_HISI
help
Build the clock driver for hi3670.
config COMMON_CLK_HI3798CV200
tristate "Hi3798CV200 Clock Driver"
depends on ARCH_HISI || COMPILE_TEST

View File

@ -11,6 +11,7 @@ obj-$(CONFIG_ARCH_HIX5HD2) += clk-hix5hd2.o
obj-$(CONFIG_COMMON_CLK_HI3516CV300) += crg-hi3516cv300.o
obj-$(CONFIG_COMMON_CLK_HI3519) += clk-hi3519.o
obj-$(CONFIG_COMMON_CLK_HI3660) += clk-hi3660.o
obj-$(CONFIG_COMMON_CLK_HI3670) += clk-hi3670.o
obj-$(CONFIG_COMMON_CLK_HI3798CV200) += crg-hi3798cv200.o
obj-$(CONFIG_COMMON_CLK_HI6220) += clk-hi6220.o
obj-$(CONFIG_RESET_HISI) += reset.o

File diff suppressed because it is too large Load Diff

View File

@ -109,9 +109,8 @@ struct hisi_reset_controller *hisi_reset_init(struct platform_device *pdev)
return NULL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rstc->membase = devm_ioremap(&pdev->dev,
res->start, resource_size(res));
if (!rstc->membase)
rstc->membase = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rstc->membase))
return NULL;
spin_lock_init(&rstc->lock);

View File

@ -94,7 +94,7 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name,
init.name = name;
init.ops = &clk_cpu_ops;
init.flags = 0;
init.flags = CLK_IS_CRITICAL;
init.parent_names = &parent_name;
init.num_parents = 1;

View File

@ -789,6 +789,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_MLB] = imx_clk_gate2("mlb", "axi", base + 0x74, 18);
clk[IMX6QDL_CLK_MMDC_CH0_AXI] = imx_clk_gate2_flags("mmdc_ch0_axi", "mmdc_ch0_axi_podf", base + 0x74, 20, CLK_IS_CRITICAL);
clk[IMX6QDL_CLK_MMDC_CH1_AXI] = imx_clk_gate2("mmdc_ch1_axi", "mmdc_ch1_axi_podf", base + 0x74, 22);
clk[IMX6QDL_CLK_MMDC_P0_IPG] = imx_clk_gate2_flags("mmdc_p0_ipg", "ipg", base + 0x74, 24, CLK_IS_CRITICAL);
clk[IMX6QDL_CLK_OCRAM] = imx_clk_gate2("ocram", "ahb", base + 0x74, 28);
clk[IMX6QDL_CLK_OPENVG_AXI] = imx_clk_gate2("openvg_axi", "axi", base + 0x74, 30);
clk[IMX6QDL_CLK_PCIE_AXI] = imx_clk_gate2("pcie_axi", "pcie_axi_sel", base + 0x78, 0);

View File

@ -386,6 +386,8 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_LCDIF_AXI] = imx_clk_gate2("lcdif_axi", "lcdif_axi_podf", base + 0x74, 6);
clks[IMX6SL_CLK_LCDIF_PIX] = imx_clk_gate2("lcdif_pix", "lcdif_pix_podf", base + 0x74, 8);
clks[IMX6SL_CLK_EPDC_PIX] = imx_clk_gate2("epdc_pix", "epdc_pix_podf", base + 0x74, 10);
clks[IMX6SL_CLK_MMDC_P0_IPG] = imx_clk_gate2_flags("mmdc_p0_ipg", "ipg", base + 0x74, 24, CLK_IS_CRITICAL);
clks[IMX6SL_CLK_MMDC_P1_IPG] = imx_clk_gate2("mmdc_p1_ipg", "ipg", base + 0x74, 26);
clks[IMX6SL_CLK_OCRAM] = imx_clk_gate2("ocram", "ocram_podf", base + 0x74, 28);
clks[IMX6SL_CLK_PWM1] = imx_clk_gate2("pwm1", "perclk", base + 0x78, 16);
clks[IMX6SL_CLK_PWM2] = imx_clk_gate2("pwm2", "perclk", base + 0x78, 18);

View File

@ -293,6 +293,7 @@ static void __init imx6sll_clocks_init(struct device_node *ccm_node)
clks[IMX6SLL_CLK_WDOG1] = imx_clk_gate2("wdog1", "ipg", base + 0x74, 16);
clks[IMX6SLL_CLK_MMDC_P0_FAST] = imx_clk_gate_flags("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20, CLK_IS_CRITICAL);
clks[IMX6SLL_CLK_MMDC_P0_IPG] = imx_clk_gate2_flags("mmdc_p0_ipg", "ipg", base + 0x74, 24, CLK_IS_CRITICAL);
clks[IMX6SLL_CLK_MMDC_P1_IPG] = imx_clk_gate2("mmdc_p1_ipg", "ipg", base + 0x74, 26);
clks[IMX6SLL_CLK_OCRAM] = imx_clk_gate_flags("ocram","ahb", base + 0x74, 28, CLK_IS_CRITICAL);
/* CCGR4 */

View File

@ -431,6 +431,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clks[IMX6SX_CLK_MLB] = imx_clk_gate2("mlb", "ahb", base + 0x74, 18);
clks[IMX6SX_CLK_MMDC_P0_FAST] = imx_clk_gate2_flags("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20, CLK_IS_CRITICAL);
clks[IMX6SX_CLK_MMDC_P0_IPG] = imx_clk_gate2_flags("mmdc_p0_ipg", "ipg", base + 0x74, 24, CLK_IS_CRITICAL);
clks[IMX6SX_CLK_MMDC_P1_IPG] = imx_clk_gate2("mmdc_p1_ipg", "ipg", base + 0x74, 26);
clks[IMX6SX_CLK_OCRAM] = imx_clk_gate2_flags("ocram", "ocram_podf", base + 0x74, 28, CLK_IS_CRITICAL);
/* CCGR4 */

View File

@ -408,6 +408,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6UL_CLK_WDOG1] = imx_clk_gate2("wdog1", "ipg", base + 0x74, 16);
clks[IMX6UL_CLK_MMDC_P0_FAST] = imx_clk_gate_flags("mmdc_p0_fast", "mmdc_podf", base + 0x74, 20, CLK_IS_CRITICAL);
clks[IMX6UL_CLK_MMDC_P0_IPG] = imx_clk_gate2_flags("mmdc_p0_ipg", "ipg", base + 0x74, 24, CLK_IS_CRITICAL);
clks[IMX6UL_CLK_MMDC_P1_IPG] = imx_clk_gate2("mmdc_p1_ipg", "ipg", base + 0x74, 26);
clks[IMX6UL_CLK_AXI] = imx_clk_gate_flags("axi", "axi_podf", base + 0x74, 28, CLK_IS_CRITICAL);
/* CCGR4 */

View File

@ -379,14 +379,6 @@ static const char *pll_enet_bypass_sel[] = { "pll_enet_main", "pll_enet_main_src
static const char *pll_audio_bypass_sel[] = { "pll_audio_main", "pll_audio_main_src", };
static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_src", };
static int const clks_init_on[] __initconst = {
IMX7D_ARM_A7_ROOT_CLK, IMX7D_MAIN_AXI_ROOT_CLK,
IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK,
IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK,
IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK,
IMX7D_AHB_CHANNEL_ROOT_CLK, IMX7D_IPG_ROOT_CLK,
};
static struct clk_onecell_data clk_data;
static struct clk ** const uart_clks[] __initconst = {
@ -404,7 +396,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
void __iomem *base;
int i;
clks[IMX7D_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
clks[IMX7D_OSC_24M_CLK] = of_clk_get_by_name(ccm_node, "osc");
@ -467,7 +458,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_PLL_SYS_MAIN_120M] = imx_clk_fixed_factor("pll_sys_main_120m", "pll_sys_main_clk", 1, 4);
clks[IMX7D_PLL_DRAM_MAIN_533M] = imx_clk_fixed_factor("pll_dram_533m", "pll_dram_main_clk", 1, 2);
clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4);
clks[IMX7D_PLL_SYS_MAIN_480M_CLK] = imx_clk_gate_dis_flags("pll_sys_main_480m_clk", "pll_sys_main_480m", base + 0xb0, 4, CLK_IS_CRITICAL);
clks[IMX7D_PLL_SYS_MAIN_240M_CLK] = imx_clk_gate_dis("pll_sys_main_240m_clk", "pll_sys_main_240m", base + 0xb0, 5);
clks[IMX7D_PLL_SYS_MAIN_120M_CLK] = imx_clk_gate_dis("pll_sys_main_120m_clk", "pll_sys_main_120m", base + 0xb0, 6);
clks[IMX7D_PLL_DRAM_MAIN_533M_CLK] = imx_clk_gate("pll_dram_533m_clk", "pll_dram_533m", base + 0x70, 12);
@ -720,7 +711,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider2("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2);
clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider_flags("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE | CLK_SET_RATE_PARENT);
clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
@ -784,17 +775,17 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_CLKO1_ROOT_DIV] = imx_clk_divider2("clko1_post_div", "clko1_pre_div", base + 0xbd80, 0, 6);
clks[IMX7D_CLKO2_ROOT_DIV] = imx_clk_divider2("clko2_post_div", "clko2_pre_div", base + 0xbe00, 0, 6);
clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0);
clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate2_flags("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0, CLK_OPS_PARENT_ENABLE);
clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0);
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate2_flags("main_axi_root_clk", "axi_post_div", base + 0x4040, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "main_axi_root_clk", base + 0x4110, 0);
clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate2_flags("dram_root_clk", "dram_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate2_flags("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0, CLK_IS_CRITICAL | CLK_OPS_PARENT_ENABLE);
clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate4("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
@ -883,9 +874,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clk_data.clk_num = ARRAY_SIZE(clks);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
clk_prepare_enable(clks[clks_init_on[i]]);
clk_set_parent(clks[IMX7D_PLL_ARM_MAIN_BYPASS], clks[IMX7D_PLL_ARM_MAIN]);
clk_set_parent(clks[IMX7D_PLL_DRAM_MAIN_BYPASS], clks[IMX7D_PLL_DRAM_MAIN]);
clk_set_parent(clks[IMX7D_PLL_SYS_MAIN_BYPASS], clks[IMX7D_PLL_SYS_MAIN]);

View File

@ -137,6 +137,13 @@ static inline struct clk *imx_clk_gate_dis(const char *name, const char *parent,
shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
}
static inline struct clk *imx_clk_gate_dis_flags(const char *name, const char *parent,
void __iomem *reg, u8 shift, unsigned long flags)
{
return clk_register_gate(NULL, name, parent, flags | CLK_SET_RATE_PARENT, reg,
shift, CLK_GATE_SET_TO_DISABLE, &imx_ccm_lock);
}
static inline struct clk *imx_clk_gate2(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{

View File

@ -0,0 +1,47 @@
menu "Ingenic JZ47xx CGU drivers"
depends on MIPS
config INGENIC_CGU_COMMON
bool
config INGENIC_CGU_JZ4740
bool "Ingenic JZ4740 CGU driver"
default MACH_JZ4740
select INGENIC_CGU_COMMON
help
Support the clocks provided by the CGU hardware on Ingenic JZ4740
and compatible SoCs.
If building for a JZ4740 SoC, you want to say Y here.
config INGENIC_CGU_JZ4725B
bool "Ingenic JZ4725B CGU driver"
default MACH_JZ4725B
select INGENIC_CGU_COMMON
help
Support the clocks provided by the CGU hardware on Ingenic JZ4725B
and compatible SoCs.
If building for a JZ4725B SoC, you want to say Y here.
config INGENIC_CGU_JZ4770
bool "Ingenic JZ4770 CGU driver"
default MACH_JZ4770
select INGENIC_CGU_COMMON
help
Support the clocks provided by the CGU hardware on Ingenic JZ4770
and compatible SoCs.
If building for a JZ4770 SoC, you want to say Y here.
config INGENIC_CGU_JZ4780
bool "Ingenic JZ4780 CGU driver"
default MACH_JZ4780
select INGENIC_CGU_COMMON
help
Support the clocks provided by the CGU hardware on Ingenic JZ4780
and compatible SoCs.
If building for a JZ4780 SoC, you want to say Y here.
endmenu

View File

@ -1,4 +1,5 @@
obj-y += cgu.o
obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o
obj-$(CONFIG_MACH_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o
obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o

View File

@ -0,0 +1,225 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Ingenic JZ4725B SoC CGU driver
*
* Copyright (C) 2018 Paul Cercueil
* Author: Paul Cercueil <paul@crapouillou.net>
*/
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <dt-bindings/clock/jz4725b-cgu.h>
#include "cgu.h"
/* CGU register offsets */
#define CGU_REG_CPCCR 0x00
#define CGU_REG_LCR 0x04
#define CGU_REG_CPPCR 0x10
#define CGU_REG_CLKGR 0x20
#define CGU_REG_OPCR 0x24
#define CGU_REG_I2SCDR 0x60
#define CGU_REG_LPCDR 0x64
#define CGU_REG_MSCCDR 0x68
#define CGU_REG_SSICDR 0x74
#define CGU_REG_CIMCDR 0x78
/* bits within the LCR register */
#define LCR_SLEEP BIT(0)
static struct ingenic_cgu *cgu;
static const s8 pll_od_encoding[4] = {
0x0, 0x1, -1, 0x3,
};
static const struct ingenic_cgu_clk_info jz4725b_cgu_clocks[] = {
/* External clocks */
[JZ4725B_CLK_EXT] = { "ext", CGU_CLK_EXT },
[JZ4725B_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
[JZ4725B_CLK_PLL] = {
"pll", CGU_CLK_PLL,
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.pll = {
.reg = CGU_REG_CPPCR,
.m_shift = 23,
.m_bits = 9,
.m_offset = 2,
.n_shift = 18,
.n_bits = 5,
.n_offset = 2,
.od_shift = 16,
.od_bits = 2,
.od_max = 4,
.od_encoding = pll_od_encoding,
.stable_bit = 10,
.bypass_bit = 9,
.enable_bit = 8,
},
},
/* Muxes & dividers */
[JZ4725B_CLK_PLL_HALF] = {
"pll half", CGU_CLK_DIV,
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1 },
},
[JZ4725B_CLK_CCLK] = {
"cclk", CGU_CLK_DIV,
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
},
[JZ4725B_CLK_HCLK] = {
"hclk", CGU_CLK_DIV,
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
},
[JZ4725B_CLK_PCLK] = {
"pclk", CGU_CLK_DIV,
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1 },
},
[JZ4725B_CLK_MCLK] = {
"mclk", CGU_CLK_DIV,
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1 },
},
[JZ4725B_CLK_IPU] = {
"ipu", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { JZ4725B_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1 },
.gate = { CGU_REG_CLKGR, 13 },
},
[JZ4725B_CLK_LCD] = {
"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },
.div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 9 },
},
[JZ4725B_CLK_I2S] = {
"i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },
.mux = { CGU_REG_CPCCR, 31, 1 },
.div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 6 },
},
[JZ4725B_CLK_SPI] = {
"spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL, -1, -1 },
.mux = { CGU_REG_SSICDR, 31, 1 },
.div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 4 },
},
[JZ4725B_CLK_MMC_MUX] = {
"mmc_mux", CGU_CLK_DIV,
.parents = { JZ4725B_CLK_PLL_HALF, -1, -1, -1 },
.div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
},
[JZ4725B_CLK_UDC] = {
"udc", CGU_CLK_MUX | CGU_CLK_DIV,
.parents = { JZ4725B_CLK_EXT, JZ4725B_CLK_PLL_HALF, -1, -1 },
.mux = { CGU_REG_CPCCR, 29, 1 },
.div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
},
/* Gate-only clocks */
[JZ4725B_CLK_UART] = {
"uart", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 0 },
},
[JZ4725B_CLK_DMA] = {
"dma", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_PCLK, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 12 },
},
[JZ4725B_CLK_ADC] = {
"adc", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 7 },
},
[JZ4725B_CLK_I2C] = {
"i2c", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 3 },
},
[JZ4725B_CLK_AIC] = {
"aic", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_EXT, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 5 },
},
[JZ4725B_CLK_MMC0] = {
"mmc0", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 6 },
},
[JZ4725B_CLK_MMC1] = {
"mmc1", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_MMC_MUX, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 16 },
},
[JZ4725B_CLK_BCH] = {
"bch", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_MCLK/* not sure */, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 11 },
},
[JZ4725B_CLK_TCU] = {
"tcu", CGU_CLK_GATE,
.parents = { JZ4725B_CLK_EXT/* not sure */, -1, -1, -1 },
.gate = { CGU_REG_CLKGR, 1 },
},
[JZ4725B_CLK_EXT512] = {
"ext/512", CGU_CLK_FIXDIV,
.parents = { JZ4725B_CLK_EXT },
/* Doc calls it EXT512, but it seems to be /256... */
.fixdiv = { 256 },
},
[JZ4725B_CLK_RTC] = {
"rtc", CGU_CLK_MUX,
.parents = { JZ4725B_CLK_EXT512, JZ4725B_CLK_OSC32K, -1, -1 },
.mux = { CGU_REG_OPCR, 2, 1},
},
};
static void __init jz4725b_cgu_init(struct device_node *np)
{
int retval;
cgu = ingenic_cgu_new(jz4725b_cgu_clocks,
ARRAY_SIZE(jz4725b_cgu_clocks), np);
if (!cgu) {
pr_err("%s: failed to initialise CGU\n", __func__);
return;
}
retval = ingenic_cgu_register_clocks(cgu);
if (retval)
pr_err("%s: failed to register CGU Clocks\n", __func__);
}
CLK_OF_DECLARE(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);

View File

@ -7,7 +7,7 @@ config COMMON_CLK_KEYSTONE
config TI_SCI_CLK
tristate "TI System Control Interface clock drivers"
depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF
depends on (ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST) && OF
depends on TI_SCI_PROTOCOL
default ARCH_KEYSTONE
---help---

View File

@ -245,7 +245,7 @@ static void __init of_psc_clk_init(struct device_node *node, spinlock_t *lock)
return;
}
pr_err("%s: error registering clk %s\n", __func__, node->name);
pr_err("%s: error registering clk %pOFn\n", __func__, node);
unmap_domain:
iounmap(data->domain_base);
@ -266,3 +266,8 @@ static void __init of_keystone_psc_clk_init(struct device_node *node)
}
CLK_OF_DECLARE(keystone_gate_clk, "ti,keystone,psc-clock",
of_keystone_psc_clk_init);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Clock driver for Keystone 2 based devices");
MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
MODULE_AUTHOR("Santosh Shilimkar <santosh.shilimkar@ti.com>");

View File

@ -219,7 +219,7 @@ static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
}
out:
pr_err("%s: error initializing pll %s\n", __func__, node->name);
pr_err("%s: error initializing pll %pOFn\n", __func__, node);
kfree(pll_data);
}
@ -338,3 +338,8 @@ static void __init of_pll_mux_clk_init(struct device_node *node)
pr_err("%s: error registering mux %s\n", __func__, clk_name);
}
CLK_OF_DECLARE(pll_mux_clock, "ti,keystone,pll-mux-clock", of_pll_mux_clk_init);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PLL clock driver for Keystone devices");
MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
MODULE_AUTHOR("Santosh Shilimkar <santosh.shilimkar@ti.com>");

View File

@ -249,11 +249,6 @@ static const char * const msdc30_parents[] = {
"univpll2_d4"
};
static const char * const audio_parents[] = {
"clk26m",
"syspll1_d16"
};
static const char * const aud_intbus_parents[] = {
"clk26m",
"syspll1_d4",

View File

@ -101,10 +101,16 @@ static const char * const mst_mux_parent_names[] = {
"axg_mst_in4", "axg_mst_in5", "axg_mst_in6", "axg_mst_in7",
};
#define AXG_MST_MCLK_MUX(_name, _reg) \
AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, CLK_MUX_ROUND_CLOSEST, \
#define AXG_MST_MUX(_name, _reg, _flag) \
AXG_AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
mst_mux_parent_names, CLK_SET_RATE_PARENT)
#define AXG_MST_MCLK_MUX(_name, _reg) \
AXG_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
#define AXG_MST_SYS_MUX(_name, _reg) \
AXG_MST_MUX(_name, _reg, 0)
static AXG_MST_MCLK_MUX(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_MUX(mst_b_mclk, AUDIO_MCLK_B_CTRL);
static AXG_MST_MCLK_MUX(mst_c_mclk, AUDIO_MCLK_C_CTRL);
@ -112,13 +118,19 @@ static AXG_MST_MCLK_MUX(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_MUX(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_MUX(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_MUX(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
static AXG_MST_MCLK_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_MUX(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
static AXG_MST_MCLK_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
static AXG_MST_SYS_MUX(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_SYS_MUX(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
#define AXG_MST_MCLK_DIV(_name, _reg) \
AXG_AUD_DIV(_name##_div, _reg, 0, 16, CLK_DIVIDER_ROUND_CLOSEST, \
"axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
#define AXG_MST_DIV(_name, _reg, _flag) \
AXG_AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
"axg_"#_name"_sel", CLK_SET_RATE_PARENT) \
#define AXG_MST_MCLK_DIV(_name, _reg) \
AXG_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
#define AXG_MST_SYS_DIV(_name, _reg) \
AXG_MST_DIV(_name, _reg, 0)
static AXG_MST_MCLK_DIV(mst_a_mclk, AUDIO_MCLK_A_CTRL);
static AXG_MST_MCLK_DIV(mst_b_mclk, AUDIO_MCLK_B_CTRL);
@ -127,12 +139,12 @@ static AXG_MST_MCLK_DIV(mst_d_mclk, AUDIO_MCLK_D_CTRL);
static AXG_MST_MCLK_DIV(mst_e_mclk, AUDIO_MCLK_E_CTRL);
static AXG_MST_MCLK_DIV(mst_f_mclk, AUDIO_MCLK_F_CTRL);
static AXG_MST_MCLK_DIV(spdifout_clk, AUDIO_CLK_SPDIFOUT_CTRL);
static AXG_MST_MCLK_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_MCLK_DIV(pdm_dclk, AUDIO_CLK_PDMIN_CTRL0);
static AXG_MST_MCLK_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
static AXG_MST_SYS_DIV(spdifin_clk, AUDIO_CLK_SPDIFIN_CTRL);
static AXG_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
#define AXG_MST_MCLK_GATE(_name, _reg) \
AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
#define AXG_MST_MCLK_GATE(_name, _reg) \
AXG_AUD_GATE(_name, _reg, 31, "axg_"#_name"_div", \
CLK_SET_RATE_PARENT)
static AXG_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);

View File

@ -22,8 +22,13 @@
static DEFINE_SPINLOCK(meson_clk_lock);
static struct clk_regmap axg_fixed_pll = {
static struct clk_regmap axg_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_MPLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_MPLL_CNTL,
.shift = 0,
@ -34,11 +39,6 @@ static struct clk_regmap axg_fixed_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = {
.reg_off = HHI_MPLL_CNTL2,
.shift = 0,
@ -56,15 +56,39 @@ static struct clk_regmap axg_fixed_pll = {
},
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
static struct clk_regmap axg_sys_pll = {
static struct clk_regmap axg_fixed_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll_dco" },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
* CLK_SET_RATE_PARENT is not required
*/
},
};
static struct clk_regmap axg_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 0,
@ -75,11 +99,6 @@ static struct clk_regmap axg_sys_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 16,
.width = 2,
},
.l = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 31,
@ -92,102 +111,59 @@ static struct clk_regmap axg_sys_pll = {
},
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
};
static const struct pll_rate_table axg_gp0_pll_rate_table[] = {
PLL_RATE(240000000, 40, 1, 2),
PLL_RATE(246000000, 41, 1, 2),
PLL_RATE(252000000, 42, 1, 2),
PLL_RATE(258000000, 43, 1, 2),
PLL_RATE(264000000, 44, 1, 2),
PLL_RATE(270000000, 45, 1, 2),
PLL_RATE(276000000, 46, 1, 2),
PLL_RATE(282000000, 47, 1, 2),
PLL_RATE(288000000, 48, 1, 2),
PLL_RATE(294000000, 49, 1, 2),
PLL_RATE(300000000, 50, 1, 2),
PLL_RATE(306000000, 51, 1, 2),
PLL_RATE(312000000, 52, 1, 2),
PLL_RATE(318000000, 53, 1, 2),
PLL_RATE(324000000, 54, 1, 2),
PLL_RATE(330000000, 55, 1, 2),
PLL_RATE(336000000, 56, 1, 2),
PLL_RATE(342000000, 57, 1, 2),
PLL_RATE(348000000, 58, 1, 2),
PLL_RATE(354000000, 59, 1, 2),
PLL_RATE(360000000, 60, 1, 2),
PLL_RATE(366000000, 61, 1, 2),
PLL_RATE(372000000, 62, 1, 2),
PLL_RATE(378000000, 63, 1, 2),
PLL_RATE(384000000, 64, 1, 2),
PLL_RATE(390000000, 65, 1, 3),
PLL_RATE(396000000, 66, 1, 3),
PLL_RATE(402000000, 67, 1, 3),
PLL_RATE(408000000, 68, 1, 3),
PLL_RATE(480000000, 40, 1, 1),
PLL_RATE(492000000, 41, 1, 1),
PLL_RATE(504000000, 42, 1, 1),
PLL_RATE(516000000, 43, 1, 1),
PLL_RATE(528000000, 44, 1, 1),
PLL_RATE(540000000, 45, 1, 1),
PLL_RATE(552000000, 46, 1, 1),
PLL_RATE(564000000, 47, 1, 1),
PLL_RATE(576000000, 48, 1, 1),
PLL_RATE(588000000, 49, 1, 1),
PLL_RATE(600000000, 50, 1, 1),
PLL_RATE(612000000, 51, 1, 1),
PLL_RATE(624000000, 52, 1, 1),
PLL_RATE(636000000, 53, 1, 1),
PLL_RATE(648000000, 54, 1, 1),
PLL_RATE(660000000, 55, 1, 1),
PLL_RATE(672000000, 56, 1, 1),
PLL_RATE(684000000, 57, 1, 1),
PLL_RATE(696000000, 58, 1, 1),
PLL_RATE(708000000, 59, 1, 1),
PLL_RATE(720000000, 60, 1, 1),
PLL_RATE(732000000, 61, 1, 1),
PLL_RATE(744000000, 62, 1, 1),
PLL_RATE(756000000, 63, 1, 1),
PLL_RATE(768000000, 64, 1, 1),
PLL_RATE(780000000, 65, 1, 1),
PLL_RATE(792000000, 66, 1, 1),
PLL_RATE(804000000, 67, 1, 1),
PLL_RATE(816000000, 68, 1, 1),
PLL_RATE(960000000, 40, 1, 0),
PLL_RATE(984000000, 41, 1, 0),
PLL_RATE(1008000000, 42, 1, 0),
PLL_RATE(1032000000, 43, 1, 0),
PLL_RATE(1056000000, 44, 1, 0),
PLL_RATE(1080000000, 45, 1, 0),
PLL_RATE(1104000000, 46, 1, 0),
PLL_RATE(1128000000, 47, 1, 0),
PLL_RATE(1152000000, 48, 1, 0),
PLL_RATE(1176000000, 49, 1, 0),
PLL_RATE(1200000000, 50, 1, 0),
PLL_RATE(1224000000, 51, 1, 0),
PLL_RATE(1248000000, 52, 1, 0),
PLL_RATE(1272000000, 53, 1, 0),
PLL_RATE(1296000000, 54, 1, 0),
PLL_RATE(1320000000, 55, 1, 0),
PLL_RATE(1344000000, 56, 1, 0),
PLL_RATE(1368000000, 57, 1, 0),
PLL_RATE(1392000000, 58, 1, 0),
PLL_RATE(1416000000, 59, 1, 0),
PLL_RATE(1440000000, 60, 1, 0),
PLL_RATE(1464000000, 61, 1, 0),
PLL_RATE(1488000000, 62, 1, 0),
PLL_RATE(1512000000, 63, 1, 0),
PLL_RATE(1536000000, 64, 1, 0),
PLL_RATE(1560000000, 65, 1, 0),
PLL_RATE(1584000000, 66, 1, 0),
PLL_RATE(1608000000, 67, 1, 0),
PLL_RATE(1632000000, 68, 1, 0),
static struct clk_regmap axg_sys_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_SYS_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "sys_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const struct pll_params_table axg_gp0_pll_params_table[] = {
PLL_PARAMS(40, 1),
PLL_PARAMS(41, 1),
PLL_PARAMS(42, 1),
PLL_PARAMS(43, 1),
PLL_PARAMS(44, 1),
PLL_PARAMS(45, 1),
PLL_PARAMS(46, 1),
PLL_PARAMS(47, 1),
PLL_PARAMS(48, 1),
PLL_PARAMS(49, 1),
PLL_PARAMS(50, 1),
PLL_PARAMS(51, 1),
PLL_PARAMS(52, 1),
PLL_PARAMS(53, 1),
PLL_PARAMS(54, 1),
PLL_PARAMS(55, 1),
PLL_PARAMS(56, 1),
PLL_PARAMS(57, 1),
PLL_PARAMS(58, 1),
PLL_PARAMS(59, 1),
PLL_PARAMS(60, 1),
PLL_PARAMS(61, 1),
PLL_PARAMS(62, 1),
PLL_PARAMS(63, 1),
PLL_PARAMS(64, 1),
PLL_PARAMS(65, 1),
PLL_PARAMS(66, 1),
PLL_PARAMS(67, 1),
PLL_PARAMS(68, 1),
{ /* sentinel */ },
};
@ -197,11 +173,15 @@ static const struct reg_sequence axg_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
{ .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
};
static struct clk_regmap axg_gp0_pll = {
static struct clk_regmap axg_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 0,
@ -212,11 +192,6 @@ static struct clk_regmap axg_gp0_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = {
.reg_off = HHI_GP0_PLL_CNTL1,
.shift = 0,
@ -232,29 +207,49 @@ static struct clk_regmap axg_gp0_pll = {
.shift = 29,
.width = 1,
},
.table = axg_gp0_pll_rate_table,
.table = axg_gp0_pll_params_table,
.init_regs = axg_gp0_init_regs,
.init_count = ARRAY_SIZE(axg_gp0_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
static struct clk_regmap axg_gp0_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gp0_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const struct reg_sequence axg_hifi_init_regs[] = {
{ .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 },
{ .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be },
{ .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 },
{ .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 },
{ .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 },
};
static struct clk_regmap axg_hifi_pll = {
static struct clk_regmap axg_hifi_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_HIFI_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_HIFI_PLL_CNTL,
.shift = 0,
@ -265,11 +260,6 @@ static struct clk_regmap axg_hifi_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_HIFI_PLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = {
.reg_off = HHI_HIFI_PLL_CNTL5,
.shift = 0,
@ -285,19 +275,35 @@ static struct clk_regmap axg_hifi_pll = {
.shift = 29,
.width = 1,
},
.table = axg_gp0_pll_rate_table,
.table = axg_gp0_pll_params_table,
.init_regs = axg_hifi_init_regs,
.init_count = ARRAY_SIZE(axg_hifi_init_regs),
.flags = CLK_MESON_PLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
static struct clk_regmap axg_hifi_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HIFI_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "hifi_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor axg_fclk_div2_div = {
.mult = 1,
.div = 2,
@ -625,29 +631,31 @@ static struct clk_regmap axg_mpll3 = {
},
};
static const struct pll_rate_table axg_pcie_pll_rate_table[] = {
static const struct pll_params_table axg_pcie_pll_params_table[] = {
{
.rate = 100000000,
.m = 200,
.n = 3,
.od = 1,
.od2 = 3,
.m = 200,
.n = 3,
},
{ /* sentinel */ },
};
static const struct reg_sequence axg_pcie_init_regs[] = {
{ .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
{ .reg = HHI_PCIE_PLL_CNTL1, .def = 0x0084a2aa },
{ .reg = HHI_PCIE_PLL_CNTL2, .def = 0xb75020be },
{ .reg = HHI_PCIE_PLL_CNTL3, .def = 0x0a47488e },
{ .reg = HHI_PCIE_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_PCIE_PLL_CNTL5, .def = 0x00078000 },
{ .reg = HHI_PCIE_PLL_CNTL6, .def = 0x002323c6 },
{ .reg = HHI_PCIE_PLL_CNTL, .def = 0x400106c8 },
};
static struct clk_regmap axg_pcie_pll = {
static struct clk_regmap axg_pcie_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_PCIE_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_PCIE_PLL_CNTL,
.shift = 0,
@ -658,16 +666,6 @@ static struct clk_regmap axg_pcie_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_PCIE_PLL_CNTL,
.shift = 16,
.width = 2,
},
.od2 = {
.reg_off = HHI_PCIE_PLL_CNTL6,
.shift = 6,
.width = 2,
},
.frac = {
.reg_off = HHI_PCIE_PLL_CNTL1,
.shift = 0,
@ -683,29 +681,63 @@ static struct clk_regmap axg_pcie_pll = {
.shift = 29,
.width = 1,
},
.table = axg_pcie_pll_rate_table,
.table = axg_pcie_pll_params_table,
.init_regs = axg_pcie_init_regs,
.init_count = ARRAY_SIZE(axg_pcie_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "pcie_pll",
.name = "pcie_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
},
};
static struct clk_regmap axg_pcie_pll_od = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_PCIE_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_od",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap axg_pcie_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_PCIE_PLL_CNTL6,
.shift = 6,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "pcie_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_od" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap axg_pcie_mux = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_PCIE_PLL_CNTL6,
.mask = 0x1,
.shift = 2,
/* skip the parent mpll3, reserved for debug */
.table = (u32[]){ 1 },
},
.hw.init = &(struct clk_init_data){
.name = "pcie_mux",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "mpll3", "pcie_pll" },
.num_parents = 2,
.parent_names = (const char *[]){ "pcie_pll" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
@ -1107,6 +1139,12 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw,
[CLKID_GEN_CLK] = &axg_gen_clk.hw,
[CLKID_SYS_PLL_DCO] = &axg_sys_pll_dco.hw,
[CLKID_FIXED_PLL_DCO] = &axg_fixed_pll_dco.hw,
[CLKID_GP0_PLL_DCO] = &axg_gp0_pll_dco.hw,
[CLKID_HIFI_PLL_DCO] = &axg_hifi_pll_dco.hw,
[CLKID_PCIE_PLL_DCO] = &axg_pcie_pll_dco.hw,
[CLKID_PCIE_PLL_OD] = &axg_pcie_pll_od.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
@ -1185,6 +1223,8 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_fclk_div4,
&axg_fclk_div5,
&axg_fclk_div7,
&axg_pcie_pll_dco,
&axg_pcie_pll_od,
&axg_pcie_pll,
&axg_pcie_mux,
&axg_pcie_ref,
@ -1194,6 +1234,12 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&axg_gen_clk_sel,
&axg_gen_clk_div,
&axg_gen_clk,
&axg_fixed_pll_dco,
&axg_sys_pll_dco,
&axg_gp0_pll_dco,
&axg_hifi_pll_dco,
&axg_pcie_pll_dco,
&axg_pcie_pll_od,
};
static const struct of_device_id clkc_match_table[] = {

View File

@ -133,8 +133,14 @@
#define CLKID_PCIE_REF 78
#define CLKID_GEN_CLK_SEL 82
#define CLKID_GEN_CLK_DIV 83
#define CLKID_SYS_PLL_DCO 85
#define CLKID_FIXED_PLL_DCO 86
#define CLKID_GP0_PLL_DCO 87
#define CLKID_HIFI_PLL_DCO 88
#define CLKID_PCIE_PLL_DCO 89
#define CLKID_PCIE_PLL_OD 90
#define NR_CLKS 85
#define NR_CLKS 91
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/axg-clkc.h>

View File

@ -11,15 +11,19 @@
* In the most basic form, a Meson PLL is composed as follows:
*
* PLL
* +------------------------------+
* | |
* in -----[ /N ]---[ *M ]---[ >>OD ]----->> out
* | ^ ^ |
* +------------------------------+
* | |
* FREF VCO
* +--------------------------------+
* | |
* | +--+ |
* in >>-----[ /N ]--->| | +-----+ |
* | | |------| DCO |---->> out
* | +--------->| | +--v--+ |
* | | +--+ | |
* | | | |
* | +--[ *(M + (F/Fmax) ]<--+ |
* | |
* +--------------------------------+
*
* out = in * (m + frac / frac_max) / (n << sum(ods))
* out = in * (m + frac / frac_max) / n
*/
#include <linux/clk-provider.h>
@ -41,12 +45,11 @@ meson_clk_pll_data(struct clk_regmap *clk)
}
static unsigned long __pll_params_to_rate(unsigned long parent_rate,
const struct pll_rate_table *pllt,
const struct pll_params_table *pllt,
u16 frac,
struct meson_clk_pll_data *pll)
{
u64 rate = (u64)parent_rate * pllt->m;
unsigned int od = pllt->od + pllt->od2 + pllt->od3;
if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
u64 frac_rate = (u64)parent_rate * frac;
@ -55,7 +58,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
(1 << pll->frac.width));
}
return DIV_ROUND_UP_ULL(rate, pllt->n << od);
return DIV_ROUND_UP_ULL(rate, pllt->n);
}
static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
@ -63,20 +66,11 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
struct pll_rate_table pllt;
struct pll_params_table pllt;
u16 frac;
pllt.n = meson_parm_read(clk->map, &pll->n);
pllt.m = meson_parm_read(clk->map, &pll->m);
pllt.od = meson_parm_read(clk->map, &pll->od);
pllt.od2 = MESON_PARM_APPLICABLE(&pll->od2) ?
meson_parm_read(clk->map, &pll->od2) :
0;
pllt.od3 = MESON_PARM_APPLICABLE(&pll->od3) ?
meson_parm_read(clk->map, &pll->od3) :
0;
frac = MESON_PARM_APPLICABLE(&pll->frac) ?
meson_parm_read(clk->map, &pll->frac) :
@ -87,14 +81,12 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
static u16 __pll_params_with_frac(unsigned long rate,
unsigned long parent_rate,
const struct pll_rate_table *pllt,
const struct pll_params_table *pllt,
struct meson_clk_pll_data *pll)
{
u16 frac_max = (1 << pll->frac.width);
u64 val = (u64)rate * pllt->n;
val <<= pllt->od + pllt->od2 + pllt->od3;
if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
else
@ -105,29 +97,50 @@ static u16 __pll_params_with_frac(unsigned long rate,
return min((u16)val, (u16)(frac_max - 1));
}
static const struct pll_rate_table *
static bool meson_clk_pll_is_better(unsigned long rate,
unsigned long best,
unsigned long now,
struct meson_clk_pll_data *pll)
{
if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
MESON_PARM_APPLICABLE(&pll->frac)) {
/* Round down */
if (now < rate && best < now)
return true;
} else {
/* Round Closest */
if (abs(now - rate) < abs(best - rate))
return true;
}
return false;
}
static const struct pll_params_table *
meson_clk_get_pll_settings(unsigned long rate,
unsigned long parent_rate,
struct meson_clk_pll_data *pll)
{
const struct pll_rate_table *table = pll->table;
unsigned int i = 0;
const struct pll_params_table *table = pll->table;
unsigned long best = 0, now = 0;
unsigned int i, best_i = 0;
if (!table)
return NULL;
/* Find the first table element exceeding rate */
while (table[i].rate && table[i].rate <= rate)
i++;
for (i = 0; table[i].n; i++) {
now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
if (i != 0) {
if (MESON_PARM_APPLICABLE(&pll->frac) ||
!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
(abs(rate - table[i - 1].rate) <
abs(rate - table[i].rate)))
i--;
/* If we get an exact match, don't bother any further */
if (now == rate) {
return &table[i];
} else if (meson_clk_pll_is_better(rate, best, now, pll)) {
best = now;
best_i = i;
}
}
return (struct pll_rate_table *)&table[i];
return (struct pll_params_table *)&table[best_i];
}
static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@ -135,16 +148,18 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
const struct pll_rate_table *pllt =
meson_clk_get_pll_settings(rate, pll);
const struct pll_params_table *pllt =
meson_clk_get_pll_settings(rate, *parent_rate, pll);
unsigned long round;
u16 frac;
if (!pllt)
return meson_clk_pll_recalc_rate(hw, *parent_rate);
if (!MESON_PARM_APPLICABLE(&pll->frac)
|| rate == pllt->rate)
return pllt->rate;
round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
return round;
/*
* The rate provided by the setting is not an exact match, let's
@ -185,12 +200,45 @@ static void meson_clk_pll_init(struct clk_hw *hw)
}
}
static int meson_clk_pll_enable(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Make sure the pll is in reset */
meson_parm_write(clk->map, &pll->rst, 1);
/* Enable the pll */
meson_parm_write(clk->map, &pll->en, 1);
/* Take the pll out reset */
meson_parm_write(clk->map, &pll->rst, 0);
if (meson_clk_pll_wait_lock(hw))
return -EIO;
return 0;
}
static void meson_clk_pll_disable(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
/* Put the pll is in reset */
meson_parm_write(clk->map, &pll->rst, 1);
/* Disable the pll */
meson_parm_write(clk->map, &pll->en, 0);
}
static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
const struct pll_rate_table *pllt;
const struct pll_params_table *pllt;
unsigned int enabled;
unsigned long old_rate;
u16 frac = 0;
@ -199,32 +247,28 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
old_rate = rate;
pllt = meson_clk_get_pll_settings(rate, pll);
pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
if (!pllt)
return -EINVAL;
/* Put the pll in reset to write the params */
meson_parm_write(clk->map, &pll->rst, 1);
enabled = meson_parm_read(clk->map, &pll->en);
if (enabled)
meson_clk_pll_disable(hw);
meson_parm_write(clk->map, &pll->n, pllt->n);
meson_parm_write(clk->map, &pll->m, pllt->m);
meson_parm_write(clk->map, &pll->od, pllt->od);
if (MESON_PARM_APPLICABLE(&pll->od2))
meson_parm_write(clk->map, &pll->od2, pllt->od2);
if (MESON_PARM_APPLICABLE(&pll->od3))
meson_parm_write(clk->map, &pll->od3, pllt->od3);
if (MESON_PARM_APPLICABLE(&pll->frac)) {
frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
meson_parm_write(clk->map, &pll->frac, frac);
}
/* make sure the reset is cleared at this point */
meson_parm_write(clk->map, &pll->rst, 0);
/* If the pll is stopped, bail out now */
if (!enabled)
return 0;
if (meson_clk_pll_wait_lock(hw)) {
if (meson_clk_pll_enable(hw)) {
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
__func__, old_rate);
/*
@ -244,6 +288,8 @@ const struct clk_ops meson_clk_pll_ops = {
.recalc_rate = meson_clk_pll_recalc_rate,
.round_rate = meson_clk_pll_round_rate,
.set_rate = meson_clk_pll_set_rate,
.enable = meson_clk_pll_enable,
.disable = meson_clk_pll_disable
};
const struct clk_ops meson_clk_pll_ro_ops = {

View File

@ -43,37 +43,29 @@ static inline void meson_parm_write(struct regmap *map, struct parm *p,
}
struct pll_rate_table {
unsigned long rate;
struct pll_params_table {
u16 m;
u16 n;
u16 od;
u16 od2;
u16 od3;
};
#define PLL_RATE(_r, _m, _n, _od) \
#define PLL_PARAMS(_m, _n) \
{ \
.rate = (_r), \
.m = (_m), \
.n = (_n), \
.od = (_od), \
}
#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
struct meson_clk_pll_data {
struct parm en;
struct parm m;
struct parm n;
struct parm frac;
struct parm od;
struct parm od2;
struct parm od3;
struct parm l;
struct parm rst;
const struct reg_sequence *init_regs;
unsigned int init_count;
const struct pll_rate_table *table;
const struct pll_params_table *table;
u8 flags;
};

View File

@ -18,165 +18,77 @@
static DEFINE_SPINLOCK(meson_clk_lock);
static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
PLL_RATE(96000000, 32, 1, 3),
PLL_RATE(99000000, 33, 1, 3),
PLL_RATE(102000000, 34, 1, 3),
PLL_RATE(105000000, 35, 1, 3),
PLL_RATE(108000000, 36, 1, 3),
PLL_RATE(111000000, 37, 1, 3),
PLL_RATE(114000000, 38, 1, 3),
PLL_RATE(117000000, 39, 1, 3),
PLL_RATE(120000000, 40, 1, 3),
PLL_RATE(123000000, 41, 1, 3),
PLL_RATE(126000000, 42, 1, 3),
PLL_RATE(129000000, 43, 1, 3),
PLL_RATE(132000000, 44, 1, 3),
PLL_RATE(135000000, 45, 1, 3),
PLL_RATE(138000000, 46, 1, 3),
PLL_RATE(141000000, 47, 1, 3),
PLL_RATE(144000000, 48, 1, 3),
PLL_RATE(147000000, 49, 1, 3),
PLL_RATE(150000000, 50, 1, 3),
PLL_RATE(153000000, 51, 1, 3),
PLL_RATE(156000000, 52, 1, 3),
PLL_RATE(159000000, 53, 1, 3),
PLL_RATE(162000000, 54, 1, 3),
PLL_RATE(165000000, 55, 1, 3),
PLL_RATE(168000000, 56, 1, 3),
PLL_RATE(171000000, 57, 1, 3),
PLL_RATE(174000000, 58, 1, 3),
PLL_RATE(177000000, 59, 1, 3),
PLL_RATE(180000000, 60, 1, 3),
PLL_RATE(183000000, 61, 1, 3),
PLL_RATE(186000000, 62, 1, 3),
PLL_RATE(192000000, 32, 1, 2),
PLL_RATE(198000000, 33, 1, 2),
PLL_RATE(204000000, 34, 1, 2),
PLL_RATE(210000000, 35, 1, 2),
PLL_RATE(216000000, 36, 1, 2),
PLL_RATE(222000000, 37, 1, 2),
PLL_RATE(228000000, 38, 1, 2),
PLL_RATE(234000000, 39, 1, 2),
PLL_RATE(240000000, 40, 1, 2),
PLL_RATE(246000000, 41, 1, 2),
PLL_RATE(252000000, 42, 1, 2),
PLL_RATE(258000000, 43, 1, 2),
PLL_RATE(264000000, 44, 1, 2),
PLL_RATE(270000000, 45, 1, 2),
PLL_RATE(276000000, 46, 1, 2),
PLL_RATE(282000000, 47, 1, 2),
PLL_RATE(288000000, 48, 1, 2),
PLL_RATE(294000000, 49, 1, 2),
PLL_RATE(300000000, 50, 1, 2),
PLL_RATE(306000000, 51, 1, 2),
PLL_RATE(312000000, 52, 1, 2),
PLL_RATE(318000000, 53, 1, 2),
PLL_RATE(324000000, 54, 1, 2),
PLL_RATE(330000000, 55, 1, 2),
PLL_RATE(336000000, 56, 1, 2),
PLL_RATE(342000000, 57, 1, 2),
PLL_RATE(348000000, 58, 1, 2),
PLL_RATE(354000000, 59, 1, 2),
PLL_RATE(360000000, 60, 1, 2),
PLL_RATE(366000000, 61, 1, 2),
PLL_RATE(372000000, 62, 1, 2),
PLL_RATE(384000000, 32, 1, 1),
PLL_RATE(396000000, 33, 1, 1),
PLL_RATE(408000000, 34, 1, 1),
PLL_RATE(420000000, 35, 1, 1),
PLL_RATE(432000000, 36, 1, 1),
PLL_RATE(444000000, 37, 1, 1),
PLL_RATE(456000000, 38, 1, 1),
PLL_RATE(468000000, 39, 1, 1),
PLL_RATE(480000000, 40, 1, 1),
PLL_RATE(492000000, 41, 1, 1),
PLL_RATE(504000000, 42, 1, 1),
PLL_RATE(516000000, 43, 1, 1),
PLL_RATE(528000000, 44, 1, 1),
PLL_RATE(540000000, 45, 1, 1),
PLL_RATE(552000000, 46, 1, 1),
PLL_RATE(564000000, 47, 1, 1),
PLL_RATE(576000000, 48, 1, 1),
PLL_RATE(588000000, 49, 1, 1),
PLL_RATE(600000000, 50, 1, 1),
PLL_RATE(612000000, 51, 1, 1),
PLL_RATE(624000000, 52, 1, 1),
PLL_RATE(636000000, 53, 1, 1),
PLL_RATE(648000000, 54, 1, 1),
PLL_RATE(660000000, 55, 1, 1),
PLL_RATE(672000000, 56, 1, 1),
PLL_RATE(684000000, 57, 1, 1),
PLL_RATE(696000000, 58, 1, 1),
PLL_RATE(708000000, 59, 1, 1),
PLL_RATE(720000000, 60, 1, 1),
PLL_RATE(732000000, 61, 1, 1),
PLL_RATE(744000000, 62, 1, 1),
PLL_RATE(768000000, 32, 1, 0),
PLL_RATE(792000000, 33, 1, 0),
PLL_RATE(816000000, 34, 1, 0),
PLL_RATE(840000000, 35, 1, 0),
PLL_RATE(864000000, 36, 1, 0),
PLL_RATE(888000000, 37, 1, 0),
PLL_RATE(912000000, 38, 1, 0),
PLL_RATE(936000000, 39, 1, 0),
PLL_RATE(960000000, 40, 1, 0),
PLL_RATE(984000000, 41, 1, 0),
PLL_RATE(1008000000, 42, 1, 0),
PLL_RATE(1032000000, 43, 1, 0),
PLL_RATE(1056000000, 44, 1, 0),
PLL_RATE(1080000000, 45, 1, 0),
PLL_RATE(1104000000, 46, 1, 0),
PLL_RATE(1128000000, 47, 1, 0),
PLL_RATE(1152000000, 48, 1, 0),
PLL_RATE(1176000000, 49, 1, 0),
PLL_RATE(1200000000, 50, 1, 0),
PLL_RATE(1224000000, 51, 1, 0),
PLL_RATE(1248000000, 52, 1, 0),
PLL_RATE(1272000000, 53, 1, 0),
PLL_RATE(1296000000, 54, 1, 0),
PLL_RATE(1320000000, 55, 1, 0),
PLL_RATE(1344000000, 56, 1, 0),
PLL_RATE(1368000000, 57, 1, 0),
PLL_RATE(1392000000, 58, 1, 0),
PLL_RATE(1416000000, 59, 1, 0),
PLL_RATE(1440000000, 60, 1, 0),
PLL_RATE(1464000000, 61, 1, 0),
PLL_RATE(1488000000, 62, 1, 0),
static const struct pll_params_table gxbb_gp0_pll_params_table[] = {
PLL_PARAMS(32, 1),
PLL_PARAMS(33, 1),
PLL_PARAMS(34, 1),
PLL_PARAMS(35, 1),
PLL_PARAMS(36, 1),
PLL_PARAMS(37, 1),
PLL_PARAMS(38, 1),
PLL_PARAMS(39, 1),
PLL_PARAMS(40, 1),
PLL_PARAMS(41, 1),
PLL_PARAMS(42, 1),
PLL_PARAMS(43, 1),
PLL_PARAMS(44, 1),
PLL_PARAMS(45, 1),
PLL_PARAMS(46, 1),
PLL_PARAMS(47, 1),
PLL_PARAMS(48, 1),
PLL_PARAMS(49, 1),
PLL_PARAMS(50, 1),
PLL_PARAMS(51, 1),
PLL_PARAMS(52, 1),
PLL_PARAMS(53, 1),
PLL_PARAMS(54, 1),
PLL_PARAMS(55, 1),
PLL_PARAMS(56, 1),
PLL_PARAMS(57, 1),
PLL_PARAMS(58, 1),
PLL_PARAMS(59, 1),
PLL_PARAMS(60, 1),
PLL_PARAMS(61, 1),
PLL_PARAMS(62, 1),
{ /* sentinel */ },
};
static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
PLL_RATE(504000000, 42, 1, 1),
PLL_RATE(516000000, 43, 1, 1),
PLL_RATE(528000000, 44, 1, 1),
PLL_RATE(540000000, 45, 1, 1),
PLL_RATE(552000000, 46, 1, 1),
PLL_RATE(564000000, 47, 1, 1),
PLL_RATE(576000000, 48, 1, 1),
PLL_RATE(588000000, 49, 1, 1),
PLL_RATE(600000000, 50, 1, 1),
PLL_RATE(612000000, 51, 1, 1),
PLL_RATE(624000000, 52, 1, 1),
PLL_RATE(636000000, 53, 1, 1),
PLL_RATE(648000000, 54, 1, 1),
PLL_RATE(660000000, 55, 1, 1),
PLL_RATE(672000000, 56, 1, 1),
PLL_RATE(684000000, 57, 1, 1),
PLL_RATE(696000000, 58, 1, 1),
PLL_RATE(708000000, 59, 1, 1),
PLL_RATE(720000000, 60, 1, 1),
PLL_RATE(732000000, 61, 1, 1),
PLL_RATE(744000000, 62, 1, 1),
PLL_RATE(756000000, 63, 1, 1),
PLL_RATE(768000000, 64, 1, 1),
PLL_RATE(780000000, 65, 1, 1),
PLL_RATE(792000000, 66, 1, 1),
static const struct pll_params_table gxl_gp0_pll_params_table[] = {
PLL_PARAMS(42, 1),
PLL_PARAMS(43, 1),
PLL_PARAMS(44, 1),
PLL_PARAMS(45, 1),
PLL_PARAMS(46, 1),
PLL_PARAMS(47, 1),
PLL_PARAMS(48, 1),
PLL_PARAMS(49, 1),
PLL_PARAMS(50, 1),
PLL_PARAMS(51, 1),
PLL_PARAMS(52, 1),
PLL_PARAMS(53, 1),
PLL_PARAMS(54, 1),
PLL_PARAMS(55, 1),
PLL_PARAMS(56, 1),
PLL_PARAMS(57, 1),
PLL_PARAMS(58, 1),
PLL_PARAMS(59, 1),
PLL_PARAMS(60, 1),
PLL_PARAMS(61, 1),
PLL_PARAMS(62, 1),
PLL_PARAMS(63, 1),
PLL_PARAMS(64, 1),
PLL_PARAMS(65, 1),
PLL_PARAMS(66, 1),
{ /* sentinel */ },
};
static struct clk_regmap gxbb_fixed_pll = {
static struct clk_regmap gxbb_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_MPLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_MPLL_CNTL,
.shift = 0,
@ -187,11 +99,6 @@ static struct clk_regmap gxbb_fixed_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = {
.reg_off = HHI_MPLL_CNTL2,
.shift = 0,
@ -209,11 +116,29 @@ static struct clk_regmap gxbb_fixed_pll = {
},
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
};
static struct clk_regmap gxbb_fixed_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_MPLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll_dco" },
.num_parents = 1,
/*
* This clock won't ever change at runtime so
* CLK_SET_RATE_PARENT is not required
*/
},
};
@ -228,8 +153,13 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
},
};
static struct clk_regmap gxbb_hdmi_pll = {
static struct clk_regmap gxbb_hdmi_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 0,
@ -245,21 +175,6 @@ static struct clk_regmap gxbb_hdmi_pll = {
.shift = 0,
.width = 12,
},
.od = {
.reg_off = HHI_HDMI_PLL_CNTL2,
.shift = 16,
.width = 2,
},
.od2 = {
.reg_off = HHI_HDMI_PLL_CNTL2,
.shift = 22,
.width = 2,
},
.od3 = {
.reg_off = HHI_HDMI_PLL_CNTL2,
.shift = 18,
.width = 2,
},
.l = {
.reg_off = HHI_HDMI_PLL_CNTL,
.shift = 31,
@ -272,106 +187,163 @@ static struct clk_regmap gxbb_hdmi_pll = {
},
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_pre_mult" },
.num_parents = 1,
/*
* Display directly handle hdmi pll registers ATM, we need
* NOCACHE to keep our view of the clock as accurate as possible
*/
.flags = CLK_GET_RATE_NOCACHE,
},
};
static struct clk_regmap gxbb_hdmi_pll_od = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL2,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_dco" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxbb_hdmi_pll_od2 = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL2,
.shift = 22,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od2",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_od" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxbb_hdmi_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL2,
.shift = 18,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_od2" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxl_hdmi_pll_od = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL + 8,
.shift = 21,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_dco" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxl_hdmi_pll_od2 = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL + 8,
.shift = 23,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od2",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_od" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxl_hdmi_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_HDMI_PLL_CNTL + 8,
.shift = 19,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "hdmi_pll_od2" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap gxbb_sys_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_HDMI_PLL_CNTL,
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 0,
.width = 9,
},
.n = {
.reg_off = HHI_HDMI_PLL_CNTL,
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 9,
.width = 5,
},
.frac = {
/*
* On gxl, there is a register shift due to
* HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
* so we compute the register offset based on the PLL
* base to get it right
*/
.reg_off = HHI_HDMI_PLL_CNTL + 4,
.shift = 0,
.width = 12,
},
.od = {
.reg_off = HHI_HDMI_PLL_CNTL + 8,
.shift = 21,
.width = 2,
},
.od2 = {
.reg_off = HHI_HDMI_PLL_CNTL + 8,
.shift = 23,
.width = 2,
},
.od3 = {
.reg_off = HHI_HDMI_PLL_CNTL + 8,
.shift = 19,
.width = 2,
},
.l = {
.reg_off = HHI_HDMI_PLL_CNTL,
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = HHI_HDMI_PLL_CNTL,
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 29,
.width = 1,
},
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
};
static struct clk_regmap gxbb_sys_pll = {
.data = &(struct meson_clk_pll_data){
.m = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 0,
.width = 9,
},
.n = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 10,
.width = 2,
},
.l = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = HHI_SYS_PLL_CNTL,
.shift = 29,
.width = 1,
},
.data = &(struct clk_regmap_div_data){
.offset = HHI_SYS_PLL_CNTL,
.shift = 10,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ "xtal" },
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "sys_pll_dco" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
.flags = CLK_SET_RATE_PARENT,
},
};
@ -379,11 +351,15 @@ static const struct reg_sequence gxbb_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL2, .def = 0x69c80000 },
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a5590c4 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0x0000500d },
{ .reg = HHI_GP0_PLL_CNTL, .def = 0x4a000228 },
};
static struct clk_regmap gxbb_gp0_pll = {
static struct clk_regmap gxbb_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 0,
@ -394,11 +370,6 @@ static struct clk_regmap gxbb_gp0_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
},
.l = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 31,
@ -409,16 +380,15 @@ static struct clk_regmap gxbb_gp0_pll = {
.shift = 29,
.width = 1,
},
.table = gxbb_gp0_pll_rate_table,
.table = gxbb_gp0_pll_params_table,
.init_regs = gxbb_gp0_init_regs,
.init_count = ARRAY_SIZE(gxbb_gp0_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
};
@ -428,11 +398,15 @@ static const struct reg_sequence gxl_gp0_init_regs[] = {
{ .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 },
{ .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d },
{ .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 },
{ .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 },
};
static struct clk_regmap gxl_gp0_pll = {
static struct clk_regmap gxl_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 30,
.width = 1,
},
.m = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 0,
@ -443,11 +417,6 @@ static struct clk_regmap gxl_gp0_pll = {
.shift = 9,
.width = 5,
},
.od = {
.reg_off = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
},
.frac = {
.reg_off = HHI_GP0_PLL_CNTL1,
.shift = 0,
@ -463,16 +432,31 @@ static struct clk_regmap gxl_gp0_pll = {
.shift = 29,
.width = 1,
},
.table = gxl_gp0_pll_rate_table,
.table = gxl_gp0_pll_params_table,
.init_regs = gxl_gp0_init_regs,
.init_count = ARRAY_SIZE(gxl_gp0_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ "xtal" },
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
},
};
static struct clk_regmap gxbb_gp0_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_GP0_PLL_CNTL,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gp0_pll_dco" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
@ -1933,6 +1917,12 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
[CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
[CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
[CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
[CLKID_HDMI_PLL_OD] = &gxbb_hdmi_pll_od.hw,
[CLKID_HDMI_PLL_OD2] = &gxbb_hdmi_pll_od2.hw,
[CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
[CLKID_GP0_PLL_DCO] = &gxbb_gp0_pll_dco.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
@ -1948,7 +1938,7 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_FCLK_DIV4] = &gxbb_fclk_div4.hw,
[CLKID_FCLK_DIV5] = &gxbb_fclk_div5.hw,
[CLKID_FCLK_DIV7] = &gxbb_fclk_div7.hw,
[CLKID_GP0_PLL] = &gxl_gp0_pll.hw,
[CLKID_GP0_PLL] = &gxbb_gp0_pll.hw,
[CLKID_MPEG_SEL] = &gxbb_mpeg_clk_sel.hw,
[CLKID_MPEG_DIV] = &gxbb_mpeg_clk_div.hw,
[CLKID_CLK81] = &gxbb_clk81.hw,
@ -2098,19 +2088,29 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_GEN_CLK_SEL] = &gxbb_gen_clk_sel.hw,
[CLKID_GEN_CLK_DIV] = &gxbb_gen_clk_div.hw,
[CLKID_GEN_CLK] = &gxbb_gen_clk.hw,
[CLKID_FIXED_PLL_DCO] = &gxbb_fixed_pll_dco.hw,
[CLKID_HDMI_PLL_DCO] = &gxbb_hdmi_pll_dco.hw,
[CLKID_HDMI_PLL_OD] = &gxl_hdmi_pll_od.hw,
[CLKID_HDMI_PLL_OD2] = &gxl_hdmi_pll_od2.hw,
[CLKID_SYS_PLL_DCO] = &gxbb_sys_pll_dco.hw,
[CLKID_GP0_PLL_DCO] = &gxl_gp0_pll_dco.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
};
static struct clk_regmap *const gxbb_clk_regmaps[] = {
&gxbb_gp0_pll,
&gxbb_gp0_pll_dco,
&gxbb_hdmi_pll,
&gxbb_hdmi_pll_od,
&gxbb_hdmi_pll_od2,
};
static struct clk_regmap *const gxl_clk_regmaps[] = {
&gxl_gp0_pll,
&gxl_gp0_pll_dco,
&gxl_hdmi_pll,
&gxl_hdmi_pll_od,
&gxl_hdmi_pll_od2,
};
static struct clk_regmap *const gx_clk_regmaps[] = {
@ -2265,6 +2265,10 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
&gxbb_gen_clk_sel,
&gxbb_gen_clk_div,
&gxbb_gen_clk,
&gxbb_fixed_pll_dco,
&gxbb_hdmi_pll_dco,
&gxbb_sys_pll_dco,
&gxbb_gp0_pll,
};
struct clkc_data {

Some files were not shown because too many files have changed in this diff Show More