Merge branches 'clk-doc', 'clk-amlogic', 'clk-mediatek', 'clk-twl' and 'clk-imx' into clk-next

- Add clock driver for TWL6032

* clk-doc:
  clk: linux/clk-provider.h: fix kernel-doc warnings and typos

* clk-amlogic:
  clk: meson: S4: select CONFIG_COMMON_CLK_MESON_CLKC_UTILS
  clk: meson: S4: add support for Amlogic S4 SoC peripheral clock controller
  clk: meson: S4: add support for Amlogic S4 SoC PLL clock driver
  dt-bindings: clock: document Amlogic S4 SoC peripherals clock controller
  dt-bindings: clock: document Amlogic S4 SoC PLL clock controller

* clk-mediatek:
  clk: mediatek: fix double free in mtk_clk_register_pllfh()
  clk: mediatek: clk-mt2701: Add check for mtk_alloc_clk_data
  clk: mediatek: clk-mt7629: Add check for mtk_alloc_clk_data
  clk: mediatek: clk-mt7629-eth: Add check for mtk_alloc_clk_data
  clk: mediatek: clk-mt6797: Add check for mtk_alloc_clk_data
  clk: mediatek: clk-mt6779: Add check for mtk_alloc_clk_data
  clk: mediatek: clk-mt6765: Add check for mtk_alloc_clk_data

* clk-twl:
  clk: twl: add clock driver for TWL6032

* clk-imx:
  clk: imx: imx8qm/qxp: add more resources to whitelist
  clk: imx: scu: ignore clks not owned by Cortex-A partition
  clk: imx8: remove MLB support
  clk: imx: imx8qm-rsrc: drop VPU_UART/VPUCORE
  clk: imx: imx8qxp: correct the enet clocks for i.MX8DXL
  clk: imx: imx8qxp: Fix elcdif_pll clock
  clk: imx: imx8dxl-rsrc: keep sorted in the ascending order
  clk: imx: imx6sx: Allow a different LCDIF1 clock parent
  clk: imx: imx8mq: correct error handling path
  clk: imx8mp: Remove non-existent IMX8MP_CLK_AUDIOMIX_PDM_ROOT
  clk: imx: imx8: Simplify clk_imx_acm_detach_pm_domains()
  clk: imx: imx8: Add a message in case of devm_clk_hw_register_mux_parent_data_table() error
  clk: imx: imx8: Fix an error handling path in imx8_acm_clk_probe()
  clk: imx: imx8: Fix an error handling path if devm_clk_hw_register_mux_parent_data_table() fails
  clk: imx: imx8: Fix an error handling path in clk_imx_acm_attach_pm_domains()
  clk: imx: Select MXC_CLK for CLK_IMX8QXP
This commit is contained in:
Stephen Boyd 2023-10-30 14:10:39 -07:00
32 changed files with 5554 additions and 47 deletions

View file

@ -0,0 +1,96 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/amlogic,s4-peripherals-clkc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic S4 Peripherals Clock Controller
maintainers:
- Yu Tu <yu.tu@amlogic.com>
properties:
compatible:
const: amlogic,s4-peripherals-clkc
reg:
maxItems: 1
clocks:
minItems: 14
items:
- description: input fixed pll div2
- description: input fixed pll div2p5
- description: input fixed pll div3
- description: input fixed pll div4
- description: input fixed pll div5
- description: input fixed pll div7
- description: input hifi pll
- description: input gp0 pll
- description: input mpll0
- description: input mpll1
- description: input mpll2
- description: input mpll3
- description: input hdmi pll
- description: input oscillator (usually at 24MHz)
- description: input external 32kHz reference (optional)
clock-names:
minItems: 14
items:
- const: fclk_div2
- const: fclk_div2p5
- const: fclk_div3
- const: fclk_div4
- const: fclk_div5
- const: fclk_div7
- const: hifi_pll
- const: gp0_pll
- const: mpll0
- const: mpll1
- const: mpll2
- const: mpll3
- const: hdmi_pll
- const: xtal
- const: ext_32k
"#clock-cells":
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- "#clock-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/amlogic,s4-peripherals-clkc.h>
clkc_periphs: clock-controller@fe000000 {
compatible = "amlogic,s4-peripherals-clkc";
reg = <0xfe000000 0x49c>;
clocks = <&clkc_pll 3>,
<&clkc_pll 13>,
<&clkc_pll 5>,
<&clkc_pll 7>,
<&clkc_pll 9>,
<&clkc_pll 11>,
<&clkc_pll 17>,
<&clkc_pll 15>,
<&clkc_pll 25>,
<&clkc_pll 27>,
<&clkc_pll 29>,
<&clkc_pll 31>,
<&clkc_pll 20>,
<&xtal>;
clock-names = "fclk_div2", "fclk_div2p5", "fclk_div3", "fclk_div4",
"fclk_div5", "fclk_div7", "hifi_pll", "gp0_pll",
"mpll0", "mpll1", "mpll2", "mpll3", "hdmi_pll", "xtal";
#clock-cells = <1>;
};
...

View file

@ -0,0 +1,49 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (C) 2022-2023 Amlogic, Inc. All rights reserved
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/amlogic,s4-pll-clkc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic S4 PLL Clock Controller
maintainers:
- Yu Tu <yu.tu@amlogic.com>
properties:
compatible:
const: amlogic,s4-pll-clkc
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: xtal
"#clock-cells":
const: 1
required:
- compatible
- reg
- clocks
- clock-names
- "#clock-cells"
additionalProperties: false
examples:
- |
clkc_pll: clock-controller@fe008000 {
compatible = "amlogic,s4-pll-clkc";
reg = <0xfe008000 0x1e8>;
clocks = <&xtal>;
clock-names = "xtal";
#clock-cells = <1>;
};
...

View file

@ -277,6 +277,15 @@ config COMMON_CLK_S2MPS11
clock. These multi-function devices have two (S2MPS14) or three
(S2MPS11, S5M8767) fixed-rate oscillators, clocked at 32KHz each.
config CLK_TWL
tristate "Clock driver for the TWL PMIC family"
depends on TWL4030_CORE
help
Enable support for controlling the clock resources on TWL family
PMICs. These devices have some 32K clock outputs which can be
controlled by software. For now, only the TWL6032 clocks are
supported.
config CLK_TWL6040
tristate "External McPDM functional clock from twl6040"
depends on TWL6040_CORE

View file

@ -72,6 +72,7 @@ obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o
obj-$(CONFIG_COMMON_CLK_TPS68470) += clk-tps68470.o
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
obj-$(CONFIG_CLK_TWL) += clk-twl.o
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
obj-$(CONFIG_COMMON_CLK_RS9_PCIE) += clk-renesas-pcie.o
obj-$(CONFIG_COMMON_CLK_SI521XX) += clk-si521xx.o

197
drivers/clk/clk-twl.c Normal file
View file

