[RESEND PATCH 1/7] clk: mediatek: mt7629: add support for ssusbsys

The SSUSB IP's clocks come from ssusbsys module on mt7629, so add its driver
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com --- drivers/clk/mediatek/clk-mt7629.c | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index 30a919f224..858be85d15 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -539,6 +539,29 @@ static const struct mtk_gate sgmii_cgs[] = { GATE_SGMII(CLK_SGMII_CDR_FB, CLK_TOP_SSUSB_CDR_FB, 5), };
+static const struct mtk_gate_regs ssusb_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +#define GATE_SSUSB(_id, _parent, _shift) { \ + .id = _id, \ + .parent = _parent, \ + .regs = &ssusb_cg_regs, \ + .shift = _shift, \ + .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN, \ +} + +static const struct mtk_gate ssusb_cgs[] = { + GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, CLK_TOP_TO_U2_PHY_1P, 0), + GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, CLK_TOP_TO_U2_PHY, 1), + GATE_SSUSB(CLK_SSUSB_REF_EN, CLK_TOP_TO_USB3_REF, 5), + GATE_SSUSB(CLK_SSUSB_SYS_EN, CLK_TOP_TO_USB3_SYS, 6), + GATE_SSUSB(CLK_SSUSB_MCU_EN, CLK_TOP_TO_USB3_MCU, 7), + GATE_SSUSB(CLK_SSUSB_DMA_EN, CLK_TOP_TO_USB3_DMA, 8), +}; + static const struct mtk_clk_tree mt7629_clk_tree = { .xtal_rate = 40 * MHZ, .xtal2_rate = 20 * MHZ, @@ -621,6 +644,11 @@ static int mt7629_sgmiisys_probe(struct udevice *dev) return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs); }
+static int mt7629_ssusbsys_probe(struct udevice *dev) +{ + return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, ssusb_cgs); +} + static const struct udevice_id mt7629_apmixed_compat[] = { { .compatible = "mediatek,mt7629-apmixedsys" }, { } @@ -651,6 +679,11 @@ static const struct udevice_id mt7629_sgmiisys_compat[] = { { } };
+static const struct udevice_id mt7629_ssusbsys_compat[] = { + { .compatible = "mediatek,mt7629-ssusbsys" }, + { } +}; + static const struct udevice_id mt7629_mcucfg_compat[] = { { .compatible = "mediatek,mt7629-mcucfg" }, { } @@ -722,3 +755,12 @@ U_BOOT_DRIVER(mtk_clk_sgmiisys) = { .priv_auto_alloc_size = sizeof(struct mtk_cg_priv), .ops = &mtk_clk_gate_ops, }; + +U_BOOT_DRIVER(mtk_clk_ssusbsys) = { + .name = "mt7629-clock-ssusbsys", + .id = UCLASS_CLK, + .of_match = mt7629_ssusbsys_compat, + .probe = mt7629_ssusbsys_probe, + .priv_auto_alloc_size = sizeof(struct mtk_cg_priv), + .ops = &mtk_clk_gate_ops, +};

If skip all return error number, it may skip some real error cases, so only skip the error when the clock is not provided in DTS
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com --- drivers/clk/clk-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 9aa8537004..2778b504c0 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -678,7 +678,7 @@ struct clk *devm_clk_get_optional(struct udevice *dev, const char *id) { struct clk *clk = devm_clk_get(dev, id);
- if (IS_ERR(clk)) + if (PTR_ERR(clk) == -ENODATA) return NULL;
return clk;

On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
If skip all return error number, it may skip some real error cases, so only skip the error when the clock is not provided in DTS
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/clk/clk-uclass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

Add valid check for clk->dev, it's useful when get optional clock even when the clk point is valid, but its dev will be NULL.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com --- drivers/clk/clk-uclass.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index 2778b504c0..b7e18668cb 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -391,7 +391,7 @@ int clk_free(struct clk *clk) const struct clk_ops *ops;
debug("%s(clk=%p)\n", __func__, clk); - if (!clk) + if (!clk_valid(clk)) return 0; ops = clk_dev_ops(clk->dev);
@@ -406,7 +406,7 @@ ulong clk_get_rate(struct clk *clk) const struct clk_ops *ops;
debug("%s(clk=%p)\n", __func__, clk); - if (!clk) + if (!clk_valid(clk)) return 0; ops = clk_dev_ops(clk->dev);
@@ -422,7 +422,7 @@ struct clk *clk_get_parent(struct clk *clk) struct clk *pclk;
debug("%s(clk=%p)\n", __func__, clk); - if (!clk) + if (!clk_valid(clk)) return NULL;
pdev = dev_get_parent(clk->dev); @@ -439,7 +439,7 @@ long long clk_get_parent_rate(struct clk *clk) struct clk *pclk;
debug("%s(clk=%p)\n", __func__, clk); - if (!clk) + if (!clk_valid(clk)) return 0;
pclk = clk_get_parent(clk); @@ -462,7 +462,7 @@ ulong clk_set_rate(struct clk *clk, ulong rate) const struct clk_ops *ops;
debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate); - if (!clk) + if (!clk_valid(clk)) return 0; ops = clk_dev_ops(clk->dev);
@@ -477,7 +477,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) const struct clk_ops *ops;
debug("%s(clk=%p, parent=%p)\n", __func__, clk, parent); - if (!clk) + if (!clk_valid(clk)) return 0; ops = clk_dev_ops(clk->dev);
@@ -494,7 +494,7 @@ int clk_enable(struct clk *clk) int ret;
debug("%s(clk=%p)\n", __func__, clk); - if (!clk) + if (!clk_valid(clk)) return 0; ops = clk_dev_ops(clk->dev);
@@ -554,7 +554,7 @@ int clk_disable(struct clk *clk) int ret;
debug("%s(clk=%p)\n", __func__, clk); - if (!clk) + if (!clk_valid(clk)) return 0; ops = clk_dev_ops(clk->dev);

On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
Add valid check for clk->dev, it's useful when get optional clock even when the clk point is valid, but its dev will be NULL.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/clk/clk-uclass.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Sometimes we may need get (optional) clock without a device, that means use ofnode. e.g. when the phy node has subnode, and there is no device created for subnode, in this case, we need these new APIs to get subnode's clock.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com --- drivers/clk/clk-uclass.c | 28 ++++++++++++++++++++++++++++ include/clk.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+)
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index b7e18668cb..93cb490eb5 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -344,6 +344,34 @@ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk) return clk_get_by_index(dev, index, clk); }
+int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk) +{ + int index; + + debug("%s(node=%p, name=%s, clk=%p)\n", __func__, + ofnode_get_name(node), name, clk); + clk->dev = NULL; + + index = ofnode_stringlist_search(node, "clock-names", name); + if (index < 0) { + debug("fdt_stringlist_search() failed: %d\n", index); + return index; + } + + return clk_get_by_index_nodev(node, index, clk); +} + +int clk_get_optional_nodev(ofnode node, const char *name, struct clk *clk) +{ + int ret; + + ret = clk_get_by_name_nodev(node, name, clk); + if (ret == -ENODATA) + return 0; + + return ret; +} + int clk_release_all(struct clk *clk, int count) { int i, ret; diff --git a/include/clk.h b/include/clk.h index a5ee53d94a..3336301815 100644 --- a/include/clk.h +++ b/include/clk.h @@ -154,6 +154,34 @@ int clk_get_bulk(struct udevice *dev, struct clk_bulk *bulk); */ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk);
+/** + * clk_get_by_name_nodev - Get/request a clock by name without a device. + * + * This is a version of clk_get_by_name() that does not use a device. + * + * @node: The client ofnode. + * @name: The name of the clock to request, within the client's list of + * clocks. + * @clock: A pointer to a clock struct to initialize. + * @return 0 if OK, or a negative error code. + */ +int clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk); + +/** + * clock_get_optional_nodev - Get/request an optinonal clock by name + * without a device. + * @node: The client ofnode. + * @name: The name of the clock to request. + * @name: The name of the clock to request, within the client's list of + * clocks. + * @clock: A pointer to a clock struct to initialize. + * + * Behaves the same as clk_get_by_name_nodev() except where there is + * no clock producer, in this case, skip the error number -ENODATA, and + * the function returns 0. + */ +int clk_get_optional_nodev(ofnode node, const char *name, struct clk *clk); + /** * devm_clk_get - lookup and obtain a managed reference to a clock producer. * @dev: device for clock "consumer" @@ -230,6 +258,18 @@ static inline int clk_get_by_name(struct udevice *dev, const char *name, return -ENOSYS; }
+static inline int +clk_get_by_name_nodev(ofnode node, const char *name, struct clk *clk) +{ + return -ENOSYS; +} + +static inline int +clk_get_optional_nodev(ofnode node, const char *name, struct clk *clk) +{ + return -ENOSYS; +} + static inline int clk_release_all(struct clk *clk, int count) { return -ENOSYS;

On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
Sometimes we may need get (optional) clock without a device, that means use ofnode. e.g. when the phy node has subnode, and there is no device created for subnode, in this case, we need these new APIs to get subnode's clock.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/clk/clk-uclass.c | 28 ++++++++++++++++++++++++++++ include/clk.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

This is used to avoid clk_enable() return -ENOSYS.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com --- drivers/clk/clk_fixed_rate.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/clk/clk_fixed_rate.c b/drivers/clk/clk_fixed_rate.c index f51126793e..2c20eddb0b 100644 --- a/drivers/clk/clk_fixed_rate.c +++ b/drivers/clk/clk_fixed_rate.c @@ -13,8 +13,15 @@ static ulong clk_fixed_rate_get_rate(struct clk *clk) return to_clk_fixed_rate(clk->dev)->fixed_rate; }
+/* avoid clk_enable() return -ENOSYS */ +static int dummy_enable(struct clk *clk) +{ + return 0; +} + const struct clk_ops clk_fixed_rate_ops = { .get_rate = clk_fixed_rate_get_rate, + .enable = dummy_enable, };
static int clk_fixed_rate_ofdata_to_platdata(struct udevice *dev)

