svn commit: r316370 - in head/sys/arm: arm conf versatile

Oleksandr Tymoshenko gonzo at FreeBSD.org
Sat Apr 1 20:10:10 UTC 2017


Author: gonzo
Date: Sat Apr  1 20:10:08 2017
New Revision: 316370
URL: https://svnweb.freebsd.org/changeset/base/316370

Log:
  [versatilepb] Convert VERSATILEPB kernel to INTRNG and switch to upstream DTB
  
  Scope of this change is somewhat larger than just converting to INTRNG.
  The reason for this is that INTRNG support required switching from custom
  to upstream DTS because custom DTS didn't have interrup routing information.
  This switch caused rewrite of PCI and CLCD drivers and adding SCM module.
  List of changes in this commit:
  
  - Enable INTRNG and switch to versatile-pb.dts
  
  - Add SCM driver that controls various peripheral devices like LCD or
    PCI controller. Previously registers required for power-up and
    configuring peripherals were part of their respective nodes. Upstream
    DTS has dedicated node for SCM
  
  - Convert PL190 driver to INTRNG
  
  - Convert Versatile SIC (secondary interrupt controller) to INTRNG
  
  - Refactor CLCD driver to use SCM API to power up and configuration
  
  - Refactor PCI driver to use SCM API to enable controller
  
  - Refactor PCI driver to use interrupt map provided in DTS for
    interrupt routing. As a result it fixes broken IRQ routing and
    it's no longer required to run QEMU with "-global versatile_pci.broken-irq-mapping=1"
    command-line arguments

Added:
  head/sys/arm/versatile/versatile_scm.c   (contents, props changed)
  head/sys/arm/versatile/versatile_scm.h   (contents, props changed)
Modified:
  head/sys/arm/arm/pl190.c
  head/sys/arm/conf/VERSATILEPB
  head/sys/arm/versatile/files.versatile
  head/sys/arm/versatile/versatile_clcd.c
  head/sys/arm/versatile/versatile_pci.c
  head/sys/arm/versatile/versatile_sic.c

Modified: head/sys/arm/arm/pl190.c
==============================================================================
--- head/sys/arm/arm/pl190.c	Sat Apr  1 19:27:06 2017	(r316369)
+++ head/sys/arm/arm/pl190.c	Sat Apr  1 20:10:08 2017	(r316370)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at bluezbox.com>
+ * Copyright (c) 2012-2017 Oleksandr Tymoshenko <gonzo at bluezbox.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,6 @@
  * SUCH DAMAGE.
  */
 
-
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -34,6 +33,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/ktr.h>
 #include <sys/module.h>
+#include <sys/proc.h>
 #include <sys/rman.h>
 #include <machine/bus.h>
 #include <machine/intr.h>
@@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 
+#include "pic_if.h"
+
 #ifdef  DEBUG
 #define dprintf(fmt, args...) printf(fmt, ##args)
 #else
@@ -62,17 +64,139 @@ __FBSDID("$FreeBSD$");
 
 #define	VIC_NIRQS	32
 
+struct pl190_intc_irqsrc {
+	struct intr_irqsrc		isrc;
+	u_int				irq;
+};
+
 struct pl190_intc_softc {
-	device_t		sc_dev;
+	device_t		dev;
+	struct mtx		mtx;
 	struct resource *	intc_res;
+	struct pl190_intc_irqsrc	isrcs[VIC_NIRQS];
 };
 
