This pull request contains zero diff to the core framework. It is a collection

of various clk driver updates. The biggest driver updates in terms of lines of
 code is the Allwinner driver, closely followed by the Qualcomm and Mediatek
 drivers. All of those hit high because we add so many lines of clk data. Coming
 in fourth place is i.MX which also adds a bunch of clk data. This accounts for
 the new driver additions this time around.
 
 Otherwise the patches are lots of little cleanups and fixes for various clk
 drivers that have baked in linux-next for a while. I suppose one highlight or
 theme is that more clk drivers are being updated to work as modules, which is
 interesting to see such critical SoC infrastructure work as a loadable module.
 
 New Drivers:
  - Support qcom SM8150/SM8250 video and display clks
  - Support Mediatek MT8167 clks
  - Add clock for CRC block found on vf610 SoCs
  - Add support for the Renesas R-Car V3U (R8A779A0) SoC
  - Add support for the VSP for Resizing clock on Renesas RZ/G1H
  - Support Allwinner A100 SoC clks
 
 Removed Drivers:
  - Remove i.MX21 clock driver, as i.MX21 platform support is being dropped
 
 Updates:
  - Change how qcom's display port clks work
  - Small non-critical fixes for TI clk driver
  - Remove various unused variables in clk drivers
  - Allow Rockchip clk driver to be a module
  - Remove most __clk_lookup() calls in Samsung drivers (yay!)
  - Support building i.MX ARMv8 platforms clock driver as module
  - Some kerneldoc fixes here and there
  - A couple of minor i.MX clk data corrections
  - Update audio clock inverter and fdiv2 flag on Amlogic g12
  - Make amlogic clk drivers configurable in Kconfig
  - Fix Renesas VSP clock names to match corrected hardware documentation
  - Sigma-delta modulation on Allwinner R40
  - Various fixes for at91 clk driver
  - Use semicolons instead of commas in some places
  - Mark some variables const so they can move to RO memory
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAl+R0K0RHHNib3lkQGtl
 cm5lbC5vcmcACgkQrQKIl8bklSU9xw/+KRDZ/xo7GKeC7QrRt4q5eWIW4l/HzjYH
 yeht/i7cEXy+jSJuOTBj4sIpOdvzdBQfsqMiNg7RKdtYs0HbYFywxWtnvetptuM1
 BCgSMDHHJ59EJSPEWAvE6bsl9xaVl4o0XEI2+qAoJ4OIcJVzVz+vRGQ7pDyEk2XT
 zTXRw4W+HftZXFB8Nw0JTj9YzBoZJzpnAB/vu2HzMYVAvoeQ8RhcdbipdSTjI+zY
 ++zkt8cmGP0iKloHbi3rk1A7w/ORJ//UjT24xmkwAO6t1CWEErVzXBtGkQ9K4ijy
 F2w5CzJb/szGCfnGlcchQ5kjB/FfgIKuLNlhTiptY+UZGIvSAbndhMSS3JFsqGbl
 aYUk5fpjdpneSsIPvHnnz1jIaK6OmHSoxmq7FgwaU+YDX6ZK6UKalMHbHUEpiNX+
 3a+FeKe2IVMZ0uVqpJGnd/o4Kud2CeRM1ufqu15ygbujfSH6xcO7fbUi/C8XJLMX
 7PR0Ze0PhwkMezdlxb3WpK+4MrOny3JT0DTAbAQDdAwsKFP/Sex4QMWP8PUdTmGY
 dQcrgvuXYC1hufOaY1JzxjfGrhEBuJAr7BsjBI+etUpnJ9Z5Uhguti/lnKm7oAlI
 EceBJ4B5M1iUYTkKXYxLWWzUlkIKNzgHvjRM2Q6Nn5LbyVlzM4i284C/E4M8AmVB
 nSXy1nWkSAU=
 =sKI8
 -----END PGP SIGNATURE-----

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

Pull clk updates from Stephen Boyd:
 "This contains no changes to the core framework. It is a collection of
  various clk driver updates.

  The biggest driver updates in terms of lines of code is the Allwinner
  driver, closely followed by the Qualcomm and Mediatek drivers. All of
  those hit high because we add so many lines of clk data. Coming in
  fourth place is i.MX which also adds a bunch of clk data. This
  accounts for the new driver additions this time around.

  Otherwise the patches are lots of little cleanups and fixes for
  various clk drivers that have baked in linux-next for a while. I
  suppose one highlight or theme is that more clk drivers are being
  updated to work as modules, which is interesting to see such critical
  SoC infrastructure work as a loadable module.

  New Drivers:
   - Support qcom SM8150/SM8250 video and display clks
   - Support Mediatek MT8167 clks
   - Add clock for CRC block found on vf610 SoCs
   - Add support for the Renesas R-Car V3U (R8A779A0) SoC
   - Add support for the VSP for Resizing clock on Renesas RZ/G1H
   - Support Allwinner A100 SoC clks

  Removed Drivers:
   - Remove i.MX21 clock driver, as i.MX21 platform support is being
     dropped

  Updates:
   - Change how qcom's display port clks work
   - Small non-critical fixes for TI clk driver
   - Remove various unused variables in clk drivers
   - Allow Rockchip clk driver to be a module
   - Remove most __clk_lookup() calls in Samsung drivers (yay!)
   - Support building i.MX ARMv8 platforms clock driver as module
   - Some kerneldoc fixes here and there
   - A couple of minor i.MX clk data corrections
   - Update audio clock inverter and fdiv2 flag on Amlogic g12
   - Make amlogic clk drivers configurable in Kconfig
   - Fix Renesas VSP clock names to match corrected hardware
     documentation
   - Sigma-delta modulation on Allwinner R40
   - Various fixes for at91 clk driver
   - Use semicolons instead of commas in some places
   - Mark some variables const so they can move to RO memory"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (102 commits)
  clk: imx8mq: Fix usdhc parents order
  clk: qcom: gdsc: Keep RETAIN_FF bit set if gdsc is already on
  clk: Restrict CLK_HSDK to ARC_SOC_HSDK
  clk: at91: sam9x60: support only two programmable clocks
  clk: ingenic: Respect CLK_SET_RATE_PARENT in .round_rate
  clk: ingenic: Don't tag custom clocks with CLK_SET_RATE_PARENT
  clk: ingenic: Don't use CLK_SET_RATE_GATE for PLL
  clk: ingenic: Use readl_poll_timeout instead of custom loop
  clk: ingenic: Use to_clk_info() macro for all clocks
  clk: bcm2835: add missing release if devm_clk_hw_register fails
  clk: at91: clk-sam9x60-pll: remove unused variable
  clk: at91: clk-main: update key before writing AT91_CKGR_MOR
  clk: at91: remove the checking of parent_name
  clk: clk-prima2: fix return value check in prima2_clk_init()
  clk: mmp2: Fix the display clock divider base
  clk: pxa: Constify static struct clk_ops
  clk: baikal-t1: Mark Ethernet PLL as critical
  clk: qoriq: modify MAX_PLL_DIV to 32
  clk: axi-clkgen: Set power bits for fractional mode
  clk: axi-clkgen: Add support for fractional dividers
  ...
This commit is contained in:
Linus Torvalds 2020-10-22 12:53:28 -07:00
commit 3fec0eaaf0
158 changed files with 7585 additions and 883 deletions

View File

@ -15,6 +15,7 @@ Required Properties:
- "mediatek,mt7623-apmixedsys", "mediatek,mt2701-apmixedsys"
- "mediatek,mt7629-apmixedsys"
- "mediatek,mt8135-apmixedsys"
- "mediatek,mt8167-apmixedsys", "syscon"
- "mediatek,mt8173-apmixedsys"
- "mediatek,mt8183-apmixedsys", "syscon"
- "mediatek,mt8516-apmixedsys"

View File

@ -11,6 +11,7 @@ Required Properties:
- "mediatek,mt6779-audio", "syscon"
- "mediatek,mt7622-audsys", "syscon"
- "mediatek,mt7623-audsys", "mediatek,mt2701-audsys", "syscon"
- "mediatek,mt8167-audiosys", "syscon"
- "mediatek,mt8183-audiosys", "syscon"
- "mediatek,mt8516-audsys", "syscon"
- #clock-cells: Must be 1

View File

@ -12,6 +12,7 @@ Required Properties:
- "mediatek,mt6779-imgsys", "syscon"
- "mediatek,mt6797-imgsys", "syscon"
- "mediatek,mt7623-imgsys", "mediatek,mt2701-imgsys", "syscon"
- "mediatek,mt8167-imgsys", "syscon"
- "mediatek,mt8173-imgsys", "syscon"
- "mediatek,mt8183-imgsys", "syscon"
- #clock-cells: Must be 1

View File

@ -16,6 +16,7 @@ Required Properties:
- "mediatek,mt7623-infracfg", "mediatek,mt2701-infracfg", "syscon"
- "mediatek,mt7629-infracfg", "syscon"
- "mediatek,mt8135-infracfg", "syscon"
- "mediatek,mt8167-infracfg", "syscon"
- "mediatek,mt8173-infracfg", "syscon"
- "mediatek,mt8183-infracfg", "syscon"
- "mediatek,mt8516-infracfg", "syscon"

View File

@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-mfgcfg", "syscon"
- "mediatek,mt6779-mfgcfg", "syscon"
- "mediatek,mt8167-mfgcfg", "syscon"
- "mediatek,mt8183-mfgcfg", "syscon"
- #clock-cells: Must be 1

View File

@ -15,6 +15,7 @@ Required Properties:
- "mediatek,mt7623-topckgen", "mediatek,mt2701-topckgen"
- "mediatek,mt7629-topckgen"
- "mediatek,mt8135-topckgen"
- "mediatek,mt8167-topckgen", "syscon"
- "mediatek,mt8173-topckgen"
- "mediatek,mt8183-topckgen", "syscon"
- "mediatek,mt8516-topckgen"

View File

@ -11,6 +11,7 @@ Required Properties:
- "mediatek,mt6779-vdecsys", "syscon"
- "mediatek,mt6797-vdecsys", "syscon"
- "mediatek,mt7623-vdecsys", "mediatek,mt2701-vdecsys", "syscon"
- "mediatek,mt8167-vdecsys", "syscon"
- "mediatek,mt8173-vdecsys", "syscon"
- "mediatek,mt8183-vdecsys", "syscon"
- #clock-cells: Must be 1

View File

@ -36,6 +36,8 @@ properties:
- allwinner,sun9i-a80-ccu
- allwinner,sun50i-a64-ccu
- allwinner,sun50i-a64-r-ccu
- allwinner,sun50i-a100-ccu
- allwinner,sun50i-a100-r-ccu
- allwinner,sun50i-h5-ccu
- allwinner,sun50i-h6-ccu
- allwinner,sun50i-h6-r-ccu
@ -78,6 +80,7 @@ if:
- allwinner,sun8i-a83t-r-ccu
- allwinner,sun8i-h3-r-ccu
- allwinner,sun50i-a64-r-ccu
- allwinner,sun50i-a100-r-ccu
- allwinner,sun50i-h6-r-ccu
then:
@ -94,7 +97,9 @@ else:
if:
properties:
compatible:
const: allwinner,sun50i-h6-ccu
enum:
- allwinner,sun50i-a100-ccu
- allwinner,sun50i-h6-ccu
then:
properties:

View File

@ -0,0 +1,93 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,dispcc-sm8x50.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Display Clock & Reset Controller Binding for SM8150/SM8250
maintainers:
- Jonathan Marek <jonathan@marek.ca>
description: |
Qualcomm display clock control module which supports the clocks, resets and
power domains on SM8150 and SM8250.
See also:
dt-bindings/clock/qcom,dispcc-sm8150.h
dt-bindings/clock/qcom,dispcc-sm8250.h
properties:
compatible:
enum:
- qcom,sm8150-dispcc
- qcom,sm8250-dispcc
clocks:
items:
- description: Board XO source
- description: Byte clock from DSI PHY0
- description: Pixel clock from DSI PHY0
- description: Byte clock from DSI PHY1
- description: Pixel clock from DSI PHY1
- description: Link clock from DP PHY
- description: VCO DIV clock from DP PHY
clock-names:
items:
- const: bi_tcxo
- const: dsi0_phy_pll_out_byteclk
- const: dsi0_phy_pll_out_dsiclk
- const: dsi1_phy_pll_out_byteclk
- const: dsi1_phy_pll_out_dsiclk
- const: dp_phy_pll_link_clk
- const: dp_phy_pll_vco_div_clk
'#clock-cells':
const: 1
'#reset-cells':
const: 1
'#power-domain-cells':
const: 1
reg:
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
- '#reset-cells'
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
clock-controller@af00000 {
compatible = "qcom,sm8250-dispcc";
reg = <0x0af00000 0x10000>;
clocks = <&rpmhcc RPMH_CXO_CLK>,
<&dsi0_phy 0>,
<&dsi0_phy 1>,
<&dsi1_phy 0>,
<&dsi1_phy 1>,
<&dp_phy 0>,
<&dp_phy 1>;
clock-names = "bi_tcxo",
"dsi0_phy_pll_out_byteclk",
"dsi0_phy_pll_out_dsiclk",
"dsi1_phy_pll_out_byteclk",
"dsi1_phy_pll_out_dsiclk",
"dp_phy_pll_link_clk",
"dp_phy_pll_vco_div_clk";
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...

View File

@ -1,65 +0,0 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,sc7180-videocc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Video Clock & Reset Controller Binding for SC7180
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
Qualcomm video clock control module which supports the clocks, resets and
power domains on SC7180.
See also dt-bindings/clock/qcom,videocc-sc7180.h.
properties:
compatible:
const: qcom,sc7180-videocc
clocks:
items:
- description: Board XO source
clock-names:
items:
- const: bi_tcxo
'#clock-cells':
const: 1
'#reset-cells':
const: 1
'#power-domain-cells':
const: 1
reg:
maxItems: 1
required:
- compatible
- reg
- clocks
- clock-names
- '#clock-cells'
- '#reset-cells'
- '#power-domain-cells'
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,rpmh.h>
clock-controller@ab00000 {
compatible = "qcom,sc7180-videocc";
reg = <0x0ab00000 0x10000>;
clocks = <&rpmhcc RPMH_CXO_CLK>;
clock-names = "bi_tcxo";
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
};
...

View File

@ -1,23 +1,31 @@
# SPDX-License-Identifier: GPL-2.0-only
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/qcom,sdm845-videocc.yaml#
$id: http://devicetree.org/schemas/clock/qcom,videocc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Video Clock & Reset Controller Binding for SDM845
title: Qualcomm Video Clock & Reset Controller Binding
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
Qualcomm video clock control module which supports the clocks, resets and
power domains on SDM845.
power domains on SDM845/SC7180/SM8150/SM8250.
See also dt-bindings/clock/qcom,videocc-sdm845.h.
See also:
dt-bindings/clock/qcom,videocc-sc7180.h
dt-bindings/clock/qcom,videocc-sdm845.h
dt-bindings/clock/qcom,videocc-sm8150.h
dt-bindings/clock/qcom,videocc-sm8250.h
properties:
compatible:
const: qcom,sdm845-videocc
enum:
- qcom,sc7180-videocc
- qcom,sdm845-videocc
- qcom,sm8150-videocc
- qcom,sm8250-videocc
clocks:
items:

View File

@ -47,6 +47,7 @@ properties:
- renesas,r8a77980-cpg-mssr # R-Car V3H
- renesas,r8a77990-cpg-mssr # R-Car E3
- renesas,r8a77995-cpg-mssr # R-Car D3
- renesas,r8a779a0-cpg-mssr # R-Car V3U
reg:
maxItems: 1

View File

@ -49,7 +49,7 @@ source "drivers/clk/versatile/Kconfig"
config CLK_HSDK
bool "PLL Driver for HSDK platform"
depends on OF || COMPILE_TEST
depends on ARC_SOC_HSDK || COMPILE_TEST
depends on HAS_IOMEM
help
This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs
@ -373,6 +373,7 @@ source "drivers/clk/meson/Kconfig"
source "drivers/clk/mvebu/Kconfig"
source "drivers/clk/qcom/Kconfig"
source "drivers/clk/renesas/Kconfig"
source "drivers/clk/rockchip/Kconfig"
source "drivers/clk/samsung/Kconfig"
source "drivers/clk/sifive/Kconfig"
source "drivers/clk/sprd/Kconfig"

View File

@ -46,13 +46,6 @@ static const struct {
{ .n = "pck1", .p = "prog1", .id = 9 },
};
static const struct clk_pcr_layout at91sam9g45_pcr_layout = {
.offset = 0x10c,
.cmd = BIT(12),
.pid_mask = GENMASK(5, 0),
.div_mask = GENMASK(17, 16),
};
struct pck {
char *n;
u8 id;

View File

@ -437,12 +437,17 @@ static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
return -EINVAL;
regmap_read(regmap, AT91_CKGR_MOR, &tmp);
tmp &= ~MOR_KEY_MASK;
if (index && !(tmp & AT91_PMC_MOSCSEL))
regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL);
tmp = AT91_PMC_MOSCSEL;
else if (!index && (tmp & AT91_PMC_MOSCSEL))
regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL);
tmp = 0;
else
return 0;
regmap_update_bits(regmap, AT91_CKGR_MOR,
AT91_PMC_MOSCSEL | MOR_KEY_MASK,
tmp | AT91_PMC_KEY);
while (!clk_sam9x5_main_ready(regmap))
cpu_relax();

View File

@ -112,8 +112,8 @@ at91_clk_register_peripheral(struct regmap *regmap, const char *name,
init.name = name;
init.ops = &peripheral_ops;
init.parent_names = (parent_name ? &parent_name : NULL);
init.num_parents = (parent_name ? 1 : 0);
init.parent_names = &parent_name;
init.num_parents = 1;
init.flags = 0;
periph->id = id;

View File

@ -331,7 +331,7 @@ static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,
struct clk_hw *parent = clk_hw_get_parent(&core->hw);
unsigned long tmp_rate, tmp_parent_rate, tmp_diff;
long best_diff = -1, best_rate = -EINVAL;
u32 divid, best_div;
u32 divid;
if (!rate)
return 0;
@ -352,7 +352,6 @@ static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core,
*parent_rate = tmp_parent_rate;
best_rate = tmp_rate;
best_diff = tmp_diff;
best_div = divid;
}
if (!best_diff)

View File