@ -0,0 +1,197 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Clock driver for twl device.
*
* inspired by the driver for the Palmas device
*/
#include <linux/clk-provider.h>
#include <linux/mfd/twl.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#define VREG_STATE 2
#define TWL6030_CFG_STATE_OFF 0x00
#define TWL6030_CFG_STATE_ON 0x01
#define TWL6030_CFG_STATE_MASK 0x03
struct twl_clock_info {
struct device *dev;
u8 base;
struct clk_hw hw;
};
static inline int
twlclk_read(struct twl_clock_info *info, unsigned int slave_subgp,
unsigned int offset)
{
u8 value;
int status;
status = twl_i2c_read_u8(slave_subgp, &value,
info->base + offset);
return (status < 0) ? status : value;
}
static inline int
twlclk_write(struct twl_clock_info *info, unsigned int slave_subgp,
unsigned int offset, u8 value)
{
return twl_i2c_write_u8(slave_subgp, value,
info->base + offset);
}
static inline struct twl_clock_info *to_twl_clks_info(struct clk_hw *hw)
{
return container_of(hw, struct twl_clock_info, hw);
}
static unsigned long twl_clks_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return 32768;
}
static int twl6032_clks_prepare(struct clk_hw *hw)
{
struct twl_clock_info *cinfo = to_twl_clks_info(hw);
int ret;
ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
TWL6030_CFG_STATE_ON);
if (ret < 0)
dev_err(cinfo->dev, "clk prepare failed\n");
return ret;
}
static void twl6032_clks_unprepare(struct clk_hw *hw)
{
struct twl_clock_info *cinfo = to_twl_clks_info(hw);
int ret;
ret = twlclk_write(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE,
TWL6030_CFG_STATE_OFF);
if (ret < 0)
dev_err(cinfo->dev, "clk unprepare failed\n");
}
static int twl6032_clks_is_prepared(struct clk_hw *hw)
{
struct twl_clock_info *cinfo = to_twl_clks_info(hw);
int val;
val = twlclk_read(cinfo, TWL_MODULE_PM_RECEIVER, VREG_STATE);
if (val < 0) {
dev_err(cinfo->dev, "clk read failed\n");
return val;
}
val &= TWL6030_CFG_STATE_MASK;
return val == TWL6030_CFG_STATE_ON;
}
static const struct clk_ops twl6032_clks_ops = {
.prepare = twl6032_clks_prepare,
.unprepare = twl6032_clks_unprepare,
.is_prepared = twl6032_clks_is_prepared,
.recalc_rate = twl_clks_recalc_rate,
};
struct twl_clks_data {
struct clk_init_data init;
u8 base;
};
static const struct twl_clks_data twl6032_clks[] = {
{
.init = {
.name = "clk32kg",
.ops = &twl6032_clks_ops,
.flags = CLK_IGNORE_UNUSED,
},
.base = 0x8C,
},
{
.init = {
.name = "clk32kaudio",
.ops = &twl6032_clks_ops,
.flags = CLK_IGNORE_UNUSED,
},
.base = 0x8F,
},
{
/* sentinel */
}
};
static int twl_clks_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *clk_data;
const struct twl_clks_data *hw_data;
struct twl_clock_info *cinfo;
int ret;
int i;
int count;
hw_data = twl6032_clks;
for (count = 0; hw_data[count].init.name; count++)
;
clk_data = devm_kzalloc(&pdev->dev,
struct_size(clk_data, hws, count),
GFP_KERNEL);
if (!clk_data)
return -ENOMEM;
clk_data->num = count;
cinfo = devm_kcalloc(&pdev->dev, count, sizeof(*cinfo), GFP_KERNEL);
if (!cinfo)
return -ENOMEM;
for (i = 0; i < count; i++) {
cinfo[i].base = hw_data[i].base;
cinfo[i].dev = &pdev->dev;
cinfo[i].hw.init = &hw_data[i].init;
ret = devm_clk_hw_register(&pdev->dev, &cinfo[i].hw);
if (ret) {
return dev_err_probe(&pdev->dev, ret,
"Fail to register clock %s\n",
hw_data[i].init.name);
}
clk_data->hws[i] = &cinfo[i].hw;
}
ret = devm_of_clk_add_hw_provider(&pdev->dev,
of_clk_hw_onecell_get, clk_data);
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Fail to add clock driver\n");
return 0;
}
static const struct platform_device_id twl_clks_id[] = {
{
.name = "twl6032-clk",
}, {
/* sentinel */
}
};
MODULE_DEVICE_TABLE(platform, twl_clks_id);
static struct platform_driver twl_clks_driver = {
.driver = {
.name = "twl-clk",
},
.probe = twl_clks_probe,
.id_table = twl_clks_id,
};
module_platform_driver(twl_clks_driver);
MODULE_DESCRIPTION("Clock driver for TWL Series Devices");
MODULE_LICENSE("GPL");

View file

@ -96,6 +96,7 @@ config CLK_IMX8QXP
depends on (ARCH_MXC && ARM64) || COMPILE_TEST
depends on IMX_SCU && HAVE_ARM_SMCCC
select MXC_CLK_SCU
select MXC_CLK
help
Build the driver for IMX8QXP SCU based clocks.

View file

@ -121,6 +121,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
void __iomem *base;
bool lcdif1_assigned_clk;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
IMX6SX_CLK_CLK_END), GFP_KERNEL);
@ -498,9 +499,16 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
clk_set_parent(hws[IMX6SX_CLK_EIM_SLOW_SEL]->clk, hws[IMX6SX_CLK_PLL2_PFD2]->clk);
clk_set_rate(hws[IMX6SX_CLK_EIM_SLOW]->clk, 132000000);
/* set parent clock for LCDIF1 pixel clock */
clk_set_parent(hws[IMX6SX_CLK_LCDIF1_PRE_SEL]->clk, hws[IMX6SX_CLK_PLL5_VIDEO_DIV]->clk);
clk_set_parent(hws[IMX6SX_CLK_LCDIF1_SEL]->clk, hws[IMX6SX_CLK_LCDIF1_PODF]->clk);
np = of_find_node_by_path("/soc/bus@2200000/spba-bus@2240000/lcdif@2220000");
lcdif1_assigned_clk = of_find_property(np, "assigned-clock-parents", NULL);
/* Set parent clock for LCDIF1 pixel clock if not done via devicetree */
if (!lcdif1_assigned_clk) {
clk_set_parent(hws[IMX6SX_CLK_LCDIF1_PRE_SEL]->clk,
hws[IMX6SX_CLK_PLL5_VIDEO_DIV]->clk);
clk_set_parent(hws[IMX6SX_CLK_LCDIF1_SEL]->clk,
hws[IMX6SX_CLK_LCDIF1_PODF]->clk);
}
/* Set the parent clks of PCIe lvds1 and pcie_axi to be pcie ref, axi */
if (clk_set_parent(hws[IMX6SX_CLK_LVDS1_SEL]->clk, hws[IMX6SX_CLK_PCIE_REF_125M]->clk))

View file

