[coreboot-gerrit] New patch to review for coreboot: 4d4b081 NOTFORMERGE: Add infrastructure for radeon native initialization

Alexandru Gagniuc (mr.nuke.me@gmail.com) gerrit at coreboot.org
Mon Jan 26 09:03:15 CET 2015


Alexandru Gagniuc (mr.nuke.me at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8281

-gerrit

commit 4d4b081646c353c6fd32ba1d36b6e193c4f02230
Author: Alexandru Gagniuc <mr.nuke.me at gmail.com>
Date:   Mon Jan 26 00:55:51 2015 -0600

    NOTFORMERGE: Add infrastructure for radeon native initialization
    
    This is the way that I'm thinking we should integrate native radeon
    init into coreboot. It doesn't make sense to have one monolithic init
    block as different parts are common to several architectures. e.g the
    VGA_MEMORY base registers seem to have been the same for years.
    
    The idea is simple: have a few macro-ops, and dispatch the correct ops
    to some generic code based on whatever heuristic is appropriate. i.e.
    we don't have to rely on PCI IDs alone; we can poke the hardware as
    well before dispatching.
    
    Note that a lot of the API is left undefined, or opaque. We'll see how
    that evolves as we build up the init code path.
    
    One thing I'm considering is dropping the PCI IDs list and going on
    an ops-based approach, where the driver fills in several
    'radeon_<component>_ops' structures, though we'll end up with some
    really big structs. Though it's also possible that the complexity of
    component ops could end up into the dispatcher, so we're back to those
    really big structs.
    
    If you're looking for some inspiration, I suggest looking at the
    radeon driver in linux, and doing the exact opposite
    
    Change-Id: Ifa95a8da1abfd430452dca50ed9b7ce4b09bc1c7
    Signed-off-by: Alexandru Gagniuc <mr.nuke.me at gmail.com>
---
 src/drivers/Kconfig                        |  1 +
 src/drivers/Makefile.inc                   |  1 +
 src/drivers/amd/Kconfig                    | 12 +++++
 src/drivers/amd/Makefile.inc               |  6 +++
 src/drivers/amd/radeon/Makefile.inc        |  8 +++
 src/drivers/amd/radeon/radeon.c            | 76 +++++++++++++++++++++++++++
 src/drivers/amd/radeon/radeon.h            | 31 +++++++++++
 src/drivers/amd/radeon/radeon_dispatcher.c | 35 +++++++++++++
 src/drivers/amd/radeon/radeon_private.h    | 21 ++++++++
 src/drivers/amd/radeon/radeon_util.c       | 84 ++++++++++++++++++++++++++++++
 10 files changed, 275 insertions(+)

diff --git a/src/drivers/Kconfig b/src/drivers/Kconfig
index 08de415..db74a73 100644
--- a/src/drivers/Kconfig
+++ b/src/drivers/Kconfig
@@ -17,6 +17,7 @@
 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 ##
 
+source src/drivers/amd/Kconfig
 source src/drivers/ams/Kconfig
 source src/drivers/ati/Kconfig
 source src/drivers/dec/Kconfig
diff --git a/src/drivers/Makefile.inc b/src/drivers/Makefile.inc
index 151e3f7..418a3ca 100644
--- a/src/drivers/Makefile.inc
+++ b/src/drivers/Makefile.inc
@@ -17,6 +17,7 @@
 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 ##
 
+subdirs-y += amd
 subdirs-y += ams
 subdirs-y += ati
 subdirs-y += dec
diff --git a/src/drivers/amd/Kconfig b/src/drivers/amd/Kconfig
new file mode 100644
index 0000000..1971c86
--- /dev/null
+++ b/src/drivers/amd/Kconfig
@@ -0,0 +1,12 @@
+#
+# Copyright (C) 2015  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+# Subject to the GNU GPL v2, or (at your option) any later version.
+#
+
+config DRIVER_AMD_RADEON
+	bool
+	default n
+	help
+	  This is a wrapper shim for various radeon functionality. Selecting
+	  this driver does not guarantee that native graphics initialization
+	  will work, or is supported.
diff --git a/src/drivers/amd/Makefile.inc b/src/drivers/amd/Makefile.inc
new file mode 100644
index 0000000..51ce627
--- /dev/null
+++ b/src/drivers/amd/Makefile.inc
@@ -0,0 +1,6 @@
+#
+# Copyright (C) 2015  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+# Subject to the GNU GPL v2, or (at your option) any later version.
+#
+
+subdirs-$(CONFIG_DRIVER_AMD_RADEON) += radeon/
diff --git a/src/drivers/amd/radeon/Makefile.inc b/src/drivers/amd/radeon/Makefile.inc
new file mode 100644
index 0000000..f5d81df
--- /dev/null
+++ b/src/drivers/amd/radeon/Makefile.inc
@@ -0,0 +1,8 @@
+#
+# Copyright (C) 2015  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+# Subject to the GNU GPL v2, or (at your option) any later version.
+#
+
+ramstage-y += radeon.c
+ramstage-y += radeon_util.c
+ramstage-y += radeon_dispatcher.c
diff --git a/src/drivers/amd/radeon/radeon.c b/src/drivers/amd/radeon/radeon.c
new file mode 100644
index 0000000..4f93bcd
--- /dev/null
+++ b/src/drivers/amd/radeon/radeon.c
@@ -0,0 +1,76 @@
+/*
+ * Wrapper for radeon utilty functions
+ *
+ * Copyright (C) 2015  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+
+#include "radeon.h"
+
+static void radeon_display_init(struct radeon_device *rdev)
+{
+	disp_init_t display_init;
+	struct radeon_disp_path *display;
+
+	display = radeon_get_default_disp_path();
+	if (!display) {
+		printk(BIOS_WARNING, "Could not get a display path\n");
+		return;
+	}
+
+	if (!is_native_init_capable(rdev, display)) {
+		printk(BIOS_WARNING, "Cannot init given display path\n");
+		return;
+	}
+
+	display_init = dispatch_display_init(rdev);
+	if (!display) {
+		printk(BIOS_WARNING, "[BUG!!!] display_init not dispatched\n");
+		return;
+	}
+
+	display_init(rdev, display);
+}
+
+static void radeon_init(device_t dev)
+{
+	asic_init_t asic_init;
+	struct radeon_device *rdev;
+
+	rdev = create_radeon_device(dev);
+	asic_init = dispatch_asic_init(dev);
+	if (asic_init) {
+		asic_init(rdev);
+	}
+
+	if (IS_ENABLED(MAINBOARD_DO_NATIVE_VGA_INIT))
+		radeon_display_init(rdev);
+
+	pci_dev_init(dev);
+}
+
+static struct device_operations radeon_operations = {
+	.read_resources = pci_dev_read_resources,
+	.set_resources = pci_dev_set_resources,
+	.enable_resources = pci_dev_enable_resources,
+	.init = radeon_init,
+	.disable = device_noop,
+	.enable = device_noop,
+	.ops_pci = 0,
+};
+
+static const uint16_t radeon_ids[] = {
+	0
+};
+
+static const struct pci_driver radeon_driver __pci_driver = {
+	.ops = &radeon_operations,
+	.vendor = PCI_VENDOR_ID_ATI,
+	.devices = radeon_ids,
+};
diff --git a/src/drivers/amd/radeon/radeon.h b/src/drivers/amd/radeon/radeon.h
new file mode 100644
index 0000000..824e609
--- /dev/null
+++ b/src/drivers/amd/radeon/radeon.h
@@ -0,0 +1,31 @@
+/*
+ * All things radeon
+ *
+ * Copyright (C) 2015  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+
+#ifndef _DRIVERS_AMD_RADEON_RADEON_H
+#define _DRIVERS_AMD_RADEON_RADEON_H
+
+#include <device/device.h>
+
+/* These structs are intentionally opaque */
+struct radeon_device;
+struct radeon_disp_path;
+
+typedef void (* asic_init_t)(struct radeon_device *);
+typedef void (* disp_init_t)(struct radeon_device *, struct radeon_disp_path *);
+
+asic_init_t dispatch_asic_init(device_t dev);
+disp_init_t dispatch_display_init(struct radeon_device *rdev);
+struct radeon_device *create_radeon_device(device_t dev);
+struct radeon_disp_path *radeon_get_default_disp_path(void);
+bool is_native_init_capable(struct radeon_device *, struct radeon_disp_path *);
+
+void rdev_write(struct radeon_device *rdev, uint32_t reg, uint32_t value);
+uint32_t rdev_read(struct radeon_device *rdev, uint32_t reg);
+void rdev_mask(struct radeon_device *rdev, uint32_t reg, uint32_t clrbits,
+	       uint32_t setbits);
+
+#endif	/* _DRIVERS_AMD_RADEON_RADEON_H */
diff --git a/src/drivers/amd/radeon/radeon_dispatcher.c b/src/drivers/amd/radeon/radeon_dispatcher.c
new file mode 100644
index 0000000..2fa52ae
--- /dev/null
+++ b/src/drivers/amd/radeon/radeon_dispatcher.c
@@ -0,0 +1,35 @@
+/*
+ * Dispatch initialization functions
+ *
+ * Copyright (C) 2015  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+#include "radeon.h"
+#include "aruba/aruba.h"
+
+#include <device/pci_ids.h>
+
+asic_init_t dispatch_asic_init(device_t dev)
+{
+	if (dev->vendor != PCI_VENDOR_ID_ATI)
+		return NULL;
+
+	return NULL;
+}
+
+disp_init_t dispatch_display_init(struct radeon_device *rdev)
+{
+	/* This is a no-op */
+	return NULL;
+}
+
+bool is_native_init_capable(struct radeon_device *rdev,
+			    struct radeon_disp_path *display)
+{
+	return false;
+}
+
+struct radeon_disp_path *radeon_get_default_disp_path(void)
+{
+	return NULL;
+}
diff --git a/src/drivers/amd/radeon/radeon_private.h b/src/drivers/amd/radeon/radeon_private.h
new file mode 100644
index 0000000..11cb0c9
--- /dev/null
+++ b/src/drivers/amd/radeon/radeon_private.h
@@ -0,0 +1,21 @@
+/*
+ * Your code should not need these. If it does, it's wrong.
+ *
+ * Copyright (C) 2015  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+
+#ifndef _RADEON_PRIVATE_H
+#define _RADEON_PRIVATE_H
+
+#include <device/device.h>
+
+struct radeon_device {
+	struct device *cb_dev;
+	uint16_t pio_base;
+	uint16_t pio_size;
+	void *mmio_base;
+	size_t mmio_size;
+};
+
+#endif /* _RADEON_PRIVATE_H */
diff --git a/src/drivers/amd/radeon/radeon_util.c b/src/drivers/amd/radeon/radeon_util.c
new file mode 100644
index 0000000..04f3682
--- /dev/null
+++ b/src/drivers/amd/radeon/radeon_util.c
@@ -0,0 +1,84 @@
+/*
+ * Low-level radeon helpers
+ *
+ * Copyright (C) 2013  Alexandru Gagniuc <mr.nuke.me at gmail.com>
+ * Subject to the GNU GPL v2, or (at your option) any later version.
+ */
+
+#include "radeon.h"
+#include "radeon_private.h"
+
+#include <arch/io.h>
+#include <device/pci.h>
+#include <stdlib.h>
+#include <string.h>
+#include <console/console.h>
+
+struct radeon_device *create_radeon_device(device_t dev)
+{
+	int num_res_found = 0;
+	struct radeon_device *rdev;
+	struct resource *res = dev->resource_list;
+
+	rdev = malloc(sizeof(*rdev));
+	if (rdev == NULL)
+		return NULL;
+	memset(rdev, 0, sizeof(*rdev));
+
+	rdev->cb_dev = dev;
+
+	while (res) {
+		/* Register PIO space */
+		if (res->index == PCI_BASE_ADDRESS_1) {
+			if (!(res->flags & IORESOURCE_IO))
+				continue;
+			rdev->pio_base = res->base;
+			rdev->pio_size = res->size;
+			num_res_found++;
+		}
+
+		/* Get the register MMIO space (not the framebuffer) */
+		if (res->index == PCI_BASE_ADDRESS_2) {
+			if (!(res->flags & IORESOURCE_MEM))
+				continue;
+			rdev->mmio_base = (void *)(uintptr_t)res->base;
+			rdev->mmio_size = res->size;
+			num_res_found++;
+		}
+		/* We care about the register IO and register MMIO resources */
+		if (num_res_found == 2)
+			break;
+
+		res = res->next;
+	}
+
+	if (num_res_found < 2) {
+		/* We're missing either the MMIO or PIO base. Can't continue*/
+		free(rdev);
+		return NULL;
+	}
+
+	return rdev;
+}
+
+
+void rdev_write(struct radeon_device *rdev, uint32_t reg, uint32_t value)
+{
+	unsigned long mmio = (unsigned long)rdev->mmio_base + reg;
+	write32(mmio, value);
+}
+
+uint32_t rdev_read(struct radeon_device *rdev, uint32_t reg)
+{
+	unsigned long mmio = (unsigned long)rdev->mmio_base + reg;
+	return read32(mmio);
+}
+
+void rdev_mask(struct radeon_device *rdev, uint32_t reg, uint32_t clrbits,
+	       uint32_t setbits)
+{
+	uint32_t reg32 = rdev_read(rdev, reg);
+	reg32 &= ~clrbits;
+	reg32 |= setbits;
+	rdev_write(rdev, reg, reg32);
+}



More information about the coreboot-gerrit mailing list