-static struct pl190_intc_softc *pl190_intc_sc = NULL;
+#define	INTC_VIC_READ_4(sc, reg)		\
+    bus_read_4(sc->intc_res, (reg))
+#define	INTC_VIC_WRITE_4(sc, reg, val)		\
+    bus_write_4(sc->intc_res, (reg), (val))
+
+#define	VIC_LOCK(_sc) mtx_lock_spin(&(_sc)->mtx)
+#define	VIC_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->mtx)
+
+static inline void
+pl190_intc_irq_dispatch(struct pl190_intc_softc *sc, u_int irq,
+    struct trapframe *tf)
+{
+	struct pl190_intc_irqsrc *src;
+
+	src = &sc->isrcs[irq];
+	if (intr_isrc_dispatch(&src->isrc, tf) != 0)
+		device_printf(sc->dev, "Stray irq %u detected\n", irq);
+}
+
+static int
+pl190_intc_intr(void *arg)
+{
+	struct pl190_intc_softc *sc;
+	u_int cpu;
+	uint32_t num, pending;
+	struct trapframe *tf;
+
+	sc = arg;
+	cpu = PCPU_GET(cpuid);
+	tf = curthread->td_intr_frame;
+
+	VIC_LOCK(sc);
+	pending = INTC_VIC_READ_4(sc, VICIRQSTATUS);
+	VIC_UNLOCK(sc);
+	for (num = 0 ; num < VIC_NIRQS; num++) {
+		if (pending & (1 << num))
+			pl190_intc_irq_dispatch(sc, num, tf);
+	}
+
+	return (FILTER_HANDLED);
+}
+
+static void
+pl190_intc_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct pl190_intc_softc *sc;
+	struct pl190_intc_irqsrc *src;
+
+	sc = device_get_softc(dev);
+	src = (struct pl190_intc_irqsrc *)isrc;
+
+	VIC_LOCK(sc);
+	INTC_VIC_WRITE_4(sc, VICINTENCLEAR, (1 << src->irq));
+	VIC_UNLOCK(sc);
+}
+
+static void
+pl190_intc_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct pl190_intc_softc *sc;
+	struct pl190_intc_irqsrc *src;
 
-#define	intc_vic_read_4(reg)		\
-    bus_read_4(pl190_intc_sc->intc_res, (reg))
-#define	intc_vic_write_4(reg, val)		\
-    bus_write_4(pl190_intc_sc->intc_res, (reg), (val))
+	sc = device_get_softc(dev);
+	src = (struct pl190_intc_irqsrc *)isrc;
+
+	VIC_LOCK(sc);
+	INTC_VIC_WRITE_4(sc, VICINTENABLE, (1 << src->irq));
+	VIC_UNLOCK(sc);
+}
+
+static int
+pl190_intc_map_intr(device_t dev, struct intr_map_data *data,
+    struct intr_irqsrc **isrcp)
+{
+	struct intr_map_data_fdt *daf;
+	struct pl190_intc_softc *sc;
+
+	if (data->type != INTR_MAP_DATA_FDT)
+		return (ENOTSUP);
+
+	daf = (struct intr_map_data_fdt *)data;
+	if (daf->ncells != 1 || daf->cells[0] >= VIC_NIRQS)
+		return (EINVAL);
+
+	sc = device_get_softc(dev);
+	*isrcp = &sc->isrcs[daf->cells[0]].isrc;
+	return (0);
+}
+
+static void
+pl190_intc_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+	pl190_intc_disable_intr(dev, isrc);
+}
+
+static void
+pl190_intc_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct pl190_intc_irqsrc *src;
+
+	src = (struct pl190_intc_irqsrc *)isrc;
+	pl190_intc_enable_intr(dev, isrc);
+	arm_irq_memory_barrier(src->irq);
+}
+
+static void
+pl190_intc_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct pl190_intc_irqsrc *src;
+
+	src = (struct pl190_intc_irqsrc *)isrc;
+	arm_irq_memory_barrier(src->irq);
+}
+
+static int
+pl190_intc_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+    struct resource *res, struct intr_map_data *data)
+{
+
+	return (0);
+}
 
 static int
 pl190_intc_probe(device_t dev)
@@ -90,14 +214,20 @@ pl190_intc_probe(device_t dev)
 static int
 pl190_intc_attach(device_t dev)
 {
-	struct		pl190_intc_softc *sc = device_get_softc(dev);
+	struct		pl190_intc_softc *sc;
 	uint32_t	id;
 	int		i, rid;
-
-	sc->sc_dev = dev;
-
-	if (pl190_intc_sc)
-		return (ENXIO);
+	struct		pl190_intc_irqsrc *isrcs;
+	struct intr_pic *pic;
+	int		error;
+	uint32_t	irq;
+	const char	*name;
+	phandle_t	xref;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	mtx_init(&sc->mtx, device_get_nameunit(dev), "pl190",
+	    MTX_SPIN);
 
 	/* Request memory resources */
 	rid = 0;
@@ -108,20 +238,17 @@ pl190_intc_attach(device_t dev)
 		return (ENXIO);
 	}
 
-	pl190_intc_sc = sc;
 	/*
 	 * All interrupts should use IRQ line
 	 */
-	intc_vic_write_4(VICINTSELECT, 0x00000000);
+	INTC_VIC_WRITE_4(sc, VICINTSELECT, 0x00000000);
 	/* Disable all interrupts */
