* Re: [PATCH v2 3/4] clk: en7523: Add en_clk_soc_data data structure
From: Stephen Boyd @ 2024-04-11 3:36 UTC (permalink / raw)
To: Lorenzo Bianconi, linux-clk
Cc: mturquette, linux-arm-kernel, robh+dt, krzysztof.kozlowski+dt,
conor+dt, nbd, john, devicetree, dd, catalin.marinas, will,
upstream, lorenzo.bianconi83, angelogioacchino.delregno
In-Reply-To: <562a0da8d7874a02a324687c152c87a1549924bd.1712399981.git.lorenzo@kernel.org>
Quoting Lorenzo Bianconi (2024-04-06 03:43:43)
> Introduce en_clk_soc_data data structure in order to define multiple
> clk_ops for each supported SoC. This is a preliminary patch to
> introduce EN7581 clock support.
>
> Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
Applied to clk-next
^ permalink raw reply
* Re: [PATCH v2 4/4] clk: en7523: Add EN7581 support
From: Stephen Boyd @ 2024-04-11 3:36 UTC (permalink / raw)
To: Lorenzo Bianconi, linux-clk
Cc: mturquette, linux-arm-kernel, robh+dt, krzysztof.kozlowski+dt,
conor+dt, nbd, john, devicetree, dd, catalin.marinas, will,
upstream, lorenzo.bianconi83, angelogioacchino.delregno
In-Reply-To: <57b6e53ed4d2b2e38abff6a3ea56841bad6be8a9.1712399981.git.lorenzo@kernel.org>
Quoting Lorenzo Bianconi (2024-04-06 03:43:44)
> Introduce EN7581 clock support to clk-en7523 driver.
> Add hw_init callback to en_clk_soc_data data structure.
>
> Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> ---
Applied to clk-next
^ permalink raw reply
* [PATCH 1/2] dt-bindings: remoteproc: mediatek: Support MT8188 dual-core SCP
From: olivia.wen @ 2024-04-11 3:37 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring
Cc: Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Tinghan Shen, linux-remoteproc,
devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Project_Global_Chrome_Upstream_Group, jason-ch.chen, yaya.chang,
teddy.chen, olivia.wen
In-Reply-To: <20240411033750.6476-1-olivia.wen@mediatek.com>
Under different applications, the MT8188 SCP can be used as single-core
or dual-core.
Signed-off-by: olivia.wen <olivia.wen@mediatek.com>
---
Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
index 507f98f..7e7b567 100644
--- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
@@ -22,7 +22,7 @@ properties:
- mediatek,mt8192-scp
- mediatek,mt8195-scp
- mediatek,mt8195-scp-dual
-
+ - mediatek,mt8188-scp-dual
reg:
description:
Should contain the address ranges for memory regions SRAM, CFG, and,
@@ -195,6 +195,7 @@ allOf:
compatible:
enum:
- mediatek,mt8195-scp-dual
+ - mediatek,mt8188-scp-dual
then:
properties:
reg:
--
2.6.4
^ permalink raw reply related
* [PATCH 2/2] remoteproc: mediatek: Support MT8188 SCP core 1
From: olivia.wen @ 2024-04-11 3:37 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring
Cc: Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Tinghan Shen, linux-remoteproc,
devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Project_Global_Chrome_Upstream_Group, jason-ch.chen, yaya.chang,
teddy.chen, olivia.wen
In-Reply-To: <20240411033750.6476-1-olivia.wen@mediatek.com>
To Support MT8188 SCP core 1 for ISP driver.
The SCP on different chips will require different code sizes
and IPI buffer sizes based on varying requirements.
Signed-off-by: olivia.wen <olivia.wen@mediatek.com>
---
drivers/remoteproc/mtk_common.h | 5 +--
drivers/remoteproc/mtk_scp.c | 62 +++++++++++++++++++++++++++++++-------
drivers/remoteproc/mtk_scp_ipi.c | 9 ++++--
include/linux/remoteproc/mtk_scp.h | 1 +
4 files changed, 62 insertions(+), 15 deletions(-)
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
index 6d7736a..8f37f65 100644
--- a/drivers/remoteproc/mtk_common.h
+++ b/drivers/remoteproc/mtk_common.h
@@ -78,7 +78,6 @@
#define MT8195_L2TCM_OFFSET 0x850d0
#define SCP_FW_VER_LEN 32
-#define SCP_SHARE_BUFFER_SIZE 288
struct scp_run {
u32 signaled;
@@ -110,6 +109,8 @@ struct mtk_scp_of_data {
u32 host_to_scp_int_bit;
size_t ipi_buf_offset;
+ u32 ipi_buffer_size;
+ u32 max_code_size;
};
struct mtk_scp_of_cluster {
@@ -162,7 +163,7 @@ struct mtk_scp {
struct mtk_share_obj {
u32 id;
u32 len;
- u8 share_buf[SCP_SHARE_BUFFER_SIZE];
+ u8 *share_buf;
};
void scp_memcpy_aligned(void __iomem *dst, const void *src, unsigned int len);
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index 6751829..270718d 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -20,7 +20,6 @@
#include "mtk_common.h"
#include "remoteproc_internal.h"
-#define MAX_CODE_SIZE 0x500000
#define SECTION_NAME_IPI_BUFFER ".ipi_buffer"
/**
@@ -94,14 +93,14 @@ static void scp_ipi_handler(struct mtk_scp *scp)
{
struct mtk_share_obj __iomem *rcv_obj = scp->recv_buf;
struct scp_ipi_desc *ipi_desc = scp->ipi_desc;
- u8 tmp_data[SCP_SHARE_BUFFER_SIZE];
+ u8 *tmp_data;
scp_ipi_handler_t handler;
u32 id = readl(&rcv_obj->id);
u32 len = readl(&rcv_obj->len);
- if (len > SCP_SHARE_BUFFER_SIZE) {
+ if (len > scp->data->ipi_buffer_size) {
dev_err(scp->dev, "ipi message too long (len %d, max %d)", len,
- SCP_SHARE_BUFFER_SIZE);
+ scp->data->ipi_buffer_size);
return;
}
if (id >= SCP_IPI_MAX) {
@@ -109,6 +108,10 @@ static void scp_ipi_handler(struct mtk_scp *scp)
return;
}
+ tmp_data = kzalloc(len, GFP_KERNEL);
+ if (!tmp_data)
+ return;
+
scp_ipi_lock(scp, id);
handler = ipi_desc[id].handler;
if (!handler) {
@@ -123,6 +126,7 @@ static void scp_ipi_handler(struct mtk_scp *scp)
scp->ipi_id_ack[id] = true;
wake_up(&scp->ack_wq);
+ kfree(tmp_data);
}
static int scp_elf_read_ipi_buf_addr(struct mtk_scp *scp,
@@ -133,6 +137,7 @@ static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
{
int ret;
size_t buf_sz, offset;
+ size_t share_buf_offset;
/* read the ipi buf addr from FW itself first */
ret = scp_elf_read_ipi_buf_addr(scp, fw, &offset);
@@ -154,10 +159,12 @@ static int scp_ipi_init(struct mtk_scp *scp, const struct firmware *fw)
scp->recv_buf = (struct mtk_share_obj __iomem *)
(scp->sram_base + offset);
+ share_buf_offset = sizeof(scp->recv_buf->id)
+ + sizeof(scp->recv_buf->len) + scp->data->ipi_buffer_size;
scp->send_buf = (struct mtk_share_obj __iomem *)
- (scp->sram_base + offset + sizeof(*scp->recv_buf));
- memset_io(scp->recv_buf, 0, sizeof(*scp->recv_buf));
- memset_io(scp->send_buf, 0, sizeof(*scp->send_buf));
+ (scp->sram_base + offset + share_buf_offset);
+ memset_io(scp->recv_buf, 0, share_buf_offset);
+ memset_io(scp->send_buf, 0, share_buf_offset);
return 0;
}
@@ -891,7 +898,7 @@ static int scp_map_memory_region(struct mtk_scp *scp)
}
/* Reserved SCP code size */
- scp->dram_size = MAX_CODE_SIZE;
+ scp->dram_size = scp->data->max_code_size;
scp->cpu_addr = dma_alloc_coherent(scp->dev, scp->dram_size,
&scp->dma_addr, GFP_KERNEL);
if (!scp->cpu_addr)
@@ -1247,6 +1254,8 @@ static const struct mtk_scp_of_data mt8183_of_data = {
.host_to_scp_reg = MT8183_HOST_TO_SCP,
.host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
.ipi_buf_offset = 0x7bdb0,
+ .max_code_size = 0x500000,
+ .ipi_buffer_size = 288,
};
static const struct mtk_scp_of_data mt8186_of_data = {
@@ -1260,18 +1269,22 @@ static const struct mtk_scp_of_data mt8186_of_data = {
.host_to_scp_reg = MT8183_HOST_TO_SCP,
.host_to_scp_int_bit = MT8183_HOST_IPC_INT_BIT,
.ipi_buf_offset = 0x3bdb0,
+ .max_code_size = 0x500000,
+ .ipi_buffer_size = 288,
};
static const struct mtk_scp_of_data mt8188_of_data = {
.scp_clk_get = mt8195_scp_clk_get,
- .scp_before_load = mt8192_scp_before_load,
- .scp_irq_handler = mt8192_scp_irq_handler,
+ .scp_before_load = mt8195_scp_before_load,
+ .scp_irq_handler = mt8195_scp_irq_handler,
.scp_reset_assert = mt8192_scp_reset_assert,
.scp_reset_deassert = mt8192_scp_reset_deassert,
- .scp_stop = mt8192_scp_stop,
+ .scp_stop = mt8195_scp_stop,
.scp_da_to_va = mt8192_scp_da_to_va,
.host_to_scp_reg = MT8192_GIPC_IN_SET,
.host_to_scp_int_bit = MT8192_HOST_IPC_INT_BIT,
+ .max_code_size = 0x500000,
+ .ipi_buffer_size = 600,
};
static const struct mtk_scp_of_data mt8192_of_data = {
@@ -1284,6 +1297,8 @@ static const struct mtk_scp_of_data mt8192_of_data = {
.scp_da_to_va = mt8192_scp_da_to_va,
.host_to_scp_reg = MT8192_GIPC_IN_SET,
.host_to_scp_int_bit = MT8192_HOST_IPC_INT_BIT,
+ .max_code_size = 0x500000,
+ .ipi_buffer_size = 288,
};
static const struct mtk_scp_of_data mt8195_of_data = {
@@ -1296,6 +1311,8 @@ static const struct mtk_scp_of_data mt8195_of_data = {
.scp_da_to_va = mt8192_scp_da_to_va,
.host_to_scp_reg = MT8192_GIPC_IN_SET,
.host_to_scp_int_bit = MT8192_HOST_IPC_INT_BIT,
+ .max_code_size = 0x500000,
+ .ipi_buffer_size = 288,
};
static const struct mtk_scp_of_data mt8195_of_data_c1 = {
@@ -1308,6 +1325,22 @@ static const struct mtk_scp_of_data mt8195_of_data_c1 = {
.scp_da_to_va = mt8192_scp_da_to_va,
.host_to_scp_reg = MT8192_GIPC_IN_SET,
.host_to_scp_int_bit = MT8195_CORE1_HOST_IPC_INT_BIT,
+ .max_code_size = 0x500000,
+ .ipi_buffer_size = 288,
+};
+
+static const struct mtk_scp_of_data mt8188_of_data_c1 = {
+ .scp_clk_get = mt8195_scp_clk_get,
+ .scp_before_load = mt8195_scp_c1_before_load,
+ .scp_irq_handler = mt8195_scp_c1_irq_handler,
+ .scp_reset_assert = mt8195_scp_c1_reset_assert,
+ .scp_reset_deassert = mt8195_scp_c1_reset_deassert,
+ .scp_stop = mt8195_scp_c1_stop,
+ .scp_da_to_va = mt8192_scp_da_to_va,
+ .host_to_scp_reg = MT8192_GIPC_IN_SET,
+ .host_to_scp_int_bit = MT8195_CORE1_HOST_IPC_INT_BIT,
+ .max_code_size = 0xA00000,
+ .ipi_buffer_size = 600,
};
static const struct mtk_scp_of_data *mt8195_of_data_cores[] = {
@@ -1316,6 +1349,12 @@ static const struct mtk_scp_of_data *mt8195_of_data_cores[] = {
NULL
};
+static const struct mtk_scp_of_data *mt8188_of_data_cores[] = {
+ &mt8188_of_data,
+ &mt8188_of_data_c1,
+ NULL
+};
+
static const struct of_device_id mtk_scp_of_match[] = {
{ .compatible = "mediatek,mt8183-scp", .data = &mt8183_of_data },
{ .compatible = "mediatek,mt8186-scp", .data = &mt8186_of_data },
@@ -1323,6 +1362,7 @@ static const struct of_device_id mtk_scp_of_match[] = {
{ .compatible = "mediatek,mt8192-scp", .data = &mt8192_of_data },
{ .compatible = "mediatek,mt8195-scp", .data = &mt8195_of_data },
{ .compatible = "mediatek,mt8195-scp-dual", .data = &mt8195_of_data_cores },
+ { .compatible = "mediatek,mt8188-scp-dual", .data = &mt8188_of_data_cores },
{},
};
MODULE_DEVICE_TABLE(of, mtk_scp_of_match);
diff --git a/drivers/remoteproc/mtk_scp_ipi.c b/drivers/remoteproc/mtk_scp_ipi.c
index cd0b601..4ef5491 100644
--- a/drivers/remoteproc/mtk_scp_ipi.c
+++ b/drivers/remoteproc/mtk_scp_ipi.c
@@ -162,10 +162,12 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len,
struct mtk_share_obj __iomem *send_obj = scp->send_buf;
u32 val;
int ret;
+ size_t share_buf_offset;
+ void __iomem *share_buf_io_address;
if (WARN_ON(id <= SCP_IPI_INIT) || WARN_ON(id >= SCP_IPI_MAX) ||
WARN_ON(id == SCP_IPI_NS_SERVICE) ||
- WARN_ON(len > sizeof(send_obj->share_buf)) || WARN_ON(!buf))
+ WARN_ON(len > scp->data->ipi_buffer_size) || WARN_ON(!buf))
return -EINVAL;
ret = clk_prepare_enable(scp->clk);
@@ -184,7 +186,10 @@ int scp_ipi_send(struct mtk_scp *scp, u32 id, void *buf, unsigned int len,
goto unlock_mutex;
}
- scp_memcpy_aligned(send_obj->share_buf, buf, len);
+ share_buf_offset = offsetof(struct mtk_share_obj, share_buf);
+ share_buf_io_address = (void __iomem *)((uintptr_t)scp->send_buf + share_buf_offset);
+
+ scp_memcpy_aligned(share_buf_io_address, buf, len);
writel(len, &send_obj->len);
writel(id, &send_obj->id);
diff --git a/include/linux/remoteproc/mtk_scp.h b/include/linux/remoteproc/mtk_scp.h
index 7c2b7cc9..344ff41 100644
--- a/include/linux/remoteproc/mtk_scp.h
+++ b/include/linux/remoteproc/mtk_scp.h
@@ -43,6 +43,7 @@ enum scp_ipi_id {
SCP_IPI_CROS_HOST_CMD,
SCP_IPI_VDEC_LAT,
SCP_IPI_VDEC_CORE,
+ SCP_IPI_IMGSYS_CMD,
SCP_IPI_NS_SERVICE = 0xFF,
SCP_IPI_MAX = 0x100,
};
--
2.6.4
^ permalink raw reply related
* [PATCH 0/2] Support MT8188 SCP core 1
From: olivia.wen @ 2024-04-11 3:37 UTC (permalink / raw)
To: Bjorn Andersson, Mathieu Poirier, Rob Herring
Cc: Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Tinghan Shen, linux-remoteproc,
devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Project_Global_Chrome_Upstream_Group, jason-ch.chen, yaya.chang,
teddy.chen, olivia.wen
Add below patches to support MT8188 SCP core 1
[PATCH 1/2] dt-bindings: remoteproc: mediatek:
Support MT8188 dual-core SCP
[PATCH 2/2] remoteproc: mediatek: Support MT8188 SCP core 1
olivia.wen (2):
dt-bindings: remoteproc: mediatek: Support MT8188 dual-core SCP
remoteproc: mediatek: Support MT8188 SCP core 1
.../devicetree/bindings/remoteproc/mtk,scp.yaml | 3 +-
drivers/remoteproc/mtk_common.h | 5 +-
drivers/remoteproc/mtk_scp.c | 62 ++++++++++++++++++----
drivers/remoteproc/mtk_scp_ipi.c | 9 +++-
include/linux/remoteproc/mtk_scp.h | 1 +
5 files changed, 64 insertions(+), 16 deletions(-)
--
2.6.4
^ permalink raw reply
* Re: [PATCH v13 4/5] clk: sophgo: Add SG2042 clock driver
From: Stephen Boyd @ 2024-04-11 4:11 UTC (permalink / raw)
To: Chen Wang, aou, chao.wei, conor, devicetree, guoren, haijiao.liu,
inochiama, jszhang, krzysztof.kozlowski+dt, linux-clk,
linux-kernel, linux-riscv, mturquette, palmer, paul.walmsley,
richardcochran, robh+dt, samuel.holland, xiaoguang.xing
Cc: Chen Wang
In-Reply-To: <816122e9f22ddd9927e81e627be7f4683ba5c9e8.1711692169.git.unicorn_wang@outlook.com>
Quoting Chen Wang (2024-03-28 23:21:40)
> From: Chen Wang <unicorn_wang@outlook.com>
>
> Add a driver for the SOPHGO SG2042 clocks.
>
> Signed-off-by: Chen Wang <unicorn_wang@outlook.com>
> ---
> drivers/clk/Kconfig | 1 +
> drivers/clk/Makefile | 1 +
> drivers/clk/sophgo/Kconfig | 7 +
> drivers/clk/sophgo/Makefile | 2 +
> drivers/clk/sophgo/clk-sophgo-sg2042.c | 1410 ++++++++++++++++++++++++
> drivers/clk/sophgo/clk-sophgo-sg2042.h | 216 ++++
Inline the contents of this file into the driver C file.
> diff --git a/drivers/clk/sophgo/clk-sophgo-sg2042.c b/drivers/clk/sophgo/clk-sophgo-sg2042.c
> new file mode 100644
> index 000000000000..7b468e7299ae
> --- /dev/null
> +++ b/drivers/clk/sophgo/clk-sophgo-sg2042.c
> @@ -0,0 +1,1410 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Sophgo SG2042 Clock Generator Driver
> + *
> + * Copyright (C) 2024 Sophgo Technology Inc. All rights reserved.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/iopoll.h>
> +#include <linux/platform_device.h>
Need include for BIT macro, io.h for readl/writel, do_div() header,
ARRAY_SIZE, etc. please check.
> +
> +/*
> + * The clock of SG2042 is composed of three parts.
> + * The registers of these three parts of the clock are scattered in three
> + * different memory address spaces:
> + * - pll clocks
> + * - gate clocks for RP subsystem
> + * - div/mux, and gate clocks working for other subsystem than RP subsystem
> + */
> +#include <dt-bindings/clock/sophgo,sg2042-pll.h>
> +#include <dt-bindings/clock/sophgo,sg2042-rpgate.h>
> +#include <dt-bindings/clock/sophgo,sg2042-clkgen.h>
> +
> +#include "clk-sophgo-sg2042.h"
> +
> +#define KHZ 1000UL
> +#define MHZ (KHZ * KHZ)
> +
> +#define REFDIV_MIN 1
> +#define REFDIV_MAX 63
> +#define FBDIV_MIN 16
> +#define FBDIV_MAX 320
> +
> +#define PLL_FREF_SG2042 (25 * MHZ)
> +
> +#define PLL_FOUTPOSTDIV_MIN (16 * MHZ)
> +#define PLL_FOUTPOSTDIV_MAX (3200 * MHZ)
> +
> +#define PLL_FOUTVCO_MIN (800 * MHZ)
> +#define PLL_FOUTVCO_MAX (3200 * MHZ)
> +
> +struct sg2042_pll_ctrl {
> + unsigned long freq;
> + unsigned int fbdiv;
> + unsigned int postdiv1;
> + unsigned int postdiv2;
> + unsigned int refdiv;
> +};
> +
> +#define PLLCTRL_FBDIV_SHIFT 16
> +#define PLLCTRL_FBDIV_MASK (GENMASK(27, 16) >> PLLCTRL_FBDIV_SHIFT)
> +#define PLLCTRL_POSTDIV2_SHIFT 12
> +#define PLLCTRL_POSTDIV2_MASK (GENMASK(14, 12) >> PLLCTRL_POSTDIV2_SHIFT)
> +#define PLLCTRL_POSTDIV1_SHIFT 8
> +#define PLLCTRL_POSTDIV1_MASK (GENMASK(10, 8) >> PLLCTRL_POSTDIV1_SHIFT)
> +#define PLLCTRL_REFDIV_SHIFT 0
> +#define PLLCTRL_REFDIV_MASK (GENMASK(5, 0) >> PLLCTRL_REFDIV_SHIFT)
> +
> +static inline u32 sg2042_pll_ctrl_encode(struct sg2042_pll_ctrl *ctrl)
> +{
> + return ((ctrl->fbdiv & PLLCTRL_FBDIV_MASK) << PLLCTRL_FBDIV_SHIFT) |
> + ((ctrl->postdiv2 & PLLCTRL_POSTDIV2_MASK) << PLLCTRL_POSTDIV2_SHIFT) |
> + ((ctrl->postdiv1 & PLLCTRL_POSTDIV1_MASK) << PLLCTRL_POSTDIV1_SHIFT) |
> + ((ctrl->refdiv & PLLCTRL_REFDIV_MASK) << PLLCTRL_REFDIV_SHIFT);
> +}
> +
> +static inline void sg2042_pll_ctrl_decode(unsigned int reg_value,
> + struct sg2042_pll_ctrl *ctrl)
> +{
> + ctrl->fbdiv = (reg_value >> PLLCTRL_FBDIV_SHIFT) & PLLCTRL_FBDIV_MASK;
> + ctrl->refdiv = (reg_value >> PLLCTRL_REFDIV_SHIFT) & PLLCTRL_REFDIV_MASK;
> + ctrl->postdiv1 = (reg_value >> PLLCTRL_POSTDIV1_SHIFT) & PLLCTRL_POSTDIV1_MASK;
> + ctrl->postdiv2 = (reg_value >> PLLCTRL_POSTDIV2_SHIFT) & PLLCTRL_POSTDIV2_MASK;
> +}
> +
> +static inline int sg2042_pll_enable(struct sg2042_pll_clock *pll, bool en)
> +{
> + unsigned int value = 0;
Don't need to initialize value? Also, type should be u32.
> +
> + if (en) {
> + /* wait pll lock */
> + if (readl_poll_timeout_atomic(pll->base + pll->offset_status,
> + value,
> + ((value >> pll->shift_status_lock) & 0x1),
> + 0,
> + 100000))
> + pr_warn("%s not locked\n", pll->hw.init->name);
> +
> + /* wait pll updating */
> + if (readl_poll_timeout_atomic(pll->base + pll->offset_status,
> + value,
> + !((value >> pll->shift_status_updating) & 0x1),
> + 0,
> + 100000))
> + pr_warn("%s still updating\n", pll->hw.init->name);
> +
> + /* enable pll */
> + value = readl(pll->base + pll->offset_enable);
> + writel(value | (1 << pll->shift_enable), pll->base + pll->offset_enable);
> + } else {
> + /* disable pll */
> + value = readl(pll->base + pll->offset_enable);
> + writel(value & (~(1 << pll->shift_enable)), pll->base + pll->offset_enable);
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * @reg_value: current register value
> + * @parent_rate: parent frequency
> + *
> + * This function is used to calculate below "rate" in equation
> + * rate = (parent_rate/REFDIV) x FBDIV/POSTDIV1/POSTDIV2
> + * = (parent_rate x FBDIV) / (REFDIV x POSTDIV1 x POSTDIV2)
> + */
> +static unsigned long sg2042_pll_recalc_rate(unsigned int reg_value,
> + unsigned long parent_rate)
> +{
> + struct sg2042_pll_ctrl ctrl_table;
> + u64 rate, numerator, denominator;
> +
> + sg2042_pll_ctrl_decode(reg_value, &ctrl_table);
> +
> + numerator = parent_rate * ctrl_table.fbdiv;
> + denominator = ctrl_table.refdiv * ctrl_table.postdiv1 * ctrl_table.postdiv2;
> + do_div(numerator, denominator);
> + rate = numerator;
> +
> + return rate;
return numerator
> +}
> +
> +/*
> + * Based on input rate/prate/fbdiv/refdiv, look up the postdiv1_2 table
> + * to get the closest postdiiv combination.
> + * postdiv1_2 contains all the possible combination lists of POSTDIV1 and POSTDIV2
> + * for example:
> + * postdiv1_2[0] = {2, 4, 8}, where div1 = 2, div2 = 4 , div1 * div2 = 8
> + *
> + * See TRM:
> + * FOUTPOSTDIV = FREF * FBDIV / REFDIV / (POSTDIV1 * POSTDIV2)
> + * So we get following formula to get POSTDIV1 and POSTDIV2:
> + * POSTDIV = (prate/REFDIV) x FBDIV/rate
> + * above POSTDIV = POSTDIV1*POSTDIV2
> + *
> + * @rate: FOUTPOSTDIV
> + * @prate: parent rate, i.e. FREF
> + * @fbdiv: FBDIV
> + * @refdiv: REFDIV
> + * @postdiv1: POSTDIV1, output
> + * @postdiv2: POSTDIV2, output
> + */
> +static int sg2042_pll_get_postdiv_1_2(unsigned long rate,
> + unsigned long prate,
> + unsigned int fbdiv,
> + unsigned int refdiv,
> + unsigned int *postdiv1,
> + unsigned int *postdiv2)
> +{
> + int index;
> + u64 tmp0;
> +
> + /* POSTDIV_RESULT_INDEX point to 3rd element in the array postdiv1_2 */
> + #define POSTDIV_RESULT_INDEX 2
> +
> + static int postdiv1_2[][3] = {
const
> + {2, 4, 8}, {3, 3, 9}, {2, 5, 10}, {2, 6, 12},
> + {2, 7, 14}, {3, 5, 15}, {4, 4, 16}, {3, 6, 18},
> + {4, 5, 20}, {3, 7, 21}, {4, 6, 24}, {5, 5, 25},
> + {4, 7, 28}, {5, 6, 30}, {5, 7, 35}, {6, 6, 36},
> + {6, 7, 42}, {7, 7, 49}
> + };
> +
> + /* prate/REFDIV and result save to tmp0 */
> + tmp0 = prate;
> + do_div(tmp0, refdiv);
> +
> + /* ((prate/REFDIV) x FBDIV) and result save to tmp0 */
> + tmp0 *= fbdiv;
> +
> + /* ((prate/REFDIV) x FBDIV)/rate and result save to tmp0 */
> + do_div(tmp0, rate);
> +
> + /* tmp0 is POSTDIV1*POSTDIV2, now we calculate div1 and div2 value */
> + if (tmp0 <= 7) {
> + /* (div1 * div2) <= 7, no need to use array search */
> + *postdiv1 = tmp0;
> + *postdiv2 = 1;
> + return 0;
> + }
> +
> + /* (div1 * div2) > 7, use array search */
> + for (index = 0; index < ARRAY_SIZE(postdiv1_2); index++) {
> + if (tmp0 > postdiv1_2[index][POSTDIV_RESULT_INDEX]) {
> + continue;
> + } else {
> + /* found it */
> + *postdiv1 = postdiv1_2[index][1];
> + *postdiv2 = postdiv1_2[index][0];
> + return 0;
> + }
> + }
> + pr_warn("%s can not find in postdiv array!\n", __func__);
> + return -EINVAL;
> +}
> +
> +/*
> + * Based on the given FOUTPISTDIV and the input FREF to calculate
> + * the REFDIV/FBDIV/PSTDIV1/POSTDIV2 combination for pllctrl register.
> + * @req_rate: expected output clock rate, i.e. FOUTPISTDIV
> + * @parent_rate: input parent clock rate, i.e. FREF
> + * @best: output to hold calculated combination of REFDIV/FBDIV/PSTDIV1/POSTDIV2
> + */
> +static int sg2042_get_pll_ctl_setting(struct sg2042_pll_ctrl *best,
> + unsigned long req_rate,
> + unsigned long parent_rate)
> +{
> + int ret;
> + unsigned int fbdiv, refdiv, postdiv1, postdiv2;
> + unsigned long foutpostdiv;
> + u64 tmp;
> + u64 foutvco;
> +
> + if (parent_rate != PLL_FREF_SG2042) {
> + pr_err("INVALID FREF: %ld\n", parent_rate);
> + return -EINVAL;
> + }
> +
> + if (req_rate < PLL_FOUTPOSTDIV_MIN || req_rate > PLL_FOUTPOSTDIV_MAX) {
> + pr_alert("INVALID FOUTPOSTDIV: %ld\n", req_rate);
> + return -EINVAL;
> + }
> +
> + memset(best, 0, sizeof(struct sg2042_pll_ctrl));
> +
> + for (refdiv = REFDIV_MIN; refdiv < REFDIV_MAX + 1; refdiv++) {
> + /* required by hardware: FREF/REFDIV must > 10 */
> + tmp = parent_rate;
> + do_div(tmp, refdiv);
> + if (tmp <= 10)
> + continue;
> +
> + for (fbdiv = FBDIV_MIN; fbdiv < FBDIV_MAX + 1; fbdiv++) {
> + /*
> + * FOUTVCO = FREF*FBDIV/REFDIV validation
> + * required by hardware, FOUTVCO must [800MHz, 3200MHz]
> + */
> + foutvco = parent_rate * fbdiv;
> + do_div(foutvco, refdiv);
> + if (foutvco < PLL_FOUTVCO_MIN || foutvco > PLL_FOUTVCO_MAX)
> + continue;
> +
> + ret = sg2042_pll_get_postdiv_1_2(req_rate, parent_rate,
> + fbdiv, refdiv,
> + &postdiv1, &postdiv2);
> + if (ret)
> + continue;
> +
> + /*
> + * FOUTPOSTDIV = FREF*FBDIV/REFDIV/(POSTDIV1*POSTDIV2)
> + * = FOUTVCO/(POSTDIV1*POSTDIV2)
> + */
> + tmp = foutvco;
> + do_div(tmp, (postdiv1 * postdiv2));
> + foutpostdiv = (unsigned long)tmp;
> + /* Iterative to approach the expected value */
> + if (abs_diff(foutpostdiv, req_rate) < abs_diff(best->freq, req_rate)) {
> + best->freq = foutpostdiv;
> + best->refdiv = refdiv;
> + best->fbdiv = fbdiv;
> + best->postdiv1 = postdiv1;
> + best->postdiv2 = postdiv2;
> + if (foutpostdiv == req_rate)
> + return 0;
> + }
> + continue;
> + }
> + }
> +
> + if (best->freq == 0)
> + return -EINVAL;
> + else
> + return 0;
> +}
> +
> +/*
> + * @hw: ccf use to hook get sg2042_pll_clock
> + * @parent_rate: parent rate
> + *
> + * The is function will be called through clk_get_rate
> + * and return current rate after decoding reg value
> + */
> +static unsigned long sg2042_clk_pll_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + unsigned int value;
> + unsigned long rate;
> + struct sg2042_pll_clock *pll = to_sg2042_pll_clk(hw);
> +
> + value = readl(pll->base + pll->offset_ctrl);
> + rate = sg2042_pll_recalc_rate(value, parent_rate);
> +
> + pr_debug("--> %s: pll_recalc_rate: val = %ld\n",
> + clk_hw_get_name(hw), rate);
> + return rate;
> +}
> +
> +static long sg2042_clk_pll_round_rate(struct clk_hw *hw,
> + unsigned long req_rate,
> + unsigned long *prate)
> +{
> + unsigned int value;
> + struct sg2042_pll_ctrl pctrl_table;
> + long proper_rate;
> + int ret;
> +
> + ret = sg2042_get_pll_ctl_setting(&pctrl_table, req_rate, *prate);
> + if (ret) {
> + proper_rate = 0;
> + goto out;
> + }
> +
> + value = sg2042_pll_ctrl_encode(&pctrl_table);
> + proper_rate = (long)sg2042_pll_recalc_rate(value, *prate);
> +
> +out:
> + pr_debug("--> %s: pll_round_rate: val = %ld\n",
> + clk_hw_get_name(hw), proper_rate);
> + return proper_rate;
> +}
> +
> +static int sg2042_clk_pll_determine_rate(struct clk_hw *hw,
> + struct clk_rate_request *req)
> +{
> + req->rate = sg2042_clk_pll_round_rate(hw, min(req->rate, req->max_rate),
> + &req->best_parent_rate);
> + pr_debug("--> %s: pll_determine_rate: val = %ld\n",
> + clk_hw_get_name(hw), req->rate);
> + return 0;
> +}
> +
> +static int sg2042_clk_pll_set_rate(struct clk_hw *hw,
> + unsigned long rate,
> + unsigned long parent_rate)
> +{
> + unsigned long flags;
> + unsigned int value;
> + int ret = 0;
> + struct sg2042_pll_ctrl pctrl_table;
> + struct sg2042_pll_clock *pll = to_sg2042_pll_clk(hw);
> +
> + spin_lock_irqsave(pll->lock, flags);
> + if (sg2042_pll_enable(pll, 0)) {
> + pr_warn("Can't disable pll(%s), status error\n", pll->hw.init->name);
> + goto out;
> + }
> + ret = sg2042_get_pll_ctl_setting(&pctrl_table, rate, parent_rate);
> + if (ret) {
> + pr_warn("%s: Can't find a proper pll setting\n", pll->hw.init->name);
> + goto out2;
> + }
> +
> + value = sg2042_pll_ctrl_encode(&pctrl_table);
> +
> + /* write the value to top register */
> + writel(value, pll->base + pll->offset_ctrl);
> +
> +out2:
> + sg2042_pll_enable(pll, 1);
> +out:
> + spin_unlock_irqrestore(pll->lock, flags);
> +
> + pr_debug("--> %s: pll_set_rate: val = 0x%x\n",
> + clk_hw_get_name(hw), value);
> + return ret;
> +}
> +
> +static const struct clk_ops sg2042_clk_pll_ops = {
> + .recalc_rate = sg2042_clk_pll_recalc_rate,
> + .round_rate = sg2042_clk_pll_round_rate,
> + .determine_rate = sg2042_clk_pll_determine_rate,
> + .set_rate = sg2042_clk_pll_set_rate,
> +};
> +
> +static const struct clk_ops sg2042_clk_pll_ro_ops = {
> + .recalc_rate = sg2042_clk_pll_recalc_rate,
> + .round_rate = sg2042_clk_pll_round_rate,
> +};
> +
> +static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
> + unsigned int val;
> + unsigned long ret_rate;
> +
> + if (!(readl(divider->reg) & BIT(3))) {
What is bit 3? Please make a define.
> + val = (int)(divider->initval);
> + } else {
> + val = readl(divider->reg) >> divider->shift;
> + val &= clk_div_mask(divider->width);
> + }
> +
> + ret_rate = divider_recalc_rate(hw, parent_rate, val, NULL,
> + divider->div_flags, divider->width);
> +
> + pr_debug("--> %s: divider_recalc_rate: ret_rate = %ld\n",
> + clk_hw_get_name(hw), ret_rate);
> + return ret_rate;
> +}
> +
> +static long sg2042_clk_divider_round_rate(struct clk_hw *hw,
> + unsigned long rate,
> + unsigned long *prate)
> +{
> + int bestdiv;
> + unsigned long ret_rate;
> + struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
> +
> + /* if read only, just return current value */
> + if (divider->div_flags & CLK_DIVIDER_READ_ONLY) {
> + if (!(readl(divider->reg) & BIT(3))) {
> + bestdiv = (int)(divider->initval);
> + } else {
> + bestdiv = readl(divider->reg) >> divider->shift;
> + bestdiv &= clk_div_mask(divider->width);
> + }
> + ret_rate = DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
> + } else {
> + ret_rate = divider_round_rate(hw, rate, prate, NULL,
> + divider->width, divider->div_flags);
> + }
> +
> + pr_debug("--> %s: divider_round_rate: val = %ld\n",
> + clk_hw_get_name(hw), ret_rate);
> + return ret_rate;
> +}
> +
> +static int sg2042_clk_divider_set_rate(struct clk_hw *hw,
> + unsigned long rate,
> + unsigned long parent_rate)
> +{
> + unsigned int value;
> + unsigned int val, val2;
> + unsigned long flags = 0;
> + struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
> +
> + value = divider_get_val(rate, parent_rate, NULL,
> + divider->width, divider->div_flags);
> +
> + if (divider->lock)
> + spin_lock_irqsave(divider->lock, flags);
> + else
> + __acquire(divider->lock);
> +
> + /*
> + * The sequence of clock frequency modification is:
> + * Assert to reset divider.
> + * Modify the value of Clock Divide Factor (and High Wide if needed).
> + * De-assert to restore divided clock with new frequency.
> + */
> + val = readl(divider->reg);
> +
> + /* assert */
> + val &= ~0x1;
> + writel(val, divider->reg);
> +
> + if (divider->div_flags & CLK_DIVIDER_HIWORD_MASK) {
> + val = clk_div_mask(divider->width) << (divider->shift + 16);
> + } else {
> + val = readl(divider->reg);
> + val &= ~(clk_div_mask(divider->width) << divider->shift);
> + }
> + val |= value << divider->shift;
> + val |= 1 << 3;
Make a define for bit 3 and bit 0 please.
> + writel(val, divider->reg);
> + val2 = val;
> +
> + /* de-assert */
> + val |= 1;
> + writel(val, divider->reg);
> +
> + if (divider->lock)
> + spin_unlock_irqrestore(divider->lock, flags);
> + else
> + __release(divider->lock);
> +
> + pr_debug("--> %s: divider_set_rate: register val = 0x%x\n",
> + clk_hw_get_name(hw), val2);
> + return 0;
> +}
> +
> +static const struct clk_ops sg2042_clk_divider_ops = {
> + .recalc_rate = sg2042_clk_divider_recalc_rate,
> + .round_rate = sg2042_clk_divider_round_rate,
> + .set_rate = sg2042_clk_divider_set_rate,
> +};
> +
> +static const struct clk_ops sg2042_clk_divider_ro_ops = {
> + .recalc_rate = sg2042_clk_divider_recalc_rate,
> + .round_rate = sg2042_clk_divider_round_rate,
> +};
> +
> +#define SG2042_PLL(_id, _name, _parent_name, _r_stat, _r_enable, _r_ctrl, _shift) \
> + { \
> + .hw.init = CLK_HW_INIT( \
> + _name, \
> + _parent_name, \
> + &sg2042_clk_pll_ops, \
> + CLK_GET_RATE_NOCACHE | CLK_GET_ACCURACY_NOCACHE),\
> + .id = _id, \
> + .offset_ctrl = _r_ctrl, \
> + .offset_status = _r_stat, \
> + .offset_enable = _r_enable, \
> + .shift_status_lock = 8 + (_shift), \
> + .shift_status_updating = _shift, \
> + .shift_enable = _shift, \
> + }
> +
> +#define SG2042_PLL_RO(_id, _name, _parent_name, _r_stat, _r_enable, _r_ctrl, _shift) \
> + { \
> + .hw.init = CLK_HW_INIT( \
> + _name, \
> + _parent_name, \
> + &sg2042_clk_pll_ro_ops, \
> + CLK_GET_RATE_NOCACHE | CLK_GET_ACCURACY_NOCACHE),\
> + .id = _id, \
> + .offset_ctrl = _r_ctrl, \
> + .offset_status = _r_stat, \
> + .offset_enable = _r_enable, \
> + .shift_status_lock = 8 + (_shift), \
> + .shift_status_updating = _shift, \
> + .shift_enable = _shift, \
> + }
> +
> +static struct sg2042_pll_clock sg2042_pll_clks[] = {
> + SG2042_PLL(MPLL_CLK, "mpll_clock", "cgi_main",
> + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_MPLL_CONTROL, 0),
> + SG2042_PLL_RO(FPLL_CLK, "fpll_clock", "cgi_main",
> + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_FPLL_CONTROL, 3),
> + SG2042_PLL_RO(DPLL0_CLK, "dpll0_clock", "cgi_dpll0",
> + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_DPLL0_CONTROL, 4),
> + SG2042_PLL_RO(DPLL1_CLK, "dpll1_clock", "cgi_dpll1",
> + R_PLL_STAT, R_PLL_CLKEN_CONTROL, R_DPLL1_CONTROL, 5),
> +};
> +
> +#define SG2042_DIV(_id, _name, _parent_name, \
> + _r_ctrl, _shift, _width, \
> + _div_flag, _initval) { \
> + .hw.init = CLK_HW_INIT( \
> + _name, \
> + _parent_name, \
> + &sg2042_clk_divider_ops, \
> + 0), \
> + .id = _id, \
> + .offset_ctrl = _r_ctrl, \
> + .shift = _shift, \
> + .width = _width, \
> + .div_flags = _div_flag, \
> + .initval = _initval, \
> + }
> +
> +#define SG2042_DIV_RO(_id, _name, _parent_name, \
> + _r_ctrl, _shift, _width, \
> + _div_flag, _initval) { \
> + .hw.init = CLK_HW_INIT( \
> + _name, \
> + _parent_name, \
> + &sg2042_clk_divider_ro_ops, \
> + 0), \
> + .id = _id, \
> + .offset_ctrl = _r_ctrl, \
> + .shift = _shift, \
> + .width = _width, \
> + .div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY, \
> + .initval = _initval, \
> + }
> +
> +/*
> + * DIV items in the array are sorted according to the clock-tree diagram,
> + * from top to bottom, from upstream to downstream. Read TRM for details.
> + */
> +#define DEF_DIVFLAG (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO)
> +static struct sg2042_divider_clock sg2042_div_clks[] = {
> + SG2042_DIV_RO(DIV_CLK_DPLL0_DDR01_0,
> + "clk_div_ddr01_0", "clk_gate_ddr01_div0",
> + R_CLKDIVREG27, 16, 5, DEF_DIVFLAG, 1),
> + SG2042_DIV_RO(DIV_CLK_FPLL_DDR01_1,
> + "clk_div_ddr01_1", "clk_gate_ddr01_div1",
> + R_CLKDIVREG28, 16, 5, DEF_DIVFLAG, 1),
> +
> + SG2042_DIV_RO(DIV_CLK_DPLL1_DDR23_0,
> + "clk_div_ddr23_0", "clk_gate_ddr23_div0",
> + R_CLKDIVREG29, 16, 5, DEF_DIVFLAG, 1),
> + SG2042_DIV_RO(DIV_CLK_FPLL_DDR23_1,
> + "clk_div_ddr23_1", "clk_gate_ddr23_div1",
> + R_CLKDIVREG30, 16, 5, DEF_DIVFLAG, 1),
> +
> + SG2042_DIV(DIV_CLK_MPLL_RP_CPU_NORMAL_0,
> + "clk_div_rp_cpu_normal_0", "clk_gate_rp_cpu_normal_div0",
> + R_CLKDIVREG0, 16, 5, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_RP_CPU_NORMAL_1,
> + "clk_div_rp_cpu_normal_1", "clk_gate_rp_cpu_normal_div1",
> + R_CLKDIVREG1, 16, 5, DEF_DIVFLAG, 1),
> +
> + SG2042_DIV(DIV_CLK_MPLL_AXI_DDR_0,
> + "clk_div_axi_ddr_0", "clk_gate_axi_ddr_div0",
> + R_CLKDIVREG25, 16, 5, DEF_DIVFLAG, 2),
> + SG2042_DIV(DIV_CLK_FPLL_AXI_DDR_1,
> + "clk_div_axi_ddr_1", "clk_gate_axi_ddr_div1",
> + R_CLKDIVREG26, 16, 5, DEF_DIVFLAG, 1),
> +
> + SG2042_DIV(DIV_CLK_FPLL_TOP_RP_CMN_DIV2,
> + "clk_div_top_rp_cmn_div2", "clk_mux_rp_cpu_normal",
> + R_CLKDIVREG3, 16, 16, DEF_DIVFLAG, 2),
> +
> + SG2042_DIV(DIV_CLK_FPLL_50M_A53, "clk_div_50m_a53", "fpll_clock",
> + R_CLKDIVREG2, 16, 8, DEF_DIVFLAG, 20),
> + /* downstream of div_50m_a53 */
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER1, "clk_div_timer1", "clk_div_50m_a53",
> + R_CLKDIVREG6, 16, 16, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER2, "clk_div_timer2", "clk_div_50m_a53",
> + R_CLKDIVREG7, 16, 16, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER3, "clk_div_timer3", "clk_div_50m_a53",
> + R_CLKDIVREG8, 16, 16, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER4, "clk_div_timer4", "clk_div_50m_a53",
> + R_CLKDIVREG9, 16, 16, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER5, "clk_div_timer5", "clk_div_50m_a53",
> + R_CLKDIVREG10, 16, 16, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER6, "clk_div_timer6", "clk_div_50m_a53",
> + R_CLKDIVREG11, 16, 16, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER7, "clk_div_timer7", "clk_div_50m_a53",
> + R_CLKDIVREG12, 16, 16, DEF_DIVFLAG, 1),
> + SG2042_DIV(DIV_CLK_FPLL_DIV_TIMER8, "clk_div_timer8", "clk_div_50m_a53",
> + R_CLKDIVREG13, 16, 16, DEF_DIVFLAG, 1),
> +
> + /*
> + * Set clk_div_uart_500m as RO, because the width of CLKDIVREG4 is too
> + * narrow for us to produce 115200. Use UART internal divider directly.
> + */
> + SG2042_DIV_RO(DIV_CLK_FPLL_UART_500M, "clk_div_uart_500m", "fpll_clock",
> + R_CLKDIVREG4, 16, 7, DEF_DIVFLAG, 2),
> + SG2042_DIV(DIV_CLK_FPLL_AHB_LPC, "clk_div_ahb_lpc", "fpll_clock",
> + R_CLKDIVREG5, 16, 16, DEF_DIVFLAG, 5),
> + SG2042_DIV(DIV_CLK_FPLL_EFUSE, "clk_div_efuse", "fpll_clock",
> + R_CLKDIVREG14, 16, 7, DEF_DIVFLAG, 40),
> + SG2042_DIV(DIV_CLK_FPLL_TX_ETH0, "clk_div_tx_eth0", "fpll_clock",
> + R_CLKDIVREG16, 16, 11, DEF_DIVFLAG, 8),
> + SG2042_DIV(DIV_CLK_FPLL_PTP_REF_I_ETH0,
> + "clk_div_ptp_ref_i_eth0", "fpll_clock",
> + R_CLKDIVREG17, 16, 8, DEF_DIVFLAG, 20),
> + SG2042_DIV(DIV_CLK_FPLL_REF_ETH0, "clk_div_ref_eth0", "fpll_clock",
> + R_CLKDIVREG18, 16, 8, DEF_DIVFLAG, 40),
> + SG2042_DIV(DIV_CLK_FPLL_EMMC, "clk_div_emmc", "fpll_clock",
> + R_CLKDIVREG19, 16, 5, DEF_DIVFLAG, 10),
> + SG2042_DIV(DIV_CLK_FPLL_SD, "clk_div_sd", "fpll_clock",
> + R_CLKDIVREG21, 16, 5, DEF_DIVFLAG, 10),
> +
> + SG2042_DIV(DIV_CLK_FPLL_TOP_AXI0, "clk_div_top_axi0", "fpll_clock",
> + R_CLKDIVREG23, 16, 5, DEF_DIVFLAG, 10),
> + /* downstream of div_top_axi0 */
> + SG2042_DIV(DIV_CLK_FPLL_100K_EMMC, "clk_div_100k_emmc", "clk_div_top_axi0",
> + R_CLKDIVREG20, 16, 16, DEF_DIVFLAG, 1000),
> + SG2042_DIV(DIV_CLK_FPLL_100K_SD, "clk_div_100k_sd", "clk_div_top_axi0",
> + R_CLKDIVREG22, 16, 16, DEF_DIVFLAG, 1000),
> + SG2042_DIV(DIV_CLK_FPLL_GPIO_DB, "clk_div_gpio_db", "clk_div_top_axi0",
> + R_CLKDIVREG15, 16, 16, DEF_DIVFLAG, 1000),
> +
> + SG2042_DIV(DIV_CLK_FPLL_TOP_AXI_HSPERI,
> + "clk_div_top_axi_hsperi", "fpll_clock",
> + R_CLKDIVREG24, 16, 5, DEF_DIVFLAG, 4),
> +};
> +
> +#define SG2042_GATE(_id, _name, _parent_name, _flags, \
> + _r_enable, _bit_idx) { \
> + .hw.init = CLK_HW_INIT( \
> + _name, \
> + _parent_name, \
> + NULL, \
> + _flags), \
> + .id = _id, \
> + .offset_enable = _r_enable, \
> + .bit_idx = _bit_idx, \
> + }
> +
> +/*
> + * GATE items in the array are sorted according to the clock-tree diagram,
> + * from top to bottom, from upstream to downstream. Read TRM for details.
> + */
> +
> +/* Gate clocks which control registers are defined in CLOCK. */
> +static const struct sg2042_gate_clock sg2042_gate_clks[] = {
> + SG2042_GATE(GATE_CLK_DDR01_DIV0, "clk_gate_ddr01_div0", "dpll0_clock",
> + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> + R_CLKDIVREG27, 4),
> + SG2042_GATE(GATE_CLK_DDR01_DIV1, "clk_gate_ddr01_div1", "fpll_clock",
> + CLK_IS_CRITICAL,
> + R_CLKDIVREG28, 4),
> +
> + SG2042_GATE(GATE_CLK_DDR23_DIV0, "clk_gate_ddr23_div0", "dpll1_clock",
> + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
> + R_CLKDIVREG29, 4),
> + SG2042_GATE(GATE_CLK_DDR23_DIV1, "clk_gate_ddr23_div1", "fpll_clock",
> + CLK_IS_CRITICAL,
> + R_CLKDIVREG30, 4),
> +
> + SG2042_GATE(GATE_CLK_RP_CPU_NORMAL_DIV0, "clk_gate_rp_cpu_normal_div0", "mpll_clock",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKDIVREG0, 4),
> + SG2042_GATE(GATE_CLK_RP_CPU_NORMAL_DIV1,
> + "clk_gate_rp_cpu_normal_div1", "fpll_clock",
> + CLK_IS_CRITICAL,
> + R_CLKDIVREG1, 4),
> +
> + SG2042_GATE(GATE_CLK_AXI_DDR_DIV0, "clk_gate_axi_ddr_div0", "mpll_clock",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKDIVREG25, 4),
> + SG2042_GATE(GATE_CLK_AXI_DDR_DIV1, "clk_gate_axi_ddr_div1", "fpll_clock",
> + CLK_IS_CRITICAL,
> + R_CLKDIVREG26, 4),
> +
> + /* upon are gate clocks as input source for the muxes */
> +
> + SG2042_GATE(GATE_CLK_DDR01, "clk_gate_ddr01", "clk_mux_ddr01",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKENREG1, 14),
> +
> + SG2042_GATE(GATE_CLK_DDR23, "clk_gate_ddr23", "clk_mux_ddr23",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKENREG1, 15),
> +
> + SG2042_GATE(GATE_CLK_RP_CPU_NORMAL,
> + "clk_gate_rp_cpu_normal", "clk_mux_rp_cpu_normal",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKENREG0, 0),
> +
> + SG2042_GATE(GATE_CLK_AXI_DDR, "clk_gate_axi_ddr", "clk_mux_axi_ddr",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKENREG1, 13),
> +
> + /* upon are gate clocks directly downstream of muxes */
> +
> + /* downstream of clk_div_top_rp_cmn_div2 */
> + SG2042_GATE(GATE_CLK_TOP_RP_CMN_DIV2,
> + "clk_gate_top_rp_cmn_div2", "clk_div_top_rp_cmn_div2",
> + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 2),
> + SG2042_GATE(GATE_CLK_HSDMA, "clk_gate_hsdma", "clk_gate_top_rp_cmn_div2",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 10),
> +
> + /*
> + * downstream of clk_gate_rp_cpu_normal
> + *
> + * FIXME: there should be one 1/2 DIV between clk_gate_rp_cpu_normal
> + * and clk_gate_axi_pcie0/clk_gate_axi_pcie1.
> + * But the 1/2 DIV is fixed and no configurable register exported, so
> + * when reading from these two clocks, the rate value are still the
> + * same as that of clk_gate_rp_cpu_normal, it's not correct.
> + * This just affects the value read.
> + */
> + SG2042_GATE(GATE_CLK_AXI_PCIE0,
> + "clk_gate_axi_pcie0", "clk_gate_rp_cpu_normal",
> + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 8),
> + SG2042_GATE(GATE_CLK_AXI_PCIE1,
> + "clk_gate_axi_pcie1", "clk_gate_rp_cpu_normal",
> + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 9),
> +
> + /* downstream of div_50m_a53 */
> + SG2042_GATE(GATE_CLK_A53_50M, "clk_gate_a53_50m", "clk_div_50m_a53",
> + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 1),
> + SG2042_GATE(GATE_CLK_TIMER1, "clk_gate_timer1", "clk_div_timer1",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 12),
> + SG2042_GATE(GATE_CLK_TIMER2, "clk_gate_timer2", "clk_div_timer2",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 13),
> + SG2042_GATE(GATE_CLK_TIMER3, "clk_gate_timer3", "clk_div_timer3",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 14),
> + SG2042_GATE(GATE_CLK_TIMER4, "clk_gate_timer4", "clk_div_timer4",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 15),
> + SG2042_GATE(GATE_CLK_TIMER5, "clk_gate_timer5", "clk_div_timer5",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 16),
> + SG2042_GATE(GATE_CLK_TIMER6, "clk_gate_timer6", "clk_div_timer6",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 17),
> + SG2042_GATE(GATE_CLK_TIMER7, "clk_gate_timer7", "clk_div_timer7",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 18),
> + SG2042_GATE(GATE_CLK_TIMER8, "clk_gate_timer8", "clk_div_timer8",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 19),
> +
> + /* gate clocks downstream from div clocks one-to-one */
> + SG2042_GATE(GATE_CLK_UART_500M, "clk_gate_uart_500m", "clk_div_uart_500m",
> + CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 4),
> + SG2042_GATE(GATE_CLK_AHB_LPC, "clk_gate_ahb_lpc", "clk_div_ahb_lpc",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 7),
> + SG2042_GATE(GATE_CLK_EFUSE, "clk_gate_efuse", "clk_div_efuse",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 20),
> + SG2042_GATE(GATE_CLK_TX_ETH0, "clk_gate_tx_eth0", "clk_div_tx_eth0",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 30),
> + SG2042_GATE(GATE_CLK_PTP_REF_I_ETH0,
> + "clk_gate_ptp_ref_i_eth0", "clk_div_ptp_ref_i_eth0",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 0),
> + SG2042_GATE(GATE_CLK_REF_ETH0, "clk_gate_ref_eth0", "clk_div_ref_eth0",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 1),
> + SG2042_GATE(GATE_CLK_EMMC_100M, "clk_gate_emmc", "clk_div_emmc",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 3),
> + SG2042_GATE(GATE_CLK_SD_100M, "clk_gate_sd", "clk_div_sd",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 6),
> +
> + /* downstream of clk_div_top_axi0 */
> + SG2042_GATE(GATE_CLK_AHB_ROM, "clk_gate_ahb_rom", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 8),
> + SG2042_GATE(GATE_CLK_AHB_SF, "clk_gate_ahb_sf", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 9),
> + SG2042_GATE(GATE_CLK_AXI_SRAM, "clk_gate_axi_sram", "clk_div_top_axi0",
> + CLK_IGNORE_UNUSED, R_CLKENREG0, 10),
> + SG2042_GATE(GATE_CLK_APB_TIMER, "clk_gate_apb_timer", "clk_div_top_axi0",
> + CLK_IGNORE_UNUSED, R_CLKENREG0, 11),
> + SG2042_GATE(GATE_CLK_APB_EFUSE, "clk_gate_apb_efuse", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 21),
> + SG2042_GATE(GATE_CLK_APB_GPIO, "clk_gate_apb_gpio", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 22),
> + SG2042_GATE(GATE_CLK_APB_GPIO_INTR,
> + "clk_gate_apb_gpio_intr", "clk_div_top_axi0",
> + CLK_IS_CRITICAL, R_CLKENREG0, 23),
> + SG2042_GATE(GATE_CLK_APB_I2C, "clk_gate_apb_i2c", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 26),
> + SG2042_GATE(GATE_CLK_APB_WDT, "clk_gate_apb_wdt", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 27),
> + SG2042_GATE(GATE_CLK_APB_PWM, "clk_gate_apb_pwm", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 28),
> + SG2042_GATE(GATE_CLK_APB_RTC, "clk_gate_apb_rtc", "clk_div_top_axi0",
> + 0, R_CLKENREG0, 29),
> + SG2042_GATE(GATE_CLK_TOP_AXI0, "clk_gate_top_axi0", "clk_div_top_axi0",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKENREG1, 11),
> + /* downstream of DIV clocks which are sourced from clk_div_top_axi0 */
> + SG2042_GATE(GATE_CLK_GPIO_DB, "clk_gate_gpio_db", "clk_div_gpio_db",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 24),
> + SG2042_GATE(GATE_CLK_100K_EMMC, "clk_gate_100k_emmc", "clk_div_100k_emmc",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 4),
> + SG2042_GATE(GATE_CLK_100K_SD, "clk_gate_100k_sd", "clk_div_100k_sd",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 7),
> +
> + /* downstream of clk_div_top_axi_hsperi */
> + SG2042_GATE(GATE_CLK_SYSDMA_AXI,
> + "clk_gate_sysdma_axi", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 3),
> + SG2042_GATE(GATE_CLK_APB_UART,
> + "clk_gate_apb_uart", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 5),
> + SG2042_GATE(GATE_CLK_AXI_DBG_I2C,
> + "clk_gate_axi_dbg_i2c", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 6),
> + SG2042_GATE(GATE_CLK_APB_SPI,
> + "clk_gate_apb_spi", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 25),
> + SG2042_GATE(GATE_CLK_AXI_ETH0,
> + "clk_gate_axi_eth0", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT, R_CLKENREG0, 31),
> + SG2042_GATE(GATE_CLK_AXI_EMMC,
> + "clk_gate_axi_emmc", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 2),
> + SG2042_GATE(GATE_CLK_AXI_SD,
> + "clk_gate_axi_sd", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT, R_CLKENREG1, 5),
> + SG2042_GATE(GATE_CLK_TOP_AXI_HSPERI,
> + "clk_gate_top_axi_hsperi", "clk_div_top_axi_hsperi",
> + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
> + R_CLKENREG1, 12),
> +};
> +
> +/*
> + * Gate clocks for RP subsystem (including the MP subsystem), which control
> + * registers are defined in SYS_CTRL.
> + */
> +static const struct sg2042_gate_clock sg2042_gate_rp[] = {
> + /* downstream of clk_gate_rp_cpu_normal about rxu */
> + SG2042_GATE(GATE_CLK_RXU0, "clk_gate_rxu0", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 0),
> + SG2042_GATE(GATE_CLK_RXU1, "clk_gate_rxu1", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 1),
> + SG2042_GATE(GATE_CLK_RXU2, "clk_gate_rxu2", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 2),
> + SG2042_GATE(GATE_CLK_RXU3, "clk_gate_rxu3", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 3),
> + SG2042_GATE(GATE_CLK_RXU4, "clk_gate_rxu4", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 4),
> + SG2042_GATE(GATE_CLK_RXU5, "clk_gate_rxu5", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 5),
> + SG2042_GATE(GATE_CLK_RXU6, "clk_gate_rxu6", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 6),
> + SG2042_GATE(GATE_CLK_RXU7, "clk_gate_rxu7", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 7),
> + SG2042_GATE(GATE_CLK_RXU8, "clk_gate_rxu8", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 8),
> + SG2042_GATE(GATE_CLK_RXU9, "clk_gate_rxu9", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 9),
> + SG2042_GATE(GATE_CLK_RXU10, "clk_gate_rxu10", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 10),
> + SG2042_GATE(GATE_CLK_RXU11, "clk_gate_rxu11", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 11),
> + SG2042_GATE(GATE_CLK_RXU12, "clk_gate_rxu12", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 12),
> + SG2042_GATE(GATE_CLK_RXU13, "clk_gate_rxu13", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 13),
> + SG2042_GATE(GATE_CLK_RXU14, "clk_gate_rxu14", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 14),
> + SG2042_GATE(GATE_CLK_RXU15, "clk_gate_rxu15", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 15),
> + SG2042_GATE(GATE_CLK_RXU16, "clk_gate_rxu16", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 16),
> + SG2042_GATE(GATE_CLK_RXU17, "clk_gate_rxu17", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 17),
> + SG2042_GATE(GATE_CLK_RXU18, "clk_gate_rxu18", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 18),
> + SG2042_GATE(GATE_CLK_RXU19, "clk_gate_rxu19", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 19),
> + SG2042_GATE(GATE_CLK_RXU20, "clk_gate_rxu20", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 20),
> + SG2042_GATE(GATE_CLK_RXU21, "clk_gate_rxu21", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 21),
> + SG2042_GATE(GATE_CLK_RXU22, "clk_gate_rxu22", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 22),
> + SG2042_GATE(GATE_CLK_RXU23, "clk_gate_rxu23", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 23),
> + SG2042_GATE(GATE_CLK_RXU24, "clk_gate_rxu24", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 24),
> + SG2042_GATE(GATE_CLK_RXU25, "clk_gate_rxu25", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 25),
> + SG2042_GATE(GATE_CLK_RXU26, "clk_gate_rxu26", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 26),
> + SG2042_GATE(GATE_CLK_RXU27, "clk_gate_rxu27", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 27),
> + SG2042_GATE(GATE_CLK_RXU28, "clk_gate_rxu28", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 28),
> + SG2042_GATE(GATE_CLK_RXU29, "clk_gate_rxu29", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 29),
> + SG2042_GATE(GATE_CLK_RXU30, "clk_gate_rxu30", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 30),
> + SG2042_GATE(GATE_CLK_RXU31, "clk_gate_rxu31", "clk_gate_rp_cpu_normal",
> + 0, R_RP_RXU_CLK_ENABLE, 31),
> +
> + /* downstream of clk_gate_rp_cpu_normal about mp */
> + SG2042_GATE(GATE_CLK_MP0, "clk_gate_mp0", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP0_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP1, "clk_gate_mp1", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP1_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP2, "clk_gate_mp2", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP2_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP3, "clk_gate_mp3", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP3_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP4, "clk_gate_mp4", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP4_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP5, "clk_gate_mp5", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP5_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP6, "clk_gate_mp6", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP6_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP7, "clk_gate_mp7", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP7_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP8, "clk_gate_mp8", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP8_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP9, "clk_gate_mp9", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP9_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP10, "clk_gate_mp10", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP10_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP11, "clk_gate_mp11", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP11_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP12, "clk_gate_mp12", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP12_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP13, "clk_gate_mp13", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP13_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP14, "clk_gate_mp14", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP14_CONTROL_REG, 0),
> + SG2042_GATE(GATE_CLK_MP15, "clk_gate_mp15", "clk_gate_rp_cpu_normal",
> + CLK_IS_CRITICAL, R_MP15_CONTROL_REG, 0),
> +};
> +
> +#define SG2042_MUX(_id, _name, _parent_names, _flags, _r_select, _shift, _width) { \
> + .hw.init = CLK_HW_INIT_PARENTS( \
> + _name, \
> + _parent_names, \
> + NULL, \
> + _flags), \
> + .id = _id, \
> + .offset_select = _r_select, \
> + .shift = _shift, \
> + .width = _width, \
> + }
> +
> +/*
> + * Note: regarding names for mux clock, "0/1" or "div0/div1" means the
> + * first/second parent input source, not the register value.
> + * For example:
> + * "clk_div_ddr01_0" is the name of Clock divider 0 control of DDR01, and
> + * "clk_gate_ddr01_div0" is the gate clock in front of the "clk_div_ddr01_0",
> + * they are both controlled by register CLKDIVREG27;
> + * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and
> + * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_1",
> + * they are both controlled by register CLKDIVREG28;
> + * While for register value of mux selection, use Clock Select for DDR01’s clock
> + * as example, see CLKSELREG0, bit[2].
> + * 1: Select in_dpll0_clk as clock source, correspondng to the parent input
> + * source from "clk_div_ddr01_0".
> + * 0: Select in_fpll_clk as clock source, corresponding to the parent input
> + * source from "clk_div_ddr01_1".
> + * So we need a table to define the array of register values corresponding to
> + * the parent index and tell CCF about this when registering mux clock.
> + */
> +static const u32 sg2042_mux_table[] = {1, 0};
> +
> +static const char *const clk_mux_ddr01_p[] = {
> + "clk_div_ddr01_0", "clk_div_ddr01_1"};
> +static const char *const clk_mux_ddr23_p[] = {
> + "clk_div_ddr23_0", "clk_div_ddr23_1"};
> +static const char *const clk_mux_rp_cpu_normal_p[] = {
> + "clk_div_rp_cpu_normal_0", "clk_div_rp_cpu_normal_1"};
> +static const char *const clk_mux_axi_ddr_p[] = {
> + "clk_div_axi_ddr_0", "clk_div_axi_ddr_1"};
> +
> +static struct sg2042_mux_clock sg2042_mux_clks[] = {
> + SG2042_MUX(MUX_CLK_DDR01, "clk_mux_ddr01", clk_mux_ddr01_p,
Please use struct clk_parent_data or struct clk_hw directly instead of
string names.
> + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
> + R_CLKSELREG0, 2, 1),
> + SG2042_MUX(MUX_CLK_DDR23, "clk_mux_ddr23", clk_mux_ddr23_p,
> + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
> + R_CLKSELREG0, 3, 1),
> + SG2042_MUX(MUX_CLK_RP_CPU_NORMAL, "clk_mux_rp_cpu_normal", clk_mux_rp_cpu_normal_p,
> + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
> + R_CLKSELREG0, 0, 1),
> + SG2042_MUX(MUX_CLK_AXI_DDR, "clk_mux_axi_ddr", clk_mux_axi_ddr_p,
> + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
> + R_CLKSELREG0, 1, 1),
> +};
> +
> +static DEFINE_SPINLOCK(sg2042_clk_lock);
> +
> +static int sg2042_clk_register_plls(struct sg2042_clk_data *clk_data,
> + struct sg2042_pll_clock pll_clks[],
> + int num_pll_clks)
> +{
> + struct clk_hw *hw;
> + struct sg2042_pll_clock *pll;
> + int i, ret = 0;
> +
> + for (i = 0; i < num_pll_clks; i++) {
> + pll = &pll_clks[i];
> + /* assign these for ops usage during registration */
> + pll->base = clk_data->iobase;
> + pll->lock = &sg2042_clk_lock;
> +
> + hw = &pll->hw;
> + ret = clk_hw_register(NULL, hw);
Use devm_clk_hw_register() and pass a device.
> + if (ret) {
> + pr_err("failed to register clock %s\n", pll->hw.init->name);
> + break;
> + }
> +
> + clk_data->onecell_data.hws[pll->id] = hw;
> + }
> +
> + /* leave unregister to outside if failed */
> + return ret;
> +}
> +
> +static int sg2042_clk_register_divs(struct sg2042_clk_data *clk_data,
> + struct sg2042_divider_clock div_clks[],
> + int num_div_clks)
> +{
> + struct clk_hw *hw;
> + struct sg2042_divider_clock *div;
> + int i, ret = 0;
> +
> + for (i = 0; i < num_div_clks; i++) {
> + div = &div_clks[i];
> +
> + if (div->div_flags & CLK_DIVIDER_HIWORD_MASK) {
> + if (div->width + div->shift > 16) {
> + pr_warn("divider value exceeds LOWORD field\n");
> + ret = -EINVAL;
> + break;
> + }
> + }
> +
> + div->reg = clk_data->iobase + div->offset_ctrl;
> + div->lock = &sg2042_clk_lock;
> +
> + hw = &div->hw;
> + ret = clk_hw_register(NULL, hw);
> + if (ret) {
> + pr_err("failed to register clock %s\n", div->hw.init->name);
> + break;
> + }
> +
> + clk_data->onecell_data.hws[div->id] = hw;
> + }
> +
> + /* leave unregister to outside if failed */
> + return ret;
> +}
> +
> +static int sg2042_clk_register_gates(struct sg2042_clk_data *clk_data,
> + const struct sg2042_gate_clock gate_clks[],
> + int num_gate_clks)
> +{
> + struct clk_hw *hw;
> + const struct sg2042_gate_clock *gate;
> + int i, ret = 0;
> +
> + for (i = 0; i < num_gate_clks; i++) {
> + gate = &gate_clks[i];
> + hw = clk_hw_register_gate(NULL,
> + gate->hw.init->name,
> + gate->hw.init->parent_names[0],
> + gate->hw.init->flags,
> + clk_data->iobase + gate->offset_enable,
> + gate->bit_idx,
> + 0,
> + &sg2042_clk_lock);
> + if (IS_ERR(hw)) {
> + pr_err("failed to register clock %s\n", gate->hw.init->name);
> + ret = PTR_ERR(hw);
> + break;
> + }
> +
> + clk_data->onecell_data.hws[gate->id] = hw;
> + }
> +
> + /* leave unregister to outside if failed */
> + return ret;
> +}
> +
> +static int sg2042_mux_notifier_cb(struct notifier_block *nb,
> + unsigned long event,
> + void *data)
> +{
> + int ret = 0;
> + struct clk_notifier_data *ndata = data;
> + struct clk_hw *hw = __clk_get_hw(ndata->clk);
> + const struct clk_ops *ops = &clk_mux_ops;
> + struct sg2042_mux_clock *mux = to_sg2042_mux_nb(nb);
> +
> + /* To switch to fpll before changing rate and restore after that */
> + if (event == PRE_RATE_CHANGE) {
> + mux->original_index = ops->get_parent(hw);
> +
> + /*
> + * "1" is the array index of the second parent input source of
> + * mux. For SG2042, it's fpll for all mux clocks.
> + * "0" is the array index of the frist parent input source of
> + * mux, For SG2042, it's mpll.
> + * FIXME, any good idea to avoid magic number?
> + */
> + if (mux->original_index == 0)
> + ret = ops->set_parent(hw, 1);
> + } else if (event == POST_RATE_CHANGE) {
> + ret = ops->set_parent(hw, mux->original_index);
> + }
> +
> + return notifier_from_errno(ret);
> +}
> +
> +static int sg2042_clk_register_muxs(struct sg2042_clk_data *clk_data,
> + struct sg2042_mux_clock mux_clks[],
> + int num_mux_clks)
> +{
> + struct clk_hw *hw;
> + struct sg2042_mux_clock *mux;
> + int i, ret = 0;
> +
> + for (i = 0; i < num_mux_clks; i++) {
> + mux = &mux_clks[i];
> +
> + hw = clk_hw_register_mux_table(NULL,
Pass a device and use devm.
> + mux->hw.init->name,
> + mux->hw.init->parent_names,
> + mux->hw.init->num_parents,
> + mux->hw.init->flags,
> + clk_data->iobase + mux->offset_select,
> + mux->shift,
> + BIT(mux->width) - 1,
> + 0,
> + sg2042_mux_table,
> + &sg2042_clk_lock);
> + if (IS_ERR(hw)) {
> + pr_err("failed to register clock %s\n", mux->hw.init->name);
> + ret = PTR_ERR(hw);
> + break;
> + }
> +
> + clk_data->onecell_data.hws[mux->id] = hw;
> +
> + /*
> + * FIXME: Theoretically, we should set parent for the
> + * mux, but seems hardware has done this for us with
> + * default value, so we don't set parent again here.
> + */
> +
> + if (!(mux->hw.init->flags & CLK_MUX_READ_ONLY)) {
> + mux->clk_nb.notifier_call = sg2042_mux_notifier_cb;
> + ret = clk_notifier_register(hw->clk, &mux->clk_nb);
> + if (ret) {
> + pr_err("failed to register clock notifier for %s\n",
> + mux->hw.init->name);
> + goto error_cleanup;
> + }
> + }
> + }
> +
> + return 0;
> +
> +error_cleanup:
> + /* unregister notifier and release the memory allocated */
> + for (i = 0; i < num_mux_clks; i++) {
> + mux = &mux_clks[i];
> +
> + hw = clk_data->onecell_data.hws[mux->id];
> +
> + if (hw)
> + clk_notifier_unregister(hw->clk, &mux->clk_nb);
> + }
> +
> + /* leave clk unregister to outside if failed */
> + return ret;
> +}
> +
> +static int sg2042_init_clkdata(struct platform_device *pdev,
> + int num_clks,
> + struct sg2042_clk_data **pp_clk_data)
> +{
> + struct sg2042_clk_data *clk_data = NULL;
> +
> + clk_data = devm_kzalloc(&pdev->dev,
> + struct_size(clk_data, onecell_data.hws, num_clks),
> + GFP_KERNEL);
> + if (!clk_data)
> + return -ENOMEM;
> +
> + clk_data->iobase = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
Why can't we use devm_platform_ioremap_resource()?
> + if (WARN_ON(IS_ERR(clk_data->iobase)))
> + return PTR_ERR(clk_data->iobase);
> +
> + clk_data->onecell_data.num = num_clks;
> +
> + *pp_clk_data = clk_data;
> +
> + return 0;
> +}
> +
> +static int sg2042_clkgen_probe(struct platform_device *pdev)
> +{
> + struct sg2042_clk_data *clk_data = NULL;
> + int i, ret = 0;
> + int num_clks = 0;
> +
> + num_clks = ARRAY_SIZE(sg2042_div_clks) +
> + ARRAY_SIZE(sg2042_gate_clks) +
> + ARRAY_SIZE(sg2042_mux_clks);
> + if (num_clks == 0) {
> + ret = -EINVAL;
> + goto error_out;
> + }
> +
> + ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
> + if (ret < 0)
> + goto error_out;
> +
> + ret = sg2042_clk_register_divs(clk_data, sg2042_div_clks,
> + ARRAY_SIZE(sg2042_div_clks));
> + if (ret)
> + goto cleanup;
> +
> + ret = sg2042_clk_register_gates(clk_data, sg2042_gate_clks,
> + ARRAY_SIZE(sg2042_gate_clks));
> + if (ret)
> + goto cleanup;
> +
> + ret = sg2042_clk_register_muxs(clk_data, sg2042_mux_clks,
> + ARRAY_SIZE(sg2042_mux_clks));
> + if (ret)
> + goto cleanup;
> +
> + return devm_of_clk_add_hw_provider(&pdev->dev,
> + of_clk_hw_onecell_get,
> + &clk_data->onecell_data);
> +
> +cleanup:
> + for (i = 0; i < num_clks; i++) {
> + if (clk_data->onecell_data.hws[i])
> + clk_hw_unregister(clk_data->onecell_data.hws[i]);
> + }
> +
> +error_out:
> + pr_err("%s failed error number %d\n", __func__, ret);
> + return ret;
> +}
> +
> +static int sg2042_rpgate_probe(struct platform_device *pdev)
> +{
> + struct sg2042_clk_data *clk_data = NULL;
> + int i, ret = 0;
> + int num_clks = 0;
> +
> + num_clks = ARRAY_SIZE(sg2042_gate_rp);
> + if (num_clks == 0) {
> + ret = -EINVAL;
> + goto error_out;
> + }
> +
> + ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
> + if (ret < 0)
> + goto error_out;
> +
> + ret = sg2042_clk_register_gates(clk_data, sg2042_gate_rp,
> + ARRAY_SIZE(sg2042_gate_rp));
> + if (ret)
> + goto cleanup;
> +
> + return devm_of_clk_add_hw_provider(&pdev->dev,
> + of_clk_hw_onecell_get,
> + &clk_data->onecell_data);
> +
> +cleanup:
> + for (i = 0; i < num_clks; i++) {
> + if (clk_data->onecell_data.hws[i])
> + clk_hw_unregister(clk_data->onecell_data.hws[i]);
> + }
> +
> +error_out:
> + pr_err("%s failed error number %d\n", __func__, ret);
> + return ret;
> +}
> +
> +static int sg2042_pll_probe(struct platform_device *pdev)
> +{
> + struct sg2042_clk_data *clk_data = NULL;
> + int i, ret = 0;
> + int num_clks = 0;
> +
> + num_clks = ARRAY_SIZE(sg2042_pll_clks);
> + if (num_clks == 0) {
> + ret = -EINVAL;
> + goto error_out;
> + }
This is dead code, please remove.
> +
> + ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
> + if (ret < 0)
> + goto error_out;
> +
> + ret = sg2042_clk_register_plls(clk_data, sg2042_pll_clks,
> + ARRAY_SIZE(sg2042_pll_clks));
> + if (ret)
> + goto cleanup;
> +
> + return devm_of_clk_add_hw_provider(&pdev->dev,
> + of_clk_hw_onecell_get,
> + &clk_data->onecell_data);
> +
> +cleanup:
> + for (i = 0; i < num_clks; i++) {
> + if (clk_data->onecell_data.hws[i])
> + clk_hw_unregister(clk_data->onecell_data.hws[i]);
> + }
> +
> +error_out:
> + pr_err("%s failed error number %d\n", __func__, ret);
> + return ret;
> +}
> +
> +static const struct of_device_id sg2042_clkgen_match[] = {
> + { .compatible = "sophgo,sg2042-clkgen" },
> + { /* sentinel */ }
> +};
> +
> +static struct platform_driver sg2042_clkgen_driver = {
> + .probe = sg2042_clkgen_probe,
> + .driver = {
> + .name = "clk-sophgo-sg2042-clkgen",
> + .of_match_table = sg2042_clkgen_match,
> + .suppress_bind_attrs = true,
> + },
> +};
> +builtin_platform_driver(sg2042_clkgen_driver);
> +
> +static const struct of_device_id sg2042_rpgate_match[] = {
> + { .compatible = "sophgo,sg2042-rpgate" },
> + { /* sentinel */ }
> +};
> +
> +static struct platform_driver sg2042_rpgate_driver = {
> + .probe = sg2042_rpgate_probe,
> + .driver = {
> + .name = "clk-sophgo-sg2042-rpgate",
> + .of_match_table = sg2042_rpgate_match,
> + .suppress_bind_attrs = true,
> + },
> +};
> +builtin_platform_driver(sg2042_rpgate_driver);
> +
> +static const struct of_device_id sg2042_pll_match[] = {
> + { .compatible = "sophgo,sg2042-pll" },
> + { /* sentinel */ }
> +};
> +
> +static struct platform_driver sg2042_pll_driver = {
> + .probe = sg2042_pll_probe,
> + .driver = {
> + .name = "clk-sophgo-sg2042-pll",
> + .of_match_table = sg2042_pll_match,
> + .suppress_bind_attrs = true,
> + },
> +};
> +builtin_platform_driver(sg2042_pll_driver);
> diff --git a/drivers/clk/sophgo/clk-sophgo-sg2042.h b/drivers/clk/sophgo/clk-sophgo-sg2042.h
> new file mode 100644
> index 000000000000..407fec6f3f02
> --- /dev/null
> +++ b/drivers/clk/sophgo/clk-sophgo-sg2042.h
> @@ -0,0 +1,216 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef __CLK_SOPHGO_SG2042_H
> +#define __CLK_SOPHGO_SG2042_H
> +
> +/* Registers defined in SYS_CTRL */
> +#define R_PLL_BEGIN 0xC0
> +#define R_PLL_STAT (0xC0 - R_PLL_BEGIN)
> +#define R_PLL_CLKEN_CONTROL (0xC4 - R_PLL_BEGIN)
> +#define R_MPLL_CONTROL (0xE8 - R_PLL_BEGIN)
> +#define R_FPLL_CONTROL (0xF4 - R_PLL_BEGIN)
> +#define R_DPLL0_CONTROL (0xF8 - R_PLL_BEGIN)
> +#define R_DPLL1_CONTROL (0xFC - R_PLL_BEGIN)
> +
> +#define R_SYSGATE_BEGIN 0x0368
> +#define R_RP_RXU_CLK_ENABLE (0x0368 - R_SYSGATE_BEGIN)
> +#define R_MP0_STATUS_REG (0x0380 - R_SYSGATE_BEGIN)
> +#define R_MP0_CONTROL_REG (0x0384 - R_SYSGATE_BEGIN)
> +#define R_MP1_STATUS_REG (0x0388 - R_SYSGATE_BEGIN)
> +#define R_MP1_CONTROL_REG (0x038C - R_SYSGATE_BEGIN)
> +#define R_MP2_STATUS_REG (0x0390 - R_SYSGATE_BEGIN)
> +#define R_MP2_CONTROL_REG (0x0394 - R_SYSGATE_BEGIN)
> +#define R_MP3_STATUS_REG (0x0398 - R_SYSGATE_BEGIN)
> +#define R_MP3_CONTROL_REG (0x039C - R_SYSGATE_BEGIN)
> +#define R_MP4_STATUS_REG (0x03A0 - R_SYSGATE_BEGIN)
> +#define R_MP4_CONTROL_REG (0x03A4 - R_SYSGATE_BEGIN)
> +#define R_MP5_STATUS_REG (0x03A8 - R_SYSGATE_BEGIN)
> +#define R_MP5_CONTROL_REG (0x03AC - R_SYSGATE_BEGIN)
> +#define R_MP6_STATUS_REG (0x03B0 - R_SYSGATE_BEGIN)
> +#define R_MP6_CONTROL_REG (0x03B4 - R_SYSGATE_BEGIN)
> +#define R_MP7_STATUS_REG (0x03B8 - R_SYSGATE_BEGIN)
> +#define R_MP7_CONTROL_REG (0x03BC - R_SYSGATE_BEGIN)
> +#define R_MP8_STATUS_REG (0x03C0 - R_SYSGATE_BEGIN)
> +#define R_MP8_CONTROL_REG (0x03C4 - R_SYSGATE_BEGIN)
> +#define R_MP9_STATUS_REG (0x03C8 - R_SYSGATE_BEGIN)
> +#define R_MP9_CONTROL_REG (0x03CC - R_SYSGATE_BEGIN)
> +#define R_MP10_STATUS_REG (0x03D0 - R_SYSGATE_BEGIN)
> +#define R_MP10_CONTROL_REG (0x03D4 - R_SYSGATE_BEGIN)
> +#define R_MP11_STATUS_REG (0x03D8 - R_SYSGATE_BEGIN)
> +#define R_MP11_CONTROL_REG (0x03DC - R_SYSGATE_BEGIN)
> +#define R_MP12_STATUS_REG (0x03E0 - R_SYSGATE_BEGIN)
> +#define R_MP12_CONTROL_REG (0x03E4 - R_SYSGATE_BEGIN)
> +#define R_MP13_STATUS_REG (0x03E8 - R_SYSGATE_BEGIN)
> +#define R_MP13_CONTROL_REG (0x03EC - R_SYSGATE_BEGIN)
> +#define R_MP14_STATUS_REG (0x03F0 - R_SYSGATE_BEGIN)
> +#define R_MP14_CONTROL_REG (0x03F4 - R_SYSGATE_BEGIN)
> +#define R_MP15_STATUS_REG (0x03F8 - R_SYSGATE_BEGIN)
> +#define R_MP15_CONTROL_REG (0x03FC - R_SYSGATE_BEGIN)
> +
> +/* Registers defined in CLOCK */
> +#define R_CLKENREG0 0x00
> +#define R_CLKENREG1 0x04
> +#define R_CLKSELREG0 0x20
> +#define R_CLKDIVREG0 0x40
> +#define R_CLKDIVREG1 0x44
> +#define R_CLKDIVREG2 0x48
> +#define R_CLKDIVREG3 0x4C
> +#define R_CLKDIVREG4 0x50
> +#define R_CLKDIVREG5 0x54
> +#define R_CLKDIVREG6 0x58
> +#define R_CLKDIVREG7 0x5C
> +#define R_CLKDIVREG8 0x60
> +#define R_CLKDIVREG9 0x64
> +#define R_CLKDIVREG10 0x68
> +#define R_CLKDIVREG11 0x6C
> +#define R_CLKDIVREG12 0x70
> +#define R_CLKDIVREG13 0x74
> +#define R_CLKDIVREG14 0x78
> +#define R_CLKDIVREG15 0x7C
> +#define R_CLKDIVREG16 0x80
> +#define R_CLKDIVREG17 0x84
> +#define R_CLKDIVREG18 0x88
> +#define R_CLKDIVREG19 0x8C
> +#define R_CLKDIVREG20 0x90
> +#define R_CLKDIVREG21 0x94
> +#define R_CLKDIVREG22 0x98
> +#define R_CLKDIVREG23 0x9C
> +#define R_CLKDIVREG24 0xA0
> +#define R_CLKDIVREG25 0xA4
> +#define R_CLKDIVREG26 0xA8
> +#define R_CLKDIVREG27 0xAC
> +#define R_CLKDIVREG28 0xB0
> +#define R_CLKDIVREG29 0xB4
> +#define R_CLKDIVREG30 0xB8
> +
> +/*
> + * Common data of clock-controller
> + * Note: this structure will be used both by clkgen & sysclk.
> + * @iobase: base address of clock-controller
> + * @onecell_data: used for adding providers.
> + */
> +struct sg2042_clk_data {
> + void __iomem *iobase;
> + struct clk_hw_onecell_data onecell_data;
> +};
> +
> +/*
> + * PLL clock
> + * @hw: clk_hw for initialization
> + * @id: used to map clk_onecell_data
> + * @base: used for readl/writel.
> + * **NOTE**: PLL registers are all in SYS_CTRL!
> + * @lock: spinlock to protect register access, modification
> + * of frequency can only be served one at the time.
> + * @offset_status: offset of pll status registers
> + * @offset_enable: offset of pll enable registers
> + * @offset_ctrl: offset of pll control registers
> + * @shift_status_lock: shift of XXX_LOCK in pll status register
> + * @shift_status_updating: shift of UPDATING_XXX in pll status register
> + * @shift_enable: shift of XXX_CLK_EN in pll enable register
> + */
> +struct sg2042_pll_clock {
> + struct clk_hw hw;
> +
> + unsigned int id;
> + void __iomem *base;
> + /* protect register access */
> + spinlock_t *lock;
> +
> + u32 offset_status;
> + u32 offset_enable;
> + u32 offset_ctrl;
> + u8 shift_status_lock;
> + u8 shift_status_updating;
> + u8 shift_enable;
> +};
> +
> +#define to_sg2042_pll_clk(_hw) container_of(_hw, struct sg2042_pll_clock, hw)
> +
> +/*
> + * Divider clock
> + * @hw: clk_hw for initialization
> + * @id: used to map clk_onecell_data
> + * @reg: used for readl/writel.
> + * **NOTE**: DIV registers are ALL in CLOCK!
> + * @lock: spinlock to protect register access, modification of
> + * frequency can only be served one at the time
> + * @offset_ctrl: offset of divider control registers
> + * @shift: shift of "Clock Divider Factor" in divider control register
> + * @width: width of "Clock Divider Factor" in divider control register
> + * @div_flags: private flags for this clock, not for framework-specific
> + * @initval: In the divider control register, we can configure whether
> + * to use the value of "Clock Divider Factor" or just use
> + * the initial value pre-configured by IC. BIT[3] controls
> + * this and by default (value is 0), means initial value
> + * is used.
> + * **NOTE** that we cannot read the initial value (default
> + * value when poweron) and default value of "Clock Divider
> + * Factor" is zero, which I think is a hardware design flaw
> + * and should be sync-ed with the initial value. So in
> + * software we have to add a configuration item (initval)
> + * to manually configure this value and use it when BIT[3]
> + * is zero.
Do you use the init clk_op for this?
> + */
> +struct sg2042_divider_clock {
> + struct clk_hw hw;
> +
> + unsigned int id;
> +
> + void __iomem *reg;
> + /* protect register access */
> + spinlock_t *lock;
> +
> + unsigned long offset_ctrl;
> + u8 shift;
> + u8 width;
> + u8 div_flags;
> + u32 initval;
> +};
> +
> +#define to_sg2042_clk_divider(_hw) \
> + container_of(_hw, struct sg2042_divider_clock, hw)
> +
> +/*
> + * Gate clock
> + * @hw: clk_hw for initialization
> + * @id: used to map clk_onecell_data
> + * @offset_enable: offset of gate enable registers
> + * @bit_idx: which bit in the register controls gating of this clock
> + */
> +struct sg2042_gate_clock {
> + struct clk_hw hw;
> +
> + unsigned int id;
> +
> + unsigned long offset_enable;
Usually we use a u32 or a shorter size so that the member width is
unchanged on different CPU architecture.
> + u8 bit_idx;
> +};
> +
> +/*
> + * Mux clock
Please use kernel doc. See https://docs.kernel.org/doc-guide/kernel-doc.html
> + * @hw: clk_hw for initialization
> + * @id: used to map clk_onecell_data
> + * @offset_select: offset of mux selection registers
> + * **NOTE**: MUX registers are ALL in CLOCK!
> + * @shift: shift of "Clock Select" in mux selection register
Is "Clock select" actually @offset_select?
> + * @width: width of "Clock Select" in mux selection register
> + * @clk_nb: used for notification
> + * @original_index: set by notifier callback
> + */
> +struct sg2042_mux_clock {
> + struct clk_hw hw;
> +
> + unsigned int id;
> +
> + unsigned long offset_select;
> + u8 shift;
> + u8 width;
> +
> + struct notifier_block clk_nb;
> + u8 original_index;
> +};
> +
^ permalink raw reply
* Re: [PATCH v7 3/3] dmaengine: add driver for Sophgo CV18XX/SG200X dmamux
From: kernel test robot @ 2024-04-11 4:14 UTC (permalink / raw)
To: Inochi Amaoto, Vinod Koul, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Chen Wang, Paul Walmsley, Palmer Dabbelt, Albert Ou
Cc: llvm, oe-kbuild-all, Jisheng Zhang, Liu Gui, Jingbao Qiu, dlan,
dmaengine, devicetree, linux-kernel, linux-riscv
In-Reply-To: <IA1PR20MB495310B8E4D7A6705A112004BB062@IA1PR20MB4953.namprd20.prod.outlook.com>
Hi Inochi,
kernel test robot noticed the following build warnings:
[auto build test WARNING on vkoul-dmaengine/next]
[also build test WARNING on robh/for-next krzk-dt/for-next linus/master v6.9-rc3 next-20240410]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Inochi-Amaoto/dt-bindings-dmaengine-Add-dma-multiplexer-for-CV18XX-SG200X-series-SoC/20240410-092207
base: https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git next
patch link: https://lore.kernel.org/r/IA1PR20MB495310B8E4D7A6705A112004BB062%40IA1PR20MB4953.namprd20.prod.outlook.com
patch subject: [PATCH v7 3/3] dmaengine: add driver for Sophgo CV18XX/SG200X dmamux
config: riscv-allyesconfig (https://download.01.org/0day-ci/archive/20240411/202404111148.YVXpdPke-lkp@intel.com/config)
compiler: clang version 19.0.0git (https://github.com/llvm/llvm-project 8b3b4a92adee40483c27f26c478a384cd69c6f05)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240411/202404111148.YVXpdPke-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202404111148.YVXpdPke-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from drivers/dma/cv1800-dmamux.c:8:
In file included from include/linux/of_dma.h:14:
In file included from include/linux/dmaengine.h:12:
In file included from include/linux/scatterlist.h:8:
In file included from include/linux/mm.h:2208:
include/linux/vmstat.h:508:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
508 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~ ^
509 | item];
| ~~~~
include/linux/vmstat.h:515:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
515 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~ ^
516 | NR_VM_NUMA_EVENT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~~
include/linux/vmstat.h:522:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
522 | return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
| ~~~~~~~~~~~ ^ ~~~
include/linux/vmstat.h:527:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
527 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~ ^
528 | NR_VM_NUMA_EVENT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~~
include/linux/vmstat.h:536:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
536 | return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~ ^
537 | NR_VM_NUMA_EVENT_ITEMS +
| ~~~~~~~~~~~~~~~~~~~~~~
>> drivers/dma/cv1800-dmamux.c:191:22: warning: unused variable 'dma_master' [-Wunused-variable]
191 | struct device_node *dma_master;
| ^~~~~~~~~~
6 warnings generated.
vim +/dma_master +191 drivers/dma/cv1800-dmamux.c
183
184 static int cv1800_dmamux_probe(struct platform_device *pdev)
185 {
186 struct device *dev = &pdev->dev;
187 struct device_node *mux_node = dev->of_node;
188 struct cv1800_dmamux_data *data;
189 struct cv1800_dmamux_map *tmp;
190 struct device *parent = dev->parent;
> 191 struct device_node *dma_master;
192 struct regmap *regmap = NULL;
193 unsigned int i;
194
195 if (!parent)
196 return -ENODEV;
197
198 regmap = device_node_to_regmap(parent->of_node);
199 if (IS_ERR(regmap))
200 return PTR_ERR(regmap);
201
202 data = devm_kmalloc(dev, sizeof(*data), GFP_KERNEL);
203 if (!data)
204 return -ENOMEM;
205
206 spin_lock_init(&data->lock);
207 init_llist_head(&data->free_maps);
208
209 for (i = 0; i <= MAX_DMA_CH_ID; i++) {
210 tmp = devm_kmalloc(dev, sizeof(*tmp), GFP_KERNEL);
211 if (!tmp) {
212 /* It is OK for not allocating all channel */
213 dev_warn(dev, "can not allocate channel %u\n", i);
214 continue;
215 }
216
217 init_llist_node(&tmp->node);
218 tmp->channel = i;
219 llist_add(&tmp->node, &data->free_maps);
220 }
221
222 /* if no channel is allocated, the probe must fail */
223 if (llist_empty(&data->free_maps))
224 return -ENOMEM;
225
226 data->regmap = regmap;
227 data->dmarouter.dev = dev;
228 data->dmarouter.route_free = cv1800_dmamux_free;
229
230 platform_set_drvdata(pdev, data);
231
232 return of_dma_router_register(mux_node,
233 cv1800_dmamux_route_allocate,
234 &data->dmarouter);
235 }
236
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH v3 0/6] Add Loongson-2k0500 and Loongson-2k2000 clock support
From: Huacai Chen @ 2024-04-11 4:31 UTC (permalink / raw)
To: Binbin Zhou
Cc: Binbin Zhou, Huacai Chen, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Yinbo Zhu,
loongson-kernel, linux-clk, devicetree, Xuerui Wang, loongarch
In-Reply-To: <cover.1712731524.git.zhoubinbin@loongson.cn>
For the whole series,
Acked-by: Huacai Chen <chenhuacai@loongson.cn>
On Thu, Apr 11, 2024 at 10:58 AM Binbin Zhou <zhoubinbin@loongson.cn> wrote:
>
> Hi all:
>
> As we know, the Loongson-2K family of SoCs (ls2k0500/ls2k1000/ls2k2000)
> have a similar clock structure, and I support them to be configured with
> different parameters (e.g., register offsets, etc.).
>
> To make it easier to add support for different SoCs, I refactored the
> original driver to make the whole driver as understandable as possible.
>
> Briefly, I have divided all clocks into three categories according to
> their properties and their parent clocks: Independent PLLs, clocks based
> on frequency scales, and clock dividers.
>
> Thanks.
>
> ----
> V3:
> - Remove the dts-related patches and update dts at once after all relevant
> drivers are complete.
> patch(1/6):
> - Drop unsuitable comments.
>
> Link to V2:
> https://lore.kernel.org/all/cover.1711504700.git.zhoubinbin@loongson.cn/
>
> V2:
> patch(1/8):
> - Drop LOONGSON2_CLK_END, for it is not a binding.
> patch(1/8)(3/8)(5/8):
> - Add Acked-by tag from Conor, Thanks.
>
> Link to V1:
> https://lore.kernel.org/all/cover.1710926402.git.zhoubinbin@loongson.cn/
>
> Binbin Zhou (6):
> dt-bindings: clock: Add Loongson-2K expand clock index
> clk: clk-loongson2: Refactor driver for adding new platforms
> dt-bindings: clock: loongson2: Add Loongson-2K0500 compatible
> clk: clk-loongson2: Add Loongson-2K0500 clock support
> dt-bindings: clock: loongson2: Add Loongson-2K2000 compatible
> clk: clk-loongson2: Add Loongson-2K2000 clock support
>
> .../bindings/clock/loongson,ls2k-clk.yaml | 4 +-
> drivers/clk/clk-loongson2.c | 549 ++++++++++--------
> include/dt-bindings/clock/loongson,ls2k-clk.h | 54 +-
> 3 files changed, 329 insertions(+), 278 deletions(-)
>
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH v23 3/3] clk: npcm8xx: add clock controller
From: Stephen Boyd @ 2024-04-11 4:51 UTC (permalink / raw)
To: Tomer Maimon
Cc: benjaminfair, joel, krzysztof.kozlowski+dt, mturquette, robh+dt,
tali.perry1, venture, yuenn, openbmc, linux-clk, linux-kernel,
devicetree
In-Reply-To: <CAP6Zq1htKQ5v0tH9HGRejnKwJ5ZauUWG_CzYUKegkVL4Ek8UxA@mail.gmail.com>
Quoting Tomer Maimon (2024-02-29 13:29:46)
> Hi Stephen,
>
> Thanks for your reply.
>
> On Thu, 29 Feb 2024 at 00:48, Stephen Boyd <sboyd@kernel.org> wrote:
> >
> > Quoting Tomer Maimon (2024-02-25 10:00:35)
> > > Hi Stephen,
> > >
> > > On Thu, 22 Feb 2024 at 07:58, Stephen Boyd <sboyd@kernel.org> wrote:
> > > >
> > > > Quoting Tomer Maimon (2024-01-31 10:26:53)
> > > > > +
> > > > > +static unsigned long npcm8xx_clk_div_get_parent(struct clk_hw *hw,
> > > > > + unsigned long parent_rate)
> > > > > +{
> > > > > + struct npcm8xx_clk *div = to_npcm8xx_clk(hw);
> > > > > + unsigned int val;
> > > > > +
> > > > > + regmap_read(div->clk_regmap, div->offset, &val);
> > > > > + val = val >> div->shift;
> > > > > + val &= clk_div_mask(div->width);
> > > > > +
> > > > > + return divider_recalc_rate(hw, parent_rate, val, NULL, div->flags,
> > > > > + div->width);
> > > > > +}
> > > > > +
> > > > > +static const struct clk_ops npcm8xx_clk_div_ops = {
> > > > > + .recalc_rate = npcm8xx_clk_div_get_parent,
> > > > > +};
> > > > > +
> > > > > +static int npcm8xx_clk_probe(struct platform_device *pdev)
> > > > > +{
> > > > > + struct device_node *parent_np = of_get_parent(pdev->dev.of_node);
> > > >
> > > > The parent of this device is not a syscon.
> > > Once I have registered the map that handles both reset and the clock
> > > in general is syscon, this is why we will modify the DTS so the clock
> > > and the reset will be under syscon father node
> > > sysctrl: system-controller@f0801000 {
> > > compatible = "syscon", "simple-mfd";
> > > reg = <0x0 0xf0801000 0x0 0x1000>;
> > >
> > > rstc: reset-controller {
> > > compatible = "nuvoton,npcm845-reset";
> > > reg = <0x0 0xf0801000 0x0 0xC4>;
> > > #reset-cells = <2>;
> > > nuvoton,sysgcr = <&gcr>;
> > > };
> > >
> > > clk: clock-controller {
> > > compatible = "nuvoton,npcm845-clk";
> > > #clock-cells = <1>;
> > > clocks = <&refclk>;
> > > clock-names = "refclk";
> > > };
> > > };
> > > You can see other drivers that using the same method like
> > > https://elixir.bootlin.com/linux/v6.8-rc5/source/Documentation/devicetree/bindings/clock/socionext,uniphier-clock.yaml
> >
> > You will need a similar file like
> > Documentation/devicetree/bindings/soc/socionext/socionext,uniphier-perictrl.yaml
> > then to describe the child nodes.
> I can do it.
> >
> > Socionext may not be the best example to follow. I generally try to
> > avoid syscon and simply put #reset-cells and #clock-cells in the node
> If I remove syscon I can't use syscon_node_to_regmap function, What
> should I use If I remove syscon? auxiliary bus? something else?
You should use auxiliary bus. You can make a regmap in the parent
driver and pass that to the child auxiliary devices still.
> > for the device. You can use the auxiliary bus to register drivers for
> > clk and reset and put them into the resepective driver directories.
> I little bit confused, what is an auxiliary bus to register drivers,
> can you provide me an example?
$ git grep -l auxiliary_ -- drivers/clk/
drivers/clk/microchip/clk-mpfs.c
drivers/clk/starfive/clk-starfive-jh7110-sys.c
You can decide to make either the clk or the reset driver the "main"
driver that registers the other auxiliary devices. Either way the DT
binding has a single node instead of one per logical driver in the
kernel.
> > Avoid syscon means random drivers can't reach into the device with a
> > regmap handle and read/write registers that they're not supposed to.
> Indeed, but the drivers could use the reset and clock memory map only
> if the module is also a child node.
>
> Please let me know what is your preferred way to handle it:
> 1. stick with syscon and upstream-defined documentation for the rst clk syscon.
> 2. avoid syscon and use an auxiliary bus, appreciate if you could give
> me an example of how it should be done.
> 3. Avoid sycon and handle it differently.
I prefer 2
^ permalink raw reply
* [PATCH] ARM: dts: aspeed: Remove Facebook Cloudripper dts
From: rentao.bupt @ 2024-04-11 4:56 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Andrew Jeffery, devicetree, linux-arm-kernel, linux-aspeed,
linux-kernel, taoren
Cc: Tao Ren
From: Tao Ren <rentao.bupt@gmail.com>
Remove Facebook Cloudripper dts because the switch platform is not
actively maintained (all the units are deprecated).
Signed-off-by: Tao Ren <rentao.bupt@gmail.com>
---
arch/arm/boot/dts/aspeed/Makefile | 1 -
.../aspeed-bmc-facebook-cloudripper.dts | 544 ------------------
2 files changed, 545 deletions(-)
delete mode 100644 arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cloudripper.dts
diff --git a/arch/arm/boot/dts/aspeed/Makefile b/arch/arm/boot/dts/aspeed/Makefile
index d3ac20e316d0..1c0e08c9ed3e 100644
--- a/arch/arm/boot/dts/aspeed/Makefile
+++ b/arch/arm/boot/dts/aspeed/Makefile
@@ -13,7 +13,6 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-bytedance-g220a.dtb \
aspeed-bmc-delta-ahe50dc.dtb \
aspeed-bmc-facebook-bletchley.dtb \
- aspeed-bmc-facebook-cloudripper.dtb \
aspeed-bmc-facebook-cmm.dtb \
aspeed-bmc-facebook-elbert.dtb \
aspeed-bmc-facebook-fuji.dtb \
diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cloudripper.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cloudripper.dts
deleted file mode 100644
index d49328fa487a..000000000000
--- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-cloudripper.dts
+++ /dev/null
@@ -1,544 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-// Copyright (c) 2020 Facebook Inc.
-
-/dts-v1/;
-
-#include <dt-bindings/leds/common.h>
-#include "ast2600-facebook-netbmc-common.dtsi"
-
-/ {
- model = "Facebook Cloudripper BMC";
- compatible = "facebook,cloudripper-bmc", "aspeed,ast2600";
-
- aliases {
- /*
- * PCA9548 (1-0070) provides 8 channels connecting to
- * SMB (Switch Main Board).
- */
- i2c16 = &imux16;
- i2c17 = &imux17;
- i2c18 = &imux18;
- i2c19 = &imux19;
- i2c20 = &imux20;
- i2c21 = &imux21;
- i2c22 = &imux22;
- i2c23 = &imux23;
-
- /*
- * PCA9548 (2-0070) provides 8 channels connecting to
- * SCM (System Controller Module).
- */
- i2c24 = &imux24;
- i2c25 = &imux25;
- i2c26 = &imux26;
- i2c27 = &imux27;
- i2c28 = &imux28;
- i2c29 = &imux29;
- i2c30 = &imux30;
- i2c31 = &imux31;
-
- /*
- * PCA9548 (3-0070) provides 8 channels connecting to
- * SMB (Switch Main Board).
- */
- i2c32 = &imux32;
- i2c33 = &imux33;
- i2c34 = &imux34;
- i2c35 = &imux35;
- i2c36 = &imux36;
- i2c37 = &imux37;
- i2c38 = &imux38;
- i2c39 = &imux39;
-
- /*
- * PCA9548 (8-0070) provides 8 channels connecting to
- * PDB (Power Delivery Board).
- */
- i2c40 = &imux40;
- i2c41 = &imux41;
- i2c42 = &imux42;
- i2c43 = &imux43;
- i2c44 = &imux44;
- i2c45 = &imux45;
- i2c46 = &imux46;
- i2c47 = &imux47;
-
- /*
- * PCA9548 (15-0076) provides 8 channels connecting to
- * FCM (Fan Controller Module).
- */
- i2c48 = &imux48;
- i2c49 = &imux49;
- i2c50 = &imux50;
- i2c51 = &imux51;
- i2c52 = &imux52;
- i2c53 = &imux53;
- i2c54 = &imux54;
- i2c55 = &imux55;
- };
-
- spi_gpio: spi {
- num-chipselects = <2>;
- cs-gpios = <&gpio0 ASPEED_GPIO(X, 0) GPIO_ACTIVE_LOW>,
- <&gpio0 ASPEED_GPIO(X, 1) GPIO_ACTIVE_HIGH>;
-
- eeprom@1 {
- compatible = "atmel,at93c46d";
- spi-max-frequency = <250000>;
- data-size = <16>;
- spi-cs-high;
- reg = <1>;
- };
- };
-};
-
-&ehci1 {
- status = "okay";
-};
-
-/*
- * "mdio1" is connected to the MDC/MDIO interface of the on-board
- * management switch (whose ports are connected to BMC, Host and front
- * panel ethernet port).
- */
-&mdio1 {
- status = "okay";
-};
-
-&mdio3 {
- status = "okay";
-
- ethphy1: ethernet-phy@13 {
- compatible = "ethernet-phy-ieee802.3-c22";
- reg = <0x0d>;
- };
-};
-
-&mac3 {
- status = "okay";
- phy-mode = "rgmii";
- phy-handle = <ðphy1>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_rgmii4_default>;
-};
-
-&i2c0 {
- multi-master;
- bus-frequency = <1000000>;
-};
-
-&i2c1 {
- /*
- * PCA9548 (1-0070) provides 8 channels connecting to SMB (Switch
- * Main Board).
- */
- i2c-mux@70 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
- i2c-mux-idle-disconnect;
-
- imux16: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- imux17: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- imux18: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- imux19: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- imux20: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- imux21: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- imux22: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- imux23: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
- };
-};
-
-&i2c2 {
- /*
- * PCA9548 (2-0070) provides 8 channels connecting to SCM (System
- * Controller Module).
- */
- i2c-mux@70 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
- i2c-mux-idle-disconnect;
-
- imux24: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- imux25: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- imux26: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- imux27: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- imux28: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- imux29: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- imux30: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- imux31: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
- };
-};
-
-&i2c3 {
- /*
- * PCA9548 (3-0070) provides 8 channels connecting to SMB (Switch
- * Main Board).
- */
- i2c-mux@70 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
- i2c-mux-idle-disconnect;
-
- imux32: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- imux33: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- imux34: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- imux35: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- imux36: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- imux37: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- imux38: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- imux39: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
- };
-};
-
-&i2c6 {
- lp5012@14 {
- compatible = "ti,lp5012";
- reg = <0x14>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- multi-led@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- color = <LED_COLOR_ID_MULTI>;
- function = LED_FUNCTION_ACTIVITY;
- label = "sys";
-
- led@0 {
- reg = <0>;
- color = <LED_COLOR_ID_RED>;
- };
-
- led@1 {
- reg = <1>;
- color = <LED_COLOR_ID_BLUE>;
- };
-
- led@2 {
- reg = <2>;
- color = <LED_COLOR_ID_GREEN>;
- };
- };
-
- multi-led@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- color = <LED_COLOR_ID_MULTI>;
- function = LED_FUNCTION_ACTIVITY;
- label = "fan";
-
- led@0 {
- reg = <0>;
- color = <LED_COLOR_ID_RED>;
- };
-
- led@1 {
- reg = <1>;
- color = <LED_COLOR_ID_BLUE>;
- };
-
- led@2 {
- reg = <2>;
- color = <LED_COLOR_ID_GREEN>;
- };
- };
-
- multi-led@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- color = <LED_COLOR_ID_MULTI>;
- function = LED_FUNCTION_ACTIVITY;
- label = "psu";
-
- led@0 {
- reg = <0>;
- color = <LED_COLOR_ID_RED>;
- };
-
- led@1 {
- reg = <1>;
- color = <LED_COLOR_ID_BLUE>;
- };
-
- led@2 {
- reg = <2>;
- color = <LED_COLOR_ID_GREEN>;
- };
- };
-
- multi-led@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- color = <LED_COLOR_ID_MULTI>;
- function = LED_FUNCTION_ACTIVITY;
- label = "scm";
-
- led@0 {
- reg = <0>;
- color = <LED_COLOR_ID_RED>;
- };
-
- led@1 {
- reg = <1>;
- color = <LED_COLOR_ID_BLUE>;
- };
-
- led@2 {
- reg = <2>;
- color = <LED_COLOR_ID_GREEN>;
- };
- };
- };
-};
-
-&i2c8 {
- /*
- * PCA9548 (8-0070) provides 8 channels connecting to PDB (Power
- * Delivery Board).
- */
- i2c-mux@70 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
- i2c-mux-idle-disconnect;
-
- imux40: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- imux41: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- imux42: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- imux43: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- imux44: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- imux45: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- imux46: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- imux47: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
-
- };
-};
-
-&i2c15 {
- /*
- * PCA9548 (15-0076) provides 8 channels connecting to FCM (Fan
- * Controller Module).
- */
- i2c-mux@76 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x76>;
- i2c-mux-idle-disconnect;
-
- imux48: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- imux49: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- imux50: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- imux51: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- imux52: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- imux53: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- imux54: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- imux55: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
- };
-};
--
2.44.0
^ permalink raw reply related
* Re: [PATCH] iio: industrialio-core: look for aliases to request device index
From: Dominique Martinet @ 2024-04-11 5:11 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Jonathan Cameron, David Lechner, Krzysztof Kozlowski,
Syunya Ohshio, Guido Günther, Lars-Peter Clausen,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-iio,
devicetree, linux-kernel
In-Reply-To: <20240401174756.0000786a@Huawei.com>
Jonathan Cameron wrote on Mon, Apr 01, 2024 at 05:47:56PM +0100:
> Good luck. If you have time it might be good to hear what you end up
> with!
Just a quick follow-up since you asked -- given we manage our own kernel
that already has its share of patches and it's not something
user-visible we'll stick with the aliases approach for this kernel to
make identifiers static.
(and I'm adding labels for meticulous users, but not expecting it to be
used in practice, it'll mostly be used in automated testing to make sure
the number doesn't change on our end)
The rationale was as per my previous mails that paths in
/sys/devices/platform have changed in the past so we'd rather not rely
on these being set in stone, and while a new symlink would have been
workable it's a user-noticeable change so we've prefered just pinning
the device numbers.
I'm always reluctant to take in more "in house" patches in our tree but
in this case it's "simple enough" (death by thousands paper cut?), and
we'll rediscuss this if/when another upstream solution shows up.
Thanks a lot for your time thinking it through and discussing it though,
that was appreciated!
(Jonathan and everyone else involved)
--
Dominique
^ permalink raw reply
* Re: [PATCH v2 2/4] dt-bindings: PCI: mediatek,mt7621: add missing child node reg
From: Krzysztof Kozlowski @ 2024-04-11 6:01 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Hector Martin,
Sven Peter, Alyssa Rosenzweig, Ray Jui, Scott Branden,
Broadcom internal kernel review list, Florian Fainelli,
Jim Quinlan, Nicolas Saenz Julienne, Will Deacon, Linus Walleij,
Srikanth Thokala, Ryder Lee, Jianjun Wang, Sergio Paracuellos,
Matthias Brugger, AngeloGioacchino Del Regno, Daire McNamara,
Bjorn Andersson, Konrad Dybcio, Marek Vasut, Yoshihiro Shimoda,
Shawn Lin, Heiko Stuebner, Jingoo Han, Gustavo Pimentel,
Manivannan Sadhasivam, Bharat Kumar Gogada, Michal Simek,
Geert Uytterhoeven, Magnus Damm, Neil Armstrong, Mark Kettenis,
Tom Joseph, Ahmad Zainie, Jiaxun Yang, Kishon Vijay Abraham I,
Thippeswamy Havalige, linux-pci, devicetree, linux-kernel, asahi,
linux-arm-kernel, linux-rpi-kernel, linux-mediatek, linux-arm-msm,
linux-renesas-soc, linux-rockchip
In-Reply-To: <20240410212638.GA2159326@bhelgaas>
On 10/04/2024 23:26, Bjorn Helgaas wrote:
> On Wed, Apr 10, 2024 at 08:15:19PM +0200, Krzysztof Kozlowski wrote:
>> MT7621 PCI host bridge has children which apparently are also PCI host
>> bridges, at least that's what the binding suggest.
>
> What does it even mean for a PCI host bridge to have a child that is
> also a PCI host bridge?
>
> Does this mean a driver binds to the "parent" host bridge, enumerates
> the PCI devices below it, and finds a "child" host bridge?
I think the question should be towards Mediatek folks. I don't know what
this hardware is exactly, just looks like pci-pci-bridge. The driver
calls the children host bridges as "ports".
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v5 0/2] Samsung Galaxy Z Fold5 initial support
From: Krzysztof Kozlowski @ 2024-04-11 6:03 UTC (permalink / raw)
To: serdeliuk, Bjorn Andersson, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley
Cc: linux-arm-msm, devicetree, linux-kernel
In-Reply-To: <20240410-samsung-galaxy-zfold5-q5q-v5-0-9311ee9a55f7@yahoo.com>
On 10/04/2024 23:28, Alexandru Marc Serdeliuc via B4 Relay wrote:
> This documents and add intial dts support for Samsung Galaxy Z Fold5 (samsung,q5q)
> which is a foldable phone by Samsung based on the sm8550 SoC.
>
> ChangeLog
>
> - v5
> . Added ChangeLog
> . Added missing Acked-by tags in their respective section in ChangeLog
Where? I cannot find anything.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/2] media: dt-bindings: i2c: add Giantec GT97xx VCM driver
From: Krzysztof Kozlowski @ 2024-04-11 6:05 UTC (permalink / raw)
To: Zhi Mao (毛智), conor@kernel.org
Cc: heiko@sntech.de, linux-kernel@vger.kernel.org,
laurent.pinchart+renesas@ideasonboard.com, yunkec@chromium.org,
linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org,
hdegoede@redhat.com, bingbu.cao@intel.com,
paul.elder@ideasonboard.com, devicetree@vger.kernel.org,
andy.shevchenko@gmail.com, mchehab@kernel.org,
Shengnan Wang (王圣男),
Yaya Chang (張雅清), p.zabel@pengutronix.de,
alain.volmat@foss.st.com, conor+dt@kernel.org,
sakari.ailus@linux.intel.com, robh@kernel.org,
hverkuil-cisco@xs4all.nl, tomi.valkeinen@ideasonboard.com,
linux-arm-kernel@lists.infradead.org, matthias.bgg@gmail.com,
mehdi.djait@bootlin.com, krzk+dt@kernel.org,
angelogioacchino.delregno@collabora.com, 10572168@qq.com
In-Reply-To: <5317cb9b01cf5668837ad7ccdcb9eb72b95d98d6.camel@mediatek.com>
On 11/04/2024 04:04, Zhi Mao (毛智) wrote:
> Hi Conor,
>
> Thanks for your review.
>
> On Wed, 2024-04-10 at 12:27 +0100, Conor Dooley wrote:
>>>
>>>
>> Hey,
>>
>> On Wed, Apr 10, 2024 at 06:40:01PM +0800, Zhi Mao wrote:
>>> b/Documentation/devicetree/bindings/media/i2c/giantec,gt97xx.yaml
>>> @@ -0,0 +1,91 @@
>>> +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
>>> +# Copyright (c) 2020 MediaTek Inc.
>>> +%YAML 1.2
>>> +---
>>> +$id: http://devicetree.org/schemas/media/i2c/giantec,gt97xx.yaml#
>>
>> Filename patching compatible please.
>>
>>
> Sorry, I don't catch this point.
> Can you explain more details?
s/patching/matching/
Use compatible as filename.
>>>
>>>
>>> +
>>> + giantec,aac-mode:
>>> + description:
>>> + Indication of AAC mode select.
>>> + $ref: /schemas/types.yaml#/definitions/uint32
>>> + enum:
>>> + - 1 # AAC2 mode(operation time# 0.48 x Tvib)
>>> + - 2 # AAC3 mode(operation time# 0.70 x Tvib)
>>> + - 3 # AAC4 mode(operation time# 0.75 x Tvib)
>>> + - 5 # AAC8 mode(operation time# 1.13 x Tvib)
>>
>> I dislike these enum based properties and I would rather this either
>> be
>> the values themselves (0.48, 0.70 etc).
>>
>>> +
>>> + giantec,aac-timing:
>>> + description:
>>> + Number of AAC Timing count that controlled by one 6-bit
>>> period of
>>> + vibration register AACT[5:0], the unit of which is 100 us.
>>
>> Then the property should be in a standard unit of time, not "random"
>> hex
>> numbers that correspond to register values.
>>
>>>
>>> + giantec,clock-presc:
>>> + description:
>>> + Indication of VCM internal clock dividing rate select, as
>>> one multiple
>>> + factor to calculate VCM ring periodic time Tvib.
>>> + $ref: /schemas/types.yaml#/definitions/uint32
>>> + enum:
>>> + - 0 # Dividing Rate - 2
>>> + - 1 # Dividing Rate - 1
>>> + - 2 # Dividing Rate - 1/2
>>> + - 3 # Dividing Rate - 1/4
>>> + - 4 # Dividing Rate - 8
>>> + - 5 # Dividing Rate - 4
>>
>> Same here, you should not need these comments explaining the values,
>> use
>> an enum with meaningful values please.
>>
> About "aac-mode/aac-timing/clock-presc", we test this driver with
> default settings accroding to SPEC and VCM works well, so I will not
> export these property in YMAL and let driver use default settings.
> How do you think about it?
You must remove them from the driver code in such case.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 1/2] dt-bindings: remoteproc: mediatek: Support MT8188 dual-core SCP
From: Krzysztof Kozlowski @ 2024-04-11 6:06 UTC (permalink / raw)
To: olivia.wen, Bjorn Andersson, Mathieu Poirier, Rob Herring
Cc: Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Tinghan Shen, linux-remoteproc,
devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Project_Global_Chrome_Upstream_Group, jason-ch.chen, yaya.chang,
teddy.chen
In-Reply-To: <20240411033750.6476-2-olivia.wen@mediatek.com>
On 11/04/2024 05:37, olivia.wen wrote:
> Under different applications, the MT8188 SCP can be used as single-core
> or dual-core.
>
> Signed-off-by: olivia.wen <olivia.wen@mediatek.com>
Are you sure you use full name, not email login as name?
> ---
> Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> index 507f98f..7e7b567 100644
> --- a/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.yaml
> @@ -22,7 +22,7 @@ properties:
> - mediatek,mt8192-scp
> - mediatek,mt8195-scp
> - mediatek,mt8195-scp-dual
> -
> + - mediatek,mt8188-scp-dual
Missing blank line, misordered.
> reg:
> description:
> Should contain the address ranges for memory regions SRAM, CFG, and,
> @@ -195,6 +195,7 @@ allOf:
> compatible:
> enum:
> - mediatek,mt8195-scp-dual
> + - mediatek,mt8188-scp-dual
Again, keep the order.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 2/2] remoteproc: mediatek: Support MT8188 SCP core 1
From: Krzysztof Kozlowski @ 2024-04-11 6:07 UTC (permalink / raw)
To: olivia.wen, Bjorn Andersson, Mathieu Poirier, Rob Herring
Cc: Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Tinghan Shen, linux-remoteproc,
devicetree, linux-kernel, linux-arm-kernel, linux-mediatek,
Project_Global_Chrome_Upstream_Group, jason-ch.chen, yaya.chang,
teddy.chen
In-Reply-To: <20240411033750.6476-3-olivia.wen@mediatek.com>
On 11/04/2024 05:37, olivia.wen wrote:
> +};
> +
> static const struct of_device_id mtk_scp_of_match[] = {
> { .compatible = "mediatek,mt8183-scp", .data = &mt8183_of_data },
> { .compatible = "mediatek,mt8186-scp", .data = &mt8186_of_data },
> @@ -1323,6 +1362,7 @@ static const struct of_device_id mtk_scp_of_match[] = {
> { .compatible = "mediatek,mt8192-scp", .data = &mt8192_of_data },
> { .compatible = "mediatek,mt8195-scp", .data = &mt8195_of_data },
> { .compatible = "mediatek,mt8195-scp-dual", .data = &mt8195_of_data_cores },
> + { .compatible = "mediatek,mt8188-scp-dual", .data = &mt8188_of_data_cores },
Why do you add new entries to the end? Look at the list first.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/4] dt-bindings: PCI: mediatek,mt7621: add missing child node reg
From: Sergio Paracuellos @ 2024-04-11 6:13 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Bjorn Helgaas, Bjorn Helgaas, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Hector Martin, Sven Peter, Alyssa Rosenzweig,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Florian Fainelli, Jim Quinlan, Nicolas Saenz Julienne,
Will Deacon, Linus Walleij, Srikanth Thokala, Ryder Lee,
Jianjun Wang, Matthias Brugger, AngeloGioacchino Del Regno,
Daire McNamara, Bjorn Andersson, Konrad Dybcio, Marek Vasut,
Yoshihiro Shimoda, Shawn Lin, Heiko Stuebner, Jingoo Han,
Gustavo Pimentel, Manivannan Sadhasivam, Bharat Kumar Gogada,
Michal Simek, Geert Uytterhoeven, Magnus Damm, Neil Armstrong,
Mark Kettenis, Tom Joseph, Ahmad Zainie, Jiaxun Yang,
Kishon Vijay Abraham I, Thippeswamy Havalige, linux-pci,
devicetree, linux-kernel, asahi, linux-arm-kernel,
linux-rpi-kernel, linux-mediatek, linux-arm-msm,
linux-renesas-soc, linux-rockchip
In-Reply-To: <458ce909-0616-487d-b4bd-42b58d059198@linaro.org>
Hi,
On Thu, Apr 11, 2024 at 8:01 AM Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
>
> On 10/04/2024 23:26, Bjorn Helgaas wrote:
> > On Wed, Apr 10, 2024 at 08:15:19PM +0200, Krzysztof Kozlowski wrote:
> >> MT7621 PCI host bridge has children which apparently are also PCI host
> >> bridges, at least that's what the binding suggest.
> >
> > What does it even mean for a PCI host bridge to have a child that is
> > also a PCI host bridge?
> >
> > Does this mean a driver binds to the "parent" host bridge, enumerates
> > the PCI devices below it, and finds a "child" host bridge?
Yes, that is exactly what you can see on enumeration.
The following is a typical boot trace where all bridges has a device also below:
[ 20.927280] mt7621-pci 1e140000.pcie: host bridge /pcie@1e140000 ranges:
[ 20.940675] mt7621-pci 1e140000.pcie: No bus range found for
/pcie@1e140000, using [bus 00-ff]
[ 20.958228] mt7621-pci 1e140000.pcie: MEM
0x0060000000..0x006fffffff -> 0x0060000000
[ 20.974566] mt7621-pci 1e140000.pcie: IO
0x001e160000..0x001e16ffff -> 0x0000000000
[ 21.369711] mt7621-pci 1e140000.pcie: PCIE0 enabled
[ 21.379316] mt7621-pci 1e140000.pcie: PCIE1 enabled
[ 21.389140] mt7621-pci 1e140000.pcie: PCIE2 enabled
[ 21.399014] PCI coherence region base: 0x60000000, mask/settings: 0xf0000002
[ 21.413343] mt7621-pci 1e140000.pcie: PCI host bridge to bus 0000:00
[ 21.425952] pci_bus 0000:00: root bus resource [bus 00-ff]
[ 21.437023] pci_bus 0000:00: root bus resource [mem 0x60000000-0x6fffffff]
[ 21.450657] pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
[ 21.462960] pci 0000:00:00.0: [0e8d:0801] type 01 class 0x060400
[ 21.474832] pci 0000:00:00.0: reg 0x10: [mem 0x00000000-0x7fffffff]
[ 21.487255] pci 0000:00:00.0: reg 0x14: [mem 0x00000000-0x0000ffff]
[ 21.499807] pci 0000:00:00.0: supports D1
[ 21.507625] pci 0000:00:00.0: PME# supported from D0 D1 D3hot
[ 21.519923] pci 0000:00:01.0: [0e8d:0801] type 01 class 0x060400
[ 21.531827] pci 0000:00:01.0: reg 0x10: [mem 0x00000000-0x7fffffff]
[ 21.544225] pci 0000:00:01.0: reg 0x14: [mem 0x00000000-0x0000ffff]
[ 21.556773] pci 0000:00:01.0: supports D1
[ 21.564621] pci 0000:00:01.0: PME# supported from D0 D1 D3hot
[ 21.576823] pci 0000:00:02.0: [0e8d:0801] type 01 class 0x060400
[ 21.588726] pci 0000:00:02.0: reg 0x10: [mem 0x00000000-0x7fffffff]
[ 21.601128] pci 0000:00:02.0: reg 0x14: [mem 0x00000000-0x0000ffff]
[ 21.613668] pci 0000:00:02.0: supports D1
[ 21.621520] pci 0000:00:02.0: PME# supported from D0 D1 D3hot
[ 21.634850] pci 0000:00:00.0: bridge configuration invalid ([bus
00-00]), reconfiguring
[ 21.650699] pci 0000:00:01.0: bridge configuration invalid ([bus
00-00]), reconfiguring
[ 21.666571] pci 0000:00:02.0: bridge configuration invalid ([bus
00-00]), reconfiguring
[ 21.682825] pci 0000:01:00.0: [1b21:0611] type 00 class 0x010185
[ 21.694707] pci 0000:01:00.0: reg 0x10: [io 0x0000-0x0007]
[ 21.705725] pci 0000:01:00.0: reg 0x14: [io 0x0000-0x0003]
[ 21.716789] pci 0000:01:00.0: reg 0x18: [io 0x0000-0x0007]
[ 21.727843] pci 0000:01:00.0: reg 0x1c: [io 0x0000-0x0003]
[ 21.738907] pci 0000:01:00.0: reg 0x20: [io 0x0000-0x000f]
[ 21.749979] pci 0000:01:00.0: reg 0x24: [mem 0x00000000-0x000001ff]
[ 21.762568] pci 0000:01:00.0: 2.000 Gb/s available PCIe bandwidth,
limited by 2.5 GT/s PCIe x1 link at 0000:00:00.0 (capable of 4.000
Gb/s with 5.0 GT/s PCIe x1 link)
[ 21.819657] pci 0000:00:00.0: PCI bridge to [bus 01-ff]
[ 21.829966] pci 0000:00:00.0: bridge window [io 0x0000-0x0fff]
[ 21.842054] pci 0000:00:00.0: bridge window [mem 0x00000000-0x000fffff]
[ 21.855532] pci 0000:00:00.0: bridge window [mem
0x00000000-0x000fffff pref]
[ 21.869874] pci_bus 0000:01: busn_res: [bus 01-ff] end is updated to 01
[ 21.883352] pci 0000:02:00.0: [1b21:0611] type 00 class 0x010185
[ 21.895230] pci 0000:02:00.0: reg 0x10: [io 0x0000-0x0007]
[ 21.906256] pci 0000:02:00.0: reg 0x14: [io 0x0000-0x0003]
[ 21.917309] pci 0000:02:00.0: reg 0x18: [io 0x0000-0x0007]
[ 21.928373] pci 0000:02:00.0: reg 0x1c: [io 0x0000-0x0003]
[ 21.939428] pci 0000:02:00.0: reg 0x20: [io 0x0000-0x000f]
[ 21.950500] pci 0000:02:00.0: reg 0x24: [mem 0x00000000-0x000001ff]
[ 21.963094] pci 0000:02:00.0: 2.000 Gb/s available PCIe bandwidth,
limited by 2.5 GT/s PCIe x1 link at 0000:00:01.0 (capable of 4.000
Gb/s with 5.0 GT/s PCIe x1 link)
[ 22.029662] pci 0000:00:01.0: PCI bridge to [bus 02-ff]
[ 22.039993] pci 0000:00:01.0: bridge window [io 0x0000-0x0fff]
[ 22.052063] pci 0000:00:01.0: bridge window [mem 0x00000000-0x000fffff]
[ 22.065538] pci 0000:00:01.0: bridge window [mem
0x00000000-0x000fffff pref]
[ 22.079886] pci_bus 0000:02: busn_res: [bus 02-ff] end is updated to 02
[ 22.093352] pci 0000:03:00.0: [1b21:0611] type 00 class 0x010185
[ 22.105233] pci 0000:03:00.0: reg 0x10: [io 0x0000-0x0007]
[ 22.116249] pci 0000:03:00.0: reg 0x14: [io 0x0000-0x0003]
[ 22.127313] pci 0000:03:00.0: reg 0x18: [io 0x0000-0x0007]
[ 22.138367] pci 0000:03:00.0: reg 0x1c: [io 0x0000-0x0003]
[ 22.149451] pci 0000:03:00.0: reg 0x20: [io 0x0000-0x000f]
[ 22.160503] pci 0000:03:00.0: reg 0x24: [mem 0x00000000-0x000001ff]
[ 22.173091] pci 0000:03:00.0: 2.000 Gb/s available PCIe bandwidth,
limited by 2.5 GT/s PCIe x1 link at 0000:00:02.0 (capable of 4.000
Gb/s with 5.0 GT/s PCIe x1 link)
[ 22.239653] pci 0000:00:02.0: PCI bridge to [bus 03-ff]
[ 22.249973] pci 0000:00:02.0: bridge window [io 0x0000-0x0fff]
[ 22.262045] pci 0000:00:02.0: bridge window [mem 0x00000000-0x000fffff]
[ 22.275524] pci 0000:00:02.0: bridge window [mem
0x00000000-0x000fffff pref]
[ 22.289870] pci_bus 0000:03: busn_res: [bus 03-ff] end is updated to 03
[ 22.303080] pci 0000:00:00.0: BAR 0: no space for [mem size 0x80000000]
[ 22.316129] pci 0000:00:00.0: BAR 0: failed to assign [mem size 0x80000000]
[ 22.329956] pci 0000:00:01.0: BAR 0: no space for [mem size 0x80000000]
[ 22.343081] pci 0000:00:01.0: BAR 0: failed to assign [mem size 0x80000000]
[ 22.356912] pci 0000:00:02.0: BAR 0: no space for [mem size 0x80000000]
[ 22.370053] pci 0000:00:02.0: BAR 0: failed to assign [mem size 0x80000000]
[ 22.383870] pci 0000:00:00.0: BAR 8: assigned [mem 0x60000000-0x600fffff]
[ 22.397349] pci 0000:00:00.0: BAR 9: assigned [mem
0x60100000-0x601fffff pref]
[ 22.411692] pci 0000:00:01.0: BAR 8: assigned [mem 0x60200000-0x602fffff]
[ 22.425165] pci 0000:00:01.0: BAR 9: assigned [mem
0x60300000-0x603fffff pref]
[ 22.439522] pci 0000:00:02.0: BAR 8: assigned [mem 0x60400000-0x604fffff]
[ 22.452991] pci 0000:00:02.0: BAR 9: assigned [mem
0x60500000-0x605fffff pref]
[ 22.467328] pci 0000:00:00.0: BAR 1: assigned [mem 0x60600000-0x6060ffff]
[ 22.480814] pci 0000:00:01.0: BAR 1: assigned [mem 0x60610000-0x6061ffff]
[ 22.494303] pci 0000:00:02.0: BAR 1: assigned [mem 0x60620000-0x6062ffff]
[ 22.507766] pci 0000:00:00.0: BAR 7: assigned [io 0x0000-0x0fff]
[ 22.519861] pci 0000:00:01.0: BAR 7: assigned [io 0x1000-0x1fff]
[ 22.531960] pci 0000:00:02.0: BAR 7: assigned [io 0x2000-0x2fff]
[ 22.544068] pci 0000:01:00.0: BAR 5: assigned [mem 0x60000000-0x600001ff]
[ 22.557548] pci 0000:01:00.0: BAR 4: assigned [io 0x0000-0x000f]
[ 22.569635] pci 0000:01:00.0: BAR 0: assigned [io 0x0010-0x0017]
[ 22.581726] pci 0000:01:00.0: BAR 2: assigned [io 0x0018-0x001f]
[ 22.593827] pci 0000:01:00.0: BAR 1: assigned [io 0x0020-0x0023]
[ 22.605917] pci 0000:01:00.0: BAR 3: assigned [io 0x0024-0x0027]
[ 22.618030] pci 0000:00:00.0: PCI bridge to [bus 01]
[ 22.627859] pci 0000:00:00.0: bridge window [io 0x0000-0x0fff]
[ 22.639956] pci 0000:00:00.0: bridge window [mem 0x60000000-0x600fffff]
[ 22.653437] pci 0000:00:00.0: bridge window [mem
0x60100000-0x601fffff pref]
[ 22.667785] pci 0000:02:00.0: BAR 5: assigned [mem 0x60200000-0x602001ff]
[ 22.681268] pci 0000:02:00.0: BAR 4: assigned [io 0x1000-0x100f]
[ 22.693359] pci 0000:02:00.0: BAR 0: assigned [io 0x1010-0x1017]
[ 22.705450] pci 0000:02:00.0: BAR 2: assigned [io 0x1018-0x101f]
[ 22.717552] pci 0000:02:00.0: BAR 1: assigned [io 0x1020-0x1023]
[ 22.729654] pci 0000:02:00.0: BAR 3: assigned [io 0x1024-0x1027]
[ 22.741746] pci 0000:00:01.0: PCI bridge to [bus 02]
[ 22.751587] pci 0000:00:01.0: bridge window [io 0x1000-0x1fff]
[ 22.763678] pci 0000:00:01.0: bridge window [mem 0x60200000-0x602fffff]
[ 22.777161] pci 0000:00:01.0: bridge window [mem
0x60300000-0x603fffff pref]
[ 22.791515] pci 0000:03:00.0: BAR 5: assigned [mem 0x60400000-0x604001ff]
[ 22.804991] pci 0000:03:00.0: BAR 4: assigned [io 0x2000-0x200f]
[ 22.817084] pci 0000:03:00.0: BAR 0: assigned [io 0x2010-0x2017]
[ 22.829175] pci 0000:03:00.0: BAR 2: assigned [io 0x2018-0x201f]
[ 22.841274] pci 0000:03:00.0: BAR 1: assigned [io 0x2020-0x2023]
[ 22.853379] pci 0000:03:00.0: BAR 3: assigned [io 0x2024-0x2027]
[ 22.865472] pci 0000:00:02.0: PCI bridge to [bus 03]
[ 22.875312] pci 0000:00:02.0: bridge window [io 0x2000-0x2fff]
[ 22.887403] pci 0000:00:02.0: bridge window [mem 0x60400000-0x604fffff]
>
> I think the question should be towards Mediatek folks. I don't know what
> this hardware is exactly, just looks like pci-pci-bridge. The driver
> calls the children host bridges as "ports".
You can see the topology here in my first driver submit cover letter
message [0].
Thanks,
Sergio Paracuellos
[0]: https://lore.kernel.org/all/CAMhs-H-BA+KzEwuDPzcmrDPdgJBFA2XdYTBvT4R4MEOUB=WQ1g@mail.gmail.com/t/
>
> Best regards,
> Krzysztof
>
^ permalink raw reply
* Re: [PATCH 02/11] dt-bindings: clock: mobileye,eyeq5-clk: add EyeQ6L and EyeQ6H
From: Krzysztof Kozlowski @ 2024-04-11 6:14 UTC (permalink / raw)
To: Théo Lebrun, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Michael Turquette, Stephen Boyd, Philipp Zabel, Linus Walleij
Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
Tawfik Bayouk
In-Reply-To: <20240410-mbly-olb-v1-2-335e496d7be3@bootlin.com>
On 10/04/2024 19:12, Théo Lebrun wrote:
> Add bindings describing EyeQ6L and EyeQ6H clock controllers.
> Add constants to index clocks.
>
> Bindings are conditional for two reasons:
> - Some compatibles expose a single clock; they do not take clock cells.
> - All compatibles take a PLLs resource, not all take others (aimed at
> divider clocks). Those that only take a resource for PLLs do not
> require named resources.
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
> .../bindings/clock/mobileye,eyeq5-clk.yaml | 103 ++++++++++++++++++---
> MAINTAINERS | 2 +
> include/dt-bindings/clock/mobileye,eyeq5-clk.h | 21 +++++
> 3 files changed, 113 insertions(+), 13 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml b/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml
> index 2d4f2cde1e58..a1651fcce258 100644
> --- a/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml
> +++ b/Documentation/devicetree/bindings/clock/mobileye,eyeq5-clk.yaml
> @@ -4,12 +4,13 @@
> $id: http://devicetree.org/schemas/clock/mobileye,eyeq5-clk.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Mobileye EyeQ5 clock controller
> +title: Mobileye EyeQ clock controller
>
> description:
> - The EyeQ5 clock controller handles 10 read-only PLLs derived from the main
> - crystal clock. It also exposes one divider clock, a child of one of the PLLs.
> - Its registers live in a shared region called OLB.
> + EyeQ clock controllers expose read-only PLLs derived from main crystal clock.
> + Some also expose divider clocks, children of specific PLLs. Its registers
> + live in a shared region called OLB. EyeQ5 and EyeQ6L have a single OLB
> + instance while EyeQ6H have seven, leading to seven clock controllers.
>
> maintainers:
> - Grégory Clement <gregory.clement@bootlin.com>
> @@ -18,18 +19,23 @@ maintainers:
>
> properties:
> compatible:
> - const: mobileye,eyeq5-clk
> + enum:
> + - mobileye,eyeq5-clk
> + - mobileye,eyeq6l-clk
> + - mobileye,eyeq6h-central-clk
> + - mobileye,eyeq6h-west-clk
> + - mobileye,eyeq6h-east-clk
> + - mobileye,eyeq6h-south-clk
> + - mobileye,eyeq6h-ddr0-clk
> + - mobileye,eyeq6h-ddr1-clk
> + - mobileye,eyeq6h-acc-clk
>
> - reg:
> - maxItems: 2
> + reg: true
No, you must leave widest constraints here.
>
> - reg-names:
> - items:
> - - const: plls
> - - const: ospi
> + reg-names: true
No, you must leave widest constraints here.
>
> "#clock-cells":
> - const: 1
> + enum: [0, 1]
Looks like you squash here quite different devices...
>
> clocks:
> maxItems: 1
> @@ -43,9 +49,80 @@ properties:
> required:
> - compatible
> - reg
> - - reg-names
> - "#clock-cells"
> - clocks
> - clock-names
>
> +allOf:
> + # "mobileye,eyeq5-clk" provides:
> + # - PLLs and,
> + # - One divider clock related to ospi.
> + - if:
> + properties:
> + compatible:
> + const: mobileye,eyeq5-clk
> + then:
> + properties:
> + reg:
> + minItems: 2
> + maxItems: 2
> + reg-names:
> + minItems: 2
> + maxItems: 2
So any name is now valid? Like "yellow-pony"?
> + items:
> + enum: [ plls, ospi ]
> + required:
> + - reg-names
> +
> + # "mobileye,eyeq6h-south-clk" provides:
> + # - PLLs and,
> + # - Four divider clocks related to emmc, ospi and tsu.
> + - if:
> + properties:
> + compatible:
> + const: mobileye,eyeq6h-south-clk
> + then:
> + properties:
> + reg:
> + minItems: 4
> + maxItems: 4
> + reg-names:
> + minItems: 4
> + maxItems: 4
> + items:
> + enum: [ plls, emmc, ospi, tsu ]
> + required:
> + - reg-names
> +
> + # Other compatibles only provide PLLs. Do not ask for named resources.
> + - if:
> + not:
> + required:
> + - reg-names
> + then:
> + properties:
> + reg:
> + minItems: 1
> + maxItems: 1
No, just restrict properly reg per variant.
> + reg-names: false
That's redundant. Drop entire if.
> +
> + # Some compatibles provide a single clock; they do not take a clock cell.
> + - if:
> + properties:
> + compatible:
> + enum:
> + - mobileye,eyeq6h-central-clk
> + - mobileye,eyeq6h-west-clk
> + - mobileye,eyeq6h-east-clk
> + - mobileye,eyeq6h-ddr0-clk
> + - mobileye,eyeq6h-ddr1-clk
> + then:
> + properties:
> + "#clock-cells":
> + const: 0
Wait, so you define device-per-clock? That's a terrible idea. We also
discussed it many times and it was rejected many times.
You have one device, not 5.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 03/11] dt-bindings: reset: mobileye,eyeq5-reset: add EyeQ6L and EyeQ6H
From: Krzysztof Kozlowski @ 2024-04-11 6:14 UTC (permalink / raw)
To: Théo Lebrun, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Michael Turquette, Stephen Boyd, Philipp Zabel, Linus Walleij
Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
Tawfik Bayouk
In-Reply-To: <20240410-mbly-olb-v1-3-335e496d7be3@bootlin.com>
On 10/04/2024 19:12, Théo Lebrun wrote:
> Add bindings for EyeQ6L and EyeQ6H reset controllers.
>
> Some controllers host a single domain, meaning a single cell is enough.
> We do not enforce reg-names for such nodes.
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
> .../bindings/reset/mobileye,eyeq5-reset.yaml | 88 ++++++++++++++++++----
> MAINTAINERS | 1 +
> 2 files changed, 74 insertions(+), 15 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml b/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml
> index 062b4518347b..799bcf15bed9 100644
> --- a/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml
> +++ b/Documentation/devicetree/bindings/reset/mobileye,eyeq5-reset.yaml
> @@ -4,11 +4,13 @@
> $id: http://devicetree.org/schemas/reset/mobileye,eyeq5-reset.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Mobileye EyeQ5 reset controller
> +title: Mobileye EyeQ reset controller
>
> description:
> - The EyeQ5 reset driver handles three reset domains. Its registers live in a
> - shared region called OLB.
> + EyeQ reset controller handles one or more reset domains. They live in shared
> + regions called OLB. EyeQ5 and EyeQ6L host one OLB each, each with one reset
> + instance. EyeQ6H hosts 7 OLB regions; three of those (west, east,
> + accelerator) host reset controllers. West and east are duplicates.
>
> maintainers:
> - Grégory Clement <gregory.clement@bootlin.com>
> @@ -17,27 +19,83 @@ maintainers:
>
> properties:
> compatible:
> - const: mobileye,eyeq5-reset
> + enum:
> + - mobileye,eyeq5-reset
> + - mobileye,eyeq6l-reset
> + - mobileye,eyeq6h-we-reset
> + - mobileye,eyeq6h-acc-reset
>
> - reg:
> - maxItems: 3
> + reg: true
Same mistakes. Please open existing bindings with multiple variants,
e.g. some Qualcomm, and take a look how it is done there.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH 08/11] MIPS: mobileye: eyeq5: add OLB syscon node
From: Krzysztof Kozlowski @ 2024-04-11 6:15 UTC (permalink / raw)
To: Théo Lebrun, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Michael Turquette, Stephen Boyd, Philipp Zabel, Linus Walleij
Cc: linux-mips, devicetree, linux-kernel, linux-clk, linux-gpio,
Vladimir Kondratiev, Gregory CLEMENT, Thomas Petazzoni,
Tawfik Bayouk
In-Reply-To: <20240410-mbly-olb-v1-8-335e496d7be3@bootlin.com>
On 10/04/2024 19:12, Théo Lebrun wrote:
> The OLB ("Other Logic Block") is a syscon region hosting clock, reset
> and pin controllers. It contains registers such as I2C speed mode that
> need to be accessible by other nodes.
>
> Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
> ---
> arch/mips/boot/dts/mobileye/eyeq5.dtsi | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/arch/mips/boot/dts/mobileye/eyeq5.dtsi b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
> index 6cc5980e2fa1..e82d2a57f6da 100644
> --- a/arch/mips/boot/dts/mobileye/eyeq5.dtsi
> +++ b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
> @@ -100,6 +100,14 @@ uart2: serial@a00000 {
> clock-names = "uartclk", "apb_pclk";
> };
>
> + olb: system-controller@e00000 {
> + compatible = "mobileye,eyeq5-olb", "syscon", "simple-mfd";
> + reg = <0 0xe00000 0x0 0x400>;
> + ranges = <0x0 0x0 0xe00000 0x400>;
> + #address-cells = <1>;
> + #size-cells = <1>;
Do not add incomplete node. ranges, address/size-cells are incorrect in
this context and you will have warnings.
Add complete node, so these properties make sense.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/4] dt-bindings: rtc: lpc32xx-rtc: convert to dtschema
From: Krzysztof Kozlowski @ 2024-04-11 6:17 UTC (permalink / raw)
To: Alexandre Belloni, Javier Carrasco
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Jiaxun Yang,
Vladimir Zapolskiy, Joel Stanley, Andrew Jeffery, Maxime Coquelin,
Alexandre Torgue, linux-rtc, devicetree, linux-kernel,
linux-arm-kernel, linux-aspeed, linux-stm32
In-Reply-To: <202404102043571b7450b5@mail.local>
On 10/04/2024 22:43, Alexandre Belloni wrote:
> On 10/04/2024 17:55:34+0200, Javier Carrasco wrote:
>> Convert existing binding to dtschema to support validation.
>>
>> Add the undocumented 'clocks' property.
>>
>> Signed-off-by: Javier Carrasco <javier.carrasco.cruz@gmail.com>
>> ---
>> .../devicetree/bindings/rtc/lpc32xx-rtc.txt | 15 --------
>> .../devicetree/bindings/rtc/nxp,lpc32xx-rtc.yaml | 41 ++++++++++++++++++++++
>> 2 files changed, 41 insertions(+), 15 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/rtc/lpc32xx-rtc.txt b/Documentation/devicetree/bindings/rtc/lpc32xx-rtc.txt
>> deleted file mode 100644
>> index a87a1e9bc060..000000000000
>> --- a/Documentation/devicetree/bindings/rtc/lpc32xx-rtc.txt
>> +++ /dev/null
>> @@ -1,15 +0,0 @@
>> -* NXP LPC32xx SoC Real Time Clock controller
>> -
>> -Required properties:
>> -- compatible: must be "nxp,lpc3220-rtc"
>> -- reg: physical base address of the controller and length of memory mapped
>> - region.
>> -- interrupts: The RTC interrupt
>> -
>> -Example:
>> -
>> - rtc@40024000 {
>> - compatible = "nxp,lpc3220-rtc";
>> - reg = <0x40024000 0x1000>;
>> - interrupts = <52 0>;
>> - };
>> diff --git a/Documentation/devicetree/bindings/rtc/nxp,lpc32xx-rtc.yaml b/Documentation/devicetree/bindings/rtc/nxp,lpc32xx-rtc.yaml
>> new file mode 100644
>> index 000000000000..62ddeef961e9
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/rtc/nxp,lpc32xx-rtc.yaml
>> @@ -0,0 +1,41 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/rtc/nxp,lpc32xx-rtc.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: NXP LPC32xx SoC Real Time Clock
>> +
>> +maintainers:
>> + - Javier Carrasco <javier.carrasco.cruz@gmail.com>
>> +
>> +allOf:
>> + - $ref: rtc.yaml#
>> +
>> +properties:
>> + compatible:
>> + const: nxp,lpc3220-rtc
>> +
>> + reg:
>> + maxItems: 1
>> +
>> + interrupts:
>> + maxItems: 1
>> +
>> + clocks:
>> + maxItems: 1
>
> As I explained the clock doesn't really exist, there is no control over
> it, it is a fixed 32768 Hz crystal, there is no point in describing it
> as this is already the input clock of the SoC.
That's common for many SoCs but it is still (at least for them) input to
the RTC. On some SoC boards 32 kHz is controllable.
But if you think it is not correct here, then we should drop it from DTS.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/4] dt-bindings: PCI: mediatek,mt7621: add missing child node reg
From: Krzysztof Kozlowski @ 2024-04-11 6:20 UTC (permalink / raw)
To: Sergio Paracuellos
Cc: Bjorn Helgaas, Bjorn Helgaas, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Hector Martin, Sven Peter, Alyssa Rosenzweig,
Ray Jui, Scott Branden, Broadcom internal kernel review list,
Florian Fainelli, Jim Quinlan, Nicolas Saenz Julienne,
Will Deacon, Linus Walleij, Srikanth Thokala, Ryder Lee,
Jianjun Wang, Matthias Brugger, AngeloGioacchino Del Regno,
Daire McNamara, Bjorn Andersson, Konrad Dybcio, Marek Vasut,
Yoshihiro Shimoda, Shawn Lin, Heiko Stuebner, Jingoo Han,
Gustavo Pimentel, Manivannan Sadhasivam, Bharat Kumar Gogada,
Michal Simek, Geert Uytterhoeven, Magnus Damm, Neil Armstrong,
Mark Kettenis, Tom Joseph, Ahmad Zainie, Jiaxun Yang,
Kishon Vijay Abraham I, Thippeswamy Havalige, linux-pci,
devicetree, linux-kernel, asahi, linux-arm-kernel,
linux-rpi-kernel, linux-mediatek, linux-arm-msm,
linux-renesas-soc, linux-rockchip
In-Reply-To: <CAMhs-H82Ymc=isxu6AX4_s1QnNpSSNt74--ED1j7JxpzE=eCRg@mail.gmail.com>
On 11/04/2024 08:13, Sergio Paracuellos wrote:
>
>>
>> I think the question should be towards Mediatek folks. I don't know what
>> this hardware is exactly, just looks like pci-pci-bridge. The driver
>> calls the children host bridges as "ports".
>
> You can see the topology here in my first driver submit cover letter
> message [0].
>
Useful diagram, thanks. It would be great if you could add it to the
binding description.
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH] MAINTAINERS: adjust DRM DRIVERS FOR EXYNOS after dt-binding conversion
From: Lukas Bulwahn @ 2024-04-11 6:30 UTC (permalink / raw)
To: Krzysztof Kozlowski, Rob Herring, Conor Dooley, dri-devel,
devicetree
Cc: kernel-janitors, linux-kernel, Lukas Bulwahn
Commit ad6d17e10306 ("dt-bindings: display: samsung,exynos5-dp: convert to
DT Schema") converts the last exynos display devicetree binding to json.
With that, all exynos display devicetree bindings are now located in
Documentation/devicetree/bindings/display/samsung/ and the directory with
the previous txt devicetree bindings, i.e.,
Documentation/devicetree/bindings/display/exynos/, has disappeared.
Adjust the DRM DRIVERS FOR EXYNOS section to this change.
Signed-off-by: Lukas Bulwahn <lukas.bulwahn@redhat.com>
---
MAINTAINERS | 1 -
1 file changed, 1 deletion(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 03204db05027..c2d913c64704 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7221,7 +7221,6 @@ M: Kyungmin Park <kyungmin.park@samsung.com>
L: dri-devel@lists.freedesktop.org
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
-F: Documentation/devicetree/bindings/display/exynos/
F: Documentation/devicetree/bindings/display/samsung/
F: drivers/gpu/drm/exynos/
F: include/uapi/drm/exynos_drm.h
--
2.44.0
^ permalink raw reply related
* Re: [PATCH v10 3/4] clk: stm32: introduce clocks for STM32MP257 platform
From: Stephen Boyd @ 2024-04-11 6:36 UTC (permalink / raw)
To: Alexandre Torgue, Conor Dooley, Gabriel Fernandez,
Krzysztof Kozlowski, Maxime Coquelin, Michael Turquette,
Philipp Zabel, Rob Herring
Cc: linux-clk, devicetree, linux-stm32, linux-arm-kernel,
linux-kernel
In-Reply-To: <20240409171241.274600-4-gabriel.fernandez@foss.st.com>
Quoting gabriel.fernandez@foss.st.com (2024-04-09 10:12:40)
> diff --git a/drivers/clk/stm32/clk-stm32mp25.c b/drivers/clk/stm32/clk-stm32mp25.c
> new file mode 100644
> index 000000000000..23876e7d9863
> --- /dev/null
> +++ b/drivers/clk/stm32/clk-stm32mp25.c
> @@ -0,0 +1,1876 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) STMicroelectronics 2023 - All Rights Reserved
> + * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
> + */
> +
> +#include <linux/clk.h>
Use clk-provider.h not clk.h
> +#include <linux/of_address.h>
Doubt this is the right include. Drop?
> +#include <linux/platform_device.h>
> +
> +#include "clk-stm32-core.h"
> +#include "reset-stm32.h"
> +#include "stm32mp25_rcc.h"
> +
> +#include <dt-bindings/clock/st,stm32mp25-rcc.h>
[...]
> + .clock_data = &stm32mp25_clock_data,
> + .reset_data = &stm32mp25_reset_data,
> +};
> +
> +static const struct of_device_id stm32mp25_match_data[] = {
> + { .compatible = "st,stm32mp25-rcc", .data = &stm32mp25_data, },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, stm32mp25_match_data);
> +
> +static int stm32mp25_rcc_clocks_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + void __iomem *base;
> +
> + base = devm_platform_ioremap_resource(pdev, 0);
> + if (WARN_ON(IS_ERR(base)))
Drop WARN_ON
> + return PTR_ERR(base);
^ permalink raw reply
* Re: [PATCH] MAINTAINERS: adjust DRM DRIVERS FOR EXYNOS after dt-binding conversion
From: Krzysztof Kozlowski @ 2024-04-11 6:36 UTC (permalink / raw)
To: Lukas Bulwahn, Krzysztof Kozlowski, Rob Herring, Conor Dooley,
dri-devel, devicetree
Cc: kernel-janitors, linux-kernel, Lukas Bulwahn
In-Reply-To: <20240411063000.48794-1-lukas.bulwahn@redhat.com>
On 11/04/2024 08:30, Lukas Bulwahn wrote:
> Commit ad6d17e10306 ("dt-bindings: display: samsung,exynos5-dp: convert to
> DT Schema") converts the last exynos display devicetree binding to json.
> With that, all exynos display devicetree bindings are now located in
> Documentation/devicetree/bindings/display/samsung/ and the directory with
> the previous txt devicetree bindings, i.e.,
> Documentation/devicetree/bindings/display/exynos/, has disappeared.
>
> Adjust the DRM DRIVERS FOR EXYNOS section to this change.
This should go via Rob's tree.
Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Best regards,
Krzysztof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox