We have two changes to the core framework this time around. The first being a

large change that introduces runtime PM support to the clk framework. Now we
 properly call runtime PM operations on the device providing a clk when the clk
 is in use. This helps on SoCs where the clks provided by a device need
 something to be powered on before using the clks, like power domains or
 regulators. It also helps power those things down when clks aren't in use. The
 other core change is a devm API addition for clk providers so we can get rid of
 a bunch of clk driver remove functions that are just doing
 of_clk_del_provider().
 
 Outside of the core, we have the usual addition of clk drivers and smattering
 of non-critical fixes to existing drivers. The biggest diff is support for
 Mediatek MT2712 and MT7622 SoCs, but those patches really just add a bunch
 of data.
 
 By the way, we're trying something new here where we build the tree up with
 topic branches. We plan to work this into our workflow so that we don't step
 on each other's toes, and so the fixes branch can be merged on an as-needed
 basis.
 
 Core:
  - Runtime PM support for clk providers
  - devm API for of_clk_add_hw_provider()
 
 New Drivers:
  - Mediatek MT2712 and MT7622
  - Renesas R-Car V3M SoC
 
 Updates:
  - Runtime PM support for Samsung exynos5433/exynos4412 providers
  - Removal of clkdev aliases on Samsung SoCs
  - Convert clk-gpio to use gpio descriptors
  - Various driver cleanups to match kernel coding style
  - Amlogic Video Processing Unit VPU and VAPB clks
  - Sigma-delta modulation for Allwinner audio PLLs
  - Allwinner A83t Display clks
  - Support for the second display unit clock on Renesas RZ/G1E
  - Suspend/resume support for Renesas R-Car Gen3 CPG/MSSR
  - New clock ids for Rockchip rk3188 and rk3368 SoCs
  - Various 'const' markings on clk_ops structures
  - RPM clk support on Qualcomm MSM8996/MSM8660 SoCs
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQIcBAABCAAGBQJaD3qRAAoJEK0CiJfG5JUlOLgQAKWekgG/IYgcPzPWDYfg8Hwr
 sVVUK7+q7TVfbHsbYVikJuUaxutKZ0onnrYmOalTTyyxqL2E1/rYScnxdYHfcwX8
 cyfHebRHsbh/Xg45ktwjzBkO49nwuppkpXd/V80GSBUZ+lsIVl5DUrrFAZdRUEdr
 CEsAsF9tEWIl+0gqXYNuiKBV7QAYv5BUPrbJQf0PwL6jX0OAhLv+ukfN8BdmYsOb
 rdoqhdgmyHkTuIMqsC/H2yP59aAKBse7wxIYebDiTdbPWfTkC9q927fTs4A02F6L
 sHfLvCpfuB4rOjXy6LSd1gMGWIcjotZai+idHBqtNLLVz6exF1QpUCp+pZjEULbA
 /Sx9lk8A3cYoa8pTu1NrrZbZX17iHkFswqMF3T20nhUN9+Ti597ZEbRcWDcoEZtw
 v2NznOTJ7Mm2SrNHOvDklstggNIGcwiAEePGMo7rJNEQZChpDjQj/gJWKzn0UwL4
 zfk+0EzoejPdvZ5FJUfmlr8Tqk53uw+y7/0xQ6gf8lDviTrzzoeXtJUyumGBiuGx
 RxFywf8n02oLYRJm5hu+0NkC+/bX0Lxg/kwiR6FLBFbBFgkWyp7FGcxhlm6ZiBfe
 0KkPciWslNavn5KhljIkZDbXymbvhhSr9uBEFsyeJueA5q7sSghWloL8Ag1cac3W
 e6swD1ngXtM/t5gjOLhR
 =hC7z
 -----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:
 "We have two changes to the core framework this time around.

  The first being a large change that introduces runtime PM support to
  the clk framework. Now we properly call runtime PM operations on the
  device providing a clk when the clk is in use. This helps on SoCs
  where the clks provided by a device need something to be powered on
  before using the clks, like power domains or regulators. It also helps
  power those things down when clks aren't in use.

  The other core change is a devm API addition for clk providers so we
  can get rid of a bunch of clk driver remove functions that are just
  doing of_clk_del_provider().

  Outside of the core, we have the usual addition of clk drivers and
  smattering of non-critical fixes to existing drivers. The biggest diff
  is support for Mediatek MT2712 and MT7622 SoCs, but those patches
  really just add a bunch of data.

  By the way, we're trying something new here where we build the tree up
  with topic branches. We plan to work this into our workflow so that we
  don't step on each other's toes, and so the fixes branch can be merged
  on an as-needed basis.

  Summary:

  Core:
   - runtime PM support for clk providers
   - devm API for of_clk_add_hw_provider()

  New Drivers:
   - Mediatek MT2712 and MT7622
   - Renesas R-Car V3M SoC

  Updates:
   - runtime PM support for Samsung exynos5433/exynos4412 providers
   - removal of clkdev aliases on Samsung SoCs
   - convert clk-gpio to use gpio descriptors
   - various driver cleanups to match kernel coding style
   - Amlogic Video Processing Unit VPU and VAPB clks
   - sigma-delta modulation for Allwinner audio PLLs
   - Allwinner A83t Display clks
   - support for the second display unit clock on Renesas RZ/G1E
   - suspend/resume support for Renesas R-Car Gen3 CPG/MSSR
   - new clock ids for Rockchip rk3188 and rk3368 SoCs
   - various 'const' markings on clk_ops structures
   - RPM clk support on Qualcomm MSM8996/MSM8660 SoCs"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (137 commits)
  clk: stm32h7: fix test of clock config
  clk: pxa: fix building on older compilers
  clk: sunxi-ng: a83t: Fix i2c buses bits
  clk: ti: dra7-atl-clock: fix child-node lookups
  clk: qcom: common: fix legacy board-clock registration
  clk: uniphier: fix DAPLL2 clock rate of Pro5
  clk: uniphier: fix parent of miodmac clock data
  clk: hi3798cv200: correct parent mux clock for 'clk_sdio0_ciu'
  clk: hisilicon: Delete an error message for a failed memory allocation in hisi_register_clkgate_sep()
  clk: hi3660: fix incorrect uart3 clock freqency
  clk: kona-setup: Delete error messages for failed memory allocations
  ARC: clk: fix spelling mistake: "configurarion" -> "configuration"
  clk: cdce925: remove redundant check for non-null parent_name
  clk: versatile: Improve sizeof() usage
  clk: versatile: Delete error messages for failed memory allocations
  clk: ux500: Improve sizeof() usage
  clk: ux500: Delete error messages for failed memory allocations
  clk: spear: Delete error messages for failed memory allocations
  clk: ti: Delete error messages for failed memory allocations
  clk: mmp: Adjust checks for NULL pointers
  ...
This commit is contained in:
Linus Torvalds 2017-11-17 20:04:24 -08:00
commit fc35c1966e
185 changed files with 7231 additions and 980 deletions

View File

@ -7,7 +7,9 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-apmixedsys"
- "mediatek,mt2712-apmixedsys", "syscon"
- "mediatek,mt6797-apmixedsys"
- "mediatek,mt7622-apmixedsys"
- "mediatek,mt8135-apmixedsys"
- "mediatek,mt8173-apmixedsys"
- #clock-cells: Must be 1

View File

@ -0,0 +1,22 @@
MediaTek AUDSYS controller
============================
The MediaTek AUDSYS controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt7622-audsys", "syscon"
- #clock-cells: Must be 1
The AUDSYS controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
audsys: audsys@11220000 {
compatible = "mediatek,mt7622-audsys", "syscon";
reg = <0 0x11220000 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be:
- "mediatek,mt2701-bdpsys", "syscon"
- "mediatek,mt2712-bdpsys", "syscon"
- #clock-cells: Must be 1
The bdpsys controller uses the common clk binding from

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be:
- "mediatek,mt2701-ethsys", "syscon"
- "mediatek,mt7622-ethsys", "syscon"
- #clock-cells: Must be 1
The ethsys controller uses the common clk binding from

View File

@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be:
- "mediatek,mt2701-hifsys", "syscon"
- "mediatek,mt7622-hifsys", "syscon"
- #clock-cells: Must be 1
The hifsys controller uses the common clk binding from

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-imgsys", "syscon"
- "mediatek,mt2712-imgsys", "syscon"
- "mediatek,mt6797-imgsys", "syscon"
- "mediatek,mt8173-imgsys", "syscon"
- #clock-cells: Must be 1

View File

@ -8,7 +8,9 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-infracfg", "syscon"
- "mediatek,mt2712-infracfg", "syscon"
- "mediatek,mt6797-infracfg", "syscon"
- "mediatek,mt7622-infracfg", "syscon"
- "mediatek,mt8135-infracfg", "syscon"
- "mediatek,mt8173-infracfg", "syscon"
- #clock-cells: Must be 1

View File

@ -0,0 +1,22 @@
Mediatek jpgdecsys controller
============================
The Mediatek jpgdecsys controller provides various clocks to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt2712-jpgdecsys", "syscon"
- #clock-cells: Must be 1
The jpgdecsys controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
jpgdecsys: syscon@19000000 {
compatible = "mediatek,mt2712-jpgdecsys", "syscon";
reg = <0 0x19000000 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -0,0 +1,22 @@
Mediatek mcucfg controller
============================
The Mediatek mcucfg controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-mcucfg", "syscon"
- #clock-cells: Must be 1
The mcucfg controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
mcucfg: syscon@10220000 {
compatible = "mediatek,mt2712-mcucfg", "syscon";
reg = <0 0x10220000 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -0,0 +1,22 @@
Mediatek mfgcfg controller
============================
The Mediatek mfgcfg controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-mfgcfg", "syscon"
- #clock-cells: Must be 1
The mfgcfg controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
mfgcfg: syscon@13000000 {
compatible = "mediatek,mt2712-mfgcfg", "syscon";
reg = <0 0x13000000 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-mmsys", "syscon"
- "mediatek,mt2712-mmsys", "syscon"
- "mediatek,mt6797-mmsys", "syscon"
- "mediatek,mt8173-mmsys", "syscon"
- #clock-cells: Must be 1

View File

@ -0,0 +1,22 @@
MediaTek PCIESYS controller
============================
The MediaTek PCIESYS controller provides various clocks to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt7622-pciesys", "syscon"
- #clock-cells: Must be 1
The PCIESYS controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
pciesys: pciesys@1a100800 {
compatible = "mediatek,mt7622-pciesys", "syscon";
reg = <0 0x1a100800 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -8,6 +8,8 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-pericfg", "syscon"
- "mediatek,mt2712-pericfg", "syscon"
- "mediatek,mt7622-pericfg", "syscon"
- "mediatek,mt8135-pericfg", "syscon"
- "mediatek,mt8173-pericfg", "syscon"
- #clock-cells: Must be 1

View File

@ -0,0 +1,22 @@
MediaTek SGMIISYS controller
============================
The MediaTek SGMIISYS controller provides various clocks to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt7622-sgmiisys", "syscon"
- #clock-cells: Must be 1
The SGMIISYS controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
sgmiisys: sgmiisys@1b128000 {
compatible = "mediatek,mt7622-sgmiisys", "syscon";
reg = <0 0x1b128000 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -0,0 +1,22 @@
MediaTek SSUSBSYS controller
============================
The MediaTek SSUSBSYS controller provides various clocks to the system.
Required Properties:
- compatible: Should be:
- "mediatek,mt7622-ssusbsys", "syscon"
- #clock-cells: Must be 1
The SSUSBSYS controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
ssusbsys: ssusbsys@1a000000 {
compatible = "mediatek,mt7622-ssusbsys", "syscon";
reg = <0 0x1a000000 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -7,7 +7,9 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-topckgen"
- "mediatek,mt2712-topckgen", "syscon"
- "mediatek,mt6797-topckgen"
- "mediatek,mt7622-topckgen"
- "mediatek,mt8135-topckgen"
- "mediatek,mt8173-topckgen"
- #clock-cells: Must be 1

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-vdecsys", "syscon"
- "mediatek,mt2712-vdecsys", "syscon"
- "mediatek,mt6797-vdecsys", "syscon"
- "mediatek,mt8173-vdecsys", "syscon"
- #clock-cells: Must be 1

View File

@ -6,6 +6,7 @@ The Mediatek vencsys controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-vencsys", "syscon"
- "mediatek,mt6797-vencsys", "syscon"
- "mediatek,mt8173-vencsys", "syscon"
- #clock-cells: Must be 1

View File

@ -33,6 +33,12 @@ Required Properties:
- clock-names: Aliases for the above clocks. They should be "pll_ref",
"pll_in", "cdclk", "sclk_audio", and "sclk_pcm_in" respectively.
Optional Properties:
- power-domains: a phandle to respective power domain node as described by
generic PM domain bindings (see power/power_domain.txt for more
information).
The following is the list of clocks generated by the controller. Each clock is
assigned an identifier and client nodes use this identifier to specify the
clock which they consume. Some of the clocks are available only on a particular

View File

@ -41,3 +41,46 @@ Example 2: UART controller node that consumes the clock generated by the clock
clocks = <&clock CLK_UART2>, <&clock CLK_SCLK_UART2>;
clock-names = "uart", "clk_uart_baud0";
};
Exynos4412 SoC contains some additional clocks for FIMC-ISP (Camera ISP)
subsystem. Registers for those clocks are located in the ISP power domain.
Because those registers are also located in a different memory region than
the main clock controller, a separate clock controller has to be defined for
handling them.
Required Properties:
- compatible: should be "samsung,exynos4412-isp-clock".
- reg: physical base address of the ISP clock controller and length of memory
mapped region.
- #clock-cells: should be 1.
- clocks: list of the clock controller input clock identifiers,
from common clock bindings, should point to CLK_ACLK200 and
CLK_ACLK400_MCUISP clocks from the main clock controller.
- clock-names: list of the clock controller input clock names,
as described in clock-bindings.txt, should be "aclk200" and
"aclk400_mcuisp".
- power-domains: a phandle to ISP power domain node as described by
generic PM domain bindings.
Example 3: The clock controllers bindings for Exynos4412 SoCs.
clock: clock-controller@10030000 {
compatible = "samsung,exynos4412-clock";
reg = <0x10030000 0x18000>;
#clock-cells = <1>;
};
isp_clock: clock-controller@10048000 {
compatible = "samsung,exynos4412-isp-clock";
reg = <0x10048000 0x1000>;
#clock-cells = <1>;
power-domains = <&pd_isp>;
clocks = <&clock CLK_ACLK200>, <&clock CLK_ACLK400_MCUISP>;
clock-names = "aclk200", "aclk400_mcuisp";
};

View File

@ -168,6 +168,11 @@ Required Properties:
- aclk_cam1_400
- aclk_cam1_552
Optional properties:
- power-domains: a phandle to respective power domain node as described by
generic PM domain bindings (see power/power_domain.txt for more
information).
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume.
@ -270,6 +275,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_ACLK_G2D_266>,
<&cmu_top CLK_ACLK_G2D_400>;
power-domains = <&pd_g2d>;
};
cmu_disp: clock-controller@13b90000 {
@ -295,6 +301,7 @@ Example 2: Examples of clock controller nodes are listed below.
<&cmu_mif CLK_SCLK_DECON_ECLK_DISP>,
<&cmu_mif CLK_SCLK_DECON_TV_VCLK_DISP>,
<&cmu_mif CLK_ACLK_DISP_333>;
power-domains = <&pd_disp>;
};
cmu_aud: clock-controller@114c0000 {
@ -304,6 +311,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "fout_aud_pll";
clocks = <&xxti>, <&cmu_top CLK_FOUT_AUD_PLL>;
power-domains = <&pd_aud>;
};
cmu_bus0: clock-controller@13600000 {
@ -340,6 +348,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "aclk_g3d_400";
clocks = <&xxti>, <&cmu_top CLK_ACLK_G3D_400>;
power-domains = <&pd_g3d>;
};
cmu_gscl: clock-controller@13cf0000 {
@ -353,6 +362,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_ACLK_GSCL_111>,
<&cmu_top CLK_ACLK_GSCL_333>;
power-domains = <&pd_gscl>;
};
cmu_apollo: clock-controller@11900000 {
@ -384,6 +394,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_SCLK_JPEG_MSCL>,
<&cmu_top CLK_ACLK_MSCL_400>;
power-domains = <&pd_mscl>;
};
cmu_mfc: clock-controller@15280000 {
@ -393,6 +404,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "aclk_mfc_400";
clocks = <&xxti>, <&cmu_top CLK_ACLK_MFC_400>;
power-domains = <&pd_mfc>;
};
cmu_hevc: clock-controller@14f80000 {
@ -402,6 +414,7 @@ Example 2: Examples of clock controller nodes are listed below.
clock-names = "oscclk", "aclk_hevc_400";
clocks = <&xxti>, <&cmu_top CLK_ACLK_HEVC_400>;
power-domains = <&pd_hevc>;
};
cmu_isp: clock-controller@146d0000 {
@ -415,6 +428,7 @@ Example 2: Examples of clock controller nodes are listed below.
clocks = <&xxti>,
<&cmu_top CLK_ACLK_ISP_DIS_400>,
<&cmu_top CLK_ACLK_ISP_400>;
power-domains = <&pd_isp>;
};
cmu_cam0: clock-controller@120d0000 {
@ -430,6 +444,7 @@ Example 2: Examples of clock controller nodes are listed below.
<&cmu_top CLK_ACLK_CAM0_333>,
<&cmu_top CLK_ACLK_CAM0_400>,
<&cmu_top CLK_ACLK_CAM0_552>;
power-domains = <&pd_cam0>;
};
cmu_cam1: clock-controller@145d0000 {
@ -451,6 +466,7 @@ Example 2: Examples of clock controller nodes are listed below.
<&cmu_top CLK_ACLK_CAM1_333>,
<&cmu_top CLK_ACLK_CAM1_400>,
<&cmu_top CLK_ACLK_CAM1_552>;
power-domains = <&pd_cam1>;
};
Example 3: UART controller node that consumes the clock generated by the clock

View File

@ -10,12 +10,23 @@ Required properties :
- compatible : shall contain only one of the following. The generic
compatible "qcom,rpmcc" should be also included.
"qcom,rpmcc-msm8660", "qcom,rpmcc"
"qcom,rpmcc-apq8060", "qcom,rpmcc"
"qcom,rpmcc-msm8916", "qcom,rpmcc"
"qcom,rpmcc-msm8974", "qcom,rpmcc"
"qcom,rpmcc-apq8064", "qcom,rpmcc"
"qcom,rpmcc-msm8996", "qcom,rpmcc"
- #clock-cells : shall contain 1
The clock enumerators are defined in <dt-bindings/clock/qcom,rpmcc.h>
and come in pairs: FOO_CLK followed by FOO_A_CLK. The latter clock
is an "active" clock, which means that the consumer only care that the
clock is available when the apps CPU subsystem is active, i.e. not
suspended or in deep idle. If it is important that the clock keeps running
during system suspend, you need to specify the non-active clock, the one
not containing *_A_* in the enumerator name.
Example:
smd {
compatible = "qcom,smd";

View File

@ -22,6 +22,7 @@ Required Properties:
- "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2)
- "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3)
- "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W)
- "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M)
- "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3)
- reg: Base address and length of the memory resource used by the CPG/MSSR
@ -31,8 +32,8 @@ Required Properties:
clock-names
- clock-names: List of external parent clock names. Valid names are:
- "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
r8a7795, r8a7796, r8a77995)
- "extalr" (r8a7795, r8a7796)
r8a7795, r8a7796, r8a77970, r8a77995)
- "extalr" (r8a7795, r8a7796, r8a77970)
- "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
- #clock-cells: Must be 2

View File

@ -1,6 +1,6 @@
* Renesas RZ Clock Pulse Generator (CPG)
* Renesas RZ/A1 Clock Pulse Generator (CPG)
The CPG generates core clocks for the RZ SoCs. It includes the PLL, variable
The CPG generates core clocks for the RZ/A1 SoCs. It includes the PLL, variable
CPU and GPU clocks, and several fixed ratio dividers.
The CPG also provides a Clock Domain for SoC devices, in combination with the
CPG Module Stop (MSTP) Clocks.

View File

@ -237,6 +237,7 @@ CLOCK
devm_clk_get()
devm_clk_put()
devm_clk_hw_register()
devm_of_clk_add_hw_provider()
DMA
dmam_alloc_coherent()

View File

@ -11543,6 +11543,7 @@ F: include/linux/rpmsg/
RENESAS CLOCK DRIVERS
M: Geert Uytterhoeven <geert+renesas@glider.be>
L: linux-renesas-soc@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-drivers.git clk-renesas
S: Supported
F: drivers/clk/renesas/

View File

@ -14,14 +14,20 @@
#include <linux/of.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <soc/at91/atmel-sfr.h>
#include "pmc.h"
#define UTMI_FIXED_MUL 40
/*
* The purpose of this clock is to generate a 480 MHz signal. A different
* rate can't be configured.
*/
#define UTMI_RATE 480000000
struct clk_utmi {
struct clk_hw hw;
struct regmap *regmap;
struct regmap *regmap_pmc;
struct regmap *regmap_sfr;
};
#define to_clk_utmi(hw) container_of(hw, struct clk_utmi, hw)
@ -37,13 +43,54 @@ static inline bool clk_utmi_ready(struct regmap *regmap)
static int clk_utmi_prepare(struct clk_hw *hw)
{
struct clk_hw *hw_parent;
struct clk_utmi *utmi = to_clk_utmi(hw);
unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
AT91_PMC_BIASEN;
unsigned int utmi_ref_clk_freq;
unsigned long parent_rate;
regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr);
/*
* If mainck rate is different from 12 MHz, we have to configure the
* FREQ field of the SFR_UTMICKTRIM register to generate properly
* the utmi clock.
*/
hw_parent = clk_hw_get_parent(hw);
parent_rate = clk_hw_get_rate(hw_parent);
while (!clk_utmi_ready(utmi->regmap))
switch (parent_rate) {
case 12000000:
utmi_ref_clk_freq = 0;
break;
case 16000000:
utmi_ref_clk_freq = 1;
break;
case 24000000:
utmi_ref_clk_freq = 2;
break;
/*
* Not supported on SAMA5D2 but it's not an issue since MAINCK
* maximum value is 24 MHz.
*/
case 48000000:
utmi_ref_clk_freq = 3;
break;
default:
pr_err("UTMICK: unsupported mainck rate\n");
return -EINVAL;
}
if (utmi->regmap_sfr) {
regmap_update_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM,
AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
} else if (utmi_ref_clk_freq) {
pr_err("UTMICK: sfr node required\n");
return -EINVAL;
}
regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr);
while (!clk_utmi_ready(utmi->regmap_pmc))
cpu_relax();
return 0;
@ -53,21 +100,22 @@ static int clk_utmi_is_prepared(struct clk_hw *hw)
{
struct clk_utmi *utmi = to_clk_utmi(hw);
return clk_utmi_ready(utmi->regmap);
return clk_utmi_ready(utmi->regmap_pmc);
}
static void clk_utmi_unprepare(struct clk_hw *hw)
{
struct clk_utmi *utmi = to_clk_utmi(hw);
regmap_update_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0);
regmap_update_bits(utmi->regmap_pmc, AT91_CKGR_UCKR,
AT91_PMC_UPLLEN, 0);
}
static unsigned long clk_utmi_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
/* UTMI clk is a fixed clk multiplier */
return parent_rate * UTMI_FIXED_MUL;
/* UTMI clk rate is fixed. */
return UTMI_RATE;
}
static const struct clk_ops utmi_ops = {
@ -78,7 +126,7 @@ static const struct clk_ops utmi_ops = {
};
static struct clk_hw * __init
at91_clk_register_utmi(struct regmap *regmap,
at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
const char *name, const char *parent_name)
{
struct clk_utmi *utmi;
@ -97,7 +145,8 @@ at91_clk_register_utmi(struct regmap *regmap,
init.flags = CLK_SET_RATE_GATE;
utmi->hw.init = &init;
utmi->regmap = regmap;
utmi->regmap_pmc = regmap_pmc;
utmi->regmap_sfr = regmap_sfr;
hw = &utmi->hw;
ret = clk_hw_register(NULL, &utmi->hw);
@ -114,17 +163,35 @@ 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;
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 = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap))
regmap_pmc = syscon_node_to_regmap(of_get_parent(np));
if (IS_ERR(regmap_pmc))
return;
hw = at91_clk_register_utmi(regmap, name, parent_name);
/*
* 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;

View File

@ -579,18 +579,13 @@ static u32 *parent_process(const char *clocks[],
*/
parent_names = kmalloc_array(parent_count, sizeof(*parent_names),
GFP_KERNEL);
if (!parent_names) {
pr_err("%s: error allocating %u parent names\n", __func__,
parent_count);
if (!parent_names)
return ERR_PTR(-ENOMEM);
}
/* There is at least one parent, so allocate a selector array */
parent_sel = kmalloc_array(parent_count, sizeof(*parent_sel),
GFP_KERNEL);
if (!parent_sel) {
pr_err("%s: error allocating %u parent selectors\n", __func__,
parent_count);
kfree(parent_names);
return ERR_PTR(-ENOMEM);

View File

@ -665,7 +665,7 @@ static int cdce925_probe(struct i2c_client *client,
init.ops = &cdce925_pll_ops;
init.flags = 0;
init.parent_names = &parent_name;
init.num_parents = parent_name ? 1 : 0;
init.num_parents = 1;
/* Register PLL clocks */
for (i = 0; i < data->chip_info->num_plls; ++i) {

View File

@ -15,9 +15,7 @@
#include <linux/clk-provider.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_gpio.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/platform_device.h>
@ -95,14 +93,12 @@ const struct clk_ops clk_gpio_mux_ops = {
EXPORT_SYMBOL_GPL(clk_gpio_mux_ops);
static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags,
const struct clk_ops *clk_gpio_ops)
const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
unsigned long flags, const struct clk_ops *clk_gpio_ops)
{
struct clk_gpio *clk_gpio;
struct clk_hw *hw;
struct clk_init_data init = {};
unsigned long gpio_flags;
int err;
if (dev)
@ -113,32 +109,13 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
if (!clk_gpio)
return ERR_PTR(-ENOMEM);
if (active_low)
gpio_flags = GPIOF_ACTIVE_LOW | GPIOF_OUT_INIT_HIGH;
else
gpio_flags = GPIOF_OUT_INIT_LOW;
if (dev)
err = devm_gpio_request_one(dev, gpio, gpio_flags, name);
else
err = gpio_request_one(gpio, gpio_flags, name);
if (err) {
if (err != -EPROBE_DEFER)
pr_err("%s: %s: Error requesting clock control gpio %u\n",
__func__, name, gpio);
if (!dev)
kfree(clk_gpio);
return ERR_PTR(err);
}
init.name = name;
init.ops = clk_gpio_ops;
init.flags = flags | CLK_IS_BASIC;
init.parent_names = parent_names;
init.num_parents = num_parents;
clk_gpio->gpiod = gpio_to_desc(gpio);
clk_gpio->gpiod = gpiod;
clk_gpio->hw.init = &init;
hw = &clk_gpio->hw;
@ -151,7 +128,6 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
return hw;
if (!dev) {
gpiod_put(clk_gpio->gpiod);
kfree(clk_gpio);
}
@ -164,29 +140,27 @@ static struct clk_hw *clk_register_gpio(struct device *dev, const char *name,
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_name: name of this clock's parent
* @gpio: gpio number to gate this clock
* @active_low: true if gpio should be set to 0 to enable clock
* @gpiod: gpio descriptor to gate this clock
* @flags: clock flags
*/
struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
const char *parent_name, unsigned gpio, bool active_low,
const char *parent_name, struct gpio_desc *gpiod,
unsigned long flags)
{
return clk_register_gpio(dev, name,
(parent_name ? &parent_name : NULL),
(parent_name ? 1 : 0), gpio, active_low, flags,
(parent_name ? 1 : 0), gpiod, flags,
&clk_gpio_gate_ops);
}
EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate);
struct clk *clk_register_gpio_gate(struct device *dev, const char *name,
const char *parent_name, unsigned gpio, bool active_low,
const char *parent_name, struct gpio_desc *gpiod,
unsigned long flags)
{
struct clk_hw *hw;
hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpio, active_low,
flags);
hw = clk_hw_register_gpio_gate(dev, name, parent_name, gpiod, flags);
if (IS_ERR(hw))
return ERR_CAST(hw);
return hw->clk;
@ -199,13 +173,12 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_gate);
* @name: name of this clock
* @parent_names: names of this clock's parents
* @num_parents: number of parents listed in @parent_names
* @gpio: gpio number to gate this clock
* @active_low: true if gpio should be set to 0 to enable clock
* @gpiod: gpio descriptor to gate this clock
* @flags: clock flags
*/
struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags)
const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
unsigned long flags)
{
if (num_parents != 2) {
pr_err("mux-clock %s must have 2 parents\n", name);
@ -213,18 +186,18 @@ struct clk_hw *clk_hw_register_gpio_mux(struct device *dev, const char *name,
}
return clk_register_gpio(dev, name, parent_names, num_parents,
gpio, active_low, flags, &clk_gpio_mux_ops);
gpiod, flags, &clk_gpio_mux_ops);
}
EXPORT_SYMBOL_GPL(clk_hw_register_gpio_mux);
struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents, unsigned gpio,
bool active_low, unsigned long flags)
const char * const *parent_names, u8 num_parents, struct gpio_desc *gpiod,
unsigned long flags)
{
struct clk_hw *hw;
hw = clk_hw_register_gpio_mux(dev, name, parent_names, num_parents,
gpio, active_low, flags);
gpiod, flags);
if (IS_ERR(hw))
return ERR_CAST(hw);
return hw->clk;
@ -236,10 +209,10 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node;
const char **parent_names, *gpio_name;
unsigned int num_parents;
int gpio;
enum of_gpio_flags of_flags;
struct gpio_desc *gpiod;
struct clk *clk;
bool active_low, is_mux;
bool is_mux;
int ret;
num_parents = of_clk_get_parent_count(node);
if (num_parents) {
@ -255,28 +228,27 @@ static int gpio_clk_driver_probe(struct platform_device *pdev)
is_mux = of_device_is_compatible(node, "gpio-mux-clock");
gpio_name = is_mux ? "select-gpios" : "enable-gpios";
gpio = of_get_named_gpio_flags(node, gpio_name, 0, &of_flags);
if (gpio < 0) {
if (gpio == -EPROBE_DEFER)
gpio_name = is_mux ? "select" : "enable";
gpiod = devm_gpiod_get(&pdev->dev, gpio_name, GPIOD_OUT_LOW);
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__);
else
pr_err("%s: %s: Can't get '%s' DT property\n",
pr_err("%s: %s: Can't get '%s' named GPIO property\n",
node->name, __func__,
gpio_name);
return gpio;
return ret;
}
active_low = of_flags & OF_GPIO_ACTIVE_LOW;
if (is_mux)
clk = clk_register_gpio_mux(&pdev->dev, node->name,
parent_names, num_parents, gpio, active_low, 0);
parent_names, num_parents, gpiod, 0);
else
clk = clk_register_gpio_gate(&pdev->dev, node->name,
parent_names ? parent_names[0] : NULL, gpio,
active_low, 0);
parent_names ? parent_names[0] : NULL, gpiod,
0);
if (IS_ERR(clk))
return PTR_ERR(clk);

