From e2d5997ffdf5cbf4f7d53584dab2ffc673f50987 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 23 Feb 2018 17:38:49 +0100 Subject: [PATCH 1/5] core: ofnode: add ofnode_get_parent function The Rockchip video drivers need to walk the ofnode-parrents to find an enclosing device that has a UCLASS_DISPLAY driver bound. This adds a ofnode_get_parent()-function that returns the parent-node. Signed-off-by: Philipp Tomsich Tested-by: Klaus Goger Reviewed-by: Anatolij Gustschin --- drivers/core/ofnode.c | 14 ++++++++++++++ include/dm/ofnode.h | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 98f4b539ea..dd6d57c49b 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -165,6 +165,20 @@ ofnode ofnode_next_subnode(ofnode node) fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node))); } +ofnode ofnode_get_parent(ofnode node) +{ + ofnode parent; + + assert(ofnode_valid(node)); + if (ofnode_is_np(node)) + parent = np_to_ofnode(of_get_parent(ofnode_to_np(node))); + else + parent.of_offset = fdt_parent_offset(gd->fdt_blob, + ofnode_to_offset(node)); + + return parent; +} + const char *ofnode_get_name(ofnode node) { assert(ofnode_valid(node)); diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index c359a60f95..6938e62993 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -301,6 +301,14 @@ ofnode ofnode_first_subnode(ofnode node); */ ofnode ofnode_next_subnode(ofnode node); +/** + * ofnode_get_parent() - get the ofnode's parent (enclosing ofnode) + * + * @node: valid node to look up + * @return ofnode reference of the parent node + */ +ofnode ofnode_get_parent(ofnode node); + /** * ofnode_get_name() - get the name of a node * From b4f20767b12a5718ed8549aece73d405c6cac800 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Fri, 23 Feb 2018 17:38:50 +0100 Subject: [PATCH 2/5] core: add ofnode_get_by_phandle() api We need to get ofnode from a phandle, add interface to support both live dt and fdt. Signed-off-by: Kever Yang Reviewed-by: Simon Glass Reviewed-by: Philipp Tomsich Tested-by: Klaus Goger Signed-off-by: Philipp Tomsich --- drivers/core/ofnode.c | 13 +++++++++++++ include/dm/ofnode.h | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index dd6d57c49b..d0bdea08df 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -188,6 +188,19 @@ const char *ofnode_get_name(ofnode node) return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL); } +ofnode ofnode_get_by_phandle(uint phandle) +{ + ofnode node; + + if (of_live_active()) + node = np_to_ofnode(of_find_node_by_phandle(phandle)); + else + node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob, + phandle); + + return node; +} + int ofnode_read_size(ofnode node, const char *propname) { int len; diff --git a/include/dm/ofnode.h b/include/dm/ofnode.h index 6938e62993..0d008404f9 100644 --- a/include/dm/ofnode.h +++ b/include/dm/ofnode.h @@ -317,6 +317,14 @@ ofnode ofnode_get_parent(ofnode node); */ const char *ofnode_get_name(ofnode node); +/** + * ofnode_get_by_phandle() - get ofnode from phandle + * + * @phandle: phandle to look up + * @return ofnode reference to the phandle + */ +ofnode ofnode_get_by_phandle(uint phandle); + /** * ofnode_read_size() - read the size of a property * From 18e48776a689cfa60a54450c6507e95c40bcf42e Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 23 Feb 2018 17:38:51 +0100 Subject: [PATCH 3/5] rockchip: video: rk_hdmi: migrate to livetree The rk_hdmi (shared functions for multiple HDMI mini-drivers) has been using devfdt_get_addr() to read the HDMI controller's IO base address. This will cause a failure with a live tree. This changes the driver to use dev_read_addr() which is safe both for flat trees and live trees. Signed-off-by: Philipp Tomsich Tested-by: Klaus Goger Reviewed-by: Anatolij Gustschin --- drivers/video/rockchip/rk_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c index a9c8fba7e4..b55b397f34 100644 --- a/drivers/video/rockchip/rk_hdmi.c +++ b/drivers/video/rockchip/rk_hdmi.c @@ -84,7 +84,7 @@ int rk_hdmi_ofdata_to_platdata(struct udevice *dev) struct rk_hdmi_priv *priv = dev_get_priv(dev); struct dw_hdmi *hdmi = &priv->hdmi; - hdmi->ioaddr = (ulong)devfdt_get_addr(dev); + hdmi->ioaddr = (ulong)dev_read_addr(dev); hdmi->mpll_cfg = rockchip_mpll_cfg; hdmi->phy_cfg = rockchip_phy_config; From 5de0b5a36a173e7fe311951ba115dec569cc0c8d Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 23 Feb 2018 17:38:52 +0100 Subject: [PATCH 4/5] rockchip: video: rk_vop: migrate to livetree This migrates rk_vop (the shared functions used by multiple VOP mini-drivers) to be compatible with a live tree. Unfortunately, there's (i) a lot of tree traversal needed for a VOP (as each active VOP vnode references back to the endpoints in the encoders and vice versa) to configure the connection between VOPs and encoders; (ii) the DTS binding is not too sane and one needs to walk a node's parents (the original code just assumed that the device would live 3 levels above the property linked through a phandle) until a UCLASS_DISPLAY device can be found. As part of the migration, the code for finding the enclosing display device has been changed to not assume a specific depth of nesting (i.e. we walk until we reach the root or find a matching device) and to use the newly introduced (in the same series) ofnode_get_parent() function. Signed-off-by: Philipp Tomsich Tested-by: Klaus Goger Reviewed-by: Anatolij Gustschin --- drivers/video/rockchip/rk_vop.c | 83 ++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c index c979049b5b..1288608207 100644 --- a/drivers/video/rockchip/rk_vop.c +++ b/drivers/video/rockchip/rk_vop.c @@ -218,41 +218,67 @@ static void rkvop_mode_set(struct udevice *dev, * node within the VOP's 'port' list. * @return 0 if OK, -ve if something went wrong */ -static int rk_display_init(struct udevice *dev, ulong fbbase, int ep_node) +static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node) { struct video_priv *uc_priv = dev_get_uclass_priv(dev); - const void *blob = gd->fdt_blob; struct rk_vop_priv *priv = dev_get_priv(dev); int vop_id, remote_vop_id; struct rk3288_vop *regs = priv->regs; struct display_timing timing; struct udevice *disp; - int ret, remote, i, offset; + int ret; + u32 remote_phandle; struct display_plat *disp_uc_plat; struct clk clk; enum video_log2_bpp l2bpp; + ofnode remote; - vop_id = fdtdec_get_int(blob, ep_node, "reg", -1); + debug("%s(%s, %lu, %s)\n", __func__, + dev_read_name(dev), fbbase, ofnode_get_name(ep_node)); + + vop_id = ofnode_read_s32_default(ep_node, "reg", -1); debug("vop_id=%d\n", vop_id); - remote = fdtdec_lookup_phandle(blob, ep_node, "remote-endpoint"); - if (remote < 0) + ret = ofnode_read_u32(ep_node, "remote-endpoint", &remote_phandle); + if (ret) + return ret; + + remote = ofnode_get_by_phandle(remote_phandle); + if (!ofnode_valid(remote)) return -EINVAL; - remote_vop_id = fdtdec_get_int(blob, remote, "reg", -1); + remote_vop_id = ofnode_read_u32_default(remote, "reg", -1); debug("remote vop_id=%d\n", remote_vop_id); - for (i = 0, offset = remote; i < 3 && offset > 0; i++) - offset = fdt_parent_offset(blob, offset); - if (offset < 0) { - debug("%s: Invalid remote-endpoint position\n", dev->name); - return -EINVAL; - } + /* + * The remote-endpoint references into a subnode of the encoder + * (i.e. HDMI, MIPI, etc.) with the DTS looking something like + * the following (assume 'hdmi_in_vopl' to be referenced): + * + * hdmi: hdmi@ff940000 { + * ports { + * hdmi_in: port { + * hdmi_in_vopb: endpoint@0 { ... }; + * hdmi_in_vopl: endpoint@1 { ... }; + * } + * } + * } + * + * The original code had 3 steps of "walking the parent", but + * a much better (as in: less likely to break if the DTS + * changes) way of doing this is to "find the enclosing device + * of UCLASS_DISPLAY". + */ + while (ofnode_valid(remote)) { + remote = ofnode_get_parent(remote); + if (!ofnode_valid(remote)) { + debug("%s(%s): no UCLASS_DISPLAY for remote-endpoint\n", + __func__, dev_read_name(dev)); + return -EINVAL; + } - ret = uclass_find_device_by_of_offset(UCLASS_DISPLAY, offset, &disp); - if (ret) { - debug("%s: device '%s' display not found (ret=%d)\n", __func__, - dev->name, ret); - return ret; - } + uclass_find_device_by_ofnode(UCLASS_DISPLAY, remote, &disp); + if (disp) + break; + }; disp_uc_plat = dev_get_uclass_platdata(disp); debug("Found device '%s', disp_uc_priv=%p\n", disp->name, disp_uc_plat); @@ -334,16 +360,15 @@ void rk_vop_probe_regulators(struct udevice *dev, int rk_vop_probe(struct udevice *dev) { struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); - const void *blob = gd->fdt_blob; struct rk_vop_priv *priv = dev_get_priv(dev); int ret = 0; - int port, node; + ofnode port, node; /* Before relocation we don't need to do anything */ if (!(gd->flags & GD_FLG_RELOC)) return 0; - priv->regs = (struct rk3288_vop *)devfdt_get_addr(dev); + priv->regs = (struct rk3288_vop *)dev_read_addr(dev); /* * Try all the ports until we find one that works. In practice this @@ -353,12 +378,16 @@ int rk_vop_probe(struct udevice *dev) * clock so it is currently not possible to use more than one display * device simultaneously. */ - port = fdt_subnode_offset(blob, dev_of_offset(dev), "port"); - if (port < 0) + port = dev_read_subnode(dev, "port"); + if (!ofnode_valid(port)) { + debug("%s(%s): 'port' subnode not found\n", + __func__, dev_read_name(dev)); return -EINVAL; - for (node = fdt_first_subnode(blob, port); - node > 0; - node = fdt_next_subnode(blob, node)) { + } + + for (node = ofnode_first_subnode(port); + ofnode_valid(node); + node = dev_read_next_subnode(node)) { ret = rk_display_init(dev, plat->base, node); if (ret) debug("Device failed: ret=%d\n", ret); From 3f56552227d1b711cf7dcae986ae0a3f2a91e8d7 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 23 Feb 2018 17:38:53 +0100 Subject: [PATCH 5/5] rockchip: video: update MAINTAINERS The video drivers (VOP, HDMI encoder, LVDS encoder, MIPI encoder) for Rockchip SOCs are self-contained and are mainly impacted by other changes in the architecture support (e.g. pinctrl, clocking, etc). Let's add these to the list of files maintained as part of the Rockchip port. Signed-off-by: Philipp Tomsich Reviewed-by: Anatolij Gustschin --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index d2f8c513e0..077828cf1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -163,6 +163,7 @@ F: drivers/misc/rockchip-efuse.c F: drivers/pinctrl/rockchip/ F: drivers/ram/rockchip/ F: drivers/sysreset/sysreset_rockchip.c +F: drivers/video/rockchip/ F: tools/rkcommon.c F: tools/rkcommon.h F: tools/rkimage.c