2021-06-06 23:46:24

by Ondřej Jirman

[permalink] [raw]
Subject: [PATCH] drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device

From: Saravana Kannan <[email protected]>

On sunxi boards that use HDMI output, HDMI device probe keeps being
avoided indefinitely with these repeated messages in dmesg:

platform 1ee0000.hdmi: probe deferral - supplier 1ef0000.hdmi-phy
not ready

There's a fwnode_link being created with fw_devlink=on between hdmi
and hdmi-phy nodes, because both nodes have 'compatible' property set.

Fw_devlink code assumes that nodes that have compatible property
set will also have a device associated with them by some driver
eventually. This is not the case with the current sun8i-hdmi-phy
driver.

This commit makes sun8i-hdmi-phy into a proper platform device
and fixes the display pipeline probe on sunxi boards that use HDMI.

More context: https://lkml.org/lkml/2021/5/16/203

Signed-off-by: Saravana Kannan <[email protected]>
Signed-off-by: Ondrej Jirman <[email protected]>
---
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 4 +--
drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 3 +-
drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 42 +++++++++++++++++++++++---
3 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index bbdfd5e26ec88..e892a05e69e9b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -209,7 +209,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,
goto err_disable_clk_tmds;
}

- ret = sun8i_hdmi_phy_probe(hdmi, phy_node);
+ ret = sun8i_hdmi_phy_get(hdmi, phy_node);
of_node_put(phy_node);
if (ret) {
dev_err(dev, "Couldn't get the HDMI PHY\n");
@@ -242,7 +242,6 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master,

cleanup_encoder:
drm_encoder_cleanup(encoder);
- sun8i_hdmi_phy_remove(hdmi);
err_disable_clk_tmds:
clk_disable_unprepare(hdmi->clk_tmds);
err_assert_ctrl_reset:
@@ -263,7 +262,6 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master,
struct sun8i_dw_hdmi *hdmi = dev_get_drvdata(dev);

dw_hdmi_unbind(hdmi->hdmi);
- sun8i_hdmi_phy_remove(hdmi);
clk_disable_unprepare(hdmi->clk_tmds);
reset_control_assert(hdmi->rst_ctrl);
gpiod_set_value(hdmi->ddc_en, 0);
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index d4b55af0592f8..8a8adef48be0f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -201,8 +201,7 @@ encoder_to_sun8i_dw_hdmi(struct drm_encoder *encoder)
return container_of(encoder, struct sun8i_dw_hdmi, encoder);
}

-int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node);
-void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi);
+int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node);

void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy);
void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 9994edf675096..947b4231f6449 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -5,6 +5,7 @@

#include <linux/delay.h>
#include <linux/of_address.h>
+#include <linux/of_platform.h>

#include "sun8i_dw_hdmi.h"

@@ -597,10 +598,30 @@ static const struct of_device_id sun8i_hdmi_phy_of_table[] = {
{ /* sentinel */ }
};

-int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
+int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
+{
+ struct platform_device *pdev = of_find_device_by_node(node);
+ struct sun8i_hdmi_phy *phy;
+
+ if (!pdev)
+ return -EPROBE_DEFER;
+
+ phy = platform_get_drvdata(pdev);
+ if (!phy)
+ return -EPROBE_DEFER;
+
+ hdmi->phy = phy;
+
+ put_device(&pdev->dev);
+
+ return 0;
+}
+
+int sun8i_hdmi_phy_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
- struct device *dev = hdmi->dev;
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
struct sun8i_hdmi_phy *phy;
struct resource res;
void __iomem *regs;
@@ -704,7 +725,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
clk_prepare_enable(phy->clk_phy);
}

- hdmi->phy = phy;
+ platform_set_drvdata(pdev, phy);

return 0;

@@ -728,9 +749,9 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
return ret;
}

-void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
+int sun8i_hdmi_phy_remove(struct platform_device *pdev)
{
- struct sun8i_hdmi_phy *phy = hdmi->phy;
+ struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev);

clk_disable_unprepare(phy->clk_mod);
clk_disable_unprepare(phy->clk_bus);
@@ -744,4 +765,15 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi)
clk_put(phy->clk_pll1);
clk_put(phy->clk_mod);
clk_put(phy->clk_bus);
+ return 0;
}
+
+static struct platform_driver sun8i_hdmi_phy_driver = {
+ .probe = sun8i_hdmi_phy_probe,
+ .remove = sun8i_hdmi_phy_remove,
+ .driver = {
+ .name = "sun8i-hdmi-phy",
+ .of_match_table = sun8i_hdmi_phy_of_table,
+ },
+};
+module_platform_driver(sun8i_hdmi_phy_driver);
--
2.31.1