@ -279,7 +279,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np)
parent_names[3] = "masterck";
parent_names[4] = "pllack_divck";
parent_names[5] = "upllck_divck";
for (i = 0; i < 8; i++) {
for (i = 0; i < 2; i++) {
char name[6];
snprintf(name, sizeof(name), "prog%d", i);

View File

@ -51,11 +51,13 @@ struct ccu_pll_info {
};
/*
* Mark as critical all PLLs except Ethernet one. CPU and DDR PLLs are sources
* of CPU cores and DDR controller reference clocks, due to which they
* obviously shouldn't be ever gated. SATA and PCIe PLLs are the parents of
* APB-bus and DDR controller AXI-bus clocks. If they are gated the system will
* be unusable.
* Alas we have to mark all PLLs as critical. CPU and DDR PLLs are sources of
* CPU cores and DDR controller reference clocks, due to which they obviously
* shouldn't be ever gated. SATA and PCIe PLLs are the parents of APB-bus and
* DDR controller AXI-bus clocks. If they are gated the system will be
* unusable. Moreover disabling SATA and Ethernet PLLs causes automatic reset
* of the corresponding subsystems. So until we aren't ready to re-initialize
* all the devices consuming those PLLs, they will be marked as critical too.
*/
static const struct ccu_pll_info pll_info[] = {
CCU_PLL_INFO(CCU_CPU_PLL, "cpu_pll", "ref_clk", CCU_CPU_PLL_BASE,
@ -67,7 +69,7 @@ static const struct ccu_pll_info pll_info[] = {
CCU_PLL_INFO(CCU_PCIE_PLL, "pcie_pll", "ref_clk", CCU_PCIE_PLL_BASE,
CLK_IS_CRITICAL),
CCU_PLL_INFO(CCU_ETH_PLL, "eth_pll", "ref_clk", CCU_ETH_PLL_BASE,
CLK_SET_RATE_GATE)
CLK_IS_CRITICAL | CLK_SET_RATE_GATE)
};
struct ccu_pll_data {

View File

@ -1338,8 +1338,10 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
pll->hw.init = &init;
ret = devm_clk_hw_register(cprman->dev, &pll->hw);
if (ret)
if (ret) {
kfree(pll);
return NULL;
}
return &pll->hw;
}

View File

@ -271,6 +271,7 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi,
case RPI_FIRMWARE_CORE_CLK_ID:
case RPI_FIRMWARE_M2MC_CLK_ID:
case RPI_FIRMWARE_V3D_CLK_ID:
case RPI_FIRMWARE_PIXEL_BVB_CLK_ID:
hw = raspberrypi_clk_register(rpi, clks->parent,
clks->id);
if (IS_ERR(hw))

View File

@ -27,19 +27,23 @@
#define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16)
#define MMCM_REG_CLKOUT5_2 0x07
#define MMCM_REG_CLKOUT0_1 0x08
#define MMCM_REG_CLKOUT0_2 0x09
#define MMCM_REG_CLKOUT6_2 0x13
#define MMCM_REG_CLK_FB1 0x14
#define MMCM_REG_CLK_FB2 0x15
#define MMCM_REG_CLK_DIV 0x16
#define MMCM_REG_LOCK1 0x18
#define MMCM_REG_LOCK2 0x19
#define MMCM_REG_LOCK3 0x1a
#define MMCM_REG_POWER 0x28
#define MMCM_REG_FILTER1 0x4e
#define MMCM_REG_FILTER2 0x4f
#define MMCM_CLKOUT_NOCOUNT BIT(6)
#define MMCM_CLK_DIV_DIVIDE BIT(11)
#define MMCM_CLK_DIV_NOCOUNT BIT(12)
struct axi_clkgen {
@ -107,6 +111,8 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
unsigned long d, d_min, d_max, _d_min, _d_max;
unsigned long m, m_min, m_max;
unsigned long f, dout, best_f, fvco;
unsigned long fract_shift = 0;
unsigned long fvco_min_fract, fvco_max_fract;
fin /= 1000;
fout /= 1000;
@ -119,42 +125,89 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
d_max = min_t(unsigned long, fin / fpfd_min, 80);
m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1);
m_max = min_t(unsigned long, fvco_max * d_max / fin, 64);
again:
fvco_min_fract = fvco_min << fract_shift;
fvco_max_fract = fvco_max << fract_shift;
m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1);
m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift);
for (m = m_min; m <= m_max; m++) {
_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max));
_d_max = min(d_max, fin * m / fvco_min);
_d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max_fract));
_d_max = min(d_max, fin * m / fvco_min_fract);
for (d = _d_min; d <= _d_max; d++) {
fvco = fin * m / d;
dout = DIV_ROUND_CLOSEST(fvco, fout);
dout = clamp_t(unsigned long, dout, 1, 128);
dout = clamp_t(unsigned long, dout, 1, 128 << fract_shift);
f = fvco / dout;
if (abs(f - fout) < abs(best_f - fout)) {
best_f = f;
*best_d = d;
*best_m = m;
*best_dout = dout;
*best_m = m << (3 - fract_shift);
*best_dout = dout << (3 - fract_shift);
if (best_f == fout)
return;
}
}
}
/* Lets see if we find a better setting in fractional mode */
if (fract_shift == 0) {
fract_shift = 3;
goto again;
}
}
static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low,
unsigned int *high, unsigned int *edge, unsigned int *nocount)
{
if (divider == 1)
*nocount = 1;
else
*nocount = 0;
struct axi_clkgen_div_params {
unsigned int low;
unsigned int high;
unsigned int edge;
unsigned int nocount;
unsigned int frac_en;
unsigned int frac;
unsigned int frac_wf_f;
unsigned int frac_wf_r;
unsigned int frac_phase;
};
*high = divider / 2;
*edge = divider % 2;
*low = divider - *high;
static void axi_clkgen_calc_clk_params(unsigned int divider,
unsigned int frac_divider, struct axi_clkgen_div_params *params)
{
memset(params, 0x0, sizeof(*params));
if (divider == 1) {
params->nocount = 1;
return;
}
if (frac_divider == 0) {
params->high = divider / 2;
params->edge = divider % 2;
params->low = divider - params->high;
} else {
params->frac_en = 1;
params->frac = frac_divider;
params->high = divider / 2;
params->edge = divider % 2;
params->low = params->high;
if (params->edge == 0) {
params->high--;
params->frac_wf_r = 1;
}
if (params->edge == 0 || frac_divider == 1)
params->low--;
if (((params->edge == 0) ^ (frac_divider == 1)) ||
(divider == 2 && frac_divider == 1))
params->frac_wf_f = 1;
params->frac_phase = params->edge * 4 + frac_divider / 2;
}
}
static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
@ -246,15 +299,29 @@ static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
return container_of(clk_hw, struct axi_clkgen, clk_hw);
}
static void axi_clkgen_set_div(struct axi_clkgen *axi_clkgen,
unsigned int reg1, unsigned int reg2, unsigned int reg3,
struct axi_clkgen_div_params *params)
{
axi_clkgen_mmcm_write(axi_clkgen, reg1,
(params->high << 6) | params->low, 0xefff);
axi_clkgen_mmcm_write(axi_clkgen, reg2,
(params->frac << 12) | (params->frac_en << 11) |
(params->frac_wf_r << 10) | (params->edge << 7) |
(params->nocount << 6), 0x7fff);
if (reg3 != 0) {
axi_clkgen_mmcm_write(axi_clkgen, reg3,
(params->frac_phase << 11) | (params->frac_wf_f << 10), 0x3c00);
}
}
static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
unsigned long rate, unsigned long parent_rate)
{
struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
unsigned int d, m, dout;
unsigned int nocount;
unsigned int high;
unsigned int edge;
unsigned int low;
struct axi_clkgen_div_params params;
uint32_t power = 0;
uint32_t filter;
uint32_t lock;
@ -266,24 +333,26 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
if (d == 0 || dout == 0 || m == 0)
return -EINVAL;
if ((dout & 0x7) != 0 || (m & 0x7) != 0)
power |= 0x9800;
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_POWER, power, 0x9800);
filter = axi_clkgen_lookup_filter(m - 1);
lock = axi_clkgen_lookup_lock(m - 1);
axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount);
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1,
(high << 6) | low, 0xefff);
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2,
(edge << 7) | (nocount << 6), 0x03ff);
axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, &params);
axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2,
MMCM_REG_CLKOUT5_2, &params);
axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount);
axi_clkgen_calc_clk_params(d, 0, &params);
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV,
(edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff);
(params.edge << 13) | (params.nocount << 12) |
(params.high << 6) | params.low, 0x3fff);
axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount);
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1,
(high << 6) | low, 0xefff);
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2,
(edge << 7) | (nocount << 6), 0x03ff);
axi_clkgen_calc_clk_params(m >> 3, m & 0x7, &params);
axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2,
MMCM_REG_CLKOUT6_2, &params);
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff);
axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2,
@ -313,35 +382,51 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
return min_t(unsigned long long, tmp, LONG_MAX);
}
static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen,
unsigned int reg1, unsigned int reg2)
{
unsigned int val1, val2;
unsigned int div;
axi_clkgen_mmcm_read(axi_clkgen, reg2, &val2);
if (val2 & MMCM_CLKOUT_NOCOUNT)
return 8;
axi_clkgen_mmcm_read(axi_clkgen, reg1, &val1);
div = (val1 & 0x3f) + ((val1 >> 6) & 0x3f);
div <<= 3;
if (val2 & MMCM_CLK_DIV_DIVIDE) {
if ((val2 & BIT(7)) && (val2 & 0x7000) != 0x1000)
div += 8;
else
div += 16;
div += (val2 >> 12) & 0x7;
}
return div;
}
static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
unsigned long parent_rate)
{
struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
unsigned int d, m, dout;
unsigned int reg;
unsigned long long tmp;
unsigned int val;
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, &reg);
if (reg & MMCM_CLKOUT_NOCOUNT) {
dout = 1;
} else {
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, &reg);
dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
}
dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1,
MMCM_REG_CLKOUT0_2);
m = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLK_FB1,
MMCM_REG_CLK_FB2);
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &reg);
if (reg & MMCM_CLK_DIV_NOCOUNT)
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &val);
if (val & MMCM_CLK_DIV_NOCOUNT)
d = 1;
else
d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB2, &reg);
if (reg & MMCM_CLKOUT_NOCOUNT) {
m = 1;
} else {
axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, &reg);
m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
}
d = (val & 0x3f) + ((val >> 6) & 0x3f);
if (d == 0 || dout == 0)
return 0;

View File

