Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Jan 2015 22:22:50 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r277779 - in projects/powernv: conf powerpc/powernv
Message-ID:  <201501262222.t0QMMoOv005751@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Mon Jan 26 22:22:50 2015
New Revision: 277779
URL: https://svnweb.freebsd.org/changeset/base/277779

Log:
  Add driver for OPAL PCI interface. This is compile-tested only at present;
  I expect IOMMU-related issues on real hardware.

Added:
  projects/powernv/powerpc/powernv/opal_pci.c   (contents, props changed)
Modified:
  projects/powernv/conf/files.powerpc
  projects/powernv/powerpc/powernv/opal.h

Modified: projects/powernv/conf/files.powerpc
==============================================================================
--- projects/powernv/conf/files.powerpc	Mon Jan 26 21:41:54 2015	(r277778)
+++ projects/powernv/conf/files.powerpc	Mon Jan 26 22:22:50 2015	(r277779)
@@ -172,6 +172,8 @@ powerpc/powermac/uninorthpci.c	optional	
 powerpc/powermac/vcoregpio.c	optional	powermac 
 powerpc/powernv/opal.c		optional	powernv
 powerpc/powernv/opal_console.c	optional	powernv
+powerpc/powernv/opal_dev.c	optional	powernv
+powerpc/powernv/opal_pci.c	optional	powernv pci
 powerpc/powernv/opalcall.S	optional	powernv
 powerpc/powernv/platform_powernv.c optional	powernv
 powerpc/powerpc/altivec.c	standard

Modified: projects/powernv/powerpc/powernv/opal.h
==============================================================================
--- projects/powernv/powerpc/powernv/opal.h	Mon Jan 26 21:41:54 2015	(r277778)
+++ projects/powernv/powerpc/powernv/opal.h	Mon Jan 26 22:22:50 2015	(r277779)
@@ -38,15 +38,21 @@ int opal_check(void);
 /* Call an OPAL method. Any pointers passed must be real-mode accessible! */
 int opal_call(uint64_t token, ...);
 
-#define OPAL_CONSOLE_WRITE	1
-#define OPAL_CONSOLE_READ	2
-#define	OPAL_CEC_POWER_DOWN	5
-#define	OPAL_CEC_REBOOT		6
-#define	OPAL_SET_XIVE		19
-#define	OPAL_GET_XIVE		20
-#define OPAL_START_CPU		41
+#define OPAL_CONSOLE_WRITE		1
+#define OPAL_CONSOLE_READ		2
+#define	OPAL_CEC_POWER_DOWN		5
+#define	OPAL_CEC_REBOOT			6
+#define	OPAL_PCI_CONFIG_READ_BYTE	13
+#define	OPAL_PCI_CONFIG_READ_HALF_WORD	14
+#define	OPAL_PCI_CONFIG_READ_WORD	15
+#define	OPAL_PCI_CONFIG_WRITE_BYTE	16
+#define	OPAL_PCI_CONFIG_WRITE_HALF_WORD	17
+#define	OPAL_PCI_CONFIG_WRITE_WORD	18
+#define	OPAL_SET_XIVE			19
+#define	OPAL_GET_XIVE			20
+#define OPAL_START_CPU			41
 
-#define OPAL_SUCCESS		0
-#define	OPAL_BUSY_EVENT		-12
+#define OPAL_SUCCESS			0
+#define	OPAL_BUSY_EVENT			-12
 
 #endif