@ -77,7 +77,7 @@ struct imx8_acm_priv {
static const struct clk_parent_data imx8qm_aud_clk_sels[] = {
{ .fw_name = "aud_rec_clk0_lpcg_clk" },
{ .fw_name = "aud_rec_clk1_lpcg_clk" },
{ .fw_name = "mlb_clk" },
{ .fw_name = "dummy" },
{ .fw_name = "hdmi_rx_mclk" },
{ .fw_name = "ext_aud_mclk0" },
{ .fw_name = "ext_aud_mclk1" },
@ -103,7 +103,7 @@ static const struct clk_parent_data imx8qm_aud_clk_sels[] = {
static const struct clk_parent_data imx8qm_mclk_out_sels[] = {
{ .fw_name = "aud_rec_clk0_lpcg_clk" },
{ .fw_name = "aud_rec_clk1_lpcg_clk" },
{ .fw_name = "mlb_clk" },
{ .fw_name = "dummy" },
{ .fw_name = "hdmi_rx_mclk" },
{ .fw_name = "spdif0_rx" },
{ .fw_name = "spdif1_rx" },
@ -122,7 +122,7 @@ static const struct clk_parent_data imx8qm_asrc_mux_clk_sels[] = {
{ .fw_name = "sai4_rx_bclk" },
{ .fw_name = "sai5_tx_bclk" },
{ .index = -1 },
{ .fw_name = "mlb_clk" },
{ .fw_name = "dummy" },
};
@ -279,8 +279,10 @@ static int clk_imx_acm_attach_pm_domains(struct device *dev,
for (i = 0; i < dev_pm->num_domains; i++) {
dev_pm->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
if (IS_ERR(dev_pm->pd_dev[i]))
return PTR_ERR(dev_pm->pd_dev[i]);
if (IS_ERR(dev_pm->pd_dev[i])) {
ret = PTR_ERR(dev_pm->pd_dev[i]);
goto detach_pm;
}
dev_pm->pd_dev_link[i] = device_link_add(dev,
dev_pm->pd_dev[i],
@ -308,20 +310,18 @@ static int clk_imx_acm_attach_pm_domains(struct device *dev,
* @dev: deivice pointer
* @dev_pm: multi power domain for device
*/
static int clk_imx_acm_detach_pm_domains(struct device *dev,
struct clk_imx_acm_pm_domains *dev_pm)
static void clk_imx_acm_detach_pm_domains(struct device *dev,
struct clk_imx_acm_pm_domains *dev_pm)
{
int i;
if (dev_pm->num_domains <= 1)
return 0;
return;
for (i = 0; i < dev_pm->num_domains; i++) {
device_link_del(dev_pm->pd_dev_link[i]);
dev_pm_domain_detach(dev_pm->pd_dev[i], false);
}
return 0;
}
static int imx8_acm_clk_probe(struct platform_device *pdev)
@ -371,22 +371,25 @@ static int imx8_acm_clk_probe(struct platform_device *pdev)
sels[i].shift, sels[i].width,
0, NULL, NULL);
if (IS_ERR(hws[sels[i].clkid])) {
pm_runtime_disable(&pdev->dev);
ret = PTR_ERR(hws[sels[i].clkid]);
imx_check_clk_hws(hws, IMX_ADMA_ACM_CLK_END);
goto err_clk_register;
}
}
imx_check_clk_hws(hws, IMX_ADMA_ACM_CLK_END);
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_hw_data);
if (ret < 0) {
dev_err(dev, "failed to register hws for ACM\n");
pm_runtime_disable(&pdev->dev);
goto err_clk_register;
}
err_clk_register:
pm_runtime_put_sync(&pdev->dev);
return 0;
err_clk_register:
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
clk_imx_acm_detach_pm_domains(&pdev->dev, &priv->dev_pm);
return ret;
}

View file

@ -47,11 +47,10 @@ static u32 imx8dxl_clk_scu_rsrc_table[] = {
IMX_SC_R_SDHC_2,
IMX_SC_R_ENET_0,
IMX_SC_R_ENET_1,
IMX_SC_R_MLB_0,
IMX_SC_R_USB_1,
IMX_SC_R_NAND,
IMX_SC_R_M4_0_I2C,
IMX_SC_R_M4_0_UART,
IMX_SC_R_M4_0_I2C,
IMX_SC_R_ELCDIF_PLL,
IMX_SC_R_AUDIO_PLL_0,
IMX_SC_R_AUDIO_PLL_1,

View file

@ -288,8 +288,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
void __iomem *base;
int err;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
IMX8MQ_CLK_END), GFP_KERNEL);
clk_hw_data = devm_kzalloc(dev, struct_size(clk_hw_data, hws, IMX8MQ_CLK_END), GFP_KERNEL);
if (WARN_ON(!clk_hw_data))
return -ENOMEM;
@ -306,10 +305,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
hws[IMX8MQ_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop");
base = of_iomap(np, 0);
base = devm_of_iomap(dev, np, 0, NULL);
of_node_put(np);
if (WARN_ON(!base))
return -ENOMEM;
if (WARN_ON(IS_ERR(base))) {
err = PTR_ERR(base);
goto unregister_hws;
}
hws[IMX8MQ_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x28, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MQ_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x18, 16, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
@ -395,8 +396,10 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base)))
return PTR_ERR(base);
if (WARN_ON(IS_ERR(base))) {
err = PTR_ERR(base);
goto unregister_hws;
}
/* CORE */
hws[IMX8MQ_CLK_A53_DIV] = imx8m_clk_hw_composite_core("arm_a53_div", imx8mq_a53_sels, base + 0x8000);

View file

@ -43,6 +43,8 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = {
IMX_SC_R_FTM_0,
IMX_SC_R_FTM_1,
IMX_SC_R_CAN_0,
IMX_SC_R_CAN_1,
IMX_SC_R_CAN_2,
IMX_SC_R_GPU_0_PID0,
IMX_SC_R_GPU_1_PID0,
IMX_SC_R_PWM_0,
@ -65,7 +67,6 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = {
IMX_SC_R_SDHC_2,
IMX_SC_R_ENET_0,
IMX_SC_R_ENET_1,
IMX_SC_R_MLB_0,
IMX_SC_R_USB_2,
IMX_SC_R_NAND,
IMX_SC_R_LVDS_0,
@ -79,8 +80,6 @@ static const u32 imx8qm_clk_scu_rsrc_table[] = {
IMX_SC_R_M4_0_I2C,
IMX_SC_R_M4_1_I2C,
IMX_SC_R_AUDIO_PLL_0,
IMX_SC_R_VPU_UART,
IMX_SC_R_VPUCORE,
IMX_SC_R_MIPI_0,
IMX_SC_R_MIPI_0_PWM_0,
IMX_SC_R_MIPI_0_I2C_0,

View file

@ -42,7 +42,6 @@
#define CONN_ENET_0_LPCG 0x30000
#define CONN_ENET_1_LPCG 0x40000
#define CONN_DTCP_LPCG 0x50000
#define CONN_MLB_LPCG 0x60000
#define CONN_USB_2_LPCG 0x70000
#define CONN_USB_3_LPCG 0x80000
#define CONN_NAND_LPCG 0x90000

View file

@ -54,15 +54,17 @@ static const u32 imx8qxp_clk_scu_rsrc_table[] = {
IMX_SC_R_SDHC_2,
IMX_SC_R_ENET_0,
IMX_SC_R_ENET_1,
IMX_SC_R_MLB_0,
IMX_SC_R_USB_2,
IMX_SC_R_NAND,
IMX_SC_R_LVDS_0,
IMX_SC_R_LVDS_1,
IMX_SC_R_M4_0_UART,
IMX_SC_R_M4_0_I2C,
IMX_SC_R_ELCDIF_PLL,
IMX_SC_R_AUDIO_PLL_0,
IMX_SC_R_PI_0,
IMX_SC_R_PI_0_PWM_0,
IMX_SC_R_PI_0_I2C_0,
IMX_SC_R_PI_0_PLL,
IMX_SC_R_MIPI_0,
IMX_SC_R_MIPI_0_PWM_0,

View file

@ -90,6 +90,11 @@ static const char * const pi_pll0_sels[] = {
"clk_dummy",
};
static inline bool clk_on_imx8dxl(struct device_node *node)
{
return of_device_is_compatible(node, "fsl,imx8dxl-clk");
}
static int imx8qxp_clk_probe(struct platform_device *pdev)
{
struct device_node *ccm_node = pdev->dev.of_node;
@ -147,10 +152,10 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
imx_clk_scu("adc0_clk", IMX_SC_R_ADC_0, IMX_SC_PM_CLK_PER);
imx_clk_scu("adc1_clk", IMX_SC_R_ADC_1, IMX_SC_PM_CLK_PER);
imx_clk_scu("pwm_clk", IMX_SC_R_LCD_0_PWM_0, IMX_SC_PM_CLK_PER);
imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL);
imx_clk_scu2("lcd_clk", lcd_sels, ARRAY_SIZE(lcd_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_PER);
imx_clk_scu2("lcd_pxl_clk", lcd_pxl_sels, ARRAY_SIZE(lcd_pxl_sels), IMX_SC_R_LCD_0, IMX_SC_PM_CLK_MISC0);
imx_clk_scu("lcd_pxl_bypass_div_clk", IMX_SC_R_LCD_0, IMX_SC_PM_CLK_BYPASS);
imx_clk_scu("elcdif_pll", IMX_SC_R_ELCDIF_PLL, IMX_SC_PM_CLK_PLL);
/* Audio SS */
imx_clk_scu("audio_pll0_clk", IMX_SC_R_AUDIO_PLL_0, IMX_SC_PM_CLK_PLL);
@ -169,13 +174,15 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
imx_clk_mux_gpr_scu("enet0_rgmii_txc_sel", enet0_rgmii_txc_sels, ARRAY_SIZE(enet0_rgmii_txc_sels), IMX_SC_R_ENET_0, IMX_SC_C_TXCLK);
imx_clk_scu("enet0_bypass_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_BYPASS);
imx_clk_gate_gpr_scu("enet0_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_0, IMX_SC_C_DISABLE_50, true);
imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
if (!clk_on_imx8dxl(ccm_node)) {
imx_clk_scu("enet0_rgmii_rx_clk", IMX_SC_R_ENET_0, IMX_SC_PM_CLK_MISC0);
imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
}
imx_clk_scu("enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_PER);
imx_clk_divider_gpr_scu("enet1_ref_div", "enet1_root_clk", IMX_SC_R_ENET_1, IMX_SC_C_CLKDIV);
imx_clk_mux_gpr_scu("enet1_rgmii_txc_sel", enet1_rgmii_txc_sels, ARRAY_SIZE(enet1_rgmii_txc_sels), IMX_SC_R_ENET_1, IMX_SC_C_TXCLK);
imx_clk_scu("enet1_bypass_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_BYPASS);
imx_clk_gate_gpr_scu("enet1_ref_50_clk", "clk_dummy", IMX_SC_R_ENET_1, IMX_SC_C_DISABLE_50, true);
imx_clk_scu("enet1_rgmii_rx_clk", IMX_SC_R_ENET_1, IMX_SC_PM_CLK_MISC0);
imx_clk_scu("gpmi_io_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_MST_BUS);
imx_clk_scu("gpmi_bch_clk", IMX_SC_R_NAND, IMX_SC_PM_CLK_PER);
imx_clk_scu("usb3_aclk_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_PER);

View file

@ -10,10 +10,12 @@
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/firmware/imx/svc/rm.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <xen/xen.h>
#include "clk-scu.h"
@ -670,6 +672,18 @@ static int imx_clk_scu_attach_pd(struct device *dev, u32 rsrc_id)
return of_genpd_add_device(&genpdspec, dev);
}
static bool imx_clk_is_resource_owned(u32 rsrc)
{
/*
* A-core resources are special. SCFW reports they are not "owned" by
* current partition but linux can still adjust them for cpufreq.
*/
if (rsrc == IMX_SC_R_A53 || rsrc == IMX_SC_R_A72 || rsrc == IMX_SC_R_A35)
return true;
return imx_sc_rm_is_resource_owned(ccm_ipc_handle, rsrc);
}
struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
const char * const *parents,
int num_parents, u32 rsrc_id, u8 clk_type)
@ -687,6 +701,9 @@ struct clk_hw *imx_clk_scu_alloc_dev(const char *name,
if (!imx_scu_clk_is_valid(rsrc_id))
return ERR_PTR(-EINVAL);
if (!imx_clk_is_resource_owned(rsrc_id))
return NULL;
pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
if (!pdev) {
pr_err("%s: failed to allocate scu clk dev rsrc %d type %d\n",
@ -869,6 +886,9 @@ struct clk_hw *__imx_clk_gpr_scu(const char *name, const char * const *parent_na
return ERR_PTR(-EINVAL);
}
if (!imx_clk_is_resource_owned(rsrc_id))
return NULL;
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
if (!clk) {
kfree(clk_node);

View file

@ -667,6 +667,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);
@ -747,6 +749,8 @@ static void __init mtk_infrasys_init_early(struct device_node *node)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
if (!infra_clk_data)
return;
for (i = 0; i < CLK_INFRA_NR; i++)
infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
@ -774,6 +778,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
if (!infra_clk_data)
return -ENOMEM;
} else {
for (i = 0; i < CLK_INFRA_NR; i++) {
if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER))
@ -890,6 +896,8 @@ static int mtk_pericfg_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, peri_clks,
ARRAY_SIZE(peri_clks), clk_data);

View file

@ -737,6 +737,8 @@ static int clk_mt6765_apmixed_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
@ -769,6 +771,8 @@ static int clk_mt6765_top_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks),
clk_data);
@ -807,6 +811,8 @@ static int clk_mt6765_ifr_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, ifr_clks,
ARRAY_SIZE(ifr_clks), clk_data);

View file

@ -1217,6 +1217,8 @@ static int clk_mt6779_apmixed_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
@ -1237,6 +1239,8 @@ static int clk_mt6779_top_probe(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);

View file

@ -390,6 +390,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
clk_data);
@ -545,6 +547,8 @@ static void mtk_infrasys_init_early(struct device_node *node)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
if (!infra_clk_data)
return;
for (i = 0; i < CLK_INFRA_NR; i++)
infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
@ -570,6 +574,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
if (!infra_clk_data) {
infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
if (!infra_clk_data)
return -ENOMEM;
} else {
for (i = 0; i < CLK_INFRA_NR; i++) {
if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER))

View file

@ -77,6 +77,8 @@ static int clk_mt7629_ethsys_init(struct platform_device *pdev)
int r;
clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, eth_clks,
CLK_ETH_NR_CLK, clk_data);
@ -100,6 +102,8 @@ static int clk_mt7629_sgmiisys_init(struct platform_device *pdev)
int r;
clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, sgmii_clks[id++],
CLK_SGMII_NR_CLK, clk_data);

View file

@ -555,6 +555,8 @@ static int mtk_topckgen_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
clk_data);
@ -579,6 +581,8 @@ static int mtk_infrasys_init(struct platform_device *pdev)
struct clk_hw_onecell_data *clk_data;
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, infra_clks,
ARRAY_SIZE(infra_clks), clk_data);
@ -602,6 +606,8 @@ static int mtk_pericfg_init(struct platform_device *pdev)
return PTR_ERR(base);
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
if (!clk_data)
return -ENOMEM;
mtk_clk_register_gates(&pdev->dev, node, peri_clks,
ARRAY_SIZE(peri_clks), clk_data);

View file

@ -321,10 +321,8 @@ struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
ret = clk_hw_register(NULL, &pll->hw);
if (ret) {
kfree(pll);
if (ret)
return ERR_PTR(ret);
}
return &pll->hw;
}
@ -340,6 +338,8 @@ struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
return ERR_PTR(-ENOMEM);
hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops);
if (IS_ERR(hw))
kfree(pll);
return hw;
}

View file

@ -144,4 +144,29 @@ 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.
config COMMON_CLK_S4_PLL
tristate "S4 SoC PLL clock controllers support"
depends on ARM64
default y
select COMMON_CLK_MESON_CLKC_UTILS
select COMMON_CLK_MESON_MPLL
select COMMON_CLK_MESON_PLL
select COMMON_CLK_MESON_REGMAP
help
Support for the PLL clock controller on Amlogic S805X2 and S905Y4 devices,
AKA S4. Say Y if you want the board to work, because PLLs are the parent of
most peripherals.
config COMMON_CLK_S4_PERIPHERALS
tristate "S4 SoC peripherals clock controllers support"
depends on ARM64
default y
select COMMON_CLK_MESON_CLKC_UTILS
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_DUALDIV
select COMMON_CLK_MESON_VID_PLL_DIV
help
Support for the peripherals clock controller on Amlogic S805X2 and S905Y4
devices, AKA S4. Say Y if you want S4 peripherals clock controller to work.
endmenu

View file

@ -22,3 +22,5 @@ obj-$(CONFIG_COMMON_CLK_A1_PERIPHERALS) += a1-peripherals.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
obj-$(CONFIG_COMMON_CLK_S4_PLL) += s4-pll.o
obj-$(CONFIG_COMMON_CLK_S4_PERIPHERALS) += s4-peripherals.o

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,56 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
* Author: Yu Tu <yu.tu@amlogic.com>
*/
#ifndef __MESON_S4_PERIPHERALS_H__
#define __MESON_S4_PERIPHERALS_H__
#define CLKCTRL_RTC_BY_OSCIN_CTRL0 0x008
#define CLKCTRL_RTC_BY_OSCIN_CTRL1 0x00c
#define CLKCTRL_RTC_CTRL 0x010
#define CLKCTRL_SYS_CLK_CTRL0 0x040
#define CLKCTRL_SYS_CLK_EN0_REG0 0x044
#define CLKCTRL_SYS_CLK_EN0_REG1 0x048
#define CLKCTRL_SYS_CLK_EN0_REG2 0x04c
#define CLKCTRL_SYS_CLK_EN0_REG3 0x050
#define CLKCTRL_CECA_CTRL0 0x088
#define CLKCTRL_CECA_CTRL1 0x08c
#define CLKCTRL_CECB_CTRL0 0x090
#define CLKCTRL_CECB_CTRL1 0x094
#define CLKCTRL_SC_CLK_CTRL 0x098
#define CLKCTRL_CLK12_24_CTRL 0x0a8
#define CLKCTRL_VID_CLK_CTRL 0x0c0
#define CLKCTRL_VID_CLK_CTRL2 0x0c4
#define CLKCTRL_VID_CLK_DIV 0x0c8
#define CLKCTRL_VIID_CLK_DIV 0x0cc
#define CLKCTRL_VIID_CLK_CTRL 0x0d0
#define CLKCTRL_HDMI_CLK_CTRL 0x0e0
#define CLKCTRL_VID_PLL_CLK_DIV 0x0e4
#define CLKCTRL_VPU_CLK_CTRL 0x0e8
#define CLKCTRL_VPU_CLKB_CTRL 0x0ec
#define CLKCTRL_VPU_CLKC_CTRL 0x0f0
#define CLKCTRL_VID_LOCK_CLK_CTRL 0x0f4
#define CLKCTRL_VDIN_MEAS_CLK_CTRL 0x0f8
#define CLKCTRL_VAPBCLK_CTRL 0x0fc
#define CLKCTRL_HDCP22_CTRL 0x100
#define CLKCTRL_VDEC_CLK_CTRL 0x140
#define CLKCTRL_VDEC2_CLK_CTRL 0x144
#define CLKCTRL_VDEC3_CLK_CTRL 0x148
#define CLKCTRL_VDEC4_CLK_CTRL 0x14c
#define CLKCTRL_TS_CLK_CTRL 0x158
#define CLKCTRL_MALI_CLK_CTRL 0x15c
#define CLKCTRL_NAND_CLK_CTRL 0x168
#define CLKCTRL_SD_EMMC_CLK_CTRL 0x16c
#define CLKCTRL_SPICC_CLK_CTRL 0x174
#define CLKCTRL_GEN_CLK_CTRL 0x178
#define CLKCTRL_SAR_CLK_CTRL 0x17c
#define CLKCTRL_PWM_CLK_AB_CTRL 0x180
#define CLKCTRL_PWM_CLK_CD_CTRL 0x184
#define CLKCTRL_PWM_CLK_EF_CTRL 0x188
#define CLKCTRL_PWM_CLK_GH_CTRL 0x18c
#define CLKCTRL_PWM_CLK_IJ_CTRL 0x190
#define CLKCTRL_DEMOD_CLK_CTRL 0x200
#endif /* __MESON_S4_PERIPHERALS_H__ */

867
drivers/clk/meson/s4-pll.c Normal file
View file

@ -0,0 +1,867 @@
// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
/*
* Amlogic S4 PLL Clock Controller Driver
*
* Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
* Author: Yu Tu <yu.tu@amlogic.com>
*/
#include <linux/clk-provider.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mpll.h"
#include "clk-pll.h"
#include "clk-regmap.h"
#include "s4-pll.h"
#include "meson-clkc-utils.h"
#include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
static DEFINE_SPINLOCK(meson_clk_lock);
/*
* These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode.
* The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable
* in the kernel phase. Write of fixed PLL-related register will cause the system to crash.
* Meanwhile, these clock won't ever change at runtime.
* For the above reasons, we can only use ro_ops for fixed PLL related clocks.
*/
static struct clk_regmap s4_fixed_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = ANACTRL_FIXPLL_CTRL0,
.shift = 28,
.width = 1,
},
.m = {
.reg_off = ANACTRL_FIXPLL_CTRL0,
.shift = 0,
.width = 8,
},
.n = {
.reg_off = ANACTRL_FIXPLL_CTRL0,
.shift = 10,
.width = 5,
},
.l = {
.reg_off = ANACTRL_FIXPLL_CTRL0,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = ANACTRL_FIXPLL_CTRL0,
.shift = 29,
.width = 1,
},
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", }
},
.num_parents = 1,
},
};
static struct clk_regmap s4_fixed_pll = {
.data = &(struct clk_regmap_div_data){
.offset = ANACTRL_FIXPLL_CTRL0,
.shift = 16,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fixed_pll_dco.hw
},
.num_parents = 1,
/*
* This clock won't ever change at runtime so
* CLK_SET_RATE_PARENT is not required
*/
},
};
static struct clk_fixed_factor s4_fclk_div2_div = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
.num_parents = 1,
},
};
static struct clk_regmap s4_fclk_div2 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_FIXPLL_CTRL1,
.bit_idx = 24,
},
.hw.init = &(struct clk_init_data){
.name = "fclk_div2",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fclk_div2_div.hw
},
.num_parents = 1,
},
};
static struct clk_fixed_factor s4_fclk_div3_div = {
.mult = 1,
.div = 3,
.hw.init = &(struct clk_init_data){
.name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
.num_parents = 1,
},
};
static struct clk_regmap s4_fclk_div3 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_FIXPLL_CTRL1,
.bit_idx = 20,
},
.hw.init = &(struct clk_init_data){
.name = "fclk_div3",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fclk_div3_div.hw
},
.num_parents = 1,
},
};
static struct clk_fixed_factor s4_fclk_div4_div = {
.mult = 1,
.div = 4,
.hw.init = &(struct clk_init_data){
.name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
.num_parents = 1,
},
};
static struct clk_regmap s4_fclk_div4 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_FIXPLL_CTRL1,
.bit_idx = 21,
},
.hw.init = &(struct clk_init_data){
.name = "fclk_div4",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fclk_div4_div.hw
},
.num_parents = 1,
},
};
static struct clk_fixed_factor s4_fclk_div5_div = {
.mult = 1,
.div = 5,
.hw.init = &(struct clk_init_data){
.name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
.num_parents = 1,
},
};
static struct clk_regmap s4_fclk_div5 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_FIXPLL_CTRL1,
.bit_idx = 22,
},
.hw.init = &(struct clk_init_data){
.name = "fclk_div5",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fclk_div5_div.hw
},
.num_parents = 1,
},
};
static struct clk_fixed_factor s4_fclk_div7_div = {
.mult = 1,
.div = 7,
.hw.init = &(struct clk_init_data){
.name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
.num_parents = 1,
},
};
static struct clk_regmap s4_fclk_div7 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_FIXPLL_CTRL1,
.bit_idx = 23,
},
.hw.init = &(struct clk_init_data){
.name = "fclk_div7",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fclk_div7_div.hw
},
.num_parents = 1,
},
};
static struct clk_fixed_factor s4_fclk_div2p5_div = {
.mult = 2,
.div = 5,
.hw.init = &(struct clk_init_data){
.name = "fclk_div2p5_div",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fixed_pll.hw
},
.num_parents = 1,
},
};
static struct clk_regmap s4_fclk_div2p5 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_FIXPLL_CTRL1,
.bit_idx = 25,
},
.hw.init = &(struct clk_init_data){
.name = "fclk_div2p5",
.ops = &clk_regmap_gate_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fclk_div2p5_div.hw
},
.num_parents = 1,
},
};
static const struct pll_mult_range s4_gp0_pll_mult_range = {
.min = 125,
.max = 250,
};
/*
* Internal gp0 pll emulation configuration parameters
*/
static const struct reg_sequence s4_gp0_init_regs[] = {
{ .reg = ANACTRL_GP0PLL_CTRL1, .def = 0x00000000 },
{ .reg = ANACTRL_GP0PLL_CTRL2, .def = 0x00000000 },
{ .reg = ANACTRL_GP0PLL_CTRL3, .def = 0x48681c00 },
{ .reg = ANACTRL_GP0PLL_CTRL4, .def = 0x88770290 },
{ .reg = ANACTRL_GP0PLL_CTRL5, .def = 0x39272000 },
{ .reg = ANACTRL_GP0PLL_CTRL6, .def = 0x56540000 }
};
static struct clk_regmap s4_gp0_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = ANACTRL_GP0PLL_CTRL0,
.shift = 28,
.width = 1,
},
.m = {
.reg_off = ANACTRL_GP0PLL_CTRL0,
.shift = 0,
.width = 8,
},
.n = {
.reg_off = ANACTRL_GP0PLL_CTRL0,
.shift = 10,
.width = 5,
},
.l = {
.reg_off = ANACTRL_GP0PLL_CTRL0,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = ANACTRL_GP0PLL_CTRL0,
.shift = 29,
.width = 1,
},
.range = &s4_gp0_pll_mult_range,
.init_regs = s4_gp0_init_regs,
.init_count = ARRAY_SIZE(s4_gp0_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", }
},
.num_parents = 1,
},
};
static struct clk_regmap s4_gp0_pll = {
.data = &(struct clk_regmap_div_data){
.offset = ANACTRL_GP0PLL_CTRL0,
.shift = 16,
.width = 3,
.flags = (CLK_DIVIDER_POWER_OF_TWO |
CLK_DIVIDER_ROUND_CLOSEST),
},
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_gp0_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
/*
* Internal hifi pll emulation configuration parameters
*/
static const struct reg_sequence s4_hifi_init_regs[] = {
{ .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x00010e56 },
{ .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00000000 },
{ .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x6a285c00 },
{ .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },
{ .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x39272000 },
{ .reg = ANACTRL_HIFIPLL_CTRL6, .def = 0x56540000 }
};
static struct clk_regmap s4_hifi_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = ANACTRL_HIFIPLL_CTRL0,
.shift = 28,
.width = 1,
},
.m = {
.reg_off = ANACTRL_HIFIPLL_CTRL0,
.shift = 0,
.width = 8,
},
.n = {
.reg_off = ANACTRL_HIFIPLL_CTRL0,
.shift = 10,
.width = 5,
},
.l = {
.reg_off = ANACTRL_HIFIPLL_CTRL0,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = ANACTRL_HIFIPLL_CTRL0,
.shift = 29,
.width = 1,
},
.range = &s4_gp0_pll_mult_range,
.init_regs = s4_hifi_init_regs,
.init_count = ARRAY_SIZE(s4_hifi_init_regs),
.flags = CLK_MESON_PLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", }
},
.num_parents = 1,
},
};
static struct clk_regmap s4_hifi_pll = {
.data = &(struct clk_regmap_div_data){
.offset = ANACTRL_HIFIPLL_CTRL0,
.shift = 16,
.width = 2,
.flags = (CLK_DIVIDER_POWER_OF_TWO |
CLK_DIVIDER_ROUND_CLOSEST),
},
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_hifi_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap s4_hdmi_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = ANACTRL_HDMIPLL_CTRL0,
.shift = 28,
.width = 1,
},
.m = {
.reg_off = ANACTRL_HDMIPLL_CTRL0,
.shift = 0,
.width = 8,
},
.n = {
.reg_off = ANACTRL_HDMIPLL_CTRL0,
.shift = 10,
.width = 5,
},
.l = {
.reg_off = ANACTRL_HDMIPLL_CTRL0,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = ANACTRL_HDMIPLL_CTRL0,
.shift = 29,
.width = 1,
},
.range = &s4_gp0_pll_mult_range,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", }
},
.num_parents = 1,
},
};
static struct clk_regmap s4_hdmi_pll_od = {
.data = &(struct clk_regmap_div_data){
.offset = ANACTRL_HDMIPLL_CTRL0,
.shift = 16,
.width = 4,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll_od",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_hdmi_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_regmap s4_hdmi_pll = {
.data = &(struct clk_regmap_div_data){
.offset = ANACTRL_HDMIPLL_CTRL0,
.shift = 20,
.width = 2,
.flags = CLK_DIVIDER_POWER_OF_TWO,
},
.hw.init = &(struct clk_init_data){
.name = "hdmi_pll",
.ops = &clk_regmap_divider_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_hdmi_pll_od.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static struct clk_fixed_factor s4_mpll_50m_div = {
.mult = 1,
.div = 80,
.hw.init = &(struct clk_init_data){
.name = "mpll_50m_div",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fixed_pll_dco.hw
},
.num_parents = 1,
},
};
static struct clk_regmap s4_mpll_50m = {
.data = &(struct clk_regmap_mux_data){
.offset = ANACTRL_FIXPLL_CTRL3,
.mask = 0x1,
.shift = 5,
},
.hw.init = &(struct clk_init_data){
.name = "mpll_50m",
.ops = &clk_regmap_mux_ro_ops,
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", },
{ .hw = &s4_mpll_50m_div.hw },
},
.num_parents = 2,
},
};
static struct clk_fixed_factor s4_mpll_prediv = {
.mult = 1,
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "mpll_prediv",
.ops = &clk_fixed_factor_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_fixed_pll_dco.hw
},
.num_parents = 1,
},
};
static const struct reg_sequence s4_mpll0_init_regs[] = {
{ .reg = ANACTRL_MPLL_CTRL2, .def = 0x40000033 }
};
static struct clk_regmap s4_mpll0_div = {
.data = &(struct meson_clk_mpll_data){
.sdm = {
.reg_off = ANACTRL_MPLL_CTRL1,
.shift = 0,
.width = 14,
},
.sdm_en = {
.reg_off = ANACTRL_MPLL_CTRL1,
.shift = 30,
.width = 1,
},
.n2 = {
.reg_off = ANACTRL_MPLL_CTRL1,
.shift = 20,
.width = 9,
},
.ssen = {
.reg_off = ANACTRL_MPLL_CTRL1,
.shift = 29,
.width = 1,
},
.lock = &meson_clk_lock,
.init_regs = s4_mpll0_init_regs,
.init_count = ARRAY_SIZE(s4_mpll0_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_mpll_prediv.hw
},
.num_parents = 1,
},
};
static struct clk_regmap s4_mpll0 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_MPLL_CTRL1,
.bit_idx = 31,
},
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_mpll0_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const struct reg_sequence s4_mpll1_init_regs[] = {
{ .reg = ANACTRL_MPLL_CTRL4, .def = 0x40000033 }
};
static struct clk_regmap s4_mpll1_div = {
.data = &(struct meson_clk_mpll_data){
.sdm = {
.reg_off = ANACTRL_MPLL_CTRL3,
.shift = 0,
.width = 14,
},
.sdm_en = {
.reg_off = ANACTRL_MPLL_CTRL3,
.shift = 30,
.width = 1,
},
.n2 = {
.reg_off = ANACTRL_MPLL_CTRL3,
.shift = 20,
.width = 9,
},
.ssen = {
.reg_off = ANACTRL_MPLL_CTRL3,
.shift = 29,
.width = 1,
},
.lock = &meson_clk_lock,
.init_regs = s4_mpll1_init_regs,
.init_count = ARRAY_SIZE(s4_mpll1_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_mpll_prediv.hw
},
.num_parents = 1,
},
};
static struct clk_regmap s4_mpll1 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_MPLL_CTRL3,
.bit_idx = 31,
},
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_mpll1_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const struct reg_sequence s4_mpll2_init_regs[] = {
{ .reg = ANACTRL_MPLL_CTRL6, .def = 0x40000033 }
};
static struct clk_regmap s4_mpll2_div = {
.data = &(struct meson_clk_mpll_data){
.sdm = {
.reg_off = ANACTRL_MPLL_CTRL5,
.shift = 0,
.width = 14,
},
.sdm_en = {
.reg_off = ANACTRL_MPLL_CTRL5,
.shift = 30,
.width = 1,
},
.n2 = {
.reg_off = ANACTRL_MPLL_CTRL5,
.shift = 20,
.width = 9,
},
.ssen = {
.reg_off = ANACTRL_MPLL_CTRL5,
.shift = 29,
.width = 1,
},
.lock = &meson_clk_lock,
.init_regs = s4_mpll2_init_regs,
.init_count = ARRAY_SIZE(s4_mpll2_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_mpll_prediv.hw
},
.num_parents = 1,
},
};
static struct clk_regmap s4_mpll2 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_MPLL_CTRL5,
.bit_idx = 31,
},
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_mpll2_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static const struct reg_sequence s4_mpll3_init_regs[] = {
{ .reg = ANACTRL_MPLL_CTRL8, .def = 0x40000033 }
};
static struct clk_regmap s4_mpll3_div = {
.data = &(struct meson_clk_mpll_data){
.sdm = {
.reg_off = ANACTRL_MPLL_CTRL7,
.shift = 0,
.width = 14,
},
.sdm_en = {
.reg_off = ANACTRL_MPLL_CTRL7,
.shift = 30,
.width = 1,
},
.n2 = {
.reg_off = ANACTRL_MPLL_CTRL7,
.shift = 20,
.width = 9,
},
.ssen = {
.reg_off = ANACTRL_MPLL_CTRL7,
.shift = 29,
.width = 1,
},
.lock = &meson_clk_lock,
.init_regs = s4_mpll3_init_regs,
.init_count = ARRAY_SIZE(s4_mpll3_init_regs),
},
.hw.init = &(struct clk_init_data){
.name = "mpll3_div",
.ops = &meson_clk_mpll_ops,
.parent_hws = (const struct clk_hw *[]) {
&s4_mpll_prediv.hw
},
.num_parents = 1,
},
};
static struct clk_regmap s4_mpll3 = {
.data = &(struct clk_regmap_gate_data){
.offset = ANACTRL_MPLL_CTRL7,
.bit_idx = 31,
},
.hw.init = &(struct clk_init_data){
.name = "mpll3",
.ops = &clk_regmap_gate_ops,
.parent_hws = (const struct clk_hw *[]) { &s4_mpll3_div.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
/* Array of all clocks provided by this provider */
static struct clk_hw *s4_pll_hw_clks[] = {
[CLKID_FIXED_PLL_DCO] = &s4_fixed_pll_dco.hw,
[CLKID_FIXED_PLL] = &s4_fixed_pll.hw,
[CLKID_FCLK_DIV2_DIV] = &s4_fclk_div2_div.hw,
[CLKID_FCLK_DIV2] = &s4_fclk_div2.hw,
[CLKID_FCLK_DIV3_DIV] = &s4_fclk_div3_div.hw,
[CLKID_FCLK_DIV3] = &s4_fclk_div3.hw,
[CLKID_FCLK_DIV4_DIV] = &s4_fclk_div4_div.hw,
[CLKID_FCLK_DIV4] = &s4_fclk_div4.hw,
[CLKID_FCLK_DIV5_DIV] = &s4_fclk_div5_div.hw,
[CLKID_FCLK_DIV5] = &s4_fclk_div5.hw,
[CLKID_FCLK_DIV7_DIV] = &s4_fclk_div7_div.hw,
[CLKID_FCLK_DIV7] = &s4_fclk_div7.hw,
[CLKID_FCLK_DIV2P5_DIV] = &s4_fclk_div2p5_div.hw,
[CLKID_FCLK_DIV2P5] = &s4_fclk_div2p5.hw,
[CLKID_GP0_PLL_DCO] = &s4_gp0_pll_dco.hw,
[CLKID_GP0_PLL] = &s4_gp0_pll.hw,
[CLKID_HIFI_PLL_DCO] = &s4_hifi_pll_dco.hw,
[CLKID_HIFI_PLL] = &s4_hifi_pll.hw,
[CLKID_HDMI_PLL_DCO] = &s4_hdmi_pll_dco.hw,
[CLKID_HDMI_PLL_OD] = &s4_hdmi_pll_od.hw,
[CLKID_HDMI_PLL] = &s4_hdmi_pll.hw,
[CLKID_MPLL_50M_DIV] = &s4_mpll_50m_div.hw,
[CLKID_MPLL_50M] = &s4_mpll_50m.hw,
[CLKID_MPLL_PREDIV] = &s4_mpll_prediv.hw,
[CLKID_MPLL0_DIV] = &s4_mpll0_div.hw,
[CLKID_MPLL0] = &s4_mpll0.hw,
[CLKID_MPLL1_DIV] = &s4_mpll1_div.hw,
[CLKID_MPLL1] = &s4_mpll1.hw,
[CLKID_MPLL2_DIV] = &s4_mpll2_div.hw,
[CLKID_MPLL2] = &s4_mpll2.hw,
[CLKID_MPLL3_DIV] = &s4_mpll3_div.hw,
[CLKID_MPLL3] = &s4_mpll3.hw,
};
static struct clk_regmap *const s4_pll_clk_regmaps[] = {
&s4_fixed_pll_dco,
&s4_fixed_pll,
&s4_fclk_div2,
&s4_fclk_div3,
&s4_fclk_div4,
&s4_fclk_div5,
&s4_fclk_div7,
&s4_fclk_div2p5,
&s4_gp0_pll_dco,
&s4_gp0_pll,
&s4_hifi_pll_dco,
&s4_hifi_pll,
&s4_hdmi_pll_dco,
&s4_hdmi_pll_od,
&s4_hdmi_pll,
&s4_mpll_50m,
&s4_mpll0_div,
&s4_mpll0,
&s4_mpll1_div,
&s4_mpll1,
&s4_mpll2_div,
&s4_mpll2,
&s4_mpll3_div,
&s4_mpll3,
};
static const struct reg_sequence s4_init_regs[] = {
{ .reg = ANACTRL_MPLL_CTRL0, .def = 0x00000543 },
};
static struct regmap_config clkc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
static struct meson_clk_hw_data s4_pll_clks = {
.hws = s4_pll_hw_clks,
.num = ARRAY_SIZE(s4_pll_hw_clks),
};
static int meson_s4_pll_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct regmap *regmap;
void __iomem *base;
int ret, i;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return dev_err_probe(dev, PTR_ERR(base),
"can't ioremap resource\n");
regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);
if (IS_ERR(regmap))
return dev_err_probe(dev, PTR_ERR(regmap),
"can't init regmap mmio region\n");
ret = regmap_multi_reg_write(regmap, s4_init_regs, ARRAY_SIZE(s4_init_regs));
if (ret)
return dev_err_probe(dev, ret,
"Failed to init registers\n");
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < ARRAY_SIZE(s4_pll_clk_regmaps); i++)
s4_pll_clk_regmaps[i]->map = regmap;
/* Register clocks */
for (i = 0; i < s4_pll_clks.num; i++) {
/* array might be sparse */
if (!s4_pll_clks.hws[i])
continue;
ret = devm_clk_hw_register(dev, s4_pll_clks.hws[i]);
if (ret)
return dev_err_probe(dev, ret,
"clock[%d] registration failed\n", i);
}
return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,
&s4_pll_clks);
}
static const struct of_device_id clkc_match_table[] = {
{
.compatible = "amlogic,s4-pll-clkc",
},
{}
};
static struct platform_driver s4_driver = {
.probe = meson_s4_pll_probe,
.driver = {
.name = "s4-pll-clkc",
.of_match_table = clkc_match_table,
},
};
module_platform_driver(s4_driver);
MODULE_AUTHOR("Yu Tu <yu.tu@amlogic.com>");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,38 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
* Author: Yu Tu <yu.tu@amlogic.com>
*/
#ifndef __MESON_S4_PLL_H__
#define __MESON_S4_PLL_H__
#define ANACTRL_FIXPLL_CTRL0 0x040
#define ANACTRL_FIXPLL_CTRL1 0x044
#define ANACTRL_FIXPLL_CTRL3 0x04c
#define ANACTRL_GP0PLL_CTRL0 0x080
#define ANACTRL_GP0PLL_CTRL1 0x084
#define ANACTRL_GP0PLL_CTRL2 0x088
#define ANACTRL_GP0PLL_CTRL3 0x08c
#define ANACTRL_GP0PLL_CTRL4 0x090
#define ANACTRL_GP0PLL_CTRL5 0x094
#define ANACTRL_GP0PLL_CTRL6 0x098
#define ANACTRL_HIFIPLL_CTRL0 0x100
#define ANACTRL_HIFIPLL_CTRL1 0x104
#define ANACTRL_HIFIPLL_CTRL2 0x108
#define ANACTRL_HIFIPLL_CTRL3 0x10c
#define ANACTRL_HIFIPLL_CTRL4 0x110
#define ANACTRL_HIFIPLL_CTRL5 0x114
#define ANACTRL_HIFIPLL_CTRL6 0x118
#define ANACTRL_MPLL_CTRL0 0x180
#define ANACTRL_MPLL_CTRL1 0x184
#define ANACTRL_MPLL_CTRL2 0x188
#define ANACTRL_MPLL_CTRL3 0x18c
#define ANACTRL_MPLL_CTRL4 0x190
#define ANACTRL_MPLL_CTRL5 0x194
#define ANACTRL_MPLL_CTRL6 0x198
#define ANACTRL_MPLL_CTRL7 0x19c
#define ANACTRL_MPLL_CTRL8 0x1a0
#define ANACTRL_HDMIPLL_CTRL0 0x1c0
#endif /* __MESON_S4_PLL_H__ */

