2015-07-10 10:00:21

by James Liao

[permalink] [raw]
Subject: [PATCH v3 0/5] Add Mediatek MT8173 subsystem clocks support

This patchset is based on 4.2-rc1 and [1], and contains subsystem
clocks support for Mediatek MT8173.

There are many different implementation suggestions [2][3] due to
each subsystem HW contains multiple functions, such as clock and
reset controllers.

In this patchset, I still put subsystem clock implementations in
drivers/clk/mediatek, no mater reset controllers may need to implement
in the same directory in the future. That's because many other vendors
also implement clock and reset controllers in drivers/clk, and it looks
like an acceptible way.

This patchset also contains device tree nodes that are needed by
subsystem clocks.

changes since v2:
- Rebase to 4.2-rc1.
- Add device tree nodes for subsystem clocks.
- Fine tune comments of patches.
- Add __init, __initconst and const to init data and functions.
- Removed unused code from init functions of subsystem clocks.

changes since v1:
- Add CA7PLL and CA15PLL as critical clocks.
- Use the same register descriptor for imgsys, vensys and vencltsys.
- Generalize apmixedsys special clocks registration.

[1] https://patchwork.kernel.org/patch/6446341/
[2] https://lkml.org/lkml/2015/5/21/96
[3] https://lkml.org/lkml/2015/6/29/590

James Liao (4):
dt-bindings: ARM: Mediatek: Document devicetree bindings for clock
controllers
clk: mediatek: Add subsystem clocks of MT8173
clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS
arm64: dts: mt8173: Add subsystem clock controller device nodes

Sascha Hauer (1):
clk: mediatek: mt8173: Fix enabling of critical clocks

.../bindings/arm/mediatek/mediatek,imgsys.txt | 22 ++
.../bindings/arm/mediatek/mediatek,mmsys.txt | 22 ++
.../bindings/arm/mediatek/mediatek,vdecsys.txt | 22 ++
.../bindings/arm/mediatek/mediatek,vencltsys.txt | 22 ++
.../bindings/arm/mediatek/mediatek,vencsys.txt | 22 ++
arch/arm64/boot/dts/mediatek/mt8173.dtsi | 30 ++
drivers/clk/mediatek/clk-mt8173.c | 432 ++++++++++++++++++++-
drivers/clk/mediatek/clk-pll.c | 7 +-
include/dt-bindings/clock/mt8173-clk.h | 94 ++++-
9 files changed, 659 insertions(+), 14 deletions(-)
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vencltsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt

--
1.8.1.1.dirty


2015-07-10 10:00:42

by James Liao

[permalink] [raw]
Subject: [PATCH v3 1/5] clk: mediatek: mt8173: Fix enabling of critical clocks

From: Sascha Hauer <[email protected]>

On the MT8173 the clocks are provided by different units. To enable
the critical clocks we must be sure that all parent clocks are already
registered, otherwise the parents of the critical clocks end up being
unused and get disabled later.

On MT8173, for example, it is the CLK_TOP clocks that have CLK_APMIXED
PLLs as their parents, so we cannot enable the CLK_TOP critical clocks
until the CLK_APMIXED clocks have all been registered.

To find a place where all parents are registered we try each time
after we've registered some clocks if all known providers are present
now and only then we enable the critical clocks.

Signed-off-by: Sascha Hauer <[email protected]>
Signed-off-by: James Liao <[email protected]>
---
drivers/clk/mediatek/clk-mt8173.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 4b9e04c..b3d91ee 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -700,6 +700,22 @@ static const struct mtk_composite peri_clks[] __initconst = {
MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
};

+static struct clk_onecell_data *mt8173_top_clk_data;
+static struct clk_onecell_data *mt8173_pll_clk_data;
+
+static void __init mtk_clk_enable_critical(void)
+{
+ if (!mt8173_top_clk_data || !mt8173_pll_clk_data)
+ return;
+
+ clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+ clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA7PLL]);
+ clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_MEM_SEL]);
+ clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]);
+ clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_CCI400_SEL]);
+ clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_RTC_SEL]);
+}
+
static void __init mtk_topckgen_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
@@ -712,19 +728,19 @@ static void __init mtk_topckgen_init(struct device_node *node)
return;
}

- clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+ mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);

mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
&mt8173_clk_lock, clk_data);

- clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]);
-
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r)
pr_err("%s(): could not register clock provider: %d\n",
__func__, r);
+
+ mtk_clk_enable_critical();
}
CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init);

@@ -818,13 +834,13 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;

- clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+ mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
return;

mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);

- clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]);
+ mtk_clk_enable_critical();
}
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
mtk_apmixedsys_init);
--
1.8.1.1.dirty

2015-07-10 10:00:54

by James Liao

[permalink] [raw]
Subject: [PATCH v3 2/5] dt-bindings: ARM: Mediatek: Document devicetree bindings for clock controllers

This adds the binding documentation for the mmsys, imgsys, vdecsys,
vencsys and vencltsys controllers found on Mediatek SoCs.

Signed-off-by: James Liao <[email protected]>
---
.../bindings/arm/mediatek/mediatek,imgsys.txt | 22 ++++++++++++++++++++++
.../bindings/arm/mediatek/mediatek,mmsys.txt | 22 ++++++++++++++++++++++
.../bindings/arm/mediatek/mediatek,vdecsys.txt | 22 ++++++++++++++++++++++
.../bindings/arm/mediatek/mediatek,vencltsys.txt | 22 ++++++++++++++++++++++
.../bindings/arm/mediatek/mediatek,vencsys.txt | 22 ++++++++++++++++++++++
5 files changed, 110 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vencltsys.txt
create mode 100644 Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt

diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
new file mode 100644
index 0000000..7612bac
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
@@ -0,0 +1,22 @@
+Mediatek imgsys controller
+============================
+
+The Mediatek imgsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8173-imgsys", "syscon"
+- #clock-cells: Must be 1
+
+The imgsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+imgsys: imgsys@15000000 {
+ compatible = "mediatek,mt8173-imgsys", "syscon";
+ reg = <0 0x15000000 0 0x1000>;
+ #clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
new file mode 100644
index 0000000..b51e417
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
@@ -0,0 +1,22 @@
+Mediatek mmsys controller
+============================
+
+The Mediatek mmsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8173-mmsys", "syscon"
+- #clock-cells: Must be 1
+
+The mmsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+mmsys: mmsys@14000000 {
+ compatible = "mediatek,mt8173-mmsys", "syscon";
+ reg = <0 0x14000000 0 0x1000>;
+ #clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
new file mode 100644
index 0000000..a5b94a7
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
@@ -0,0 +1,22 @@
+Mediatek vdecsys controller
+============================
+
+The Mediatek vdecsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8173-vdecsys", "syscon"
+- #clock-cells: Must be 1
+
+The vdecsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+vdecsys: vdecsys@16000000 {
+ compatible = "mediatek,mt8173-vdecsys", "syscon";
+ reg = <0 0x16000000 0 0x1000>;
+ #clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencltsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencltsys.txt
new file mode 100644
index 0000000..3d4e8d8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencltsys.txt
@@ -0,0 +1,22 @@
+Mediatek vencltsys controller
+============================
+
+The Mediatek vencltsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8173-vencltsys", "syscon"
+- #clock-cells: Must be 1
+
+The vencltsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+vencltsys: vencltsys@19000000 {
+ compatible = "mediatek,mt8173-vencltsys", "syscon";
+ reg = <0 0x19000000 0 0x1000>;
+ #clock-cells = <1>;
+};
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
new file mode 100644
index 0000000..e5b72f5
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
@@ -0,0 +1,22 @@
+Mediatek vencsys controller
+============================
+
+The Mediatek vencsys controller provides various clocks to the system.
+
+Required Properties:
+
+- compatible: Should be:
+ - "mediatek,mt8173-vencsys", "syscon"
+- #clock-cells: Must be 1
+
+The vencsys controller uses the common clk binding from
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+The available clocks are defined in dt-bindings/clock/mt*-clk.h.
+
+Example:
+
+vencsys: vencsys@18000000 {
+ compatible = "mediatek,mt8173-vencsys", "syscon";
+ reg = <0 0x18000000 0 0x1000>;
+ #clock-cells = <1>;
+};
--
1.8.1.1.dirty

2015-07-10 10:01:02

by James Liao

[permalink] [raw]
Subject: [PATCH v3 3/5] clk: mediatek: Add subsystem clocks of MT8173

Most multimedia subsystem clocks will be accessed by multiple
drivers, so it's a better way to manage these clocks in CCF.
This patch adds clock support for MM, IMG, VDEC, VENC and VENC_LT
subsystems.

Signed-off-by: James Liao <[email protected]>
---
drivers/clk/mediatek/clk-mt8173.c | 263 +++++++++++++++++++++++++++++++++
include/dt-bindings/clock/mt8173-clk.h | 91 +++++++++++-
2 files changed, 352 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index b3d91ee..1d21e26 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -700,6 +700,183 @@ static const struct mtk_composite peri_clks[] __initconst = {
MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
};

+static const struct mtk_gate_regs cg_regs_4_8_0 = {
+ .set_ofs = 0x0004,
+ .clr_ofs = 0x0008,
+ .sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &cg_regs_4_8_0, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate img_clks[] __initconst = {
+ GATE_IMG(CLK_IMG_LARB2_SMI, "img_larb2_smi", "mm_sel", 0),
+ GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "mm_sel", 5),
+ GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "mm_sel", 6),
+ GATE_IMG(CLK_IMG_SEN_TG, "img_sen_tg", "camtg_sel", 7),
+ GATE_IMG(CLK_IMG_SEN_CAM, "img_sen_cam", "mm_sel", 8),
+ GATE_IMG(CLK_IMG_CAM_SV, "img_cam_sv", "mm_sel", 9),
+ GATE_IMG(CLK_IMG_FD, "img_fd", "mm_sel", 11),
+};
+
+static const struct mtk_gate_regs mm0_cg_regs = {
+ .set_ofs = 0x0104,
+ .clr_ofs = 0x0108,
+ .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs = {
+ .set_ofs = 0x0114,
+ .clr_ofs = 0x0118,
+ .sta_ofs = 0x0110,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mm0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+#define GATE_MM1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &mm1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr, \
+ }
+
+static const struct mtk_gate mm_clks[] __initconst = {
+ /* MM0 */
+ GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
+ GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+ GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2),
+ GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3),
+ GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4),
+ GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5),
+ GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6),
+ GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7),
+ GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8),
+ GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9),
+ GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+ GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
+ GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
+ GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
+ GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 15),
+ GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16),
+ GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17),
+ GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18),
+ GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
+ GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20),
+ GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
+ GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
+ GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23),
+ GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24),
+ GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
+ GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
+ GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27),
+ GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28),
+ GATE_MM0(CLK_MM_DISP_SPLIT1, "mm_disp_split1", "mm_sel", 29),
+ GATE_MM0(CLK_MM_DISP_MERGE, "mm_disp_merge", "mm_sel", 30),
+ GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31),
+ /* MM1 */
+ GATE_MM1(CLK_MM_DISP_PWM0MM, "mm_disp_pwm0mm", "mm_sel", 0),
+ GATE_MM1(CLK_MM_DISP_PWM026M, "mm_disp_pwm026m", "pwm_sel", 1),
+ GATE_MM1(CLK_MM_DISP_PWM1MM, "mm_disp_pwm1mm", "mm_sel", 2),
+ GATE_MM1(CLK_MM_DISP_PWM126M, "mm_disp_pwm126m", "pwm_sel", 3),
+ GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4),
+ GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "clk_null", 5),
+ GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6),
+ GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "clk_null", 7),
+ GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "dpi0_sel", 8),
+ GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9),
+ GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "clk_null", 10),
+ GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11),
+ GATE_MM1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi0_sel", 12),
+ GATE_MM1(CLK_MM_HDMI_PLLCK, "mm_hdmi_pllck", "hdmi_sel", 13),
+ GATE_MM1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll1", 14),
+ GATE_MM1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll2", 15),
+ GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "clk_null", 16),
+ GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "clk_null", 17),
+ GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18),
+ GATE_MM1(CLK_MM_HDMI_HDCP, "mm_hdmi_hdcp", "hdcp_sel", 19),
+ GATE_MM1(CLK_MM_HDMI_HDCP24M, "mm_hdmi_hdcp24m", "hdcp_24m_sel", 20),
+};
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+ .set_ofs = 0x0000,
+ .clr_ofs = 0x0004,
+ .sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+ .set_ofs = 0x0008,
+ .clr_ofs = 0x000c,
+ .sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec0_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &vdec1_cg_regs, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate vdec_clks[] __initconst = {
+ GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
+ GATE_VDEC1(CLK_VDEC_LARB_CKEN, "vdec_larb_cken", "mm_sel", 0),
+};
+
+#define GATE_VENC(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &cg_regs_4_8_0, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate venc_clks[] __initconst = {
+ GATE_VENC(CLK_VENC_CKE0, "venc_cke0", "mm_sel", 0),
+ GATE_VENC(CLK_VENC_CKE1, "venc_cke1", "venc_sel", 4),
+ GATE_VENC(CLK_VENC_CKE2, "venc_cke2", "venc_sel", 8),
+ GATE_VENC(CLK_VENC_CKE3, "venc_cke3", "venc_sel", 12),
+};
+
+#define GATE_VENCLT(_id, _name, _parent, _shift) { \
+ .id = _id, \
+ .name = _name, \
+ .parent_name = _parent, \
+ .regs = &cg_regs_4_8_0, \
+ .shift = _shift, \
+ .ops = &mtk_clk_gate_ops_setclr_inv, \
+ }
+
+static const struct mtk_gate venclt_clks[] __initconst = {
+ GATE_VENCLT(CLK_VENCLT_CKE0, "venclt_cke0", "mm_sel", 0),
+ GATE_VENCLT(CLK_VENCLT_CKE1, "venclt_cke1", "venclt_sel", 4),
+};
+
static struct clk_onecell_data *mt8173_top_clk_data;
static struct clk_onecell_data *mt8173_pll_clk_data;