-	intc_vic_write_4(VICINTENCLEAR, 0xffffffff);
-	/* Enable INT31, SIC IRQ */
-	intc_vic_write_4(VICINTENABLE, (1U << 31));
+	INTC_VIC_WRITE_4(sc, VICINTENCLEAR, 0xffffffff);
 
 	id = 0;
 	for (i = 3; i >= 0; i--) {
 		id = (id << 8) |
-		     (intc_vic_read_4(VICPERIPHID + i*4) & 0xff);
+		     (INTC_VIC_READ_4(sc, VICPERIPHID + i*4) & 0xff);
 	}
 
 	device_printf(dev, "Peripheral ID: %08x\n", id);
@@ -129,18 +256,43 @@ pl190_intc_attach(device_t dev)
 	id = 0;
 	for (i = 3; i >= 0; i--) {
 		id = (id << 8) |
-		     (intc_vic_read_4(VICPRIMECELLID + i*4) & 0xff);
+		     (INTC_VIC_READ_4(sc, VICPRIMECELLID + i*4) & 0xff);
 	}
 
 	device_printf(dev, "PrimeCell ID: %08x\n", id);
 
-	return (0);
+	/* PIC attachment */
+	isrcs = sc->isrcs;
+	name = device_get_nameunit(sc->dev);
+	for (irq = 0; irq < VIC_NIRQS; irq++) {
+		isrcs[irq].irq = irq;
+		error = intr_isrc_register(&isrcs[irq].isrc, sc->dev,
+		    0, "%s,%u", name, irq);
+		if (error != 0)
+			return (error);
+	}
+
+	xref = OF_xref_from_node(ofw_bus_get_node(sc->dev));
+	pic = intr_pic_register(sc->dev, xref);
+	if (pic == NULL)
+		return (ENXIO);
+
+	return (intr_pic_claim_root(sc->dev, xref, pl190_intc_intr, sc, 0));
 }
 
 static device_method_t pl190_intc_methods[] = {
 	DEVMETHOD(device_probe,		pl190_intc_probe),
 	DEVMETHOD(device_attach,	pl190_intc_attach),
-	{ 0, 0 }
+
+	DEVMETHOD(pic_disable_intr,	pl190_intc_disable_intr),
+	DEVMETHOD(pic_enable_intr,	pl190_intc_enable_intr),
+	DEVMETHOD(pic_map_intr,		pl190_intc_map_intr),
+	DEVMETHOD(pic_post_filter,	pl190_intc_post_filter),
+	DEVMETHOD(pic_post_ithread,	pl190_intc_post_ithread),
+	DEVMETHOD(pic_pre_ithread,	pl190_intc_pre_ithread),
+	DEVMETHOD(pic_setup_intr,	pl190_intc_setup_intr),
+
+	DEVMETHOD_END
 };
 
 static driver_t pl190_intc_driver = {
@@ -153,39 +305,3 @@ static devclass_t pl190_intc_devclass;
 
 EARLY_DRIVER_MODULE(intc, simplebus, pl190_intc_driver, pl190_intc_devclass,
     0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
-
-int
-arm_get_next_irq(int last_irq)
-{
-	uint32_t pending;
-	int32_t irq = last_irq + 1;
-
-	/* Sanity check */
-	if (irq < 0)
-		irq = 0;
-
-	pending = intc_vic_read_4(VICIRQSTATUS);
-	while (irq < VIC_NIRQS) {
-		if (pending & (1 << irq))
-			return (irq);
-		irq++;
-	}
-
-	return (-1);
-}
-
-void
-arm_mask_irq(uintptr_t nb)
-{
-
-	dprintf("%s: %d\n", __func__, nb);
-	intc_vic_write_4(VICINTENCLEAR, (1 << nb));
-}
-
-void
-arm_unmask_irq(uintptr_t nb)
-{
-
-	dprintf("%s: %d\n", __func__, nb);
-	intc_vic_write_4(VICINTENABLE, (1 << nb));
-}

Modified: head/sys/arm/conf/VERSATILEPB
==============================================================================
--- head/sys/arm/conf/VERSATILEPB	Sat Apr  1 19:27:06 2017	(r316369)
+++ head/sys/arm/conf/VERSATILEPB	Sat Apr  1 20:10:08 2017	(r316370)
@@ -68,7 +68,9 @@ makeoptions	SC_DFLT_FONT=cp437
 device		md
 device		random			# Entropy device
 
+options 	INTRNG
+
 # Flattened Device Tree
 options 	FDT			# Configure using FDT/DTB data
 options 	FDT_DTB_STATIC
-makeoptions	FDT_DTS_FILE=versatilepb.dts
+makeoptions	FDT_DTS_FILE=versatile-pb.dts

Modified: head/sys/arm/versatile/files.versatile
==============================================================================
--- head/sys/arm/versatile/files.versatile	Sat Apr  1 19:27:06 2017	(r316369)
+++ head/sys/arm/versatile/files.versatile	Sat Apr  1 20:10:08 2017	(r316370)
@@ -6,6 +6,7 @@ arm/versatile/versatile_machdep.c		stand
 arm/versatile/versatile_clcd.c			optional sc
 arm/versatile/versatile_common.c		standard
 arm/versatile/versatile_pci.c			optional pci
+arm/versatile/versatile_scm.c			standard
 arm/versatile/versatile_sic.c			standard
 arm/versatile/versatile_timer.c			standard
 

Modified: head/sys/arm/versatile/versatile_clcd.c
==============================================================================
--- head/sys/arm/versatile/versatile_clcd.c	Sat Apr  1 19:27:06 2017	(r316369)
+++ head/sys/arm/versatile/versatile_clcd.c	Sat Apr  1 20:10:08 2017	(r316370)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012-2017 Oleksandr Tymoshenko <gonzo at freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,22 +49,12 @@ __FBSDID("$FreeBSD$");
 #include <dev/fb/fbreg.h>
 #include <dev/syscons/syscons.h>
 
+#include <arm/versatile/versatile_scm.h>
+
 #include <machine/bus.h>
 
 #define	PL110_VENDOR_ARM926PXP	1
 
-#define	MEM_SYS		0
-#define	MEM_CLCD	1
-#define MEM_REGIONS	2
-
-#define	SYS_CLCD		0x00
-#define		SYS_CLCD_CLCDID_SHIFT	0x08
-#define		SYS_CLCD_CLCDID_MASK	0x1f
-#define		SYS_CLCD_PWR3V5VSWITCH	(1 << 4)
-#define		SYS_CLCD_VDDPOSSWITCH 	(1 << 3)
-#define		SYS_CLCD_NLCDIOON  	(1 << 2)
-#define		SYS_CLCD_LCD_MODE_MASK	0x03
-
 #define	CLCD_MODE_RGB888	0x0
 #define	CLCD_MODE_RGB555	0x01
 #define	CLCD_MODE_RBG565	0x02
@@ -119,18 +109,13 @@ __FBSDID("$FreeBSD$");
 #define dprintf(fmt, args...)
 #endif
 
-#define	versatile_clcdc_sys_read_4(sc, reg)	\
-	bus_read_4((sc)->mem_res[MEM_SYS], (reg))
-#define	versatile_clcdc_sys_write_4(sc, reg, val)	\
-	bus_write_4((sc)->mem_res[MEM_SYS], (reg), (val))
-
 #define	versatile_clcdc_read_4(sc, reg)	\
-	bus_read_4((sc)->mem_res[MEM_CLCD], (reg))
+	bus_read_4((sc)->mem_res, (reg))
 #define	versatile_clcdc_write_4(sc, reg, val)	\
-	bus_write_4((sc)->mem_res[MEM_CLCD], (reg), (val))
+	bus_write_4((sc)->mem_res, (reg), (val))
 
 struct versatile_clcdc_softc {
-	struct resource*	mem_res[MEM_REGIONS];
+	struct resource*	mem_res;
 
 	struct mtx		mtx;
 
@@ -205,12 +190,6 @@ static u_char mouse_pointer[16] = {
 
 static struct video_adapter_softc va_softc;
 
-static struct resource_spec versatile_clcdc_mem_spec[] = {
-	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
-	{ SYS_RES_MEMORY, 1, RF_ACTIVE },
-	{ -1, 0, 0 }
-};
-
 static int versatilefb_configure(int);
 static void versatilefb_update_margins(video_adapter_t *adp);
 
@@ -246,21 +225,25 @@ versatile_clcdc_attach(device_t dev)
 {
 	struct versatile_clcdc_softc *sc = device_get_softc(dev);
 	struct video_adapter_softc *va_sc = &va_softc;
-	int err;
+	int err, rid;
 	uint32_t reg;
 	int clcdid;
 	int dma_size;
 
 	/* Request memory resources */
-	err = bus_alloc_resources(dev, versatile_clcdc_mem_spec,
-		sc->mem_res);
-	if (err) {
-		device_printf(dev, "Error: could not allocate memory resources\n");
+	rid = 0;
+	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+	if (sc->mem_res == NULL) {
+		device_printf(dev, "could not allocate memory resources\n");
 		return (ENXIO);
 	}
 
-	reg = versatile_clcdc_sys_read_4(sc, SYS_CLCD);
-	clcdid = (reg >> SYS_CLCD_CLCDID_SHIFT) & SYS_CLCD_CLCDID_MASK;
+	err = versatile_scm_reg_read_4(SCM_CLCD, &reg);
+	if (err) {
+		device_printf(dev, "failed to read SCM register\n");
+		goto fail;
+	}
+	clcdid = (reg >> SCM_CLCD_CLCDID_SHIFT) & SCM_CLCD_CLCDID_MASK;
 	switch (clcdid) {
 		case 31:
 			device_printf(dev, "QEMU VGA 640x480\n");
@@ -272,17 +255,17 @@ versatile_clcdc_attach(device_t dev)
 			goto fail;
 	}
 
-	reg &= ~SYS_CLCD_LCD_MODE_MASK;
+	reg &= ~SCM_CLCD_LCD_MODE_MASK;
 	reg |= CLCD_MODE_RGB565;
 	sc->mode = CLCD_MODE_RGB565;
-	versatile_clcdc_sys_write_4(sc, SYS_CLCD, reg);
-	dma_size = sc->width*sc->height*2;
-
-	/*
+	versatile_scm_reg_write_4(SCM_CLCD, reg);
+ 	dma_size = sc->width*sc->height*2;
+ 
+ 	/*
 	 * Power on LCD
 	 */
-	reg |= SYS_CLCD_PWR3V5VSWITCH | SYS_CLCD_NLCDIOON;
-	versatile_clcdc_sys_write_4(sc, SYS_CLCD, reg);
+	reg |= SCM_CLCD_PWR3V5VSWITCH | SCM_CLCD_NLCDIOON;
+	versatile_scm_reg_write_4(SCM_CLCD, reg);
 
 	/*
 	 * XXX: hardcoded timing for VGA. For other modes/panels
@@ -655,7 +638,6 @@ versatilefb_init(int unit, video_adapter
 	sc->xmargin = (sc->width - (vi->vi_width * vi->vi_cwidth)) / 2;
 	sc->ymargin = (sc->height - (vi->vi_height * vi->vi_cheight))/2;
 
-
 	adp->va_window = (vm_offset_t) versatilefb_static_window;
 	adp->va_flags |= V_ADP_FONT /* | V_ADP_COLOR | V_ADP_MODECHANGE */;
 

Modified: head/sys/arm/versatile/versatile_pci.c
==============================================================================
--- head/sys/arm/versatile/versatile_pci.c	Sat Apr  1 19:27:06 2017	(r316369)
+++ head/sys/arm/versatile/versatile_pci.c	Sat Apr  1 20:10:08 2017	(r316370)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012-2017 Oleksandr Tymoshenko <gonzo at freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -52,17 +52,17 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/ofw_pci.h>
+
+#include <arm/versatile/versatile_scm.h>
 
 #include <machine/bus.h>
 #include <machine/fdt.h>
 
-#define	MEM_SYS		0
-#define	MEM_CORE	1
-#define	MEM_BASE	2
-#define	MEM_CONF_BASE	3
-#define MEM_REGIONS	4
-
-#define	SYS_PCICTL		0x00
+#define	MEM_CORE	0
+#define	MEM_BASE	1
+#define	MEM_CONF_BASE	2
+#define MEM_REGIONS	3
 
 #define	PCI_CORE_IMAP0		0x00
 #define	PCI_CORE_IMAP1		0x04
@@ -92,12 +92,6 @@ __FBSDID("$FreeBSD$");
 #define dprintf(fmt, args...)
 #endif
 
-
-#define	versatile_pci_sys_read_4(reg)	\
-	bus_read_4(sc->mem_res[MEM_SYS], (reg))
-#define	versatile_pci_sys_write_4(reg, val)	\
-	bus_write_4(sc->mem_res[MEM_SYS], (reg), (val))
-
 #define	versatile_pci_core_read_4(reg)	\
 	bus_read_4(sc->mem_res[MEM_CORE], (reg))
 #define	versatile_pci_core_write_4(reg, val)	\
@@ -131,13 +125,13 @@ struct versatile_pci_softc {
 	struct rman		mem_rman;
 
 	struct mtx		mtx;
+	struct ofw_bus_iinfo	pci_iinfo;
 };
 
 static struct resource_spec versatile_pci_mem_spec[] = {
 	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
 	{ SYS_RES_MEMORY, 1, RF_ACTIVE },
 	{ SYS_RES_MEMORY, 2, RF_ACTIVE },
-	{ SYS_RES_MEMORY, 3, RF_ACTIVE },
 	{ -1, 0, 0 }
 };
 
@@ -148,7 +142,7 @@ versatile_pci_probe(device_t dev)
 	if (!ofw_bus_status_okay(dev))
 		return (ENXIO);
 
-	if (ofw_bus_is_compatible(dev, "versatile,pci")) {
+	if (ofw_bus_is_compatible(dev, "arm,versatile-pci")) {
 		device_set_desc(dev, "Versatile PCI controller");
 		return (BUS_PROBE_DEFAULT);
 	}
@@ -164,6 +158,9 @@ versatile_pci_attach(device_t dev)
 	int slot;
 	uint32_t vendordev_id, class_id;
 	uint32_t val;
+	phandle_t node;
+
+	node = ofw_bus_get_node(dev);
 
 	/* Request memory resources */
 	err = bus_alloc_resources(dev, versatile_pci_mem_spec,
@@ -188,7 +185,7 @@ versatile_pci_attach(device_t dev)
 	versatile_pci_core_write_4(PCI_CORE_SMAP1, (PCI_NPREFETCH_WINDOW >> 28));
 	versatile_pci_core_write_4(PCI_CORE_SMAP2, (PCI_NPREFETCH_WINDOW >> 28));
 
-	versatile_pci_sys_write_4(SYS_PCICTL, 1);
+	versatile_scm_reg_write_4(SCM_PCICTL, 1);
 
 	for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
 		vendordev_id = versatile_pci_read_4((slot << 11) + PCIR_DEVVENDOR);
@@ -265,6 +262,8 @@ versatile_pci_attach(device_t dev)
 		versatile_pci_conf_write_4((slot << 11) + PCIR_COMMAND, val);
 	}
 
+	ofw_bus_setup_iinfo(node, &sc->pci_iinfo, sizeof(cell_t));
+
 	device_add_child(dev, "pci", -1);
 	return (bus_generic_attach(dev));
 }
@@ -318,7 +317,7 @@ versatile_pci_alloc_resource(device_t bu
 		rm = &sc->io_rman;
 		break;
 	case SYS_RES_IRQ:
-		rm = &sc->irq_rman;
+		rm = NULL;
 		break;
 	case SYS_RES_MEMORY:
 		rm = &sc->mem_rman;
@@ -327,8 +326,11 @@ versatile_pci_alloc_resource(device_t bu
 		return (NULL);
 	}
 
-	rv = rman_reserve_resource(rm, start, end, count, flags, child);
+	if (rm == NULL)
+		return (BUS_ALLOC_RESOURCE(device_get_parent(bus),
+		    child, type, rid, start, end, count, flags));
 
+	rv = rman_reserve_resource(rm, start, end, count, flags, child);
 	if (rv == NULL)
 		return (NULL);
 
@@ -389,8 +391,6 @@ versatile_pci_teardown_intr(device_t dev
 	return BUS_TEARDOWN_INTR(device_get_parent(dev), dev, ires, cookie);
 }
 
-
-
 static int
 versatile_pci_maxslots(device_t dev)
 {
@@ -399,10 +399,33 @@ versatile_pci_maxslots(device_t dev)
 }
 
 static int
-versatile_pci_route_interrupt(device_t pcib, device_t device, int pin)
+versatile_pci_route_interrupt(device_t bus, device_t dev, int pin)
 {
-
-	return (27 + ((pci_get_slot(device) + pin - 1) & 3));
+	struct versatile_pci_softc *sc;
+	struct ofw_pci_register reg;
+	uint32_t pintr, mintr[4];
+	phandle_t iparent;
+	int intrcells;
+
+	sc = device_get_softc(bus);
+	pintr = pin;
+
+	bzero(&reg, sizeof(reg));
+	reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
+	    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
+	    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
+
+	intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
+	    &sc->pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
+	    mintr, sizeof(mintr), &iparent);
+	if (intrcells) {
+		pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
+		return (pintr);
+	}
+
+	device_printf(bus, "could not route pin %d for device %d.%d\n",
+	    pin, pci_get_slot(dev), pci_get_function(dev));
+	return (PCI_INVALID_IRQ);
 }
 
 static uint32_t

Added: head/sys/arm/versatile/versatile_scm.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/versatile/versatile_scm.c	Sat Apr  1 20:10:08 2017	(r316370)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2017 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * SCM - System Control Module
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/resource.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "versatile_scm.h"
+
+struct versatile_scm_softc {
+	device_t		sc_dev;
+	struct resource *	sc_mem_res;
+};
+
+static struct versatile_scm_softc *versatile_scm_sc;
+
+#define	versatile_scm_read_4(sc, reg)		\
+    bus_read_4((sc)->sc_mem_res, (reg))
+#define	versatile_scm_write_4(sc, reg, val)		\
+    bus_write_4((sc)->sc_mem_res, (reg), (val))
+
+static int
+versatile_scm_probe(device_t dev)
+{
+	if (!ofw_bus_status_okay(dev))
+		return (ENXIO);
+
+	if (!ofw_bus_is_compatible(dev, "syscon"))
+		return (ENXIO);
+
+	if (versatile_scm_sc) {
+		return (EEXIST);
+	}
+
+	device_set_desc(dev, "Versatile Control Module");
+	return (BUS_PROBE_DEFAULT);
+}
+
+static int
+versatile_scm_attach(device_t dev)
+{
+	struct versatile_scm_softc *sc;
+	int rid;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+
+	rid = 0;
+	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
+
+	if (sc->sc_mem_res == NULL) {
+		device_printf(dev, "could not allocate memory resources\n");
+		return (ENXIO);
+	}
+
+	versatile_scm_sc = sc;
+
+	return (0);
+}
+
+int
+versatile_scm_reg_read_4(uint32_t reg, uint32_t *val)
+{
+	if (!versatile_scm_sc)
+		return (ENXIO);
+
+	*val = versatile_scm_read_4(versatile_scm_sc, reg);
+	return (0);
+}
+
+int
+versatile_scm_reg_write_4(uint32_t reg, uint32_t val)
+{
+	if (!versatile_scm_sc)
+		return (ENXIO);
+
+	versatile_scm_write_4(versatile_scm_sc, reg, val);
+	return (0);
+}
+
+static device_method_t versatile_scm_methods[] = {
+	DEVMETHOD(device_probe,		versatile_scm_probe),
+	DEVMETHOD(device_attach,	versatile_scm_attach),
+
+	DEVMETHOD_END
+};
+
+static driver_t versatile_scm_driver = {
+	"scm",
+	versatile_scm_methods,
+	sizeof(struct versatile_scm_softc),
+};
+
+static devclass_t versatile_scm_devclass;
+
+EARLY_DRIVER_MODULE(versatile_scm, simplebus, versatile_scm_driver, versatile_scm_devclass, 0, 0,
+    BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);

Added: head/sys/arm/versatile/versatile_scm.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/arm/versatile/versatile_scm.h	Sat Apr  1 20:10:08 2017	(r316370)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Ben Gray.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BEN GRAY ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL BEN GRAY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VERSATILE_SCM_H_
+#define _VERSATILE_SCM_H_
+
+#define	SCM_PCICTL		0x44
+#define	SCM_CLCD		0x50
+#define	 SCM_CLCD_CLCDID_SHIFT		0x08
+#define	 SCM_CLCD_CLCDID_MASK		0x1f
+#define	 SCM_CLCD_PWR3V5VSWITCH		(1 << 4)
+#define	 SCM_CLCD_VDDPOSSWITCH 		(1 << 3)
+#define	 SCM_CLCD_NLCDIOON  		(1 << 2)
+#define	 SCM_CLCD_LCD_MODE_MASK		0x03
+
+int versatile_scm_reg_read_4(uint32_t reg, uint32_t *val);
+int versatile_scm_reg_write_4(uint32_t reg, uint32_t val);
+
+#endif /* _VERSATILE_SCM_H_ */

Modified: head/sys/arm/versatile/versatile_sic.c
==============================================================================
--- head/sys/arm/versatile/versatile_sic.c	Sat Apr  1 19:27:06 2017	(r316369)
+++ head/sys/arm/versatile/versatile_sic.c	Sat Apr  1 20:10:08 2017	(r316370)
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ * Copyright (c) 2012-2017 Oleksandr Tymoshenko <gonzo at freebsd.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -24,7 +24,6 @@
  * SUCH DAMAGE.
  */
 
-
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -34,6 +33,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/ktr.h>
 #include <sys/module.h>
+#include <sys/proc.h>
 #include <sys/rman.h>
 #include <machine/bus.h>
 #include <machine/intr.h>
@@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 
+#include "pic_if.h"
+
 #ifdef  DEBUG
 #define dprintf(fmt, args...) printf(fmt, ##args)
 #else
@@ -59,16 +61,142 @@ __FBSDID("$FreeBSD$");
 #define	SIC_PICENSET	0x20
 #define	SIC_PICENCLR	0x24
 
+#define	SIC_NIRQS	32
+
+struct versatile_sic_irqsrc {
+	struct intr_irqsrc		isrc;
+	u_int				irq;
+};
+
 struct versatile_sic_softc {
-	device_t		sc_dev;
+	device_t		dev;
+	struct mtx		mtx;
 	struct resource *	mem_res;
+	struct resource *	irq_res;
+	void			*intrh;
+	struct versatile_sic_irqsrc	isrcs[SIC_NIRQS];
 };
 
-#define	sic_read_4(sc, reg)			\
+#define	SIC_LOCK(_sc) mtx_lock_spin(&(_sc)->mtx)
+#define	SIC_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->mtx)
+
+#define	SIC_READ_4(sc, reg)			\
     bus_read_4(sc->mem_res, (reg))
-#define	sic_write_4(sc, reg, val)		\
+#define	SIC_WRITE_4(sc, reg, val)		\
     bus_write_4(sc->mem_res, (reg), (val))
 
+/*
+ * Driver stuff
+ */
+static int versatile_sic_probe(device_t);
+static int versatile_sic_attach(device_t);
+static int versatile_sic_detach(device_t);
+
+static void
+versatile_sic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct versatile_sic_softc *sc;
+	struct versatile_sic_irqsrc *src;
+
+	sc = device_get_softc(dev);
+	src = (struct versatile_sic_irqsrc *)isrc;
+
+	SIC_LOCK(sc);
+	SIC_WRITE_4(sc, SIC_ENCLR, (1 << src->irq));
+	SIC_UNLOCK(sc);
+}
+
+static void
+versatile_sic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct versatile_sic_softc *sc;
+	struct versatile_sic_irqsrc *src;
+
+	sc = device_get_softc(dev);
+	src = (struct versatile_sic_irqsrc *)isrc;
+
+	SIC_LOCK(sc);
+	SIC_WRITE_4(sc, SIC_ENSET, (1 << src->irq));
+	SIC_UNLOCK(sc);
+}
+
+static int
+versatile_sic_map_intr(device_t dev, struct intr_map_data *data,
+    struct intr_irqsrc **isrcp)
+{
+	struct intr_map_data_fdt *daf;
+	struct versatile_sic_softc *sc;
+
+	if (data->type != INTR_MAP_DATA_FDT)
+		return (ENOTSUP);
+
+	daf = (struct intr_map_data_fdt *)data;
+	if (daf->ncells != 1 || daf->cells[0] >= SIC_NIRQS)
+		return (EINVAL);
+
+	sc = device_get_softc(dev);
+	*isrcp = &sc->isrcs[daf->cells[0]].isrc;
+	return (0);
+}
+
+static void
+versatile_sic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+	versatile_sic_disable_intr(dev, isrc);
+}
+
+static void
+versatile_sic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct versatile_sic_irqsrc *src;
+
+	src = (struct versatile_sic_irqsrc *)isrc;
+	arm_irq_memory_barrier(src->irq);
+	versatile_sic_enable_intr(dev, isrc);
+}
+
+static void
+versatile_sic_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+	struct versatile_sic_irqsrc *src;
+
+	src = (struct versatile_sic_irqsrc *)isrc;
+	arm_irq_memory_barrier(src->irq);
+}
+
+static int
+versatile_sic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+    struct resource *res, struct intr_map_data *data)
+{
+
+	return (0);
+}
+
+static int
+versatile_sic_filter(void *arg)
+{
+	struct versatile_sic_softc *sc;
+	struct intr_irqsrc *isrc;
+	uint32_t i, interrupts;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list