View file

@ -0,0 +1,236 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (c) 2022-2023 Amlogic, Inc. All rights reserved.
* Author: Yu Tu <yu.tu@amlogic.com>
*/
#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_S4_PERIPHERALS_CLKC_H
#define _DT_BINDINGS_CLOCK_AMLOGIC_S4_PERIPHERALS_CLKC_H
#define CLKID_RTC_32K_CLKIN 0
#define CLKID_RTC_32K_DIV 1
#define CLKID_RTC_32K_SEL 2
#define CLKID_RTC_32K_XATL 3
#define CLKID_RTC 4
#define CLKID_SYS_CLK_B_SEL 5
#define CLKID_SYS_CLK_B_DIV 6
#define CLKID_SYS_CLK_B 7
#define CLKID_SYS_CLK_A_SEL 8
#define CLKID_SYS_CLK_A_DIV 9
#define CLKID_SYS_CLK_A 10
#define CLKID_SYS 11
#define CLKID_CECA_32K_CLKIN 12
#define CLKID_CECA_32K_DIV 13
#define CLKID_CECA_32K_SEL_PRE 14
#define CLKID_CECA_32K_SEL 15
#define CLKID_CECA_32K_CLKOUT 16
#define CLKID_CECB_32K_CLKIN 17
#define CLKID_CECB_32K_DIV 18
#define CLKID_CECB_32K_SEL_PRE 19
#define CLKID_CECB_32K_SEL 20
#define CLKID_CECB_32K_CLKOUT 21
#define CLKID_SC_CLK_SEL 22
#define CLKID_SC_CLK_DIV 23
#define CLKID_SC 24
#define CLKID_12_24M 25
#define CLKID_12M_CLK_DIV 26
#define CLKID_12_24M_CLK_SEL 27
#define CLKID_VID_PLL_DIV 28
#define CLKID_VID_PLL_SEL 29
#define CLKID_VID_PLL 30
#define CLKID_VCLK_SEL 31
#define CLKID_VCLK2_SEL 32
#define CLKID_VCLK_INPUT 33
#define CLKID_VCLK2_INPUT 34
#define CLKID_VCLK_DIV 35
#define CLKID_VCLK2_DIV 36
#define CLKID_VCLK 37
#define CLKID_VCLK2 38
#define CLKID_VCLK_DIV1 39
#define CLKID_VCLK_DIV2_EN 40
#define CLKID_VCLK_DIV4_EN 41
#define CLKID_VCLK_DIV6_EN 42
#define CLKID_VCLK_DIV12_EN 43
#define CLKID_VCLK2_DIV1 44
#define CLKID_VCLK2_DIV2_EN 45
#define CLKID_VCLK2_DIV4_EN 46
#define CLKID_VCLK2_DIV6_EN 47
#define CLKID_VCLK2_DIV12_EN 48
#define CLKID_VCLK_DIV2 49
#define CLKID_VCLK_DIV4 50
#define CLKID_VCLK_DIV6 51
#define CLKID_VCLK_DIV12 52
#define CLKID_VCLK2_DIV2 53
#define CLKID_VCLK2_DIV4 54
#define CLKID_VCLK2_DIV6 55
#define CLKID_VCLK2_DIV12 56
#define CLKID_CTS_ENCI_SEL 57
#define CLKID_CTS_ENCP_SEL 58
#define CLKID_CTS_VDAC_SEL 59
#define CLKID_HDMI_TX_SEL 60
#define CLKID_CTS_ENCI 61
#define CLKID_CTS_ENCP 62
#define CLKID_CTS_VDAC 63
#define CLKID_HDMI_TX 64
#define CLKID_HDMI_SEL 65
#define CLKID_HDMI_DIV 66
#define CLKID_HDMI 67
#define CLKID_TS_CLK_DIV 68
#define CLKID_TS 69
#define CLKID_MALI_0_SEL 70
#define CLKID_MALI_0_DIV 71
#define CLKID_MALI_0 72
#define CLKID_MALI_1_SEL 73
#define CLKID_MALI_1_DIV 74
#define CLKID_MALI_1 75
#define CLKID_MALI_SEL 76
#define CLKID_VDEC_P0_SEL 77
#define CLKID_VDEC_P0_DIV 78
#define CLKID_VDEC_P0 79
#define CLKID_VDEC_P1_SEL 80
#define CLKID_VDEC_P1_DIV 81
#define CLKID_VDEC_P1 82
#define CLKID_VDEC_SEL 83
#define CLKID_HEVCF_P0_SEL 84
#define CLKID_HEVCF_P0_DIV 85
#define CLKID_HEVCF_P0 86
#define CLKID_HEVCF_P1_SEL 87
#define CLKID_HEVCF_P1_DIV 88
#define CLKID_HEVCF_P1 89
#define CLKID_HEVCF_SEL 90
#define CLKID_VPU_0_SEL 91
#define CLKID_VPU_0_DIV 92
#define CLKID_VPU_0 93
#define CLKID_VPU_1_SEL 94
#define CLKID_VPU_1_DIV 95
#define CLKID_VPU_1 96
#define CLKID_VPU 97
#define CLKID_VPU_CLKB_TMP_SEL 98
#define CLKID_VPU_CLKB_TMP_DIV 99
#define CLKID_VPU_CLKB_TMP 100
#define CLKID_VPU_CLKB_DIV 101
#define CLKID_VPU_CLKB 102
#define CLKID_VPU_CLKC_P0_SEL 103
#define CLKID_VPU_CLKC_P0_DIV 104
#define CLKID_VPU_CLKC_P0 105
#define CLKID_VPU_CLKC_P1_SEL 106
#define CLKID_VPU_CLKC_P1_DIV 107
#define CLKID_VPU_CLKC_P1 108
#define CLKID_VPU_CLKC_SEL 109
#define CLKID_VAPB_0_SEL 110
#define CLKID_VAPB_0_DIV 111
#define CLKID_VAPB_0 112
#define CLKID_VAPB_1_SEL 113
#define CLKID_VAPB_1_DIV 114
#define CLKID_VAPB_1 115
#define CLKID_VAPB 116
#define CLKID_GE2D 117
#define CLKID_VDIN_MEAS_SEL 118
#define CLKID_VDIN_MEAS_DIV 119
#define CLKID_VDIN_MEAS 120
#define CLKID_SD_EMMC_C_CLK_SEL 121
#define CLKID_SD_EMMC_C_CLK_DIV 122
#define CLKID_SD_EMMC_C 123
#define CLKID_SD_EMMC_A_CLK_SEL 124
#define CLKID_SD_EMMC_A_CLK_DIV 125
#define CLKID_SD_EMMC_A 126
#define CLKID_SD_EMMC_B_CLK_SEL 127
#define CLKID_SD_EMMC_B_CLK_DIV 128
#define CLKID_SD_EMMC_B 129
#define CLKID_SPICC0_SEL 130
#define CLKID_SPICC0_DIV 131
#define CLKID_SPICC0_EN 132
#define CLKID_PWM_A_SEL 133
#define CLKID_PWM_A_DIV 134
#define CLKID_PWM_A 135
#define CLKID_PWM_B_SEL 136
#define CLKID_PWM_B_DIV 137
#define CLKID_PWM_B 138
#define CLKID_PWM_C_SEL 139
#define CLKID_PWM_C_DIV 140
#define CLKID_PWM_C 141
#define CLKID_PWM_D_SEL 142
#define CLKID_PWM_D_DIV 143
#define CLKID_PWM_D 144
#define CLKID_PWM_E_SEL 145
#define CLKID_PWM_E_DIV 146
#define CLKID_PWM_E 147
#define CLKID_PWM_F_SEL 148
#define CLKID_PWM_F_DIV 149
#define CLKID_PWM_F 150
#define CLKID_PWM_G_SEL 151
#define CLKID_PWM_G_DIV 152
#define CLKID_PWM_G 153
#define CLKID_PWM_H_SEL 154
#define CLKID_PWM_H_DIV 155
#define CLKID_PWM_H 156
#define CLKID_PWM_I_SEL 157
#define CLKID_PWM_I_DIV 158
#define CLKID_PWM_I 159
#define CLKID_PWM_J_SEL 160
#define CLKID_PWM_J_DIV 161
#define CLKID_PWM_J 162
#define CLKID_SARADC_SEL 163
#define CLKID_SARADC_DIV 164
#define CLKID_SARADC 165
#define CLKID_GEN_SEL 166
#define CLKID_GEN_DIV 167
#define CLKID_GEN 168
#define CLKID_DDR 169
#define CLKID_DOS 170
#define CLKID_ETHPHY 171
#define CLKID_MALI 172
#define CLKID_AOCPU 173
#define CLKID_AUCPU 174
#define CLKID_CEC 175
#define CLKID_SDEMMC_A 176
#define CLKID_SDEMMC_B 177
#define CLKID_NAND 178
#define CLKID_SMARTCARD 179
#define CLKID_ACODEC 180
#define CLKID_SPIFC 181
#define CLKID_MSR 182
#define CLKID_IR_CTRL 183
#define CLKID_AUDIO 184
#define CLKID_ETH 185
#define CLKID_UART_A 186
#define CLKID_UART_B 187
#define CLKID_UART_C 188
#define CLKID_UART_D 189
#define CLKID_UART_E 190
#define CLKID_AIFIFO 191
#define CLKID_TS_DDR 192
#define CLKID_TS_PLL 193
#define CLKID_G2D 194
#define CLKID_SPICC0 195
#define CLKID_SPICC1 196
#define CLKID_USB 197
#define CLKID_I2C_M_A 198
#define CLKID_I2C_M_B 199
#define CLKID_I2C_M_C 200
#define CLKID_I2C_M_D 201
#define CLKID_I2C_M_E 202
#define CLKID_HDMITX_APB 203
#define CLKID_I2C_S_A 204
#define CLKID_USB1_TO_DDR 205
#define CLKID_HDCP22 206
#define CLKID_MMC_APB 207
#define CLKID_RSA 208
#define CLKID_CPU_DEBUG 209
#define CLKID_VPU_INTR 210
#define CLKID_DEMOD 211
#define CLKID_SAR_ADC 212
#define CLKID_GIC 213
#define CLKID_PWM_AB 214
#define CLKID_PWM_CD 215
#define CLKID_PWM_EF 216
#define CLKID_PWM_GH 217
#define CLKID_PWM_IJ 218
#define CLKID_HDCP22_ESMCLK_SEL 219
#define CLKID_HDCP22_ESMCLK_DIV 220
#define CLKID_HDCP22_ESMCLK 221
#define CLKID_HDCP22_SKPCLK_SEL 222
#define CLKID_HDCP22_SKPCLK_DIV 223
#define CLKID_HDCP22_SKPCLK 224
#endif /* _DT_BINDINGS_CLOCK_AMLOGIC_S4_PERIPHERALS_CLKC_H */