@@ -844,3 +1021,89 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
}
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
mtk_apmixedsys_init);
+
+static void __init mtk_imgsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
+
+ mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8173-imgsys", mtk_imgsys_init);
+
+static void __init mtk_mmsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
+
+ mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_mmsys, "mediatek,mt8173-mmsys", mtk_mmsys_init);
+
+static void __init mtk_vdecsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
+
+ mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8173-vdecsys", mtk_vdecsys_init);
+
+static void __init mtk_vencsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
+
+ mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_vencsys, "mediatek,mt8173-vencsys", mtk_vencsys_init);
+
+static void __init mtk_vencltsys_init(struct device_node *node)
+{
+ struct clk_onecell_data *clk_data;
+ int r;
+
+ clk_data = mtk_alloc_clk_data(CLK_VENCLT_NR_CLK);
+
+ mtk_clk_register_gates(node, venclt_clks, ARRAY_SIZE(venclt_clks),
+ clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);
+}
+CLK_OF_DECLARE(mtk_vencltsys, "mediatek,mt8173-vencltsys", mtk_vencltsys_init);
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
index 4ad76ed..6ce88bf 100644
--- a/include/dt-bindings/clock/mt8173-clk.h
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -158,8 +158,8 @@

/* APMIXED_SYS */

-#define CLK_APMIXED_ARMCA15PLL 1
-#define CLK_APMIXED_ARMCA7PLL 2
+#define CLK_APMIXED_ARMCA15PLL 1
+#define CLK_APMIXED_ARMCA7PLL 2
#define CLK_APMIXED_MAINPLL 3
#define CLK_APMIXED_UNIVPLL 4
#define CLK_APMIXED_MMPLL 5
@@ -232,4 +232,91 @@
#define CLK_PERI_UART3_SEL 39
#define CLK_PERI_NR_CLK 40

+/* IMG_SYS */
+
+#define CLK_IMG_LARB2_SMI 1
+#define CLK_IMG_CAM_SMI 2
+#define CLK_IMG_CAM_CAM 3
+#define CLK_IMG_SEN_TG 4
+#define CLK_IMG_SEN_CAM 5
+#define CLK_IMG_CAM_SV 6
+#define CLK_IMG_FD 7
+#define CLK_IMG_NR_CLK 8
+
+/* MM_SYS */
+
+#define CLK_MM_SMI_COMMON 1
+#define CLK_MM_SMI_LARB0 2
+#define CLK_MM_CAM_MDP 3
+#define CLK_MM_MDP_RDMA0 4
+#define CLK_MM_MDP_RDMA1 5
+#define CLK_MM_MDP_RSZ0 6
+#define CLK_MM_MDP_RSZ1 7
+#define CLK_MM_MDP_RSZ2 8
+#define CLK_MM_MDP_TDSHP0 9
+#define CLK_MM_MDP_TDSHP1 10
+#define CLK_MM_MDP_WDMA 11
+#define CLK_MM_MDP_WROT0 12
+#define CLK_MM_MDP_WROT1 13
+#define CLK_MM_FAKE_ENG 14
+#define CLK_MM_MUTEX_32K 15
+#define CLK_MM_DISP_OVL0 16
+#define CLK_MM_DISP_OVL1 17
+#define CLK_MM_DISP_RDMA0 18
+#define CLK_MM_DISP_RDMA1 19
+#define CLK_MM_DISP_RDMA2 20
+#define CLK_MM_DISP_WDMA0 21
+#define CLK_MM_DISP_WDMA1 22
+#define CLK_MM_DISP_COLOR0 23
+#define CLK_MM_DISP_COLOR1 24
+#define CLK_MM_DISP_AAL 25
+#define CLK_MM_DISP_GAMMA 26
+#define CLK_MM_DISP_UFOE 27
+#define CLK_MM_DISP_SPLIT0 28
+#define CLK_MM_DISP_SPLIT1 29
+#define CLK_MM_DISP_MERGE 30
+#define CLK_MM_DISP_OD 31
+#define CLK_MM_DISP_PWM0MM 32
+#define CLK_MM_DISP_PWM026M 33
+#define CLK_MM_DISP_PWM1MM 34
+#define CLK_MM_DISP_PWM126M 35
+#define CLK_MM_DSI0_ENGINE 36
+#define CLK_MM_DSI0_DIGITAL 37
+#define CLK_MM_DSI1_ENGINE 38
+#define CLK_MM_DSI1_DIGITAL 39
+#define CLK_MM_DPI_PIXEL 40
+#define CLK_MM_DPI_ENGINE 41
+#define CLK_MM_DPI1_PIXEL 42
+#define CLK_MM_DPI1_ENGINE 43
+#define CLK_MM_HDMI_PIXEL 44
+#define CLK_MM_HDMI_PLLCK 45
+#define CLK_MM_HDMI_AUDIO 46
+#define CLK_MM_HDMI_SPDIF 47
+#define CLK_MM_LVDS_PIXEL 48
+#define CLK_MM_LVDS_CTS 49
+#define CLK_MM_SMI_LARB4 50
+#define CLK_MM_HDMI_HDCP 51
+#define CLK_MM_HDMI_HDCP24M 52
+#define CLK_MM_NR_CLK 53
+
+/* VDEC_SYS */
+
+#define CLK_VDEC_CKEN 1
+#define CLK_VDEC_LARB_CKEN 2
+#define CLK_VDEC_NR_CLK 3
+
+/* VENC_SYS */
+
+#define CLK_VENC_CKE0 1
+#define CLK_VENC_CKE1 2
+#define CLK_VENC_CKE2 3
+#define CLK_VENC_CKE3 4
+#define CLK_VENC_NR_CLK 5
+
+/* VENCLT_SYS */
+
+#define CLK_VENCLT_CKE0 1
+#define CLK_VENCLT_CKE1 2
+#define CLK_VENCLT_NR_CLK 3
+
#endif /* _DT_BINDINGS_CLK_MT8173_H */
--
1.8.1.1.dirty