On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
This is used to avoid clk_enable() return -ENOSYS.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/clk/clk_fixed_rate.c | 7 +++++++ 1 file changed, 7 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

No need check -ENOSYS anymore after add dummy_enable() for fixed-clock.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com --- drivers/phy/phy-mtk-tphy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/phy/phy-mtk-tphy.c b/drivers/phy/phy-mtk-tphy.c index 3701481256..c4fb404f20 100644 --- a/drivers/phy/phy-mtk-tphy.c +++ b/drivers/phy/phy-mtk-tphy.c @@ -204,9 +204,8 @@ static int mtk_phy_init(struct phy *phy) struct mtk_phy_instance *instance = tphy->phys[phy->id]; int ret;
- /* we may use a fixed-clock here */ ret = clk_enable(&instance->ref_clk); - if (ret && ret != -ENOSYS) + if (ret) return ret;
switch (instance->type) {

On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
No need check -ENOSYS anymore after add dummy_enable() for fixed-clock.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/phy/phy-mtk-tphy.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

If make the ref clock optional, no need refer to fixed-clock when the ref clock is always on or comes from oscillator directly.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com --- drivers/phy/phy-mtk-tphy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/phy/phy-mtk-tphy.c b/drivers/phy/phy-mtk-tphy.c index c4fb404f20..fd33062ae4 100644 --- a/drivers/phy/phy-mtk-tphy.c +++ b/drivers/phy/phy-mtk-tphy.c @@ -338,7 +338,8 @@ static int mtk_tphy_probe(struct udevice *dev) tphy->phys[index] = instance; index++;
- err = clk_get_by_index_nodev(subnode, 0, &instance->ref_clk); + err = clk_get_optional_nodev(subnode, "ref", + &instance->ref_clk); if (err) return err; }