View file

@ -0,0 +1,43 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR MIT) */
/*
* Copyright (c) 2022-2023 Amlogic, Inc. All rights reserved.
* Author: Yu Tu <yu.tu@amlogic.com>
*/
#ifndef _DT_BINDINGS_CLOCK_AMLOGIC_S4_PLL_CLKC_H
#define _DT_BINDINGS_CLOCK_AMLOGIC_S4_PLL_CLKC_H
#define CLKID_FIXED_PLL_DCO 0
#define CLKID_FIXED_PLL 1
#define CLKID_FCLK_DIV2_DIV 2
#define CLKID_FCLK_DIV2 3
#define CLKID_FCLK_DIV3_DIV 4
#define CLKID_FCLK_DIV3 5
#define CLKID_FCLK_DIV4_DIV 6
#define CLKID_FCLK_DIV4 7
#define CLKID_FCLK_DIV5_DIV 8
#define CLKID_FCLK_DIV5 9
#define CLKID_FCLK_DIV7_DIV 10
#define CLKID_FCLK_DIV7 11
#define CLKID_FCLK_DIV2P5_DIV 12
#define CLKID_FCLK_DIV2P5 13
#define CLKID_GP0_PLL_DCO 14
#define CLKID_GP0_PLL 15
#define CLKID_HIFI_PLL_DCO 16
#define CLKID_HIFI_PLL 17
#define CLKID_HDMI_PLL_DCO 18
#define CLKID_HDMI_PLL_OD 19
#define CLKID_HDMI_PLL 20
#define CLKID_MPLL_50M_DIV 21
#define CLKID_MPLL_50M 22
#define CLKID_MPLL_PREDIV 23
#define CLKID_MPLL0_DIV 24
#define CLKID_MPLL0 25
#define CLKID_MPLL1_DIV 26
#define CLKID_MPLL1 27
#define CLKID_MPLL2_DIV 28
#define CLKID_MPLL2 29
#define CLKID_MPLL3_DIV 30
#define CLKID_MPLL3 31
#endif /* _DT_BINDINGS_CLOCK_AMLOGIC_S4_PLL_CLKC_H */