2015-07-10 10:01:12

by James Liao

[permalink] [raw]
Subject: [PATCH v3 4/5] clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS

Add REF2USB_TX clock support into MT8173 APMIXEDSYS. This clock
is needed by USB 3.0.

Signed-off-by: James Liao <[email protected]>
---
drivers/clk/mediatek/clk-mt8173.c | 143 +++++++++++++++++++++++++++++++++
drivers/clk/mediatek/clk-pll.c | 7 +-
include/dt-bindings/clock/mt8173-clk.h | 3 +-
3 files changed, 146 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 1d21e26..11f82cb 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -12,6 +12,7 @@
* GNU General Public License for more details.
*/

+#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/slab.h>
@@ -968,6 +969,141 @@ static void __init mtk_pericfg_init(struct device_node *node)
}
CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);

+#define REF2USB_TX_EN BIT(0)
+#define REF2USB_TX_LPF_EN BIT(1)
+#define REF2USB_TX_OUT_EN BIT(2)
+#define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
+ REF2USB_TX_OUT_EN)
+
+struct mtk_ref2usb_tx {
+ struct clk_hw hw;
+ void __iomem *base_addr;
+};
+
+static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtk_ref2usb_tx, hw);
+}
+
+static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
+{
+ struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
+
+ return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
+}
+
+static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
+{
+ struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
+ u32 val;
+
+ val = readl(tx->base_addr);
+
+ val |= REF2USB_TX_EN;
+ writel(val, tx->base_addr);
+ udelay(100);
+
+ val |= REF2USB_TX_LPF_EN;
+ writel(val, tx->base_addr);
+
+ val |= REF2USB_TX_OUT_EN;
+ writel(val, tx->base_addr);
+
+ return 0;
+}
+
+static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
+{
+ struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
+ u32 val;
+
+ val = readl(tx->base_addr);
+ val &= ~REF2USB_EN_MASK;
+ writel(val, tx->base_addr);
+}
+
+static const struct clk_ops mtk_ref2usb_tx_ops = {
+ .is_prepared = mtk_ref2usb_tx_is_prepared,
+ .prepare = mtk_ref2usb_tx_prepare,
+ .unprepare = mtk_ref2usb_tx_unprepare,
+};
+
+static struct clk *mtk_clk_register_ref2usb_tx(const char *name,
+ const char *parent_name, void __iomem *reg)
+{
+ struct mtk_ref2usb_tx *tx;
+ struct clk_init_data init = {};
+ struct clk *clk;
+
+ tx = kzalloc(sizeof(*tx), GFP_KERNEL);
+ if (!tx)
+ return ERR_PTR(-ENOMEM);
+
+ tx->base_addr = reg;
+ tx->hw.init = &init;
+
+ init.name = name;
+ init.ops = &mtk_ref2usb_tx_ops;
+ init.parent_names = &parent_name;
+ init.num_parents = 1;
+
+ clk = clk_register(NULL, &tx->hw);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk));
+ kfree(tx);
+ }
+
+ return clk;
+}
+
+struct mtk_apmixed_ex {
+ int id;
+ const char *name;
+ const char *parent;
+ u32 reg_ofs;
+};
+
+#define APMIXED_EX(_id, _name, _parent, _reg_ofs) { \
+ .id = _id, \
+ .name = _name, \
+ .parent = _parent, \
+ .reg_ofs = _reg_ofs, \
+ }
+
+static const struct mtk_apmixed_ex apmixed_ex[] = {
+ APMIXED_EX(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8),
+};
+
+static void __init mtk_clk_register_apmixedsys_special(struct device_node *node,
+ struct clk_onecell_data *clk_data)
+{
+ void __iomem *base;
+ struct clk *clk;
+ int i;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(apmixed_ex); i++) {
+ const struct mtk_apmixed_ex *ape = &apmixed_ex[i];
+
+ clk = mtk_clk_register_ref2usb_tx(ape->name, ape->parent,
+ base + ape->reg_ofs);
+
+ if (IS_ERR(clk)) {
+ pr_err("Failed to register clk %s: %ld\n", ape->name,
+ PTR_ERR(clk));
+ continue;
+ }
+
+ clk_data->clks[CLK_APMIXED_REF2USB_TX] = clk;
+ }
+}
+
#define MT8173_PLL_FMAX (3000UL * MHZ)

