baytrail: add south cluster fixed resources

The PCU (platform controller unit) contains the
resources and IP blocks that used to reside in the
south bridge. Bay Trail has since renamed it south
cluster. There are quite a few fixed MMIO and I/O
resources. If these aren't added the resource allocator
will freely assign these addresses which causes conflicts
and other subtle bugs.

BUG=chrome-os-partner:23544
BUG=chrome-os-partner:23545
BRANCH=None
TEST=Built and booted through depthcharge. Verified
     resource allocation not weird. And no more depthcharge
     crashes.

Change-Id: I697fbda4538c03fded293bcb63a5823b1ed150ec
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/174421
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-on: http://review.coreboot.org/4893
Tested-by: build bot (Jenkins)
Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
diff --git a/src/soc/intel/baytrail/southcluster.c b/src/soc/intel/baytrail/southcluster.c
new file mode 100644
index 0000000..32b8799
--- /dev/null
+++ b/src/soc/intel/baytrail/southcluster.c
@@ -0,0 +1,130 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2013 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <romstage_handoff.h>
+
+#include <baytrail/iomap.h>
+#include <baytrail/lpc.h>
+#include <baytrail/nvs.h>
+#include <baytrail/pci_devs.h>
+#include <baytrail/ramstage.h>
+
+static inline void
+add_mmio_resource(device_t dev, int i, unsigned long addr, unsigned long size)
+{
+	mmio_resource(dev, i, addr >> 10, size >> 10);
+}
+
+static void sc_add_mmio_resources(device_t dev)
+{
+	add_mmio_resource(dev, PBASE, PMC_BASE_ADDRESS, 1024);
+	add_mmio_resource(dev, IOBASE, IO_BASE_ADDRESS, 16 * 1024);
+	add_mmio_resource(dev, IBASE, ILB_BASE_ADDRESS, 1024);
+	add_mmio_resource(dev, SBASE, SPI_BASE_ADDRESS, 1024);
+	add_mmio_resource(dev, MPBASE, MPHY_BASE_ADDRESS, 1024 * 1024);
+	add_mmio_resource(dev, PUBASE, PUNIT_BASE_ADDRESS, 2048);
+	add_mmio_resource(dev, RCBA, RCBA_BASE_ADDRESS, 1024);
+}
+
+/* Default IO range claimed by the LPC device. The upper bound is exclusive. */
+#define LPC_DEFAULT_IO_RANGE_LOWER 0
+#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000
+
+static inline int io_range_in_default(int base, int size)
+{
+	/* Does it start above the range? */
+	if (base >= LPC_DEFAULT_IO_RANGE_UPPER)
+		return 0;
+
+	/* Is it entirely contained? */
+	if (base >= LPC_DEFAULT_IO_RANGE_LOWER &&
+	    (base + size) < LPC_DEFAULT_IO_RANGE_UPPER)
+		return 1;
+
+	/* This will return not in range for partial overlaps. */
+	return 0;
+}
+
+/*
+ * Note: this function assumes there is no overlap with the default LPC device's
+ * claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER.
+ */
+static void sc_add_io_resource(device_t dev, int base, int size, int index)
+{
+	struct resource *res;
+
+	if (io_range_in_default(base, size))
+		return;
+
+	res = new_resource(dev, index);
+	res->base = base;
+	res->size = size;
+	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+}
+
+static void sc_add_io_resources(device_t dev)
+{
+	struct resource *res;
+
+	/* Add the default claimed IO range for the LPC device. */
+	res = new_resource(dev, 0);
+	res->base = LPC_DEFAULT_IO_RANGE_LOWER;
+	res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER;
+	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
+
+	/* GPIO */
+	sc_add_io_resource(dev, GPIO_BASE_ADDRESS, 256, GBASE);
+
+	/* ACPI */
+	sc_add_io_resource(dev, ACPI_BASE_ADDRESS, 128, ABASE);
+}
+
+static void sc_read_resources(device_t dev)
+{
+	/* Get the normal PCI resources of this device. */
+	pci_dev_read_resources(dev);
+
+	/* Add non-standard MMIO resources. */
+	sc_add_mmio_resources(dev);
+
+	/* Add IO resources. */
+	sc_add_io_resources(dev);
+}
+
+static struct device_operations device_ops = {
+	.read_resources		= sc_read_resources,
+	.set_resources		= pci_dev_set_resources,
+	.enable_resources	= NULL,
+	.init			= NULL,
+	.enable			= NULL,
+	.scan_bus		= NULL,
+	.ops_pci		= &soc_pci_ops,
+};
+
+static const struct pci_driver southcluster __pci_driver = {
+	.ops		= &device_ops,
+	.vendor		= PCI_VENDOR_ID_INTEL,
+	.device		= LPC_DEVID,
+};