View file

@ -376,7 +376,6 @@
#define IMX8MP_CLK_AUDIOMIX_MU2_ROOT 36
#define IMX8MP_CLK_AUDIOMIX_MU3_ROOT 37
#define IMX8MP_CLK_AUDIOMIX_EARC_PHY 38
#define IMX8MP_CLK_AUDIOMIX_PDM_ROOT 39
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1_SEL 40
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK2_SEL 41
#define IMX8MP_CLK_AUDIOMIX_SAI2_MCLK1_SEL 42

View file

@ -74,7 +74,7 @@ void clk_hw_forward_rate_request(const struct clk_hw *core,
unsigned long parent_rate);
/**
* struct clk_duty - Struture encoding the duty cycle ratio of a clock
* struct clk_duty - Structure encoding the duty cycle ratio of a clock
*
* @num: Numerator of the duty cycle ratio
* @den: Denominator of the duty cycle ratio
@ -129,7 +129,7 @@ struct clk_duty {
* @restore_context: Restore the context of the clock after a restoration
* of power.
*
* @recalc_rate Recalculate the rate of this clock, by querying hardware. The
* @recalc_rate: Recalculate the rate of this clock, by querying hardware. The
* parent rate is an input parameter. It is up to the caller to
* ensure that the prepare_mutex is held across this call. If the
* driver cannot figure out a rate for this clock, it must return
@ -456,7 +456,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
* clock with the clock framework
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_name: name of clock's parent
* @parent_data: name of clock's parent
* @flags: framework-specific flags
* @fixed_rate: non-adjustable clock rate
* @fixed_accuracy: non-adjustable clock accuracy
@ -471,7 +471,7 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
* the clock framework
* @dev: device that is registering this clock
* @name: name of this clock
* @parent_name: name of clock's parent
* @parent_data: name of clock's parent
* @flags: framework-specific flags
* @fixed_rate: non-adjustable clock rate
*/
@ -649,7 +649,7 @@ struct clk_div_table {
* Clock with an adjustable divider affecting its output frequency. Implements
* .recalc_rate, .set_rate and .round_rate
*
* Flags:
* @flags:
* CLK_DIVIDER_ONE_BASED - by default the divisor is the value read from the
* register plus one. If CLK_DIVIDER_ONE_BASED is set then the divider is
* the raw value read from the register, with the value of zero considered
@ -1130,11 +1130,12 @@ struct clk_hw *clk_hw_register_fixed_factor_parent_hw(struct device *dev,
* @mwidth: width of the numerator bit field
* @nshift: shift to the denominator bit field
* @nwidth: width of the denominator bit field
* @approximation: clk driver's callback for calculating the divider clock
* @lock: register lock
*
* Clock with adjustable fractional divider affecting its output frequency.
*
* Flags:
* @flags:
* CLK_FRAC_DIVIDER_ZERO_BASED - by default the numerator and denominator
* is the value read from the register. If CLK_FRAC_DIVIDER_ZERO_BASED
* is set then the numerator and denominator are both the value read
@ -1191,7 +1192,7 @@ void clk_hw_unregister_fractional_divider(struct clk_hw *hw);
* Clock with an adjustable multiplier affecting its output frequency.
* Implements .recalc_rate, .set_rate and .round_rate
*
* Flags:
* @flags:
* CLK_MULTIPLIER_ZERO_BYPASS - By default, the multiplier is the value read
* from the register, with 0 being a valid value effectively
* zeroing the output clock rate. If CLK_MULTIPLIER_ZERO_BYPASS is