#define CON0_MT8173_RST_BAR BIT(24)
@@ -1010,12 +1146,19 @@ static const struct mtk_pll_data plls[] = {
static void __init mtk_apmixedsys_init(struct device_node *node)
{
struct clk_onecell_data *clk_data;
+ int r;

mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
return;

mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+ mtk_clk_register_apmixedsys_special(node, clk_data);
+
+ r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+ if (r)
+ pr_err("%s(): could not register clock provider: %d\n",
+ __func__, r);

mtk_clk_enable_critical();
}
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 44409e9..813f0c7 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -302,7 +302,7 @@ void __init mtk_clk_register_plls(struct device_node *node,
const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
{
void __iomem *base;
- int r, i;
+ int i;
struct clk *clk;

base = of_iomap(node, 0);
@@ -324,9 +324,4 @@ void __init mtk_clk_register_plls(struct device_node *node,

clk_data->clks[pll->id] = clk;
}
-
- r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
- if (r)
- pr_err("%s(): could not register clock provider: %d\n",
- __func__, r);
}
diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
index 6ce88bf..7b7c555 100644
--- a/include/dt-bindings/clock/mt8173-clk.h
+++ b/include/dt-bindings/clock/mt8173-clk.h
@@ -172,7 +172,8 @@
#define CLK_APMIXED_APLL2 12
#define CLK_APMIXED_LVDSPLL 13
#define CLK_APMIXED_MSDCPLL2 14
-#define CLK_APMIXED_NR_CLK 15
+#define CLK_APMIXED_REF2USB_TX 15
+#define CLK_APMIXED_NR_CLK 16

/* INFRA_SYS */

--
1.8.1.1.dirty

2015-07-10 10:01:24

by James Liao

[permalink] [raw]
Subject: [PATCH v3 5/5] arm64: dts: mt8173: Add subsystem clock controller device nodes

This patch adds device nodes providing subsystem clocks on MT8173,
includes mmsys, imgsys, vdecsys, vencsys and vencltsys.

Signed-off-by: James Liao <[email protected]>
---
arch/arm64/boot/dts/mediatek/mt8173.dtsi | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
index a2f63e4..9d74ce5 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
@@ -227,6 +227,36 @@
clocks = <&uart_clk>;
status = "disabled";
};
+
+ mmsys: mmsys@14000000 {
+ compatible = "mediatek,mt8173-mmsys", "syscon";
+ reg = <0 0x14000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ imgsys: imgsys@15000000 {
+ compatible = "mediatek,mt8173-imgsys", "syscon";
+ reg = <0 0x15000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ vdecsys: vdecsys@16000000 {
+ compatible = "mediatek,mt8173-vdecsys", "syscon";
+ reg = <0 0x16000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ vencsys: vencsys@18000000 {
+ compatible = "mediatek,mt8173-vencsys", "syscon";
+ reg = <0 0x18000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ vencltsys: vencltsys@19000000 {
+ compatible = "mediatek,mt8173-vencltsys", "syscon";
+ reg = <0 0x19000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
};
};

--
1.8.1.1.dirty

2015-07-10 15:58:10

by Matthias Brugger

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] arm64: dts: mt8173: Add subsystem clock controller device nodes

2015-07-10 17:02 GMT+02:00 Daniel Kurtz <[email protected]>:
>
> On Jul 10, 2015 18:00, "James Liao" <[email protected]> wrote:
>>
>> This patch adds device nodes providing subsystem clocks on MT8173,
>> includes mmsys, imgsys, vdecsys, vencsys and vencltsys.
>>
>> Signed-off-by: James Liao <[email protected]>
>> ---
>> arch/arm64/boot/dts/mediatek/mt8173.dtsi | 30
>> ++++++++++++++++++++++++++++++
>> 1 file changed, 30 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
>> b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
>> index a2f63e4..9d74ce5 100644
>> --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
>> +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
>> @@ -227,6 +227,36 @@
>> clocks = <&uart_clk>;
>> status = "disabled";
>> };
>> +
>> + mmsys: mmsys@14000000 {
>
> I think we agreed previously that these should all be clock-controller@.
>

I did understand the same.
Please change that.

Thanks.

2015-07-13 03:35:03

by James Liao

[permalink] [raw]
Subject: Re: [PATCH v3 5/5] arm64: dts: mt8173: Add subsystem clock controller device nodes

Hi Daniel,

On Fri, 2015-07-10 at 23:02 +0800, Daniel Kurtz wrote:
> > diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> > index a2f63e4..9d74ce5 100644
> > --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> > +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi
> > @@ -227,6 +227,36 @@
> > clocks = <&uart_clk>;
> > status = "disabled";
> > };
> > +
> > + mmsys: mmsys@14000000 {
>
> I think we agreed previously that these should all be
> clock-controller@.
>
You're right. I'll change it in next patch.


Best regards,

James

2015-07-13 14:46:45

by Daniel Kurtz

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS

Hi James,


On Fri, Jul 10, 2015 at 6:00 PM, James Liao <[email protected]> wrote:
> Add REF2USB_TX clock support into MT8173 APMIXEDSYS. This clock
> is needed by USB 3.0.
>
> Signed-off-by: James Liao <[email protected]>
> ---
> drivers/clk/mediatek/clk-mt8173.c | 143 +++++++++++++++++++++++++++++++++
> drivers/clk/mediatek/clk-pll.c | 7 +-
> include/dt-bindings/clock/mt8173-clk.h | 3 +-
> 3 files changed, 146 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
> index 1d21e26..11f82cb 100644
> --- a/drivers/clk/mediatek/clk-mt8173.c
> +++ b/drivers/clk/mediatek/clk-mt8173.c
> @@ -12,6 +12,7 @@
> * GNU General Public License for more details.
> */
>
> +#include <linux/delay.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> #include <linux/slab.h>
> @@ -968,6 +969,141 @@ static void __init mtk_pericfg_init(struct device_node *node)
> }
> CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
>
> +#define REF2USB_TX_EN BIT(0)
> +#define REF2USB_TX_LPF_EN BIT(1)
> +#define REF2USB_TX_OUT_EN BIT(2)
> +#define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
> + REF2USB_TX_OUT_EN)
> +
> +struct mtk_ref2usb_tx {
> + struct clk_hw hw;
> + void __iomem *base_addr;
> +};
> +
> +static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
> +{
> + return container_of(hw, struct mtk_ref2usb_tx, hw);
> +}
> +
> +static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
> +{
> + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
> +
> + return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
> +}
> +
> +static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
> +{
> + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
> + u32 val;
> +
> + val = readl(tx->base_addr);
> +
> + val |= REF2USB_TX_EN;
> + writel(val, tx->base_addr);
> + udelay(100);
> +
> + val |= REF2USB_TX_LPF_EN;
> + writel(val, tx->base_addr);
> +
> + val |= REF2USB_TX_OUT_EN;
> + writel(val, tx->base_addr);
> +
> + return 0;
> +}
> +
> +static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
> +{
> + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
> + u32 val;
> +
> + val = readl(tx->base_addr);
> + val &= ~REF2USB_EN_MASK;
> + writel(val, tx->base_addr);
> +}
> +
> +static const struct clk_ops mtk_ref2usb_tx_ops = {
> + .is_prepared = mtk_ref2usb_tx_is_prepared,
> + .prepare = mtk_ref2usb_tx_prepare,
> + .unprepare = mtk_ref2usb_tx_unprepare,
> +};

Burying the implementation of this special "mtk_ref2usb" clock in
clk-mt8173,c seems a bit awkward.
Can you please move it to its own file, like mediatek/clk-usb.c?


> +
> +static struct clk *mtk_clk_register_ref2usb_tx(const char *name,
> + const char *parent_name, void __iomem *reg)
> +{
> + struct mtk_ref2usb_tx *tx;
> + struct clk_init_data init = {};
> + struct clk *clk;
> +
> + tx = kzalloc(sizeof(*tx), GFP_KERNEL);
> + if (!tx)
> + return ERR_PTR(-ENOMEM);
> +
> + tx->base_addr = reg;
> + tx->hw.init = &init;
> +
> + init.name = name;
> + init.ops = &mtk_ref2usb_tx_ops;
> + init.parent_names = &parent_name;
> + init.num_parents = 1;
> +
> + clk = clk_register(NULL, &tx->hw);
> +
> + if (IS_ERR(clk)) {
> + pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk));
> + kfree(tx);
> + }
> +
> + return clk;
> +}
> +
> +struct mtk_apmixed_ex {
> + int id;
> + const char *name;
> + const char *parent;
> + u32 reg_ofs;
> +};
> +
> +#define APMIXED_EX(_id, _name, _parent, _reg_ofs) { \
> + .id = _id, \
> + .name = _name, \
> + .parent = _parent, \
> + .reg_ofs = _reg_ofs, \
> + }
> +
> +static const struct mtk_apmixed_ex apmixed_ex[] = {

__initconst

> + APMIXED_EX(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8),
> +};
> +
> +static void __init mtk_clk_register_apmixedsys_special(struct device_node *node,
> + struct clk_onecell_data *clk_data)
> +{
> + void __iomem *base;
> + struct clk *clk;
> + int i;
> +
> + base = of_iomap(node, 0);
> + if (!base) {
> + pr_err("%s(): ioremap failed\n", __func__);
> + return;
> + }
> +
> + for (i = 0; i < ARRAY_SIZE(apmixed_ex); i++) {
> + const struct mtk_apmixed_ex *ape = &apmixed_ex[i];
> +
> + clk = mtk_clk_register_ref2usb_tx(ape->name, ape->parent,
> + base + ape->reg_ofs);
> +
> + if (IS_ERR(clk)) {
> + pr_err("Failed to register clk %s: %ld\n", ape->name,
> + PTR_ERR(clk));
> + continue;
> + }
> +
> + clk_data->clks[CLK_APMIXED_REF2USB_TX] = clk;

This works assuming ARRAY_SIZE(apmixed_ex) == 1.
Either remove the loop since it is unnecessary, or do:
clk_data->clks[ape->id] = clk;

> + }
> +}
> +
> #define MT8173_PLL_FMAX (3000UL * MHZ)
>
> #define CON0_MT8173_RST_BAR BIT(24)
> @@ -1010,12 +1146,19 @@ static const struct mtk_pll_data plls[] = {
> static void __init mtk_apmixedsys_init(struct device_node *node)
> {
> struct clk_onecell_data *clk_data;
> + int r;
>
> mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
> if (!clk_data)
> return;
>
> mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
> + mtk_clk_register_apmixedsys_special(node, clk_data);
> +
> + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> + if (r)
> + pr_err("%s(): could not register clock provider: %d\n",
> + __func__, r);
>
> mtk_clk_enable_critical();
> }
> diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
> index 44409e9..813f0c7 100644
> --- a/drivers/clk/mediatek/clk-pll.c
> +++ b/drivers/clk/mediatek/clk-pll.c
> @@ -302,7 +302,7 @@ void __init mtk_clk_register_plls(struct device_node *node,
> const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
> {
> void __iomem *base;
> - int r, i;
> + int i;
> struct clk *clk;
>
> base = of_iomap(node, 0);
> @@ -324,9 +324,4 @@ void __init mtk_clk_register_plls(struct device_node *node,
>
> clk_data->clks[pll->id] = clk;
> }
> -
> - r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
> - if (r)
> - pr_err("%s(): could not register clock provider: %d\n",
> - __func__, r);
> }
> diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h
> index 6ce88bf..7b7c555 100644
> --- a/include/dt-bindings/clock/mt8173-clk.h
> +++ b/include/dt-bindings/clock/mt8173-clk.h
> @@ -172,7 +172,8 @@
> #define CLK_APMIXED_APLL2 12
> #define CLK_APMIXED_LVDSPLL 13
> #define CLK_APMIXED_MSDCPLL2 14
> -#define CLK_APMIXED_NR_CLK 15
> +#define CLK_APMIXED_REF2USB_TX 15
> +#define CLK_APMIXED_NR_CLK 16
>
> /* INFRA_SYS */
>
> --
> 1.8.1.1.dirty
>

2015-07-14 02:45:42

by James Liao

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS

Hi Daniel,

On Mon, 2015-07-13 at 22:46 +0800, Daniel Kurtz wrote:

> > +static const struct clk_ops mtk_ref2usb_tx_ops = {
> > + .is_prepared = mtk_ref2usb_tx_is_prepared,
> > + .prepare = mtk_ref2usb_tx_prepare,
> > + .unprepare = mtk_ref2usb_tx_unprepare,
> > +};
>
> Burying the implementation of this special "mtk_ref2usb" clock in
> clk-mt8173,c seems a bit awkward.
> Can you please move it to its own file, like mediatek/clk-usb.c?

Do you mean clk/mediatek/clk-usb.c?

This clock is a MT8173 specific clock, which may not be reused by other
SoCs. So I think it's not necessary to move it to a separated file.

> > +
> > +static struct clk *mtk_clk_register_ref2usb_tx(const char *name,
> > + const char *parent_name, void __iomem *reg)
> > +{
> > + struct mtk_ref2usb_tx *tx;
> > + struct clk_init_data init = {};
> > + struct clk *clk;
> > +
> > + tx = kzalloc(sizeof(*tx), GFP_KERNEL);
> > + if (!tx)
> > + return ERR_PTR(-ENOMEM);
> > +
> > + tx->base_addr = reg;
> > + tx->hw.init = &init;
> > +
> > + init.name = name;
> > + init.ops = &mtk_ref2usb_tx_ops;
> > + init.parent_names = &parent_name;
> > + init.num_parents = 1;
> > +
> > + clk = clk_register(NULL, &tx->hw);
> > +
> > + if (IS_ERR(clk)) {
> > + pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk));
> > + kfree(tx);
> > + }
> > +
> > + return clk;
> > +}
> > +
> > +struct mtk_apmixed_ex {
> > + int id;
> > + const char *name;
> > + const char *parent;
> > + u32 reg_ofs;
> > +};
> > +
> > +#define APMIXED_EX(_id, _name, _parent, _reg_ofs) { \
> > + .id = _id, \
> > + .name = _name, \
> > + .parent = _parent, \
> > + .reg_ofs = _reg_ofs, \
> > + }
> > +
> > +static const struct mtk_apmixed_ex apmixed_ex[] = {
>
> __initconst

OK. I'll fix it in next patch.

> > + APMIXED_EX(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8),
> > +};
> > +
> > +static void __init mtk_clk_register_apmixedsys_special(struct device_node *node,
> > + struct clk_onecell_data *clk_data)
> > +{
> > + void __iomem *base;
> > + struct clk *clk;
> > + int i;
> > +
> > + base = of_iomap(node, 0);
> > + if (!base) {
> > + pr_err("%s(): ioremap failed\n", __func__);
> > + return;
> > + }
> > +
> > + for (i = 0; i < ARRAY_SIZE(apmixed_ex); i++) {
> > + const struct mtk_apmixed_ex *ape = &apmixed_ex[i];
> > +
> > + clk = mtk_clk_register_ref2usb_tx(ape->name, ape->parent,
> > + base + ape->reg_ofs);
> > +
> > + if (IS_ERR(clk)) {
> > + pr_err("Failed to register clk %s: %ld\n", ape->name,
> > + PTR_ERR(clk));
> > + continue;
> > + }
> > +
> > + clk_data->clks[CLK_APMIXED_REF2USB_TX] = clk;
>
> This works assuming ARRAY_SIZE(apmixed_ex) == 1.
> Either remove the loop since it is unnecessary, or do:
> clk_data->clks[ape->id] = clk;

It should be "clk_data->clks[ape->id] = clk". I'll fix it in next patch.


Best regards,

James

2015-07-14 03:24:06

by Daniel Kurtz

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS

On Tue, Jul 14, 2015 at 10:45 AM, James Liao <[email protected]> wrote:
> Hi Daniel,
>
> On Mon, 2015-07-13 at 22:46 +0800, Daniel Kurtz wrote:
>
>> > +static const struct clk_ops mtk_ref2usb_tx_ops = {
>> > + .is_prepared = mtk_ref2usb_tx_is_prepared,
>> > + .prepare = mtk_ref2usb_tx_prepare,
>> > + .unprepare = mtk_ref2usb_tx_unprepare,
>> > +};
>>
>> Burying the implementation of this special "mtk_ref2usb" clock in
>> clk-mt8173,c seems a bit awkward.
>> Can you please move it to its own file, like mediatek/clk-usb.c?
>
> Do you mean clk/mediatek/clk-usb.c?
>
> This clock is a MT8173 specific clock, which may not be reused by other
> SoCs. So I think it's not necessary to move it to a separated file.

Yes, this is a wrapper for a type of clock. I think it would be
better in its own file, rather than embedded in clk-mt8173.c, which is
more about enumerating and initializing the clock tree.

Perhaps today it is only used for mt8173, but that may not be the case
in the future.

-Dan


>
>> > +
>> > +static struct clk *mtk_clk_register_ref2usb_tx(const char *name,
>> > + const char *parent_name, void __iomem *reg)
>> > +{
>> > + struct mtk_ref2usb_tx *tx;
>> > + struct clk_init_data init = {};
>> > + struct clk *clk;
>> > +
>> > + tx = kzalloc(sizeof(*tx), GFP_KERNEL);
>> > + if (!tx)
>> > + return ERR_PTR(-ENOMEM);
>> > +
>> > + tx->base_addr = reg;
>> > + tx->hw.init = &init;
>> > +
>> > + init.name = name;
>> > + init.ops = &mtk_ref2usb_tx_ops;
>> > + init.parent_names = &parent_name;
>> > + init.num_parents = 1;
>> > +
>> > + clk = clk_register(NULL, &tx->hw);
>> > +
>> > + if (IS_ERR(clk)) {
>> > + pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk));
>> > + kfree(tx);
>> > + }
>> > +
>> > + return clk;
>> > +}
>> > +
>> > +struct mtk_apmixed_ex {
>> > + int id;
>> > + const char *name;
>> > + const char *parent;
>> > + u32 reg_ofs;
>> > +};
>> > +
>> > +#define APMIXED_EX(_id, _name, _parent, _reg_ofs) { \
>> > + .id = _id, \
>> > + .name = _name, \
>> > + .parent = _parent, \
>> > + .reg_ofs = _reg_ofs, \
>> > + }
>> > +
>> > +static const struct mtk_apmixed_ex apmixed_ex[] = {
>>
>> __initconst
>
> OK. I'll fix it in next patch.
>
>> > + APMIXED_EX(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8),
>> > +};
>> > +
>> > +static void __init mtk_clk_register_apmixedsys_special(struct device_node *node,
>> > + struct clk_onecell_data *clk_data)
>> > +{
>> > + void __iomem *base;
>> > + struct clk *clk;
>> > + int i;
>> > +
>> > + base = of_iomap(node, 0);
>> > + if (!base) {
>> > + pr_err("%s(): ioremap failed\n", __func__);
>> > + return;
>> > + }
>> > +
>> > + for (i = 0; i < ARRAY_SIZE(apmixed_ex); i++) {
>> > + const struct mtk_apmixed_ex *ape = &apmixed_ex[i];
>> > +
>> > + clk = mtk_clk_register_ref2usb_tx(ape->name, ape->parent,
>> > + base + ape->reg_ofs);
>> > +
>> > + if (IS_ERR(clk)) {
>> > + pr_err("Failed to register clk %s: %ld\n", ape->name,
>> > + PTR_ERR(clk));
>> > + continue;
>> > + }
>> > +
>> > + clk_data->clks[CLK_APMIXED_REF2USB_TX] = clk;
>>
>> This works assuming ARRAY_SIZE(apmixed_ex) == 1.
>> Either remove the loop since it is unnecessary, or do:
>> clk_data->clks[ape->id] = clk;
>
> It should be "clk_data->clks[ape->id] = clk". I'll fix it in next patch.
>
>
> Best regards,
>
> James
>

2015-07-14 09:46:46

by James Liao

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS

Hi Daniel,

On Tue, 2015-07-14 at 11:23 +0800, Daniel Kurtz wrote:
> On Tue, Jul 14, 2015 at 10:45 AM, James Liao <[email protected]> wrote:
> > On Mon, 2015-07-13 at 22:46 +0800, Daniel Kurtz wrote:
> >> > +static const struct clk_ops mtk_ref2usb_tx_ops = {
> >> > + .is_prepared = mtk_ref2usb_tx_is_prepared,
> >> > + .prepare = mtk_ref2usb_tx_prepare,
> >> > + .unprepare = mtk_ref2usb_tx_unprepare,
> >> > +};
> >>
> >> Burying the implementation of this special "mtk_ref2usb" clock in
> >> clk-mt8173,c seems a bit awkward.
> >> Can you please move it to its own file, like mediatek/clk-usb.c?
> >
> > Do you mean clk/mediatek/clk-usb.c?
> >
> > This clock is a MT8173 specific clock, which may not be reused by other
> > SoCs. So I think it's not necessary to move it to a separated file.
>
> Yes, this is a wrapper for a type of clock. I think it would be
> better in its own file, rather than embedded in clk-mt8173.c, which is
> more about enumerating and initializing the clock tree.
>
> Perhaps today it is only used for mt8173, but that may not be the case
> in the future.

OK, I'll separate it from clk-mt8173.c.

Ref2usb_tx's control register is located in APMIXEDSYS, which contains
most of PLL controlling. Is this clock suitable to implemented
mtk-pll.c? Or it's proper to be a separated file such as clk-usb.c?


Best regards,

James

2015-07-14 10:16:21

by Daniel Kurtz

[permalink] [raw]
Subject: Re: [PATCH v3 4/5] clk: mediatek: Add USB clock support in MT8173 APMIXEDSYS

On Tue, Jul 14, 2015 at 5:46 PM, James Liao <[email protected]> wrote:
> Hi Daniel,
>
> On Tue, 2015-07-14 at 11:23 +0800, Daniel Kurtz wrote:
>> On Tue, Jul 14, 2015 at 10:45 AM, James Liao <[email protected]> wrote:
>> > On Mon, 2015-07-13 at 22:46 +0800, Daniel Kurtz wrote:
>> >> > +static const struct clk_ops mtk_ref2usb_tx_ops = {
>> >> > + .is_prepared = mtk_ref2usb_tx_is_prepared,
>> >> > + .prepare = mtk_ref2usb_tx_prepare,
>> >> > + .unprepare = mtk_ref2usb_tx_unprepare,
>> >> > +};
>> >>
>> >> Burying the implementation of this special "mtk_ref2usb" clock in
>> >> clk-mt8173,c seems a bit awkward.
>> >> Can you please move it to its own file, like mediatek/clk-usb.c?
>> >
>> > Do you mean clk/mediatek/clk-usb.c?
>> >
>> > This clock is a MT8173 specific clock, which may not be reused by other
>> > SoCs. So I think it's not necessary to move it to a separated file.
>>
>> Yes, this is a wrapper for a type of clock. I think it would be
>> better in its own file, rather than embedded in clk-mt8173.c, which is
>> more about enumerating and initializing the clock tree.
>>
>> Perhaps today it is only used for mt8173, but that may not be the case
>> in the future.
>
> OK, I'll separate it from clk-mt8173.c.
>
> Ref2usb_tx's control register is located in APMIXEDSYS, which contains
> most of PLL controlling. Is this clock suitable to implemented
> mtk-pll.c? Or it's proper to be a separated file such as clk-usb.c?

I think a separate clk-usb.c might be better since the driver is very
different than what is used for the PLLs.

Thanks!
-Dan

> Best regards,
>
> James
>
>