Added: projects/powernv/powerpc/powernv/opal_pci.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/powernv/powerpc/powernv/opal_pci.c	Mon Jan 26 22:22:50 2015	(r277779)
@@ -0,0 +1,215 @@
+/*-
+ * Copyright (c) 2015 Nathan Whitehorn
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/intr_machdep.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+#include <machine/rtas.h>
+
+#include <sys/rman.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <powerpc/ofw/ofw_pci.h>
+
+#include "pcib_if.h"
+#include "iommu_if.h"
+#include "opal.h"
+
+/*
+ * Device interface.
+ */
+static int		opalpci_probe(device_t);
+static int		opalpci_attach(device_t);
+
+/*
+ * pcib interface.
+ */
+static u_int32_t	opalpci_read_config(device_t, u_int, u_int, u_int,
+			    u_int, int);
+static void		opalpci_write_config(device_t, u_int, u_int, u_int,
+			    u_int, u_int32_t, int);
+
+/*
+ * Driver methods.
+ */
+static device_method_t	opalpci_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		opalpci_probe),
+	DEVMETHOD(device_attach,	opalpci_attach),
+
+	/* pcib interface */
+	DEVMETHOD(pcib_read_config,	opalpci_read_config),
+	DEVMETHOD(pcib_write_config,	opalpci_write_config),
+
+	DEVMETHOD_END
+};
+
+struct opalpci_softc {
+	struct ofw_pci_softc ofw_sc;
+	uint64_t phb_id;
+};
+
+static devclass_t	opalpci_devclass;
+DEFINE_CLASS_1(pcib, opalpci_driver, opalpci_methods,
+    sizeof(struct opalpci_softc), ofw_pci_driver);
+DRIVER_MODULE(opalpci, ofwbus, opalpci_driver, opalpci_devclass, 0, 0);
+
+static int
+opalpci_probe(device_t dev)
+{
+	const char	*type;
+
+	if (opal_check() != 0)
+		return (ENXIO);
+
+	type = ofw_bus_get_type(dev);
+
+	if (type == NULL || strcmp(type, "pci") != 0)
+		return (ENXIO);
+
+	if (!OF_hasprop(ofw_bus_get_node(dev), "ibm,opal-phbid"))
+		return (ENXIO); 
+
+	device_set_desc(dev, "OPAL Host-PCI bridge");
+	return (BUS_PROBE_GENERIC);
+}
+
+static int
+opalpci_attach(device_t dev)
+{
+	struct opalpci_softc *sc;
+	cell_t id[2];
+
+	sc = device_get_softc(dev);
+
+	switch (OF_getproplen(ofw_bus_get_node(dev), "ibm,opal-phbid")) {
+	case 8:
+		OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-phbid", id, 8);
+		sc->phb_id = ((uint64_t)id[0] << 32) | id[1];
+		break;
+	case 4:
+		OF_getencprop(ofw_bus_get_node(dev), "ibm,opal-phbid", id, 4);
+		sc->phb_id = id[0];
+		break;
+	default:
+		device_printf(dev, "PHB ID property had wrong length (%zd)\n",
+		    OF_getproplen(ofw_bus_get_node(dev), "ibm,opal-phbid"));
+		return (ENXIO);
+	}
+
+	return (ofw_pci_attach(dev));
+}
+
+static uint32_t
+opalpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+    int width)
+{
+	struct opalpci_softc *sc;
+	uint64_t config_addr;
+	uint8_t byte;
+	uint16_t half;
+	uint32_t word;
+	int error;
+
+	sc = device_get_softc(dev);
+
+	config_addr = (bus << 8) | ((slot & 0x1f) << 3) | (func & 0x7);
+
+	/* Sign-extend output */
+	switch (width) {
+	case 1:
+		error = opal_call(OPAL_PCI_CONFIG_READ_BYTE, sc->phb_id,
+		    config_addr, reg, vtophys(&byte));
+		word = byte;
+		break;
+	case 2:
+		error = opal_call(OPAL_PCI_CONFIG_READ_HALF_WORD, sc->phb_id,
+		    config_addr, reg, vtophys(&half));
+		word = half;
+		break;
+	case 4:
+		error = opal_call(OPAL_PCI_CONFIG_READ_WORD, sc->phb_id,
+		    config_addr, reg, vtophys(&word));
+		break;
+	default:
+		word = 0xffffffff;
+	}
+	
+	if (error != OPAL_SUCCESS)
+		word = 0xffffffff;
+
+	return (word);
+}
+
+static void
+opalpci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+    u_int reg, uint32_t val, int width)
+{
+	struct opalpci_softc *sc;
+	uint64_t config_addr;
+
+	sc = device_get_softc(dev);
+
+	config_addr = (bus << 8) | ((slot & 0x1f) << 3) | (func & 0x7);
+
+	/* Sign-extend output */
+	switch (width) {
+	case 1:
+		opal_call(OPAL_PCI_CONFIG_WRITE_BYTE, sc->phb_id, config_addr,
+		    reg, val);
+		break;
+	case 2:
+		opal_call(OPAL_PCI_CONFIG_WRITE_HALF_WORD, sc->phb_id,
+		    config_addr, reg, val);
+		break;
+	case 4:
+		opal_call(OPAL_PCI_CONFIG_WRITE_WORD, sc->phb_id, config_addr,
+		    reg, val);
+		break;
+	}
+}
+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501262222.t0QMMoOv005751>