2021-06-07 04:46:36

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device

Hi Ondrej,

I love your patch! Perhaps something to improve:

[auto build test WARNING on sunxi/sunxi/for-next]
[also build test WARNING on drm-intel/for-linux-next drm-tip/drm-tip v5.13-rc5 next-20210604]
[cannot apply to mripard/sunxi/for-next]
[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]

url: https://github.com/0day-ci/linux/commits/Ondrej-Jirman/drm-sun4i-dw-hdmi-Make-HDMI-PHY-into-a-platform-device/20210607-073052
base: https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git sunxi/for-next
config: arm64-allyesconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/c6089f30e38cc9cc85d5c5856420a8c429cdfa23
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Ondrej-Jirman/drm-sun4i-dw-hdmi-Make-HDMI-PHY-into-a-platform-device/20210607-073052
git checkout c6089f30e38cc9cc85d5c5856420a8c429cdfa23
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c:620:5: warning: no previous prototype for 'sun8i_hdmi_phy_probe' [-Wmissing-prototypes]
620 | int sun8i_hdmi_phy_probe(struct platform_device *pdev)
| ^~~~~~~~~~~~~~~~~~~~
>> drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c:752:5: warning: no previous prototype for 'sun8i_hdmi_phy_remove' [-Wmissing-prototypes]
752 | int sun8i_hdmi_phy_remove(struct platform_device *pdev)
| ^~~~~~~~~~~~~~~~~~~~~


vim +/sun8i_hdmi_phy_probe +620 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c

619
> 620 int sun8i_hdmi_phy_probe(struct platform_device *pdev)
621 {
622 const struct of_device_id *match;
623 struct device *dev = &pdev->dev;
624 struct device_node *node = dev->of_node;
625 struct sun8i_hdmi_phy *phy;
626 struct resource res;
627 void __iomem *regs;
628 int ret;
629
630 match = of_match_node(sun8i_hdmi_phy_of_table, node);
631 if (!match) {
632 dev_err(dev, "Incompatible HDMI PHY\n");
633 return -EINVAL;
634 }
635
636 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
637 if (!phy)
638 return -ENOMEM;
639
640 phy->variant = (struct sun8i_hdmi_phy_variant *)match->data;
641
642 ret = of_address_to_resource(node, 0, &res);
643 if (ret) {
644 dev_err(dev, "phy: Couldn't get our resources\n");
645 return ret;
646 }
647
648 regs = devm_ioremap_resource(dev, &res);
649 if (IS_ERR(regs)) {
650 dev_err(dev, "Couldn't map the HDMI PHY registers\n");
651 return PTR_ERR(regs);
652 }
653
654 phy->regs = devm_regmap_init_mmio(dev, regs,
655 &sun8i_hdmi_phy_regmap_config);
656 if (IS_ERR(phy->regs)) {
657 dev_err(dev, "Couldn't create the HDMI PHY regmap\n");
658 return PTR_ERR(phy->regs);
659 }
660
661 phy->clk_bus = of_clk_get_by_name(node, "bus");
662 if (IS_ERR(phy->clk_bus)) {
663 dev_err(dev, "Could not get bus clock\n");
664 return PTR_ERR(phy->clk_bus);
665 }
666
667 phy->clk_mod = of_clk_get_by_name(node, "mod");
668 if (IS_ERR(phy->clk_mod)) {
669 dev_err(dev, "Could not get mod clock\n");
670 ret = PTR_ERR(phy->clk_mod);
671 goto err_put_clk_bus;
672 }
673
674 if (phy->variant->has_phy_clk) {
675 phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
676 if (IS_ERR(phy->clk_pll0)) {
677 dev_err(dev, "Could not get pll-0 clock\n");
678 ret = PTR_ERR(phy->clk_pll0);
679 goto err_put_clk_mod;
680 }
681
682 if (phy->variant->has_second_pll) {
683 phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
684 if (IS_ERR(phy->clk_pll1)) {
685 dev_err(dev, "Could not get pll-1 clock\n");
686 ret = PTR_ERR(phy->clk_pll1);
687 goto err_put_clk_pll0;
688 }
689 }
690 }
691
692 phy->rst_phy = of_reset_control_get_shared(node, "phy");
693 if (IS_ERR(phy->rst_phy)) {
694 dev_err(dev, "Could not get phy reset control\n");
695 ret = PTR_ERR(phy->rst_phy);
696 goto err_put_clk_pll1;
697 }
698
699 ret = reset_control_deassert(phy->rst_phy);
700 if (ret) {
701 dev_err(dev, "Cannot deassert phy reset control: %d\n", ret);
702 goto err_put_rst_phy;
703 }
704
705 ret = clk_prepare_enable(phy->clk_bus);
706 if (ret) {
707 dev_err(dev, "Cannot enable bus clock: %d\n", ret);
708 goto err_deassert_rst_phy;
709 }
710
711 ret = clk_prepare_enable(phy->clk_mod);
712 if (ret) {
713 dev_err(dev, "Cannot enable mod clock: %d\n", ret);
714 goto err_disable_clk_bus;
715 }
716
717 if (phy->variant->has_phy_clk) {
718 ret = sun8i_phy_clk_create(phy, dev,
719 phy->variant->has_second_pll);
720 if (ret) {
721 dev_err(dev, "Couldn't create the PHY clock\n");
722 goto err_disable_clk_mod;
723 }
724
725 clk_prepare_enable(phy->clk_phy);
726 }
727
728 platform_set_drvdata(pdev, phy);
729
730 return 0;
731
732 err_disable_clk_mod:
733 clk_disable_unprepare(phy->clk_mod);
734 err_disable_clk_bus:
735 clk_disable_unprepare(phy->clk_bus);
736 err_deassert_rst_phy:
737 reset_control_assert(phy->rst_phy);
738 err_put_rst_phy:
739 reset_control_put(phy->rst_phy);
740 err_put_clk_pll1:
741 clk_put(phy->clk_pll1);
742 err_put_clk_pll0:
743 clk_put(phy->clk_pll0);
744 err_put_clk_mod:
745 clk_put(phy->clk_mod);
746 err_put_clk_bus:
747 clk_put(phy->clk_bus);
748
749 return ret;
750 }
751
> 752 int sun8i_hdmi_phy_remove(struct platform_device *pdev)
753 {
754 struct sun8i_hdmi_phy *phy = platform_get_drvdata(pdev);
755
756 clk_disable_unprepare(phy->clk_mod);
757 clk_disable_unprepare(phy->clk_bus);
758 clk_disable_unprepare(phy->clk_phy);
759
760 reset_control_assert(phy->rst_phy);
761
762 reset_control_put(phy->rst_phy);
763
764 clk_put(phy->clk_pll0);
765 clk_put(phy->clk_pll1);
766 clk_put(phy->clk_mod);
767 clk_put(phy->clk_bus);
768 return 0;
769 }
770

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (6.89 kB)
.config.gz (75.85 kB)
Download all attachments