View File

@ -139,7 +139,7 @@ static inline void hsdk_pll_set_cfg(struct hsdk_pll_clk *clk,
val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT;
val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT;
dev_dbg(clk->dev, "write configurarion: %#x\n", val);
dev_dbg(clk->dev, "write configuration: %#x\n", val);
hsdk_pll_write(clk, CGU_PLL_CTRL, val);
}
@ -169,7 +169,7 @@ static unsigned long hsdk_pll_recalc_rate(struct clk_hw *hw,
val = hsdk_pll_read(clk, CGU_PLL_CTRL);
dev_dbg(clk->dev, "current configurarion: %#x\n", val);
dev_dbg(clk->dev, "current configuration: %#x\n", val);
/* Check if PLL is disabled */
if (val & CGU_PLL_CTRL_PD)

View File

@ -134,11 +134,9 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
}
/* allocate the mux */
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
if (!mux) {
pr_err("%s: could not allocate mux clk\n", __func__);
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
if (!mux)
return ERR_PTR(-ENOMEM);
}
init.name = name;
if (clk_mux_flags & CLK_MUX_READ_ONLY)

View File

@ -384,7 +384,7 @@ static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg,
mux_ops = div_ops = gate_ops = NULL;
mux_hw = div_hw = gate_hw = NULL;
if (gcfg->mux && gcfg->mux) {
if (gcfg->mux && cfg->mux) {
mux = _get_cmux(base + cfg->mux->offset,
cfg->mux->shift,
cfg->mux->width,
@ -410,7 +410,7 @@ static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg,
}
}
if (gcfg->gate && gcfg->gate) {
if (gcfg->gate && cfg->gate) {
gate = _get_cgate(base + cfg->gate->offset,
cfg->gate->bit_idx,
gcfg->gate->flags, lock);

View File

@ -82,7 +82,7 @@ static const struct clk_ops twl6040_pdmclk_ops = {
.recalc_rate = twl6040_pdmclk_recalc_rate,
};
static struct clk_init_data twl6040_pdmclk_init = {
static const struct clk_init_data twl6040_pdmclk_init = {
.name = "pdmclk",
.ops = &twl6040_pdmclk_ops,
.flags = CLK_GET_RATE_NOCACHE,

View File

@ -229,15 +229,15 @@
#define U300_SYSCON_S0CCR_CLOCK_FREQ_MASK (0x01E0)
#define U300_SYSCON_S0CCR_CLOCK_SELECT_MASK (0x001E)
#define U300_SYSCON_S0CCR_CLOCK_ENABLE (0x0001)
#define U300_SYSCON_S0CCR_SEL_MCLK (0x8<<1)
#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA<<1)
#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC<<1)
#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD<<1)
#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE<<1)
#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0<<1)
#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2<<1)
#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4<<1)
#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6<<1)
#define U300_SYSCON_S0CCR_SEL_MCLK (0x8 << 1)
#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA << 1)
#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC << 1)
#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD << 1)
#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE << 1)
#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0 << 1)
#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2 << 1)
#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4 << 1)
#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6 << 1)
/* SYS_1_CLK_CONTROL second clock control 16 bit (R/W) */
#define U300_SYSCON_S1CCR (0x124)
#define U300_SYSCON_S1CCR_FIELD_MASK (0x43FF)
@ -247,16 +247,16 @@
#define U300_SYSCON_S1CCR_CLOCK_FREQ_MASK (0x01E0)
#define U300_SYSCON_S1CCR_CLOCK_SELECT_MASK (0x001E)
#define U300_SYSCON_S1CCR_CLOCK_ENABLE (0x0001)
#define U300_SYSCON_S1CCR_SEL_MCLK (0x8<<1)
#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA<<1)
#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC<<1)
#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD<<1)
#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE<<1)
#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0<<1)
#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2<<1)
#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4<<1)
#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6<<1)
/* SYS_2_CLK_CONTROL third clock contol 16 bit (R/W) */
#define U300_SYSCON_S1CCR_SEL_MCLK (0x8 << 1)
#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA << 1)
#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC << 1)
#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD << 1)
#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE << 1)
#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0 << 1)
#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2 << 1)
#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4 << 1)
#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6 << 1)
/* SYS_2_CLK_CONTROL third clock control 16 bit (R/W) */
#define U300_SYSCON_S2CCR (0x128)
#define U300_SYSCON_S2CCR_FIELD_MASK (0xC3FF)
#define U300_SYSCON_S2CCR_CLK_STEAL (0x8000)
@ -266,15 +266,15 @@
#define U300_SYSCON_S2CCR_CLOCK_FREQ_MASK (0x01E0)
#define U300_SYSCON_S2CCR_CLOCK_SELECT_MASK (0x001E)
#define U300_SYSCON_S2CCR_CLOCK_ENABLE (0x0001)
#define U300_SYSCON_S2CCR_SEL_MCLK (0x8<<1)
#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA<<1)
#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC<<1)
#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD<<1)
#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE<<1)
#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0<<1)
#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2<<1)
#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4<<1)
#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6<<1)
#define U300_SYSCON_S2CCR_SEL_MCLK (0x8 << 1)
#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA << 1)
#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC << 1)
#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD << 1)
#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE << 1)
#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0 << 1)
#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2 << 1)
#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4 << 1)
#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6 << 1)
/* SC_PLL_IRQ_CONTROL 16bit (R/W) */
#define U300_SYSCON_PICR (0x0130)
#define U300_SYSCON_PICR_MASK (0x00FF)
@ -378,7 +378,7 @@
* +- ISP Image Signal Processor (U335 only)
* +- CDS (U335 only)
* +- DMA Direct Memory Access Controller
* +- AAIF APP/ACC Inteface (Mobile Scalable Link, MSL)
* +- AAIF APP/ACC Interface (Mobile Scalable Link, MSL)
* +- APEX
* +- VIDEO_ENC AVE2/3 Video Encoder
* +- XGAM Graphics Accelerator Controller
@ -568,14 +568,14 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
struct clk_syscon *sclk = to_syscon(hw);
u16 perf = syscon_get_perf();
switch(sclk->clk_val) {
switch (sclk->clk_val) {
case U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN:
case U300_SYSCON_SBCER_I2C0_CLK_EN:
case U300_SYSCON_SBCER_I2C1_CLK_EN:
case U300_SYSCON_SBCER_MMC_CLK_EN:
case U300_SYSCON_SBCER_SPI_CLK_EN:
/* The FAST clocks have one progression */
switch(perf) {
switch (perf) {
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
return 13000000;
@ -586,7 +586,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
case U300_SYSCON_SBCER_NANDIF_CLK_EN:
case U300_SYSCON_SBCER_XGAM_CLK_EN:
/* AMBA interconnect peripherals */
switch(perf) {
switch (perf) {
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
return 6500000;
@ -598,7 +598,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
case U300_SYSCON_SBCER_SEMI_CLK_EN:
case U300_SYSCON_SBCER_EMIF_CLK_EN:
/* EMIF speeds */
switch(perf) {
switch (perf) {
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
return 13000000;
@ -609,7 +609,7 @@ syscon_clk_recalc_rate(struct clk_hw *hw,
}
case U300_SYSCON_SBCER_CPU_CLK_EN:
/* And the fast CPU clock */
switch(perf) {
switch (perf) {
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER:
case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW:
return 13000000;
@ -702,12 +702,10 @@ syscon_clk_register(struct device *dev, const char *name,
struct clk_init_data init;
int ret;
sclk = kzalloc(sizeof(struct clk_syscon), GFP_KERNEL);
if (!sclk) {
pr_err("could not allocate syscon clock %s\n",
name);
sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
if (!sclk)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &syscon_clk_ops;
init.flags = flags;
@ -1123,12 +1121,10 @@ mclk_clk_register(struct device *dev, const char *name,
struct clk_init_data init;
int ret;
mclk = kzalloc(sizeof(struct clk_mclk), GFP_KERNEL);
if (!mclk) {
pr_err("could not allocate MMC/SD clock %s\n",
name);
mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
if (!mclk)
return ERR_PTR(-ENOMEM);
}
init.name = "mclk";
init.ops = &mclk_ops;
init.flags = 0;

View File

@ -52,7 +52,7 @@ static const struct clk_ops wm831x_xtal_ops = {
.recalc_rate = wm831x_xtal_recalc_rate,
};
static struct clk_init_data wm831x_xtal_init = {
static const struct clk_init_data wm831x_xtal_init = {
.name = "xtal",
.ops = &wm831x_xtal_ops,
};
@ -225,7 +225,7 @@ static const struct clk_ops wm831x_fll_ops = {
.get_parent = wm831x_fll_get_parent,
};
static struct clk_init_data wm831x_fll_init = {
static const struct clk_init_data wm831x_fll_init = {
.name = "fll",
.ops = &wm831x_fll_ops,
.parent_names = wm831x_fll_parents,
@ -338,7 +338,7 @@ static const struct clk_ops wm831x_clkout_ops = {
.set_parent = wm831x_clkout_set_parent,
};
static struct clk_init_data wm831x_clkout_init = {
static const struct clk_init_data wm831x_clkout_init = {
.name = "clkout",
.ops = &wm831x_clkout_ops,
.parent_names = wm831x_clkout_parents,

View File

@ -146,10 +146,8 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
/* allocate the APM clock structure */
apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
if (!apmclk) {
pr_err("%s: could not allocate APM clk\n", __func__);
if (!apmclk)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &xgene_clk_pll_ops;
@ -191,7 +189,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty
int version = xgene_pllclk_version(np);
reg = of_iomap(np, 0);
if (reg == NULL) {
if (!reg) {
pr_err("Unable to map CSR register for %pOF\n", np);
return;
}
@ -467,7 +465,7 @@ static int xgene_clk_enable(struct clk_hw *hw)
if (pclk->lock)
spin_lock_irqsave(pclk->lock, flags);
if (pclk->param.csr_reg != NULL) {
if (pclk->param.csr_reg) {
pr_debug("%s clock enabled\n", clk_hw_get_name(hw));
/* First enable the clock */
data = xgene_clk_read(pclk->param.csr_reg +
@ -507,7 +505,7 @@ static void xgene_clk_disable(struct clk_hw *hw)
if (pclk->lock)
spin_lock_irqsave(pclk->lock, flags);
if (pclk->param.csr_reg != NULL) {
if (pclk->param.csr_reg) {
pr_debug("%s clock disabled\n", clk_hw_get_name(hw));
/* First put the CSR in reset */
data = xgene_clk_read(pclk->param.csr_reg +
@ -533,7 +531,7 @@ static int xgene_clk_is_enabled(struct clk_hw *hw)
struct xgene_clk *pclk = to_xgene_clk(hw);
u32 data = 0;
if (pclk->param.csr_reg != NULL) {
if (pclk->param.csr_reg) {
pr_debug("%s clock checking\n", clk_hw_get_name(hw));
data = xgene_clk_read(pclk->param.csr_reg +
pclk->param.reg_clk_offset);
@ -542,7 +540,7 @@ static int xgene_clk_is_enabled(struct clk_hw *hw)
"disabled");
}
if (pclk->param.csr_reg == NULL)
if (!pclk->param.csr_reg)
return 1;
return data & pclk->param.reg_clk_mask ? 1 : 0;
}
@ -650,10 +648,8 @@ static struct clk *xgene_register_clk(struct device *dev,
/* allocate the APM clock structure */
apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
if (!apmclk) {
pr_err("%s: could not allocate APM clk\n", __func__);
if (!apmclk)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &xgene_clk_ops;
@ -709,7 +705,7 @@ static void __init xgene_devclk_init(struct device_node *np)
break;
}
map_res = of_iomap(np, i);
if (map_res == NULL) {
if (!map_res) {
pr_err("Unable to map resource %d for %pOF\n", i, np);
goto err;
}

View File

@ -21,6 +21,7 @@
#include <linux/of.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/pm_runtime.h>
#include <linux/sched.h>
#include <linux/clkdev.h>
@ -46,6 +47,7 @@ struct clk_core {
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
struct device *dev;
struct clk_core *parent;
const char **parent_names;
struct clk_core **parents;
@ -87,6 +89,26 @@ struct clk {
struct hlist_node clks_node;
};
/*** runtime pm ***/
static int clk_pm_runtime_get(struct clk_core *core)
{
int ret = 0;
if (!core->dev)
return 0;
ret = pm_runtime_get_sync(core->dev);
return ret < 0 ? ret : 0;
}
static void clk_pm_runtime_put(struct clk_core *core)
{
if (!core->dev)
return;
pm_runtime_put_sync(core->dev);
}
/*** locking ***/
static void clk_prepare_lock(void)
{
@ -150,6 +172,8 @@ static void clk_enable_unlock(unsigned long flags)
static bool clk_core_is_prepared(struct clk_core *core)
{
bool ret = false;
/*
* .is_prepared is optional for clocks that can prepare
* fall back to software usage counter if it is missing
@ -157,11 +181,18 @@ static bool clk_core_is_prepared(struct clk_core *core)
if (!core->ops->is_prepared)
return core->prepare_count;
return core->ops->is_prepared(core->hw);
if (!clk_pm_runtime_get(core)) {
ret = core->ops->is_prepared(core->hw);
clk_pm_runtime_put(core);
}
return ret;
}
static bool clk_core_is_enabled(struct clk_core *core)
{
bool ret = false;
/*
* .is_enabled is only mandatory for clocks that gate
* fall back to software usage counter if .is_enabled is missing
@ -169,7 +200,29 @@ static bool clk_core_is_enabled(struct clk_core *core)
if (!core->ops->is_enabled)
return core->enable_count;
return core->ops->is_enabled(core->hw);
/*
* Check if clock controller's device is runtime active before
* calling .is_enabled callback. If not, assume that clock is
* disabled, because we might be called from atomic context, from
* which pm_runtime_get() is not allowed.
* This function is called mainly from clk_disable_unused_subtree,
* which ensures proper runtime pm activation of controller before
* taking enable spinlock, but the below check is needed if one tries
* to call it from other places.
*/
if (core->dev) {
pm_runtime_get_noresume(core->dev);
if (!pm_runtime_active(core->dev)) {
ret = false;
goto done;
}
}
ret = core->ops->is_enabled(core->hw);
done:
clk_pm_runtime_put(core);
return ret;
}
/*** helper functions ***/
@ -489,6 +542,8 @@ static void clk_core_unprepare(struct clk_core *core)
if (core->ops->unprepare)
core->ops->unprepare(core->hw);
clk_pm_runtime_put(core);
trace_clk_unprepare_complete(core);
clk_core_unprepare(core->parent);
}
@ -530,10 +585,14 @@ static int clk_core_prepare(struct clk_core *core)
return 0;
if (core->prepare_count == 0) {
ret = clk_core_prepare(core->parent);
ret = clk_pm_runtime_get(core);
if (ret)
return ret;
ret = clk_core_prepare(core->parent);
if (ret)
goto runtime_put;
trace_clk_prepare(core);
if (core->ops->prepare)
@ -541,15 +600,18 @@ static int clk_core_prepare(struct clk_core *core)
trace_clk_prepare_complete(core);
if (ret) {
clk_core_unprepare(core->parent);
return ret;
}
if (ret)
goto unprepare;
}
core->prepare_count++;
return 0;
unprepare:
clk_core_unprepare(core->parent);
runtime_put:
clk_pm_runtime_put(core);
return ret;
}
static int clk_core_prepare_lock(struct clk_core *core)
@ -745,6 +807,9 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
if (core->flags & CLK_IGNORE_UNUSED)
return;
if (clk_pm_runtime_get(core))
return;
if (clk_core_is_prepared(core)) {
trace_clk_unprepare(core);
if (core->ops->unprepare_unused)
@ -753,6 +818,8 @@ static void clk_unprepare_unused_subtree(struct clk_core *core)
core->ops->unprepare(core->hw);
trace_clk_unprepare_complete(core);
}
clk_pm_runtime_put(core);
}
static void clk_disable_unused_subtree(struct clk_core *core)
@ -768,6 +835,9 @@ static void clk_disable_unused_subtree(struct clk_core *core)
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_prepare_enable(core->parent);
if (clk_pm_runtime_get(core))
goto unprepare_out;
flags = clk_enable_lock();
if (core->enable_count)
@ -792,6 +862,8 @@ static void clk_disable_unused_subtree(struct clk_core *core)
unlock_out:
clk_enable_unlock(flags);
clk_pm_runtime_put(core);
unprepare_out:
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_disable_unprepare(core->parent);
}
@ -1038,9 +1110,13 @@ EXPORT_SYMBOL_GPL(clk_get_accuracy);
static unsigned long clk_recalc(struct clk_core *core,
unsigned long parent_rate)
{
if (core->ops->recalc_rate)
return core->ops->recalc_rate(core->hw, parent_rate);
return parent_rate;
unsigned long rate = parent_rate;
if (core->ops->recalc_rate && !clk_pm_runtime_get(core)) {
rate = core->ops->recalc_rate(core->hw, parent_rate);
clk_pm_runtime_put(core);
}
return rate;
}
/**
@ -1565,6 +1641,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
{
struct clk_core *top, *fail_clk;
unsigned long rate = req_rate;
int ret = 0;
if (!core)
return 0;
@ -1581,21 +1658,28 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
if (!top)
return -EINVAL;
ret = clk_pm_runtime_get(core);
if (ret)
return ret;
/* notify that we are about to change rates */
fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
if (fail_clk) {
pr_debug("%s: failed to set %s rate\n", __func__,
fail_clk->name);
clk_propagate_rate_change(top, ABORT_RATE_CHANGE);
return -EBUSY;
ret = -EBUSY;
goto err;
}
/* change the rates */
clk_change_rate(top);
core->req_rate = req_rate;
err:
clk_pm_runtime_put(core);
return 0;
return ret;
}
/**
@ -1826,12 +1910,16 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
p_rate = parent->rate;
}
ret = clk_pm_runtime_get(core);
if (ret)
goto out;
/* propagate PRE_RATE_CHANGE notifications */
ret = __clk_speculate_rates(core, p_rate);
/* abort if a driver objects */
if (ret & NOTIFY_STOP_MASK)
goto out;
goto runtime_put;
/* do the re-parent */
ret = __clk_set_parent(core, parent, p_index);
@ -1844,6 +1932,8 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
__clk_recalc_accuracies(core);
}
runtime_put:
clk_pm_runtime_put(core);
out:
clk_prepare_unlock();
@ -2350,7 +2440,7 @@ static inline void clk_debug_unregister(struct clk_core *core)
*/
static int __clk_core_init(struct clk_core *core)
{
int i, ret = 0;
int i, ret;
struct clk_core *orphan;
struct hlist_node *tmp2;
unsigned long rate;
@ -2360,6 +2450,10 @@ static int __clk_core_init(struct clk_core *core)
clk_prepare_lock();
ret = clk_pm_runtime_get(core);
if (ret)
goto unlock;
/* check to see if a clock with this name is already registered */
if (clk_core_lookup(core->name)) {
pr_debug("%s: clk %s already initialized\n",
@ -2512,6 +2606,8 @@ static int __clk_core_init(struct clk_core *core)
kref_init(&core->ref);
out:
clk_pm_runtime_put(core);
unlock:
clk_prepare_unlock();
if (!ret)
@ -2583,6 +2679,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
goto fail_name;
}
core->ops = hw->init->ops;
if (dev && pm_runtime_enabled(dev))
core->dev = dev;
if (dev && dev->driver)
core->owner = dev->driver->owner;
core->hw = hw;
@ -3177,6 +3275,37 @@ int of_clk_add_hw_provider(struct device_node *np,
}
EXPORT_SYMBOL_GPL(of_clk_add_hw_provider);
static void devm_of_clk_release_provider(struct device *dev, void *res)
{
of_clk_del_provider(*(struct device_node **)res);
}
int devm_of_clk_add_hw_provider(struct device *dev,
struct clk_hw *(*get)(struct of_phandle_args *clkspec,
void *data),
void *data)
{
struct device_node **ptr, *np;
int ret;
ptr = devres_alloc(devm_of_clk_release_provider, sizeof(*ptr),
GFP_KERNEL);
if (!ptr)
return -ENOMEM;
np = dev->of_node;
ret = of_clk_add_hw_provider(np, get, data);
if (!ret) {
*ptr = np;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return ret;
}
EXPORT_SYMBOL_GPL(devm_of_clk_add_hw_provider);
/**
* of_clk_del_provider() - Remove a previously registered clock provider
* @np: Device node pointer associated with clock provider
@ -3198,6 +3327,27 @@ void of_clk_del_provider(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_clk_del_provider);
static int devm_clk_provider_match(struct device *dev, void *res, void *data)
{
struct device_node **np = res;
if (WARN_ON(!np || !*np))
return 0;
return *np == data;
}
void devm_of_clk_del_provider(struct device *dev)
{
int ret;
ret = devres_release(dev, devm_of_clk_release_provider,
devm_clk_provider_match, dev->of_node);
WARN_ON(ret);
}
EXPORT_SYMBOL(devm_of_clk_del_provider);
static struct clk_hw *
__of_clk_get_hw_from_provider(struct of_clk_provider *provider,
struct of_phandle_args *clkspec)

View File

@ -415,7 +415,7 @@ static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
return mmc_clk_set_timing(hw, rate);
}
static struct clk_ops clk_mmc_ops = {
static const struct clk_ops clk_mmc_ops = {
.prepare = mmc_clk_prepare,
.determine_rate = mmc_clk_determine_rate,
.set_rate = mmc_clk_set_rate,

View File

@ -34,7 +34,7 @@ static const struct hisi_fixed_rate_clock hi3660_fixed_rate_clks[] = {
/* crgctrl */
static const struct hisi_fixed_factor_clock hi3660_crg_fixed_factor_clks[] = {
{ HI3660_FACTOR_UART3, "clk_factor_uart3", "iomcu_peri0", 1, 8, 0, },
{ HI3660_FACTOR_UART3, "clk_factor_uart3", "iomcu_peri0", 1, 16, 0, },
{ HI3660_CLK_FACTOR_MMC, "clk_factor_mmc", "clkin_sys", 1, 6, 0, },
{ HI3660_CLK_GATE_I2C0, "clk_gate_i2c0", "clk_i2c0_iomcu", 1, 4, 0, },
{ HI3660_CLK_GATE_I2C1, "clk_gate_i2c1", "clk_i2c1_iomcu", 1, 4, 0, },

View File

@ -145,7 +145,7 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
{ HI6220_BBPPLL_SEL, "bbppll_sel", "pll0_bbp_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 9, 0, },
{ HI6220_MEDIA_PLL_SRC, "media_pll_src", "pll_media_gate", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 10, 0, },
{ HI6220_MMC2_SEL, "mmc2_sel", "mmc2_mux1", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 11, 0, },
{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 12, 0, },
{ HI6220_CS_ATB_SYSPLL, "cs_atb_syspll", "syspll", CLK_SET_RATE_PARENT|CLK_IS_CRITICAL, 0x270, 12, 0, },
};
static struct hisi_mux_clock hi6220_mux_clks_sys[] __initdata = {

View File

@ -208,7 +208,7 @@ static void clk_ether_unprepare(struct clk_hw *hw)
writel_relaxed(val, clk->ctrl_reg);
}
static struct clk_ops clk_ether_ops = {
static const struct clk_ops clk_ether_ops = {
.prepare = clk_ether_prepare,
.unprepare = clk_ether_unprepare,
};
@ -247,7 +247,7 @@ static void clk_complex_disable(struct clk_hw *hw)
writel_relaxed(val, clk->phy_reg);
}
static struct clk_ops clk_complex_ops = {
static const struct clk_ops clk_complex_ops = {
.enable = clk_complex_enable,
.disable = clk_complex_disable,
};

View File

@ -88,7 +88,7 @@ static int clkgate_separated_is_enabled(struct clk_hw *hw)
return reg ? 1 : 0;
}
static struct clk_ops clkgate_separated_ops = {
static const struct clk_ops clkgate_separated_ops = {
.enable = clkgate_separated_enable,
.disable = clkgate_separated_disable,
.is_enabled = clkgate_separated_is_enabled,
@ -105,10 +105,8 @@ struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name,
struct clk_init_data init;
sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
if (!sclk) {
pr_err("%s: fail to allocate separated gated clk\n", __func__);
if (!sclk)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &clkgate_separated_ops;

View File

@ -47,6 +47,8 @@
#define HI3798CV200_FIXED_12M 81
#define HI3798CV200_FIXED_48M 82
#define HI3798CV200_FIXED_60M 83
#define HI3798CV200_FIXED_166P5M 84
#define HI3798CV200_SDIO0_MUX 85
#define HI3798CV200_CRG_NR_CLKS 128
@ -63,6 +65,7 @@ static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
{ HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },
{ HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },
{ HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },
{ HI3798CV200_FIXED_166P5M, "166p5m", NULL, 0, 165000000, },
{ HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },
{ HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },
};
@ -75,12 +78,19 @@ static const char *const comphy1_mux_p[] = {
"100m", "25m"};
static u32 comphy1_mux_table[] = {2, 3};
static const char *const sdio_mux_p[] = {
"100m", "50m", "150m", "166p5m" };
static u32 sdio_mux_table[] = {0, 1, 2, 3};
static struct hisi_mux_clock hi3798cv200_mux_clks[] = {
{ HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },
{ HI3798CV200_COMBPHY1_MUX, "combphy1_mux",
comphy1_mux_p, ARRAY_SIZE(comphy1_mux_p),
CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy1_mux_table, },
{ HI3798CV200_SDIO0_MUX, "sdio0_mux", sdio_mux_p,
ARRAY_SIZE(sdio_mux_p), CLK_SET_RATE_PARENT,
0x9c, 8, 2, 0, sdio_mux_table, },
};
static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
@ -104,7 +114,7 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
/* SDIO */
{ HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",
CLK_SET_RATE_PARENT, 0x9c, 0, 0, },
{ HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "mmc_mux",
{ HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",
CLK_SET_RATE_PARENT, 0x9c, 1, 0, },
/* EMMC */
{ HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",

View File

@ -72,7 +72,7 @@ static int clk_busy_divider_set_rate(struct clk_hw *hw, unsigned long rate,
return ret;
}
static struct clk_ops clk_busy_divider_ops = {
static const struct clk_ops clk_busy_divider_ops = {
.recalc_rate = clk_busy_divider_recalc_rate,
.round_rate = clk_busy_divider_round_rate,
.set_rate = clk_busy_divider_set_rate,
@ -147,7 +147,7 @@ static int clk_busy_mux_set_parent(struct clk_hw *hw, u8 index)
return ret;
}
static struct clk_ops clk_busy_mux_ops = {
static const struct clk_ops clk_busy_mux_ops = {
.get_parent = clk_busy_mux_get_parent,
.set_parent = clk_busy_mux_set_parent,
};

View File

@ -118,7 +118,7 @@ static void clk_gate2_disable_unused(struct clk_hw *hw)
spin_unlock_irqrestore(gate->lock, flags);
}
static struct clk_ops clk_gate2_ops = {
static const struct clk_ops clk_gate2_ops = {
.enable = clk_gate2_enable,
.disable = clk_gate2_disable,
.disable_unused = clk_gate2_disable_unused,

View File

@ -761,7 +761,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_GPU2D_CORE] = imx_clk_gate2("gpu2d_core", "gpu2d_core_podf", base + 0x6c, 24);
clk[IMX6QDL_CLK_GPU3D_CORE] = imx_clk_gate2("gpu3d_core", "gpu3d_core_podf", base + 0x6c, 26);
clk[IMX6QDL_CLK_HDMI_IAHB] = imx_clk_gate2("hdmi_iahb", "ahb", base + 0x70, 0);
clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "video_27m", base + 0x70, 4);
clk[IMX6QDL_CLK_HDMI_ISFR] = imx_clk_gate2("hdmi_isfr", "mipi_core_cfg", base + 0x70, 4);
clk[IMX6QDL_CLK_I2C1] = imx_clk_gate2("i2c1", "ipg_per", base + 0x70, 6);
clk[IMX6QDL_CLK_I2C2] = imx_clk_gate2("i2c2", "ipg_per", base + 0x70, 8);
clk[IMX6QDL_CLK_I2C3] = imx_clk_gate2("i2c3", "ipg_per", base + 0x70, 10);

View File

@ -267,7 +267,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
clks[IMX6ULL_CLK_EPDC_SEL] = imx_clk_mux("epdc_sel", base + 0x34, 9, 3, epdc_sels, ARRAY_SIZE(epdc_sels));
}
clks[IMX6UL_CLK_ECSPI_SEL] = imx_clk_mux("ecspi_sel", base + 0x38, 18, 1, ecspi_sels, ARRAY_SIZE(ecspi_sels));
clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels));
clks[IMX6UL_CLK_LCDIF_PRE_SEL] = imx_clk_mux_flags("lcdif_pre_sel", base + 0x38, 15, 3, lcdif_pre_sels, ARRAY_SIZE(lcdif_pre_sels), CLK_SET_RATE_PARENT);
clks[IMX6UL_CLK_LCDIF_SEL] = imx_clk_mux("lcdif_sel", base + 0x38, 9, 3, lcdif_sels, ARRAY_SIZE(lcdif_sels));
clks[IMX6UL_CLK_LDB_DI0_DIV_SEL] = imx_clk_mux("ldb_di0", base + 0x20, 10, 1, ldb_di0_div_sels, ARRAY_SIZE(ldb_di0_div_sels));

View File

@ -54,11 +54,6 @@ static const char *arm_m4_sel[] = { "osc", "pll_sys_main_240m_clk",
"pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
"pll_usb_main_clk", };
static const char *arm_m0_sel[] = { "osc", "pll_sys_main_120m_clk",
"pll_enet_125m_clk", "pll_sys_pfd2_135m_clk",
"pll_dram_533m_clk", "pll_audio_post_div", "pll_video_main_clk",
"pll_usb_main_clk", };
static const char *axi_sel[] = { "osc", "pll_sys_pfd1_332m_clk",
"pll_dram_533m_clk", "pll_enet_250m_clk", "pll_sys_pfd5_clk",
"pll_audio_post_div", "pll_video_main_clk", "pll_sys_pfd7_clk", };
@ -510,7 +505,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_ARM_A7_ROOT_SRC] = imx_clk_mux2("arm_a7_src", base + 0x8000, 24, 3, arm_a7_sel, ARRAY_SIZE(arm_a7_sel));
clks[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel));
clks[IMX7D_ARM_M0_ROOT_SRC] = imx_clk_mux2("arm_m0_src", base + 0x8100, 24, 3, arm_m0_sel, ARRAY_SIZE(arm_m0_sel));
clks[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel));
clks[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel));
clks[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel));
@ -582,7 +576,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_ARM_A7_ROOT_CG] = imx_clk_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28);
clks[IMX7D_ARM_M4_ROOT_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
clks[IMX7D_ARM_M0_ROOT_CG] = imx_clk_gate3("arm_m0_cg", "arm_m0_src", base + 0x8100, 28);
clks[IMX7D_MAIN_AXI_ROOT_CG] = imx_clk_gate3("axi_cg", "axi_src", base + 0x8800, 28);
clks[IMX7D_DISP_AXI_ROOT_CG] = imx_clk_gate3("disp_axi_cg", "disp_axi_src", base + 0x8880, 28);
clks[IMX7D_ENET_AXI_ROOT_CG] = imx_clk_gate3("enet_axi_cg", "enet_axi_src", base + 0x8900, 28);
@ -721,7 +714,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_ARM_A7_ROOT_DIV] = imx_clk_divider2("arm_a7_div", "arm_a7_cg", base + 0x8000, 0, 3);
clks[IMX7D_ARM_M4_ROOT_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
clks[IMX7D_ARM_M0_ROOT_DIV] = imx_clk_divider2("arm_m0_div", "arm_m0_cg", base + 0x8100, 0, 3);
clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
@ -793,11 +785,10 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
clks[IMX7D_ARM_A7_ROOT_CLK] = imx_clk_gate4("arm_a7_root_clk", "arm_a7_div", base + 0x4000, 0);
clks[IMX7D_ARM_M4_ROOT_CLK] = imx_clk_gate4("arm_m4_root_clk", "arm_m4_div", base + 0x4010, 0);
clks[IMX7D_ARM_M0_ROOT_CLK] = imx_clk_gate4("arm_m0_root_clk", "arm_m0_div", base + 0x4020, 0);
clks[IMX7D_MAIN_AXI_ROOT_CLK] = imx_clk_gate4("main_axi_root_clk", "axi_post_div", base + 0x4040, 0);
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", "axi_post_div", base + 0x4110, 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);

View File

@ -107,7 +107,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
return ull;
}
static struct clk_ops clk_pllv1_ops = {
static const struct clk_ops clk_pllv1_ops = {
.recalc_rate = clk_pllv1_recalc_rate,
};

View File

@ -227,7 +227,7 @@ static void clk_pllv2_unprepare(struct clk_hw *hw)
__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);
}
static struct clk_ops clk_pllv2_ops = {
static const struct clk_ops clk_pllv2_ops = {
.prepare = clk_pllv2_prepare,
.unprepare = clk_pllv2_unprepare,
.recalc_rate = clk_pllv2_recalc_rate,

View File

@ -50,6 +50,56 @@ config COMMON_CLK_MT2701_BDPSYS
---help---
This driver supports Mediatek MT2701 bdpsys clocks.
config COMMON_CLK_MT2712
bool "Clock driver for Mediatek MT2712"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
---help---
This driver supports Mediatek MT2712 basic clocks.
config COMMON_CLK_MT2712_BDPSYS
bool "Clock driver for Mediatek MT2712 bdpsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 bdpsys clocks.
config COMMON_CLK_MT2712_IMGSYS
bool "Clock driver for Mediatek MT2712 imgsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 imgsys clocks.
config COMMON_CLK_MT2712_JPGDECSYS
bool "Clock driver for Mediatek MT2712 jpgdecsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 jpgdecsys clocks.
config COMMON_CLK_MT2712_MFGCFG
bool "Clock driver for Mediatek MT2712 mfgcfg"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 mfgcfg clocks.
config COMMON_CLK_MT2712_MMSYS
bool "Clock driver for Mediatek MT2712 mmsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 mmsys clocks.
config COMMON_CLK_MT2712_VDECSYS
bool "Clock driver for Mediatek MT2712 vdecsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 vdecsys clocks.
config COMMON_CLK_MT2712_VENCSYS
bool "Clock driver for Mediatek MT2712 vencsys"
depends on COMMON_CLK_MT2712
---help---
This driver supports Mediatek MT2712 vencsys clocks.
config COMMON_CLK_MT6797
bool "Clock driver for Mediatek MT6797"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
@ -82,6 +132,36 @@ config COMMON_CLK_MT6797_VENCSYS
---help---
This driver supports Mediatek MT6797 vencsys clocks.
config COMMON_CLK_MT7622
bool "Clock driver for MediaTek MT7622"
depends on ARCH_MEDIATEK || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
---help---
This driver supports MediaTek MT7622 basic clocks and clocks
required for various periperals found on MediaTek.
config COMMON_CLK_MT7622_ETHSYS
bool "Clock driver for MediaTek MT7622 ETHSYS"
depends on COMMON_CLK_MT7622
---help---
This driver add support for clocks for Ethernet and SGMII
required on MediaTek MT7622 SoC.
config COMMON_CLK_MT7622_HIFSYS
bool "Clock driver for MediaTek MT7622 HIFSYS"
depends on COMMON_CLK_MT7622
---help---
This driver supports MediaTek MT7622 HIFSYS clocks providing
to PCI-E and USB.
config COMMON_CLK_MT7622_AUDSYS
bool "Clock driver for MediaTek MT7622 AUDSYS"
depends on COMMON_CLK_MT7622
---help---
This driver supports MediaTek MT7622 AUDSYS clocks providing
to audio consumers such as I2S and TDM.
config COMMON_CLK_MT8135
bool "Clock driver for Mediatek MT8135"
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST

View File

@ -13,5 +13,17 @@ obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o
obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o
obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o
obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o
obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o
obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o
obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o
obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o
obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o
obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o
obj-$(CONFIG_COMMON_CLK_MT7622_ETHSYS) += clk-mt7622-eth.o
obj-$(CONFIG_COMMON_CLK_MT7622_HIFSYS) += clk-mt7622-hif.o
obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o

View File

@ -750,7 +750,7 @@ static const struct mtk_fixed_factor infra_fixed_divs[] = {
static struct clk_onecell_data *infra_clk_data;
static void mtk_infrasys_init_early(struct device_node *node)
static void __init mtk_infrasys_init_early(struct device_node *node)
{
int r, i;

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt2712-clk.h>
static const struct mtk_gate_regs bdp_cg_regs = {
.set_ofs = 0x100,
.clr_ofs = 0x100,
.sta_ofs = 0x100,
};
#define GATE_BDP(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &bdp_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
static const struct mtk_gate bdp_clks[] = {
GATE_BDP(CLK_BDP_BRIDGE_B, "bdp_bridge_b", "mm_sel", 0),
GATE_BDP(CLK_BDP_BRIDGE_DRAM, "bdp_bridge_d", "mm_sel", 1),
GATE_BDP(CLK_BDP_LARB_DRAM, "bdp_larb_d", "mm_sel", 2),
GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_PXL, "bdp_vdi_pxl", "tvd_sel", 3),
GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_DRAM, "bdp_vdi_d", "mm_sel", 4),
GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_B, "bdp_vdi_b", "mm_sel", 5),
GATE_BDP(CLK_BDP_MT_B, "bdp_fmt_b", "mm_sel", 9),
GATE_BDP(CLK_BDP_DISPFMT_27M, "bdp_27m", "di_sel", 10),
GATE_BDP(CLK_BDP_DISPFMT_27M_VDOUT, "bdp_27m_vdout", "di_sel", 11),
GATE_BDP(CLK_BDP_DISPFMT_27_74_74, "bdp_27_74_74", "di_sel", 12),
GATE_BDP(CLK_BDP_DISPFMT_2FS, "bdp_2fs", "di_sel", 13),
GATE_BDP(CLK_BDP_DISPFMT_2FS_2FS74_148, "bdp_2fs74_148", "di_sel", 14),
GATE_BDP(CLK_BDP_DISPFMT_B, "bdp_b", "mm_sel", 15),
GATE_BDP(CLK_BDP_VDO_DRAM, "bdp_vdo_d", "mm_sel", 16),
GATE_BDP(CLK_BDP_VDO_2FS, "bdp_vdo_2fs", "di_sel", 17),
GATE_BDP(CLK_BDP_VDO_B, "bdp_vdo_b", "mm_sel", 18),
GATE_BDP(CLK_BDP_WR_CHANNEL_DI_PXL, "bdp_di_pxl", "di_sel", 19),
GATE_BDP(CLK_BDP_WR_CHANNEL_DI_DRAM, "bdp_di_d", "mm_sel", 20),
GATE_BDP(CLK_BDP_WR_CHANNEL_DI_B, "bdp_di_b", "mm_sel", 21),
GATE_BDP(CLK_BDP_NR_AGENT, "bdp_nr_agent", "nr_sel", 22),
GATE_BDP(CLK_BDP_NR_DRAM, "bdp_nr_d", "mm_sel", 23),
GATE_BDP(CLK_BDP_NR_B, "bdp_nr_b", "mm_sel", 24),
GATE_BDP(CLK_BDP_BRIDGE_RT_B, "bdp_bridge_rt_b", "mm_sel", 25),
GATE_BDP(CLK_BDP_BRIDGE_RT_DRAM, "bdp_bridge_rt_d", "mm_sel", 26),
GATE_BDP(CLK_BDP_LARB_RT_DRAM, "bdp_larb_rt_d", "mm_sel", 27),
GATE_BDP(CLK_BDP_TVD_TDC, "bdp_tvd_tdc", "mm_sel", 28),
GATE_BDP(CLK_BDP_TVD_54, "bdp_tvd_clk_54", "tvd_sel", 29),
GATE_BDP(CLK_BDP_TVD_CBUS, "bdp_tvd_cbus", "mm_sel", 30),
};
static int clk_mt2712_bdp_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_BDP_NR_CLK);
mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r != 0)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt2712_bdp[] = {
{ .compatible = "mediatek,mt2712-bdpsys", },
{}
};
static struct platform_driver clk_mt2712_bdp_drv = {
.probe = clk_mt2712_bdp_probe,
.driver = {
.name = "clk-mt2712-bdp",
.of_match_table = of_match_clk_mt2712_bdp,
},
};
builtin_platform_driver(clk_mt2712_bdp_drv);

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt2712-clk.h>
static const struct mtk_gate_regs img_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x0,
.sta_ofs = 0x0,
};
#define GATE_IMG(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &img_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
static const struct mtk_gate img_clks[] = {
GATE_IMG(CLK_IMG_SMI_LARB2, "img_smi_larb2", "mm_sel", 0),
GATE_IMG(CLK_IMG_SENINF_SCAM_EN, "img_scam_en", "csi0", 3),
GATE_IMG(CLK_IMG_SENINF_CAM_EN, "img_cam_en", "mm_sel", 8),
GATE_IMG(CLK_IMG_CAM_SV_EN, "img_cam_sv_en", "mm_sel", 9),
GATE_IMG(CLK_IMG_CAM_SV1_EN, "img_cam_sv1_en", "mm_sel", 10),
GATE_IMG(CLK_IMG_CAM_SV2_EN, "img_cam_sv2_en", "mm_sel", 11),
};
static int clk_mt2712_img_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r != 0)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt2712_img[] = {
{ .compatible = "mediatek,mt2712-imgsys", },
{}
};
static struct platform_driver clk_mt2712_img_drv = {
.probe = clk_mt2712_img_probe,
.driver = {
.name = "clk-mt2712-img",
.of_match_table = of_match_clk_mt2712_img,
},
};
builtin_platform_driver(clk_mt2712_img_drv);

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt2712-clk.h>
static const struct mtk_gate_regs jpgdec_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_JPGDEC(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &jpgdec_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
static const struct mtk_gate jpgdec_clks[] = {
GATE_JPGDEC(CLK_JPGDEC_JPGDEC1, "jpgdec_jpgdec1", "jpgdec_sel", 0),
GATE_JPGDEC(CLK_JPGDEC_JPGDEC, "jpgdec_jpgdec", "jpgdec_sel", 4),
};
static int clk_mt2712_jpgdec_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_JPGDEC_NR_CLK);
mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r != 0)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt2712_jpgdec[] = {
{ .compatible = "mediatek,mt2712-jpgdecsys", },
{}
};
static struct platform_driver clk_mt2712_jpgdec_drv = {
.probe = clk_mt2712_jpgdec_probe,
.driver = {
.name = "clk-mt2712-jpgdec",
.of_match_table = of_match_clk_mt2712_jpgdec,
},
};
builtin_platform_driver(clk_mt2712_jpgdec_drv);

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt2712-clk.h>
static const struct mtk_gate_regs mfg_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_MFG(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &mfg_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static const struct mtk_gate mfg_clks[] = {
GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0),
};
static int clk_mt2712_mfg_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r != 0)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt2712_mfg[] = {
{ .compatible = "mediatek,mt2712-mfgcfg", },
{}
};
static struct platform_driver clk_mt2712_mfg_drv = {
.probe = clk_mt2712_mfg_probe,
.driver = {
.name = "clk-mt2712-mfg",
.of_match_table = of_match_clk_mt2712_mfg,
},
};
builtin_platform_driver(clk_mt2712_mfg_drv);

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt2712-clk.h>
static const struct mtk_gate_regs mm0_cg_regs = {
.set_ofs = 0x104,
.clr_ofs = 0x108,
.sta_ofs = 0x100,
};
static const struct mtk_gate_regs mm1_cg_regs = {
.set_ofs = 0x114,
.clr_ofs = 0x118,
.sta_ofs = 0x110,
};
static const struct mtk_gate_regs mm2_cg_regs = {
.set_ofs = 0x224,
.clr_ofs = 0x228,
.sta_ofs = 0x220,
};
#define GATE_MM0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &mm0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_MM1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &mm1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_MM2(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &mm2_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static const struct mtk_gate mm_clks[] = {
/* MM0 */
GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2),
GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3),
GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4),
GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5),
GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6),
GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7),
GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8),
GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9),
GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10),
GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15),
GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16),
GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17),
GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18),
GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20),
GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23),
GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24),
GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27),
GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28),
GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31),
/* MM1 */
GATE_MM1(CLK_MM_DISP_PWM0_MM, "mm_pwm0_mm", "mm_sel", 0),
GATE_MM1(CLK_MM_DISP_PWM0_26M, "mm_pwm0_26m", "pwm_sel", 1),
GATE_MM1(CLK_MM_DISP_PWM1_MM, "mm_pwm1_mm", "mm_sel", 2),
GATE_MM1(CLK_MM_DISP_PWM1_26M, "mm_pwm1_26m", "pwm_sel", 3),
GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4),
GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_lntc", 5),
GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6),
GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_lntc", 7),
GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "vpll_dpix", 8),
GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9),
GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "vpll3_dpix", 10),
GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11),
GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "vpll_dpix", 16),
GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx", 17),
GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18),
GATE_MM1(CLK_MM_SMI_COMMON1, "mm_smi_common1", "mm_sel", 21),
GATE_MM1(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 22),
GATE_MM1(CLK_MM_MDP_RDMA2, "mm_mdp_rdma2", "mm_sel", 23),
GATE_MM1(CLK_MM_MDP_TDSHP2, "mm_mdp_tdshp2", "mm_sel", 24),
GATE_MM1(CLK_MM_DISP_OVL2, "mm_disp_ovl2", "mm_sel", 25),
GATE_MM1(CLK_MM_DISP_WDMA2, "mm_disp_wdma2", "mm_sel", 26),
GATE_MM1(CLK_MM_DISP_COLOR2, "mm_disp_color2", "mm_sel", 27),
GATE_MM1(CLK_MM_DISP_AAL1, "mm_disp_aal1", "mm_sel", 28),
GATE_MM1(CLK_MM_DISP_OD1, "mm_disp_od1", "mm_sel", 29),
GATE_MM1(CLK_MM_LVDS1_PIXEL, "mm_lvds1_pixel", "vpll3_dpix", 30),
GATE_MM1(CLK_MM_LVDS1_CTS, "mm_lvds1_cts", "lvdstx3", 31),
/* MM2 */
GATE_MM2(CLK_MM_SMI_LARB7, "mm_smi_larb7", "mm_sel", 0),
GATE_MM2(CLK_MM_MDP_RDMA3, "mm_mdp_rdma3", "mm_sel", 1),
GATE_MM2(CLK_MM_MDP_WROT2, "mm_mdp_wrot2", "mm_sel", 2),
GATE_MM2(CLK_MM_DSI2, "mm_dsi2", "mm_sel", 3),
GATE_MM2(CLK_MM_DSI2_DIGITAL, "mm_dsi2_digital", "dsi0_lntc", 4),
GATE_MM2(CLK_MM_DSI3, "mm_dsi3", "mm_sel", 5),
GATE_MM2(CLK_MM_DSI3_DIGITAL, "mm_dsi3_digital", "dsi1_lntc", 6),
};
static int clk_mt2712_mm_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r != 0)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt2712_mm[] = {
{ .compatible = "mediatek,mt2712-mmsys", },
{}
};
static struct platform_driver clk_mt2712_mm_drv = {
.probe = clk_mt2712_mm_probe,
.driver = {
.name = "clk-mt2712-mm",
.of_match_table = of_match_clk_mt2712_mm,
},
};
builtin_platform_driver(clk_mt2712_mm_drv);

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt2712-clk.h>
static const struct mtk_gate_regs vdec0_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x4,
.sta_ofs = 0x0,
};
static const struct mtk_gate_regs vdec1_cg_regs = {
.set_ofs = 0x8,
.clr_ofs = 0xc,
.sta_ofs = 0x8,
};
#define GATE_VDEC0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &vdec0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
#define GATE_VDEC1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &vdec1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
static const struct mtk_gate vdec_clks[] = {
/* VDEC0 */
GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
/* VDEC1 */
GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "vdec_sel", 0),
GATE_VDEC1(CLK_VDEC_IMGRZ_CKEN, "vdec_imgrz_cken", "vdec_sel", 1),
};
static int clk_mt2712_vdec_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r != 0)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt2712_vdec[] = {
{ .compatible = "mediatek,mt2712-vdecsys", },
{}
};
static struct platform_driver clk_mt2712_vdec_drv = {
.probe = clk_mt2712_vdec_probe,
.driver = {
.name = "clk-mt2712-vdec",
.of_match_table = of_match_clk_mt2712_vdec,
},
};
builtin_platform_driver(clk_mt2712_vdec_drv);

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt2712-clk.h>
static const struct mtk_gate_regs venc_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_VENC(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &venc_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr_inv, \
}
static const struct mtk_gate venc_clks[] = {
GATE_VENC(CLK_VENC_SMI_COMMON_CON, "venc_smi", "mm_sel", 0),
GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4),
GATE_VENC(CLK_VENC_SMI_LARB6, "venc_smi_larb6", "jpgdec_sel", 12),
};
static int clk_mt2712_venc_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
int r;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r != 0)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
static const struct of_device_id of_match_clk_mt2712_venc[] = {
{ .compatible = "mediatek,mt2712-vencsys", },
{}
};
static struct platform_driver clk_mt2712_venc_drv = {
.probe = clk_mt2712_venc_probe,
.driver = {
.name = "clk-mt2712-venc",
.of_match_table = of_match_clk_mt2712_venc,
},
};
builtin_platform_driver(clk_mt2712_venc_drv);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Chen Zhong <chen.zhong@mediatek.com>
* Sean Wang <sean.wang@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt7622-clk.h>
#define GATE_AUDIO0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO2(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio2_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_AUDIO3(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &audio3_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
static const struct mtk_gate_regs audio0_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x0,
.sta_ofs = 0x0,
};
static const struct mtk_gate_regs audio1_cg_regs = {
.set_ofs = 0x10,
.clr_ofs = 0x10,
.sta_ofs = 0x10,
};
static const struct mtk_gate_regs audio2_cg_regs = {
.set_ofs = 0x14,
.clr_ofs = 0x14,
.sta_ofs = 0x14,
};
static const struct mtk_gate_regs audio3_cg_regs = {
.set_ofs = 0x634,
.clr_ofs = 0x634,
.sta_ofs = 0x634,
};
static const struct mtk_gate audio_clks[] = {
/* AUDIO0 */
GATE_AUDIO0(CLK_AUDIO_AFE, "audio_afe", "rtc", 2),
GATE_AUDIO0(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 20),
GATE_AUDIO0(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 21),
GATE_AUDIO0(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 23),
/* AUDIO1 */
GATE_AUDIO1(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0),
GATE_AUDIO1(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 1),
GATE_AUDIO1(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 2),
GATE_AUDIO1(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 3),
GATE_AUDIO1(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 6),
GATE_AUDIO1(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 7),
GATE_AUDIO1(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 8),
GATE_AUDIO1(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 9),
GATE_AUDIO1(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 12),
GATE_AUDIO1(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 13),
GATE_AUDIO1(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 14),
GATE_AUDIO1(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 15),
GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20),
GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21),
GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22),
/* AUDIO2 */
GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0),
GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1),
GATE_AUDIO2(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 2),
GATE_AUDIO2(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 3),
GATE_AUDIO2(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 4),
GATE_AUDIO2(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 5),
GATE_AUDIO2(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 6),
GATE_AUDIO2(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 7),
GATE_AUDIO2(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 8),
GATE_AUDIO2(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 9),
GATE_AUDIO2(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 10),
GATE_AUDIO2(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 11),
GATE_AUDIO2(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 12),
GATE_AUDIO2(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 13),
GATE_AUDIO2(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 14),
GATE_AUDIO2(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 15),
GATE_AUDIO2(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 16),
GATE_AUDIO2(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 17),
/* AUDIO3 */
GATE_AUDIO3(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 2),
GATE_AUDIO3(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 3),
GATE_AUDIO3(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 6),
GATE_AUDIO3(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 7),
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10),
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11),
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12),
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13),
GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14),
};
static int clk_mt7622_audiosys_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK);
mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static const struct of_device_id of_match_clk_mt7622_aud[] = {
{
.compatible = "mediatek,mt7622-audsys",
.data = clk_mt7622_audiosys_init,
}, {
/* sentinel */
}
};
static int clk_mt7622_aud_probe(struct platform_device *pdev)
{
int (*clk_init)(struct platform_device *);
int r;
clk_init = of_device_get_match_data(&pdev->dev);
if (!clk_init)
return -EINVAL;
r = clk_init(pdev);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static struct platform_driver clk_mt7622_aud_drv = {
.probe = clk_mt7622_aud_probe,
.driver = {
.name = "clk-mt7622-aud",
.of_match_table = of_match_clk_mt7622_aud,
},
};
builtin_platform_driver(clk_mt7622_aud_drv);

View File

@ -0,0 +1,156 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Chen Zhong <chen.zhong@mediatek.com>
* Sean Wang <sean.wang@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt7622-clk.h>
#define GATE_ETH(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &eth_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate_regs eth_cg_regs = {
.set_ofs = 0x30,
.clr_ofs = 0x30,
.sta_ofs = 0x30,
};
static const struct mtk_gate eth_clks[] = {
GATE_ETH(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 5),
GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 6),
GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7),
GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8),
GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9),
};
static const struct mtk_gate_regs sgmii_cg_regs = {
.set_ofs = 0xE4,
.clr_ofs = 0xE4,
.sta_ofs = 0xE4,
};
#define GATE_SGMII(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &sgmii_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate sgmii_clks[] = {
GATE_SGMII(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en",
"ssusb_tx250m", 2),
GATE_SGMII(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en",
"ssusb_eq_rx250m", 3),
GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref",
"ssusb_cdr_ref", 4),
GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb",
"ssusb_cdr_fb", 5),
};
static int clk_mt7622_ethsys_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
mtk_register_reset_controller(node, 1, 0x34);
return r;
}
static int clk_mt7622_sgmiisys_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static const struct of_device_id of_match_clk_mt7622_eth[] = {
{
.compatible = "mediatek,mt7622-ethsys",
.data = clk_mt7622_ethsys_init,
}, {
.compatible = "mediatek,mt7622-sgmiisys",
.data = clk_mt7622_sgmiisys_init,
}, {
/* sentinel */
}
};
static int clk_mt7622_eth_probe(struct platform_device *pdev)
{
int (*clk_init)(struct platform_device *);
int r;
clk_init = of_device_get_match_data(&pdev->dev);
if (!clk_init)
return -EINVAL;
r = clk_init(pdev);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static struct platform_driver clk_mt7622_eth_drv = {
.probe = clk_mt7622_eth_probe,
.driver = {
.name = "clk-mt7622-eth",
.of_match_table = of_match_clk_mt7622_eth,
},
};
builtin_platform_driver(clk_mt7622_eth_drv);

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Chen Zhong <chen.zhong@mediatek.com>
* Sean Wang <sean.wang@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt7622-clk.h>
#define GATE_PCIE(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &pcie_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
#define GATE_SSUSB(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &ssusb_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
static const struct mtk_gate_regs pcie_cg_regs = {
.set_ofs = 0x30,
.clr_ofs = 0x30,
.sta_ofs = 0x30,
};
static const struct mtk_gate_regs ssusb_cg_regs = {
.set_ofs = 0x30,
.clr_ofs = 0x30,
.sta_ofs = 0x30,
};
static const struct mtk_gate ssusb_clks[] = {
GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p",
"to_u2_phy_1p", 0),
GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1),
GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5),
GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6),
GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 7),
GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 8),
};
static const struct mtk_gate pcie_clks[] = {
GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12),
GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13),
GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 14),
GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 15),
GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16),
GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17),
GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18),
GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19),
GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 20),
GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 21),
GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22),
GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23),
GATE_PCIE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 26),
GATE_PCIE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 27),
GATE_PCIE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 28),
GATE_PCIE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 29),
GATE_PCIE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 30),
};
static int clk_mt7622_ssusbsys_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK);
mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
mtk_register_reset_controller(node, 1, 0x34);
return r;
}
static int clk_mt7622_pciesys_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK);
mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
mtk_register_reset_controller(node, 1, 0x34);
return r;
}
static const struct of_device_id of_match_clk_mt7622_hif[] = {
{
.compatible = "mediatek,mt7622-pciesys",
.data = clk_mt7622_pciesys_init,
}, {
.compatible = "mediatek,mt7622-ssusbsys",
.data = clk_mt7622_ssusbsys_init,
}, {
/* sentinel */
}
};
static int clk_mt7622_hif_probe(struct platform_device *pdev)
{
int (*clk_init)(struct platform_device *);
int r;
clk_init = of_device_get_match_data(&pdev->dev);
if (!clk_init)
return -EINVAL;
r = clk_init(pdev);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static struct platform_driver clk_mt7622_hif_drv = {
.probe = clk_mt7622_hif_probe,
.driver = {
.name = "clk-mt7622-hif",
.of_match_table = of_match_clk_mt7622_hif,
},
};
builtin_platform_driver(clk_mt7622_hif_drv);

View File

@ -0,0 +1,780 @@
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: Chen Zhong <chen.zhong@mediatek.com>
* Sean Wang <sean.wang@mediatek.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include "clk-cpumux.h"
#include <dt-bindings/clock/mt7622-clk.h>
#include <linux/clk.h> /* for consumer */
#define MT7622_PLL_FMAX (2500UL * MHZ)
#define CON0_MT7622_RST_BAR BIT(27)
#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
_pcw_shift, _div_table, _parent_name) { \
.id = _id, \
.name = _name, \
.reg = _reg, \
.pwr_reg = _pwr_reg, \
.en_mask = _en_mask, \
.flags = _flags, \
.rst_bar_mask = CON0_MT7622_RST_BAR, \
.fmax = MT7622_PLL_FMAX, \
.pcwbits = _pcwbits, \
.pd_reg = _pd_reg, \
.pd_shift = _pd_shift, \
.tuner_reg = _tuner_reg, \
.pcw_reg = _pcw_reg, \
.pcw_shift = _pcw_shift, \
.div_table = _div_table, \
.parent_name = _parent_name, \
}
#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \
_pcw_shift) \
PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\
_pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
NULL, "clkxtal")
#define GATE_APMIXED(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &apmixed_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr_inv, \
}
#define GATE_INFRA(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &infra_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_TOP0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &top0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_TOP1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &top1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
#define GATE_PERI0(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &peri0_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
#define GATE_PERI1(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &peri1_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_setclr, \
}
static DEFINE_SPINLOCK(mt7622_clk_lock);
static const char * const infra_mux1_parents[] = {
"clkxtal",
"armpll",
"main_core_en",
"armpll"
};
static const char * const axi_parents[] = {
"clkxtal",
"syspll1_d2",
"syspll_d5",
"syspll1_d4",
"univpll_d5",
"univpll2_d2",
"univpll_d7"
};
static const char * const mem_parents[] = {
"clkxtal",
"dmpll_ck"
};
static const char * const ddrphycfg_parents[] = {
"clkxtal",
"syspll1_d8"
};
static const char * const eth_parents[] = {
"clkxtal",
"syspll1_d2",
"univpll1_d2",
"syspll1_d4",
"univpll_d5",
"clk_null",
"univpll_d7"
};
static const char * const pwm_parents[] = {
"clkxtal",
"univpll2_d4"
};
static const char * const f10m_ref_parents[] = {
"clkxtal",
"syspll4_d16"
};
static const char * const nfi_infra_parents[] = {
"clkxtal",
"clkxtal",
"clkxtal",
"clkxtal",
"clkxtal",
"clkxtal",
"clkxtal",
"clkxtal",
"univpll2_d8",
"syspll1_d8",
"univpll1_d8",
"syspll4_d2",
"univpll2_d4",
"univpll3_d2",
"syspll1_d4"
};
static const char * const flash_parents[] = {
"clkxtal",
"univpll_d80_d4",
"syspll2_d8",
"syspll3_d4",
"univpll3_d4",
"univpll1_d8",
"syspll2_d4",
"univpll2_d4"
};
static const char * const uart_parents[] = {
"clkxtal",
"univpll2_d8"
};
static const char * const spi0_parents[] = {
"clkxtal",
"syspll3_d2",
"clkxtal",
"syspll2_d4",
"syspll4_d2",
"univpll2_d4",
"univpll1_d8",
"clkxtal"
};
static const char * const spi1_parents[] = {
"clkxtal",
"syspll3_d2",
"clkxtal",
"syspll4_d4",
"syspll4_d2",
"univpll2_d4",
"univpll1_d8",
"clkxtal"
};
static const char * const msdc30_0_parents[] = {
"clkxtal",
"univpll2_d16",
"univ48m"
};
static const char * const a1sys_hp_parents[] = {
"clkxtal",
"aud1pll_ck",
"aud2pll_ck",
"clkxtal"
};
static const char * const intdir_parents[] = {
"clkxtal",
"syspll_d2",
"univpll_d2",
"sgmiipll_ck"
};
static const char * const aud_intbus_parents[] = {
"clkxtal",
"syspll1_d4",
"syspll4_d2",
"syspll3_d2"
};
static const char * const pmicspi_parents[] = {
"clkxtal",
"clk_null",
"clk_null",
"clk_null",
"clk_null",
"univpll2_d16"
};
static const char * const atb_parents[] = {
"clkxtal",
"syspll1_d2",
"syspll_d5"
};
static const char * const audio_parents[] = {
"clkxtal",
"syspll3_d4",
"syspll4_d4",
"univpll1_d16"
};
static const char * const usb20_parents[] = {
"clkxtal",
"univpll3_d4",
"syspll1_d8",
"clkxtal"
};
static const char * const aud1_parents[] = {
"clkxtal",
"aud1pll_ck"
};
static const char * const aud2_parents[] = {
"clkxtal",
"aud2pll_ck"
};
static const char * const asm_l_parents[] = {
"clkxtal",
"syspll_d5",
"univpll2_d2",
"univpll2_d4"
};
static const char * const apll1_ck_parents[] = {
"aud1_sel",
"aud2_sel"
};
static const char * const peribus_ck_parents[] = {
"syspll1_d8",
"syspll1_d4"
};
static const struct mtk_gate_regs apmixed_cg_regs = {
.set_ofs = 0x8,
.clr_ofs = 0x8,
.sta_ofs = 0x8,
};
static const struct mtk_gate_regs infra_cg_regs = {
.set_ofs = 0x40,
.clr_ofs = 0x44,
.sta_ofs = 0x48,
};
static const struct mtk_gate_regs top0_cg_regs = {
.set_ofs = 0x120,
.clr_ofs = 0x120,
.sta_ofs = 0x120,
};
static const struct mtk_gate_regs top1_cg_regs = {
.set_ofs = 0x128,
.clr_ofs = 0x128,
.sta_ofs = 0x128,
};
static const struct mtk_gate_regs peri0_cg_regs = {
.set_ofs = 0x8,
.clr_ofs = 0x10,
.sta_ofs = 0x18,
};
static const struct mtk_gate_regs peri1_cg_regs = {
.set_ofs = 0xC,
.clr_ofs = 0x14,
.sta_ofs = 0x1C,
};
static const struct mtk_pll_data plls[] = {
PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x00000001,
PLL_AO, 21, 0x0204, 24, 0, 0x0204, 0),
PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0x00000001,
HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0),
PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0x00000001,
HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14),
PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0x00000001,
0, 21, 0x0300, 1, 0, 0x0304, 0),
PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0x00000001,
0, 21, 0x0314, 1, 0, 0x0318, 0),
PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0x00000001,
0, 31, 0x0324, 1, 0, 0x0328, 0),
PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0x00000001,
0, 31, 0x0334, 1, 0, 0x0338, 0),
PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0x00000001,
0, 21, 0x0344, 1, 0, 0x0348, 0),
PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0x00000001,
0, 21, 0x0358, 1, 0, 0x035C, 0),
};
static const struct mtk_gate apmixed_clks[] = {
GATE_APMIXED(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5),
};
static const struct mtk_gate infra_clks[] = {
GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0),
GATE_INFRA(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 2),
GATE_INFRA(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 5),
GATE_INFRA(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 16),
GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 18),
GATE_INFRA(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 22),
};
static const struct mtk_fixed_clk top_fixed_clks[] = {
FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal",
31250000),
FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal",
31250000),
FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal",
125000000),
FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal",
125000000),
FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal",
250000000),
FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal",
250000000),
FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal",
33333333),
FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal",
50000000),
FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal",
50000000),
FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal",
50000000),
};
static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4),
FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500),
FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125),
FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500),
FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1),
FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024),
FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1),
FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1),
FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4),
FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8),
FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16),
FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12),
FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24),
FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10),
FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20),
FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14),
FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28),
FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112),
FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2),
FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4),
FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8),
FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16),
FACTOR(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32),
FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6),
FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12),
FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24),
FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48),
FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10),
FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20),
FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80),
FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320),
FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25),
FACTOR(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1),
FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2),
FACTOR(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1),
FACTOR(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1),
FACTOR(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2),
FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4),
FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1),
FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1),
FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1),
};
static const struct mtk_gate top_clks[] = {
/* TOP0 */
GATE_TOP0(CLK_TOP_APLL1_DIV_PD, "apll1_ck_div_pd", "apll1_ck_div", 0),
GATE_TOP0(CLK_TOP_APLL2_DIV_PD, "apll2_ck_div_pd", "apll2_ck_div", 1),
GATE_TOP0(CLK_TOP_I2S0_MCK_DIV_PD, "i2s0_mck_div_pd", "i2s0_mck_div",
2),
GATE_TOP0(CLK_TOP_I2S1_MCK_DIV_PD, "i2s1_mck_div_pd", "i2s1_mck_div",
3),
GATE_TOP0(CLK_TOP_I2S2_MCK_DIV_PD, "i2s2_mck_div_pd", "i2s2_mck_div",
4),
GATE_TOP0(CLK_TOP_I2S3_MCK_DIV_PD, "i2s3_mck_div_pd", "i2s3_mck_div",
5),
/* TOP1 */
GATE_TOP1(CLK_TOP_A1SYS_HP_DIV_PD, "a1sys_div_pd", "a1sys_div", 0),
GATE_TOP1(CLK_TOP_A2SYS_HP_DIV_PD, "a2sys_div_pd", "a2sys_div", 16),
};
static const struct mtk_clk_divider top_adj_divs[] = {
DIV_ADJ(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_sel",
0x120, 24, 3),
DIV_ADJ(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_sel",
0x120, 28, 3),
DIV_ADJ(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_sel",
0x124, 0, 7),
DIV_ADJ(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_sel",
0x124, 8, 7),
DIV_ADJ(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "aud_i2s2_mck",
0x124, 16, 7),
DIV_ADJ(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_sel",
0x124, 24, 7),
DIV_ADJ(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel",
0x128, 8, 7),
DIV_ADJ(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel",
0x128, 24, 7),
};
static const struct mtk_gate peri_clks[] = {
/* PERI0 */
GATE_PERI0(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", 1),
GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", 2),
GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", 3),
GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", 4),
GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", 5),
GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", 6),
GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", 7),
GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", 8),
GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", 9),
GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", 12),
GATE_PERI0(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", 13),
GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", 14),
GATE_PERI0(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", 17),
GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", 18),
GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", 19),
GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", 20),
GATE_PERI0(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", 21),
GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", 22),
GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", 23),
GATE_PERI0(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", 24),
GATE_PERI0(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", 25),
GATE_PERI0(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", 26),
GATE_PERI0(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", 27),
GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", 28),
GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "nfi_infra_sel", 29),
GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", 30),
GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", 31),
/* PERI1 */
GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", 1),
GATE_PERI1(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", 2),
};
static struct mtk_composite infra_muxes[] __initdata = {
MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents,
0x000, 2, 2),
};
static struct mtk_composite top_muxes[] = {
/* CLK_CFG_0 */
MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents,
0x040, 0, 3, 7),
MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents,
0x040, 8, 1, 15),
MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents,
0x040, 16, 1, 23),
MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents,
0x040, 24, 3, 31),
/* CLK_CFG_1 */
MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents,
0x050, 0, 2, 7),
MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents,
0x050, 8, 1, 15),
MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents,
0x050, 16, 4, 23),
MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents,
0x050, 24, 3, 31),
/* CLK_CFG_2 */
MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents,
0x060, 0, 1, 7),
MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents,
0x060, 8, 3, 15),
MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents,
0x060, 16, 3, 23),
MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents,
0x060, 24, 3, 31),
/* CLK_CFG_3 */
MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents,
0x070, 0, 3, 7),
MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_0_parents,
0x070, 8, 3, 15),
MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", a1sys_hp_parents,
0x070, 16, 2, 23),
MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", a1sys_hp_parents,
0x070, 24, 2, 31),
/* CLK_CFG_4 */
MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents,
0x080, 0, 2, 7),
MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents,
0x080, 8, 2, 15),
MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents,
0x080, 16, 3, 23),
MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", ddrphycfg_parents,
0x080, 24, 2, 31),
/* CLK_CFG_5 */
MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents,
0x090, 0, 2, 7),
MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", eth_parents,
0x090, 8, 3, 15),
MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents,
0x090, 16, 2, 23),
MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents,
0x090, 24, 2, 31),
/* CLK_CFG_6 */
MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents,
0x0A0, 0, 1, 7),
MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents,
0x0A0, 8, 1, 15),
MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", f10m_ref_parents,
0x0A0, 16, 1, 23),
MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", f10m_ref_parents,
0x0A0, 24, 1, 31),
/* CLK_CFG_7 */
MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", asm_l_parents,
0x0B0, 0, 2, 7),
MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_l_parents,
0x0B0, 8, 2, 15),
MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_l_parents,
0x0B0, 16, 2, 23),
/* CLK_AUDDIV_0 */
MUX(CLK_TOP_APLL1_SEL, "apll1_ck_sel", apll1_ck_parents,
0x120, 6, 1),
MUX(CLK_TOP_APLL2_SEL, "apll2_ck_sel", apll1_ck_parents,
0x120, 7, 1),
MUX(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", apll1_ck_parents,
0x120, 8, 1),
MUX(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", apll1_ck_parents,
0x120, 9, 1),
MUX(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", apll1_ck_parents,
0x120, 10, 1),
MUX(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", apll1_ck_parents,
0x120, 11, 1),
};
static struct mtk_composite peri_muxes[] = {
/* PERI_GLOBALCON_CKSEL */
MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1),
};
static int mtk_topckgen_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
void __iomem *base;
struct device_node *node = pdev->dev.of_node;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs),
clk_data);
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes),
base, &mt7622_clk_lock, clk_data);
mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs),
base, &mt7622_clk_lock, clk_data);
mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks),
clk_data);
clk_prepare_enable(clk_data->clks[CLK_TOP_AXI_SEL]);
clk_prepare_enable(clk_data->clks[CLK_TOP_MEM_SEL]);
clk_prepare_enable(clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static int __init mtk_infrasys_init(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct clk_onecell_data *clk_data;
int r;
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
clk_data);
mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get,
clk_data);
if (r)
return r;
mtk_register_reset_controller(node, 1, 0x30);
return 0;
}
static int mtk_apmixedsys_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls),
clk_data);
mtk_clk_register_gates(node, apmixed_clks,
ARRAY_SIZE(apmixed_clks), clk_data);
clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMPLL]);
clk_prepare_enable(clk_data->clks[CLK_APMIXED_MAIN_CORE_EN]);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static int mtk_pericfg_init(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
void __iomem *base;
int r;
struct device_node *node = pdev->dev.of_node;
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
clk_data);
mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base,
&mt7622_clk_lock, clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
return r;
clk_prepare_enable(clk_data->clks[CLK_PERI_UART0_PD]);
mtk_register_reset_controller(node, 2, 0x0);
return 0;
}
static const struct of_device_id of_match_clk_mt7622[] = {
{
.compatible = "mediatek,mt7622-apmixedsys",
.data = mtk_apmixedsys_init,
}, {
.compatible = "mediatek,mt7622-infracfg",
.data = mtk_infrasys_init,
}, {
.compatible = "mediatek,mt7622-topckgen",
.data = mtk_topckgen_init,
}, {
.compatible = "mediatek,mt7622-pericfg",
.data = mtk_pericfg_init,
}, {
/* sentinel */
}
};
static int clk_mt7622_probe(struct platform_device *pdev)
{
int (*clk_init)(struct platform_device *);
int r;
clk_init = of_device_get_match_data(&pdev->dev);
if (!clk_init)
return -EINVAL;
r = clk_init(pdev);
if (r)
dev_err(&pdev->dev,
"could not register clock provider: %s: %d\n",
pdev->name, r);
return r;
}
static struct platform_driver clk_mt7622_drv = {
.probe = clk_mt7622_probe,
.driver = {
.name = "clk-mt7622",
.of_match_table = of_match_clk_mt7622,
},
};
static int clk_mt7622_init(void)
{
return platform_driver_register(&clk_mt7622_drv);
}
arch_initcall(clk_mt7622_init);

View File

@ -207,6 +207,8 @@ struct mtk_pll_data {
uint32_t en_mask;
uint32_t pd_reg;
uint32_t tuner_reg;
uint32_t tuner_en_reg;
uint8_t tuner_en_bit;
int pd_shift;
unsigned int flags;
const struct clk_ops *ops;
@ -216,6 +218,7 @@ struct mtk_pll_data {
uint32_t pcw_reg;
int pcw_shift;
const struct mtk_pll_div_table *div_table;
const char *parent_name;
};
void mtk_clk_register_plls(struct device_node *node,

View File

@ -47,6 +47,7 @@ struct mtk_clk_pll {
void __iomem *pd_addr;
void __iomem *pwr_addr;
void __iomem *tuner_addr;
void __iomem *tuner_en_addr;
void __iomem *pcw_addr;
const struct mtk_pll_data *data;
};
@ -227,7 +228,10 @@ static int mtk_pll_prepare(struct clk_hw *hw)
r |= pll->data->en_mask;
writel(r, pll->base_addr + REG_CON0);
if (pll->tuner_addr) {
if (pll->tuner_en_addr) {
r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit);
writel(r, pll->tuner_en_addr);
} else if (pll->tuner_addr) {
r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN;
writel(r, pll->tuner_addr);
}
@ -254,7 +258,10 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
writel(r, pll->base_addr + REG_CON0);
}
if (pll->tuner_addr) {
if (pll->tuner_en_addr) {
r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit);
writel(r, pll->tuner_en_addr);
} else if (pll->tuner_addr) {
r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN;
writel(r, pll->tuner_addr);
}
@ -297,13 +304,18 @@ static struct clk *mtk_clk_register_pll(const struct mtk_pll_data *data,
pll->pcw_addr = base + data->pcw_reg;
if (data->tuner_reg)
pll->tuner_addr = base + data->tuner_reg;
if (data->tuner_en_reg)
pll->tuner_en_addr = base + data->tuner_en_reg;
pll->hw.init = &init;
pll->data = data;
init.name = data->name;
init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
init.ops = &mtk_pll_ops;
init.parent_names = &parent_name;
if (data->parent_name)
init.parent_names = &data->parent_name;
else
init.parent_names = &parent_name;
init.num_parents = 1;
clk = clk_register(NULL, &pll->hw);

View File

@ -1131,6 +1131,253 @@ static struct clk_gate gxbb_sd_emmc_c_clk0 = {
},
};
/* VPU Clock */
static u32 mux_table_vpu[] = {0, 1, 2, 3};
static const char * const gxbb_vpu_parent_names[] = {
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
};
static struct clk_mux gxbb_vpu_0_sel = {
.reg = (void *)HHI_VPU_CLK_CNTL,
.mask = 0x3,
.shift = 9,
.lock = &clk_lock,
.table = mux_table_vpu,
.hw.init = &(struct clk_init_data){
.name = "vpu_0_sel",
.ops = &clk_mux_ops,
/*
* bits 9:10 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
.parent_names = gxbb_vpu_parent_names,
.num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
static struct clk_divider gxbb_vpu_0_div = {
.reg = (void *)HHI_VPU_CLK_CNTL,
.shift = 0,
.width = 7,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vpu_0_div",
.ops = &clk_divider_ops,
.parent_names = (const char *[]){ "vpu_0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_gate gxbb_vpu_0 = {
.reg = (void *)HHI_VPU_CLK_CNTL,
.bit_idx = 8,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data) {
.name = "vpu_0",
.ops = &clk_gate_ops,
.parent_names = (const char *[]){ "vpu_0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
static struct clk_mux gxbb_vpu_1_sel = {
.reg = (void *)HHI_VPU_CLK_CNTL,
.mask = 0x3,
.shift = 25,
.lock = &clk_lock,
.table = mux_table_vpu,
.hw.init = &(struct clk_init_data){
.name = "vpu_1_sel",
.ops = &clk_mux_ops,
/*
* bits 25:26 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
.parent_names = gxbb_vpu_parent_names,
.num_parents = ARRAY_SIZE(gxbb_vpu_parent_names),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
static struct clk_divider gxbb_vpu_1_div = {
.reg = (void *)HHI_VPU_CLK_CNTL,
.shift = 16,
.width = 7,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vpu_1_div",
.ops = &clk_divider_ops,
.parent_names = (const char *[]){ "vpu_1_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_gate gxbb_vpu_1 = {
.reg = (void *)HHI_VPU_CLK_CNTL,
.bit_idx = 24,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data) {
.name = "vpu_1",
.ops = &clk_gate_ops,
.parent_names = (const char *[]){ "vpu_1_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
static struct clk_mux gxbb_vpu = {
.reg = (void *)HHI_VPU_CLK_CNTL,
.mask = 1,
.shift = 31,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vpu",
.ops = &clk_mux_ops,
/*
* bit 31 selects from 2 possible parents:
* vpu_0 or vpu_1
*/
.parent_names = (const char *[]){ "vpu_0", "vpu_1" },
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
/* VAPB Clock */
static u32 mux_table_vapb[] = {0, 1, 2, 3};
static const char * const gxbb_vapb_parent_names[] = {
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7"
};
static struct clk_mux gxbb_vapb_0_sel = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.mask = 0x3,
.shift = 9,
.lock = &clk_lock,
.table = mux_table_vapb,
.hw.init = &(struct clk_init_data){
.name = "vapb_0_sel",
.ops = &clk_mux_ops,
/*
* bits 9:10 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
.parent_names = gxbb_vapb_parent_names,
.num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
static struct clk_divider gxbb_vapb_0_div = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.shift = 0,
.width = 7,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vapb_0_div",
.ops = &clk_divider_ops,
.parent_names = (const char *[]){ "vapb_0_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_gate gxbb_vapb_0 = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.bit_idx = 8,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data) {
.name = "vapb_0",
.ops = &clk_gate_ops,
.parent_names = (const char *[]){ "vapb_0_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
static struct clk_mux gxbb_vapb_1_sel = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.mask = 0x3,
.shift = 25,
.lock = &clk_lock,
.table = mux_table_vapb,
.hw.init = &(struct clk_init_data){
.name = "vapb_1_sel",
.ops = &clk_mux_ops,
/*
* bits 25:26 selects from 4 possible parents:
* fclk_div4, fclk_div3, fclk_div5, fclk_div7,
*/
.parent_names = gxbb_vapb_parent_names,
.num_parents = ARRAY_SIZE(gxbb_vapb_parent_names),
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
static struct clk_divider gxbb_vapb_1_div = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.shift = 16,
.width = 7,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vapb_1_div",
.ops = &clk_divider_ops,
.parent_names = (const char *[]){ "vapb_1_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_gate gxbb_vapb_1 = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.bit_idx = 24,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data) {
.name = "vapb_1",
.ops = &clk_gate_ops,
.parent_names = (const char *[]){ "vapb_1_div" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
static struct clk_mux gxbb_vapb_sel = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.mask = 1,
.shift = 31,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data){
.name = "vapb_sel",
.ops = &clk_mux_ops,
/*
* bit 31 selects from 2 possible parents:
* vapb_0 or vapb_1
*/
.parent_names = (const char *[]){ "vapb_0", "vapb_1" },
.num_parents = 2,
.flags = CLK_SET_RATE_NO_REPARENT,
},
};
static struct clk_gate gxbb_vapb = {
.reg = (void *)HHI_VAPBCLK_CNTL,
.bit_idx = 30,
.lock = &clk_lock,
.hw.init = &(struct clk_init_data) {
.name = "vapb",
.ops = &clk_gate_ops,
.parent_names = (const char *[]){ "vapb_sel" },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
},
};
/* Everything Else (EE) domain gates */
static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
@ -1349,6 +1596,21 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
[CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw,
[CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw,
[CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw,
[CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw,
[CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw,
[CLKID_VPU_0] = &gxbb_vpu_0.hw,
[CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw,
[CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw,
[CLKID_VPU_1] = &gxbb_vpu_1.hw,
[CLKID_VPU] = &gxbb_vpu.hw,
[CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw,
[CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw,
[CLKID_VAPB_0] = &gxbb_vapb_0.hw,
[CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw,
[CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw,
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
[CLKID_VAPB] = &gxbb_vapb.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
@ -1481,6 +1743,21 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
[CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw,
[CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw,
[CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw,
[CLKID_VPU_0_SEL] = &gxbb_vpu_0_sel.hw,
[CLKID_VPU_0_DIV] = &gxbb_vpu_0_div.hw,
[CLKID_VPU_0] = &gxbb_vpu_0.hw,
[CLKID_VPU_1_SEL] = &gxbb_vpu_1_sel.hw,
[CLKID_VPU_1_DIV] = &gxbb_vpu_1_div.hw,
[CLKID_VPU_1] = &gxbb_vpu_1.hw,
[CLKID_VPU] = &gxbb_vpu.hw,
[CLKID_VAPB_0_SEL] = &gxbb_vapb_0_sel.hw,
[CLKID_VAPB_0_DIV] = &gxbb_vapb_0_div.hw,
[CLKID_VAPB_0] = &gxbb_vapb_0.hw,
[CLKID_VAPB_1_SEL] = &gxbb_vapb_1_sel.hw,
[CLKID_VAPB_1_DIV] = &gxbb_vapb_1_div.hw,
[CLKID_VAPB_1] = &gxbb_vapb_1.hw,
[CLKID_VAPB_SEL] = &gxbb_vapb_sel.hw,
[CLKID_VAPB] = &gxbb_vapb.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
@ -1600,6 +1877,11 @@ static struct clk_gate *const gxbb_clk_gates[] = {
&gxbb_sd_emmc_a_clk0,
&gxbb_sd_emmc_b_clk0,
&gxbb_sd_emmc_c_clk0,
&gxbb_vpu_0,
&gxbb_vpu_1,
&gxbb_vapb_0,
&gxbb_vapb_1,
&gxbb_vapb,
};
static struct clk_mux *const gxbb_clk_muxes[] = {
@ -1615,6 +1897,12 @@ static struct clk_mux *const gxbb_clk_muxes[] = {
&gxbb_sd_emmc_a_clk0_sel,
&gxbb_sd_emmc_b_clk0_sel,
&gxbb_sd_emmc_c_clk0_sel,
&gxbb_vpu_0_sel,
&gxbb_vpu_1_sel,
&gxbb_vpu,
&gxbb_vapb_0_sel,
&gxbb_vapb_1_sel,
&gxbb_vapb_sel,
};
static struct clk_divider *const gxbb_clk_dividers[] = {
@ -1627,6 +1915,10 @@ static struct clk_divider *const gxbb_clk_dividers[] = {
&gxbb_sd_emmc_a_clk0_div,
&gxbb_sd_emmc_b_clk0_div,
&gxbb_sd_emmc_c_clk0_div,
&gxbb_vpu_0_div,
&gxbb_vpu_1_div,
&gxbb_vapb_0_div,
&gxbb_vapb_1_div,
};
static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {

View File

@ -190,8 +190,12 @@
#define CLKID_SD_EMMC_B_CLK0_DIV 121
#define CLKID_SD_EMMC_C_CLK0_SEL 123
#define CLKID_SD_EMMC_C_CLK0_DIV 124
#define CLKID_VPU_0_DIV 127
#define CLKID_VPU_1_DIV 130
#define CLKID_VAPB_0_DIV 134
#define CLKID_VAPB_1_DIV 137
#define NR_CLKS 126
#define NR_CLKS 141
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/gxbb-clkc.h>

View File

@ -114,7 +114,7 @@ static void clk_apbc_unprepare(struct clk_hw *hw)
spin_unlock_irqrestore(apbc->lock, flags);
}
static struct clk_ops clk_apbc_ops = {
static const struct clk_ops clk_apbc_ops = {
.prepare = clk_apbc_prepare,
.unprepare = clk_apbc_unprepare,
};

View File

@ -60,7 +60,7 @@ static void clk_apmu_disable(struct clk_hw *hw)
spin_unlock_irqrestore(apmu->lock, flags);
}
static struct clk_ops clk_apmu_ops = {
static const struct clk_ops clk_apmu_ops = {
.enable = clk_apmu_enable,
.disable = clk_apmu_disable,
};

View File

@ -149,7 +149,7 @@ static void clk_factor_init(struct clk_hw *hw)
spin_unlock_irqrestore(factor->lock, flags);
}
static struct clk_ops clk_factor_ops = {
static const struct clk_ops clk_factor_ops = {
.recalc_rate = clk_factor_recalc_rate,
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
@ -172,10 +172,8 @@ struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
}
factor = kzalloc(sizeof(*factor), GFP_KERNEL);
if (!factor) {
pr_err("%s: could not allocate factor clk\n", __func__);
if (!factor)
return ERR_PTR(-ENOMEM);
}
/* struct clk_aux assignments */
factor->base = base;

View File

@ -103,10 +103,8 @@ struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
/* allocate the gate */
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate) {
pr_err("%s:%s could not allocate gate clk\n", __func__, name);
if (!gate)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &mmp_clk_gate_ops;

View File

@ -229,7 +229,7 @@ static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
parent_rate = clk_hw_get_rate(parent);
mix_rate = parent_rate / item->divisor;
gap = abs(mix_rate - req->rate);
if (parent_best == NULL || gap < gap_best) {
if (!parent_best || gap < gap_best) {
parent_best = parent;
parent_rate_best = parent_rate;
mix_rate_best = mix_rate;
@ -247,7 +247,7 @@ static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
div = _get_div(mix, j);
mix_rate = parent_rate / div;
gap = abs(mix_rate - req->rate);
if (parent_best == NULL || gap < gap_best) {
if (!parent_best || gap < gap_best) {
parent_best = parent;
parent_rate_best = parent_rate;
mix_rate_best = mix_rate;
@ -451,11 +451,8 @@ struct clk *mmp_clk_register_mix(struct device *dev,
size_t table_bytes;
mix = kzalloc(sizeof(*mix), GFP_KERNEL);
if (!mix) {
pr_err("%s:%s: could not allocate mmp mix clk\n",
__func__, name);
if (!mix)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.flags = flags | CLK_GET_RATE_NOCACHE;
@ -467,12 +464,9 @@ struct clk *mmp_clk_register_mix(struct device *dev,
if (config->table) {
table_bytes = sizeof(*config->table) * config->table_size;
mix->table = kmemdup(config->table, table_bytes, GFP_KERNEL);
if (!mix->table) {
pr_err("%s:%s: could not allocate mmp mix table\n",
__func__, name);
kfree(mix);
return ERR_PTR(-ENOMEM);
}
if (!mix->table)
goto free_mix;
mix->table_size = config->table_size;
}
@ -481,11 +475,8 @@ struct clk *mmp_clk_register_mix(struct device *dev,
mix->mux_table = kmemdup(config->mux_table, table_bytes,
GFP_KERNEL);
if (!mix->mux_table) {
pr_err("%s:%s: could not allocate mmp mix mux-table\n",
__func__, name);
kfree(mix->table);
kfree(mix);
return ERR_PTR(-ENOMEM);
goto free_mix;
}
}
@ -509,4 +500,8 @@ struct clk *mmp_clk_register_mix(struct device *dev,
}
return clk;
free_mix:
kfree(mix);
return ERR_PTR(-ENOMEM);
}

View File

@ -83,19 +83,19 @@ void __init mmp2_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys,
void __iomem *apbc_base;
mpmu_base = ioremap(mpmu_phys, SZ_4K);
if (mpmu_base == NULL) {
if (!mpmu_base) {
pr_err("error to ioremap MPMU base\n");
return;
}
apmu_base = ioremap(apmu_phys, SZ_4K);
if (apmu_base == NULL) {
if (!apmu_base) {
pr_err("error to ioremap APMU base\n");
return;
}
apbc_base = ioremap(apbc_phys, SZ_4K);
if (apbc_base == NULL) {
if (!apbc_base) {
pr_err("error to ioremap APBC base\n");
return;
}

View File

@ -75,19 +75,19 @@ void __init pxa168_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys,
void __iomem *apbc_base;
mpmu_base = ioremap(mpmu_phys, SZ_4K);
if (mpmu_base == NULL) {
if (!mpmu_base) {
pr_err("error to ioremap MPMU base\n");
return;
}
apmu_base = ioremap(apmu_phys, SZ_4K);
if (apmu_base == NULL) {
if (!apmu_base) {
pr_err("error to ioremap APMU base\n");
return;
}
apbc_base = ioremap(apbc_phys, SZ_4K);
if (apbc_base == NULL) {
if (!apbc_base) {
pr_err("error to ioremap APBC base\n");
return;
}

View File

@ -74,25 +74,25 @@ void __init pxa910_clk_init(phys_addr_t mpmu_phys, phys_addr_t apmu_phys,
void __iomem *apbc_base;
mpmu_base = ioremap(mpmu_phys, SZ_4K);
if (mpmu_base == NULL) {
if (!mpmu_base) {
pr_err("error to ioremap MPMU base\n");
return;
}
apmu_base = ioremap(apmu_phys, SZ_4K);
if (apmu_base == NULL) {
if (!apmu_base) {
pr_err("error to ioremap APMU base\n");
return;
}
apbcp_base = ioremap(apbcp_phys, SZ_4K);
if (apbcp_base == NULL) {
if (!apbcp_base) {
pr_err("error to ioremap APBC extension base\n");
return;
}
apbc_base = ioremap(apbc_phys, SZ_4K);
if (apbc_base == NULL) {
if (!apbc_base) {
pr_err("error to ioremap APBC base\n");
return;
}

View File

@ -67,7 +67,7 @@ static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
return ret;
}
static struct clk_ops clk_div_ops = {
static const struct clk_ops clk_div_ops = {
.recalc_rate = clk_div_recalc_rate,
.round_rate = clk_div_round_rate,
.set_rate = clk_div_set_rate,

View File

@ -107,7 +107,7 @@ static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
return mxs_clk_wait(frac->reg, frac->busy);
}
static struct clk_ops clk_frac_ops = {
static const struct clk_ops clk_frac_ops = {
.recalc_rate = clk_frac_recalc_rate,
.round_rate = clk_frac_round_rate,
.set_rate = clk_frac_set_rate,

View File

@ -147,9 +147,7 @@ void pxa2xx_core_turbo_switch(bool on)
" b 3f\n"
"2: b 1b\n"
"3: nop\n"
: "=&r" (unused)
: "r" (clkcfg)
: );
: "=&r" (unused) : "r" (clkcfg));
local_irq_restore(flags);
}

View File

@ -156,7 +156,6 @@ extern const struct clk_ops clk_dyn_rcg_ops;
* @hid_width: number of bits in half integer divider
* @parent_map: map from software's parent index to hardware's src_sel field
* @freq_tbl: frequency table
* @current_freq: last cached frequency when using branches with shared RCGs
* @clkr: regmap clock handle
*
*/
@ -166,7 +165,6 @@ struct clk_rcg2 {
u8 hid_width;
const struct parent_map *parent_map;
const struct freq_tbl *freq_tbl;
unsigned long current_freq;
struct clk_regmap clkr;
};
@ -174,7 +172,6 @@ struct clk_rcg2 {
extern const struct clk_ops clk_rcg2_ops;
extern const struct clk_ops clk_rcg2_floor_ops;
extern const struct clk_ops clk_rcg2_shared_ops;
extern const struct clk_ops clk_edp_pixel_ops;
extern const struct clk_ops clk_byte_ops;
extern const struct clk_ops clk_byte2_ops;

View File

@ -358,85 +358,6 @@ const struct clk_ops clk_rcg2_floor_ops = {
};
EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
const char *name = clk_hw_get_name(hw);
int ret, count;
/* force enable RCG */
ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
CMD_ROOT_EN, CMD_ROOT_EN);
if (ret)
return ret;
/* wait for RCG to turn ON */
for (count = 500; count > 0; count--) {
ret = clk_rcg2_is_enabled(hw);
if (ret)
break;
udelay(1);
}
if (!count)
pr_err("%s: RCG did not turn on\n", name);
/* set clock rate */
ret = __clk_rcg2_set_rate(hw, rate, CEIL);
if (ret)
return ret;
/* clear force enable RCG */
return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
CMD_ROOT_EN, 0);
}
static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
/* cache the rate */
rcg->current_freq = rate;
if (!__clk_is_enabled(hw->clk))
return 0;
return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
}
static unsigned long
clk_rcg2_shared_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
return rcg->current_freq = clk_rcg2_recalc_rate(hw, parent_rate);
}
static int clk_rcg2_shared_enable(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
}
static void clk_rcg2_shared_disable(struct clk_hw *hw)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
/* switch to XO, which is the lowest entry in the freq table */
clk_rcg2_shared_set_rate(hw, rcg->freq_tbl[0].freq, 0);
}
const struct clk_ops clk_rcg2_shared_ops = {
.enable = clk_rcg2_shared_enable,
.disable = clk_rcg2_shared_disable,
.get_parent = clk_rcg2_get_parent,
.recalc_rate = clk_rcg2_shared_recalc_rate,
.determine_rate = clk_rcg2_determine_rate,
.set_rate = clk_rcg2_shared_set_rate,
};
EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops);
struct frac_entry {
int num;
int den;

View File

@ -56,6 +56,18 @@
}, \
}
#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \
static struct clk_rpm _platform##_##_name = { \
.rpm_clk_id = (r_id), \
.rate = (r), \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_fixed_ops, \
.name = #_name, \
.parent_names = (const char *[]){ "pxo" }, \
.num_parents = 1, \
}, \
}
#define DEFINE_CLK_RPM_PXO_BRANCH(_platform, _name, _active, r_id, r) \
static struct clk_rpm _platform##_##_active; \
static struct clk_rpm _platform##_##_name = { \
@ -143,6 +155,13 @@ static int clk_rpm_handoff(struct clk_rpm *r)
int ret;
u32 value = INT_MAX;
/*
* The vendor tree simply reads the status for this
* RPM clock.
*/
if (r->rpm_clk_id == QCOM_RPM_PLL_4)
return 0;
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
r->rpm_clk_id, &value, 1);
if (ret)
@ -269,6 +288,32 @@ out:
mutex_unlock(&rpm_clk_lock);
}
static int clk_rpm_fixed_prepare(struct clk_hw *hw)
{
struct clk_rpm *r = to_clk_rpm(hw);
u32 value = 1;
int ret;
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
r->rpm_clk_id, &value, 1);
if (!ret)
r->enabled = true;
return ret;
}
static void clk_rpm_fixed_unprepare(struct clk_hw *hw)
{
struct clk_rpm *r = to_clk_rpm(hw);
u32 value = 0;
int ret;
ret = qcom_rpm_write(r->rpm, QCOM_RPM_ACTIVE_STATE,
r->rpm_clk_id, &value, 1);
if (!ret)
r->enabled = false;
}
static int clk_rpm_set_rate(struct clk_hw *hw,
unsigned long rate, unsigned long parent_rate)
{
@ -333,6 +378,13 @@ static unsigned long clk_rpm_recalc_rate(struct clk_hw *hw,
return r->rate;
}
static const struct clk_ops clk_rpm_fixed_ops = {
.prepare = clk_rpm_fixed_prepare,
.unprepare = clk_rpm_fixed_unprepare,
.round_rate = clk_rpm_round_rate,
.recalc_rate = clk_rpm_recalc_rate,
};
static const struct clk_ops clk_rpm_ops = {
.prepare = clk_rpm_prepare,
.unprepare = clk_rpm_unprepare,
@ -348,6 +400,45 @@ static const struct clk_ops clk_rpm_branch_ops = {
.recalc_rate = clk_rpm_recalc_rate,
};
/* MSM8660/APQ8060 */
DEFINE_CLK_RPM(msm8660, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
DEFINE_CLK_RPM(msm8660, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
DEFINE_CLK_RPM(msm8660, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);
DEFINE_CLK_RPM(msm8660, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
DEFINE_CLK_RPM(msm8660, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
DEFINE_CLK_RPM(msm8660, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
DEFINE_CLK_RPM(msm8660, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
DEFINE_CLK_RPM(msm8660, smi_clk, smi_a_clk, QCOM_RPM_SMI_CLK);
DEFINE_CLK_RPM(msm8660, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
DEFINE_CLK_RPM_FIXED(msm8660, pll4_clk, pll4_a_clk, QCOM_RPM_PLL_4, 540672000);
static struct clk_rpm *msm8660_clks[] = {
[RPM_APPS_FABRIC_CLK] = &msm8660_afab_clk,
[RPM_APPS_FABRIC_A_CLK] = &msm8660_afab_a_clk,
[RPM_SYS_FABRIC_CLK] = &msm8660_sfab_clk,
[RPM_SYS_FABRIC_A_CLK] = &msm8660_sfab_a_clk,
[RPM_MM_FABRIC_CLK] = &msm8660_mmfab_clk,
[RPM_MM_FABRIC_A_CLK] = &msm8660_mmfab_a_clk,
[RPM_DAYTONA_FABRIC_CLK] = &msm8660_daytona_clk,
[RPM_DAYTONA_FABRIC_A_CLK] = &msm8660_daytona_a_clk,
[RPM_SFPB_CLK] = &msm8660_sfpb_clk,
[RPM_SFPB_A_CLK] = &msm8660_sfpb_a_clk,
[RPM_CFPB_CLK] = &msm8660_cfpb_clk,
[RPM_CFPB_A_CLK] = &msm8660_cfpb_a_clk,
[RPM_MMFPB_CLK] = &msm8660_mmfpb_clk,
[RPM_MMFPB_A_CLK] = &msm8660_mmfpb_a_clk,
[RPM_SMI_CLK] = &msm8660_smi_clk,
[RPM_SMI_A_CLK] = &msm8660_smi_a_clk,
[RPM_EBI1_CLK] = &msm8660_ebi1_clk,
[RPM_EBI1_A_CLK] = &msm8660_ebi1_a_clk,
[RPM_PLL4_CLK] = &msm8660_pll4_clk,
};
static const struct rpm_clk_desc rpm_clk_msm8660 = {
.clks = msm8660_clks,
.num_clks = ARRAY_SIZE(msm8660_clks),
};
/* apq8064 */
DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
@ -386,6 +477,8 @@ static const struct rpm_clk_desc rpm_clk_apq8064 = {
};
static const struct of_device_id rpm_clk_match_table[] = {
{ .compatible = "qcom,rpmcc-msm8660", .data = &rpm_clk_msm8660 },
{ .compatible = "qcom,rpmcc-apq8060", .data = &rpm_clk_msm8660 },
{ .compatible = "qcom,rpmcc-apq8064", .data = &rpm_clk_apq8064 },
{ }
};

View File

@ -530,9 +530,91 @@ static const struct rpm_smd_clk_desc rpm_clk_msm8974 = {
.clks = msm8974_clks,
.num_clks = ARRAY_SIZE(msm8974_clks),
};
/* msm8996 */
DEFINE_CLK_SMD_RPM(msm8996, pcnoc_clk, pcnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8996, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
DEFINE_CLK_SMD_RPM(msm8996, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
DEFINE_CLK_SMD_RPM(msm8996, bimc_clk, bimc_a_clk, QCOM_SMD_RPM_MEM_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8996, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk,
QCOM_SMD_RPM_MMAXI_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8996, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
DEFINE_CLK_SMD_RPM(msm8996, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre1_noc_clk, aggre1_noc_a_clk,
QCOM_SMD_RPM_AGGR_CLK, 1, 1000);
DEFINE_CLK_SMD_RPM_BRANCH(msm8996, aggre2_noc_clk, aggre2_noc_a_clk,
QCOM_SMD_RPM_AGGR_CLK, 2, 1000);
DEFINE_CLK_SMD_RPM_QDSS(msm8996, qdss_clk, qdss_a_clk,
QCOM_SMD_RPM_MISC_CLK, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk1, bb_clk1_a, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, bb_clk2, bb_clk2_a, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk1, rf_clk1_a, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, rf_clk2, rf_clk2_a, 5);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, ln_bb_clk, ln_bb_a_clk, 8);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk1, div_clk1_a, 0xb);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk2, div_clk2_a, 0xc);
DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8996, div_clk3, div_clk3_a, 0xd);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk1_pin, bb_clk1_a_pin, 1);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, bb_clk2_pin, bb_clk2_a_pin, 2);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk1_pin, rf_clk1_a_pin, 4);
DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8996, rf_clk2_pin, rf_clk2_a_pin, 5);
static struct clk_smd_rpm *msm8996_clks[] = {
[RPM_SMD_PCNOC_CLK] = &msm8996_pcnoc_clk,
[RPM_SMD_PCNOC_A_CLK] = &msm8996_pcnoc_a_clk,
[RPM_SMD_SNOC_CLK] = &msm8996_snoc_clk,
[RPM_SMD_SNOC_A_CLK] = &msm8996_snoc_a_clk,
[RPM_SMD_CNOC_CLK] = &msm8996_cnoc_clk,
[RPM_SMD_CNOC_A_CLK] = &msm8996_cnoc_a_clk,
[RPM_SMD_BIMC_CLK] = &msm8996_bimc_clk,
[RPM_SMD_BIMC_A_CLK] = &msm8996_bimc_a_clk,
[RPM_SMD_MMAXI_CLK] = &msm8996_mmssnoc_axi_rpm_clk,
[RPM_SMD_MMAXI_A_CLK] = &msm8996_mmssnoc_axi_rpm_a_clk,
[RPM_SMD_IPA_CLK] = &msm8996_ipa_clk,
[RPM_SMD_IPA_A_CLK] = &msm8996_ipa_a_clk,
[RPM_SMD_CE1_CLK] = &msm8996_ce1_clk,
[RPM_SMD_CE1_A_CLK] = &msm8996_ce1_a_clk,
[RPM_SMD_AGGR1_NOC_CLK] = &msm8996_aggre1_noc_clk,
[RPM_SMD_AGGR1_NOC_A_CLK] = &msm8996_aggre1_noc_a_clk,
[RPM_SMD_AGGR2_NOC_CLK] = &msm8996_aggre2_noc_clk,
[RPM_SMD_AGGR2_NOC_A_CLK] = &msm8996_aggre2_noc_a_clk,
[RPM_SMD_QDSS_CLK] = &msm8996_qdss_clk,
[RPM_SMD_QDSS_A_CLK] = &msm8996_qdss_a_clk,
[RPM_SMD_BB_CLK1] = &msm8996_bb_clk1,
[RPM_SMD_BB_CLK1_A] = &msm8996_bb_clk1_a,
[RPM_SMD_BB_CLK2] = &msm8996_bb_clk2,
[RPM_SMD_BB_CLK2_A] = &msm8996_bb_clk2_a,
[RPM_SMD_RF_CLK1] = &msm8996_rf_clk1,
[RPM_SMD_RF_CLK1_A] = &msm8996_rf_clk1_a,
[RPM_SMD_RF_CLK2] = &msm8996_rf_clk2,
[RPM_SMD_RF_CLK2_A] = &msm8996_rf_clk2_a,
[RPM_SMD_LN_BB_CLK] = &msm8996_ln_bb_clk,
[RPM_SMD_LN_BB_A_CLK] = &msm8996_ln_bb_a_clk,
[RPM_SMD_DIV_CLK1] = &msm8996_div_clk1,
[RPM_SMD_DIV_A_CLK1] = &msm8996_div_clk1_a,
[RPM_SMD_DIV_CLK2] = &msm8996_div_clk2,
[RPM_SMD_DIV_A_CLK2] = &msm8996_div_clk2_a,
[RPM_SMD_DIV_CLK3] = &msm8996_div_clk3,
[RPM_SMD_DIV_A_CLK3] = &msm8996_div_clk3_a,
[RPM_SMD_BB_CLK1_PIN] = &msm8996_bb_clk1_pin,
[RPM_SMD_BB_CLK1_A_PIN] = &msm8996_bb_clk1_a_pin,
[RPM_SMD_BB_CLK2_PIN] = &msm8996_bb_clk2_pin,
[RPM_SMD_BB_CLK2_A_PIN] = &msm8996_bb_clk2_a_pin,
[RPM_SMD_RF_CLK1_PIN] = &msm8996_rf_clk1_pin,
[RPM_SMD_RF_CLK1_A_PIN] = &msm8996_rf_clk1_a_pin,
[RPM_SMD_RF_CLK2_PIN] = &msm8996_rf_clk2_pin,
[RPM_SMD_RF_CLK2_A_PIN] = &msm8996_rf_clk2_a_pin,
};
static const struct rpm_smd_clk_desc rpm_clk_msm8996 = {
.clks = msm8996_clks,
.num_clks = ARRAY_SIZE(msm8996_clks),
};
static const struct of_device_id rpm_smd_clk_match_table[] = {
{ .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
{ .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 },
{ .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 },
{ }
};
MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table);

View File

@ -111,16 +111,6 @@ qcom_pll_set_fsm_mode(struct regmap *map, u32 reg, u8 bias_count, u8 lock_count)
}
EXPORT_SYMBOL_GPL(qcom_pll_set_fsm_mode);
static void qcom_cc_del_clk_provider(void *data)
{
of_clk_del_provider(data);
}
static void qcom_cc_reset_unregister(void *data)
{
reset_controller_unregister(data);
}
static void qcom_cc_gdsc_unregister(void *data)
{
gdsc_unregister(data);
@ -143,8 +133,10 @@ static int _qcom_cc_register_board_clk(struct device *dev, const char *path,
int ret;
clocks_node = of_find_node_by_path("/clocks");
if (clocks_node)
node = of_find_node_by_name(clocks_node, path);
if (clocks_node) {
node = of_get_child_by_name(clocks_node, path);
of_node_put(clocks_node);
}
if (!node) {
fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL);
@ -248,13 +240,7 @@ int qcom_cc_really_probe(struct platform_device *pdev,
return ret;
}
ret = of_clk_add_hw_provider(dev->of_node, qcom_cc_clk_hw_get, cc);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, qcom_cc_del_clk_provider,
pdev->dev.of_node);
ret = devm_of_clk_add_hw_provider(dev, qcom_cc_clk_hw_get, cc);
if (ret)
return ret;
@ -266,13 +252,7 @@ int qcom_cc_really_probe(struct platform_device *pdev,
reset->regmap = regmap;
reset->reset_map = desc->resets;
ret = reset_controller_register(&reset->rcdev);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, qcom_cc_reset_unregister,
&reset->rcdev);
ret = devm_reset_controller_register(dev, &reset->rcdev);
if (ret)
return ret;

View File

@ -15,6 +15,7 @@ config CLK_RENESAS
select CLK_R8A7794 if ARCH_R8A7794
select CLK_R8A7795 if ARCH_R8A7795
select CLK_R8A7796 if ARCH_R8A7796
select CLK_R8A77970 if ARCH_R8A77970
select CLK_R8A77995 if ARCH_R8A77995
select CLK_SH73A0 if ARCH_SH73A0
@ -95,6 +96,10 @@ config CLK_R8A7796
bool "R-Car M3-W clock support" if COMPILE_TEST
select CLK_RCAR_GEN3_CPG
config CLK_R8A77970
bool "R-Car V3M clock support" if COMPILE_TEST
select CLK_RCAR_GEN3_CPG
config CLK_R8A77995
bool "R-Car D3 clock support" if COMPILE_TEST
select CLK_RCAR_GEN3_CPG

View File

@ -14,6 +14,7 @@ obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o
obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o
obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o
obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o

View File

@ -14,8 +14,10 @@
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/pm.h>
#include <linux/slab.h>
#include "clk-div6.h"
@ -32,6 +34,7 @@
* @src_shift: Shift to access the register bits to select the parent clock
* @src_width: Number of register bits to select the parent clock (may be 0)
* @parents: Array to map from valid parent clocks indices to hardware indices
* @nb: Notifier block to save/restore clock state for system resume
*/
struct div6_clock {
struct clk_hw hw;
@ -40,6 +43,7 @@ struct div6_clock {
u32 src_shift;
u32 src_width;
u8 *parents;
struct notifier_block nb;
};
#define to_div6_clock(_hw) container_of(_hw, struct div6_clock, hw)
@ -176,6 +180,29 @@ static const struct clk_ops cpg_div6_clock_ops = {
.set_rate = cpg_div6_clock_set_rate,
};
static int cpg_div6_clock_notifier_call(struct notifier_block *nb,
unsigned long action, void *data)
{
struct div6_clock *clock = container_of(nb, struct div6_clock, nb);
switch (action) {
case PM_EVENT_RESUME:
/*
* TODO: This does not yet support DIV6 clocks with multiple
* parents, as the parent selection bits are not restored.
* Fortunately so far such DIV6 clocks are found only on
* R/SH-Mobile SoCs, while the resume functionality is only
* needed on R-Car Gen3.
*/
if (__clk_get_enable_count(clock->hw.clk))
cpg_div6_clock_enable(&clock->hw);
else
cpg_div6_clock_disable(&clock->hw);
return NOTIFY_OK;
}
return NOTIFY_DONE;
}
/**
* cpg_div6_register - Register a DIV6 clock
@ -183,11 +210,13 @@ static const struct clk_ops cpg_div6_clock_ops = {
* @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8)
* @parent_names: Array containing the names of the parent clocks
* @reg: Mapped register used to control the DIV6 clock
* @notifiers: Optional notifier chain to save/restore state for system resume
*/
struct clk * __init cpg_div6_register(const char *name,
unsigned int num_parents,
const char **parent_names,
void __iomem *reg)
void __iomem *reg,
struct raw_notifier_head *notifiers)
{
unsigned int valid_parents;
struct clk_init_data init;
@ -258,6 +287,11 @@ struct clk * __init cpg_div6_register(const char *name,
if (IS_ERR(clk))
goto free_parents;
if (notifiers) {
clock->nb.notifier_call = cpg_div6_clock_notifier_call;
raw_notifier_chain_register(notifiers, &clock->nb);
}
return clk;
free_parents:
@ -301,7 +335,7 @@ static void __init cpg_div6_clock_init(struct device_node *np)
for (i = 0; i < num_parents; i++)
parent_names[i] = of_clk_get_parent_name(np, i);
clk = cpg_div6_register(clk_name, num_parents, parent_names, reg);
clk = cpg_div6_register(clk_name, num_parents, parent_names, reg, NULL);
if (IS_ERR(clk)) {
pr_err("%s: failed to register %s DIV6 clock (%ld)\n",
__func__, np->name, PTR_ERR(clk));

View File

@ -3,6 +3,7 @@
#define __RENESAS_CLK_DIV6_H__
struct clk *cpg_div6_register(const char *name, unsigned int num_parents,
const char **parent_names, void __iomem *reg);
const char **parent_names, void __iomem *reg,
struct raw_notifier_head *notifiers);
#endif

View File

@ -156,10 +156,8 @@ static struct clk * __init cpg_mstp_clock_register(const char *name,
struct clk *clk;
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
if (!clock) {
pr_err("%s: failed to allocate MSTP clock.\n", __func__);
if (!clock)
return ERR_PTR(-ENOMEM);
}
init.name = name;
init.ops = &cpg_mstp_clock_ops;
@ -196,7 +194,6 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
if (group == NULL || clks == NULL) {
kfree(group);
kfree(clks);
pr_err("%s: failed to allocate group\n", __func__);
return;
}

View File

@ -423,7 +423,6 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
/* We're leaking memory on purpose, there's no point in cleaning
* up as the system won't boot anyway.
*/
pr_err("%s: failed to allocate cpg\n", __func__);
return;
}

View File

@ -1,5 +1,5 @@
/*
* rz Core CPG Clocks
* RZ/A1 Core CPG Clocks
*
* Copyright (C) 2013 Ideas On Board SPRL
* Copyright (C) 2014 Wolfram Sang, Sang Engineering <wsa@sang-engineering.com>

View File

@ -129,6 +129,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = {
DEF_MOD("scif2", 719, R8A7745_CLK_P),
DEF_MOD("scif1", 720, R8A7745_CLK_P),
DEF_MOD("scif0", 721, R8A7745_CLK_P),
DEF_MOD("du1", 723, R8A7745_CLK_ZX),
DEF_MOD("du0", 724, R8A7745_CLK_ZX),
DEF_MOD("ipmmu-sgx", 800, R8A7745_CLK_ZX),
DEF_MOD("vin1", 810, R8A7745_CLK_ZG),

View File

@ -149,7 +149,7 @@ static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
DEF_MOD("usb-dmac1", 331, R8A7795_CLK_S3D1),
DEF_MOD("rwdt", 402, R8A7795_CLK_R),
DEF_MOD("intc-ex", 407, R8A7795_CLK_CP),
DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1),
DEF_MOD("intc-ap", 408, R8A7795_CLK_S0D3),
DEF_MOD("audmac1", 501, R8A7795_CLK_S0D3),
DEF_MOD("audmac0", 502, R8A7795_CLK_S0D3),
DEF_MOD("drif7", 508, R8A7795_CLK_S3D2),
@ -348,6 +348,7 @@ static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = {
{ MOD_CLK_ID(217), R8A7795_CLK_S3D1 }, /* SYS-DMAC2 */
{ MOD_CLK_ID(218), R8A7795_CLK_S3D1 }, /* SYS-DMAC1 */
{ MOD_CLK_ID(219), R8A7795_CLK_S3D1 }, /* SYS-DMAC0 */
{ MOD_CLK_ID(408), R8A7795_CLK_S3D1 }, /* INTC-AP */
{ MOD_CLK_ID(501), R8A7795_CLK_S3D1 }, /* AUDMAC1 */
{ MOD_CLK_ID(502), R8A7795_CLK_S3D1 }, /* AUDMAC0 */
{ MOD_CLK_ID(523), R8A7795_CLK_S3D4 }, /* PWM */

View File

@ -143,7 +143,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1),
DEF_MOD("rwdt", 402, R8A7796_CLK_R),
DEF_MOD("intc-ex", 407, R8A7796_CLK_CP),
DEF_MOD("intc-ap", 408, R8A7796_CLK_S3D1),
DEF_MOD("intc-ap", 408, R8A7796_CLK_S0D3),
DEF_MOD("audmac1", 501, R8A7796_CLK_S0D3),
DEF_MOD("audmac0", 502, R8A7796_CLK_S0D3),
DEF_MOD("drif7", 508, R8A7796_CLK_S3D2),

View File

@ -0,0 +1,199 @@
/*
* r8a77970 Clock Pulse Generator / Module Standby and Software Reset
*
* Copyright (C) 2017 Cogent Embedded Inc.
*
* Based on r8a7795-cpg-mssr.c
*
* Copyright (C) 2015 Glider bvba
*
* 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; version 2 of the License.
*/
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/soc/renesas/rcar-rst.h>
#include <dt-bindings/clock/r8a77970-cpg-mssr.h>
#include "renesas-cpg-mssr.h"
#include "rcar-gen3-cpg.h"
enum clk_ids {
/* Core Clock Outputs exported to DT */
LAST_DT_CORE_CLK = R8A77970_CLK_OSC,
/* External Input Clocks */
CLK_EXTAL,
CLK_EXTALR,
/* Internal Core Clocks */
CLK_MAIN,
CLK_PLL0,
CLK_PLL1,
CLK_PLL3,
CLK_PLL1_DIV2,
CLK_PLL1_DIV4,
/* Module Clocks */
MOD_CLK_BASE
};
static const struct cpg_core_clk r8a77970_core_clks[] __initconst = {
/* External Clock Inputs */
DEF_INPUT("extal", CLK_EXTAL),
DEF_INPUT("extalr", CLK_EXTALR),
/* Internal Core Clocks */
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
/* Core Clock Outputs */
DEF_FIXED("ztr", R8A77970_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
DEF_FIXED("ztrd2", R8A77970_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
DEF_FIXED("zt", R8A77970_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
DEF_FIXED("zx", R8A77970_CLK_ZX, CLK_PLL1_DIV2, 3, 1),
DEF_FIXED("s1d1", R8A77970_CLK_S1D1, CLK_PLL1_DIV2, 4, 1),
DEF_FIXED("s1d2", R8A77970_CLK_S1D2, CLK_PLL1_DIV2, 8, 1),
DEF_FIXED("s1d4", R8A77970_CLK_S1D4, CLK_PLL1_DIV2, 16, 1),
DEF_FIXED("s2d1", R8A77970_CLK_S2D1, CLK_PLL1_DIV2, 6, 1),
DEF_FIXED("s2d2", R8A77970_CLK_S2D2, CLK_PLL1_DIV2, 12, 1),
DEF_FIXED("s2d4", R8A77970_CLK_S2D4, CLK_PLL1_DIV2, 24, 1),
DEF_FIXED("cl", R8A77970_CLK_CL, CLK_PLL1_DIV2, 48, 1),
DEF_FIXED("cp", R8A77970_CLK_CP, CLK_EXTAL, 2, 1),
DEF_DIV6P1("canfd", R8A77970_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
DEF_DIV6P1("mso", R8A77970_CLK_MSO, CLK_PLL1_DIV4, 0x014),
DEF_DIV6P1("csi0", R8A77970_CLK_CSI0, CLK_PLL1_DIV4, 0x00c),
DEF_FIXED("osc", R8A77970_CLK_OSC, CLK_PLL1_DIV2, 12*1024, 1),
DEF_FIXED("r", R8A77970_CLK_R, CLK_EXTALR, 1, 1),
};
static const struct mssr_mod_clk r8a77970_mod_clks[] __initconst = {
DEF_MOD("ivcp1e", 127, R8A77970_CLK_S2D1),
DEF_MOD("scif4", 203, R8A77970_CLK_S2D4),
DEF_MOD("scif3", 204, R8A77970_CLK_S2D4),
DEF_MOD("scif1", 206, R8A77970_CLK_S2D4),
DEF_MOD("scif0", 207, R8A77970_CLK_S2D4),
DEF_MOD("msiof3", 208, R8A77970_CLK_MSO),
DEF_MOD("msiof2", 209, R8A77970_CLK_MSO),
DEF_MOD("msiof1", 210, R8A77970_CLK_MSO),
DEF_MOD("msiof0", 211, R8A77970_CLK_MSO),
DEF_MOD("mfis", 213, R8A77970_CLK_S2D2),
DEF_MOD("sys-dmac2", 217, R8A77970_CLK_S2D1),
DEF_MOD("sys-dmac1", 218, R8A77970_CLK_S2D1),
DEF_MOD("rwdt", 402, R8A77970_CLK_R),
DEF_MOD("intc-ex", 407, R8A77970_CLK_CP),
DEF_MOD("intc-ap", 408, R8A77970_CLK_S2D1),
DEF_MOD("hscif3", 517, R8A77970_CLK_S2D1),
DEF_MOD("hscif2", 518, R8A77970_CLK_S2D1),
DEF_MOD("hscif1", 519, R8A77970_CLK_S2D1),
DEF_MOD("hscif0", 520, R8A77970_CLK_S2D1),
DEF_MOD("thermal", 522, R8A77970_CLK_CP),
DEF_MOD("pwm", 523, R8A77970_CLK_S2D4),
DEF_MOD("fcpvd0", 603, R8A77970_CLK_S2D1),
DEF_MOD("vspd0", 623, R8A77970_CLK_S2D1),
DEF_MOD("csi40", 716, R8A77970_CLK_CSI0),
DEF_MOD("du0", 724, R8A77970_CLK_S2D1),
DEF_MOD("vin3", 808, R8A77970_CLK_S2D1),
DEF_MOD("vin2", 809, R8A77970_CLK_S2D1),
DEF_MOD("vin1", 810, R8A77970_CLK_S2D1),
DEF_MOD("vin0", 811, R8A77970_CLK_S2D1),
DEF_MOD("etheravb", 812, R8A77970_CLK_S2D2),
DEF_MOD("gpio5", 907, R8A77970_CLK_CP),
DEF_MOD("gpio4", 908, R8A77970_CLK_CP),
DEF_MOD("gpio3", 909, R8A77970_CLK_CP),
DEF_MOD("gpio2", 910, R8A77970_CLK_CP),
DEF_MOD("gpio1", 911, R8A77970_CLK_CP),
DEF_MOD("gpio0", 912, R8A77970_CLK_CP),
DEF_MOD("can-fd", 914, R8A77970_CLK_S2D2),
DEF_MOD("i2c4", 927, R8A77970_CLK_S2D2),
DEF_MOD("i2c3", 928, R8A77970_CLK_S2D2),
DEF_MOD("i2c2", 929, R8A77970_CLK_S2D2),
DEF_MOD("i2c1", 930, R8A77970_CLK_S2D2),
DEF_MOD("i2c0", 931, R8A77970_CLK_S2D2),
};
static const unsigned int r8a77970_crit_mod_clks[] __initconst = {
MOD_CLK_ID(408), /* INTC-AP (GIC) */
};
/*
* CPG Clock Data
*/
/*
* MD EXTAL PLL0 PLL1 PLL3
* 14 13 19 (MHz)
*-------------------------------------------------
* 0 0 0 16.66 x 1 x192 x192 x96
* 0 0 1 16.66 x 1 x192 x192 x80
* 0 1 0 20 x 1 x160 x160 x80
* 0 1 1 20 x 1 x160 x160 x66
* 1 0 0 27 / 2 x236 x236 x118
* 1 0 1 27 / 2 x236 x236 x98
* 1 1 0 33.33 / 2 x192 x192 x96
* 1 1 1 33.33 / 2 x192 x192 x80
*/
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
(((md) & BIT(13)) >> 12) | \
(((md) & BIT(19)) >> 19))
static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[8] __initconst = {
/* EXTAL div PLL1 mult/div PLL3 mult/div */
{ 1, 192, 1, 96, 1, },
{ 1, 192, 1, 80, 1, },
{ 1, 160, 1, 80, 1, },
{ 1, 160, 1, 66, 1, },
{ 2, 236, 1, 118, 1, },
{ 2, 236, 1, 98, 1, },
{ 2, 192, 1, 96, 1, },
{ 2, 192, 1, 80, 1, },
};
static int __init r8a77970_cpg_mssr_init(struct device *dev)
{
const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
u32 cpg_mode;
int error;
error = rcar_rst_read_mode_pins(&cpg_mode);
if (error)
return error;
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
}
const struct cpg_mssr_info r8a77970_cpg_mssr_info __initconst = {
/* Core Clocks */
.core_clks = r8a77970_core_clks,
.num_core_clks = ARRAY_SIZE(r8a77970_core_clks),
.last_dt_core_clk = LAST_DT_CORE_CLK,
.num_total_core_clks = MOD_CLK_BASE,
/* Module Clocks */
.mod_clks = r8a77970_mod_clks,
.num_mod_clks = ARRAY_SIZE(r8a77970_mod_clks),
.num_hw_mod_clks = 12 * 32,
/* Critical Module Clocks */
.crit_mod_clks = r8a77970_crit_mod_clks,
.num_crit_mod_clks = ARRAY_SIZE(r8a77970_crit_mod_clks),
/* Callbacks */
.init = r8a77970_cpg_mssr_init,
.cpg_clk_register = rcar_gen3_cpg_clk_register,
};

View File

@ -127,7 +127,7 @@ static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = {
DEF_MOD("usb-dmac1", 331, R8A77995_CLK_S3D1),
DEF_MOD("rwdt", 402, R8A77995_CLK_R),
DEF_MOD("intc-ex", 407, R8A77995_CLK_CP),
DEF_MOD("intc-ap", 408, R8A77995_CLK_S3D1),
DEF_MOD("intc-ap", 408, R8A77995_CLK_S1D2),
DEF_MOD("audmac0", 502, R8A77995_CLK_S3D1),
DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C),
DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C),

View File

@ -262,10 +262,9 @@ static unsigned int cpg_pll0_div __initdata;
static u32 cpg_mode __initdata;
struct clk * __init rcar_gen2_cpg_clk_register(struct device *dev,
const struct cpg_core_clk *core,
const struct cpg_mssr_info *info,
struct clk **clks,
void __iomem *base)
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
struct clk **clks, void __iomem *base,
struct raw_notifier_head *notifiers)
{
const struct clk_div_table *table = NULL;
const struct clk *parent;

View File

@ -34,9 +34,9 @@ struct rcar_gen2_cpg_pll_config {
};
struct clk *rcar_gen2_cpg_clk_register(struct device *dev,
const struct cpg_core_clk *core,
const struct cpg_mssr_info *info,
struct clk **clks, void __iomem *base);
const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
struct clk **clks, void __iomem *base,
struct raw_notifier_head *notifiers);
int rcar_gen2_cpg_init(const struct rcar_gen2_cpg_pll_config *config,
unsigned int pll0_div, u32 mode);

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