From owner-svn-src-all@freebsd.org Tue Feb 23 01:08:40 2016 Return-Path: Delivered-To: svn-src-all@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 79AF3AB1176; Tue, 23 Feb 2016 01:08:40 +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 mx1.freebsd.org (Postfix) with ESMTPS id 54C311A61; Tue, 23 Feb 2016 01:08:40 +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 u1N18des076455; Tue, 23 Feb 2016 01:08:39 GMT (envelope-from ian@FreeBSD.org) Received: (from ian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u1N18db1076454; Tue, 23 Feb 2016 01:08:39 GMT (envelope-from ian@FreeBSD.org) Message-Id: <201602230108.u1N18db1076454@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: ian set sender to ian@FreeBSD.org using -f From: Ian Lepore Date: Tue, 23 Feb 2016 01:08:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r295904 - head/sys/arm/freescale/imx X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Feb 2016 01:08:40 -0000 Author: ian Date: Tue Feb 23 01:08:39 2016 New Revision: 295904 URL: https://svnweb.freebsd.org/changeset/base/295904 Log: Make imx6 systems work again after recent import of new dts files. Linux-driven changes to the way the chip's two interrupt controllers are defined (we only support one of them) led to no interrupt processing, so the system would hang after device instantiation. This workaround just rewrites the FDT data on the fly to get interrupt handling back under the control of the main GIC device. If/when we ever support deep sleep modes that involve powering down the main GIC, we'll have to undo this change, write a driver for the GPC-PIC, and somehow manage the handoff of responsibilities between the two drivers as the chip transitions in/out of deep sleep mode. Modified: head/sys/arm/freescale/imx/imx6_machdep.c Modified: head/sys/arm/freescale/imx/imx6_machdep.c ============================================================================== --- head/sys/arm/freescale/imx/imx6_machdep.c Tue Feb 23 00:45:27 2016 (r295903) +++ head/sys/arm/freescale/imx/imx6_machdep.c Tue Feb 23 01:08:39 2016 (r295904) @@ -94,6 +94,74 @@ fdt_pic_decode_t fdt_pic_table[] = { }; #endif +/* + * Fix FDT data related to interrupts. + * + * Driven by the needs of linux and its drivers (as always), the published FDT + * data for imx6 now sets the interrupt parent for most devices to the GPC + * interrupt controller, which is for use when the chip is in deep-sleep mode. + * We don't support deep sleep or have a GPC-PIC driver; we need all interrupts + * to be handled by the GIC. + * + * Luckily, the change to the FDT data was to assign the GPC as the interrupt + * parent for the soc node and letting that get inherited by all other devices + * (except a few that directly name GIC as their interrupt parent). So we can + * set the world right by just changing the interrupt-parent property of the soc + * node to refer to GIC instead of GPC. This will get us by until we write our + * own GPC driver (or until linux changes its mind and the FDT data again). + * + * We validate that we have data that looks like we expect before changing it: + * - SOC node exists and has GPC as its interrupt parent. + * - GPC node exists and has GIC as its interrupt parent. + * - GIC node exists and is its own interrupt parent. + * + * This applies to all models of imx6. Luckily all of them have the devices + * involved at the same addresses on the same busses, so we don't need any + * per-soc logic. We handle this at platform attach time rather than via the + * fdt_fixup_table, because the latter requires matching on the FDT "model" + * property, and this applies to all boards including those not yet invented. + */ +static void +fix_fdt_interrupt_data(void) +{ + phandle_t gicipar, gicnode, gicxref; + phandle_t gpcipar, gpcnode, gpcxref; + phandle_t socipar, socnode; + int result; + + socnode = OF_finddevice("/soc"); + if (socnode == -1) + return; + result = OF_getencprop(socnode, "interrupt-parent", &socipar, + sizeof(socipar)); + if (result <= 0) + return; + + gicnode = OF_finddevice("/soc/interrupt-controller@00a01000"); + if (gicnode == -1) + return; + result = OF_getencprop(gicnode, "interrupt-parent", &gicipar, + sizeof(gicipar)); + if (result <= 0) + return; + gicxref = OF_xref_from_node(gicnode); + + gpcnode = OF_finddevice("/soc/aips-bus@02000000/gpc@020dc000"); + if (gpcnode == -1) + return; + result = OF_getencprop(gpcnode, "interrupt-parent", &gpcipar, + sizeof(gpcipar)); + if (result <= 0) + return; + gpcxref = OF_xref_from_node(gpcnode); + + if (socipar != gpcxref || gpcipar != gicxref || gicipar != gicxref) + return; + + gicxref = cpu_to_fdt32(gicxref); + OF_setprop(socnode, "interrupt-parent", &gicxref, sizeof(gicxref)); +} + static vm_offset_t imx6_lastaddr(platform_t plat) { @@ -104,6 +172,10 @@ imx6_lastaddr(platform_t plat) static int imx6_attach(platform_t plat) { + + /* Fix soc interrupt-parent property. */ + fix_fdt_interrupt_data(); + /* Inform the MPCore timer driver that its clock is variable. */ arm_tmr_change_frequency(ARM_TMR_FREQUENCY_VARIES);