On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
If make the ref clock optional, no need refer to fixed-clock when the ref clock is always on or comes from oscillator directly.
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/phy/phy-mtk-tphy.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
The SSUSB IP's clocks come from ssusbsys module on mt7629, so add its driver
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/clk/mediatek/clk-mt7629.c | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
Who is the maintainer for mediatek in U-Boot?

On Fri, 2019-12-27 at 19:27 -0700, Simon Glass wrote:
On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
The SSUSB IP's clocks come from ssusbsys module on mt7629, so add its driver
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/clk/mediatek/clk-mt7629.c | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
Who is the maintainer for mediatek in U-Boot?
Hi Ryder,
It's you, right?

On Sat, 2019-12-28 at 10:49 +0800, Chunfeng Yun wrote:
On Fri, 2019-12-27 at 19:27 -0700, Simon Glass wrote:
On Sun, 15 Dec 2019 at 20:14, Chunfeng Yun chunfeng.yun@mediatek.com wrote:
The SSUSB IP's clocks come from ssusbsys module on mt7629, so add its driver
Signed-off-by: Chunfeng Yun chunfeng.yun@mediatek.com
drivers/clk/mediatek/clk-mt7629.c | 42 +++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
Who is the maintainer for mediatek in U-Boot?
Hi Ryder,
It's you, right?
for the series Reviewed-by: Ryder Lee ryder.lee@mediatek.com
participants (3)
-
Chunfeng Yun
-
Ryder Lee
-
Simon Glass