2021-06-07 04:57:10

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] drm/sun4i: dw-hdmi: Make HDMI PHY into a platform device

Hi Ondrej,

I love your patch! Yet something to improve:

[auto build test ERROR on sunxi/sunxi/for-next]
[also build test ERROR on drm-intel/for-linux-next drm-tip/drm-tip v5.13-rc5 next-20210604]
[cannot apply to mripard/sunxi/for-next]
[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]

url: https://github.com/0day-ci/linux/commits/Ondrej-Jirman/drm-sun4i-dw-hdmi-Make-HDMI-PHY-into-a-platform-device/20210607-073052
base: https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git sunxi/for-next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/c6089f30e38cc9cc85d5c5856420a8c429cdfa23
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Ondrej-Jirman/drm-sun4i-dw-hdmi-Make-HDMI-PHY-into-a-platform-device/20210607-073052
git checkout c6089f30e38cc9cc85d5c5856420a8c429cdfa23
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

aarch64-linux-ld: drivers/gpu/drm/sun4i/sun8i_hdmi_phy.o: in function `sun8i_hdmi_phy_driver_init':
>> sun8i_hdmi_phy.c:(.init.text+0x0): multiple definition of `init_module'; drivers/gpu/drm/sun4i/sun8i_dw_hdmi.o:sun8i_dw_hdmi.c:(.init.text+0x0): first defined here
aarch64-linux-ld: drivers/gpu/drm/sun4i/sun8i_hdmi_phy.o: in function `sun8i_hdmi_phy_driver_exit':
>> sun8i_hdmi_phy.c:(.exit.text+0x0): multiple definition of `cleanup_module'; drivers/gpu/drm/sun4i/sun8i_dw_hdmi.o:sun8i_dw_hdmi.c:(.exit.text+0x0): first defined here

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (2.19 kB)
.config.gz (53.84 kB)
Download all attachments