@ -328,6 +328,7 @@ struct clk_hw *clk_hw_register_composite(struct device *dev, const char *name,
rate_hw, rate_ops, gate_hw,
gate_ops, flags);
}
EXPORT_SYMBOL_GPL(clk_hw_register_composite);
struct clk_hw *clk_hw_register_composite_pdata(struct device *dev,
const char *name,

View File

@ -206,6 +206,7 @@ static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node)
/**
* of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
* @node: device node for the clock
*/
void __init of_fixed_factor_clk_setup(struct device_node *node)
{

View File

@ -168,6 +168,7 @@ static struct clk_hw *_of_fixed_clk_setup(struct device_node *node)
/**
* of_fixed_clk_setup() - Setup function for simple fixed rate clock
* @node: device node for the clock
*/
void __init of_fixed_clk_setup(struct device_node *node)
{

View File

@ -31,7 +31,7 @@
#define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */
#define CGB_PLL1 4
#define CGB_PLL2 5
#define MAX_PLL_DIV 16
#define MAX_PLL_DIV 32
struct clockgen_pll_div {
struct clk *clk;

View File

@ -267,18 +267,7 @@ static struct platform_driver s2mps11_clk_driver = {
.remove = s2mps11_clk_remove,
.id_table = s2mps11_clk_id,
};
static int __init s2mps11_clk_init(void)
{
return platform_driver_register(&s2mps11_clk_driver);
}
subsys_initcall(s2mps11_clk_init);
static void __exit s2mps11_clk_cleanup(void)
{
platform_driver_unregister(&s2mps11_clk_driver);
}
module_exit(s2mps11_clk_cleanup);
module_platform_driver(s2mps11_clk_driver);
MODULE_DESCRIPTION("S2MPS11 Clock Driver");
MODULE_AUTHOR("Yadwinder Singh Brar <yadi.brar@samsung.com>");

View File

@ -883,11 +883,9 @@ static int si5341_output_set_parent(struct clk_hw *hw, u8 index)
static u8 si5341_output_get_parent(struct clk_hw *hw)
{
struct clk_si5341_output *output = to_clk_si5341_output(hw);
int err;
u32 val;
err = regmap_read(output->data->regmap,
SI5341_OUT_MUX_SEL(output), &val);
regmap_read(output->data->regmap, SI5341_OUT_MUX_SEL(output), &val);
return val & 0x7;
}

View File

@ -571,6 +571,7 @@ static const struct clk_ops da8xx_usb1_clk48_ops = {
/**
* da8xx_cfgchip_register_usb1_clk48 - Register a new USB 1.1 PHY clock
* @dev: The device
* @regmap: The CFGCHIP regmap
*/
static struct da8xx_usb1_clk48 *

View File

@ -1,40 +1,102 @@
# SPDX-License-Identifier: GPL-2.0
# common clock support for NXP i.MX SoC family.
config MXC_CLK
bool
def_bool ARCH_MXC
tristate "IMX clock"
depends on ARCH_MXC || COMPILE_TEST
config MXC_CLK_SCU
bool
depends on IMX_SCU
tristate "IMX SCU clock"
depends on ARCH_MXC || COMPILE_TEST
depends on IMX_SCU && HAVE_ARM_SMCCC
config CLK_IMX1
def_bool SOC_IMX1
select MXC_CLK
config CLK_IMX25
def_bool SOC_IMX25
select MXC_CLK
config CLK_IMX27
def_bool SOC_IMX27
select MXC_CLK
config CLK_IMX31
def_bool SOC_IMX31
select MXC_CLK
config CLK_IMX35
def_bool SOC_IMX35
select MXC_CLK
config CLK_IMX5
def_bool SOC_IMX5
select MXC_CLK
config CLK_IMX6Q
def_bool SOC_IMX6Q
select MXC_CLK
config CLK_IMX6SL
def_bool SOC_IMX6SL
select MXC_CLK
config CLK_IMX6SLL
def_bool SOC_IMX6SLL
select MXC_CLK
config CLK_IMX6SX
def_bool SOC_IMX6SX
select MXC_CLK
config CLK_IMX6UL
def_bool SOC_IMX6UL
select MXC_CLK
config CLK_IMX7D
def_bool SOC_IMX7D
select MXC_CLK
config CLK_IMX7ULP
def_bool SOC_IMX7ULP
select MXC_CLK
config CLK_VF610
def_bool SOC_VF610
select MXC_CLK
config CLK_IMX8MM
bool "IMX8MM CCM Clock Driver"
depends on ARCH_MXC
tristate "IMX8MM CCM Clock Driver"
depends on ARCH_MXC || COMPILE_TEST
select MXC_CLK
help
Build the driver for i.MX8MM CCM Clock Driver
config CLK_IMX8MN
bool "IMX8MN CCM Clock Driver"
depends on ARCH_MXC
tristate "IMX8MN CCM Clock Driver"
depends on ARCH_MXC || COMPILE_TEST
select MXC_CLK
help
Build the driver for i.MX8MN CCM Clock Driver
config CLK_IMX8MP
bool "IMX8MP CCM Clock Driver"
depends on ARCH_MXC
tristate "IMX8MP CCM Clock Driver"
depends on ARCH_MXC || COMPILE_TEST
select MXC_CLK
help
Build the driver for i.MX8MP CCM Clock Driver
config CLK_IMX8MQ
bool "IMX8MQ CCM Clock Driver"
depends on ARCH_MXC
tristate "IMX8MQ CCM Clock Driver"
depends on ARCH_MXC || COMPILE_TEST
select MXC_CLK
help
Build the driver for i.MX8MQ CCM Clock Driver
config CLK_IMX8QXP
bool "IMX8QXP SCU Clock"
depends on ARCH_MXC && IMX_SCU && ARM64
tristate "IMX8QXP SCU Clock"
depends on (ARCH_MXC && ARM64) || COMPILE_TEST
depends on IMX_SCU && HAVE_ARM_SMCCC
select MXC_CLK_SCU
help
Build the driver for IMX8QXP SCU based clocks.

View File

@ -1,48 +1,46 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_MXC_CLK) += \
clk.o \
clk-busy.o \
clk-composite-8m.o \
clk-cpu.o \
clk-composite-7ulp.o \
clk-divider-gate.o \
clk-fixup-div.o \
clk-fixup-mux.o \
clk-frac-pll.o \
clk-gate-exclusive.o \
clk-gate2.o \
clk-pfd.o \
clk-pfdv2.o \
clk-pllv1.o \
clk-pllv2.o \
clk-pllv3.o \
clk-pllv4.o \
clk-sscg-pll.o \
clk-pll14xx.o
obj-$(CONFIG_MXC_CLK_SCU) += \
clk-scu.o \
clk-lpcg-scu.o
mxc-clk-objs += clk.o
mxc-clk-objs += clk-busy.o
mxc-clk-objs += clk-composite-7ulp.o
mxc-clk-objs += clk-composite-8m.o
mxc-clk-objs += clk-cpu.o
mxc-clk-objs += clk-divider-gate.o
mxc-clk-objs += clk-fixup-div.o
mxc-clk-objs += clk-fixup-mux.o
mxc-clk-objs += clk-frac-pll.o
mxc-clk-objs += clk-gate2.o
mxc-clk-objs += clk-gate-exclusive.o
mxc-clk-objs += clk-pfd.o
mxc-clk-objs += clk-pfdv2.o
mxc-clk-objs += clk-pllv1.o
mxc-clk-objs += clk-pllv2.o
mxc-clk-objs += clk-pllv3.o
mxc-clk-objs += clk-pllv4.o
mxc-clk-objs += clk-pll14xx.o
mxc-clk-objs += clk-sscg-pll.o
obj-$(CONFIG_MXC_CLK) += mxc-clk.o
obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
obj-$(CONFIG_CLK_IMX8MN) += clk-imx8mn.o
obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o
obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
obj-$(CONFIG_SOC_IMX1) += clk-imx1.o
obj-$(CONFIG_SOC_IMX21) += clk-imx21.o
obj-$(CONFIG_SOC_IMX25) += clk-imx25.o
obj-$(CONFIG_SOC_IMX27) += clk-imx27.o
obj-$(CONFIG_SOC_IMX31) += clk-imx31.o
obj-$(CONFIG_SOC_IMX35) += clk-imx35.o
obj-$(CONFIG_SOC_IMX5) += clk-imx5.o
obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o
obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o
obj-$(CONFIG_SOC_IMX6SLL) += clk-imx6sll.o
obj-$(CONFIG_SOC_IMX6SX) += clk-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_SOC_IMX7D) += clk-imx7d.o
obj-$(CONFIG_SOC_IMX7ULP) += clk-imx7ulp.o
obj-$(CONFIG_SOC_VF610) += clk-vf610.o
obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o
clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o
clk-imx-lpcg-scu-$(CONFIG_CLK_IMX8QXP) += clk-lpcg-scu.o clk-imx8qxp-lpcg.o
obj-$(CONFIG_CLK_IMX1) += clk-imx1.o
obj-$(CONFIG_CLK_IMX25) += clk-imx25.o
obj-$(CONFIG_CLK_IMX27) += clk-imx27.o
obj-$(CONFIG_CLK_IMX31) += clk-imx31.o
obj-$(CONFIG_CLK_IMX35) += clk-imx35.o
obj-$(CONFIG_CLK_IMX5) += clk-imx5.o
obj-$(CONFIG_CLK_IMX6Q) += clk-imx6q.o
obj-$(CONFIG_CLK_IMX6SL) += clk-imx6sl.o
obj-$(CONFIG_CLK_IMX6SLL) += clk-imx6sll.o
obj-$(CONFIG_CLK_IMX6SX) += clk-imx6sx.o
obj-$(CONFIG_CLK_IMX6UL) += clk-imx6ul.o
obj-$(CONFIG_CLK_IMX7D) += clk-imx7d.o
obj-$(CONFIG_CLK_IMX7ULP) += clk-imx7ulp.o
obj-$(CONFIG_CLK_VF610) += clk-vf610.o

View File

@ -4,6 +4,7 @@
* Copyright 2012 Linaro Ltd.
*/
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/io.h>

View File

@ -5,6 +5,7 @@
*
*/
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/slab.h>

View File

@ -5,6 +5,7 @@
#include <linux/clk-provider.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/slab.h>
@ -215,6 +216,7 @@ struct clk_hw *imx8m_clk_hw_composite_flags(const char *name,
div->width = PCG_PREDIV_WIDTH;
divider_ops = &imx8m_clk_composite_divider_ops;
mux_ops = &clk_mux_ops;
flags |= CLK_SET_PARENT_GATE;
}
div->lock = &imx_ccm_lock;
@ -243,3 +245,4 @@ fail:
kfree(mux);
return ERR_CAST(hw);
}
EXPORT_SYMBOL_GPL(imx8m_clk_hw_composite_flags);

View File

@ -5,6 +5,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/export.h>
#include <linux/slab.h>
#include "clk.h"
@ -104,3 +105,4 @@ struct clk_hw *imx_clk_hw_cpu(const char *name, const char *parent_name,
return hw;
}
EXPORT_SYMBOL_GPL(imx_clk_hw_cpu);

View File

@ -3,6 +3,7 @@
* Copyright (C) 2013 Freescale Semiconductor, Inc.
*/
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>

View File

@ -10,6 +10,7 @@
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/slab.h>
@ -233,3 +234,4 @@ struct clk_hw *imx_clk_hw_frac_pll(const char *name,
return hw;
}
EXPORT_SYMBOL_GPL(imx_clk_hw_frac_pll);

View File

@ -7,6 +7,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
@ -15,7 +16,7 @@
#include "clk.h"
/**
* DOC: basic gatable clock which can gate and ungate it's ouput
* DOC: basic gateable clock which can gate and ungate its output
*
* Traits of this clock:
* prepare - clk_(un)prepare only ensures parent is (un)prepared
@ -177,3 +178,4 @@ struct clk_hw *clk_hw_register_gate2(struct device *dev, const char *name,
return hw;
}
EXPORT_SYMBOL_GPL(clk_hw_register_gate2);

View File

@ -1,171 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2008 Juergen Beisert, kernel@pengutronix.de
* Copyright 2008 Martin Fuzzey, mfuzzey@gmail.com
*/
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/imx21-clock.h>
#include <soc/imx/timer.h>
#include <asm/irq.h>
#include "clk.h"
#define MX21_CCM_BASE_ADDR 0x10027000
#define MX21_GPT1_BASE_ADDR 0x10003000
#define MX21_INT_GPT1 (NR_IRQS_LEGACY + 26)
static void __iomem *ccm __initdata;
/* Register offsets */
#define CCM_CSCR (ccm + 0x00)
#define CCM_MPCTL0 (ccm + 0x04)
#define CCM_SPCTL0 (ccm + 0x0c)
#define CCM_PCDR0 (ccm + 0x18)
#define CCM_PCDR1 (ccm + 0x1c)
#define CCM_PCCR0 (ccm + 0x20)
#define CCM_PCCR1 (ccm + 0x24)
static const char *mpll_osc_sel_clks[] = { "ckih_gate", "ckih_div1p5", };
static const char *mpll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", };
static const char *spll_sel_clks[] = { "fpm_gate", "mpll_osc_sel", };
static const char *ssi_sel_clks[] = { "spll_gate", "mpll_gate", };
static struct clk *clk[IMX21_CLK_MAX];
static struct clk_onecell_data clk_data;
static void __init _mx21_clocks_init(unsigned long lref, unsigned long href)
{
BUG_ON(!ccm);
clk[IMX21_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
clk[IMX21_CLK_CKIL] = imx_obtain_fixed_clock("ckil", lref);
clk[IMX21_CLK_CKIH] = imx_obtain_fixed_clock("ckih", href);
clk[IMX21_CLK_FPM] = imx_clk_fixed_factor("fpm", "ckil", 512, 1);
clk[IMX21_CLK_CKIH_DIV1P5] = imx_clk_fixed_factor("ckih_div1p5", "ckih_gate", 2, 3);
clk[IMX21_CLK_MPLL_GATE] = imx_clk_gate("mpll_gate", "mpll", CCM_CSCR, 0);
clk[IMX21_CLK_SPLL_GATE] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
clk[IMX21_CLK_FPM_GATE] = imx_clk_gate("fpm_gate", "fpm", CCM_CSCR, 2);
clk[IMX21_CLK_CKIH_GATE] = imx_clk_gate_dis("ckih_gate", "ckih", CCM_CSCR, 3);
clk[IMX21_CLK_MPLL_OSC_SEL] = imx_clk_mux("mpll_osc_sel", CCM_CSCR, 4, 1, mpll_osc_sel_clks, ARRAY_SIZE(mpll_osc_sel_clks));
clk[IMX21_CLK_IPG] = imx_clk_divider("ipg", "hclk", CCM_CSCR, 9, 1);
clk[IMX21_CLK_HCLK] = imx_clk_divider("hclk", "fclk", CCM_CSCR, 10, 4);
clk[IMX21_CLK_MPLL_SEL] = imx_clk_mux("mpll_sel", CCM_CSCR, 16, 1, mpll_sel_clks, ARRAY_SIZE(mpll_sel_clks));
clk[IMX21_CLK_SPLL_SEL] = imx_clk_mux("spll_sel", CCM_CSCR, 17, 1, spll_sel_clks, ARRAY_SIZE(spll_sel_clks));
clk[IMX21_CLK_SSI1_SEL] = imx_clk_mux("ssi1_sel", CCM_CSCR, 19, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
clk[IMX21_CLK_SSI2_SEL] = imx_clk_mux("ssi2_sel", CCM_CSCR, 20, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
clk[IMX21_CLK_USB_DIV] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 26, 3);
clk[IMX21_CLK_FCLK] = imx_clk_divider("fclk", "mpll_gate", CCM_CSCR, 29, 3);
clk[IMX21_CLK_MPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "mpll", "mpll_sel", CCM_MPCTL0);
clk[IMX21_CLK_SPLL] = imx_clk_pllv1(IMX_PLLV1_IMX21, "spll", "spll_sel", CCM_SPCTL0);
clk[IMX21_CLK_NFC_DIV] = imx_clk_divider("nfc_div", "fclk", CCM_PCDR0, 12, 4);
clk[IMX21_CLK_SSI1_DIV] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
clk[IMX21_CLK_SSI2_DIV] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
clk[IMX21_CLK_PER1] = imx_clk_divider("per1", "mpll_gate", CCM_PCDR1, 0, 6);
clk[IMX21_CLK_PER2] = imx_clk_divider("per2", "mpll_gate", CCM_PCDR1, 8, 6);
clk[IMX21_CLK_PER3] = imx_clk_divider("per3", "mpll_gate", CCM_PCDR1, 16, 6);
clk[IMX21_CLK_PER4] = imx_clk_divider("per4", "mpll_gate", CCM_PCDR1, 24, 6);
clk[IMX21_CLK_UART1_IPG_GATE] = imx_clk_gate("uart1_ipg_gate", "ipg", CCM_PCCR0, 0);
clk[IMX21_CLK_UART2_IPG_GATE] = imx_clk_gate("uart2_ipg_gate", "ipg", CCM_PCCR0, 1);
clk[IMX21_CLK_UART3_IPG_GATE] = imx_clk_gate("uart3_ipg_gate", "ipg", CCM_PCCR0, 2);
clk[IMX21_CLK_UART4_IPG_GATE] = imx_clk_gate("uart4_ipg_gate", "ipg", CCM_PCCR0, 3);
clk[IMX21_CLK_CSPI1_IPG_GATE] = imx_clk_gate("cspi1_ipg_gate", "ipg", CCM_PCCR0, 4);
clk[IMX21_CLK_CSPI2_IPG_GATE] = imx_clk_gate("cspi2_ipg_gate", "ipg", CCM_PCCR0, 5);
clk[IMX21_CLK_SSI1_GATE] = imx_clk_gate("ssi1_gate", "ipg", CCM_PCCR0, 6);
clk[IMX21_CLK_SSI2_GATE] = imx_clk_gate("ssi2_gate", "ipg", CCM_PCCR0, 7);
clk[IMX21_CLK_SDHC1_IPG_GATE] = imx_clk_gate("sdhc1_ipg_gate", "ipg", CCM_PCCR0, 9);
clk[IMX21_CLK_SDHC2_IPG_GATE] = imx_clk_gate("sdhc2_ipg_gate", "ipg", CCM_PCCR0, 10);
clk[IMX21_CLK_GPIO_GATE] = imx_clk_gate("gpio_gate", "ipg", CCM_PCCR0, 11);
clk[IMX21_CLK_I2C_GATE] = imx_clk_gate("i2c_gate", "ipg", CCM_PCCR0, 12);
clk[IMX21_CLK_DMA_GATE] = imx_clk_gate("dma_gate", "ipg", CCM_PCCR0, 13);
clk[IMX21_CLK_USB_GATE] = imx_clk_gate("usb_gate", "usb_div", CCM_PCCR0, 14);
clk[IMX21_CLK_EMMA_GATE] = imx_clk_gate("emma_gate", "ipg", CCM_PCCR0, 15);
clk[IMX21_CLK_SSI2_BAUD_GATE] = imx_clk_gate("ssi2_baud_gate", "ipg", CCM_PCCR0, 16);
clk[IMX21_CLK_SSI1_BAUD_GATE] = imx_clk_gate("ssi1_baud_gate", "ipg", CCM_PCCR0, 17);
clk[IMX21_CLK_LCDC_IPG_GATE] = imx_clk_gate("lcdc_ipg_gate", "ipg", CCM_PCCR0, 18);
clk[IMX21_CLK_NFC_GATE] = imx_clk_gate("nfc_gate", "nfc_div", CCM_PCCR0, 19);
clk[IMX21_CLK_SLCDC_HCLK_GATE] = imx_clk_gate("slcdc_hclk_gate", "hclk", CCM_PCCR0, 21);
clk[IMX21_CLK_PER4_GATE] = imx_clk_gate("per4_gate", "per4", CCM_PCCR0, 22);
clk[IMX21_CLK_BMI_GATE] = imx_clk_gate("bmi_gate", "hclk", CCM_PCCR0, 23);
clk[IMX21_CLK_USB_HCLK_GATE] = imx_clk_gate("usb_hclk_gate", "hclk", CCM_PCCR0, 24);
clk[IMX21_CLK_SLCDC_GATE] = imx_clk_gate("slcdc_gate", "hclk", CCM_PCCR0, 25);
clk[IMX21_CLK_LCDC_HCLK_GATE] = imx_clk_gate("lcdc_hclk_gate", "hclk", CCM_PCCR0, 26);
clk[IMX21_CLK_EMMA_HCLK_GATE] = imx_clk_gate("emma_hclk_gate", "hclk", CCM_PCCR0, 27);
clk[IMX21_CLK_BROM_GATE] = imx_clk_gate("brom_gate", "hclk", CCM_PCCR0, 28);
clk[IMX21_CLK_DMA_HCLK_GATE] = imx_clk_gate("dma_hclk_gate", "hclk", CCM_PCCR0, 30);
clk[IMX21_CLK_CSI_HCLK_GATE] = imx_clk_gate("csi_hclk_gate", "hclk", CCM_PCCR0, 31);
clk[IMX21_CLK_CSPI3_IPG_GATE] = imx_clk_gate("cspi3_ipg_gate", "ipg", CCM_PCCR1, 23);
clk[IMX21_CLK_WDOG_GATE] = imx_clk_gate("wdog_gate", "ipg", CCM_PCCR1, 24);
clk[IMX21_CLK_GPT1_IPG_GATE] = imx_clk_gate("gpt1_ipg_gate", "ipg", CCM_PCCR1, 25);
clk[IMX21_CLK_GPT2_IPG_GATE] = imx_clk_gate("gpt2_ipg_gate", "ipg", CCM_PCCR1, 26);
clk[IMX21_CLK_GPT3_IPG_GATE] = imx_clk_gate("gpt3_ipg_gate", "ipg", CCM_PCCR1, 27);
clk[IMX21_CLK_PWM_IPG_GATE] = imx_clk_gate("pwm_ipg_gate", "ipg", CCM_PCCR1, 28);
clk[IMX21_CLK_RTC_GATE] = imx_clk_gate("rtc_gate", "ipg", CCM_PCCR1, 29);
clk[IMX21_CLK_KPP_GATE] = imx_clk_gate("kpp_gate", "ipg", CCM_PCCR1, 30);
clk[IMX21_CLK_OWIRE_GATE] = imx_clk_gate("owire_gate", "ipg", CCM_PCCR1, 31);
imx_check_clocks(clk, ARRAY_SIZE(clk));
}
int __init mx21_clocks_init(unsigned long lref, unsigned long href)
{
ccm = ioremap(MX21_CCM_BASE_ADDR, SZ_2K);
_mx21_clocks_init(lref, href);
clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.0");
clk_register_clkdev(clk[IMX21_CLK_UART1_IPG_GATE], "ipg", "imx21-uart.0");
clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.1");
clk_register_clkdev(clk[IMX21_CLK_UART2_IPG_GATE], "ipg", "imx21-uart.1");
clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.2");
clk_register_clkdev(clk[IMX21_CLK_UART3_IPG_GATE], "ipg", "imx21-uart.2");
clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx21-uart.3");
clk_register_clkdev(clk[IMX21_CLK_UART4_IPG_GATE], "ipg", "imx21-uart.3");
clk_register_clkdev(clk[IMX21_CLK_GPT1_IPG_GATE], "ipg", "imx-gpt.0");
clk_register_clkdev(clk[IMX21_CLK_PER1], "per", "imx-gpt.0");
clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.0");
clk_register_clkdev(clk[IMX21_CLK_CSPI1_IPG_GATE], "ipg", "imx21-cspi.0");
clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.1");
clk_register_clkdev(clk[IMX21_CLK_CSPI2_IPG_GATE], "ipg", "imx21-cspi.1");
clk_register_clkdev(clk[IMX21_CLK_PER2], "per", "imx21-cspi.2");
clk_register_clkdev(clk[IMX21_CLK_CSPI3_IPG_GATE], "ipg", "imx21-cspi.2");
clk_register_clkdev(clk[IMX21_CLK_PER3], "per", "imx21-fb.0");
clk_register_clkdev(clk[IMX21_CLK_LCDC_IPG_GATE], "ipg", "imx21-fb.0");
clk_register_clkdev(clk[IMX21_CLK_LCDC_HCLK_GATE], "ahb", "imx21-fb.0");
clk_register_clkdev(clk[IMX21_CLK_USB_GATE], "per", "imx21-hcd.0");
clk_register_clkdev(clk[IMX21_CLK_USB_HCLK_GATE], "ahb", "imx21-hcd.0");
clk_register_clkdev(clk[IMX21_CLK_NFC_GATE], NULL, "imx21-nand.0");
clk_register_clkdev(clk[IMX21_CLK_DMA_HCLK_GATE], "ahb", "imx21-dma");
clk_register_clkdev(clk[IMX21_CLK_DMA_GATE], "ipg", "imx21-dma");
clk_register_clkdev(clk[IMX21_CLK_WDOG_GATE], NULL, "imx2-wdt.0");
clk_register_clkdev(clk[IMX21_CLK_I2C_GATE], NULL, "imx21-i2c.0");
clk_register_clkdev(clk[IMX21_CLK_OWIRE_GATE], NULL, "mxc_w1.0");
mxc_timer_init(MX21_GPT1_BASE_ADDR, MX21_INT_GPT1, GPT_TYPE_IMX21);
return 0;
}
static void __init mx21_clocks_init_dt(struct device_node *np)
{
ccm = of_iomap(np, 0);
_mx21_clocks_init(32768, 26000000);
clk_data.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
}
CLK_OF_DECLARE(imx27_ccm, "fsl,imx21-ccm", mx21_clocks_init_dt);

View File

@ -6,6 +6,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>

View File

@ -3,6 +3,7 @@
* Copyright 2013-2014 Freescale Semiconductor, Inc.
*/
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
@ -14,19 +15,19 @@
#include "clk.h"
#define CCSR 0xc
#define BM_CCSR_PLL1_SW_CLK_SEL (1 << 2)
#define BM_CCSR_PLL1_SW_CLK_SEL BIT(2)
#define CACRR 0x10
#define CDHIPR 0x48
#define BM_CDHIPR_ARM_PODF_BUSY (1 << 16)
#define BM_CDHIPR_ARM_PODF_BUSY BIT(16)
#define ARM_WAIT_DIV_396M 2
#define ARM_WAIT_DIV_792M 4
#define ARM_WAIT_DIV_996M 6
#define PLL_ARM 0x0
#define BM_PLL_ARM_DIV_SELECT (0x7f << 0)
#define BM_PLL_ARM_POWERDOWN (1 << 12)
#define BM_PLL_ARM_ENABLE (1 << 13)
#define BM_PLL_ARM_LOCK (1 << 31)
#define BM_PLL_ARM_DIV_SELECT 0x7f
#define BM_PLL_ARM_POWERDOWN BIT(12)
#define BM_PLL_ARM_ENABLE BIT(13)
#define BM_PLL_ARM_LOCK BIT(31)
#define PLL_ARM_DIV_792M 66
static const char *step_sels[] = { "osc", "pll2_pfd2", };
@ -145,7 +146,7 @@ static void imx6sl_enable_pll_arm(bool enable)
val |= BM_PLL_ARM_ENABLE;
val &= ~BM_PLL_ARM_POWERDOWN;
writel_relaxed(val, anatop_base + PLL_ARM);
while (!(__raw_readl(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK))
while (!(readl_relaxed(anatop_base + PLL_ARM) & BM_PLL_ARM_LOCK))
;
} else {
writel_relaxed(saved_pll_arm, anatop_base + PLL_ARM);

View File

@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/imx6sx-clock.h>
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>

View File

@ -4,6 +4,7 @@
*/
#include <dt-bindings/clock/imx7d-clock.h>
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
@ -505,72 +506,73 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
hws[IMX7D_ARM_M4_ROOT_SRC] = imx_clk_hw_mux2("arm_m4_src", base + 0x8080, 24, 3, arm_m4_sel, ARRAY_SIZE(arm_m4_sel));
hws[IMX7D_MAIN_AXI_ROOT_SRC] = imx_clk_hw_mux2("axi_src", base + 0x8800, 24, 3, axi_sel, ARRAY_SIZE(axi_sel));
hws[IMX7D_DISP_AXI_ROOT_SRC] = imx_clk_hw_mux2("disp_axi_src", base + 0x8880, 24, 3, disp_axi_sel, ARRAY_SIZE(disp_axi_sel));
hws[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_hw_mux2("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel));
hws[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_hw_mux2("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel));
hws[IMX7D_AHB_CHANNEL_ROOT_SRC] = imx_clk_hw_mux2("ahb_src", base + 0x9000, 24, 3, ahb_channel_sel, ARRAY_SIZE(ahb_channel_sel));
hws[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_hw_mux2("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel));
hws[IMX7D_DRAM_ROOT_SRC] = imx_clk_hw_mux2("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel));
hws[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_hw_mux2("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel));
hws[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_hw_mux2("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel));
hws[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_hw_mux2("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel));
hws[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_hw_mux2("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel));
hws[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_hw_mux2("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel));
hws[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_hw_mux2("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel));
hws[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_hw_mux2("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel));
hws[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_hw_mux2("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel));
hws[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_hw_mux2("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel));
hws[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_hw_mux2("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel));
hws[IMX7D_SAI1_ROOT_SRC] = imx_clk_hw_mux2("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel));
hws[IMX7D_SAI2_ROOT_SRC] = imx_clk_hw_mux2("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel));
hws[IMX7D_SAI3_ROOT_SRC] = imx_clk_hw_mux2("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel));
hws[IMX7D_SPDIF_ROOT_SRC] = imx_clk_hw_mux2("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel));
hws[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_hw_mux2("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel));
hws[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_hw_mux2("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel));
hws[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_hw_mux2("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel));
hws[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_hw_mux2("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel));
hws[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_hw_mux2("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel));
hws[IMX7D_EIM_ROOT_SRC] = imx_clk_hw_mux2("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel));
hws[IMX7D_NAND_ROOT_SRC] = imx_clk_hw_mux2("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel));
hws[IMX7D_QSPI_ROOT_SRC] = imx_clk_hw_mux2("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel));
hws[IMX7D_USDHC1_ROOT_SRC] = imx_clk_hw_mux2("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel));
hws[IMX7D_USDHC2_ROOT_SRC] = imx_clk_hw_mux2("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel));
hws[IMX7D_USDHC3_ROOT_SRC] = imx_clk_hw_mux2("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel));
hws[IMX7D_CAN1_ROOT_SRC] = imx_clk_hw_mux2("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel));
hws[IMX7D_CAN2_ROOT_SRC] = imx_clk_hw_mux2("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel));
hws[IMX7D_I2C1_ROOT_SRC] = imx_clk_hw_mux2("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel));
hws[IMX7D_I2C2_ROOT_SRC] = imx_clk_hw_mux2("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel));
hws[IMX7D_I2C3_ROOT_SRC] = imx_clk_hw_mux2("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel));
hws[IMX7D_I2C4_ROOT_SRC] = imx_clk_hw_mux2("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel));
hws[IMX7D_UART1_ROOT_SRC] = imx_clk_hw_mux2("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel));
hws[IMX7D_UART2_ROOT_SRC] = imx_clk_hw_mux2("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel));
hws[IMX7D_UART3_ROOT_SRC] = imx_clk_hw_mux2("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel));
hws[IMX7D_UART4_ROOT_SRC] = imx_clk_hw_mux2("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel));
hws[IMX7D_UART5_ROOT_SRC] = imx_clk_hw_mux2("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel));
hws[IMX7D_UART6_ROOT_SRC] = imx_clk_hw_mux2("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel));
hws[IMX7D_UART7_ROOT_SRC] = imx_clk_hw_mux2("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel));
hws[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_hw_mux2("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel));
hws[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_hw_mux2("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel));
hws[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_hw_mux2("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel));
hws[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_hw_mux2("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel));
hws[IMX7D_PWM1_ROOT_SRC] = imx_clk_hw_mux2("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel));
hws[IMX7D_PWM2_ROOT_SRC] = imx_clk_hw_mux2("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel));
hws[IMX7D_PWM3_ROOT_SRC] = imx_clk_hw_mux2("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel));
hws[IMX7D_PWM4_ROOT_SRC] = imx_clk_hw_mux2("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel));
hws[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_hw_mux2("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel));
hws[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_hw_mux2("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel));
hws[IMX7D_SIM1_ROOT_SRC] = imx_clk_hw_mux2("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel));
hws[IMX7D_SIM2_ROOT_SRC] = imx_clk_hw_mux2("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel));
hws[IMX7D_GPT1_ROOT_SRC] = imx_clk_hw_mux2("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel));
hws[IMX7D_GPT2_ROOT_SRC] = imx_clk_hw_mux2("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel));
hws[IMX7D_GPT3_ROOT_SRC] = imx_clk_hw_mux2("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel));
hws[IMX7D_GPT4_ROOT_SRC] = imx_clk_hw_mux2("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel));
hws[IMX7D_TRACE_ROOT_SRC] = imx_clk_hw_mux2("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel));
hws[IMX7D_WDOG_ROOT_SRC] = imx_clk_hw_mux2("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel));
hws[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_hw_mux2("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel));
hws[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_hw_mux2("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel));
hws[IMX7D_WRCLK_ROOT_SRC] = imx_clk_hw_mux2("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel));
hws[IMX7D_CLKO1_ROOT_SRC] = imx_clk_hw_mux2("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel));
hws[IMX7D_CLKO2_ROOT_SRC] = imx_clk_hw_mux2("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel));
hws[IMX7D_ENET_AXI_ROOT_SRC] = imx_clk_hw_mux2_flags("enet_axi_src", base + 0x8900, 24, 3, enet_axi_sel, ARRAY_SIZE(enet_axi_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_NAND_USDHC_BUS_ROOT_SRC] = imx_clk_hw_mux2_flags("nand_usdhc_src", base + 0x8980, 24, 3, nand_usdhc_bus_sel, ARRAY_SIZE(nand_usdhc_bus_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_DRAM_PHYM_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_phym_src", base + 0x9800, 24, 1, dram_phym_sel, ARRAY_SIZE(dram_phym_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_DRAM_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_src", base + 0x9880, 24, 1, dram_sel, ARRAY_SIZE(dram_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_DRAM_PHYM_ALT_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_phym_alt_src", base + 0xa000, 24, 3, dram_phym_alt_sel, ARRAY_SIZE(dram_phym_alt_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_DRAM_ALT_ROOT_SRC] = imx_clk_hw_mux2_flags("dram_alt_src", base + 0xa080, 24, 3, dram_alt_sel, ARRAY_SIZE(dram_alt_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_USB_HSIC_ROOT_SRC] = imx_clk_hw_mux2_flags("usb_hsic_src", base + 0xa100, 24, 3, usb_hsic_sel, ARRAY_SIZE(usb_hsic_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_PCIE_CTRL_ROOT_SRC] = imx_clk_hw_mux2_flags("pcie_ctrl_src", base + 0xa180, 24, 3, pcie_ctrl_sel, ARRAY_SIZE(pcie_ctrl_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_PCIE_PHY_ROOT_SRC] = imx_clk_hw_mux2_flags("pcie_phy_src", base + 0xa200, 24, 3, pcie_phy_sel, ARRAY_SIZE(pcie_phy_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_EPDC_PIXEL_ROOT_SRC] = imx_clk_hw_mux2_flags("epdc_pixel_src", base + 0xa280, 24, 3, epdc_pixel_sel, ARRAY_SIZE(epdc_pixel_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_LCDIF_PIXEL_ROOT_SRC] = imx_clk_hw_mux2_flags("lcdif_pixel_src", base + 0xa300, 24, 3, lcdif_pixel_sel, ARRAY_SIZE(lcdif_pixel_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_MIPI_DSI_ROOT_SRC] = imx_clk_hw_mux2_flags("mipi_dsi_src", base + 0xa380, 24, 3, mipi_dsi_sel, ARRAY_SIZE(mipi_dsi_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_MIPI_CSI_ROOT_SRC] = imx_clk_hw_mux2_flags("mipi_csi_src", base + 0xa400, 24, 3, mipi_csi_sel, ARRAY_SIZE(mipi_csi_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_MIPI_DPHY_ROOT_SRC] = imx_clk_hw_mux2_flags("mipi_dphy_src", base + 0xa480, 24, 3, mipi_dphy_sel, ARRAY_SIZE(mipi_dphy_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_SAI1_ROOT_SRC] = imx_clk_hw_mux2_flags("sai1_src", base + 0xa500, 24, 3, sai1_sel, ARRAY_SIZE(sai1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_SAI2_ROOT_SRC] = imx_clk_hw_mux2_flags("sai2_src", base + 0xa580, 24, 3, sai2_sel, ARRAY_SIZE(sai2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_SAI3_ROOT_SRC] = imx_clk_hw_mux2_flags("sai3_src", base + 0xa600, 24, 3, sai3_sel, ARRAY_SIZE(sai3_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_SPDIF_ROOT_SRC] = imx_clk_hw_mux2_flags("spdif_src", base + 0xa680, 24, 3, spdif_sel, ARRAY_SIZE(spdif_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ENET1_REF_ROOT_SRC] = imx_clk_hw_mux2_flags("enet1_ref_src", base + 0xa700, 24, 3, enet1_ref_sel, ARRAY_SIZE(enet1_ref_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ENET1_TIME_ROOT_SRC] = imx_clk_hw_mux2_flags("enet1_time_src", base + 0xa780, 24, 3, enet1_time_sel, ARRAY_SIZE(enet1_time_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ENET2_REF_ROOT_SRC] = imx_clk_hw_mux2_flags("enet2_ref_src", base + 0xa800, 24, 3, enet2_ref_sel, ARRAY_SIZE(enet2_ref_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ENET2_TIME_ROOT_SRC] = imx_clk_hw_mux2_flags("enet2_time_src", base + 0xa880, 24, 3, enet2_time_sel, ARRAY_SIZE(enet2_time_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ENET_PHY_REF_ROOT_SRC] = imx_clk_hw_mux2_flags("enet_phy_ref_src", base + 0xa900, 24, 3, enet_phy_ref_sel, ARRAY_SIZE(enet_phy_ref_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_EIM_ROOT_SRC] = imx_clk_hw_mux2_flags("eim_src", base + 0xa980, 24, 3, eim_sel, ARRAY_SIZE(eim_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_NAND_ROOT_SRC] = imx_clk_hw_mux2_flags("nand_src", base + 0xaa00, 24, 3, nand_sel, ARRAY_SIZE(nand_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_QSPI_ROOT_SRC] = imx_clk_hw_mux2_flags("qspi_src", base + 0xaa80, 24, 3, qspi_sel, ARRAY_SIZE(qspi_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_USDHC1_ROOT_SRC] = imx_clk_hw_mux2_flags("usdhc1_src", base + 0xab00, 24, 3, usdhc1_sel, ARRAY_SIZE(usdhc1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_USDHC2_ROOT_SRC] = imx_clk_hw_mux2_flags("usdhc2_src", base + 0xab80, 24, 3, usdhc2_sel, ARRAY_SIZE(usdhc2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_USDHC3_ROOT_SRC] = imx_clk_hw_mux2_flags("usdhc3_src", base + 0xac00, 24, 3, usdhc3_sel, ARRAY_SIZE(usdhc3_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_CAN1_ROOT_SRC] = imx_clk_hw_mux2_flags("can1_src", base + 0xac80, 24, 3, can1_sel, ARRAY_SIZE(can1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_CAN2_ROOT_SRC] = imx_clk_hw_mux2_flags("can2_src", base + 0xad00, 24, 3, can2_sel, ARRAY_SIZE(can2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_I2C1_ROOT_SRC] = imx_clk_hw_mux2_flags("i2c1_src", base + 0xad80, 24, 3, i2c1_sel, ARRAY_SIZE(i2c1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_I2C2_ROOT_SRC] = imx_clk_hw_mux2_flags("i2c2_src", base + 0xae00, 24, 3, i2c2_sel, ARRAY_SIZE(i2c2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_I2C3_ROOT_SRC] = imx_clk_hw_mux2_flags("i2c3_src", base + 0xae80, 24, 3, i2c3_sel, ARRAY_SIZE(i2c3_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_I2C4_ROOT_SRC] = imx_clk_hw_mux2_flags("i2c4_src", base + 0xaf00, 24, 3, i2c4_sel, ARRAY_SIZE(i2c4_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_UART1_ROOT_SRC] = imx_clk_hw_mux2_flags("uart1_src", base + 0xaf80, 24, 3, uart1_sel, ARRAY_SIZE(uart1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_UART2_ROOT_SRC] = imx_clk_hw_mux2_flags("uart2_src", base + 0xb000, 24, 3, uart2_sel, ARRAY_SIZE(uart2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_UART3_ROOT_SRC] = imx_clk_hw_mux2_flags("uart3_src", base + 0xb080, 24, 3, uart3_sel, ARRAY_SIZE(uart3_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_UART4_ROOT_SRC] = imx_clk_hw_mux2_flags("uart4_src", base + 0xb100, 24, 3, uart4_sel, ARRAY_SIZE(uart4_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_UART5_ROOT_SRC] = imx_clk_hw_mux2_flags("uart5_src", base + 0xb180, 24, 3, uart5_sel, ARRAY_SIZE(uart5_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_UART6_ROOT_SRC] = imx_clk_hw_mux2_flags("uart6_src", base + 0xb200, 24, 3, uart6_sel, ARRAY_SIZE(uart6_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_UART7_ROOT_SRC] = imx_clk_hw_mux2_flags("uart7_src", base + 0xb280, 24, 3, uart7_sel, ARRAY_SIZE(uart7_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ECSPI1_ROOT_SRC] = imx_clk_hw_mux2_flags("ecspi1_src", base + 0xb300, 24, 3, ecspi1_sel, ARRAY_SIZE(ecspi1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ECSPI2_ROOT_SRC] = imx_clk_hw_mux2_flags("ecspi2_src", base + 0xb380, 24, 3, ecspi2_sel, ARRAY_SIZE(ecspi2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ECSPI3_ROOT_SRC] = imx_clk_hw_mux2_flags("ecspi3_src", base + 0xb400, 24, 3, ecspi3_sel, ARRAY_SIZE(ecspi3_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ECSPI4_ROOT_SRC] = imx_clk_hw_mux2_flags("ecspi4_src", base + 0xb480, 24, 3, ecspi4_sel, ARRAY_SIZE(ecspi4_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_PWM1_ROOT_SRC] = imx_clk_hw_mux2_flags("pwm1_src", base + 0xb500, 24, 3, pwm1_sel, ARRAY_SIZE(pwm1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_PWM2_ROOT_SRC] = imx_clk_hw_mux2_flags("pwm2_src", base + 0xb580, 24, 3, pwm2_sel, ARRAY_SIZE(pwm2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_PWM3_ROOT_SRC] = imx_clk_hw_mux2_flags("pwm3_src", base + 0xb600, 24, 3, pwm3_sel, ARRAY_SIZE(pwm3_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_PWM4_ROOT_SRC] = imx_clk_hw_mux2_flags("pwm4_src", base + 0xb680, 24, 3, pwm4_sel, ARRAY_SIZE(pwm4_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_FLEXTIMER1_ROOT_SRC] = imx_clk_hw_mux2_flags("flextimer1_src", base + 0xb700, 24, 3, flextimer1_sel, ARRAY_SIZE(flextimer1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_FLEXTIMER2_ROOT_SRC] = imx_clk_hw_mux2_flags("flextimer2_src", base + 0xb780, 24, 3, flextimer2_sel, ARRAY_SIZE(flextimer2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_SIM1_ROOT_SRC] = imx_clk_hw_mux2_flags("sim1_src", base + 0xb800, 24, 3, sim1_sel, ARRAY_SIZE(sim1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_SIM2_ROOT_SRC] = imx_clk_hw_mux2_flags("sim2_src", base + 0xb880, 24, 3, sim2_sel, ARRAY_SIZE(sim2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_GPT1_ROOT_SRC] = imx_clk_hw_mux2_flags("gpt1_src", base + 0xb900, 24, 3, gpt1_sel, ARRAY_SIZE(gpt1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_GPT2_ROOT_SRC] = imx_clk_hw_mux2_flags("gpt2_src", base + 0xb980, 24, 3, gpt2_sel, ARRAY_SIZE(gpt2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_GPT3_ROOT_SRC] = imx_clk_hw_mux2_flags("gpt3_src", base + 0xba00, 24, 3, gpt3_sel, ARRAY_SIZE(gpt3_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_GPT4_ROOT_SRC] = imx_clk_hw_mux2_flags("gpt4_src", base + 0xba80, 24, 3, gpt4_sel, ARRAY_SIZE(gpt4_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_TRACE_ROOT_SRC] = imx_clk_hw_mux2_flags("trace_src", base + 0xbb00, 24, 3, trace_sel, ARRAY_SIZE(trace_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_WDOG_ROOT_SRC] = imx_clk_hw_mux2_flags("wdog_src", base + 0xbb80, 24, 3, wdog_sel, ARRAY_SIZE(wdog_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_CSI_MCLK_ROOT_SRC] = imx_clk_hw_mux2_flags("csi_mclk_src", base + 0xbc00, 24, 3, csi_mclk_sel, ARRAY_SIZE(csi_mclk_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_AUDIO_MCLK_ROOT_SRC] = imx_clk_hw_mux2_flags("audio_mclk_src", base + 0xbc80, 24, 3, audio_mclk_sel, ARRAY_SIZE(audio_mclk_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_WRCLK_ROOT_SRC] = imx_clk_hw_mux2_flags("wrclk_src", base + 0xbd00, 24, 3, wrclk_sel, ARRAY_SIZE(wrclk_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_CLKO1_ROOT_SRC] = imx_clk_hw_mux2_flags("clko1_src", base + 0xbd80, 24, 3, clko1_sel, ARRAY_SIZE(clko1_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_CLKO2_ROOT_SRC] = imx_clk_hw_mux2_flags("clko2_src", base + 0xbe00, 24, 3, clko2_sel, ARRAY_SIZE(clko2_sel), CLK_SET_PARENT_GATE);
hws[IMX7D_ARM_A7_ROOT_CG] = imx_clk_hw_gate3("arm_a7_cg", "arm_a7_src", base + 0x8000, 28);
hws[IMX7D_ARM_M4_ROOT_CG] = imx_clk_hw_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);

View File

@ -657,3 +657,7 @@ static struct platform_driver imx8mm_clk_driver = {
},
};
module_platform_driver(imx8mm_clk_driver);
MODULE_AUTHOR("Bai Ping <ping.bai@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8MM clock driver");
MODULE_LICENSE("GPL v2");

View File

@ -608,3 +608,7 @@ static struct platform_driver imx8mn_clk_driver = {
},
};
module_platform_driver(imx8mn_clk_driver);
MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8MN clock driver");
MODULE_LICENSE("GPL v2");

View File

@ -152,10 +152,6 @@ static const char * const imx8mp_can2_sels[] = {"osc_24m", "sys_pll2_200m", "sys
"sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll2_out", };
static const char * const imx8mp_memrepair_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
"sys_pll3_out", "audio_pll1_out", "video_pll1_out",
"audio_pll2_out", "sys_pll1_133m", };
static const char * const imx8mp_pcie_phy_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll2_500m",
"clk_ext1", "clk_ext2", "clk_ext3",
"clk_ext4", "sys_pll1_400m", };
@ -375,15 +371,14 @@ static const char * const imx8mp_media_cam2_pix_sels[] = {"osc_24m", "sys_pll1_2
"sys_pll3_out", "audio_pll2_out",
"video_pll1_out", };
static const char * const imx8mp_media_mipi_phy2_ref_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
"sys_pll1_800m", "sys_pll2_1000m",
"clk_ext2", "audio_pll2_out",
"video_pll1_out", };
static const char * const imx8mp_media_ldb_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
"sys_pll1_800m", "sys_pll2_1000m",
"clk_ext2", "audio_pll2_out",
"video_pll1_out", };
static const char * const imx8mp_media_mipi_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
"sys_pll1_800m", "sys_pll2_1000m",
"sys_pll3_out", "clk_ext3",
"audio_pll2_out", };
static const char * const imx8mp_memrepair_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
"clk_ext3", "audio_pll2_out", };
static const char * const imx8mp_pcie2_ctrl_sels[] = {"osc_24m", "sys_pll2_250m", "sys_pll2_200m",
"sys_pll1_266m", "sys_pll1_800m", "sys_pll2_500m",
@ -590,7 +585,6 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_VPU_G2] = imx8m_clk_hw_composite("vpu_g2", imx8mp_vpu_g2_sels, ccm_base + 0xa180);
hws[IMX8MP_CLK_CAN1] = imx8m_clk_hw_composite("can1", imx8mp_can1_sels, ccm_base + 0xa200);
hws[IMX8MP_CLK_CAN2] = imx8m_clk_hw_composite("can2", imx8mp_can2_sels, ccm_base + 0xa280);
hws[IMX8MP_CLK_MEMREPAIR] = imx8m_clk_hw_composite("memrepair", imx8mp_memrepair_sels, ccm_base + 0xa300);
hws[IMX8MP_CLK_PCIE_PHY] = imx8m_clk_hw_composite("pcie_phy", imx8mp_pcie_phy_sels, ccm_base + 0xa380);
hws[IMX8MP_CLK_PCIE_AUX] = imx8m_clk_hw_composite("pcie_aux", imx8mp_pcie_aux_sels, ccm_base + 0xa400);
hws[IMX8MP_CLK_I2C5] = imx8m_clk_hw_composite("i2c5", imx8mp_i2c5_sels, ccm_base + 0xa480);
@ -647,8 +641,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_MEDIA_MIPI_PHY1_REF] = imx8m_clk_hw_composite("media_mipi_phy1_ref", imx8mp_media_mipi_phy1_ref_sels, ccm_base + 0xbd80);
hws[IMX8MP_CLK_MEDIA_DISP1_PIX] = imx8m_clk_hw_composite("media_disp1_pix", imx8mp_media_disp1_pix_sels, ccm_base + 0xbe00);
hws[IMX8MP_CLK_MEDIA_CAM2_PIX] = imx8m_clk_hw_composite("media_cam2_pix", imx8mp_media_cam2_pix_sels, ccm_base + 0xbe80);
hws[IMX8MP_CLK_MEDIA_MIPI_PHY2_REF] = imx8m_clk_hw_composite("media_mipi_phy2_ref", imx8mp_media_mipi_phy2_ref_sels, ccm_base + 0xbf00);
hws[IMX8MP_CLK_MEDIA_MIPI_CSI2_ESC] = imx8m_clk_hw_composite("media_mipi_csi2_esc", imx8mp_media_mipi_csi2_esc_sels, ccm_base + 0xbf80);
hws[IMX8MP_CLK_MEDIA_LDB] = imx8m_clk_hw_composite("media_ldb", imx8mp_media_ldb_sels, ccm_base + 0xbf00);
hws[IMX8MP_CLK_MEMREPAIR] = imx8m_clk_hw_composite_critical("mem_repair", imx8mp_memrepair_sels, ccm_base + 0xbf80);
hws[IMX8MP_CLK_PCIE2_CTRL] = imx8m_clk_hw_composite("pcie2_ctrl", imx8mp_pcie2_ctrl_sels, ccm_base + 0xc000);
hws[IMX8MP_CLK_PCIE2_PHY] = imx8m_clk_hw_composite("pcie2_phy", imx8mp_pcie2_phy_sels, ccm_base + 0xc080);
hws[IMX8MP_CLK_MEDIA_MIPI_TEST_BYTE] = imx8m_clk_hw_composite("media_mipi_test_byte", imx8mp_media_mipi_test_byte_sels, ccm_base + 0xc100);
@ -773,3 +767,7 @@ static struct platform_driver imx8mp_clk_driver = {
},
};
module_platform_driver(imx8mp_clk_driver);
MODULE_AUTHOR("Anson Huang <Anson.Huang@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8MP clock driver");
MODULE_LICENSE("GPL v2");

View File

@ -157,10 +157,10 @@ static const char * const imx8mq_qspi_sels[] = {"osc_25m", "sys1_pll_400m", "sys
"audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
static const char * const imx8mq_usdhc1_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
"audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
"sys3_pll_out", "sys1_pll_266m", "audio_pll2_out", "sys1_pll_100m", };
static const char * const imx8mq_usdhc2_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
"audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
"sys3_pll_out", "sys1_pll_266m", "audio_pll2_out", "sys1_pll_100m", };
static const char * const imx8mq_i2c1_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
"video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
@ -643,3 +643,7 @@ static struct platform_driver imx8mq_clk_driver = {
},
};
module_platform_driver(imx8mq_clk_driver);
MODULE_AUTHOR("Abel Vesa <abel.vesa@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8MQ clock driver");
MODULE_LICENSE("GPL v2");

View File

@ -232,3 +232,7 @@ static struct platform_driver imx8qxp_lpcg_clk_driver = {
};
builtin_platform_driver(imx8qxp_lpcg_clk_driver);
MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8QXP LPCG clock driver");
MODULE_LICENSE("GPL v2");

View File

@ -152,3 +152,7 @@ static struct platform_driver imx8qxp_clk_driver = {
.probe = imx8qxp_clk_probe,
};
builtin_platform_driver(imx8qxp_clk_driver);
MODULE_AUTHOR("Aisheng Dong <aisheng.dong@nxp.com>");
MODULE_DESCRIPTION("NXP i.MX8QXP clock driver");
MODULE_LICENSE("GPL v2");

View File

@ -4,6 +4,7 @@
* Dong Aisheng <aisheng.dong@nxp.com>
*/
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>

View File

@ -12,7 +12,7 @@
/**
* struct clk_pfd - IMX PFD clock
* @clk_hw: clock source
* @hw: clock source
* @reg: PFD register address
* @idx: the index of PFD encoded in the register
*

View File

@ -17,7 +17,7 @@
/**
* struct clk_pfdv2 - IMX PFD clock
* @clk_hw: clock source
* @hw: clock source
* @reg: PFD register address
* @gate_bit: Gate bit offset
* @vld_bit: Valid bit offset

View File

@ -3,9 +3,10 @@
* Copyright 2017-2018 NXP.
*/
#include <linux/bitops.h>
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/slab.h>
@ -68,6 +69,7 @@ struct imx_pll14xx_clk imx_1443x_pll = {
.rate_table = imx_pll1443x_tbl,
.rate_count = ARRAY_SIZE(imx_pll1443x_tbl),
};
EXPORT_SYMBOL_GPL(imx_1443x_pll);
struct imx_pll14xx_clk imx_1443x_dram_pll = {
.type = PLL_1443X,
@ -75,12 +77,14 @@ struct imx_pll14xx_clk imx_1443x_dram_pll = {
.rate_count = ARRAY_SIZE(imx_pll1443x_tbl),
.flags = CLK_GET_RATE_NOCACHE,
};
EXPORT_SYMBOL_GPL(imx_1443x_dram_pll);
struct imx_pll14xx_clk imx_1416x_pll = {
.type = PLL_1416X,
.rate_table = imx_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx_pll1416x_tbl),
};
EXPORT_SYMBOL_GPL(imx_1416x_pll);
static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
struct clk_pll14xx *pll, unsigned long rate)
@ -436,3 +440,4 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
return hw;
}
EXPORT_SYMBOL_GPL(imx_dev_clk_hw_pll14xx);

View File

@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/slab.h>

View File

@ -30,12 +30,15 @@
/**
* struct clk_pllv3 - IMX PLL clock version 3
* @clk_hw: clock source
* @hw: clock source
* @base: base address of PLL registers
* @power_bit: pll power bit mask
* @powerup_set: set power_bit to power up the PLL
* @div_mask: mask of divider bits
* @div_shift: shift of divider bits
* @ref_clock: reference clock rate
* @num_offset: num register offset
* @denom_offset: denom register offset
*
* IMX PLL clock version 3, found on i.MX6 series. Divider for pllv3
* is actually a multiplier, and always sits at bit 0.

View File

@ -7,6 +7,7 @@
*
*/
#include <linux/bits.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>

View File

@ -10,6 +10,7 @@
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/slab.h>
@ -537,3 +538,4 @@ struct clk_hw *imx_clk_hw_sscg_pll(const char *name,
return hw;
}
EXPORT_SYMBOL_GPL(imx_clk_hw_sscg_pll);

View File

@ -4,6 +4,7 @@
*/
#include <linux/of_address.h>
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/syscore_ops.h>
#include <dt-bindings/clock/vf610-clock.h>
@ -328,6 +329,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
clk[VF610_CLK_DSPI2] = imx_clk_gate2("dspi2", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(12));
clk[VF610_CLK_DSPI3] = imx_clk_gate2("dspi3", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(13));
clk[VF610_CLK_CRC] = imx_clk_gate2("crc", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(3));
clk[VF610_CLK_WDT] = imx_clk_gate2("wdt", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(14));
clk[VF610_CLK_ESDHC0_SEL] = imx_clk_mux("esdhc0_sel", CCM_CSCMR1, 16, 2, esdhc_sels, 4);

View File

@ -1,8 +1,10 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
@ -13,6 +15,7 @@
#define CCDR_MMDC_CH1_MASK BIT(16)
DEFINE_SPINLOCK(imx_ccm_lock);
EXPORT_SYMBOL_GPL(imx_ccm_lock);
void imx_unregister_clocks(struct clk *clks[], unsigned int count)
{
@ -29,8 +32,9 @@ void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count)
for (i = 0; i < count; i++)
clk_hw_unregister(hws[i]);
}
EXPORT_SYMBOL_GPL(imx_unregister_hw_clocks);
void __init imx_mmdc_mask_handshake(void __iomem *ccm_base,
void imx_mmdc_mask_handshake(void __iomem *ccm_base,
unsigned int chn)
{
unsigned int reg;
@ -59,8 +63,9 @@ void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count)
pr_err("i.MX clk %u: register failed with %ld\n",
i, PTR_ERR(clks[i]));
}
EXPORT_SYMBOL_GPL(imx_check_clk_hws);
static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
static struct clk *imx_obtain_fixed_clock_from_dt(const char *name)
{
struct of_phandle_args phandle;
struct clk *clk = ERR_PTR(-ENODEV);
@ -80,7 +85,7 @@ static struct clk * __init imx_obtain_fixed_clock_from_dt(const char *name)
return clk;
}
struct clk * __init imx_obtain_fixed_clock(
struct clk *imx_obtain_fixed_clock(
const char *name, unsigned long rate)
{
struct clk *clk;
@ -91,7 +96,7 @@ struct clk * __init imx_obtain_fixed_clock(
return clk;
}
struct clk_hw * __init imx_obtain_fixed_clock_hw(
struct clk_hw *imx_obtain_fixed_clock_hw(
const char *name, unsigned long rate)
{
struct clk *clk;
@ -113,6 +118,7 @@ struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
return __clk_get_hw(clk);
}
EXPORT_SYMBOL_GPL(imx_obtain_fixed_clk_hw);
/*
* This fixups the register CCM_CSCMR1 write value.
@ -140,6 +146,7 @@ void imx_cscmr1_fixup(u32 *val)
return;
}
#ifndef MODULE
static int imx_keep_uart_clocks;
static struct clk ** const *imx_uart_clocks;
@ -177,3 +184,6 @@ static int __init imx_clk_disable_uart(void)
return 0;
}
late_initcall_sync(imx_clk_disable_uart);
#endif
MODULE_LICENSE("GPL v2");

View File

@ -2,6 +2,7 @@
#ifndef __MACH_IMX_CLK_H
#define __MACH_IMX_CLK_H
#include <linux/bits.h>
#include <linux/spinlock.h>
#include <linux/clk-provider.h>
@ -11,7 +12,13 @@ extern spinlock_t imx_ccm_lock;
void imx_check_clocks(struct clk *clks[], unsigned int count);
void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count);
#ifndef MODULE
void imx_register_uart_clocks(struct clk ** const clks[]);
#else
static inline void imx_register_uart_clocks(struct clk ** const clks[])
{
}
#endif
void imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn);
void imx_unregister_clocks(struct clk *clks[], unsigned int count);
void imx_unregister_hw_clocks(struct clk_hw *hws[], unsigned int count);

View File

@ -12,15 +12,24 @@
#include <linux/clkdev.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/math64.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/time.h>
#include "cgu.h"
#define MHZ (1000 * 1000)
static inline const struct ingenic_cgu_clk_info *
to_clk_info(struct ingenic_clk *clk)
{
return &clk->cgu->clock_info[clk->idx];
}
/**
* ingenic_cgu_gate_get() - get the value of clock gate register bit
* @cgu: reference to the CGU whose registers should be read
@ -71,14 +80,13 @@ static unsigned long
ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
const struct ingenic_cgu_pll_info *pll_info;
unsigned m, n, od_enc, od;
bool bypass;
u32 ctl;
clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);
pll_info = &clk_info->pll;
@ -144,18 +152,6 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
n * od);
}
static inline const struct ingenic_cgu_clk_info *to_clk_info(
struct ingenic_clk *ingenic_clk)
{
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
clk_info = &cgu->clock_info[ingenic_clk->idx];
BUG_ON(clk_info->type != CGU_CLK_PLL);
return clk_info;
}
static long
ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long *prate)
@ -166,6 +162,16 @@ ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
}
static inline int ingenic_pll_check_stable(struct ingenic_cgu *cgu,
const struct ingenic_cgu_pll_info *pll_info)
{
u32 ctl;
return readl_poll_timeout(cgu->base + pll_info->reg, ctl,
ctl & BIT(pll_info->stable_bit),
0, 100 * USEC_PER_MSEC);
}
static int
ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long parent_rate)
@ -176,6 +182,7 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
unsigned long rate, flags;
unsigned int m, n, od;
int ret = 0;
u32 ctl;
rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
@ -197,9 +204,14 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
writel(ctl, cgu->base + pll_info->reg);
/* If the PLL is enabled, verify that it's stable */
if (ctl & BIT(pll_info->enable_bit))
ret = ingenic_pll_check_stable(cgu, pll_info);
spin_unlock_irqrestore(&cgu->lock, flags);
return 0;
return ret;
}
static int ingenic_pll_enable(struct clk_hw *hw)
@ -208,9 +220,8 @@ static int ingenic_pll_enable(struct clk_hw *hw)
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
const unsigned int timeout = 100;
unsigned long flags;
unsigned int i;
int ret;
u32 ctl;
spin_lock_irqsave(&cgu->lock, flags);
@ -226,20 +237,10 @@ static int ingenic_pll_enable(struct clk_hw *hw)
writel(ctl, cgu->base + pll_info->reg);
/* wait for the PLL to stabilise */
for (i = 0; i < timeout; i++) {
ctl = readl(cgu->base + pll_info->reg);
if (ctl & BIT(pll_info->stable_bit))
break;
mdelay(1);
}
ret = ingenic_pll_check_stable(cgu, pll_info);
spin_unlock_irqrestore(&cgu->lock, flags);
if (i == timeout)
return -EBUSY;
return 0;
return ret;
}
static void ingenic_pll_disable(struct clk_hw *hw)
@ -290,13 +291,11 @@ static const struct clk_ops ingenic_pll_ops = {
static u8 ingenic_clk_get_parent(struct clk_hw *hw)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
u32 reg;
u8 i, hw_idx, idx = 0;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_MUX) {
reg = readl(cgu->base + clk_info->mux.reg);
hw_idx = (reg >> clk_info->mux.shift) &
@ -318,14 +317,12 @@ static u8 ingenic_clk_get_parent(struct clk_hw *hw)
static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
unsigned long flags;
u8 curr_idx, hw_idx, num_poss;
u32 reg, mask;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_MUX) {
/*
* Convert the parent index to the hardware index by adding
@ -368,13 +365,11 @@ static unsigned long
ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
unsigned long rate = parent_rate;
u32 div_reg, div;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_DIV) {
div_reg = readl(cgu->base + clk_info->div.reg);
div = (div_reg >> clk_info->div.shift) &
@ -443,35 +438,41 @@ ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long *parent_rate)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
unsigned int div = 1;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_DIV)
div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
else if (clk_info->type & CGU_CLK_FIXDIV)
div = clk_info->fixdiv.div;
else if (clk_hw_can_set_rate_parent(hw))
*parent_rate = req_rate;
return DIV_ROUND_UP(*parent_rate, div);
}
static inline int ingenic_clk_check_stable(struct ingenic_cgu *cgu,
const struct ingenic_cgu_clk_info *clk_info)
{
u32 reg;
return readl_poll_timeout(cgu->base + clk_info->div.reg, reg,
!(reg & BIT(clk_info->div.busy_bit)),
0, 100 * USEC_PER_MSEC);
}
static int
ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
unsigned long parent_rate)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
const unsigned timeout = 100;
unsigned long rate, flags;
unsigned int hw_div, div, i;
unsigned int hw_div, div;
u32 reg, mask;
int ret = 0;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_DIV) {
div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
rate = DIV_ROUND_UP(parent_rate, div);
@ -504,16 +505,8 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
writel(reg, cgu->base + clk_info->div.reg);
/* wait for the change to take effect */
if (clk_info->div.busy_bit != -1) {
for (i = 0; i < timeout; i++) {
reg = readl(cgu->base + clk_info->div.reg);
if (!(reg & BIT(clk_info->div.busy_bit)))
break;
mdelay(1);
}
if (i == timeout)
ret = -EBUSY;
}
if (clk_info->div.busy_bit != -1)
ret = ingenic_clk_check_stable(cgu, clk_info);
spin_unlock_irqrestore(&cgu->lock, flags);
return ret;
@ -525,12 +518,10 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
static int ingenic_clk_enable(struct clk_hw *hw)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
unsigned long flags;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_GATE) {
/* ungate the clock */
spin_lock_irqsave(&cgu->lock, flags);
@ -547,12 +538,10 @@ static int ingenic_clk_enable(struct clk_hw *hw)
static void ingenic_clk_disable(struct clk_hw *hw)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
unsigned long flags;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_GATE) {
/* gate the clock */
spin_lock_irqsave(&cgu->lock, flags);
@ -564,12 +553,10 @@ static void ingenic_clk_disable(struct clk_hw *hw)
static int ingenic_clk_is_enabled(struct clk_hw *hw)
{
struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_clk_info *clk_info;
int enabled = 1;
clk_info = &cgu->clock_info[ingenic_clk->idx];
if (clk_info->type & CGU_CLK_GATE)
enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
@ -644,6 +631,13 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
caps = clk_info->type;
if (caps & CGU_CLK_DIV) {
caps &= ~CGU_CLK_DIV;
} else if (!(caps & CGU_CLK_CUSTOM)) {
/* pass rate changes to the parent clock */
clk_init.flags |= CLK_SET_RATE_PARENT;
}
if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
clk_init.num_parents = 0;
@ -683,7 +677,6 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
}
} else if (caps & CGU_CLK_PLL) {
clk_init.ops = &ingenic_pll_ops;
clk_init.flags |= CLK_SET_RATE_GATE;
caps &= ~CGU_CLK_PLL;
@ -706,13 +699,6 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
}
if (caps & CGU_CLK_DIV) {
caps &= ~CGU_CLK_DIV;
} else {
/* pass rate changes to the parent clock */
clk_init.flags |= CLK_SET_RATE_PARENT;
}
if (caps) {
pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
goto out;

View File

@ -54,6 +54,8 @@ struct sci_clk_provider {
* @provider: Master clock provider
* @flags: Flags for the clock
* @node: Link for handling clocks probed via DT
* @cached_req: Cached requested freq for determine rate calls
* @cached_res: Cached result freq for determine rate calls
*/
struct sci_clk {
struct clk_hw hw;
@ -63,6 +65,8 @@ struct sci_clk {
struct sci_clk_provider *provider;
u8 flags;
struct list_head node;
unsigned long cached_req;
unsigned long cached_res;
};
#define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw)
@ -175,6 +179,11 @@ static int sci_clk_determine_rate(struct clk_hw *hw,
int ret;
u64 new_rate;
if (clk->cached_req && clk->cached_req == req->rate) {
req->rate = clk->cached_res;
return 0;
}
ret = clk->provider->ops->get_best_match_freq(clk->provider->sci,
clk->dev_id,
clk->clk_id,
@ -189,6 +198,9 @@ static int sci_clk_determine_rate(struct clk_hw *hw,
return ret;
}
clk->cached_req = req->rate;
clk->cached_res = new_rate;
req->rate = new_rate;
return 0;
@ -209,7 +221,8 @@ static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate,
struct sci_clk *clk = to_sci_clk(hw);
return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id,
clk->clk_id, rate, rate, rate);
clk->clk_id, rate / 10 * 9, rate,
rate / 10 * 11);
}
/**
@ -249,6 +262,8 @@ static int sci_clk_set_parent(struct clk_hw *hw, u8 index)
{
struct sci_clk *clk = to_sci_clk(hw);
clk->cached_req = 0;
return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id,
clk->clk_id,
index + 1 + clk->clk_id);
@ -522,7 +537,7 @@ static int ti_sci_scan_clocks_from_dt(struct sci_clk_provider *provider)
np = of_find_node_with_property(np, *clk_name);
if (!np) {
clk_name++;
break;
continue;
}
if (!of_device_is_available(np))

View File

@ -352,6 +352,54 @@ config COMMON_CLK_MT8135
help
This driver supports MediaTek MT8135 clocks.
config COMMON_CLK_MT8167
bool "Clock driver for MediaTek MT8167"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8167 basic clocks.
config COMMON_CLK_MT8167_AUDSYS
bool "Clock driver for MediaTek MT8167 audsys"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8167 audsys clocks.
config COMMON_CLK_MT8167_IMGSYS
bool "Clock driver for MediaTek MT8167 imgsys"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8167 imgsys clocks.
config COMMON_CLK_MT8167_MFGCFG
bool "Clock driver for MediaTek MT8167 mfgcfg"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8167 mfgcfg clocks.
config COMMON_CLK_MT8167_MMSYS
bool "Clock driver for MediaTek MT8167 mmsys"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8167 mmsys clocks.
config COMMON_CLK_MT8167_VDECSYS
bool "Clock driver for MediaTek MT8167 vdecsys"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8167 vdecsys clocks.
config COMMON_CLK_MT8173
bool "Clock driver for MediaTek MT8173"
depends on ARCH_MEDIATEK || COMPILE_TEST

View File

@ -47,6 +47,12 @@ obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o
obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o
obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o
obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o
obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o
obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o
obj-$(CONFIG_COMMON_CLK_MT8167_IMGSYS) += clk-mt8167-img.o
obj-$(CONFIG_COMMON_CLK_MT8167_MFGCFG) += clk-mt8167-mfgcfg.o
obj-$(CONFIG_COMMON_CLK_MT8167_MMSYS) += clk-mt8167-mm.o
obj-$(CONFIG_COMMON_CLK_MT8167_VDECSYS) += clk-mt8167-vdec.o
obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o
obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) += clk-mt8173-mm.o
obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o

View File

@ -909,7 +909,6 @@ static struct platform_driver clk_mt6765_drv = {
.probe = clk_mt6765_probe,
.driver = {
.name = "clk-mt6765",
.owner = THIS_MODULE,
.of_match_table = of_match_clk_mt6765,
},
};

View File

@ -919,6 +919,8 @@ static const struct mtk_gate infra_clks[] = {
"pwm_sel", 19),
GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm",
"pwm_sel", 21),
GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0",
"uart_sel", 22),
GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1",
"uart_sel", 23),
GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2",

View File

@ -582,7 +582,7 @@ CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt6797-infracfg",
static int mtk_infrasys_init(struct platform_device *pdev)
{
int r, i;
int i;
struct device_node *node = pdev->dev.of_node;
if (!infra_clk_data) {
@ -599,11 +599,7 @@ static int mtk_infrasys_init(struct platform_device *pdev)
mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
infra_clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
if (r)
return r;
return 0;
return of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
}
#define MT6797_PLL_FMAX (3000UL * MHZ)

View File

@ -601,7 +601,6 @@ static int 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);
@ -611,12 +610,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
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;
return 0;
return of_clk_add_provider(node, of_clk_src_onecell_get,
clk_data);
}
static int mtk_pericfg_init(struct platform_device *pdev)

View File

@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
* Copyright (c) 2020 BayLibre, SAS
* Author: James Liao <jamesjj.liao@mediatek.com>
* Fabien Parent <fparent@baylibre.com>
*/
#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/mt8167-clk.h>
static const struct mtk_gate_regs aud_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x0,
.sta_ofs = 0x0,
};
#define GATE_AUD(_id, _name, _parent, _shift) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.regs = &aud_cg_regs, \
.shift = _shift, \
.ops = &mtk_clk_gate_ops_no_setclr, \
}
static const struct mtk_gate aud_clks[] __initconst = {
GATE_AUD(CLK_AUD_AFE, "aud_afe", "clk26m_ck", 2),
GATE_AUD(CLK_AUD_I2S, "aud_i2s", "i2s_infra_bck", 6),
GATE_AUD(CLK_AUD_22M, "aud_22m", "rg_aud_engen1", 8),
GATE_AUD(CLK_AUD_24M, "aud_24m", "rg_aud_engen2", 9),
GATE_AUD(CLK_AUD_INTDIR, "aud_intdir", "rg_aud_spdif_in", 15),
GATE_AUD(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "rg_aud_engen2", 18),
GATE_AUD(CLK_AUD_APLL_TUNER, "aud_apll_tuner", "rg_aud_engen1", 19),
GATE_AUD(CLK_AUD_HDMI, "aud_hdmi", "apll12_div4", 20),
GATE_AUD(CLK_AUD_SPDF, "aud_spdf", "apll12_div6", 21),
GATE_AUD(CLK_AUD_ADC, "aud_adc", "aud_afe", 24),
GATE_AUD(CLK_AUD_DAC, "aud_dac", "aud_afe", 25),
GATE_AUD(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "aud_afe", 26),
GATE_AUD(CLK_AUD_TML, "aud_tml", "aud_afe", 27),
};
static void __init mtk_audsys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
int r;
clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK);
mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
}
CLK_OF_DECLARE(mtk_audsys, "mediatek,mt8167-audsys", mtk_audsys_init);

View File

@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
* Copyright (c) 2020 BayLibre, SAS
* Author: James Liao <jamesjj.liao@mediatek.com>
* Fabien Parent <fparent@baylibre.com>
*/
#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/mt8167-clk.h>
static const struct mtk_gate_regs img_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.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_setclr, \
}
static const struct mtk_gate img_clks[] __initconst = {
GATE_IMG(CLK_IMG_LARB1_SMI, "img_larb1_smi", "smi_mm", 0),
GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "smi_mm", 5),
GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "smi_mm", 6),
GATE_IMG(CLK_IMG_SEN_TG, "img_sen_tg", "cam_mm", 7),
GATE_IMG(CLK_IMG_SEN_CAM, "img_sen_cam", "smi_mm", 8),
GATE_IMG(CLK_IMG_VENC, "img_venc", "smi_mm", 9),
};
static void __init mtk_imgsys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
int r;
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)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
}
CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8167-imgsys", mtk_imgsys_init);

View File

@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
* Copyright (c) 2020 BayLibre, SAS
* Author: James Liao <jamesjj.liao@mediatek.com>
* Fabien Parent <fparent@baylibre.com>
*/
#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/mt8167-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[] __initconst = {
GATE_MFG(CLK_MFG_BAXI, "mfg_baxi", "ahb_infra_sel", 0),
GATE_MFG(CLK_MFG_BMEM, "mfg_bmem", "gfmux_emi1x_sel", 1),
GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_mm", 2),
GATE_MFG(CLK_MFG_B26M, "mfg_b26m", "clk26m_ck", 3),
};
static void __init mtk_mfgcfg_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
int r;
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)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
}
CLK_OF_DECLARE(mtk_mfgcfg, "mediatek,mt8167-mfgcfg", mtk_mfgcfg_init);

View File

@ -0,0 +1,132 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
* Copyright (c) 2020 BayLibre, SAS
* Author: James Liao <jamesjj.liao@mediatek.com>
* Fabien Parent <fparent@baylibre.com>
*/
#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/mt8167-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,
};
#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, \
}
static const struct mtk_gate mm_clks[] = {
/* MM0 */
GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "smi_mm", 0),
GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "smi_mm", 1),
GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "smi_mm", 2),
GATE_MM0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "smi_mm", 3),
GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "smi_mm", 4),
GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "smi_mm", 5),
GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "smi_mm", 6),
GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "smi_mm", 7),
GATE_MM0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "smi_mm", 8),
GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "smi_mm", 9),
GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "smi_mm", 10),
GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "smi_mm", 11),
GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "smi_mm", 12),
GATE_MM0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "smi_mm", 13),
GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "smi_mm", 14),
GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "smi_mm", 15),
GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "smi_mm", 16),
GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "smi_mm", 17),
GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "smi_mm", 18),
GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "smi_mm", 19),
/* MM1 */
GATE_MM1(CLK_MM_DISP_PWM_MM, "mm_disp_pwm_mm", "smi_mm", 0),
GATE_MM1(CLK_MM_DISP_PWM_26M, "mm_disp_pwm_26m", "smi_mm", 1),
GATE_MM1(CLK_MM_DSI_ENGINE, "mm_dsi_engine", "smi_mm", 2),
GATE_MM1(CLK_MM_DSI_DIGITAL, "mm_dsi_digital", "dsi0_lntc_dsick", 3),
GATE_MM1(CLK_MM_DPI0_ENGINE, "mm_dpi0_engine", "smi_mm", 4),
GATE_MM1(CLK_MM_DPI0_PXL, "mm_dpi0_pxl", "rg_fdpi0", 5),
GATE_MM1(CLK_MM_LVDS_PXL, "mm_lvds_pxl", "vpll_dpix", 14),
GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx_dig_cts", 15),
GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "smi_mm", 16),
GATE_MM1(CLK_MM_DPI1_PXL, "mm_dpi1_pxl", "rg_fdpi1", 17),
GATE_MM1(CLK_MM_HDMI_PXL, "mm_hdmi_pxl", "rg_fdpi1", 18),
GATE_MM1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll12_div6", 19),
GATE_MM1(CLK_MM_HDMI_ADSP_BCK, "mm_hdmi_adsp_b", "apll12_div4b", 20),
GATE_MM1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmtx_dig_cts", 21),
};
struct clk_mt8167_mm_driver_data {
const struct mtk_gate *gates_clk;
int gates_num;
};
static const struct clk_mt8167_mm_driver_data mt8167_mmsys_driver_data = {
.gates_clk = mm_clks,
.gates_num = ARRAY_SIZE(mm_clks),
};
static int clk_mt8167_mm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->parent->of_node;
const struct clk_mt8167_mm_driver_data *data;
struct clk_onecell_data *clk_data;
int ret;
clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
if (!clk_data)
return -ENOMEM;
data = &mt8167_mmsys_driver_data;
ret = mtk_clk_register_gates(node, data->gates_clk, data->gates_num,
clk_data);
if (ret)
return ret;
ret = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (ret)
return ret;
return 0;
}
static struct platform_driver clk_mt8173_mm_drv = {
.driver = {
.name = "clk-mt8167-mm",
},
.probe = clk_mt8167_mm_probe,
};
builtin_platform_driver(clk_mt8173_mm_drv);

View File

@ -0,0 +1,73 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020 MediaTek Inc.
* Copyright (c) 2020 BayLibre, SAS
* Author: James Liao <jamesjj.liao@mediatek.com>
* Fabien Parent <fparent@baylibre.com>
*/
#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/mt8167-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_I(_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_I(_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[] __initconst = {
/* VDEC0 */
GATE_VDEC0_I(CLK_VDEC_CKEN, "vdec_cken", "rg_vdec", 0),
/* VDEC1 */
GATE_VDEC1_I(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "smi_mm", 0),
};
static void __init mtk_vdecsys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
int r;
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)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
}
CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8167-vdecsys", mtk_vdecsys_init);

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
menu "Clock support for Amlogic platforms"
depends on ARCH_MESON || COMPILE_TEST
config COMMON_CLK_MESON_REGMAP
tristate
select REGMAP
@ -41,8 +44,9 @@ config COMMON_CLK_MESON_CPU_DYNDIV
select COMMON_CLK_MESON_REGMAP
config COMMON_CLK_MESON8B
bool
depends on ARCH_MESON
bool "Meson8 SoC Clock controller support"
depends on ARM
default y
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_MPLL
select COMMON_CLK_MESON_PLL
@ -54,8 +58,9 @@ config COMMON_CLK_MESON8B
want peripherals and CPU frequency scaling to work.
config COMMON_CLK_GXBB
bool
depends on ARCH_MESON
bool "GXBB and GXL SoC clock controllers support"
depends on ARM64
default y
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_DUALDIV
select COMMON_CLK_MESON_VID_PLL_DIV
@ -69,8 +74,9 @@ config COMMON_CLK_GXBB
Say Y if you want peripherals and CPU frequency scaling to work.
config COMMON_CLK_AXG
bool
depends on ARCH_MESON
bool "AXG SoC clock controllers support"
depends on ARM64
default y
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_DUALDIV
select COMMON_CLK_MESON_MPLL
@ -84,7 +90,7 @@ config COMMON_CLK_AXG
config COMMON_CLK_AXG_AUDIO
tristate "Meson AXG Audio Clock Controller Driver"
depends on ARCH_MESON
depends on ARM64
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_PHASE
select COMMON_CLK_MESON_SCLK_DIV
@ -94,8 +100,9 @@ config COMMON_CLK_AXG_AUDIO
aka axg, Say Y if you want audio subsystem to work.
config COMMON_CLK_G12A
bool
depends on ARCH_MESON
bool "G12 and SM1 SoC clock controllers support"
depends on ARM64
default y
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_DUALDIV
select COMMON_CLK_MESON_MPLL
@ -107,3 +114,4 @@ config COMMON_CLK_G12A
help
Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
devices, aka g12a. Say Y if you want peripherals to work.
endmenu

View File

@ -147,6 +147,29 @@
}, \
}
#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname, \
_iflags) { \
.data = &(struct meson_sclk_ws_inv_data) { \
.ph = { \
.reg_off = (_reg), \
.shift = (_shift_ph), \
.width = (_width), \
}, \
.ws = { \
.reg_off = (_reg), \
.shift = (_shift_ws), \
.width = (_width), \
}, \
}, \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &meson_clk_phase_ops, \
.parent_names = (const char *[]){ #_pname }, \
.num_parents = 1, \
.flags = (_iflags), \
}, \
}
/* Audio Master Clocks */
static const struct clk_parent_data mst_mux_parent_data[] = {
{ .fw_name = "mst_in0", },
@ -254,6 +277,10 @@ static const struct clk_parent_data tdm_lrclk_parent_data[] = {
AUD_PHASE(tdm##_name##_sclk, _reg, 1, 29, \
aud_tdm##_name##_sclk_post_en, \
CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)
#define AUD_TDM_SCLK_WS(_name, _reg) \
AUD_SCLK_WS(tdm##_name##_sclk, _reg, 1, 29, 28, \
aud_tdm##_name##_sclk_post_en, \
CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)
#define AUD_TDM_LRLCK(_name, _reg) \
AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
@ -499,12 +526,6 @@ static struct clk_regmap tdmin_c_sclk =
AUD_TDM_SCLK(in_c, AUDIO_CLK_TDMIN_C_CTRL);
static struct clk_regmap tdmin_lb_sclk =
AUD_TDM_SCLK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL);
static struct clk_regmap tdmout_a_sclk =
AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static struct clk_regmap tdmout_b_sclk =
AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static struct clk_regmap tdmout_c_sclk =
AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
static struct clk_regmap tdmin_a_lrclk =
AUD_TDM_LRLCK(in_a, AUDIO_CLK_TDMIN_A_CTRL);
@ -521,6 +542,14 @@ static struct clk_regmap tdmout_b_lrclk =
static struct clk_regmap tdmout_c_lrclk =
AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
/* AXG Clocks */
static struct clk_regmap axg_tdmout_a_sclk =
AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static struct clk_regmap axg_tdmout_b_sclk =
AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static struct clk_regmap axg_tdmout_c_sclk =
AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
/* AXG/G12A Clocks */
static struct clk_hw axg_aud_top = {
.init = &(struct clk_init_data) {
@ -591,7 +620,13 @@ static struct clk_regmap g12a_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL(
static struct clk_regmap g12a_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL(
sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data);
/* G12a/SM1 clocks */
static struct clk_regmap g12a_tdmout_a_sclk =
AUD_TDM_SCLK_WS(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static struct clk_regmap g12a_tdmout_b_sclk =
AUD_TDM_SCLK_WS(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static struct clk_regmap g12a_tdmout_c_sclk =
AUD_TDM_SCLK_WS(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
static struct clk_regmap toram =
AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20);
static struct clk_regmap spdifout_b =
@ -889,9 +924,9 @@ static struct clk_hw_onecell_data axg_audio_hw_onecell_data = {
[AUD_CLKID_TDMIN_B_SCLK] = &tdmin_b_sclk.hw,
[AUD_CLKID_TDMIN_C_SCLK] = &tdmin_c_sclk.hw,
[AUD_CLKID_TDMIN_LB_SCLK] = &tdmin_lb_sclk.hw,
[AUD_CLKID_TDMOUT_A_SCLK] = &tdmout_a_sclk.hw,
[AUD_CLKID_TDMOUT_B_SCLK] = &tdmout_b_sclk.hw,
[AUD_CLKID_TDMOUT_C_SCLK] = &tdmout_c_sclk.hw,
[AUD_CLKID_TDMOUT_A_SCLK] = &axg_tdmout_a_sclk.hw,
[AUD_CLKID_TDMOUT_B_SCLK] = &axg_tdmout_b_sclk.hw,
[AUD_CLKID_TDMOUT_C_SCLK] = &axg_tdmout_c_sclk.hw,
[AUD_CLKID_TDMIN_A_LRCLK] = &tdmin_a_lrclk.hw,
[AUD_CLKID_TDMIN_B_LRCLK] = &tdmin_b_lrclk.hw,
[AUD_CLKID_TDMIN_C_LRCLK] = &tdmin_c_lrclk.hw,
@ -1026,9 +1061,9 @@ static struct clk_hw_onecell_data g12a_audio_hw_onecell_data = {
[AUD_CLKID_TDMIN_B_SCLK] = &tdmin_b_sclk.hw,
[AUD_CLKID_TDMIN_C_SCLK] = &tdmin_c_sclk.hw,
[AUD_CLKID_TDMIN_LB_SCLK] = &tdmin_lb_sclk.hw,
[AUD_CLKID_TDMOUT_A_SCLK] = &tdmout_a_sclk.hw,
[AUD_CLKID_TDMOUT_B_SCLK] = &tdmout_b_sclk.hw,
[AUD_CLKID_TDMOUT_C_SCLK] = &tdmout_c_sclk.hw,
[AUD_CLKID_TDMOUT_A_SCLK] = &g12a_tdmout_a_sclk.hw,
[AUD_CLKID_TDMOUT_B_SCLK] = &g12a_tdmout_b_sclk.hw,
[AUD_CLKID_TDMOUT_C_SCLK] = &g12a_tdmout_c_sclk.hw,
[AUD_CLKID_TDMIN_A_LRCLK] = &tdmin_a_lrclk.hw,
[AUD_CLKID_TDMIN_B_LRCLK] = &tdmin_b_lrclk.hw,
[AUD_CLKID_TDMIN_C_LRCLK] = &tdmin_c_lrclk.hw,
@ -1170,9 +1205,9 @@ static struct clk_hw_onecell_data sm1_audio_hw_onecell_data = {
[AUD_CLKID_TDMIN_B_SCLK] = &tdmin_b_sclk.hw,
[AUD_CLKID_TDMIN_C_SCLK] = &tdmin_c_sclk.hw,
[AUD_CLKID_TDMIN_LB_SCLK] = &tdmin_lb_sclk.hw,
[AUD_CLKID_TDMOUT_A_SCLK] = &tdmout_a_sclk.hw,
[AUD_CLKID_TDMOUT_B_SCLK] = &tdmout_b_sclk.hw,
[AUD_CLKID_TDMOUT_C_SCLK] = &tdmout_c_sclk.hw,
[AUD_CLKID_TDMOUT_A_SCLK] = &g12a_tdmout_a_sclk.hw,
[AUD_CLKID_TDMOUT_B_SCLK] = &g12a_tdmout_b_sclk.hw,
[AUD_CLKID_TDMOUT_C_SCLK] = &g12a_tdmout_c_sclk.hw,
[AUD_CLKID_TDMIN_A_LRCLK] = &tdmin_a_lrclk.hw,
[AUD_CLKID_TDMIN_B_LRCLK] = &tdmin_b_lrclk.hw,
[AUD_CLKID_TDMIN_C_LRCLK] = &tdmin_c_lrclk.hw,
@ -1209,13 +1244,132 @@ static struct clk_hw_onecell_data sm1_audio_hw_onecell_data = {
};
/* Convenience table to populate regmap in .probe()
* Note that this table is shared between both AXG and G12A,
* with spdifout_b clocks being exclusive to G12A. Since those
* clocks are not declared within the AXG onecell table, we do not
* feel the need to have separate AXG/G12A regmap tables.
*/
/* Convenience table to populate regmap in .probe(). */
static struct clk_regmap *const axg_clk_regmaps[] = {
&ddr_arb,
&pdm,
&tdmin_a,
&tdmin_b,
&tdmin_c,
&tdmin_lb,
&tdmout_a,
&tdmout_b,
&tdmout_c,
&frddr_a,
&frddr_b,
&frddr_c,
&toddr_a,
&toddr_b,
&toddr_c,
&loopback,
&spdifin,
&spdifout,
&resample,
&power_detect,
&mst_a_mclk_sel,
&mst_b_mclk_sel,
&mst_c_mclk_sel,
&mst_d_mclk_sel,
&mst_e_mclk_sel,
&mst_f_mclk_sel,
&mst_a_mclk_div,
&mst_b_mclk_div,
&mst_c_mclk_div,
&mst_d_mclk_div,
&mst_e_mclk_div,
&mst_f_mclk_div,
&mst_a_mclk,
&mst_b_mclk,
&mst_c_mclk,
&mst_d_mclk,
&mst_e_mclk,
&mst_f_mclk,
&spdifout_clk_sel,
&spdifout_clk_div,
&spdifout_clk,
&spdifin_clk_sel,
&spdifin_clk_div,
&spdifin_clk,
&pdm_dclk_sel,
&pdm_dclk_div,
&pdm_dclk,
&pdm_sysclk_sel,
&pdm_sysclk_div,
&pdm_sysclk,
&mst_a_sclk_pre_en,
&mst_b_sclk_pre_en,
&mst_c_sclk_pre_en,
&mst_d_sclk_pre_en,
&mst_e_sclk_pre_en,
&mst_f_sclk_pre_en,
&mst_a_sclk_div,
&mst_b_sclk_div,
&mst_c_sclk_div,
&mst_d_sclk_div,
&mst_e_sclk_div,
&mst_f_sclk_div,
&mst_a_sclk_post_en,
&mst_b_sclk_post_en,
&mst_c_sclk_post_en,
&mst_d_sclk_post_en,
&mst_e_sclk_post_en,
&mst_f_sclk_post_en,
&mst_a_sclk,
&mst_b_sclk,
&mst_c_sclk,
&mst_d_sclk,
&mst_e_sclk,
&mst_f_sclk,
&mst_a_lrclk_div,
&mst_b_lrclk_div,
&mst_c_lrclk_div,
&mst_d_lrclk_div,
&mst_e_lrclk_div,
&mst_f_lrclk_div,
&mst_a_lrclk,
&mst_b_lrclk,
&mst_c_lrclk,
&mst_d_lrclk,
&mst_e_lrclk,
&mst_f_lrclk,
&tdmin_a_sclk_sel,
&tdmin_b_sclk_sel,
&tdmin_c_sclk_sel,
&tdmin_lb_sclk_sel,
&tdmout_a_sclk_sel,
&tdmout_b_sclk_sel,
&tdmout_c_sclk_sel,
&tdmin_a_sclk_pre_en,
&tdmin_b_sclk_pre_en,
&tdmin_c_sclk_pre_en,
&tdmin_lb_sclk_pre_en,
&tdmout_a_sclk_pre_en,
&tdmout_b_sclk_pre_en,
&tdmout_c_sclk_pre_en,
&tdmin_a_sclk_post_en,
&tdmin_b_sclk_post_en,
&tdmin_c_sclk_post_en,
&tdmin_lb_sclk_post_en,
&tdmout_a_sclk_post_en,
&tdmout_b_sclk_post_en,
&tdmout_c_sclk_post_en,
&tdmin_a_sclk,
&tdmin_b_sclk,
&tdmin_c_sclk,
&tdmin_lb_sclk,
&axg_tdmout_a_sclk,
&axg_tdmout_b_sclk,
&axg_tdmout_c_sclk,
&tdmin_a_lrclk,
&tdmin_b_lrclk,
&tdmin_c_lrclk,
&tdmin_lb_lrclk,
&tdmout_a_lrclk,
&tdmout_b_lrclk,
&tdmout_c_lrclk,
};
static struct clk_regmap *const g12a_clk_regmaps[] = {
&ddr_arb,
&pdm,
&tdmin_a,
@ -1328,9 +1482,9 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
&tdmin_b_sclk,
&tdmin_c_sclk,
&tdmin_lb_sclk,
&tdmout_a_sclk,
&tdmout_b_sclk,
&tdmout_c_sclk,
&g12a_tdmout_a_sclk,
&g12a_tdmout_b_sclk,
&g12a_tdmout_c_sclk,
&tdmin_a_lrclk,
&tdmin_b_lrclk,
&tdmin_c_lrclk,
@ -1465,9 +1619,9 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
&tdmin_b_sclk,
&tdmin_c_sclk,
&tdmin_lb_sclk,
&tdmout_a_sclk,
&tdmout_b_sclk,
&tdmout_c_sclk,
&g12a_tdmout_a_sclk,
&g12a_tdmout_b_sclk,
&g12a_tdmout_c_sclk,
&tdmin_a_lrclk,
&tdmin_b_lrclk,
&tdmin_c_lrclk,
@ -1713,8 +1867,8 @@ static const struct audioclk_data axg_audioclk_data = {
};
static const struct audioclk_data g12a_audioclk_data = {
.regmap_clks = axg_clk_regmaps,
.regmap_clk_num = ARRAY_SIZE(axg_clk_regmaps),
.regmap_clks = g12a_clk_regmaps,
.regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
.hw_onecell_data = &g12a_audio_hw_onecell_data,
.reset_offset = AUDIO_SW_RESET,
.reset_num = 26,

View File

@ -125,6 +125,62 @@ const struct clk_ops meson_clk_triphase_ops = {
};
EXPORT_SYMBOL_GPL(meson_clk_triphase_ops);
/*
* This is a special clock for the audio controller.
* This drive a bit clock inverter for which the
* opposite value of the inverter bit needs to be manually
* set into another bit
*/
static inline struct meson_sclk_ws_inv_data *
meson_sclk_ws_inv_data(struct clk_regmap *clk)
{
return (struct meson_sclk_ws_inv_data *)clk->data;
}
static int meson_sclk_ws_inv_sync(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk);
unsigned int val;
/* Get phase and sync the inverted value to ws */
val = meson_parm_read(clk->map, &tph->ph);
meson_parm_write(clk->map, &tph->ws, val ? 0 : 1);
return 0;
}
static int meson_sclk_ws_inv_get_phase(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk);
unsigned int val;
val = meson_parm_read(clk->map, &tph->ph);
return meson_clk_degrees_from_val(val, tph->ph.width);
}
static int meson_sclk_ws_inv_set_phase(struct clk_hw *hw, int degrees)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk);
unsigned int val;
val = meson_clk_degrees_to_val(degrees, tph->ph.width);
meson_parm_write(clk->map, &tph->ph, val);
meson_parm_write(clk->map, &tph->ws, val ? 0 : 1);
return 0;
}
const struct clk_ops meson_sclk_ws_inv_ops = {
.init = meson_sclk_ws_inv_sync,
.get_phase = meson_sclk_ws_inv_get_phase,
.set_phase = meson_sclk_ws_inv_set_phase,
};
EXPORT_SYMBOL_GPL(meson_sclk_ws_inv_ops);
MODULE_DESCRIPTION("Amlogic phase driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL v2");

View File

@ -20,7 +20,13 @@ struct meson_clk_triphase_data {
struct parm ph2;
};
struct meson_sclk_ws_inv_data {
struct parm ph;
struct parm ws;
};
extern const struct clk_ops meson_clk_phase_ops;
extern const struct clk_ops meson_clk_triphase_ops;
extern const struct clk_ops meson_sclk_ws_inv_ops;
#endif /* __MESON_CLK_PHASE_H */

View File

@ -298,6 +298,17 @@ static struct clk_regmap g12a_fclk_div2 = {
&g12a_fclk_div2_div.hw
},
.num_parents = 1,
/*
* Similar to fclk_div3, it seems that this clock is used by
* the resident firmware and is required by the platform to
* operate correctly.
* Until the following condition are met, we need this clock to
* be marked as critical:
* a) Mark the clock used by a firmware resource, if possible
* b) CCF has a clock hand-off mechanism to make the sure the
* clock stays on until the proper driver comes along
*/
.flags = CLK_IS_CRITICAL,
},
};

View File

@ -57,7 +57,7 @@ int meson_aoclkc_probe(struct platform_device *pdev)
rstc->data = data;
rstc->regmap = regmap;
rstc->reset.ops = &meson_aoclk_reset_ops;
rstc->reset.nr_resets = data->num_reset,
rstc->reset.nr_resets = data->num_reset;
rstc->reset.of_node = dev->of_node;
ret = devm_reset_controller_register(dev, &rstc->reset);
if (ret) {

View File

@ -347,9 +347,9 @@ static struct mmp_param_mux_clk mmp3_apmu_mux_clks[] = {
};
static struct mmp_param_div_clk apmu_div_clks[] = {
{0, "disp0_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 8, 4, 0, &disp0_lock},
{0, "disp0_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 8, 4, CLK_DIVIDER_ONE_BASED, &disp0_lock},
{0, "disp0_sphy_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 15, 5, 0, &disp0_lock},
{0, "disp1_div", "disp1_mux", CLK_SET_RATE_PARENT, APMU_DISP1, 8, 4, 0, &disp1_lock},
{0, "disp1_div", "disp1_mux", CLK_SET_RATE_PARENT, APMU_DISP1, 8, 4, CLK_DIVIDER_ONE_BASED, &disp1_lock},
{0, "ccic0_sphy_div", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock},
{0, "ccic1_sphy_div", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 10, 5, 0, &ccic1_lock},
};

View File

@ -68,7 +68,6 @@ static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
{
struct clk *clk;
struct mmp_clk_unit *unit = &pxa_unit->unit;
mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
@ -77,7 +76,7 @@ static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit)
mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
ARRAY_SIZE(fixed_factor_clks));
clk = mmp_clk_register_factor("uart_pll", "pll1_416",
mmp_clk_register_factor("uart_pll", "pll1_416",
CLK_SET_RATE_PARENT,
pxa_unit->mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,

View File

@ -197,7 +197,7 @@ static int ap_cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
stable_bit = BIT(clk->pll_regs->ratio_state_offset +
clk->cluster *
clk->pll_regs->ratio_state_cluster_offset),
clk->pll_regs->ratio_state_cluster_offset);
ret = regmap_read_poll_timeout(clk->pll_cr_base,
clk->pll_regs->ratio_state_reg, reg,
reg & stable_bit, STATUS_POLL_PERIOD_US,

View File

@ -19,11 +19,11 @@
#define MUX_RO_RATE_RO_OPS(name, clk_name) \
static struct clk_hw name ## _mux_hw; \
static struct clk_hw name ## _rate_hw; \
static struct clk_ops name ## _mux_ops = { \
static const struct clk_ops name ## _mux_ops = { \
.get_parent = name ## _get_parent, \
.set_parent = dummy_clk_set_parent, \
}; \
static struct clk_ops name ## _rate_ops = { \
static const struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
}; \
static struct clk * __init clk_register_ ## name(void) \
@ -38,7 +38,7 @@
#define RATE_RO_OPS(name, clk_name) \
static struct clk_hw name ## _rate_hw; \
static const struct clk_ops name ## _rate_ops = { \
static const struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
}; \
static struct clk * __init clk_register_ ## name(void) \
@ -53,7 +53,7 @@
#define RATE_OPS(name, clk_name) \
static struct clk_hw name ## _rate_hw; \
static struct clk_ops name ## _rate_ops = { \
static const struct clk_ops name ## _rate_ops = { \
.recalc_rate = name ## _get_rate, \
.set_rate = name ## _set_rate, \
.determine_rate = name ## _determine_rate, \

View File

@ -413,6 +413,15 @@ config SDM_LPASSCC_845
Say Y if you want to use the LPASS branch clocks of the LPASS clock
controller to reset the LPASS subsystem.
config SM_DISPCC_8250
tristate "SM8150 and SM8250 Display Clock Controller"
depends on SM_GCC_8150 || SM_GCC_8250
help
Support for the display clock controller on Qualcomm Technologies, Inc
SM8150 and SM8250 devices.
Say Y if you want to support display devices and functionality such as
splash screen.
config SM_GCC_8150
tristate "SM8150 Global Clock Controller"
help
@ -444,6 +453,24 @@ config SM_GPUCC_8250
Say Y if you want to support graphics controller devices and
functionality such as 3D graphics.
config SM_VIDEOCC_8150
tristate "SM8150 Video Clock Controller"
select SDM_GCC_8150
select QCOM_GDSC
help
Support for the video clock controller on SM8150 devices.
Say Y if you want to support video devices and functionality such as
video encode and decode.
config SM_VIDEOCC_8250
tristate "SM8250 Video Clock Controller"
select SDM_GCC_8250
select QCOM_GDSC
help
Support for the video clock controller on SM8250 devices.
Say Y if you want to support video devices and functionality such as
video encode and decode.
config SPMI_PMIC_CLKDIV
tristate "SPMI PMIC clkdiv Support"
depends on SPMI || COMPILE_TEST

View File

@ -64,10 +64,13 @@ obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o
obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o
obj-$(CONFIG_SM_VIDEOCC_8250) += videocc-sm8250.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
obj-$(CONFIG_QCOM_HFPLL) += hfpll.o

View File

@ -609,7 +609,7 @@ static unsigned long
alpha_huayra_pll_calc_rate(u64 prate, u32 l, u32 a)
{
/*
* a contains 16 bit alpha_val in twos compliment number in the range
* a contains 16 bit alpha_val in twos complement number in the range
* of [-0.5, 0.5).
*/
if (a >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1))
@ -641,7 +641,7 @@ alpha_huayra_pll_round_rate(unsigned long rate, unsigned long prate,
quotient++;
/*
* alpha_val should be in twos compliment number in the range
* alpha_val should be in twos complement number in the range
* of [-0.5, 0.5) so if quotient >= 0.5 then increment the l value
* since alpha value will be subtracted in this case.
*/
@ -666,7 +666,7 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha);
/*
* Depending upon alpha_mode, it can be treated as M/N value or
* as a twos compliment number. When alpha_mode=1,
* as a twos complement number. When alpha_mode=1,
* pll_alpha_val<15:8>=M and pll_apla_val<7:0>=N
*
* Fout=FIN*(L+(M/N))
@ -674,12 +674,12 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
* M is a signed number (-128 to 127) and N is unsigned
* (0 to 255). M/N has to be within +/-0.5.
*
* When alpha_mode=0, it is a twos compliment number in the
* When alpha_mode=0, it is a twos complement number in the
* range [-0.5, 0.5).
*
* Fout=FIN*(L+(alpha_val)/2^16)
*
* where alpha_val is twos compliment number.
* where alpha_val is twos complement number.
*/
if (!(ctl & PLL_ALPHA_MODE))
return alpha_huayra_pll_calc_rate(rate, l, alpha);

View File

@ -1182,14 +1182,21 @@ static int clk_rcg2_dp_set_rate_and_parent(struct clk_hw *hw,
static int clk_rcg2_dp_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_rate_request parent_req = *req;
int ret;
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
unsigned long num, den;
u64 tmp;
ret = __clk_determine_rate(clk_hw_get_parent(hw), &parent_req);
if (ret)
return ret;
/* Parent rate is a fixed phy link rate */
rational_best_approximation(req->best_parent_rate, req->rate,
GENMASK(rcg->mnd_width - 1, 0),
GENMASK(rcg->mnd_width - 1, 0), &den, &num);
req->best_parent_rate = parent_req.rate;
if (!num || !den)
return -EINVAL;
tmp = req->best_parent_rate * num;
do_div(tmp, den);
req->rate = tmp;
return 0;
}

View File

@ -202,7 +202,6 @@ static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = {
.name = "disp_cc_mdss_dp_crypto_clk_src",
.parent_data = disp_cc_parent_data_1,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_byte2_ops,
},
};
@ -216,7 +215,6 @@ static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = {
.name = "disp_cc_mdss_dp_link_clk_src",
.parent_data = disp_cc_parent_data_1,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_byte2_ops,
},
};
@ -230,7 +228,6 @@ static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = {
.name = "disp_cc_mdss_dp_pixel_clk_src",
.parent_data = disp_cc_parent_data_1,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_dp_ops,
},
};

File diff suppressed because it is too large Load Diff

View File

@ -4322,7 +4322,7 @@ static const struct freq_tbl ftbl_pcie_rchng_clk_src[] = {
{ }
};
struct clk_rcg2 pcie0_rchng_clk_src = {
static struct clk_rcg2 pcie0_rchng_clk_src = {
.cmd_rcgr = 0x75070,
.freq_tbl = ftbl_pcie_rchng_clk_src,
.hid_width = 5,

View File

@ -595,24 +595,12 @@ static const struct clk_parent_data gcc_xo_gpll1_emclk_sleep_parent_data[] = {
{ .fw_name = "sleep_clk", .name = "sleep_clk" },
};
static const struct parent_map gcc_xo_gpll6_gpll0_map[] = {
{ P_XO, 0 },
{ P_GPLL6, 1 },
{ P_GPLL0, 2 },
};
static const struct clk_parent_data gcc_xo_gpll6_gpll0_parent_data[] = {
{ .fw_name = "xo" },
{ .hw = &gpll6_vote.hw },
{ .hw = &gpll0_vote.hw },
};
static const struct parent_map gcc_xo_gpll6_gpll0a_map[] = {
{ P_XO, 0 },
{ P_GPLL6, 1 },
{ P_GPLL0_AUX, 2 },
};
static const struct clk_parent_data gcc_xo_gpll6_gpll0a_parent_data[] = {
{ .fw_name = "xo" },
{ .hw = &gpll6_vote.hw },

View File

@ -20,6 +20,7 @@
#include "clk-rcg.h"
#include "clk-branch.h"
#include "reset.h"
#include "gdsc.h"
enum {
P_XO,
@ -1772,6 +1773,32 @@ static struct clk_branch gcc_gp3_clk = {
},
};
static struct clk_branch gcc_lpass_q6_axi_clk = {
.halt_reg = 0x0280,
.clkr = {
.enable_reg = 0x0280,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_lpass_q6_axi_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
.halt_reg = 0x0284,
.clkr = {
.enable_reg = 0x0284,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_mss_q6_bimc_axi_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pcie_0_aux_clk = {
.halt_reg = 0x1ad4,
.clkr = {
@ -1790,6 +1817,32 @@ static struct clk_branch gcc_pcie_0_aux_clk = {
},
};
static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
.halt_reg = 0x1ad0,
.clkr = {
.enable_reg = 0x1ad0,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_pcie_0_cfg_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
.halt_reg = 0x1acc,
.clkr = {
.enable_reg = 0x1acc,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_pcie_0_mstr_axi_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pcie_0_pipe_clk = {
.halt_reg = 0x1ad8,
.halt_check = BRANCH_HALT_DELAY,
@ -1809,6 +1862,20 @@ static struct clk_branch gcc_pcie_0_pipe_clk = {
},
};
static struct clk_branch gcc_pcie_0_slv_axi_clk = {
.halt_reg = 0x1ac8,
.halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x1ac8,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_pcie_0_slv_axi_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pcie_1_aux_clk = {
.halt_reg = 0x1b54,
.clkr = {
@ -1827,6 +1894,32 @@ static struct clk_branch gcc_pcie_1_aux_clk = {
},
};
static struct clk_branch gcc_pcie_1_cfg_ahb_clk = {
.halt_reg = 0x1b54,
.clkr = {
.enable_reg = 0x1b54,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_pcie_1_cfg_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
.halt_reg = 0x1b50,
.clkr = {
.enable_reg = 0x1b50,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_pcie_1_mstr_axi_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pcie_1_pipe_clk = {
.halt_reg = 0x1b58,
.halt_check = BRANCH_HALT_DELAY,
@ -1846,6 +1939,19 @@ static struct clk_branch gcc_pcie_1_pipe_clk = {
},
};
static struct clk_branch gcc_pcie_1_slv_axi_clk = {
.halt_reg = 0x1b48,
.clkr = {
.enable_reg = 0x1b48,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_pcie_1_slv_axi_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_pdm2_clk = {
.halt_reg = 0x0ccc,
.clkr = {
@ -1864,6 +1970,19 @@ static struct clk_branch gcc_pdm2_clk = {
},
};
static struct clk_branch gcc_pdm_ahb_clk = {
.halt_reg = 0x0cc4,
.clkr = {
.enable_reg = 0x0cc4,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_pdm_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_sdcc1_apps_clk = {
.halt_reg = 0x04c4,
.clkr = {
@ -1899,6 +2018,23 @@ static struct clk_branch gcc_sdcc1_ahb_clk = {
},
};
static struct clk_branch gcc_sdcc2_ahb_clk = {
.halt_reg = 0x0508,
.clkr = {
.enable_reg = 0x0508,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_sdcc2_ahb_clk",
.parent_names = (const char *[]){
"periph_noc_clk_src",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_sdcc2_apps_clk = {
.halt_reg = 0x0504,
.clkr = {
@ -1917,6 +2053,23 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
},
};
static struct clk_branch gcc_sdcc3_ahb_clk = {
.halt_reg = 0x0548,
.clkr = {
.enable_reg = 0x0548,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_sdcc3_ahb_clk",
.parent_names = (const char *[]){
"periph_noc_clk_src",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_sdcc3_apps_clk = {
.halt_reg = 0x0544,
.clkr = {
@ -1935,6 +2088,23 @@ static struct clk_branch gcc_sdcc3_apps_clk = {
},
};
static struct clk_branch gcc_sdcc4_ahb_clk = {
.halt_reg = 0x0588,
.clkr = {
.enable_reg = 0x0588,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_sdcc4_ahb_clk",
.parent_names = (const char *[]){
"periph_noc_clk_src",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_sdcc4_apps_clk = {
.halt_reg = 0x0584,
.clkr = {
@ -1989,6 +2159,19 @@ static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
},
};
static struct clk_branch gcc_tsif_ahb_clk = {
.halt_reg = 0x0d84,
.clkr = {
.enable_reg = 0x0d84,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_tsif_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_tsif_ref_clk = {
.halt_reg = 0x0d88,
.clkr = {
@ -2007,6 +2190,19 @@ static struct clk_branch gcc_tsif_ref_clk = {
},
};
static struct clk_branch gcc_ufs_ahb_clk = {
.halt_reg = 0x1d4c,
.clkr = {
.enable_reg = 0x1d4c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_ufs_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_axi_clk = {
.halt_reg = 0x1d48,
.clkr = {
@ -2043,6 +2239,34 @@ static struct clk_branch gcc_ufs_rx_cfg_clk = {
},
};
static struct clk_branch gcc_ufs_rx_symbol_0_clk = {
.halt_reg = 0x1d60,
.halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x1d60,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_ufs_rx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_rx_symbol_1_clk = {
.halt_reg = 0x1d64,
.halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x1d64,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_ufs_rx_symbol_1_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_tx_cfg_clk = {
.halt_reg = 0x1d50,
.clkr = {
@ -2061,6 +2285,47 @@ static struct clk_branch gcc_ufs_tx_cfg_clk = {
},
};
static struct clk_branch gcc_ufs_tx_symbol_0_clk = {
.halt_reg = 0x1d58,
.halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x1d58,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_ufs_tx_symbol_0_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_ufs_tx_symbol_1_clk = {
.halt_reg = 0x1d5c,
.halt_check = BRANCH_HALT_DELAY,
.clkr = {
.enable_reg = 0x1d5c,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_ufs_tx_symbol_1_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_usb2_hs_phy_sleep_clk = {
.halt_reg = 0x04ac,
.clkr = {
.enable_reg = 0x04ac,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_usb2_hs_phy_sleep_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_usb30_master_clk = {
.halt_reg = 0x03c8,
.clkr = {
@ -2097,6 +2362,19 @@ static struct clk_branch gcc_usb30_mock_utmi_clk = {
},
};
static struct clk_branch gcc_usb30_sleep_clk = {
.halt_reg = 0x03cc,
.clkr = {
.enable_reg = 0x03cc,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_usb30_sleep_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_usb3_phy_aux_clk = {
.halt_reg = 0x1408,
.clkr = {
@ -2115,6 +2393,19 @@ static struct clk_branch gcc_usb3_phy_aux_clk = {
},
};
static struct clk_branch gcc_usb_hs_ahb_clk = {
.halt_reg = 0x0488,
.clkr = {
.enable_reg = 0x0488,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_usb_hs_ahb_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_usb_hs_system_clk = {
.halt_reg = 0x0484,
.clkr = {
@ -2133,6 +2424,59 @@ static struct clk_branch gcc_usb_hs_system_clk = {
},
};
static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = {
.halt_reg = 0x1a84,
.clkr = {
.enable_reg = 0x1a84,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data)
{
.name = "gcc_usb_phy_cfg_ahb2phy_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct gdsc pcie_gdsc = {
.gdscr = 0x1e18,
.pd = {
.name = "pcie",
},
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc pcie_0_gdsc = {
.gdscr = 0x1ac4,
.pd = {
.name = "pcie_0",
},
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc pcie_1_gdsc = {
.gdscr = 0x1b44,
.pd = {
.name = "pcie_1",
},
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc usb30_gdsc = {
.gdscr = 0x3c4,
.pd = {
.name = "usb30",
},
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc ufs_gdsc = {
.gdscr = 0x1d44,
.pd = {
.name = "ufs",
},
.pwrsts = PWRSTS_OFF_ON,
};
static struct clk_regmap *gcc_msm8994_clocks[] = {
[GPLL0_EARLY] = &gpll0_early.clkr,
[GPLL0] = &gpll0.clkr,
@ -2233,26 +2577,64 @@ static struct clk_regmap *gcc_msm8994_clocks[] = {
[GCC_GP1_CLK] = &gcc_gp1_clk.clkr,
[GCC_GP2_CLK] = &gcc_gp2_clk.clkr,
[GCC_GP3_CLK] = &gcc_gp3_clk.clkr,
[GCC_LPASS_Q6_AXI_CLK] = &gcc_lpass_q6_axi_clk.clkr,
[GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr,
[GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
[GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr,
[GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr,
[GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
[GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr,
[GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
[GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr,
[GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr,
[GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr,
[GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr,
[GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr,
[GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
[GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
[GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
[GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr,
[GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr,
[GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr,
[GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
[GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr,
[GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr,
[GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr,
[GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
[GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr,
[GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr,
[GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr,
[GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr,
[GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr,
[GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr,
[GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr,
[GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr,
[GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr,
[GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr,
[GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr,
[GCC_UFS_TX_SYMBOL_1_CLK] = &gcc_ufs_tx_symbol_1_clk.clkr,
[GCC_USB2_HS_PHY_SLEEP_CLK] = &gcc_usb2_hs_phy_sleep_clk.clkr,
[GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr,
[GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr,
[GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr,
[GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr,
[GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr,
[GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr,
[GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr,
};
static struct gdsc *gcc_msm8994_gdscs[] = {
[PCIE_GDSC] = &pcie_gdsc,
[PCIE_0_GDSC] = &pcie_0_gdsc,
[PCIE_1_GDSC] = &pcie_1_gdsc,
[USB30_GDSC] = &usb30_gdsc,
[UFS_GDSC] = &ufs_gdsc,
};
static const struct qcom_reset_map gcc_msm8994_resets[] = {
[USB3_PHY_RESET] = { 0x1400 },
[USB3PHY_PHY_RESET] = { 0x1404 },
[PCIE_PHY_0_RESET] = { 0x1b18 },
[PCIE_PHY_1_RESET] = { 0x1b98 },
[QUSB2_PHY_RESET] = { 0x04b8 },
};
static const struct regmap_config gcc_msm8994_regmap_config = {
@ -2267,6 +2649,10 @@ static const struct qcom_cc_desc gcc_msm8994_desc = {
.config = &gcc_msm8994_regmap_config,
.clks = gcc_msm8994_clocks,
.num_clks = ARRAY_SIZE(gcc_msm8994_clocks),
.resets = gcc_msm8994_resets,
.num_resets = ARRAY_SIZE(gcc_msm8994_resets),
.gdscs = gcc_msm8994_gdscs,
.num_gdscs = ARRAY_SIZE(gcc_msm8994_gdscs),
};
static const struct of_device_id gcc_msm8994_match_table[] = {

View File

@ -666,7 +666,7 @@ static struct clk_rcg2 hmss_rbcpr_clk_src = {
.cmd_rcgr = 0x48044,
.mnd_width = 0,
.hid_width = 5,
.parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div,
.parent_map = gcc_parent_map_xo_gpll0,
.freq_tbl = ftbl_hmss_rbcpr_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "hmss_rbcpr_clk_src",

View File

@ -358,6 +358,14 @@ static int gdsc_init(struct gdsc *sc)
if ((sc->flags & VOTABLE) && on)
gdsc_enable(&sc->pd);
/*
* Make sure the retain bit is set if the GDSC is already on, otherwise
* we end up turning off the GDSC and destroying all the register
* contents that we thought we were saving.
*/
if ((sc->flags & RETAIN_FF_ENABLE) && on)
gdsc_retain_ff_on(sc);
/* If ALWAYS_ON GDSCs are not ON, turn them ON */
if (sc->flags & ALWAYS_ON) {
if (!on)

View File

@ -0,0 +1,276 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,videocc-sm8150.h>
#include "common.h"
#include "clk-alpha-pll.h"
#include "clk-branch.h"
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "reset.h"
#include "gdsc.h"
enum {
P_BI_TCXO,
P_CHIP_SLEEP_CLK,
P_CORE_BI_PLL_TEST_SE,
P_VIDEO_PLL0_OUT_EVEN,
P_VIDEO_PLL0_OUT_MAIN,
P_VIDEO_PLL0_OUT_ODD,
};
static struct pll_vco trion_vco[] = {
{ 249600000, 2000000000, 0 },
};
static struct alpha_pll_config video_pll0_config = {
.l = 0x14,
.alpha = 0xD555,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002267,
.config_ctl_hi1_val = 0x00000024,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x000000D0,
};
static struct clk_alpha_pll video_pll0 = {
.offset = 0x42c,
.vco_table = trion_vco,
.num_vco = ARRAY_SIZE(trion_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION],
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "video_pll0",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_trion_ops,
},
},
};
static const struct parent_map video_cc_parent_map_0[] = {
{ P_BI_TCXO, 0 },
{ P_VIDEO_PLL0_OUT_MAIN, 1 },
};
static const struct clk_parent_data video_cc_parent_data_0[] = {
{ .fw_name = "bi_tcxo" },
{ .hw = &video_pll0.clkr.hw },
};
static const struct freq_tbl ftbl_video_cc_iris_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(240000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(338000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(365000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(444000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
F(533000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
{ }
};
static struct clk_rcg2 video_cc_iris_clk_src = {
.cmd_rcgr = 0x7f0,
.mnd_width = 0,
.hid_width = 5,
.parent_map = video_cc_parent_map_0,
.freq_tbl = ftbl_video_cc_iris_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "video_cc_iris_clk_src",
.parent_data = video_cc_parent_data_0,
.num_parents = ARRAY_SIZE(video_cc_parent_data_0),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
},
};
static struct clk_branch video_cc_iris_ahb_clk = {
.halt_reg = 0x8f4,
.halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x8f4,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_iris_ahb_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvs0_core_clk = {
.halt_reg = 0x890,
.halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x890,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs0_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvs1_core_clk = {
.halt_reg = 0x8d0,
.halt_check = BRANCH_VOTED,
.clkr = {
.enable_reg = 0x8d0,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs1_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvsc_core_clk = {
.halt_reg = 0x850,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x850,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvsc_core_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_iris_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct gdsc venus_gdsc = {
.gdscr = 0x814,
.pd = {
.name = "venus_gdsc",
},
.flags = 0,
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc vcodec0_gdsc = {
.gdscr = 0x874,
.pd = {
.name = "vcodec0_gdsc",
},
.flags = HW_CTRL,
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc vcodec1_gdsc = {
.gdscr = 0x8b4,
.pd = {
.name = "vcodec1_gdsc",
},
.flags = HW_CTRL,
.pwrsts = PWRSTS_OFF_ON,
};
static struct clk_regmap *video_cc_sm8150_clocks[] = {
[VIDEO_CC_IRIS_AHB_CLK] = &video_cc_iris_ahb_clk.clkr,
[VIDEO_CC_IRIS_CLK_SRC] = &video_cc_iris_clk_src.clkr,
[VIDEO_CC_MVS0_CORE_CLK] = &video_cc_mvs0_core_clk.clkr,
[VIDEO_CC_MVS1_CORE_CLK] = &video_cc_mvs1_core_clk.clkr,
[VIDEO_CC_MVSC_CORE_CLK] = &video_cc_mvsc_core_clk.clkr,
[VIDEO_CC_PLL0] = &video_pll0.clkr,
};
static struct gdsc *video_cc_sm8150_gdscs[] = {
[VENUS_GDSC] = &venus_gdsc,
[VCODEC0_GDSC] = &vcodec0_gdsc,
[VCODEC1_GDSC] = &vcodec1_gdsc,
};
static const struct regmap_config video_cc_sm8150_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0xb94,
.fast_io = true,
};
static const struct qcom_reset_map video_cc_sm8150_resets[] = {
[VIDEO_CC_MVSC_CORE_CLK_BCR] = { 0x850, 2 },
};
static const struct qcom_cc_desc video_cc_sm8150_desc = {
.config = &video_cc_sm8150_regmap_config,
.clks = video_cc_sm8150_clocks,
.num_clks = ARRAY_SIZE(video_cc_sm8150_clocks),
.resets = video_cc_sm8150_resets,
.num_resets = ARRAY_SIZE(video_cc_sm8150_resets),
.gdscs = video_cc_sm8150_gdscs,
.num_gdscs = ARRAY_SIZE(video_cc_sm8150_gdscs),
};
static const struct of_device_id video_cc_sm8150_match_table[] = {
{ .compatible = "qcom,sm8150-videocc" },
{ }
};
MODULE_DEVICE_TABLE(of, video_cc_sm8150_match_table);
static int video_cc_sm8150_probe(struct platform_device *pdev)
{
struct regmap *regmap;
regmap = qcom_cc_map(pdev, &video_cc_sm8150_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
clk_trion_pll_configure(&video_pll0, regmap, &video_pll0_config);
/* Keep VIDEO_CC_XO_CLK ALWAYS-ON */
regmap_update_bits(regmap, 0x984, 0x1, 0x1);
return qcom_cc_really_probe(pdev, &video_cc_sm8150_desc, regmap);
}
static struct platform_driver video_cc_sm8150_driver = {
.probe = video_cc_sm8150_probe,
.driver = {
.name = "video_cc-sm8150",
.of_match_table = video_cc_sm8150_match_table,
},
};
static int __init video_cc_sm8150_init(void)
{
return platform_driver_register(&video_cc_sm8150_driver);
}
subsys_initcall(video_cc_sm8150_init);
static void __exit video_cc_sm8150_exit(void)
{
platform_driver_unregister(&video_cc_sm8150_driver);
}
module_exit(video_cc_sm8150_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("QTI VIDEOCC SM8150 Driver");

View File

@ -0,0 +1,369 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,videocc-sm8250.h>
#include "clk-alpha-pll.h"
#include "clk-branch.h"
#include "clk-rcg.h"
#include "clk-regmap.h"
#include "clk-regmap-divider.h"
#include "common.h"
#include "reset.h"
#include "gdsc.h"
enum {
P_BI_TCXO,
P_CHIP_SLEEP_CLK,
P_CORE_BI_PLL_TEST_SE,
P_VIDEO_PLL0_OUT_MAIN,
P_VIDEO_PLL1_OUT_MAIN,
};
static struct pll_vco lucid_vco[] = {
{ 249600000, 2000000000, 0 },
};
static const struct alpha_pll_config video_pll0_config = {
.l = 0x25,
.alpha = 0x8000,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002261,
.config_ctl_hi1_val = 0x329A699C,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x00000000,
};
static struct clk_alpha_pll video_pll0 = {
.offset = 0x42c,
.vco_table = lucid_vco,
.num_vco = ARRAY_SIZE(lucid_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "video_pll0",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_lucid_ops,
},
},
};
static const struct alpha_pll_config video_pll1_config = {
.l = 0x2B,
.alpha = 0xC000,
.config_ctl_val = 0x20485699,
.config_ctl_hi_val = 0x00002261,
.config_ctl_hi1_val = 0x329A699C,
.user_ctl_val = 0x00000000,
.user_ctl_hi_val = 0x00000805,
.user_ctl_hi1_val = 0x00000000,
};
static struct clk_alpha_pll video_pll1 = {
.offset = 0x7d0,
.vco_table = lucid_vco,
.num_vco = ARRAY_SIZE(lucid_vco),
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "video_pll1",
.parent_data = &(const struct clk_parent_data){
.fw_name = "bi_tcxo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_lucid_ops,
},
},
};
static const struct parent_map video_cc_parent_map_1[] = {
{ P_BI_TCXO, 0 },
{ P_VIDEO_PLL0_OUT_MAIN, 1 },
};
static const struct clk_parent_data video_cc_parent_data_1[] = {
{ .fw_name = "bi_tcxo" },
{ .hw = &video_pll0.clkr.hw },
};
static const struct parent_map video_cc_parent_map_2[] = {
{ P_BI_TCXO, 0 },
{ P_VIDEO_PLL1_OUT_MAIN, 1 },
};
static const struct clk_parent_data video_cc_parent_data_2[] = {
{ .fw_name = "bi_tcxo" },
{ .hw = &video_pll1.clkr.hw },
};
static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(720000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(1014000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(1098000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
F(1332000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
{ }
};
static struct clk_rcg2 video_cc_mvs0_clk_src = {
.cmd_rcgr = 0xb94,
.mnd_width = 0,
.hid_width = 5,
.parent_map = video_cc_parent_map_1,
.freq_tbl = ftbl_video_cc_mvs0_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs0_clk_src",
.parent_data = video_cc_parent_data_1,
.num_parents = ARRAY_SIZE(video_cc_parent_data_1),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
},
};
static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {
F(19200000, P_BI_TCXO, 1, 0, 0),
F(840000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
F(1098000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
F(1332000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),
{ }
};
static struct clk_rcg2 video_cc_mvs1_clk_src = {
.cmd_rcgr = 0xbb4,
.mnd_width = 0,
.hid_width = 5,
.parent_map = video_cc_parent_map_2,
.freq_tbl = ftbl_video_cc_mvs1_clk_src,
.clkr.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs1_clk_src",
.parent_data = video_cc_parent_data_2,
.num_parents = ARRAY_SIZE(video_cc_parent_data_2),
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_rcg2_shared_ops,
},
};
static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {
.reg = 0xc54,
.shift = 0,
.width = 2,
.clkr.hw.init = &(struct clk_init_data) {
.name = "video_cc_mvs0c_div2_div_clk_src",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_mvs0_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_regmap_div_ro_ops,
},
};
static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {
.reg = 0xcf4,
.shift = 0,
.width = 2,
.clkr.hw.init = &(struct clk_init_data) {
.name = "video_cc_mvs1c_div2_div_clk_src",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_mvs1_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_regmap_div_ro_ops,
},
};
static struct clk_branch video_cc_mvs0c_clk = {
.halt_reg = 0xc34,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0xc34,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs0c_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_mvs0c_div2_div_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvs1_div2_clk = {
.halt_reg = 0xdf4,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0xdf4,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs1_div2_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch video_cc_mvs1c_clk = {
.halt_reg = 0xcd4,
.halt_check = BRANCH_HALT_VOTED,
.clkr = {
.enable_reg = 0xcd4,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "video_cc_mvs1c_clk",
.parent_data = &(const struct clk_parent_data){
.hw = &video_cc_mvs1c_div2_div_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
};
static struct gdsc mvs0c_gdsc = {
.gdscr = 0xbf8,
.pd = {
.name = "mvs0c_gdsc",
},
.flags = 0,
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc mvs1c_gdsc = {
.gdscr = 0xc98,
.pd = {
.name = "mvs1c_gdsc",
},
.flags = 0,
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc mvs0_gdsc = {
.gdscr = 0xd18,
.pd = {
.name = "mvs0_gdsc",
},
.flags = HW_CTRL,
.pwrsts = PWRSTS_OFF_ON,
};
static struct gdsc mvs1_gdsc = {
.gdscr = 0xd98,
.pd = {
.name = "mvs1_gdsc",
},
.flags = HW_CTRL,
.pwrsts = PWRSTS_OFF_ON,
};
static struct clk_regmap *video_cc_sm8250_clocks[] = {
[VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,
[VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,
[VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,
[VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,
[VIDEO_CC_MVS1_DIV2_CLK] = &video_cc_mvs1_div2_clk.clkr,
[VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,
[VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,
[VIDEO_CC_PLL0] = &video_pll0.clkr,
[VIDEO_CC_PLL1] = &video_pll1.clkr,
};
static const struct qcom_reset_map video_cc_sm8250_resets[] = {
[VIDEO_CC_CVP_INTERFACE_BCR] = { 0xe54 },
[VIDEO_CC_CVP_MVS0_BCR] = { 0xd14 },
[VIDEO_CC_MVS0C_CLK_ARES] = { 0xc34, 2 },
[VIDEO_CC_CVP_MVS0C_BCR] = { 0xbf4 },
[VIDEO_CC_CVP_MVS1_BCR] = { 0xd94 },
[VIDEO_CC_MVS1C_CLK_ARES] = { 0xcd4, 2 },
[VIDEO_CC_CVP_MVS1C_BCR] = { 0xc94 },
};
static struct gdsc *video_cc_sm8250_gdscs[] = {
[MVS0C_GDSC] = &mvs0c_gdsc,
[MVS1C_GDSC] = &mvs1c_gdsc,
[MVS0_GDSC] = &mvs0_gdsc,
[MVS1_GDSC] = &mvs1_gdsc,
};
static const struct regmap_config video_cc_sm8250_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0xf4c,
.fast_io = true,
};
static const struct qcom_cc_desc video_cc_sm8250_desc = {
.config = &video_cc_sm8250_regmap_config,
.clks = video_cc_sm8250_clocks,
.num_clks = ARRAY_SIZE(video_cc_sm8250_clocks),
.resets = video_cc_sm8250_resets,
.num_resets = ARRAY_SIZE(video_cc_sm8250_resets),
.gdscs = video_cc_sm8250_gdscs,
.num_gdscs = ARRAY_SIZE(video_cc_sm8250_gdscs),
};
static const struct of_device_id video_cc_sm8250_match_table[] = {
{ .compatible = "qcom,sm8250-videocc" },
{ }
};
MODULE_DEVICE_TABLE(of, video_cc_sm8250_match_table);
static int video_cc_sm8250_probe(struct platform_device *pdev)
{
struct regmap *regmap;
regmap = qcom_cc_map(pdev, &video_cc_sm8250_desc);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config);
clk_lucid_pll_configure(&video_pll1, regmap, &video_pll1_config);
/* Keep VIDEO_CC_AHB_CLK and VIDEO_CC_XO_CLK ALWAYS-ON */
regmap_update_bits(regmap, 0xe58, BIT(0), BIT(0));
regmap_update_bits(regmap, 0xeec, BIT(0), BIT(0));
return qcom_cc_really_probe(pdev, &video_cc_sm8250_desc, regmap);
}
static struct platform_driver video_cc_sm8250_driver = {
.probe = video_cc_sm8250_probe,
.driver = {
.name = "sm8250-videocc",
.of_match_table = video_cc_sm8250_match_table,
},
};
static int __init video_cc_sm8250_init(void)
{
return platform_driver_register(&video_cc_sm8250_driver);
}
subsys_initcall(video_cc_sm8250_init);
static void __exit video_cc_sm8250_exit(void)
{
platform_driver_unregister(&video_cc_sm8250_driver);
}
module_exit(video_cc_sm8250_exit);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("QTI VIDEOCC SM8250 Driver");

View File

@ -30,6 +30,7 @@ config CLK_RENESAS
select CLK_R8A77980 if ARCH_R8A77980
select CLK_R8A77990 if ARCH_R8A77990
select CLK_R8A77995 if ARCH_R8A77995
select CLK_R8A779A0 if ARCH_R8A779A0
select CLK_R9A06G032 if ARCH_R9A06G032
select CLK_SH73A0 if ARCH_SH73A0
@ -145,6 +146,10 @@ config CLK_R8A77995
bool "R-Car D3 clock support" if COMPILE_TEST
select CLK_RCAR_GEN3_CPG
config CLK_R8A779A0
bool "R-Car V3U clock support" if COMPILE_TEST
select CLK_RENESAS_CPG_MSSR
config CLK_R9A06G032
bool "Renesas R9A06G032 clock driver"
help
@ -162,7 +167,7 @@ config CLK_RCAR_GEN2_CPG
select CLK_RENESAS_CPG_MSSR
config CLK_RCAR_GEN3_CPG
bool "R-Car Gen3 CPG clock support" if COMPILE_TEST
bool "R-Car Gen3 and RZ/G2 CPG clock support" if COMPILE_TEST
select CLK_RENESAS_CPG_MSSR
config CLK_RCAR_USB2_CLOCK_SEL

View File

@ -27,6 +27,7 @@ obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77980) += r8a77980-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o
obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o
obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o
obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o
obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o

View File

@ -214,7 +214,7 @@ const struct cpg_mssr_info r7s9210_cpg_mssr_info __initconst = {
.cpg_clk_register = rza2_cpg_clk_register,
/* RZ/A2 has Standby Control Registers */
.stbyctrl = true,
.reg_layout = CLK_REG_LAYOUT_RZ_A,
};
static void __init r7s9210_cpg_mssr_early_init(struct device_node *np)

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