From owner-svn-src-stable-11@freebsd.org Sat Jan 6 19:24:50 2018 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B9EC3EC7930; Sat, 6 Jan 2018 19:24:50 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 959CC7BDA1; Sat, 6 Jan 2018 19:24:50 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id D7598169C8; Sat, 6 Jan 2018 19:24:49 +0000 (UTC) (envelope-from ian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w06JOn5h004255; Sat, 6 Jan 2018 19:24:49 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w06JOnlF004254; Sat, 6 Jan 2018 19:24:49 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201801061924.w06JOnlF004254@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Sat, 6 Jan 2018 19:24:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r327633 - stable/11/sys/arm/freescale/imx X-SVN-Group: stable-11 X-SVN-Commit-Author: ian X-SVN-Commit-Paths: stable/11/sys/arm/freescale/imx X-SVN-Commit-Revision: 327633 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 06 Jan 2018 19:24:50 -0000 Author: ian Date: Sat Jan 6 19:24:49 2018 New Revision: 327633 URL: https://svnweb.freebsd.org/changeset/base/327633 Log: Fix imx6 hdmi init after r323553. This is a direct commit to 11-stable because major architectural changes in 12 prevent a direct MFC of the affected code. Conceptually, this is... MFC r324416: Fix imx6 hdmi init after r323553, which used a config_intrhook to defer the attachment of i2c devices needed by hdmi. The hdmi init also uses an intrhook callback to defer initialization, and if the hdmi callback runs first, the i2c devices will not yet have registered their device_t in association with their FDT phandle, which allows cross- device references on FDT systems. Now the hdmi deferred init checks for the i2c device registration, and if it's not complete yet, it registers as an eventhandler watching for newbus attach events. When the i2c device eventually attaches, the hdmi driver unregisters from watching further events, and continues with the hdmi init. Because the function signatures for an intrhook callback and an event handler callback are the same, a single function is used for both callbacks. Reported by: Russell Haley Modified: stable/11/sys/arm/freescale/imx/imx6_hdmi.c Modified: stable/11/sys/arm/freescale/imx/imx6_hdmi.c ============================================================================== --- stable/11/sys/arm/freescale/imx/imx6_hdmi.c Sat Jan 6 18:42:17 2018 (r327632) +++ stable/11/sys/arm/freescale/imx/imx6_hdmi.c Sat Jan 6 19:24:49 2018 (r327633) @@ -63,11 +63,11 @@ struct imx_hdmi_softc { device_t sc_dev; struct resource *sc_mem_res; int sc_mem_rid; - struct intr_config_hook sc_mode_hook; struct videomode sc_mode; uint8_t *sc_edid; uint8_t sc_edid_len; phandle_t sc_i2c_xref; + eventhandler_tag eh_tag; }; static struct ofw_compat_data compat_data[] = { @@ -626,15 +626,51 @@ hdmi_edid_read(struct imx_hdmi_softc *sc, uint8_t **ed return (result); } +/* + * Deferred HDMI init. dwc_hdmi_init() does i2c transfers for DDC/EDID. The imx + * i2c devices also use a config_intrhook function to finish their init, because + * they require interrupts to perform transfers. There is no way to control + * whether the i2c or our hdmi intrhook function runs first. If we go first we + * have to continue waiting until after the i2c driver is ready to do transfers + * and has registered its phandle. + * + * This function is used as both a config_intrhook function and after that as an + * eventhandler callback function (if necessary), to see if our i2c device is + * ready yet. When it is, continue with hdmi init. When first called as an + * intrhook function the i2c devices might be ready, in which case we never + * register as an eventhandler at all. Otherwise we register to see newbus + * attach events, and as each device attaches we check to see whether it was the + * i2c device we care about. Once we have our i2c device we unregister from + * seeing further attach events. + */ static void -imx_hdmi_detect_cable(void *arg) +imx_hdmi_init(void *dev) { struct imx_hdmi_softc *sc; - sc = arg; - EVENTHANDLER_INVOKE(hdmi_event, sc->sc_dev, HDMI_EVENT_CONNECTED); - /* Finished with the interrupt hook */ - config_intrhook_disestablish(&sc->sc_mode_hook); + sc = device_get_softc((device_t)dev); + + if (OF_device_from_xref(sc->sc_i2c_xref) != NULL) { + if (sc->eh_tag != NULL) { + EVENTHANDLER_DEREGISTER_NOWAIT(device_attach, + sc->eh_tag); + } + WR1(sc, HDMI_PHY_POL0, HDMI_PHY_HPD); + WR1(sc, HDMI_IH_PHY_STAT0, HDMI_IH_PHY_STAT0_HPD); + if ((RD1(sc, HDMI_IH_PHY_STAT0) & HDMI_IH_PHY_STAT0_HPD) != 0) { + EVENTHANDLER_INVOKE(hdmi_event, sc->sc_dev, + HDMI_EVENT_CONNECTED); + } + return; + } + + if (bootverbose) + device_printf((device_t)dev, "Waiting for DDC i2c device\n"); + + if (sc->eh_tag == NULL) { + sc->eh_tag = EVENTHANDLER_REGISTER(device_attach, + imx_hdmi_init, dev, EVENTHANDLER_PRI_ANY); + } } static int @@ -673,14 +709,6 @@ imx_hdmi_attach(device_t dev) goto out; } - sc->sc_mode_hook.ich_func = imx_hdmi_detect_cable; - sc->sc_mode_hook.ich_arg = sc; - - if (config_intrhook_establish(&sc->sc_mode_hook) != 0) { - err = ENOMEM; - goto out; - } - node = ofw_bus_get_node(dev); if (OF_getencprop(node, "ddc-i2c-bus", &i2c_xref, sizeof(i2c_xref)) == -1) sc->sc_i2c_xref = 0; @@ -702,8 +730,8 @@ imx_hdmi_attach(device_t dev) gpr3 |= IOMUXC_GPR3_HDMI_IPU1_DI0; imx_iomux_gpr_set(IOMUXC_GPR3, gpr3); - WR1(sc, HDMI_PHY_POL0, HDMI_PHY_HPD); - WR1(sc, HDMI_IH_PHY_STAT0, HDMI_IH_PHY_STAT0_HPD); + /* Further HDMI init requires interrupts for i2c transfers. */ + config_intrhook_oneshot(imx_hdmi_init, dev); out: