[coreboot-gerrit] New patch to review for coreboot: soc/qualcomm/ipq40xx: Initial commit for IPQ40xx SoC support

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Fri May 6 23:27:42 CEST 2016


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14644

-gerrit

commit cae99a698ea25628466ae8cac6d5e73508b3d462
Author: Varadarajan Narayanan <varada at codeaurora.org>
Date:   Wed Mar 2 16:57:10 2016 +0530

    soc/qualcomm/ipq40xx: Initial commit for IPQ40xx SoC support
    
    Copy 'ipq806x' files as a template
    
    BUG=chrome-os-partner:49249
    TEST=None. Initial code not sure if it will even compile
    BRANCH=none
    
    Change-Id: Ie5794c48131ae562861074b406106734541880d9
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: dc6a5937953fe61cd4b5a99ca49f9371c4b712d4
    Original-Change-Id: If171fcdd3b0561cb6b7dab5f8434de7ef711ea41
    Original-Signed-off-by: Varadarajan Narayanan <varada at codeaurora.org>
    Original-Signed-off-by: Kan Yan <kyan at google.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/333178
    Original-Commit-Ready: David Hendricks <dhendrix at chromium.org>
    Original-Tested-by: David Hendricks <dhendrix at chromium.org>
    Original-Reviewed-by: David Hendricks <dhendrix at chromium.org>
---
 src/soc/qualcomm/ipq40xx/Kconfig                   |  33 +
 src/soc/qualcomm/ipq40xx/Makefile.inc              |  88 +++
 src/soc/qualcomm/ipq40xx/blobs_init.c              | 159 ++++
 src/soc/qualcomm/ipq40xx/cbmem.c                   |  26 +
 src/soc/qualcomm/ipq40xx/clock.c                   | 173 +++++
 src/soc/qualcomm/ipq40xx/gpio.c                    | 152 ++++
 src/soc/qualcomm/ipq40xx/gsbi.c                    | 109 +++
 src/soc/qualcomm/ipq40xx/i2c.c                     | 170 +++++
 src/soc/qualcomm/ipq40xx/include/soc/cdp.h         | 177 +++++
 src/soc/qualcomm/ipq40xx/include/soc/clock.h       | 214 ++++++
 src/soc/qualcomm/ipq40xx/include/soc/ebi2.h        | 107 +++
 src/soc/qualcomm/ipq40xx/include/soc/gpio.h        | 110 +++
 src/soc/qualcomm/ipq40xx/include/soc/gsbi.h        |  75 ++
 src/soc/qualcomm/ipq40xx/include/soc/iomap.h       | 165 +++++
 src/soc/qualcomm/ipq40xx/include/soc/ipq_timer.h   |  37 +
 src/soc/qualcomm/ipq40xx/include/soc/ipq_uart.h    | 273 +++++++
 src/soc/qualcomm/ipq40xx/include/soc/lcc-reg.h     | 341 +++++++++
 src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld  |  55 ++
 src/soc/qualcomm/ipq40xx/include/soc/qup.h         | 219 ++++++
 .../qualcomm/ipq40xx/include/soc/soc_services.h    |  39 +
 src/soc/qualcomm/ipq40xx/include/soc/spi.h         | 305 ++++++++
 src/soc/qualcomm/ipq40xx/include/soc/usb.h         |  26 +
 src/soc/qualcomm/ipq40xx/include/soc/usbl_if.h     |  70 ++
 src/soc/qualcomm/ipq40xx/lcc.c                     | 316 ++++++++
 src/soc/qualcomm/ipq40xx/mbn_header.h              |  36 +
 src/soc/qualcomm/ipq40xx/qup.c                     | 480 ++++++++++++
 src/soc/qualcomm/ipq40xx/soc.c                     |  61 ++
 src/soc/qualcomm/ipq40xx/spi.c                     | 805 +++++++++++++++++++++
 src/soc/qualcomm/ipq40xx/timer.c                   |  98 +++
 src/soc/qualcomm/ipq40xx/tz_wrapper.S              | 106 +++
 src/soc/qualcomm/ipq40xx/uart.c                    | 406 +++++++++++
 src/soc/qualcomm/ipq40xx/usb.c                     | 226 ++++++
 32 files changed, 5657 insertions(+)

diff --git a/src/soc/qualcomm/ipq40xx/Kconfig b/src/soc/qualcomm/ipq40xx/Kconfig
new file mode 100644
index 0000000..9a1e4f9
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/Kconfig
@@ -0,0 +1,33 @@
+config SOC_QC_IPQ806X
+	bool
+	default n
+	select ARCH_BOOTBLOCK_ARMV7
+	select ARCH_VERSTAGE_ARMV7
+	select ARCH_ROMSTAGE_ARMV7
+	select ARCH_RAMSTAGE_ARMV7
+	select BOOTBLOCK_CONSOLE
+	select CHROMEOS_VBNV_FLASH
+	select HAS_PRECBMEM_TIMESTAMP_REGION
+	select HAVE_UART_SPECIAL
+	select SPI_ATOMIC_SEQUENCING
+	select GENERIC_GPIO_LIB
+	select SEPARATE_VERSTAGE
+	select RETURN_FROM_VERSTAGE
+
+if SOC_QC_IPQ806X
+
+config MBN_ENCAPSULATION
+	depends on USE_BLOBS
+	bool "bootblock encapsulation for ipq8064"
+	default y
+
+config SBL_BLOB
+	depends on USE_BLOBS
+	string "file name of the Qualcomm SBL blob"
+	default "3rdparty/blobs/cpu/qualcomm/ipq806x/uber-sbl.mbn"
+	help
+	  The path and filename of the binary blob containing
+	  ipq806x early initialization code, as supplied by the
+	  vendor.
+
+endif
diff --git a/src/soc/qualcomm/ipq40xx/Makefile.inc b/src/soc/qualcomm/ipq40xx/Makefile.inc
new file mode 100644
index 0000000..83b5e06
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/Makefile.inc
@@ -0,0 +1,88 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright 2014 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.
+##
+
+ifeq ($(CONFIG_SOC_QC_IPQ806X),y)
+
+bootblock-y += clock.c
+bootblock-y += gpio.c
+bootblock-$(CONFIG_SPI_FLASH) += spi.c
+bootblock-y += timer.c
+bootblock-$(CONFIG_DRIVERS_UART) += uart.c
+
+verstage-y += clock.c
+verstage-y += gpio.c
+libverstage-y += gsbi.c
+libverstage-y += i2c.c
+libverstage-y += qup.c
+libverstage-y += spi.c
+verstage-y += timer.c
+verstage-$(CONFIG_DRIVERS_UART) += uart.c
+
+romstage-y += clock.c
+romstage-y += blobs_init.c
+romstage-y += gpio.c
+romstage-$(CONFIG_SPI_FLASH) += spi.c
+romstage-y += timer.c
+romstage-$(CONFIG_DRIVERS_UART) += uart.c
+romstage-y += cbmem.c
+
+ramstage-y += blobs_init.c
+ramstage-y += cbmem.c
+ramstage-y += clock.c
+ramstage-y += gpio.c
+ramstage-y += lcc.c
+ramstage-y += soc.c
+ramstage-$(CONFIG_SPI_FLASH) += spi.c
+ramstage-y += timer.c
+ramstage-y += uart.c  # Want the UART always ready for the kernels' earlyprintk
+ramstage-y += usb.c
+ramstage-y += tz_wrapper.S
+
+ifeq ($(CONFIG_USE_BLOBS),y)
+
+# Add MBN header to allow SBL3 to start coreboot bootblock
+$(objcbfs)/bootblock.mbn: $(objcbfs)/bootblock.raw.bin
+	@printf "    ADD MBN    $(subst $(obj)/,,$(@))\n"
+	./util/ipqheader/ipqheader.py $(call loadaddr,bootblock) $< $@.tmp
+	@mv $@.tmp $@
+
+# Create a complete bootblock which will start up the system
+$(objcbfs)/bootblock.bin: $(call strip_quotes,$(CONFIG_SBL_BLOB)) \
+			   $(objcbfs)/bootblock.mbn
+	@printf "    MBNCAT     $(subst $(obj)/,,$(@))\n"
+	@util/ipqheader/mbncat.py -o $@.tmp $^
+	@mv $@.tmp $@
+
+endif
+
+CPPFLAGS_common += -Isrc/soc/qualcomm/ipq806x/include
+
+# List of binary blobs coreboot needs in CBFS to be able to boot up this SOC
+mbn-files := cdt.mbn  ddr.mbn  rpm.mbn tz.mbn
+
+# Location of the binary blobs
+mbn-root := 3rdparty/blobs/cpu/qualcomm/ipq806x
+
+# Create make variables to aid cbfs-files-handler in processing the blobs (add
+# them all as raw binaries at the root level).
+$(foreach f,$(mbn-files),$(eval cbfs-files-y += $(f))\
+	  $(eval $(f)-file := $(mbn-root)/$(f))\
+	  $(eval $(f)-type := raw))
+
+endif
diff --git a/src/soc/qualcomm/ipq40xx/blobs_init.c b/src/soc/qualcomm/ipq40xx/blobs_init.c
new file mode 100644
index 0000000..2821677
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/blobs_init.c
@@ -0,0 +1,159 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * 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.
+ */
+
+#include <arch/cache.h>
+#include <arch/io.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <string.h>
+#include <timer.h>
+
+#include <soc/iomap.h>
+#include <soc/soc_services.h>
+
+#include "mbn_header.h"
+
+static void *load_ipq_blob(const char *file_name)
+{
+	struct mbn_header *blob_mbn;
+	void *blob_dest;
+	size_t blob_size;
+
+	blob_mbn = cbfs_boot_map_with_leak(file_name, CBFS_TYPE_RAW,
+						&blob_size);
+	if (!blob_mbn)
+		return NULL;
+
+	/* some sanity checks on the headers */
+	if ((blob_mbn->mbn_version != 3) ||
+	    (blob_mbn->mbn_total_size > blob_size))
+		return NULL;
+
+	blob_dest = (void *) blob_mbn->mbn_destination;
+	if (blob_mbn->mbn_destination) {
+		/* Copy the blob to the appropriate memory location. */
+		memcpy(blob_dest, blob_mbn + 1, blob_mbn->mbn_total_size);
+		cache_sync_instructions();
+		return blob_dest;
+	}
+
+	/*
+	 * The blob did not have to be relocated, return its address in CBFS
+	 * cache.
+	 */
+	return blob_mbn + 1;
+}
+
+#ifdef __PRE_RAM__
+
+#define DDR_VERSION() ((const char *)0x2a03f600)
+#define MAX_DDR_VERSION_SIZE 48
+
+int initialize_dram(void)
+{
+	void *cdt;
+	int (*ddr_init_function)(void *cdt_header);
+
+	cdt = load_ipq_blob("cdt.mbn");
+	ddr_init_function = load_ipq_blob("ddr.mbn");
+
+	if (!cdt || !ddr_init_function) {
+		printk(BIOS_ERR, "cdt: %p, ddr_init_function: %p\n",
+		       cdt, ddr_init_function);
+		die("could not find DDR initialization blobs\n");
+	}
+
+	if (ddr_init_function(cdt) < 0)
+		die("Fail to Initialize DDR\n");
+
+	/*
+	 * Once DDR initializer finished, its verison can be found at a fixed
+	 * address in SRAM.
+	 */
+	printk(BIOS_INFO, "DDR version %.*s initialized\n",
+	       MAX_DDR_VERSION_SIZE, DDR_VERSION());
+
+	return 0;
+}
+
+#else  /* __PRE_RAM__ */
+
+void start_tzbsp(void)
+{
+	void *tzbsp = load_ipq_blob("tz.mbn");
+
+	if (!tzbsp)
+		die("could not find or map TZBSP\n");
+
+	printk(BIOS_INFO, "Starting TZBSP\n");
+
+	tz_init_wrapper(0, 0, tzbsp);
+}
+
+/* RPM version is encoded in a 32 bit word at the fixed address */
+#define RPM_VERSION() (*((u32 *)(0x00108008)))
+void start_rpm(void)
+{
+	u32 load_addr;
+	u32 ready_mask = 1 << 10;
+	u32 rpm_version;
+
+	struct stopwatch sw;
+
+	if (read32(RPM_SIGNAL_COOKIE) == RPM_FW_MAGIC_NUM) {
+		printk(BIOS_INFO, "RPM appears to have already started\n");
+		return;
+	}
+
+	load_addr = (u32) load_ipq_blob("rpm.mbn");
+	if (!load_addr)
+		die("could not find or map RPM code\n");
+
+	printk(BIOS_INFO, "Starting RPM\n");
+
+	/* Clear 'ready' indication. */
+	/*
+	 * RPM_INT_ACK is clear-on-write type register,
+	 * read-modify-write is not recommended.
+	 */
+	write32(RPM_INT_ACK, ready_mask);
+
+	/* Set RPM entry address */
+	write32(RPM_SIGNAL_ENTRY, load_addr);
+	/* Set cookie */
+	write32(RPM_SIGNAL_COOKIE, RPM_FW_MAGIC_NUM);
+
+	/* Wait for RPM start indication, up to 100ms. */
+	stopwatch_init_usecs_expire(&sw, 100000);
+	while (!(read32(RPM_INT) & ready_mask))
+		if (stopwatch_expired(&sw))
+			die("RPM Initialization failed\n");
+
+	/* Acknowledge RPM initialization */
+	write32(RPM_INT_ACK, ready_mask);
+
+	/* Report RPM version, it is encoded in a 32 bit value. */
+	rpm_version = RPM_VERSION();
+	printk(BIOS_INFO, "Started RPM version %d.%d.%d\n",
+	       rpm_version >> 24,
+	       (rpm_version >> 16) & 0xff,
+	       rpm_version & 0xffff);
+}
+#endif  /* !__PRE_RAM__ */
diff --git a/src/soc/qualcomm/ipq40xx/cbmem.c b/src/soc/qualcomm/ipq40xx/cbmem.c
new file mode 100644
index 0000000..14f1a0a
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/cbmem.c
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ */
+
+#include <cbmem.h>
+#include <soc/soc_services.h>
+
+void *cbmem_top(void)
+{
+	return _memlayout_cbmem_top;
+}
diff --git a/src/soc/qualcomm/ipq40xx/clock.c b/src/soc/qualcomm/ipq40xx/clock.c
new file mode 100644
index 0000000..4d8d8e9
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/clock.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2012 - 2013 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <delay.h>
+#include <soc/clock.h>
+#include <types.h>
+
+/**
+ * uart_pll_vote_clk_enable - enables PLL8
+ */
+void uart_pll_vote_clk_enable(unsigned int clk_dummy)
+{
+	setbits_le32(BB_PLL_ENA_SC0_REG, BIT(8));
+
+	if (!clk_dummy)
+		while ((read32(PLL_LOCK_DET_STATUS_REG) & BIT(8)) == 0)
+			;
+}
+
+/**
+ * uart_set_rate_mnd - configures divider M and D values
+ *
+ * Sets the M, D parameters of the divider to generate the GSBI UART
+ * apps clock.
+ */
+static void uart_set_rate_mnd(unsigned int gsbi_port, unsigned int m,
+		unsigned int n)
+{
+	/* Assert MND reset. */
+	setbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(7));
+	/* Program M and D values. */
+	write32(GSBIn_UART_APPS_MD_REG(gsbi_port), MD16(m, n));
+	/* Deassert MND reset. */
+	clrbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(7));
+}
+
+/**
+ * uart_branch_clk_enable_reg - enables branch clock
+ *
+ * Enables branch clock for GSBI UART port.
+ */
+static void uart_branch_clk_enable_reg(unsigned int gsbi_port)
+{
+	setbits_le32(GSBIn_UART_APPS_NS_REG(gsbi_port), BIT(9));
+}
+
+/**
+ * uart_local_clock_enable - configures N value and enables root clocks
+ *
+ * Sets the N parameter of the divider and enables root clock and
+ * branch clocks for GSBI UART port.
+ */
+static void uart_local_clock_enable(unsigned int gsbi_port, unsigned int n,
+					unsigned int m)
+{
+	unsigned int reg_val, uart_ns_val;
+	void *const reg = (void *)GSBIn_UART_APPS_NS_REG(gsbi_port);
+
+	/*
+	* Program the NS register, if applicable. NS registers are not
+	* set in the set_rate path because power can be saved by deferring
+	* the selection of a clocked source until the clock is enabled.
+	*/
+	reg_val = read32(reg); // REG(0x29D4+(0x20*((n)-1)))
+	reg_val &= ~(Uart_clk_ns_mask);
+	uart_ns_val =  NS(BIT_POS_31, BIT_POS_16, n, m, 5, 4, 3, 1, 2, 0, 3);
+	reg_val |= (uart_ns_val & Uart_clk_ns_mask);
+	write32(reg, reg_val);
+
+	/* enable MNCNTR_EN */
+	reg_val = read32(reg);
+	reg_val |= BIT(8);
+	write32(reg, reg_val);
+
+	/* set source to PLL8 running @384MHz */
+	reg_val = read32(reg);
+	reg_val |= 0x3;
+	write32(reg, reg_val);
+
+	/* Enable root. */
+	reg_val |= Uart_en_mask;
+	write32(reg, reg_val);
+	uart_branch_clk_enable_reg(gsbi_port);
+}
+
+/**
+ * uart_set_gsbi_clk - enables HCLK for UART GSBI port
+ */
+static void uart_set_gsbi_clk(unsigned int gsbi_port)
+{
+	setbits_le32(GSBIn_HCLK_CTL_REG(gsbi_port), BIT(4));
+}
+
+/**
+ * uart_clock_config - configures UART clocks
+ *
+ * Configures GSBI UART dividers, enable root and branch clocks.
+ */
+void uart_clock_config(unsigned int gsbi_port, unsigned int m,
+		unsigned int n, unsigned int d, unsigned int clk_dummy)
+{
+	uart_set_rate_mnd(gsbi_port, m, d);
+	uart_pll_vote_clk_enable(clk_dummy);
+	uart_local_clock_enable(gsbi_port, n, m);
+	uart_set_gsbi_clk(gsbi_port);
+}
+
+/**
+ * nand_clock_config - configure NAND controller clocks
+ *
+ * Enable clocks to EBI2. Must be invoked before touching EBI2
+ * registers.
+ */
+void nand_clock_config(void)
+{
+	write32(EBI2_CLK_CTL_REG,
+		CLK_BRANCH_ENA(1) | ALWAYS_ON_CLK_BRANCH_ENA(1));
+
+	/* Wait for clock to stabilize. */
+	udelay(10);
+}
+
+/**
+ * usb_clock_config - configure USB controller clocks and reset the controller
+ */
+void usb_clock_config(void)
+{
+	/* Magic clock initialization numbers, nobody knows how they work... */
+	write32(USB30_MASTER_CLK_CTL_REG, 0x10);
+	write32(USB30_1_MASTER_CLK_CTL_REG, 0x10);
+	write32(USB30_MASTER_CLK_MD, 0x500DF);
+	write32(USB30_MASTER_CLK_NS, 0xE40942);
+	write32(USB30_MOC_UTMI_CLK_MD, 0x100D7);
+	write32(USB30_MOC_UTMI_CLK_NS, 0xD80942);
+	write32(USB30_MOC_UTMI_CLK_CTL, 0x10);
+	write32(USB30_1_MOC_UTMI_CLK_CTL, 0x10);
+
+	write32(USB30_RESET,
+		1 << 5 |		/* assert port2 HS PHY async reset */
+		1 << 4 |		/* assert master async reset */
+		1 << 3 |		/* assert sleep async reset */
+		1 << 2 |		/* assert MOC UTMI async reset */
+		1 << 1 |		/* assert power-on async reset */
+		1 << 0);		/* assert PHY async reset */
+	udelay(5);
+	write32(USB30_RESET, 0);	/* deassert all USB resets again */
+}
diff --git a/src/soc/qualcomm/ipq40xx/gpio.c b/src/soc/qualcomm/ipq40xx/gpio.c
new file mode 100644
index 0000000..47c0fcd
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/gpio.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <arch/io.h>
+#include <gpio.h>
+#include <soc/iomap.h>
+
+/*******************************************************
+Function description: check for invalid GPIO #
+Arguments :
+gpio_t gpio - Gpio number
+
+Return : GPIO Valid(0)/Invalid(1)
+*******************************************************/
+
+static inline int gpio_not_valid(gpio_t gpio)
+{
+	return (gpio > GPIO_MAX_NUM);
+}
+
+
+/*******************************************************
+Function description: configure GPIO functinality
+Arguments :
+gpio_t gpio - Gpio number
+unsigned func - Functionality number
+unsigned pull - pull up/down, no pull range(0-3)
+unsigned drvstr - range (0 - 7)-> (2- 16)MA steps of 2
+unsigned enable - 0 Disable, 1 - Enable.
+
+Return : None
+*******************************************************/
+
+
+void gpio_tlmm_config_set(gpio_t gpio, unsigned func,
+			  unsigned pull, unsigned drvstr,
+			  unsigned enable)
+{
+	unsigned val = 0;
+
+	if (gpio_not_valid(gpio))
+		return;
+
+	val |= (pull & GPIO_CFG_PULL_MASK) << GPIO_CFG_PULL_SHIFT;
+	val |= (func & GPIO_CFG_FUNC_MASK) << GPIO_CFG_FUNC_SHIFT;
+	val |= (drvstr & GPIO_CFG_DRV_MASK) << GPIO_CFG_DRV_SHIFT;
+	val |= (enable & GPIO_CFG_OE_MASK) << GPIO_CFG_OE_SHIFT;
+
+	write32(GPIO_CONFIG_ADDR(gpio), val);
+}
+
+/*******************************************************
+Function description: Get GPIO configuration
+Arguments :
+gpio_t gpio - Gpio number
+unsigned *func - Functionality number
+unsigned *pull - pull up/down, no pull range(0-3)
+unsigned *drvstr - range (0 - 7)-> (2- 16)MA steps of 2
+unsigned *enable - 0 - Disable, 1- Enable.
+
+Return : None
+*******************************************************/
+
+
+void gpio_tlmm_config_get(gpio_t gpio, unsigned *func,
+			  unsigned *pull, unsigned *drvstr,
+			  unsigned *enable)
+{
+	unsigned val;
+	void *addr = GPIO_CONFIG_ADDR(gpio);
+
+	if (gpio_not_valid(gpio))
+		return;
+
+	val = read32(addr);
+
+	*pull = (val >> GPIO_CFG_PULL_SHIFT) & GPIO_CFG_PULL_MASK;
+	*func = (val >> GPIO_CFG_FUNC_SHIFT) & GPIO_CFG_FUNC_MASK;
+	*drvstr = (val >> GPIO_CFG_DRV_SHIFT) & GPIO_CFG_DRV_MASK;
+	*enable = (val >> GPIO_CFG_OE_SHIFT) & GPIO_CFG_OE_MASK;
+}
+
+/*******************************************************
+Function description: get GPIO IO functinality details
+Arguments :
+gpio_t gpio - Gpio number
+unsigned *in - Value of GPIO input
+unsigned *out - Value of GPIO output
+
+Return : None
+*******************************************************/
+int gpio_get(gpio_t gpio)
+{
+	if (gpio_not_valid(gpio))
+		return -1;
+
+
+	return (read32(GPIO_IN_OUT_ADDR(gpio)) >> GPIO_IO_IN_SHIFT) &
+		GPIO_IO_IN_MASK;
+}
+
+void gpio_set(gpio_t gpio, int value)
+{
+	if (gpio_not_valid(gpio))
+		return;
+
+	write32(GPIO_IN_OUT_ADDR(gpio), (value & 1) << GPIO_IO_OUT_SHIFT);
+}
+
+void gpio_input_pulldown(gpio_t gpio)
+{
+	gpio_tlmm_config_set(gpio, GPIO_FUNC_DISABLE,
+			     GPIO_PULL_DOWN, GPIO_2MA, GPIO_DISABLE);
+}
+
+void gpio_input_pullup(gpio_t gpio)
+{
+	gpio_tlmm_config_set(gpio, GPIO_FUNC_DISABLE,
+			     GPIO_PULL_UP, GPIO_2MA, GPIO_DISABLE);
+}
+
+void gpio_input(gpio_t gpio)
+{
+	gpio_tlmm_config_set(gpio, GPIO_FUNC_DISABLE,
+			     GPIO_NO_PULL, GPIO_2MA, GPIO_DISABLE);
+}
diff --git a/src/soc/qualcomm/ipq40xx/gsbi.c b/src/soc/qualcomm/ipq40xx/gsbi.c
new file mode 100644
index 0000000..98c4edd
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/gsbi.c
@@ -0,0 +1,109 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 - 2015 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <arch/io.h>
+#include <soc/iomap.h>
+#include <soc/gsbi.h>
+#include <console/console.h>
+
+static inline void *gsbi_ctl_reg_addr(gsbi_id_t gsbi_id)
+{
+	switch (gsbi_id) {
+	case GSBI_ID_1:
+		return GSBI1_CTL_REG;
+	case GSBI_ID_2:
+		return GSBI2_CTL_REG;
+	case GSBI_ID_3:
+		return GSBI3_CTL_REG;
+	case GSBI_ID_4:
+		return GSBI4_CTL_REG;
+	case GSBI_ID_5:
+		return GSBI5_CTL_REG;
+	case GSBI_ID_6:
+		return GSBI6_CTL_REG;
+	case GSBI_ID_7:
+		return GSBI7_CTL_REG;
+	default:
+		printk(BIOS_ERR, "Unsupported GSBI%d\n", gsbi_id);
+		return 0;
+	}
+}
+
+gsbi_return_t gsbi_init(gsbi_id_t gsbi_id, gsbi_protocol_t protocol)
+{
+	unsigned reg_val;
+	unsigned m = 1;
+	unsigned n = 4;
+	unsigned pre_div = 4;
+	unsigned src = 3;
+	unsigned mnctr_mode = 2;
+	void *gsbi_ctl = gsbi_ctl_reg_addr(gsbi_id);
+
+	if (!gsbi_ctl)
+		return GSBI_ID_ERROR;
+
+	write32(GSBI_HCLK_CTL(gsbi_id),
+		(1 << GSBI_HCLK_CTL_GATE_ENA) |
+		(1 << GSBI_HCLK_CTL_BRANCH_ENA));
+
+	if (gsbi_init_board(gsbi_id))
+		return GSBI_UNSUPPORTED;
+
+	write32(GSBI_QUP_APSS_NS_REG(gsbi_id), 0);
+	write32(GSBI_QUP_APSS_MD_REG(gsbi_id), 0);
+
+	reg_val = ((m & GSBI_QUP_APPS_M_MASK) << GSBI_QUP_APPS_M_SHFT) |
+		  ((~n & GSBI_QUP_APPS_D_MASK) << GSBI_QUP_APPS_D_SHFT);
+	write32(GSBI_QUP_APSS_MD_REG(gsbi_id), reg_val);
+
+	reg_val = (((~(n - m)) & GSBI_QUP_APPS_N_MASK) <<
+					GSBI_QUP_APPS_N_SHFT) |
+		  ((mnctr_mode & GSBI_QUP_APPS_MNCTR_MODE_MSK) <<
+				 GSBI_QUP_APPS_MNCTR_MODE_SFT) |
+		  (((pre_div - 1) & GSBI_QUP_APPS_PRE_DIV_MSK) <<
+				 GSBI_QUP_APPS_PRE_DIV_SFT) |
+		  (src & GSBI_QUP_APPS_SRC_SEL_MSK);
+	write32(GSBI_QUP_APSS_NS_REG(gsbi_id), reg_val);
+
+	reg_val |= (1 << GSBI_QUP_APPS_ROOT_ENA_SFT) |
+		   (1 << GSBI_QUP_APPS_MNCTR_EN_SFT);
+	write32(GSBI_QUP_APSS_NS_REG(gsbi_id), reg_val);
+
+	reg_val |= (1 << GSBI_QUP_APPS_BRANCH_ENA_SFT);
+	write32(GSBI_QUP_APSS_NS_REG(gsbi_id), reg_val);
+
+	/*Select i2c protocol*/
+	write32(gsbi_ctl,
+		((GSBI_CTL_PROTO_I2C & GSBI_CTL_PROTO_CODE_MSK)
+			<< GSBI_CTL_PROTO_CODE_SFT));
+
+	return GSBI_SUCCESS;
+}
diff --git a/src/soc/qualcomm/ipq40xx/i2c.c b/src/soc/qualcomm/ipq40xx/i2c.c
new file mode 100644
index 0000000..f84b8e2
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/i2c.c
@@ -0,0 +1,170 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 - 2015 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <arch/io.h>
+#include <assert.h>
+#include <console/console.h>
+#include <delay.h>
+#include <device/i2c.h>
+#include <stdlib.h>
+#include <string.h>
+#include <soc/gsbi.h>
+#include <soc/qup.h>
+
+static qup_config_t gsbi1_qup_config = {
+	QUP_MINICORE_I2C_MASTER,
+	100000,
+	24000000,
+	QUP_MODE_FIFO,
+	0
+};
+
+static qup_config_t gsbi4_qup_config = {
+	QUP_MINICORE_I2C_MASTER,
+	100000,
+	24000000,
+	QUP_MODE_FIFO,
+	0
+};
+
+static qup_config_t gsbi7_qup_config = {
+	QUP_MINICORE_I2C_MASTER,
+	100000,
+	24000000,
+	QUP_MODE_FIFO,
+	0
+};
+
+static int i2c_read(uint32_t gsbi_id, uint8_t slave,
+		    uint8_t *data, int data_len)
+{
+	qup_data_t obj;
+	qup_return_t qup_ret = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.protocol = QUP_MINICORE_I2C_MASTER;
+	obj.p.iic.addr = slave;
+	obj.p.iic.data_len = data_len;
+	obj.p.iic.data = data;
+	qup_ret = qup_recv_data(gsbi_id, &obj);
+
+	if (QUP_SUCCESS != qup_ret)
+		return 1;
+	else
+		return 0;
+}
+
+static int i2c_write(uint32_t gsbi_id, uint8_t slave,
+		     uint8_t *data, int data_len, uint8_t stop_seq)
+{
+	qup_data_t obj;
+	qup_return_t qup_ret = 0;
+
+	memset(&obj, 0, sizeof(obj));
+	obj.protocol = QUP_MINICORE_I2C_MASTER;
+	obj.p.iic.addr = slave;
+	obj.p.iic.data_len = data_len;
+	obj.p.iic.data = data;
+	qup_ret = qup_send_data(gsbi_id, &obj, stop_seq);
+
+	if (QUP_SUCCESS != qup_ret)
+		return 1;
+	else
+		return 0;
+}
+
+static int i2c_init(unsigned bus)
+{
+	unsigned gsbi_id = bus;
+	qup_config_t *qup_config;
+
+	switch (gsbi_id) {
+	case GSBI_ID_1:
+		qup_config = &gsbi1_qup_config;
+		break;
+	case GSBI_ID_4:
+		qup_config = &gsbi4_qup_config;
+		break;
+	case GSBI_ID_7:
+		qup_config = &gsbi7_qup_config;
+		break;
+	default:
+		printk(BIOS_ERR, "QUP configuration not defind for GSBI%d.\n",
+		       gsbi_id);
+		return 1;
+	}
+
+	if (qup_config->initialized)
+		return 0;
+
+	if (gsbi_init(gsbi_id, GSBI_PROTO_I2C_ONLY)) {
+		printk(BIOS_ERR, "failed to initialize gsbi\n");
+		return 1;
+	}
+
+	if (qup_init(gsbi_id, qup_config)) {
+		printk(BIOS_ERR, "failed to initialize qup\n");
+		return 1;
+	}
+
+	if (qup_reset_i2c_master_status(gsbi_id)) {
+		printk(BIOS_ERR, "failed to reset i2c master status\n");
+		return 1;
+	}
+
+	qup_config->initialized = 1;
+	return 0;
+}
+
+int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int seg_count)
+{
+	struct i2c_seg *seg = segments;
+	int ret = 0;
+
+	if (i2c_init(bus))
+		return 1;
+
+	while (!ret && seg_count--) {
+		if (seg->read)
+			ret = i2c_read(bus, seg->chip, seg->buf, seg->len);
+		else
+			ret = i2c_write(bus, seg->chip, seg->buf, seg->len,
+					(seg_count ? 0 : 1));
+		seg++;
+	}
+
+	if (ret) {
+		qup_set_state(bus, QUP_STATE_RESET);
+		return 1;
+	}
+
+	return 0;
+}
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/cdp.h b/src/soc/qualcomm/ipq40xx/include/soc/cdp.h
new file mode 100644
index 0000000..c63a937
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/cdp.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+
+#ifndef _IPQ806X_CDP_H_
+#define _IPQ806X_CDP_H_
+
+#include <types.h>
+
+unsigned smem_get_board_machtype(void);
+
+typedef enum {
+	PHY_INTERFACE_MODE_MII,
+	PHY_INTERFACE_MODE_GMII,
+	PHY_INTERFACE_MODE_SGMII,
+	PHY_INTERFACE_MODE_QSGMII,
+	PHY_INTERFACE_MODE_TBI,
+	PHY_INTERFACE_MODE_RMII,
+	PHY_INTERFACE_MODE_RGMII,
+	PHY_INTERFACE_MODE_RGMII_ID,
+	PHY_INTERFACE_MODE_RGMII_RXID,
+	PHY_INTERFACE_MODE_RGMII_TXID,
+	PHY_INTERFACE_MODE_RTBI,
+	PHY_INTERFACE_MODE_XGMII,
+	PHY_INTERFACE_MODE_NONE /* Must be last */
+} phy_interface_t;
+
+typedef struct {
+	unsigned int gpio;
+	unsigned int func;
+	unsigned int dir;
+	unsigned int pull;
+	unsigned int drvstr;
+	unsigned int enable;
+} gpio_func_data_t;
+
+typedef struct {
+	unsigned int m_value;
+	unsigned int n_value;
+	unsigned int d_value;
+} uart_clk_mnd_t;
+
+/* SPI Mode */
+
+typedef enum {
+	NOR_SPI_MODE_0,
+	NOR_SPI_MODE_1,
+	NOR_SPI_MODE_2,
+	NOR_SPI_MODE_3,
+} spi_mode;
+
+/* SPI GSBI Bus number */
+
+typedef enum {
+	GSBI_BUS_5 = 0,
+	GSBI_BUS_6,
+	GSBI_BUS_7,
+} spi_gsbi_bus_num;
+
+/* SPI Chip selects */
+
+typedef enum {
+	SPI_CS_0 ,
+	SPI_CS_1,
+	SPI_CS_2,
+	SPI_CS_3,
+} spi_cs;
+
+/* Flash Types */
+
+typedef enum {
+	ONLY_NAND,
+	ONLY_NOR,
+	NAND_NOR,
+	NOR_MMC,
+} flash_desc;
+
+#define NO_OF_DBG_UART_GPIOS	2
+
+#define SPI_NOR_FLASH_VENDOR_MICRON       0x1
+#define SPI_NOR_FLASH_VENDOR_SPANSION     0x2
+
+/* SPI parameters */
+
+typedef struct {
+	spi_mode mode;
+	spi_gsbi_bus_num bus_number;
+	spi_cs chip_select;
+	int vendor;
+} spinorflash_params_t;
+
+typedef struct {
+	unsigned count;
+	uint8_t addr[7];
+} ipq_gmac_phy_addr_t;
+
+typedef struct {
+	unsigned base;
+	int unit;
+	unsigned is_macsec;
+	unsigned mac_pwr0;
+	unsigned mac_pwr1;
+	unsigned mac_conn_to_phy;
+	phy_interface_t phy;
+	ipq_gmac_phy_addr_t phy_addr;
+} ipq_gmac_board_cfg_t;
+
+#define IPQ_GMAC_NMACS		4
+
+enum storm_board_id {
+	BOARD_ID_PROTO_0 = 0,
+	BOARD_ID_PROTO_0_2 = 1,
+	BOARD_ID_WHIRLWIND = 2,
+	BOARD_ID_WHIRLWIND_SP5 = 3,
+	BOARD_ID_PROTO_0_2_NAND = 26,
+};
+
+/* Board specific parameters */
+typedef struct {
+#if 0
+	unsigned int gmac_gpio_count;
+	gpio_func_data_t *gmac_gpio;
+	ipq_gmac_board_cfg_t gmac_cfg[IPQ_GMAC_NMACS];
+	flash_desc flashdesc;
+	spinorflash_params_t flash_param;
+#endif
+} __attribute__ ((__packed__)) board_ipq806x_params_t;
+
+extern board_ipq806x_params_t *gboard_param;
+
+#if 0
+static inline int gmac_cfg_is_valid(ipq_gmac_board_cfg_t *cfg)
+{
+	/*
+	 * 'cfg' is valid if and only if
+	 *	unit number is non-negative and less than IPQ_GMAC_NMACS.
+	 *	'cfg' pointer lies within the array range of
+	 *		board_ipq806x_params_t->gmac_cfg[]
+	 */
+	return ((cfg >= &gboard_param->gmac_cfg[0]) &&
+		(cfg < &gboard_param->gmac_cfg[IPQ_GMAC_NMACS]) &&
+		(cfg->unit >= 0) && (cfg->unit < IPQ_GMAC_NMACS));
+}
+#endif
+
+unsigned int get_board_index(unsigned machid);
+void ipq_configure_gpio(const gpio_func_data_t *gpio, unsigned count);
+
+void board_nand_init(void);
+
+#endif	/* _IPQ806X_CDP_H_ */
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/clock.h b/src/soc/qualcomm/ipq40xx/include/soc/clock.h
new file mode 100644
index 0000000..29bbb55
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/clock.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Source : APQ8064 LK Boot
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef __IPQ860X_CLOCK_H_
+#define __IPQ860X_CLOCK_H_
+
+#include <soc/iomap.h>
+
+/* UART clock @ 7.3728 MHz */
+#define UART_DM_CLK_RX_TX_BIT_RATE 0xCC
+
+/* UART specific definitions */
+
+#define Uart_ns_val		NS(BIT_POS_31, BIT_POS_16, N_VALUE, M_VALUE, \
+						5, 4, 3, 1, 2, 0, 3)
+#define Uart_clk_ns_mask	(BM(BIT_POS_31, BIT_POS_16) | \
+						BM(BIT_POS_6, BIT_POS_0))
+#define Uart_mnd_en_mask	(BIT(8) * !!(625))
+#define Uart_en_mask		BIT(11)
+#define MD16(m, n)		(BVAL(BIT_POS_31, BIT_POS_16, m) | \
+					BVAL(BIT_POS_15, BIT_POS_0, ~(n)))
+#define Uart_ns_val_rumi	NS(BIT_POS_31, BIT_POS_16, N_VALUE, M_VALUE, \
+						5, 4, 3, 1, 2, 0, 0)
+#define GSBIn_UART_APPS_MD_REG(n)           REG(0x29D0+(0x20*((n)-1)))
+#define GSBIn_UART_APPS_NS_REG(n)           REG(0x29D4+(0x20*((n)-1)))
+#define GSBIn_HCLK_CTL_REG(n)               REG(0x29C0+(0x20*((n)-1)))
+#define BB_PLL_ENA_SC0_REG                  REG(0x34C0)
+#define BB_PLL8_STATUS_REG                  REG(0x3158)
+#define REG(off)        ((void *)(MSM_CLK_CTL_BASE + (off)))
+#define PLL8_STATUS_BIT                     16
+
+#define PLL_LOCK_DET_STATUS_REG             REG(0x03420)
+#define SFAB_AHB_S3_FCLK_CTL_REG            REG(0x0216C)
+#define CFPB_CLK_NS_REG                     REG(0x0264C)
+#define CFPB0_HCLK_CTL_REG                  REG(0x02650)
+#define SFAB_CFPB_S_HCLK_CTL_REG            REG(0x026C0)
+#define CFPB_SPLITTER_HCLK_CTL_REG          REG(0x026E0)
+#define EBI2_CLK_CTL_REG                    REG(0x03B00)
+
+#define USB30_MASTER_CLK_CTL_REG            REG(0x3b24)
+#define USB30_MASTER_CLK_MD                 REG(0x3b28)
+#define USB30_MASTER_CLK_NS                 REG(0x3b2c)
+#define USB30_1_MASTER_CLK_CTL_REG          REG(0x3b34)
+#define USB30_MOC_UTMI_CLK_MD               REG(0x3b40)
+#define USB30_MOC_UTMI_CLK_NS               REG(0x3b44)
+#define USB30_MOC_UTMI_CLK_CTL              REG(0x3b48)
+#define USB30_1_MOC_UTMI_CLK_CTL            REG(0x3b4c)
+#define USB30_RESET                         REG(0x3b50)
+
+#define ALWAYS_ON_CLK_BRANCH_ENA(i)         ((i) << 8)
+
+#define CLK_BRANCH_ENA_MASK                 0x00000010
+#define CLK_BRANCH_ENA_ENABLE               0x00000010
+#define CLK_BRANCH_ENA_DISABLE              0x00000000
+#define CLK_BRANCH_ENA(i)                   ((i) << 4)
+
+/* Register: CFPB_CLK_NS */
+#define CLK_DIV_MASK                        0x00000003
+#define CLK_DIV_DIV_1                       0x00000000
+#define CLK_DIV_DIV_2                       0x00000001
+#define CLK_DIV_DIV_3                       0x00000002
+#define CLK_DIV_DIV_4                       0x00000003
+#define CLK_DIV(i)                          ((i) << 0)
+
+#define MN_MODE_DUAL_EDGE 0x2
+#define BIT_POS_31 31
+#define BIT_POS_16 16
+#define BIT_POS_6  6
+#define BIT_POS_0  0
+#define BIT_POS_15 15
+
+#define BM(m, l) (((((unsigned int)-1) << (31-m)) >> (31-m+l)) << l)
+#define BVAL(m, l, val)     (((val) << l) & BM(m, l))
+
+/* MD Registers */
+#define MD4(m_lsb, m, n_lsb, n) \
+	(BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
+
+#define MD8(m_lsb, m, n_lsb, n) \
+	(BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
+
+/* NS Registers */
+#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+	(BVAL(n_msb, n_lsb, ~(n-m)) \
+	| (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
+	| BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
+
+#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+	(BVAL(n_msb, n_lsb, ~(n-m)) | BVAL(d_msb, d_lsb, (d-1)) \
+	| BVAL(s_msb, s_lsb, s))
+
+#define NS_DIVSRC(d_msb , d_lsb, d, s_msb, s_lsb, s) \
+	(BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
+
+#define NS_DIV(d_msb , d_lsb, d) \
+	BVAL(d_msb, d_lsb, (d-1))
+
+#define NS_SRC_SEL(s_msb, s_lsb, s) \
+	BVAL(s_msb, s_lsb, s)
+
+#define GMAC_AHB_RESET			0x903E24
+
+#define SRC_SEL_PLL0			(0x2 << 0)
+#define MNCNTR_MODE_DUAL_EDGE		(0x2 << 5)
+#define MNCNTR_ENABLE			(0x1 << 8)
+#define MNCNTR_RST_ACTIVE		(0x1 << 7)
+#define N_VAL				15
+
+#define GMAC_CORE_RESET(n)	\
+		((void *)(0x903CBC + ((n) * 0x20)))
+
+#define GMACSEC_CORE_RESET(n)	\
+		((void *)(0x903E28 + ((n - 1) * 4)))
+
+#define GMAC_COREn_CLCK_SRC_CTL(N)	\
+		(0x00900000 + (0x3CA0 + (32*(N-1))))
+
+#define GMAC_COREn_CLCK_SRC0_MD(N)	\
+		(0x00900000 + (0x3CA4 + (32*(N-1))))
+
+#define GMAC_COREn_CLCK_SRC1_MD(N)	\
+		(0x00900000 + (0x3CA8	+ (32*(N-1))))
+
+#define GMAC_COREn_CLCK_SRC0_NS(N)	\
+		(0x00900000 + (0x3CAC + (32*(N-1))))
+
+#define GMAC_COREn_CLCK_SRC1_NS(N)	\
+		(0x00900000 + (0x3CB0 + (32*(N-1))))
+
+#define DISABLE_DUAL_MN8_SEL		(0)
+#define DISABLE_CLK_LOW_PWR		(0 << 2)
+#define GMAC_CORE_CLCK_ROOT_ENABLE	(1 << 1)
+
+/* GMAC_COREn_CLK_SRC[0,1]_MD register bits (Assuming 133MHz) */
+#define GMAC_CORE_CLCK_M		0x32
+#define GMAC_CORE_CLCK_D		0	/* NOT(2*D) value */
+#define GMAC_CORE_CLCK_M_SHIFT		16
+#define GMAC_CORE_CLCK_D_SHIFT		0
+#define GMAC_CORE_CLCK_M_VAL		\
+	(GMAC_CORE_CLCK_M << GMAC_CORE_CLCK_M_SHIFT)
+#define GMAC_CORE_CLCK_D_VAL		\
+	(GMAC_CORE_CLCK_D << GMAC_CORE_CLCK_D_SHIFT)
+
+/* GMAC_COREn_CLK_SRC[0,1]_NS register bits (Assuming 133MHz) */
+#define GMAC_CORE_CLCK_N			0x4 /* NOT(N-M) value, N=301 */
+#define GMAC_CORE_CLCK_N_SHIFT			16
+#define GMAC_CORE_CLCK_N_VAL			\
+	(GMAC_CORE_CLCK_N << GMAC_CORE_CLCK_N_SHIFT)
+/* Enable M/N counter */
+#define GMAC_CORE_CLCK_MNCNTR_EN		0x00000100
+/* Activate reset for M/N counter */
+#define GMAC_CORE_CLCK_MNCNTR_RST		0x00000080
+/* M/N counter mode mask */
+#define GMAC_CORE_CLCK_MNCNTR_MODE_MASK		0x00000060
+#define GMAC_CORE_CLCK_MNCNTR_MODE_SHIFT		5
+/* M/N counter mode dual-edge */
+#define GMAC_CORE_CLCK_MNCNTR_MODE_DUAL		\
+	(2 << GMAC_CORE_CLCK_MNCNTR_MODE_SHIFT)
+/* Pre divider select mask */
+#define GMAC_CORE_CLCK_PRE_DIV_SEL_MASK		0x00000018
+#define GMAC_CORE_CLCK_PRE_DIV_SEL_SHIFT		3
+/* Pre divider bypass */
+#define GMAC_CORE_CLCK_PRE_DIV_SEL_BYP		\
+	(0 << GMAC_CORE_CLCK_PRE_DIV_SEL_SHIFT)
+/* clk source Mux select mask */
+#define GMAC_CORE_CLCK_SRC_SEL_MASK		0x00000007
+#define GMAC_CORE_CLCK_SRC_SEL_SHIFT		0
+/* output of clk source Mux is PLL0 */
+#define GMAC_CORE_CLCK_SRC_SEL_PLL0		\
+	(2 << GMAC_CORE_CLCK_SRC_SEL_SHIFT)
+#define GMAC_COREn_CLCK_CTL(N)			\
+	(0x00900000 + (0x3CB4 + (32*(N-1))))
+
+#define GMAC_COREn_CLCK_INV_DISABLE		(0 << 5)
+#define GMAC_COREn_CLCK_BRANCH_ENA		(1 << 4)
+
+
+/* Uart specific clock settings */
+
+void uart_pll_vote_clk_enable(unsigned int);
+void uart_clock_config(unsigned int gsbi_port, unsigned int m, unsigned int n,
+		unsigned int d, unsigned int clk_dummy);
+void nand_clock_config(void);
+void usb_clock_config(void);
+int audio_clock_config(unsigned frequency);
+
+#endif  /*  __PLATFORM_IPQ860X_CLOCK_H_ */
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/ebi2.h b/src/soc/qualcomm/ipq40xx/include/soc/ebi2.h
new file mode 100644
index 0000000..3636768
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/ebi2.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.
+ *
+ * Taken from U-Boot.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+#ifndef __SOC_QUALCOMM_IPQ806X_EBI2_H_
+#define __SOC_QUALCOMM_IPQ806X_EBI2_H_
+
+#define EBI2CR_BASE                                       (0x1A600000)
+
+struct ebi2cr_regs {
+	uint32_t chip_select_cfg0;                        /* 0x00000000 */
+	uint32_t cfg;                                     /* 0x00000004 */
+	uint32_t hw_info;                                 /* 0x00000008 */
+	uint8_t reserved0[20];
+	uint32_t lcd_cfg0;                                /* 0x00000020 */
+	uint32_t lcd_cfg1;                                /* 0x00000024 */
+	uint8_t reserved1[8];
+	uint32_t arbiter_cfg;                             /* 0x00000030 */
+	uint8_t reserved2[28];
+	uint32_t debug_sel;                               /* 0x00000050 */
+	uint32_t crc_cfg;                                 /* 0x00000054 */
+	uint32_t crc_reminder_cfg;                        /* 0x00000058 */
+	uint32_t nand_adm_mux;                            /* 0x0000005C */
+	uint32_t mutex_addr_offset;                       /* 0x00000060 */
+	uint32_t misr_value;                              /* 0x00000064 */
+	uint32_t clkon_cfg;                               /* 0x00000068 */
+	uint32_t core_clkon_cfg;                          /* 0x0000006C */
+};
+
+/* Register: EBI2_CHIP_SELECT_CFG0 */
+#define CS7_CFG_MASK                             0x00001000
+#define CS7_CFG_DISABLE                          0x00000000
+#define CS7_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x00001000
+#define CS7_CFG(i)                               ((i) << 12)
+
+#define CS6_CFG_MASK                             0x00000800
+#define CS6_CFG_DISABLE                          0x00000000
+#define CS6_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x00000800
+#define CS6_CFG(i)                               ((i) << 11)
+
+#define ETM_CS_CFG_MASK                          0x00000400
+#define ETM_CS_CFG_DISABLE                       0x00000000
+#define ETM_CS_CFG_GENERAL_SRAM_MEMORY_INTERFACE 0x00000400
+#define ETM_CS_CFG(i)                            ((i) << 10)
+
+#define CS5_CFG_MASK                             0x00000300
+#define CS5_CFG_DISABLE                          0x00000000
+#define CS5_CFG_LCD_DEVICE_CONNECTED             0x00000100
+#define CS5_CFG_LCD_DEVICE_CHIP_ENABLE           0x00000200
+#define CS5_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x00000300
+#define CS5_CFG(i)                               ((i) << 8)
+
+#define CS4_CFG_MASK                             0x000000c0
+#define CS4_CFG_DISABLE                          0x00000000
+#define CS4_CFG_LCD_DEVICE_CONNECTED             0x00000040
+#define CS4_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x000000C0
+#define CS4_CFG(i)                               ((i) << 6)
+
+#define CS3_CFG_MASK                             0x00000020
+#define CS3_CFG_DISABLE                          0x00000000
+#define CS3_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x00000020
+#define CS3_CFG(i)                               ((i) << 5)
+
+#define CS2_CFG_MASK                             0x00000010
+#define CS2_CFG_DISABLE                          0x00000000
+#define CS2_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x00000010
+#define CS2_CFG(i)                               ((i) << 4)
+
+#define CS1_CFG_MASK                             0x0000000c
+#define CS1_CFG_DISABLE                          0x00000000
+#define CS1_CFG_SERIAL_FLASH_DEVICE              0x00000004
+#define CS1_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x00000008
+#define CS1_CFG(i)                               ((i) << 2)
+
+#define CS0_CFG_MASK                             0x00000003
+#define CS0_CFG_DISABLE                          0x00000000
+#define CS0_CFG_SERIAL_FLASH_DEVICE              0x00000001
+#define CS0_CFG_GENERAL_SRAM_MEMORY_INTERFACE    0x00000002
+#define CS0_CFG(i)                               ((i) << 0)
+
+#endif
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/gpio.h b/src/soc/qualcomm/ipq40xx/include/soc/gpio.h
new file mode 100644
index 0000000..f7146fe
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/gpio.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.
+ * Source : APQ8064 LK Boot
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef __SOC_QUALCOMM_IPQ806X_GPIO_H_
+#define __SOC_QUALCOMM_IPQ806X_GPIO_H_
+
+#include <types.h>
+
+#define GPIO_FUNC_ENABLE			1
+#define GPIO_FUNC_DISABLE			0
+#define FUNC_SEL_1				1
+#define FUNC_SEL_3				3
+#define FUNC_SEL_GPIO				0
+#define GPIO_DRV_STR_10MA			0x4
+#define GPIO_DRV_STR_11MA			0x7
+
+/* GPIO TLMM: Direction */
+#define GPIO_INPUT      0
+#define GPIO_OUTPUT     1
+
+/* GPIO TLMM: Pullup/Pulldown */
+#define GPIO_NO_PULL    0
+#define GPIO_PULL_DOWN  1
+#define GPIO_KEEPER     2
+#define GPIO_PULL_UP    3
+
+/* GPIO TLMM: Drive Strength */
+#define GPIO_2MA        0
+#define GPIO_4MA        1
+#define GPIO_6MA        2
+#define GPIO_8MA        3
+#define GPIO_10MA       4
+#define GPIO_12MA       5
+#define GPIO_14MA       6
+#define GPIO_16MA       7
+
+/* GPIO TLMM: Status */
+#define GPIO_DISABLE    0
+#define GPIO_ENABLE     1
+
+/* GPIO MAX Valid # */
+#define GPIO_MAX_NUM  68
+
+/* GPIO TLMM: Mask */
+#define GPIO_CFG_PULL_MASK    0x3
+#define GPIO_CFG_FUNC_MASK    0xF
+#define GPIO_CFG_DRV_MASK     0x7
+#define GPIO_CFG_OE_MASK      0x1
+
+/* GPIO TLMM: Shift */
+#define GPIO_CFG_PULL_SHIFT   0
+#define GPIO_CFG_FUNC_SHIFT   2
+#define GPIO_CFG_DRV_SHIFT    6
+#define GPIO_CFG_OE_SHIFT     9
+
+/* GPIO IO: Mask */
+#define GPIO_IO_IN_MASK       0x1
+#define GPIO_IO_OUT_MASK      0x1
+
+/* GPIO IO: Shift */
+#define GPIO_IO_IN_SHIFT      0
+#define GPIO_IO_OUT_SHIFT     1
+
+typedef u32 gpio_t;
+
+void gpio_tlmm_config_set(gpio_t gpio, unsigned int func,
+			  unsigned int pull, unsigned int drvstr,
+			  unsigned int enable);
+
+void gpio_tlmm_config_get(gpio_t gpio, unsigned int *func,
+			  unsigned int *pull, unsigned int *drvstr,
+			  unsigned int *enable);
+
+void gpio_io_config_set(gpio_t gpio, unsigned int out);
+
+/* Keep this to maintain backwards compatibility with the vendor API. */
+static inline void gpio_tlmm_config(unsigned int gpio, unsigned int func,
+				    unsigned int dir, unsigned int pull,
+				    unsigned int drvstr, unsigned int enable)
+{
+	gpio_tlmm_config_set(gpio, func, pull, drvstr, enable);
+}
+#endif // __SOC_QUALCOMM_IPQ806X_GPIO_H_
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/gsbi.h b/src/soc/qualcomm/ipq40xx/include/soc/gsbi.h
new file mode 100644
index 0000000..f2c375d
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/gsbi.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011-2012 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+
+#ifndef __GSBI_H_
+#define __GSBI_H_
+
+/* GSBI Registers */
+#define GSBI_CTRL_REG(base)        ((base) + 0x0)
+
+#define GSBI_CTRL_REG_PROTOCOL_CODE_S   4
+#define GSBI_PROTOCOL_CODE_I2C          0x2
+#define GSBI_PROTOCOL_CODE_SPI          0x3
+#define GSBI_PROTOCOL_CODE_UART_FLOW    0x4
+#define GSBI_PROTOCOL_CODE_I2C_UART     0x6
+
+#define GSBI_HCLK_CTL_S                 4
+#define GSBI_HCLK_CTL_CLK_ENA           0x1
+
+typedef enum {
+	GSBI_ID_1 = 1,
+	GSBI_ID_2,
+	GSBI_ID_3,
+	GSBI_ID_4,
+	GSBI_ID_5,
+	GSBI_ID_6,
+	GSBI_ID_7,
+} gsbi_id_t;
+
+typedef enum {
+	GSBI_SUCCESS = 0,
+	GSBI_ID_ERROR,
+	GSBI_ERROR,
+	GSBI_UNSUPPORTED
+} gsbi_return_t;
+
+typedef enum {
+	GSBI_PROTO_I2C_UIM = 1,
+	GSBI_PROTO_I2C_ONLY,
+	GSBI_PROTO_SPI_ONLY,
+	GSBI_PROTO_UART_FLOW_CTL,
+	GSBI_PROTO_UIM,
+	GSBI_PROTO_I2C_UART,
+} gsbi_protocol_t;
+
+gsbi_return_t gsbi_init(gsbi_id_t gsbi_id, gsbi_protocol_t protocol);
+int gsbi_init_board(gsbi_id_t gsbi_id);
+
+#endif
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/iomap.h b/src/soc/qualcomm/ipq40xx/include/soc/iomap.h
new file mode 100644
index 0000000..4a3aa49
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/iomap.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2012 - 2013, 2015 The Linux Foundation. All rights reserved.
+ *
+ * Copyright (c) 2008, Google Inc.
+ * All rights reserved.
+ *
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *  * Neither the name of Google, Inc. nor the names of its contributors
+ *    may be used to endorse or promote products derived from this
+ *    software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef __SOC_QUALCOMM_IPQ806X_IOMAP_H_
+#define __SOC_QUALCOMM_IPQ806X_IOMAP_H_
+
+#include <arch/io.h>
+#include <soc/cdp.h>
+
+/* Typecast to allow integers being passed as address
+   This needs to be included because vendor code is not compliant with our
+   macros for read/write. Hence, special macros for readl_i and writel_i are
+   included to do this in one place for all occurrences in vendor code
+ */
+#define readl_i(a)           read32((const void *)(a))
+#define writel_i(v,a)        write32((void *)a, v)
+#define clrsetbits_le32_i(addr, clear, set)  \
+	clrsetbits_le32(((void *)(addr)), (clear), (set))
+
+#define MSM_CLK_CTL_BASE    ((void *)0x00900000)
+
+#define MSM_TMR_BASE        ((void *)0x0200A000)
+#define MSM_GPT_BASE        (MSM_TMR_BASE + 0x04)
+#define MSM_DGT_BASE        (MSM_TMR_BASE + 0x24)
+
+#define GPT_REG(off)        (MSM_GPT_BASE + (off))
+#define DGT_REG(off)        (MSM_DGT_BASE + (off))
+
+#define APCS_WDT0_EN        (MSM_TMR_BASE + 0x0040)
+#define APCS_WDT0_RST       (MSM_TMR_BASE + 0x0038)
+#define APCS_WDT0_BARK_TIME (MSM_TMR_BASE + 0x004C)
+#define APCS_WDT0_BITE_TIME (MSM_TMR_BASE + 0x005C)
+
+#define APCS_WDT0_CPU0_WDOG_EXPIRED_ENABLE (MSM_CLK_CTL_BASE + 0x3820)
+
+#define GPT_MATCH_VAL        GPT_REG(0x0000)
+#define GPT_COUNT_VAL        GPT_REG(0x0004)
+#define GPT_ENABLE           GPT_REG(0x0008)
+#define GPT_CLEAR            GPT_REG(0x000C)
+
+#define GPT1_MATCH_VAL       GPT_REG(0x00010)
+#define GPT1_COUNT_VAL       GPT_REG(0x00014)
+#define GPT1_ENABLE          GPT_REG(0x00018)
+#define GPT1_CLEAR           GPT_REG(0x0001C)
+
+#define DGT_MATCH_VAL        DGT_REG(0x0000)
+#define DGT_COUNT_VAL        DGT_REG(0x0004)
+#define DGT_ENABLE           DGT_REG(0x0008)
+#define DGT_CLEAR            DGT_REG(0x000C)
+#define DGT_CLK_CTL          DGT_REG(0x0010)
+
+/* RPM interface constants */
+#define RPM_INT           ((void *)0x63020)
+#define RPM_INT_ACK       ((void *)0x63060)
+#define RPM_SIGNAL_COOKIE ((void *)0x47C20)
+#define RPM_SIGNAL_ENTRY  ((void *)0x47C24)
+#define RPM_FW_MAGIC_NUM 0x4D505242
+
+#define TLMM_BASE_ADDR      ((void *)0x00800000)
+#define GPIO_CONFIG_ADDR(x) (TLMM_BASE_ADDR + 0x1000 + (x)*0x10)
+#define GPIO_IN_OUT_ADDR(x) (GPIO_CONFIG_ADDR(x) + 4)
+
+/* Yes, this is not a typo... host2 is actually mapped before host1. */
+#define USB_HOST2_XHCI_BASE	0x10000000
+#define USB_HOST2_DWC3_BASE	0x1000C100
+#define USB_HOST2_PHY_BASE	0x100F8800
+#define USB_HOST1_XHCI_BASE	0x11000000
+#define USB_HOST1_DWC3_BASE	0x1100C100
+#define USB_HOST1_PHY_BASE	0x110F8800
+
+#define GSBI_4			4
+#define UART1_DM_BASE         	0x12450000
+#define UART_GSBI1_BASE       	0x12440000
+#define UART2_DM_BASE		0x12490000
+#define UART_GSBI2_BASE		0x12480000
+#define UART4_DM_BASE         	0x16340000
+#define UART_GSBI4_BASE       	0x16300000
+
+#define UART2_DM_BASE           0x12490000
+#define UART_GSBI2_BASE         0x12480000
+
+#define GSBI1_BASE		((void *)0x12440000)
+#define GSBI2_BASE		((void *)0x12480000)
+#define GSBI3_BASE		((void *)0x16200000)
+#define GSBI4_BASE		((void *)0x16300000)
+#define GSBI5_BASE		((void *)0x1A200000)
+#define GSBI6_BASE		((void *)0x16500000)
+#define GSBI7_BASE		((void *)0x16600000)
+
+#define GSBI1_CTL_REG		(GSBI1_BASE + (0x0))
+#define GSBI2_CTL_REG		(GSBI2_BASE + (0x0))
+#define GSBI3_CTL_REG		(GSBI3_BASE + (0x0))
+#define GSBI4_CTL_REG		(GSBI4_BASE + (0x0))
+#define GSBI5_CTL_REG		(GSBI5_BASE + (0x0))
+#define GSBI6_CTL_REG		(GSBI6_BASE + (0x0))
+#define GSBI7_CTL_REG		(GSBI7_BASE + (0x0))
+
+#define GSBI_QUP1_BASE		(GSBI1_BASE + 0x20000)
+#define GSBI_QUP2_BASE		(GSBI2_BASE + 0x20000)
+#define GSBI_QUP3_BASE		(GSBI3_BASE + 0x80000)
+#define GSBI_QUP4_BASE		(GSBI4_BASE + 0x80000)
+#define GSBI_QUP5_BASE		(GSBI5_BASE + 0x80000)
+#define GSBI_QUP6_BASE		(GSBI6_BASE + 0x80000)
+#define GSBI_QUP7_BASE		(GSBI7_BASE + 0x80000)
+
+#define GSBI_CTL_PROTO_I2C              2
+#define GSBI_CTL_PROTO_CODE_SFT         4
+#define GSBI_CTL_PROTO_CODE_MSK         0x7
+#define GSBI_HCLK_CTL_GATE_ENA          6
+#define GSBI_HCLK_CTL_BRANCH_ENA        4
+#define GSBI_QUP_APPS_M_SHFT            16
+#define GSBI_QUP_APPS_M_MASK            0xFF
+#define GSBI_QUP_APPS_D_SHFT            0
+#define GSBI_QUP_APPS_D_MASK            0xFF
+#define GSBI_QUP_APPS_N_SHFT            16
+#define GSBI_QUP_APPS_N_MASK            0xFF
+#define GSBI_QUP_APPS_ROOT_ENA_SFT      11
+#define GSBI_QUP_APPS_BRANCH_ENA_SFT    9
+#define GSBI_QUP_APPS_MNCTR_EN_SFT      8
+#define GSBI_QUP_APPS_MNCTR_MODE_MSK    0x3
+#define GSBI_QUP_APPS_MNCTR_MODE_SFT    5
+#define GSBI_QUP_APPS_PRE_DIV_MSK       0x3
+#define GSBI_QUP_APPS_PRE_DIV_SFT       3
+#define GSBI_QUP_APPS_SRC_SEL_MSK       0x7
+
+
+#define GSBI_QUP_APSS_MD_REG(gsbi_n)	((MSM_CLK_CTL_BASE + 0x29c8) + \
+							(32*(gsbi_n-1)))
+#define GSBI_QUP_APSS_NS_REG(gsbi_n)	((MSM_CLK_CTL_BASE + 0x29cc) + \
+							(32*(gsbi_n-1)))
+#define GSBI_HCLK_CTL(n)		((MSM_CLK_CTL_BASE + 0x29C0) + \
+							(32*(n-1)))
+#endif // __SOC_QUALCOMM_IPQ806X_IOMAP_H_
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/ipq_timer.h b/src/soc/qualcomm/ipq40xx/include/soc/ipq_timer.h
new file mode 100644
index 0000000..0d0f9d2
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/ipq_timer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#define TIMER_LOAD_VAL 0x21
+
+#define GPT_ENABLE_CLR_ON_MATCH_EN        2
+#define GPT_ENABLE_EN                     1
+#define DGT_ENABLE_CLR_ON_MATCH_EN        2
+#define DGT_ENABLE_EN                     1
+
+#define SPSS_TIMER_STATUS_DGT_EN    (1 << 0)
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/ipq_uart.h b/src/soc/qualcomm/ipq40xx/include/soc/ipq_uart.h
new file mode 100644
index 0000000..1c994a3
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/ipq_uart.h
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.*
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef __UART_DM_H__
+#define __UART_DM_H__
+
+#define PERIPH_BLK_BLSP 0
+
+#define MSM_BOOT_UART_DM_EXTR_BITS(value, start_pos, end_pos) \
+	((value << (32 - end_pos)) >> (32 - (end_pos - start_pos)))
+
+extern void __udelay(unsigned long usec);
+
+
+enum MSM_BOOT_UART_DM_PARITY_MODE {
+	MSM_BOOT_UART_DM_NO_PARITY,
+	MSM_BOOT_UART_DM_ODD_PARITY,
+	MSM_BOOT_UART_DM_EVEN_PARITY,
+	MSM_BOOT_UART_DM_SPACE_PARITY
+};
+
+/* UART Stop Bit Length */
+enum MSM_BOOT_UART_DM_STOP_BIT_LEN {
+	MSM_BOOT_UART_DM_SBL_9_16,
+	MSM_BOOT_UART_DM_SBL_1,
+	MSM_BOOT_UART_DM_SBL_1_9_16,
+	MSM_BOOT_UART_DM_SBL_2
+};
+
+/* UART Bits per Char */
+enum MSM_BOOT_UART_DM_BITS_PER_CHAR {
+	MSM_BOOT_UART_DM_5_BPS,
+	MSM_BOOT_UART_DM_6_BPS,
+	MSM_BOOT_UART_DM_7_BPS,
+	MSM_BOOT_UART_DM_8_BPS
+};
+
+/* 8-N-1 Configuration */
+#define MSM_BOOT_UART_DM_8_N_1_MODE	(MSM_BOOT_UART_DM_NO_PARITY | \
+					 (MSM_BOOT_UART_DM_SBL_1 << 2) | \
+					 (MSM_BOOT_UART_DM_8_BPS << 4))
+
+/* UART_DM Registers */
+
+/* UART Operational Mode Register */
+#define MSM_BOOT_UART_DM_MR1(base)	((base) + 0x00)
+#define MSM_BOOT_UART_DM_MR2(base)	((base) + 0x04)
+#define MSM_BOOT_UART_DM_RXBRK_ZERO_CHAR_OFF (1 << 8)
+#define MSM_BOOT_UART_DM_LOOPBACK	(1 << 7)
+
+/* UART Clock Selection Register */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_CSR(base)	((base) + 0xA0)
+#else
+#define MSM_BOOT_UART_DM_CSR(base)	((base) + 0x08)
+#endif
+
+/* UART DM TX FIFO Registers - 4 */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_TF(base, x)	((base) + 0x100+(4*(x)))
+#else
+#define MSM_BOOT_UART_DM_TF(base, x)	((base) + 0x70+(4*(x)))
+#endif
+
+/* UART Command Register */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_CR(base)	((base) + 0xA8)
+#else
+#define MSM_BOOT_UART_DM_CR(base)	((base) + 0x10)
+#endif
+#define MSM_BOOT_UART_DM_CR_RX_ENABLE        (1 << 0)
+#define MSM_BOOT_UART_DM_CR_RX_DISABLE       (1 << 1)
+#define MSM_BOOT_UART_DM_CR_TX_ENABLE        (1 << 2)
+#define MSM_BOOT_UART_DM_CR_TX_DISABLE       (1 << 3)
+
+/* UART Channel Command */
+#define MSM_BOOT_UART_DM_CR_CH_CMD_LSB(x)    ((x & 0x0f) << 4)
+#define MSM_BOOT_UART_DM_CR_CH_CMD_MSB(x)    ((x >> 4) << 11)
+#define MSM_BOOT_UART_DM_CR_CH_CMD(x)		\
+	(MSM_BOOT_UART_DM_CR_CH_CMD_LSB(x) | MSM_BOOT_UART_DM_CR_CH_CMD_MSB(x))
+#define MSM_BOOT_UART_DM_CMD_NULL            MSM_BOOT_UART_DM_CR_CH_CMD(0)
+#define MSM_BOOT_UART_DM_CMD_RESET_RX        MSM_BOOT_UART_DM_CR_CH_CMD(1)
+#define MSM_BOOT_UART_DM_CMD_RESET_TX        MSM_BOOT_UART_DM_CR_CH_CMD(2)
+#define MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT  MSM_BOOT_UART_DM_CR_CH_CMD(3)
+#define MSM_BOOT_UART_DM_CMD_RES_BRK_CHG_INT MSM_BOOT_UART_DM_CR_CH_CMD(4)
+#define MSM_BOOT_UART_DM_CMD_START_BRK       MSM_BOOT_UART_DM_CR_CH_CMD(5)
+#define MSM_BOOT_UART_DM_CMD_STOP_BRK        MSM_BOOT_UART_DM_CR_CH_CMD(6)
+#define MSM_BOOT_UART_DM_CMD_RES_CTS_N       MSM_BOOT_UART_DM_CR_CH_CMD(7)
+#define MSM_BOOT_UART_DM_CMD_RES_STALE_INT   MSM_BOOT_UART_DM_CR_CH_CMD(8)
+#define MSM_BOOT_UART_DM_CMD_PACKET_MODE     MSM_BOOT_UART_DM_CR_CH_CMD(9)
+#define MSM_BOOT_UART_DM_CMD_MODE_RESET      MSM_BOOT_UART_DM_CR_CH_CMD(C)
+#define MSM_BOOT_UART_DM_CMD_SET_RFR_N       MSM_BOOT_UART_DM_CR_CH_CMD(D)
+#define MSM_BOOT_UART_DM_CMD_RES_RFR_N       MSM_BOOT_UART_DM_CR_CH_CMD(E)
+#define MSM_BOOT_UART_DM_CMD_RES_TX_ERR      MSM_BOOT_UART_DM_CR_CH_CMD(10)
+#define MSM_BOOT_UART_DM_CMD_CLR_TX_DONE     MSM_BOOT_UART_DM_CR_CH_CMD(11)
+#define MSM_BOOT_UART_DM_CMD_RES_BRKSTRT_INT MSM_BOOT_UART_DM_CR_CH_CMD(12)
+#define MSM_BOOT_UART_DM_CMD_RES_BRKEND_INT  MSM_BOOT_UART_DM_CR_CH_CMD(13)
+#define MSM_BOOT_UART_DM_CMD_RES_PER_FRM_INT MSM_BOOT_UART_DM_CR_CH_CMD(14)
+
+/*UART General Command */
+#define MSM_BOOT_UART_DM_CR_GENERAL_CMD(x)   ((x) << 8)
+
+#define MSM_BOOT_UART_DM_GCMD_NULL            MSM_BOOT_UART_DM_CR_GENERAL_CMD(0)
+#define MSM_BOOT_UART_DM_GCMD_CR_PROT_EN      MSM_BOOT_UART_DM_CR_GENERAL_CMD(1)
+#define MSM_BOOT_UART_DM_GCMD_CR_PROT_DIS     MSM_BOOT_UART_DM_CR_GENERAL_CMD(2)
+#define MSM_BOOT_UART_DM_GCMD_RES_TX_RDY_INT  MSM_BOOT_UART_DM_CR_GENERAL_CMD(3)
+#define MSM_BOOT_UART_DM_GCMD_SW_FORCE_STALE  MSM_BOOT_UART_DM_CR_GENERAL_CMD(4)
+#define MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT   MSM_BOOT_UART_DM_CR_GENERAL_CMD(5)
+#define MSM_BOOT_UART_DM_GCMD_DIS_STALE_EVT   MSM_BOOT_UART_DM_CR_GENERAL_CMD(6)
+
+/* UART Interrupt Mask Register */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_IMR(base)             ((base) + 0xB0)
+#else
+#define MSM_BOOT_UART_DM_IMR(base)             ((base) + 0x14)
+#endif
+
+#define MSM_BOOT_UART_DM_TXLEV               (1 << 0)
+#define MSM_BOOT_UART_DM_RXHUNT              (1 << 1)
+#define MSM_BOOT_UART_DM_RXBRK_CHNG          (1 << 2)
+#define MSM_BOOT_UART_DM_RXSTALE             (1 << 3)
+#define MSM_BOOT_UART_DM_RXLEV               (1 << 4)
+#define MSM_BOOT_UART_DM_DELTA_CTS           (1 << 5)
+#define MSM_BOOT_UART_DM_CURRENT_CTS         (1 << 6)
+#define MSM_BOOT_UART_DM_TX_READY            (1 << 7)
+#define MSM_BOOT_UART_DM_TX_ERROR            (1 << 8)
+#define MSM_BOOT_UART_DM_TX_DONE             (1 << 9)
+#define MSM_BOOT_UART_DM_RXBREAK_START       (1 << 10)
+#define MSM_BOOT_UART_DM_RXBREAK_END         (1 << 11)
+#define MSM_BOOT_UART_DM_PAR_FRAME_ERR_IRQ   (1 << 12)
+
+#define MSM_BOOT_UART_DM_IMR_ENABLED         (MSM_BOOT_UART_DM_TX_READY | \
+						MSM_BOOT_UART_DM_TXLEV | \
+						MSM_BOOT_UART_DM_RXSTALE)
+
+/* UART Interrupt Programming Register */
+#define MSM_BOOT_UART_DM_IPR(base)             ((base) + 0x18)
+#define MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB   0x0f
+#define MSM_BOOT_UART_DM_STALE_TIMEOUT_MSB   0	/* Not used currently */
+
+/* UART Transmit/Receive FIFO Watermark Register */
+#define MSM_BOOT_UART_DM_TFWR(base)            ((base) + 0x1C)
+/* Interrupt is generated when FIFO level is less than or equal to this value */
+#define MSM_BOOT_UART_DM_TFW_VALUE           0
+
+#define MSM_BOOT_UART_DM_RFWR(base)            ((base) + 0x20)
+/*Interrupt generated when no of words in RX FIFO is greater than this value */
+#define MSM_BOOT_UART_DM_RFW_VALUE           0
+
+/* UART Hunt Character Register */
+#define MSM_BOOT_UART_DM_HCR(base)             ((base) + 0x24)
+
+/* Used for RX transfer initialization */
+#define MSM_BOOT_UART_DM_DMRX(base)            ((base) + 0x34)
+
+/* Default DMRX value - any value bigger than FIFO size would be fine */
+#define MSM_BOOT_UART_DM_DMRX_DEF_VALUE    0x220
+
+/* Register to enable IRDA function */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_IRDA(base)            ((base) + 0xB8)
+#else
+#define MSM_BOOT_UART_DM_IRDA(base)            ((base) + 0x38)
+#endif
+
+/* UART Data Mover Enable Register */
+#define MSM_BOOT_UART_DM_DMEN(base)            ((base) + 0x3C)
+
+/* Number of characters for Transmission */
+#define MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base) ((base) + 0x040)
+
+/* UART RX FIFO Base Address */
+#define MSM_BOOT_UART_DM_BADR(base)            ((base) + 0x44)
+
+/* UART Status Register */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_SR(base)              ((base) + 0x0A4)
+#else
+#define MSM_BOOT_UART_DM_SR(base)              ((base) + 0x008)
+#endif
+#define MSM_BOOT_UART_DM_SR_RXRDY            (1 << 0)
+#define MSM_BOOT_UART_DM_SR_RXFULL           (1 << 1)
+#define MSM_BOOT_UART_DM_SR_TXRDY            (1 << 2)
+#define MSM_BOOT_UART_DM_SR_TXEMT            (1 << 3)
+#define MSM_BOOT_UART_DM_SR_UART_OVERRUN     (1 << 4)
+#define MSM_BOOT_UART_DM_SR_PAR_FRAME_ERR    (1 << 5)
+#define MSM_BOOT_UART_DM_RX_BREAK            (1 << 6)
+#define MSM_BOOT_UART_DM_HUNT_CHAR           (1 << 7)
+#define MSM_BOOT_UART_DM_RX_BRK_START_LAST   (1 << 8)
+
+/* UART Receive FIFO Registers - 4 in numbers */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_RF(base, x)      ((base) + 0x140 + (4*(x)))
+#else
+#define MSM_BOOT_UART_DM_RF(base, x)      ((base) + 0x70 + (4*(x)))
+#endif
+
+/* UART Masked Interrupt Status Register */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_MISR(base)         ((base) + 0xAC)
+#else
+#define MSM_BOOT_UART_DM_MISR(base)         ((base) + 0x10)
+#endif
+
+/* UART Interrupt Status Register */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_ISR(base)          ((base) + 0xB4)
+#else
+#define MSM_BOOT_UART_DM_ISR(base)          ((base) + 0x14)
+#endif
+
+/* Number of characters received since the end of last RX transfer */
+#if PERIPH_BLK_BLSP
+#define MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base)  ((base) + 0xBC)
+#else
+#define MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base)  ((base) + 0x38)
+#endif
+
+/* UART TX FIFO Status Register */
+#define MSM_BOOT_UART_DM_TXFS(base)           ((base) + 0x4C)
+#define MSM_BOOT_UART_DM_TXFS_STATE_LSB(x)   MSM_BOOT_UART_DM_EXTR_BITS(x, 0, 6)
+#define MSM_BOOT_UART_DM_TXFS_STATE_MSB(x)   \
+	MSM_BOOT_UART_DM_EXTR_BITS(x, 14, 31)
+#define MSM_BOOT_UART_DM_TXFS_BUF_STATE(x)   MSM_BOOT_UART_DM_EXTR_BITS(x, 7, 9)
+#define MSM_BOOT_UART_DM_TXFS_ASYNC_STATE(x) \
+	MSM_BOOT_UART_DM_EXTR_BITS(x, 10, 13)
+
+/* UART RX FIFO Status Register */
+#define MSM_BOOT_UART_DM_RXFS(base)           ((base) + 0x50)
+#define MSM_BOOT_UART_DM_RXFS_STATE_LSB(x)   MSM_BOOT_UART_DM_EXTR_BITS(x, 0, 6)
+#define MSM_BOOT_UART_DM_RXFS_STATE_MSB(x)   \
+	MSM_BOOT_UART_DM_EXTR_BITS(x, 14, 31)
+#define MSM_BOOT_UART_DM_RXFS_BUF_STATE(x)   MSM_BOOT_UART_DM_EXTR_BITS(x, 7, 9)
+#define MSM_BOOT_UART_DM_RXFS_ASYNC_STATE(x) \
+	MSM_BOOT_UART_DM_EXTR_BITS(x, 10, 13)
+
+/* Macros for Common Errors */
+#define MSM_BOOT_UART_DM_E_SUCCESS           0
+#define MSM_BOOT_UART_DM_E_FAILURE           1
+#define MSM_BOOT_UART_DM_E_TIMEOUT           2
+#define MSM_BOOT_UART_DM_E_INVAL             3
+#define MSM_BOOT_UART_DM_E_MALLOC_FAIL       4
+#define MSM_BOOT_UART_DM_E_RX_NOT_READY      5
+
+void ipq806x_uart_init(void);
+
+#endif				/* __UART_DM_H__ */
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/lcc-reg.h b/src/soc/qualcomm/ipq40xx/include/soc/lcc-reg.h
new file mode 100644
index 0000000..2827ac9
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/lcc-reg.h
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef __DRIVERS_CLOCK_IPQ806X_LCC_REG_H__
+#define __DRIVERS_CLOCK_IPQ806X_LCC_REG_H__
+
+#define MSM_GCC_BASE			0x00900000
+#define MSM_LPASS_LCC_BASE		0x28000000
+
+/* GCC APCS Configuration/Control */
+
+#define GCC_PLL_APCS_REG		0x34C0
+
+#define GCC_PLL_APCS_PLL4_MASK		0x10
+#define GCC_PLL_APCS_PLL4_SHIFT		4
+#define GCC_PLL_APCS_PLL4_ENABLE	(1 << GCC_PLL_APCS_PLL4_SHIFT)
+
+/* LCC PLL0 Configuration/Control */
+
+#define LCC_PLL0_MODE_REG		0x00
+#define LCC_PLL0_L_REG			0x04
+#define LCC_PLL0_M_REG			0x08
+#define LCC_PLL0_N_REG			0x0C
+#define LCC_PLL0_CFG_REG		0x14
+#define LCC_PLL0_STAT_REG		0x18
+
+#define LCC_PLL0_MODE_FSM_RESET_MASK	0x200000
+#define LCC_PLL0_MODE_FSM_RESET_SHIFT	21
+#define LCC_PLL0_MODE_FSM_RESET_ASSERT	(1 << LCC_PLL0_MODE_FSM_RESET_SHIFT)
+
+#define LCC_PLL0_MODE_FSM_VOTE_MASK	0x100000
+#define LCC_PLL0_MODE_FSM_VOTE_SHIFT	20
+#define LCC_PLL0_MODE_FSM_VOTE_ENABLE	(1 << LCC_PLL0_MODE_FSM_VOTE_SHIFT)
+
+#define LCC_PLL0_MODE_BIAS_CNT_MASK	0xFC000
+#define LCC_PLL0_MODE_BIAS_CNT_SHIFT	14
+
+#define LCC_PLL0_MODE_LOCK_CNT_MASK	0x3F00
+#define LCC_PLL0_MODE_LOCK_CNT_SHIFT	8
+
+#define LCC_PLL0_MODE_XO_SEL_MASK	0x30
+#define LCC_PLL0_MODE_XO_SEL_SHIFT	4
+#define LCC_PLL0_MODE_XO_SEL_PXO	(0 << LCC_PLL0_MODE_XO_SEL_SHIFT)
+#define LCC_PLL0_MODE_XO_SEL_MXO	(1 << LCC_PLL0_MODE_XO_SEL_SHIFT)
+#define LCC_PLL0_MODE_XO_SEL_CXO	(2 << LCC_PLL0_MODE_XO_SEL_SHIFT)
+
+#define LCC_PLL0_MODE_TEST_MASK		0x8
+#define LCC_PLL0_MODE_TEST_SHIFT	3
+#define LCC_PLL0_MODE_TEST_ENABLE	(1 << LCC_PLL0_MODE_TEST_SHIFT)
+
+#define LCC_PLL0_MODE_RESET_MASK	0x4
+#define LCC_PLL0_MODE_RESET_SHIFT	2
+#define LCC_PLL0_MODE_RESET_DEASSERT	(1 << LCC_PLL0_MODE_RESET_SHIFT)
+
+#define LCC_PLL0_MODE_BYPASS_MASK	0x2
+#define LCC_PLL0_MODE_BYPASS_SHIFT	1
+#define LCC_PLL0_MODE_BYPASS_DISABLE	(1 << LCC_PLL0_MODE_BYPASS_SHIFT)
+
+#define LCC_PLL0_MODE_OUTPUT_MASK	0x1
+#define LCC_PLL0_MODE_OUTPUT_SHIFT	0
+#define LCC_PLL0_MODE_OUTPUT_ENABLE	(1 << LCC_PLL0_MODE_OUTPUT_SHIFT)
+
+#define LCC_PLL0_L_MASK			0x3FF
+#define LCC_PLL0_L_SHIFT		0
+
+#define LCC_PLL0_M_MASK			0x7FFFF
+#define LCC_PLL0_M_SHIFT		0
+
+#define LCC_PLL0_N_MASK			0x7FFFF
+#define LCC_PLL0_N_SHIFT		0
+
+#define LCC_PLL0_CFG_LV_MAIN_MASK	0x800000
+#define LCC_PLL0_CFG_LV_MAIN_SHIFT	23
+#define LCC_PLL0_CFG_LV_MAIN_ENABLE	(1 << LCC_PLL0_CFG_LV_MAIN_SHIFT)
+
+#define LCC_PLL0_CFG_FRAC_MASK		0x400000
+#define LCC_PLL0_CFG_FRAC_SHIFT		22
+#define LCC_PLL0_CFG_FRAC_ENABLE	(1 << LCC_PLL0_CFG_FRAC_SHIFT)
+
+#define LCC_PLL0_CFG_POSTDIV_MASK	0x300000
+#define LCC_PLL0_CFG_POSTDIV_SHIFT	20
+#define LCC_PLL0_CFG_POSTDIV_DIV1	(0 << LCC_PLL0_CFG_POSTDIV_SHIFT)
+#define LCC_PLL0_CFG_POSTDIV_DIV2	(1 << LCC_PLL0_CFG_POSTDIV_SHIFT)
+#define LCC_PLL0_CFG_POSTDIV_DIV4	(2 << LCC_PLL0_CFG_POSTDIV_SHIFT)
+
+#define LCC_PLL0_CFG_PREDIV_MASK	0x80000
+#define LCC_PLL0_CFG_PREDIV_SHIFT	19
+#define LCC_PLL0_CFG_PREDIV_DIV1	(0 << LCC_PLL0_CFG_PREDIV_SHIFT)
+#define LCC_PLL0_CFG_PREDIV_DIV2	(1 << LCC_PLL0_CFG_PREDIV_SHIFT)
+
+#define LCC_PLL0_CFG_VCO_SEL_MASK	0x30000
+#define LCC_PLL0_CFG_VCO_SEL_SHIFT	16
+#define LCC_PLL0_CFG_VCO_SEL_LOW	(0 << LCC_PLL0_CFG_VCO_SEL_SHIFT)
+#define LCC_PLL0_CFG_VCO_SEL_MED	(1 << LCC_PLL0_CFG_VCO_SEL_SHIFT)
+#define LCC_PLL0_CFG_VCO_SEL_HIGH	(2 << LCC_PLL0_CFG_VCO_SEL_SHIFT)
+
+#define LCC_PLL0_STAT_ACTIVE_MASK	0x10000
+#define LCC_PLL0_STAT_ACTIVE_SHIFT	16
+#define LCC_PLL0_STAT_ACTIVE_SET	(1 << LCC_PLL0_STAT_ACTIVE_SHIFT)
+
+#define LCC_PLL0_STAT_NOCLK_MASK	0x1
+#define LCC_PLL0_STAT_NOCLK_SHIFT	0
+#define LCC_PLL0_STAT_NOCLK_SET		(1 << LCC_PLL0_STAT_NOCLK_SHIFT)
+
+/* LCC AHBIX Configuration/Control */
+
+#define LCC_AHBIX_NS_REG		0x38
+#define LCC_AHBIX_MD_REG		0x3C
+#define LCC_AHBIX_STAT_REG		0x44
+
+#define LCC_AHBIX_NS_N_VAL_MASK		0xFF000000
+#define LCC_AHBIX_NS_N_VAL_SHIFT	24
+
+#define LCC_AHBIX_NS_CRC_MASK		0x800
+#define LCC_AHBIX_NS_CRC_SHIFT		11
+#define LCC_AHBIX_NS_CRC_ENABLE		(1 << LCC_AHBIX_NS_CRC_SHIFT)
+
+#define LCC_AHBIX_NS_GFM_SEL_MASK	0x400
+#define LCC_AHBIX_NS_GFM_SEL_SHIFT	10
+#define LCC_AHBIX_NS_GFM_SEL_PXO	(0 << LCC_AHBIX_NS_GFM_SEL_SHIFT)
+#define LCC_AHBIX_NS_GFM_SEL_MNC	(1 << LCC_AHBIX_NS_GFM_SEL_SHIFT)
+
+#define LCC_AHBIX_NS_MNC_CLK_MASK	0x200
+#define LCC_AHBIX_NS_MNC_CLK_SHIFT	9
+#define LCC_AHBIX_NS_MNC_CLK_ENABLE	(1 << LCC_AHBIX_NS_MNC_CLK_SHIFT)
+
+#define LCC_AHBIX_NS_MNC_MASK		0x100
+#define LCC_AHBIX_NS_MNC_SHIFT		8
+#define LCC_AHBIX_NS_MNC_ENABLE		(1 << LCC_AHBIX_NS_MNC_SHIFT)
+
+#define LCC_AHBIX_NS_MNC_RESET_MASK	0x80
+#define LCC_AHBIX_NS_MNC_RESET_SHIFT	7
+#define LCC_AHBIX_NS_MNC_RESET_ASSERT	(1 << LCC_AHBIX_NS_MNC_RESET_SHIFT)
+
+#define LCC_AHBIX_NS_MNC_MODE_MASK	0x60
+#define LCC_AHBIX_NS_MNC_MODE_SHIFT	5
+#define LCC_AHBIX_NS_MNC_MODE_BYPASS	(0 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
+#define LCC_AHBIX_NS_MNC_MODE_SWALLOW	(1 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
+#define LCC_AHBIX_NS_MNC_MODE_DUAL	(2 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
+#define LCC_AHBIX_NS_MNC_MODE_SINGLE	(3 << LCC_AHBIX_NS_MNC_MODE_SHIFT)
+
+#define LCC_AHBIX_NS_PREDIV_MASK	0x18
+#define LCC_AHBIX_NS_PREDIV_SHIFT	3
+#define LCC_AHBIX_NS_PREDIV_BYPASS	(0 << LCC_AHBIX_NS_PREDIV_SHIFT)
+#define LCC_AHBIX_NS_PREDIV_DIV2	(1 << LCC_AHBIX_NS_PREDIV_SHIFT)
+#define LCC_AHBIX_NS_PREDIV_DIV4	(3 << LCC_AHBIX_NS_PREDIV_SHIFT)
+
+#define LCC_AHBIX_NS_MN_SRC_MASK	0x7
+#define LCC_AHBIX_NS_MN_SRC_SHIFT	0
+#define LCC_AHBIX_NS_MN_SRC_PXO		(0 << LCC_AHBIX_NS_MN_SRC_SHIFT)
+#define LCC_AHBIX_NS_MN_SRC_CXO		(1 << LCC_AHBIX_NS_MN_SRC_SHIFT)
+#define LCC_AHBIX_NS_MN_SRC_LPA		(2 << LCC_AHBIX_NS_MN_SRC_SHIFT)
+#define LCC_AHBIX_NS_MN_SRC_SEC		(3 << LCC_AHBIX_NS_MN_SRC_SHIFT)
+#define LCC_AHBIX_NS_MN_SRC_CTEST	(6 << LCC_AHBIX_NS_MN_SRC_SHIFT)
+#define LCC_AHBIX_NS_MN_SRC_PTEST	(7 << LCC_AHBIX_NS_MN_SRC_SHIFT)
+
+#define LCC_AHBIX_MD_M_VAL_MASK		0xFF00
+#define LCC_AHBIX_MD_M_VAL_SHIFT	8
+
+#define LCC_AHBIX_MD_NOT_2D_VAL_MASK	0xFF
+#define LCC_AHBIX_MD_NOT_2D_VAL_SHIFT	0
+
+#define LCC_AHBIX_STAT_AHB_CLK_MASK	0x400
+#define LCC_AHBIX_STAT_AHB_CLK_SHIFT	10
+#define LCC_AHBIX_STAT_AHB_CLK_ON	(1 << LCC_AHBIX_STAT_AHB_CLK_SHIFT)
+
+#define LCC_AHBIX_STAT_AIF_CLK_MASK	0x200
+#define LCC_AHBIX_STAT_AIF_CLK_SHIFT	9
+#define LCC_AHBIX_STAT_AIF_CLK_ON	(1 << LCC_AHBIX_STAT_AIF_CLK_SHIFT)
+
+#define LCC_AHBIX_STAT_FAB2_CLK_MASK	0x40
+#define LCC_AHBIX_STAT_FAB2_CLK_SHIFT	6
+#define LCC_AHBIX_STAT_FAB2_CLK_ON	(1 << LCC_AHBIX_STAT_FAB2_CLK_SHIFT)
+
+#define LCC_AHBIX_STAT_2FAB_CLK_MASK	0x20
+#define LCC_AHBIX_STAT_2FAB_CLK_SHIFT	5
+#define LCC_AHBIX_STAT_2FAB_CLK_ON	(1 << LCC_AHBIX_STAT_2FAB_CLK_SHIFT)
+
+/* LCC MI2S Configuration/Control */
+
+#define LCC_MI2S_NS_REG			0x48
+#define LCC_MI2S_MD_REG			0x4C
+#define LCC_MI2S_STAT_REG		0x50
+
+#define LCC_MI2S_NS_N_VAL_MASK		0xFF000000
+#define LCC_MI2S_NS_N_VAL_SHIFT		24
+
+#define LCC_MI2S_NS_RESET_MASK		0x80000
+#define LCC_MI2S_NS_RESET_SHIFT		19
+#define LCC_MI2S_NS_RESET_ASSERT	(1 << LCC_MI2S_NS_RESET_SHIFT)
+
+#define LCC_MI2S_NS_OSR_INV_MASK	0x40000
+#define LCC_MI2S_NS_OSR_INV_SHIFT	18
+#define LCC_MI2S_NS_OSR_INV_ENABLE	(1 << LCC_MI2S_NS_OSR_INV_SHIFT)
+
+#define LCC_MI2S_NS_OSR_CXC_MASK	0x20000
+#define LCC_MI2S_NS_OSR_CXC_SHIFT	17
+#define LCC_MI2S_NS_OSR_CXC_ENABLE	(1 << LCC_MI2S_NS_OSR_CXC_SHIFT)
+
+#define LCC_MI2S_NS_BIT_INV_MASK	0x10000
+#define LCC_MI2S_NS_BIT_INV_SHIFT	16
+#define LCC_MI2S_NS_BIT_INV_ENABLE	(1 << LCC_MI2S_NS_BIT_INV_SHIFT)
+
+#define LCC_MI2S_NS_BIT_CXC_MASK	0x8000
+#define LCC_MI2S_NS_BIT_CXC_SHIFT	15
+#define LCC_MI2S_NS_BIT_CXC_ENABLE	(1 << LCC_MI2S_NS_BIT_CXC_SHIFT)
+
+#define LCC_MI2S_NS_BIT_SRC_MASK	0x4000
+#define LCC_MI2S_NS_BIT_SRC_SHIFT	14
+#define LCC_MI2S_NS_BIT_SRC_MASTER	(0 << LCC_MI2S_NS_BIT_SRC_SHIFT)
+#define LCC_MI2S_NS_BIT_SRC_SLAVE	(1 << LCC_MI2S_NS_BIT_SRC_SHIFT)
+
+#define LCC_MI2S_NS_BIT_DIV_MASK	0x3C00
+#define LCC_MI2S_NS_BIT_DIV_SHIFT	10
+#define LCC_MI2S_NS_BIT_DIV_BYPASS	(0  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV2	(1  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV3	(2  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV4	(3  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV5	(4  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV6	(5  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV7	(6  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV8	(7  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV9	(8  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV10	(9  << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV11	(10 << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV12	(11 << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV13	(12 << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV14	(13 << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV15	(14 << LCC_MI2S_NS_BIT_DIV_SHIFT)
+#define LCC_MI2S_NS_BIT_DIV_DIV16	(15 << LCC_MI2S_NS_BIT_DIV_SHIFT)
+
+#define LCC_MI2S_NS_MNC_CLK_MASK	0x200
+#define LCC_MI2S_NS_MNC_CLK_SHIFT	9
+#define LCC_MI2S_NS_MNC_CLK_ENABLE	(1 << LCC_MI2S_NS_MNC_CLK_SHIFT)
+
+#define LCC_MI2S_NS_MNC_MASK		0x100
+#define LCC_MI2S_NS_MNC_SHIFT		8
+#define LCC_MI2S_NS_MNC_ENABLE		(1 << LCC_MI2S_NS_MNC_SHIFT)
+
+#define LCC_MI2S_NS_MNC_RESET_MASK	0x80
+#define LCC_MI2S_NS_MNC_RESET_SHIFT	7
+#define LCC_MI2S_NS_MNC_RESET_ASSERT	(1 << LCC_MI2S_NS_MNC_RESET_SHIFT)
+
+#define LCC_MI2S_NS_MNC_MODE_MASK	0x60
+#define LCC_MI2S_NS_MNC_MODE_SHIFT	5
+#define LCC_MI2S_NS_MNC_MODE_BYPASS	(0 << LCC_MI2S_NS_MNC_MODE_SHIFT)
+#define LCC_MI2S_NS_MNC_MODE_SWALLOW	(1 << LCC_MI2S_NS_MNC_MODE_SHIFT)
+#define LCC_MI2S_NS_MNC_MODE_DUAL	(2 << LCC_MI2S_NS_MNC_MODE_SHIFT)
+#define LCC_MI2S_NS_MNC_MODE_SINGLE	(3 << LCC_MI2S_NS_MNC_MODE_SHIFT)
+
+#define LCC_MI2S_NS_PREDIV_MASK		0x18
+#define LCC_MI2S_NS_PREDIV_SHIFT	3
+#define LCC_MI2S_NS_PREDIV_BYPASS	(0 << LCC_MI2S_NS_PREDIV_SHIFT)
+#define LCC_MI2S_NS_PREDIV_DIV2		(1 << LCC_MI2S_NS_PREDIV_SHIFT)
+#define LCC_MI2S_NS_PREDIV_DIV4		(3 << LCC_MI2S_NS_PREDIV_SHIFT)
+
+#define LCC_MI2S_NS_MN_SRC_MASK		0x7
+#define LCC_MI2S_NS_MN_SRC_SHIFT	0
+#define LCC_MI2S_NS_MN_SRC_PXO		(0 << LCC_MI2S_NS_MN_SRC_SHIFT)
+#define LCC_MI2S_NS_MN_SRC_CXO		(1 << LCC_MI2S_NS_MN_SRC_SHIFT)
+#define LCC_MI2S_NS_MN_SRC_LPA		(2 << LCC_MI2S_NS_MN_SRC_SHIFT)
+#define LCC_MI2S_NS_MN_SRC_SEC		(3 << LCC_MI2S_NS_MN_SRC_SHIFT)
+#define LCC_MI2S_NS_MN_SRC_CTEST	(6 << LCC_MI2S_NS_MN_SRC_SHIFT)
+#define LCC_MI2S_NS_MN_SRC_PTEST	(7 << LCC_MI2S_NS_MN_SRC_SHIFT)
+
+#define LCC_MI2S_MD_M_VAL_MASK		0xFF00
+#define LCC_MI2S_MD_M_VAL_SHIFT		8
+
+#define LCC_MI2S_MD_NOT_2D_VAL_MASK	0xFF
+#define LCC_MI2S_MD_NOT_2D_VAL_SHIFT	0
+
+#define LCC_MI2S_STAT_OSR_CLK_MASK	0x2
+#define LCC_MI2S_STAT_OSR_CLK_SHIFT	1
+#define LCC_MI2S_STAT_OSR_CLK_ON	(1 << LCC_MI2S_STAT_OSR_CLK_SHIFT)
+
+#define LCC_MI2S_STAT_BIT_CLK_MASK	0x1
+#define LCC_MI2S_STAT_BIT_CLK_SHIFT	0
+#define LCC_MI2S_STAT_BIT_CLK_ON	(1 << LCC_MI2S_STAT_BIT_CLK_SHIFT)
+
+/* LCC PLL Configuration/Control */
+
+#define LCC_PLL_PCLK_REG		0xC4
+#define LCC_PLL_SCLK_REG		0xC8
+
+#define LCC_PLL_PCLK_RESET_MASK		0x2
+#define LCC_PLL_PCLK_RESET_SHIFT	1
+#define LCC_PLL_PCLK_RESET_ASSERT	(1 << LCC_PLL_PCLK_RESET_SHIFT)
+
+#define LCC_PLL_PCLK_SRC_MASK		0x1
+#define LCC_PLL_PCLK_SRC_SHIFT		0
+#define LCC_PLL_PCLK_SRC_PXO		(0 << LCC_PLL_PCLK_SRC_SHIFT)
+#define LCC_PLL_PCLK_SRC_PRI		(1 << LCC_PLL_PCLK_SRC_SHIFT)
+
+#define LCC_PLL_SCLK_RESET_MASK		0x10
+#define LCC_PLL_SCLK_RESET_SHIFT	4
+#define LCC_PLL_SCLK_RESET_ASSERT	(1 << LCC_PLL_SCLK_RESET_SHIFT)
+
+#define LCC_PLL_SCLK_DIV_MASK		0xC
+#define LCC_PLL_SCLK_DIV_SHIFT		2
+#define LCC_PLL_SCLK_DIV_BYPASS		(0 << LCC_PLL_SCLK_DIV_SHIFT)
+#define LCC_PLL_SCLK_DIV_DIV2		(1 << LCC_PLL_SCLK_DIV_SHIFT)
+#define LCC_PLL_SCLK_DIV_DIV3		(2 << LCC_PLL_SCLK_DIV_SHIFT)
+#define LCC_PLL_SCLK_DIV_DIV4		(3 << LCC_PLL_SCLK_DIV_SHIFT)
+
+#define LCC_PLL_SCLK_XO_MASK		0x2
+#define LCC_PLL_SCLK_XO_SHIFT		1
+#define LCC_PLL_SCLK_XO_PXO		(0 << LCC_PLL_SCLK_XO_SHIFT)
+#define LCC_PLL_SCLK_XO_SEC		(1 << LCC_PLL_SCLK_XO_SHIFT)
+
+#define LCC_PLL_SCLK_MUX_MASK		0x1
+#define LCC_PLL_SCLK_MUX_SHIFT		0
+#define LCC_PLL_SCLK_MUX_PLL1		(0 << LCC_PLL_SCLK_MUX_SHIFT)
+#define LCC_PLL_SCLK_MUX_PLL0		(1 << LCC_PLL_SCLK_MUX_SHIFT)
+
+#endif /* __DRIVERS_CLOCK_IPQ806X_LCC_REG_H__ */
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld b/src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld
new file mode 100644
index 0000000..5f9efac
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/memlayout.ld
@@ -0,0 +1,55 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright 2014 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.
+ */
+
+#include <memlayout.h>
+
+#include <arch/header.ld>
+
+SECTIONS
+{
+	REGION(rpm, 0x00020000,  160K, 8K)
+	SRAM_START(0x2A000000)
+	/* This includes bootblock image, can be reused after bootblock starts */
+/*	UBER_SBL(0x2A000000, 48K) */
+/*	DDR(0x2A000000, 48K) */
+	BOOTBLOCK(0x2A00C000, 24K)
+	OVERLAP_VERSTAGE_ROMSTAGE(0x2A012000, 64K)
+	VBOOT2_WORK(0x2A022000, 16K)
+	PRERAM_CBMEM_CONSOLE(0x2A026000, 32K)
+	TIMESTAMP(0x2A02E000, 1K)
+
+/*	0x2e400..0x3F000  67 KB free */
+
+/* Keep the below area reserved at all times, it is used by various QCA
+   components as shared data
+	QCA_SHARED_RAM(2A03F000, 4K)
+*/
+	STACK(0x2A040000, 16K)
+	PRERAM_CBFS_CACHE(0x2A044000, 93K)
+	TTB_SUBTABLES(0x2A05B800, 2K)
+	TTB(0x2A05C000, 16K)
+	SRAM_END(0x2A060000)
+
+	DRAM_START(0x40000000)
+	RAMSTAGE(0x40640000, 128K)
+	SYMBOL(memlayout_cbmem_top, 0x59F80000)
+	POSTRAM_CBFS_CACHE(0x59F80000, 384K)
+	DMA_COHERENT(0x5A000000, 2M)
+}
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/qup.h b/src/soc/qualcomm/ipq40xx/include/soc/qup.h
new file mode 100644
index 0000000..d0186f5
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/qup.h
@@ -0,0 +1,219 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 - 2015 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef __QUP_H__
+#define __QUP_H__
+
+#include <soc/gsbi.h>
+
+/* QUP block registers */
+#define QUP_CONFIG			0x0
+#define QUP_STATE			0x4
+#define QUP_IO_MODES			0x8
+#define QUP_SW_RESET			0xc
+#define QUP_TIME_OUT			0x10
+#define QUP_TIME_OUT_CURRENT		0x14
+#define QUP_OPERATIONAL			0x18
+#define QUP_ERROR_FLAGS			0x1c
+#define QUP_ERROR_FLAGS_EN		0x20
+#define QUP_TEST_CTRL			0x24
+#define QUP_MX_OUTPUT_COUNT		0x100
+#define QUP_MX_OUTPUT_CNT_CURRENT	0x104
+#define QUP_OUTPUT_DEBUG		0x108
+#define QUP_OUTPUT_FIFO_WORD_CNT	0x10c
+#define QUP_OUTPUT_FIFO			0x110
+#define QUP_MX_WRITE_COUNT		0x150
+#define QUP_WRITE_CNT_CURRENT		0x154
+#define QUP_MX_INPUT_COUNT		0x200
+#define QUP_READ_COUNT			0x208
+#define QUP_MX_READ_CNT_CURRENT		0x20c
+#define QUP_INPUT_DEBUG			0x210
+#define QUP_INPUT_FIFO_WORD_CNT		0x214
+#define QUP_INPUT_FIFO			0x218
+#define QUP_I2C_MASTER_CLK_CTL		0x400
+#define QUP_I2C_MASTER_STATUS		0x404
+
+#define OUTPUT_FIFO_FULL		(1<<6)
+#define INPUT_FIFO_NOT_EMPTY		(1<<5)
+#define OUTPUT_FIFO_NOT_EMPTY		(1<<4)
+#define INPUT_SERVICE_FLAG		(1<<9)
+#define OUTPUT_SERVICE_FLAG		(1<<8)
+#define QUP_OUTPUT_BIT_SHIFT_EN		(1<<16)
+
+#define QUP_MODE_MASK			(0x03)
+#define QUP_OUTPUT_MODE_SHFT		(10)
+#define QUP_INPUT_MODE_SHFT		(12)
+
+#define QUP_FS_DIVIDER_MASK		(0xFF)
+
+#define QUP_MINI_CORE_PROTO_SHFT	(8)
+#define QUP_MINI_CORE_PROTO_MASK	(0x0F)
+
+/* Mini-core states */
+#define QUP_STATE_RESET			0x0
+#define QUP_STATE_RUN			0x1
+#define QUP_STATE_PAUSE			0x3
+#define QUP_STATE_VALID			(1<<2)
+#define QUP_STATE_MASK			0x3
+#define QUP_STATE_VALID_MASK		(1<<2)
+
+/* Tags for output FIFO */
+#define QUP_I2C_1CLK_NOOP_SEQ	0x1	/*MSB 8-bit NOP, LSB 8-bits 1 clk.*/
+#define QUP_I2C_START_SEQ		(0x1 << 8)
+#define QUP_I2C_DATA_SEQ		(0x2 << 8)
+#define QUP_I2C_STOP_SEQ		(0x3 << 8)
+#define QUP_I2C_RECV_SEQ		(0x4 << 8)
+
+/* Tags for input FIFO */
+#define QUP_I2C_MIDATA_SEQ		(0x5 << 8)
+#define QUP_I2C_MISTOP_SEQ		(0x6 << 8)
+#define QUP_I2C_MINACK_SEQ		(0x7 << 8)
+
+#define QUP_I2C_ADDR(x)			((x & 0xFF) << 1)
+#define QUP_I2C_DATA(x)			(x & 0xFF)
+#define QUP_I2C_MI_TAG(x)		(x & 0xFF00)
+#define QUP_I2C_SLAVE_READ		(0x1)
+
+/*Bit vals for I2C_MASTER_CLK_CTL register */
+#define QUP_HS_DIVIDER_SHFT		(8)
+#define QUP_DIVIDER_MIN_VAL		(0x3)
+
+/* Bit masks for I2C_MASTER_STATUS register */
+#define QUP_I2C_INVALID_READ_SEQ	(1 << 25)
+#define QUP_I2C_INVALID_READ_ADDR	(1 << 24)
+#define QUP_I2C_INVALID_TAG		(1 << 23)
+#define QUP_I2C_FAILED_MASK		(0x3 << 6)
+#define QUP_I2C_INVALID_WRITE		(1 << 5)
+#define QUP_I2C_ARB_LOST		(1 << 4)
+#define QUP_I2C_PACKET_NACK		(1 << 3)
+#define QUP_I2C_BUS_ERROR		(1 << 2)
+
+typedef enum {
+	QUP_SUCCESS = 0,
+	QUP_ERR_BAD_PARAM,
+	QUP_ERR_STATE_SET,
+	QUP_ERR_TIMEOUT,
+	QUP_ERR_UNSUPPORTED,
+	QUP_ERR_I2C_FAILED,
+	QUP_ERR_I2C_ARB_LOST,
+	QUP_ERR_I2C_BUS_ERROR,
+	QUP_ERR_I2C_INVALID_SLAVE_ADDR,
+	QUP_ERR_XFER_FAIL,
+	QUP_ERR_I2C_NACK,
+	QUP_ERR_I2C_INVALID_WRITE,
+	QUP_ERR_I2C_INVALID_TAG,
+	QUP_ERR_UNDEFINED,
+} qup_return_t;
+
+typedef enum {
+	QUP_MINICORE_SPI = 1,
+	QUP_MINICORE_I2C_MASTER,
+	QUP_MINICORE_I2C_SLAVE
+} qup_protocol_t;
+
+typedef enum {
+	QUP_MODE_FIFO = 0,
+	QUP_MODE_BLOCK,
+	QUP_MODE_DATAMOVER,
+} qup_mode_t;
+
+typedef struct {
+	qup_protocol_t protocol;
+	unsigned clk_frequency;
+	unsigned src_frequency;
+	qup_mode_t mode;
+	unsigned initialized;
+} qup_config_t;
+
+typedef struct {
+	qup_protocol_t protocol;
+	union {
+		struct {
+			uint8_t addr;
+			uint8_t *data;
+			unsigned data_len;
+		} iic;
+		struct {
+			void *in;
+			void *out;
+			unsigned size;
+		} spi;
+	} p;
+} qup_data_t;
+
+/*
+ * Initialize GSBI QUP block for FIFO I2C transfers.
+ * gsbi_id[IN]: GSBI for which QUP is to be initialized.
+ * config_ptr[IN]: configurations parameters for the QUP.
+ *
+ * return: QUP_SUCCESS, if initialization succeeds.
+ */
+qup_return_t qup_init(gsbi_id_t gsbi_id, const qup_config_t *config_ptr);
+
+/*
+ * Set QUP state to run, pause, reset.
+ * gsbi_id[IN]: GSBI block for which QUP state is to be set.
+ * state[IN]: New state to transition to.
+ *
+ * return: QUP_SUCCESS, if state transition succeeds.
+ */
+qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state);
+
+/*
+ * Reset the status bits set during an i2c transfer.
+ * gsbi_id[IN]: GSBI block for which i2c status bits are to be cleared.
+ *
+ * return: QUP_SUCCESS, if status bits are cleared successfully.
+ */
+qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id);
+
+/*
+ * Send data to the peripheral on the bus.
+ * gsbi_id[IN]: GSBI block for which data is to be sent.
+ * p_tx_obj[IN]: Data to be sent to the slave on the bus.
+ * stop_seq[IN]: When set to non-zero QUP engine sends i2c stop sequnce.
+ *
+ * return: QUP_SUCCESS, when data is sent successfully to the peripheral.
+ */
+qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+			   uint8_t stop_seq);
+
+/*
+ * Receive data from peripheral on the bus.
+ * gsbi_id[IN]: GSBI block from which data is to be received.
+ * p_tx_obj[IN]: length of data to be received, slave address.
+ *      [OUT]: buffer filled with data from slave.
+ *
+ * return: QUP_SUCCESS, when data is received successfully.
+ */
+qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj);
+
+#endif //__QUP_H__
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/soc_services.h b/src/soc/qualcomm/ipq40xx/include/soc/soc_services.h
new file mode 100644
index 0000000..f995968
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/soc_services.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ */
+
+#ifndef __SOC_QUALCOMM_IPQ806X_INCLUDE_SOC_SOC_SERVICES_H__
+#define __SOC_QUALCOMM_IPQ806X_INCLUDE_SOC_SOC_SERVICES_H__
+
+#include <types.h>
+
+extern u8 _memlayout_cbmem_top[];
+
+/* Returns zero on success, nonzero on failure. */
+int initialize_dram(void);
+
+/* Loads and runs TZBSP, switches into user mode. */
+void start_tzbsp(void);
+
+/* A helper function needed to start TZBSP properly. */
+int tz_init_wrapper(int, int, void *);
+
+/* Load RPM code into memory and trigger its execution. */
+void start_rpm(void);
+
+#endif
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/spi.h b/src/soc/qualcomm/ipq40xx/include/soc/spi.h
new file mode 100644
index 0000000..adc5eeb
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/spi.h
@@ -0,0 +1,305 @@
+/*
+ * Register definitions for the IPQ GSBI Controller
+ *
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef _IPQ806X_SPI_H_
+#define _IPQ806X_SPI_H_
+
+#include <spi_flash.h>
+#include <soc/iomap.h>
+
+#define QUP5_BASE	((uint32_t)GSBI_QUP5_BASE)
+#define QUP6_BASE	((uint32_t)GSBI_QUP6_BASE)
+#define QUP7_BASE	((uint32_t)GSBI_QUP7_BASE)
+
+#define GSBI5_QUP5_REG_BASE		(QUP5_BASE + 0x00000000)
+#define GSBI6_QUP6_REG_BASE		(QUP6_BASE + 0x00000000)
+#define GSBI7_QUP7_REG_BASE		(QUP7_BASE + 0x00000000)
+
+#define GSBI5_REG_BASE			((uint32_t)(GSBI5_BASE + 0x00000000))
+#define GSBI6_REG_BASE			((uint32_t)(GSBI6_BASE + 0x00000000))
+#define GSBI7_REG_BASE			((uint32_t)(GSBI7_BASE + 0x00000000))
+
+#define BOOT_SPI_PORT5_BASE		QUP5_BASE
+#define BOOT_SPI_PORT6_BASE		QUP6_BASE
+#define BOOT_SPI_PORT7_BASE		QUP7_BASE
+
+#define GSBI5_SPI_CONFIG_REG		(GSBI5_QUP5_REG_BASE + 0x00000300)
+#define GSBI6_SPI_CONFIG_REG		(GSBI6_QUP6_REG_BASE + 0x00000300)
+#define GSBI7_SPI_CONFIG_REG		(GSBI7_QUP7_REG_BASE + 0x00000300)
+
+#define GSBI5_SPI_IO_CONTROL_REG	(GSBI5_QUP5_REG_BASE + 0x00000304)
+#define GSBI6_SPI_IO_CONTROL_REG	(GSBI6_QUP6_REG_BASE + 0x00000304)
+#define GSBI7_SPI_IO_CONTROL_REG	(GSBI7_QUP7_REG_BASE + 0x00000304)
+
+#define GSBI5_SPI_ERROR_FLAGS_REG	(GSBI5_QUP5_REG_BASE + 0x00000308)
+#define GSBI6_SPI_ERROR_FLAGS_REG	(GSBI6_QUP6_REG_BASE + 0x00000308)
+#define GSBI7_SPI_ERROR_FLAGS_REG	(GSBI7_QUP7_REG_BASE + 0x00000308)
+
+#define GSBI5_SPI_ERROR_FLAGS_EN_REG	(GSBI5_QUP5_REG_BASE + 0x0000030c)
+#define GSBI6_SPI_ERROR_FLAGS_EN_REG	(GSBI6_QUP6_REG_BASE + 0x0000030c)
+#define GSBI7_SPI_ERROR_FLAGS_EN_REG	(GSBI7_QUP7_REG_BASE + 0x0000030c)
+
+#define GSBI5_GSBI_CTRL_REG_REG		(GSBI5_REG_BASE + 0x00000000)
+#define GSBI6_GSBI_CTRL_REG_REG		(GSBI6_REG_BASE + 0x00000000)
+#define GSBI7_GSBI_CTRL_REG_REG		(GSBI7_REG_BASE + 0x00000000)
+
+#define GSBI5_QUP_CONFIG_REG		(GSBI5_QUP5_REG_BASE + 0x00000000)
+#define GSBI6_QUP_CONFIG_REG		(GSBI6_QUP6_REG_BASE + 0x00000000)
+#define GSBI7_QUP_CONFIG_REG		(GSBI7_QUP7_REG_BASE + 0x00000000)
+
+#define GSBI5_QUP_ERROR_FLAGS_REG	(GSBI5_QUP5_REG_BASE      + 0x0000001c)
+#define GSBI6_QUP_ERROR_FLAGS_REG	(GSBI6_QUP6_REG_BASE      + 0x0000001c)
+#define GSBI7_QUP_ERROR_FLAGS_REG	(GSBI7_QUP7_REG_BASE      + 0x0000001c)
+
+#define GSBI5_QUP_ERROR_FLAGS_EN_REG	(GSBI5_QUP5_REG_BASE + 0x00000020)
+#define GSBI6_QUP_ERROR_FLAGS_EN_REG	(GSBI6_QUP6_REG_BASE + 0x00000020)
+#define GSBI7_QUP_ERROR_FLAGS_EN_REG	(GSBI7_QUP7_REG_BASE + 0x00000020)
+
+#define GSBI5_QUP_OPERATIONAL_REG	(GSBI5_QUP5_REG_BASE + 0x00000018)
+#define GSBI6_QUP_OPERATIONAL_REG	(GSBI6_QUP6_REG_BASE + 0x00000018)
+#define GSBI7_QUP_OPERATIONAL_REG	(GSBI7_QUP7_REG_BASE + 0x00000018)
+
+#define GSBI5_QUP_IO_MODES_REG		(GSBI5_QUP5_REG_BASE + 0x00000008)
+#define GSBI6_QUP_IO_MODES_REG		(GSBI6_QUP6_REG_BASE + 0x00000008)
+#define GSBI7_QUP_IO_MODES_REG		(GSBI7_QUP7_REG_BASE + 0x00000008)
+
+#define GSBI5_QUP_STATE_REG		(GSBI5_QUP5_REG_BASE + 0x00000004)
+#define GSBI6_QUP_STATE_REG		(GSBI6_QUP6_REG_BASE + 0x00000004)
+#define GSBI7_QUP_STATE_REG		(GSBI7_QUP7_REG_BASE + 0x00000004)
+
+#define GSBI5_QUP_OUT_FIFO_WORD_CNT_REG	(GSBI5_QUP5_REG_BASE + 0x0000010c)
+#define GSBI6_QUP_OUT_FIFO_WORD_CNT_REG	(GSBI6_QUP6_REG_BASE + 0x0000010c)
+#define GSBI7_QUP_OUT_FIFO_WORD_CNT_REG	(GSBI7_QUP7_REG_BASE + 0x0000010c)
+
+#define GSBI5_QUP_IN_FIFO_WORD_CNT_REG	(GSBI5_QUP5_REG_BASE + 0x00000214)
+#define GSBI6_QUP_IN_FIFO_WORD_CNT_REG	(GSBI6_QUP6_REG_BASE + 0x00000214)
+#define GSBI7_QUP_IN_FIFO_WORD_CNT_REG	(GSBI7_QUP7_REG_BASE + 0x00000214)
+
+#define GSBI5_QUP_INPUT_FIFOc_REG(c) \
+		(GSBI5_QUP5_REG_BASE + 0x00000218 + 4 * (c))
+#define GSBI6_QUP_INPUT_FIFOc_REG(c) \
+		(GSBI6_QUP6_REG_BASE + 0x00000218 + 4 * (c))
+#define GSBI7_QUP_INPUT_FIFOc_REG(c) \
+		(GSBI7_QUP7_REG_BASE + 0x00000218 + 4 * (c))
+
+#define GSBI5_QUP_OUTPUT_FIFOc_REG(c) \
+		(GSBI5_QUP5_REG_BASE + 0x00000110 + 4 * (c))
+#define GSBI6_QUP_OUTPUT_FIFOc_REG(c) \
+		(GSBI6_QUP6_REG_BASE + 0x00000110 + 4 * (c))
+#define GSBI7_QUP_OUTPUT_FIFOc_REG(c) \
+		(GSBI7_QUP7_REG_BASE + 0x00000110 + 4 * (c))
+
+#define GSBI5_QUP_MX_INPUT_COUNT_REG	(GSBI5_QUP5_REG_BASE + 0x00000200)
+#define GSBI6_QUP_MX_INPUT_COUNT_REG	(GSBI6_QUP6_REG_BASE + 0x00000200)
+#define GSBI7_QUP_MX_INPUT_COUNT_REG	(GSBI7_QUP7_REG_BASE + 0x00000200)
+
+#define GSBI5_QUP_MX_OUTPUT_COUNT_REG	(GSBI5_QUP5_REG_BASE + 0x00000100)
+#define GSBI6_QUP_MX_OUTPUT_COUNT_REG	(GSBI6_QUP6_REG_BASE + 0x00000100)
+#define GSBI7_QUP_MX_OUTPUT_COUNT_REG	(GSBI7_QUP7_REG_BASE + 0x00000100)
+
+#define GSBI5_QUP_SW_RESET_REG		(GSBI5_QUP5_REG_BASE + 0x0000000c)
+#define GSBI6_QUP_SW_RESET_REG		(GSBI6_QUP6_REG_BASE + 0x0000000c)
+#define GSBI7_QUP_SW_RESET_REG		(GSBI7_QUP7_REG_BASE + 0x0000000c)
+
+#define CLK_CTL_REG_BASE		0x00900000
+#define GSBIn_RESET_REG(n) \
+		(CLK_CTL_REG_BASE      + 0x000029dc + 32 * ((n)-1))
+
+#define SFAB_AHB_S3_FCLK_CTL_REG \
+		(CLK_CTL_REG_BASE      + 0x0000216c)
+#define CFPB_CLK_NS_REG \
+		(CLK_CTL_REG_BASE      + 0x0000264c)
+#define SFAB_CFPB_S_HCLK_CTL_REG \
+		(CLK_CTL_REG_BASE      + 0x000026c0)
+#define CFPB_SPLITTER_HCLK_CTL_REG \
+		(CLK_CTL_REG_BASE      + 0x000026e0)
+#define CFPB0_HCLK_CTL_REG \
+		(CLK_CTL_REG_BASE      + 0x00002650)
+#define CFPB2_HCLK_CTL_REG \
+		(CLK_CTL_REG_BASE      + 0x00002658)
+#define GSBIn_HCLK_CTL_REG(n) \
+		(CLK_CTL_REG_BASE      + 0x000029c0 + 32 * ((n)-1))
+#define GSBIn_QUP_APPS_NS_REG(n) \
+	(CLK_CTL_REG_BASE      + 0x000029cc + 32 * ((n)-1))
+#define GSBIn_QUP_APPS_MD_REG(n) \
+		(CLK_CTL_REG_BASE      + 0x000029c8 + 32 * ((n)-1))
+#define CLK_HALT_CFPB_STATEB_REG \
+		(CLK_CTL_REG_BASE      + 0x00002fd0)
+
+#define GSBI5_HCLK				23
+#define GSBI6_HCLK				19
+#define GSBI7_HCLK				15
+#define GSBI5_QUP_APPS_CLK			20
+#define GSBI6_QUP_APPS_CLK			16
+#define GSBI7_QUP_APPS_CLK			12
+#define GSBI_CLK_BRANCH_ENA_MSK			(1 << 4)
+#define GSBI_CLK_BRANCH_ENA			(1 << 4)
+#define GSBI_CLK_BRANCH_DIS			(0 << 4)
+#define QUP_CLK_BRANCH_ENA_MSK			(1 << 9)
+#define QUP_CLK_BRANCH_ENA			(1 << 9)
+#define QUP_CLK_BRANCH_DIS			(0 << 9)
+#define CLK_ROOT_ENA_MSK			(1 << 11)
+#define CLK_ROOT_ENA				(1 << 11)
+#define CLK_ROOT_DIS				(0 << 11)
+
+#define QUP_STATE_VALID_BIT			2
+#define QUP_STATE_VALID				1
+#define QUP_STATE_MASK				0x3
+#define QUP_CONFIG_MINI_CORE_MSK		(0x0F << 8)
+#define QUP_CONFIG_MINI_CORE_SPI		(1 << 8)
+#define SPI_QUP_CONF_INPUT_MSK			(1 << 7)
+#define SPI_QUP_CONF_INPUT_ENA			(0 << 7)
+#define SPI_QUP_CONF_NO_INPUT			(1 << 7)
+#define SPI_QUP_CONF_OUTPUT_MSK			(1 << 6)
+#define SPI_QUP_CONF_OUTPUT_ENA			(0 << 6)
+#define SPI_QUP_CONF_NO_OUTPUT			(1 << 6)
+#define SPI_QUP_CONF_OUTPUT_ENA			(0 << 6)
+#define QUP_STATE_RESET_STATE			0x0
+#define QUP_STATE_RUN_STATE			0x1
+#define QUP_STATE_PAUSE_STATE			0x3
+#define SPI_BIT_WORD_MSK			0x1F
+#define SPI_8_BIT_WORD				0x07
+#define PROTOCOL_CODE_MSK			(0x07 << 4)
+#define PROTOCOL_CODE_SPI			(0x03 << 4)
+#define LOOP_BACK_MSK				(1 << 8)
+#define NO_LOOP_BACK				(0 << 8)
+#define SLAVE_OPERATION_MSK			(1 << 5)
+#define SLAVE_OPERATION				(0 << 5)
+#define CLK_ALWAYS_ON				(0 << 9)
+#define MX_CS_MODE				(0 << 8)
+#define NO_TRI_STATE				(1 << 0)
+#define OUTPUT_BIT_SHIFT_MSK			(1 << 16)
+#define OUTPUT_BIT_SHIFT_EN			(1 << 16)
+#define INPUT_BLOCK_MODE_MSK			(0x03 << 12)
+#define INPUT_BLOCK_MODE			(0x01 << 12)
+#define OUTPUT_BLOCK_MODE_MSK			(0x03 << 10)
+#define OUTPUT_BLOCK_MODE			(0x01 << 10)
+#define GSBI1_RESET				(1 << 0)
+#define GSBI1_RESET_MSK				0x1
+
+#define GSBI_M_VAL_SHFT				16
+#define GSBIn_M_VAL_MSK				(0xFF << GSBI_M_VAL_SHFT)
+#define GSBI_N_VAL_SHFT				16
+#define GSBIn_N_VAL_MSK				(0xFF << GSBI_N_VAL_SHFT)
+#define GSBI_D_VAL_SHFT				0
+#define GSBIn_D_VAL_MSK				(0xFF << GSBI_D_VAL_SHFT)
+#define MNCNTR_RST_MSK				(1 << 7)
+#define MNCNTR_RST_ENA				(1 << 7)
+#define MNCNTR_RST_DIS				(0 << 7)
+#define MNCNTR_MSK				(1 << 8)
+#define MNCNTR_EN				(1 << 8)
+#define MNCNTR_DIS				(0 << 8)
+#define MNCNTR_MODE_MSK				(0x3 << 5)
+#define MNCNTR_MODE_BYPASS			(0 << 5)
+#define MNCNTR_MODE_DUAL_EDGE			(0x2 << 5)
+#define GSBI_PRE_DIV_SEL_SHFT			3
+#define GSBIn_PRE_DIV_SEL_MSK			(0x3 << GSBI_PRE_DIV_SEL_SHFT)
+#define GSBIn_PLL_SRC_MSK			(0x03 << 0)
+#define GSBIn_PLL_SRC_PXO			(0 << 0)
+#define GSBIn_PLL_SRC_PLL8			(0x3 << 0)
+
+#define SPI_INPUT_FIRST_MODE			(1 << 9)
+#define SPI_IO_CONTROL_CLOCK_IDLE_HIGH		(1 << 10)
+#define QUP_DATA_AVAILABLE_FOR_READ		(1 << 5)
+#define QUP_OUTPUT_FIFO_NOT_EMPTY		(1 << 4)
+#define OUTPUT_SERVICE_FLAG			(1 << 8)
+#define INPUT_SERVICE_FLAG			(1 << 9)
+#define QUP_OUTPUT_FIFO_FULL			(1 << 6)
+#define QUP_INPUT_FIFO_NOT_EMPTY		(1 << 5)
+#define SPI_INPUT_BLOCK_SIZE			4
+#define SPI_OUTPUT_BLOCK_SIZE			4
+#define GSBI5_SPI_CLK				21
+#define GSBI5_SPI_MISO				19
+#define GSBI5_SPI_MOSI				18
+#define GSBI5_SPI_CS_0				20
+#define GSBI5_SPI_CS_1				61
+#define GSBI5_SPI_CS_2				62
+#define GSBI5_SPI_CS_3				2
+#define GSBI6_SPI_CLK				30
+#define GSBI6_SPI_CS_0				29
+#define GSBI6_SPI_MISO				28
+#define GSBI6_SPI_MOSI				27
+#define GSBI7_SPI_CLK				9
+#define GSBI7_SPI_CS_0				8
+#define GSBI7_SPI_MISO				7
+#define GSBI7_SPI_MOSI				6
+
+#define MSM_GSBI_MAX_FREQ			51200000
+
+#define SPI_RESET_STATE				0
+#define SPI_RUN_STATE				1
+#define SPI_PAUSE_STATE				3
+#define SPI_CORE_RESET				0
+#define SPI_CORE_RUNNING			1
+#define GSBI_SPI_MODE_0				0
+#define GSBI_SPI_MODE_1				1
+#define GSBI_SPI_MODE_2				2
+#define GSBI_SPI_MODE_3				3
+#define GSBI5_SPI				0
+#define GSBI6_SPI				1
+#define GSBI7_SPI				2
+
+struct gsbi_spi {
+	unsigned int     spi_config;
+	unsigned int     io_control;
+	unsigned int     error_flags;
+	unsigned int     error_flags_en;
+	unsigned int     gsbi_ctrl;
+	unsigned int     qup_config;
+	unsigned int     qup_error_flags;
+	unsigned int     qup_error_flags_en;
+	unsigned int     qup_operational;
+	unsigned int     qup_io_modes;
+	unsigned int     qup_state;
+	unsigned int     qup_input_fifo;
+	unsigned int     qup_output_fifo;
+	unsigned int     qup_mx_input_count;
+	unsigned int     qup_mx_output_count;
+	unsigned int     qup_sw_reset;
+	unsigned int     qup_ns_reg;
+	unsigned int     qup_md_reg;
+};
+
+struct ipq_spi_slave {
+	struct spi_slave slave;
+	const struct gsbi_spi *regs;
+	unsigned int mode;
+	unsigned int initialized;
+	unsigned long freq;
+	int allocated;
+};
+
+static inline struct ipq_spi_slave *to_ipq_spi(struct spi_slave *slave)
+{
+	return container_of(slave, struct ipq_spi_slave, slave);
+}
+
+#endif /* _IPQ_SPI_H_ */
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/usb.h b/src/soc/qualcomm/ipq40xx/include/soc/usb.h
new file mode 100644
index 0000000..7bd6656
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/usb.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ */
+
+#ifndef _IPQ806X_USB_H_
+#define _IPQ806X_USB_H_
+
+void setup_usb_host1(void);
+void setup_usb_host2(void);
+
+#endif /* _IPQ806X_USB_H_ */
diff --git a/src/soc/qualcomm/ipq40xx/include/soc/usbl_if.h b/src/soc/qualcomm/ipq40xx/include/soc/usbl_if.h
new file mode 100644
index 0000000..5ca784d
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/include/soc/usbl_if.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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.
+ */
+
+#ifndef __SOC_QUALCOMM_IPQ806X_INCLUDE_SOC_USBL_IF_H__
+#define __SOC_QUALCOMM_IPQ806X_INCLUDE_SOC_USBL_IF_H__
+
+#include <types.h>
+
+typedef struct {
+	u32	time_stamp;
+	char	msg[27];
+	u8	type;
+
+} boot_log_entry;
+
+typedef struct {
+	u32		num_log_entries;
+	boot_log_entry	*log;
+} sbl_ro_info;
+
+typedef struct {
+	u32		start_magic;
+	u32		num;
+	char		*version;
+	sbl_ro_info	info[2];
+	/*
+	 * The two addresses below can be used for communicating with the RPM
+	 * (passing it the starting address of the program to execute and
+	 * triggering the jump to the program). Presently these addresses are
+	 * hardcodeded in firmware source code.
+	 */
+	u32		*rpm_jump_trigger;
+	u32		*rpm_entry_addr_ptr;
+	u32		end_magic;
+} uber_sbl_shared_info;
+
+#define UBER_SBL_SHARED_INFO_START_MAGIC	0x5552504d // URPM
+#define UBER_SBL_SHARED_INFO_END_MAGIC		0x554b5254 // UKRT
+
+extern uber_sbl_shared_info *maskrom_param;
+
+#endif
diff --git a/src/soc/qualcomm/ipq40xx/lcc.c b/src/soc/qualcomm/ipq40xx/lcc.c
new file mode 100644
index 0000000..d577487
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/lcc.c
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <stdlib.h>
+#include <stdint.h>
+#include <delay.h>
+#include <console/console.h>
+#include <soc/clock.h>
+#include <soc/lcc-reg.h>
+#include <arch/io.h>
+
+typedef struct {
+	void *gcc_apcs_regs;
+	void *lcc_pll0_regs;
+	void *lcc_ahbix_regs;
+	void *lcc_mi2s_regs;
+	void *lcc_pll_regs;
+} Ipq806xLccClocks;
+
+typedef struct __attribute__((packed)) {
+	uint32_t apcs;
+} Ipq806xLccGccRegs;
+
+typedef struct __attribute__((packed)) {
+	uint32_t mode;
+	uint32_t l_val;
+	uint32_t m_val;
+	uint32_t n_val;
+	uint32_t UNUSED;
+	uint32_t config;
+	uint32_t status;
+} Ipq806xLccPll0Regs;
+
+typedef struct __attribute__((packed)) {
+	uint32_t ns;
+	uint32_t md;
+	uint32_t UNUSED;
+	uint32_t status;
+} Ipq806xLccAhbixRegs;
+
+typedef struct __attribute__((packed)) {
+	uint32_t ns;
+	uint32_t md;
+	uint32_t status;
+} Ipq806xLccMi2sRegs;
+
+typedef struct __attribute__((packed)) {
+	uint32_t pri;
+	uint32_t sec;
+} Ipq806xLccPllRegs;
+
+struct lcc_freq_tbl {
+	unsigned freq;
+	unsigned pd;
+	unsigned m;
+	unsigned n;
+	unsigned d;
+};
+
+static const struct lcc_freq_tbl lcc_mi2s_freq_tbl[] = {
+	{  1024000, 4,  1,  96, 8 },
+	{  1411200, 4,  2, 139, 8 },
+	{  1536000, 4,  1,  64, 8 },
+	{  2048000, 4,  1,  48, 8 },
+	{  2116800, 4,  2,  93, 8 },
+	{  2304000, 4,  2,  85, 8 },
+	{  2822400, 4,  6, 209, 8 },
+	{  3072000, 4,  1,  32, 8 },
+	{  3175200, 4,  1,  31, 8 },
+	{  4096000, 4,  1,  24, 8 },
+	{  4233600, 4,  9, 209, 8 },
+	{  4608000, 4,  3,  64, 8 },
+	{  5644800, 4, 12, 209, 8 },
+	{  6144000, 4,  1,  16, 8 },
+	{  6350400, 4,  2,  31, 8 },
+	{  8192000, 4,  1,  12, 8 },
+	{  8467200, 4, 18, 209, 8 },
+	{  9216000, 4,  3,  32, 8 },
+	{ 11289600, 4, 24, 209, 8 },
+	{ 12288000, 4,  1,   8, 8 },
+	{ 12700800, 4, 27, 209, 8 },
+	{ 13824000, 4,  9,  64, 8 },
+	{ 16384000, 4,  1,   6, 8 },
+	{ 16934400, 4, 41, 238, 8 },
+	{ 18432000, 4,  3,  16, 8 },
+	{ 22579200, 2, 24, 209, 8 },
+	{ 24576000, 4,  1,   4, 8 },
+	{ 27648000, 4,  9,  32, 8 },
+	{ 33868800, 4, 41, 119, 8 },
+	{ 36864000, 4,  3,   8, 8 },
+	{ 45158400, 1, 24, 209, 8 },
+	{ 49152000, 4,  1,   2, 8 },
+	{ 50803200, 1, 27, 209, 8 },
+	{ }
+};
+
+static int lcc_init_enable_pll0(Ipq806xLccClocks *bus)
+{
+	Ipq806xLccGccRegs *gcc_regs = bus->gcc_apcs_regs;
+	Ipq806xLccPll0Regs *pll0_regs = bus->lcc_pll0_regs;
+	Ipq806xLccPllRegs *pll_regs = bus->lcc_pll_regs;
+	uint32_t regval;
+
+	regval = 0;
+	regval = 15 << LCC_PLL0_L_SHIFT & LCC_PLL0_L_MASK;
+	write32(&pll0_regs->l_val, regval);
+
+	regval = 0;
+	regval = 145 << LCC_PLL0_M_SHIFT & LCC_PLL0_M_MASK;
+	write32(&pll0_regs->m_val, regval);
+
+	regval = 0;
+	regval = 199 << LCC_PLL0_N_SHIFT & LCC_PLL0_N_MASK;
+	write32(&pll0_regs->n_val, regval);
+
+	regval = 0;
+	regval |= LCC_PLL0_CFG_LV_MAIN_ENABLE;
+	regval |= LCC_PLL0_CFG_FRAC_ENABLE;
+	write32(&pll0_regs->config, regval);
+
+	regval = 0;
+	regval |= LCC_PLL_PCLK_SRC_PRI;
+	write32(&pll_regs->pri, regval);
+
+	regval = 0;
+	regval |= 1 << LCC_PLL0_MODE_BIAS_CNT_SHIFT &
+			LCC_PLL0_MODE_BIAS_CNT_MASK;
+	regval |= 8 << LCC_PLL0_MODE_LOCK_CNT_SHIFT &
+			LCC_PLL0_MODE_LOCK_CNT_MASK;
+	write32(&pll0_regs->mode, regval);
+
+	regval = read32(&gcc_regs->apcs);
+	regval |= GCC_PLL_APCS_PLL4_ENABLE;
+	write32(&gcc_regs->apcs, regval);
+
+	regval = read32(&pll0_regs->mode);
+	regval |= LCC_PLL0_MODE_FSM_VOTE_ENABLE;
+	write32(&pll0_regs->mode, regval);
+
+	mdelay(1);
+
+	regval = read32(&pll0_regs->status);
+	if (regval & LCC_PLL0_STAT_ACTIVE_MASK)
+		return 0;
+
+	printk(BIOS_ERR, "%s: error enabling PLL4 clock\n", __func__);
+	return 1;
+}
+
+static int lcc_init_enable_ahbix(Ipq806xLccClocks *bus)
+{
+	Ipq806xLccAhbixRegs *ahbix_regs = bus->lcc_ahbix_regs;
+	uint32_t regval;
+
+	regval = 0;
+	regval |= 1 << LCC_AHBIX_MD_M_VAL_SHIFT & LCC_AHBIX_MD_M_VAL_MASK;
+	regval |= 252 << LCC_AHBIX_MD_NOT_2D_VAL_SHIFT &
+			LCC_AHBIX_MD_NOT_2D_VAL_MASK;
+	write32(&ahbix_regs->md, regval);
+
+	regval = 0;
+	regval |= 253 << LCC_AHBIX_NS_N_VAL_SHIFT & LCC_AHBIX_NS_N_VAL_MASK;
+	regval |= LCC_AHBIX_NS_CRC_ENABLE;
+	regval |= LCC_AHBIX_NS_GFM_SEL_MNC;
+	regval |= LCC_AHBIX_NS_MNC_CLK_ENABLE;
+	regval |= LCC_AHBIX_NS_MNC_ENABLE;
+	regval |= LCC_AHBIX_NS_MNC_MODE_DUAL;
+	regval |= LCC_AHBIX_NS_PREDIV_BYPASS;
+	regval |= LCC_AHBIX_NS_MN_SRC_LPA;
+	write32(&ahbix_regs->ns, regval);
+
+	mdelay(1);
+
+	regval = read32(&ahbix_regs->status);
+	if (regval & LCC_AHBIX_STAT_AIF_CLK_MASK)
+		return 0;
+
+	printk(BIOS_ERR, "%s: error enabling AHBIX clock\n", __func__);
+	return 1;
+}
+
+static int lcc_init_mi2s(Ipq806xLccClocks *bus, unsigned freq)
+{
+	Ipq806xLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
+	uint32_t regval;
+	uint8_t pd, m, n, d;
+	unsigned i;
+
+	i = 0;
+	while (lcc_mi2s_freq_tbl[i].freq != 0) {
+		if (lcc_mi2s_freq_tbl[i].freq == freq)
+			break;
+		++i;
+	}
+	if (lcc_mi2s_freq_tbl[i].freq == 0) {
+		printk(BIOS_ERR, "%s: invalid frequency given: %u\n",
+		       __func__, freq);
+		return 1;
+	}
+
+	switch (lcc_mi2s_freq_tbl[i].pd) {
+	case 1:
+		pd = LCC_MI2S_NS_PREDIV_BYPASS;
+		break;
+	case 2:
+		pd = LCC_MI2S_NS_PREDIV_DIV2;
+		break;
+	case 4:
+		pd = LCC_MI2S_NS_PREDIV_DIV4;
+		break;
+	default:
+		printk(BIOS_ERR, "%s: invalid prediv found: %u\n", __func__,
+				lcc_mi2s_freq_tbl[i].pd);
+		return 1;
+	}
+
+	m = lcc_mi2s_freq_tbl[i].m;
+	n = ~(lcc_mi2s_freq_tbl[i].n - m);
+	d = ~(lcc_mi2s_freq_tbl[i].d * 2);
+
+	regval = 0;
+	regval |= m << LCC_MI2S_MD_M_VAL_SHIFT & LCC_MI2S_MD_M_VAL_MASK;
+	regval |= d << LCC_MI2S_MD_NOT_2D_VAL_SHIFT &
+			LCC_MI2S_MD_NOT_2D_VAL_MASK;
+	write32(&mi2s_regs->md, regval);
+
+	regval = 0;
+	regval |= n << LCC_MI2S_NS_N_VAL_SHIFT & LCC_MI2S_NS_N_VAL_MASK;
+	regval |= LCC_MI2S_NS_BIT_DIV_DIV4;
+	regval |= LCC_MI2S_NS_MNC_CLK_ENABLE;
+	regval |= LCC_MI2S_NS_MNC_ENABLE;
+	regval |= LCC_MI2S_NS_MNC_MODE_DUAL;
+	regval |= pd;
+	regval |= LCC_MI2S_NS_MN_SRC_LPA;
+	write32(&mi2s_regs->ns, regval);
+
+	return 0;
+}
+
+static int lcc_enable_mi2s(Ipq806xLccClocks *bus)
+{
+	Ipq806xLccMi2sRegs *mi2s_regs = bus->lcc_mi2s_regs;
+	uint32_t regval;
+
+	regval = read32(&mi2s_regs->ns);
+	regval |= LCC_MI2S_NS_OSR_CXC_ENABLE;
+	regval |= LCC_MI2S_NS_BIT_CXC_ENABLE;
+	write32(&mi2s_regs->ns, regval);
+
+	udelay(10);
+
+	regval = read32(&mi2s_regs->status);
+	if (regval & LCC_MI2S_STAT_OSR_CLK_MASK)
+		if (regval & LCC_MI2S_STAT_BIT_CLK_MASK)
+			return 0;
+
+	printk(BIOS_ERR, "%s: error enabling MI2S clocks: %u\n",
+	       __func__, regval);
+	return 1;
+}
+
+int audio_clock_config(unsigned frequency)
+{
+	Ipq806xLccClocks *bus = malloc(sizeof(*bus));
+
+	if (!bus) {
+		printk(BIOS_ERR, "%s: failed to allocate bus structure\n",
+		       __func__);
+		return 1;
+	}
+
+	bus->gcc_apcs_regs = (void *)(MSM_GCC_BASE + GCC_PLL_APCS_REG);
+	bus->lcc_pll0_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL0_MODE_REG);
+	bus->lcc_ahbix_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_AHBIX_NS_REG);
+	bus->lcc_mi2s_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_MI2S_NS_REG);
+	bus->lcc_pll_regs = (void *)(MSM_LPASS_LCC_BASE + LCC_PLL_PCLK_REG);
+
+
+	if (lcc_init_enable_pll0(bus))
+		return 1;
+	if (lcc_init_enable_ahbix(bus))
+		return 1;
+	if (lcc_init_mi2s(bus, frequency))
+		return 1;
+
+	if (lcc_enable_mi2s(bus))
+		return 1;
+
+	return 0;
+}
diff --git a/src/soc/qualcomm/ipq40xx/mbn_header.h b/src/soc/qualcomm/ipq40xx/mbn_header.h
new file mode 100644
index 0000000..a58242b
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/mbn_header.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ */
+
+#ifndef __SOC_QUALCOMM_IPQ806X_MBN_HEADER_H__
+#define __SOC_QUALCOMM_IPQ806X_MBN_HEADER_H__
+
+#include <types.h>
+
+/* Qualcomm firmware blob header gleaned from util/ipqheader/ipqheader.py */
+
+struct mbn_header {
+	u32	mbn_type;
+	u32	mbn_version;
+	u32	mbn_source;
+	u32	mbn_destination;
+	u32	mbn_total_size;
+	u32	mbn_padding[5];
+};
+
+#endif
diff --git a/src/soc/qualcomm/ipq40xx/qup.c b/src/soc/qualcomm/ipq40xx/qup.c
new file mode 100644
index 0000000..c876d30
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/qup.c
@@ -0,0 +1,480 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 - 2015 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <arch/io.h>
+#include <console/console.h>
+#include <delay.h>
+#include <soc/iomap.h>
+#include <stdlib.h>
+#include <soc/qup.h>
+
+#define TIMEOUT_CNT	100000
+
+//TODO: refactor the following array to iomap driver.
+static unsigned gsbi_qup_base[] = {
+	(unsigned)GSBI_QUP1_BASE,
+	(unsigned)GSBI_QUP2_BASE,
+	(unsigned)GSBI_QUP3_BASE,
+	(unsigned)GSBI_QUP4_BASE,
+	(unsigned)GSBI_QUP5_BASE,
+	(unsigned)GSBI_QUP6_BASE,
+	(unsigned)GSBI_QUP7_BASE,
+};
+
+#define QUP_ADDR(gsbi_num, reg)	((void *)((gsbi_qup_base[gsbi_num-1]) + (reg)))
+
+static qup_return_t qup_i2c_master_status(gsbi_id_t gsbi_id)
+{
+	uint32_t reg_val = read32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS));
+
+	if (read32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS)))
+		return QUP_ERR_XFER_FAIL;
+	if (reg_val & QUP_I2C_INVALID_READ_ADDR)
+		return QUP_ERR_I2C_INVALID_SLAVE_ADDR;
+	if (reg_val & QUP_I2C_FAILED_MASK)
+		return QUP_ERR_I2C_FAILED;
+	if (reg_val & QUP_I2C_ARB_LOST)
+		return QUP_ERR_I2C_ARB_LOST;
+	if (reg_val & QUP_I2C_BUS_ERROR)
+		return QUP_ERR_I2C_BUS_ERROR;
+	if (reg_val & QUP_I2C_INVALID_WRITE)
+		return QUP_ERR_I2C_INVALID_WRITE;
+	if (reg_val & QUP_I2C_PACKET_NACK)
+		return QUP_ERR_I2C_NACK;
+	if (reg_val & QUP_I2C_INVALID_TAG)
+		return QUP_ERR_I2C_INVALID_TAG;
+
+	return QUP_SUCCESS;
+}
+
+static int check_bit_state(uint32_t *reg, int wait_for)
+{
+	unsigned int count = TIMEOUT_CNT;
+
+	while ((read32(reg) & (QUP_STATE_VALID_MASK | QUP_STATE_MASK)) !=
+			(QUP_STATE_VALID | wait_for)) {
+		if (count == 0)
+			return QUP_ERR_TIMEOUT;
+		count--;
+		udelay(1);
+	}
+
+	return QUP_SUCCESS;
+}
+
+/*
+ * Check whether GSBIn_QUP State is valid
+ */
+static qup_return_t qup_wait_for_state(gsbi_id_t gsbi_id, unsigned wait_for)
+{
+	return check_bit_state(QUP_ADDR(gsbi_id, QUP_STATE), wait_for);
+}
+
+qup_return_t qup_reset_i2c_master_status(gsbi_id_t gsbi_id)
+{
+	/*
+	 * Writing a one clears the status bits.
+	 * Bit31-25, Bit1 and Bit0 are reserved.
+	 */
+	//TODO: Define each status bit. OR all status bits in a single macro.
+	write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_STATUS), 0x3FFFFFC);
+	return QUP_SUCCESS;
+}
+
+static qup_return_t qup_reset_master_status(gsbi_id_t gsbi_id)
+{
+	write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS), 0x7C);
+	write32(QUP_ADDR(gsbi_id, QUP_ERROR_FLAGS_EN), 0x7C);
+	qup_reset_i2c_master_status(gsbi_id);
+	return QUP_SUCCESS;
+}
+
+static qup_return_t qup_fifo_wait_for(gsbi_id_t gsbi_id, uint32_t status)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	unsigned int count = TIMEOUT_CNT;
+
+	while (!(read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status)) {
+		ret = qup_i2c_master_status(gsbi_id);
+		if (ret)
+			return ret;
+		if (count == 0)
+			return QUP_ERR_TIMEOUT;
+		count--;
+	}
+
+	return QUP_SUCCESS;
+}
+
+static qup_return_t qup_fifo_wait_while(gsbi_id_t gsbi_id, uint32_t status)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	unsigned int count = TIMEOUT_CNT;
+
+	while (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) & status) {
+		ret = qup_i2c_master_status(gsbi_id);
+		if (ret)
+			return ret;
+		if (count == 0)
+			return QUP_ERR_TIMEOUT;
+		count--;
+	}
+
+	return QUP_SUCCESS;
+}
+
+static qup_return_t qup_i2c_write_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+				       uint8_t stop_seq)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	uint8_t addr = p_tx_obj->p.iic.addr;
+	uint8_t *data_ptr = p_tx_obj->p.iic.data;
+	unsigned data_len = p_tx_obj->p.iic.data_len;
+	unsigned idx = 0;
+
+	qup_reset_master_status(gsbi_id);
+	qup_set_state(gsbi_id, QUP_STATE_RUN);
+
+	write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
+		(QUP_I2C_START_SEQ | QUP_I2C_ADDR(addr)));
+
+	while (data_len) {
+		if (data_len == 1 && stop_seq) {
+			write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
+				QUP_I2C_STOP_SEQ | QUP_I2C_DATA(data_ptr[idx]));
+		} else {
+			write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
+				QUP_I2C_DATA_SEQ | QUP_I2C_DATA(data_ptr[idx]));
+		}
+		data_len--;
+		idx++;
+		if (data_len) {
+			ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_FULL);
+			if (ret)
+				return ret;
+		}
+		/* Hardware sets the OUTPUT_SERVICE_FLAG flag to 1 when
+			OUTPUT_FIFO_NOT_EMPTY flag in the QUP_OPERATIONAL
+			register changes from 1 to 0, indicating that software
+			can write more data to the output FIFO. Software should
+			set OUTPUT_SERVICE_FLAG to 1 to clear it to 0, which
+			means that software knows to return to fill the output
+			FIFO with data.
+		 */
+		if (read32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL)) &
+				OUTPUT_SERVICE_FLAG) {
+			write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
+				OUTPUT_SERVICE_FLAG);
+		}
+	}
+
+	ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY);
+	if (ret)
+		return ret;
+
+	qup_set_state(gsbi_id, QUP_STATE_PAUSE);
+	return qup_i2c_master_status(gsbi_id);
+}
+
+static qup_return_t qup_i2c_write(gsbi_id_t gsbi_id, uint8_t mode,
+				  qup_data_t *p_tx_obj, uint8_t stop_seq)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+
+	switch (mode) {
+	case QUP_MODE_FIFO:
+		ret = qup_i2c_write_fifo(gsbi_id, p_tx_obj, stop_seq);
+		break;
+	default:
+		ret = QUP_ERR_UNSUPPORTED;
+	}
+
+	if (ret) {
+		qup_set_state(gsbi_id, QUP_STATE_RESET);
+		printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
+	}
+
+	return ret;
+}
+
+static qup_return_t qup_i2c_read_fifo(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	uint8_t addr = p_tx_obj->p.iic.addr;
+	uint8_t *data_ptr = p_tx_obj->p.iic.data;
+	unsigned data_len = p_tx_obj->p.iic.data_len;
+	unsigned idx = 0;
+
+	qup_reset_master_status(gsbi_id);
+	qup_set_state(gsbi_id, QUP_STATE_RUN);
+
+	write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
+		QUP_I2C_START_SEQ | (QUP_I2C_ADDR(addr) | QUP_I2C_SLAVE_READ));
+
+	write32(QUP_ADDR(gsbi_id, QUP_OUTPUT_FIFO),
+		QUP_I2C_RECV_SEQ | data_len);
+
+	ret = qup_fifo_wait_while(gsbi_id, OUTPUT_FIFO_NOT_EMPTY);
+	if (ret)
+		return ret;
+
+	write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), OUTPUT_SERVICE_FLAG);
+
+	while (data_len) {
+		uint32_t data;
+
+		ret = qup_fifo_wait_for(gsbi_id, INPUT_SERVICE_FLAG);
+		if (ret)
+			return ret;
+
+		data = read32(QUP_ADDR(gsbi_id, QUP_INPUT_FIFO));
+
+		/*
+		 * Process tag and corresponding data value. For I2C master
+		 * mini-core, data in FIFO is composed of 16 bits and is divided
+		 * into an 8-bit tag for the upper bits and 8-bit data for the
+		 * lower bits. The 8-bit tag indicates whether the byte is the
+		 * last byte, or if a bus error happened during the receipt of
+		 * the byte.
+		 */
+		if ((QUP_I2C_MI_TAG(data)) == QUP_I2C_MIDATA_SEQ) {
+			/* Tag: MIDATA = Master input data.*/
+			data_ptr[idx] = QUP_I2C_DATA(data);
+			idx++;
+			data_len--;
+			write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL),
+				INPUT_SERVICE_FLAG);
+		} else {
+			if (QUP_I2C_MI_TAG(data) == QUP_I2C_MISTOP_SEQ) {
+				/* Tag: MISTOP: Last byte of master input. */
+				data_ptr[idx] = QUP_I2C_DATA(data);
+				idx++;
+				data_len--;
+				break;
+			}
+			/* Tag: MINACK: Invalid master input data.*/
+			break;
+		}
+	}
+
+	write32(QUP_ADDR(gsbi_id, QUP_OPERATIONAL), INPUT_SERVICE_FLAG);
+	p_tx_obj->p.iic.data_len = idx;
+	qup_set_state(gsbi_id, QUP_STATE_PAUSE);
+
+	return QUP_SUCCESS;
+}
+
+static qup_return_t qup_i2c_read(gsbi_id_t gsbi_id, uint8_t mode,
+				 qup_data_t *p_tx_obj)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+
+	switch (mode) {
+	case QUP_MODE_FIFO:
+		ret = qup_i2c_read_fifo(gsbi_id, p_tx_obj);
+		break;
+	default:
+		ret = QUP_ERR_UNSUPPORTED;
+	}
+
+	if (ret) {
+		qup_set_state(gsbi_id, QUP_STATE_RESET);
+		printk(BIOS_ERR, "%s() failed (%d)\n", __func__, ret);
+	}
+
+	return ret;
+}
+
+qup_return_t qup_init(gsbi_id_t gsbi_id, const qup_config_t *config_ptr)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	uint32_t reg_val;
+
+	/* Reset the QUP core.*/
+	write32(QUP_ADDR(gsbi_id, QUP_SW_RESET), 0x1);
+
+	/*Wait till the reset takes effect */
+	ret = qup_wait_for_state(gsbi_id, QUP_STATE_RESET);
+	if (ret)
+		goto bailout;
+
+	/* Reset the config */
+	write32(QUP_ADDR(gsbi_id, QUP_CONFIG), 0);
+
+	/*Program the config register*/
+	/*Set N value*/
+	reg_val = 0x0F;
+	/*Set protocol*/
+	switch (config_ptr->protocol) {
+	case QUP_MINICORE_I2C_MASTER:
+		reg_val |= ((config_ptr->protocol &
+				QUP_MINI_CORE_PROTO_MASK) <<
+				QUP_MINI_CORE_PROTO_SHFT);
+		break;
+	default:
+		ret = QUP_ERR_UNSUPPORTED;
+		goto bailout;
+	}
+	write32(QUP_ADDR(gsbi_id, QUP_CONFIG), reg_val);
+
+	/*Reset i2c clk cntl register*/
+	write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), 0);
+
+	/*Set QUP IO Mode*/
+	switch (config_ptr->mode) {
+	case QUP_MODE_FIFO:
+		reg_val = QUP_OUTPUT_BIT_SHIFT_EN |
+			  ((config_ptr->mode & QUP_MODE_MASK) <<
+					QUP_OUTPUT_MODE_SHFT) |
+			  ((config_ptr->mode & QUP_MODE_MASK) <<
+					QUP_INPUT_MODE_SHFT);
+		break;
+	default:
+		ret = QUP_ERR_UNSUPPORTED;
+		goto bailout;
+	}
+	write32(QUP_ADDR(gsbi_id, QUP_IO_MODES), reg_val);
+
+	/*Set i2c clk cntl*/
+	reg_val = (QUP_DIVIDER_MIN_VAL << QUP_HS_DIVIDER_SHFT);
+	reg_val |= ((((config_ptr->src_frequency / config_ptr->clk_frequency)
+			/ 2) - QUP_DIVIDER_MIN_VAL) &
+				QUP_FS_DIVIDER_MASK);
+	write32(QUP_ADDR(gsbi_id, QUP_I2C_MASTER_CLK_CTL), reg_val);
+
+bailout:
+	if (ret)
+		printk(BIOS_ERR, "failed to init qup (%d)\n", ret);
+
+	return ret;
+}
+
+qup_return_t qup_set_state(gsbi_id_t gsbi_id, uint32_t state)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	unsigned curr_state = read32(QUP_ADDR(gsbi_id, QUP_STATE));
+
+	if ((state >= QUP_STATE_RESET && state <= QUP_STATE_PAUSE)
+		&& (curr_state & QUP_STATE_VALID_MASK)) {
+		/*
+		* For PAUSE_STATE to RESET_STATE transition,
+		* two writes of  10[binary]) are required for the
+		* transition to complete.
+		*/
+		if (QUP_STATE_PAUSE == curr_state && QUP_STATE_RESET == state) {
+			write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
+			write32(QUP_ADDR(gsbi_id, QUP_STATE), 0x2);
+		} else {
+			write32(QUP_ADDR(gsbi_id, QUP_STATE), state);
+		}
+		ret = qup_wait_for_state(gsbi_id, state);
+	}
+
+	return ret;
+}
+
+static qup_return_t qup_i2c_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+				      uint8_t stop_seq)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
+			QUP_OUTPUT_MODE_SHFT) & QUP_MODE_MASK;
+
+	ret = qup_i2c_write(gsbi_id, mode, p_tx_obj, stop_seq);
+	if (0) {
+		int i;
+
+		printk(BIOS_DEBUG, "i2c tx bus %d device %2.2x:",
+		       gsbi_id, p_tx_obj->p.iic.addr);
+		for (i = 0; i < p_tx_obj->p.iic.data_len; i++)
+			printk(BIOS_DEBUG, " %2.2x", p_tx_obj->p.iic.data[i]);
+		printk(BIOS_DEBUG, "\n");
+	}
+
+	return ret;
+}
+
+qup_return_t qup_send_data(gsbi_id_t gsbi_id, qup_data_t *p_tx_obj,
+			   uint8_t stop_seq)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+
+	if (p_tx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
+			QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
+		switch (p_tx_obj->protocol) {
+		case QUP_MINICORE_I2C_MASTER:
+			ret = qup_i2c_send_data(gsbi_id, p_tx_obj, stop_seq);
+			break;
+		default:
+			ret = QUP_ERR_UNSUPPORTED;
+		}
+	}
+
+	return ret;
+}
+
+static qup_return_t qup_i2c_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+	uint8_t mode = (read32(QUP_ADDR(gsbi_id, QUP_IO_MODES)) >>
+			QUP_INPUT_MODE_SHFT) & QUP_MODE_MASK;
+
+	ret = qup_i2c_read(gsbi_id, mode, p_rx_obj);
+	if (0) {
+		int i;
+
+		printk(BIOS_DEBUG, "i2c rxed on bus %d device %2.2x:",
+		       gsbi_id, p_rx_obj->p.iic.addr);
+		for (i = 0; i < p_rx_obj->p.iic.data_len; i++)
+			printk(BIOS_DEBUG, " %2.2x", p_rx_obj->p.iic.data[i]);
+		printk(BIOS_DEBUG, "\n");
+	}
+
+	return ret;
+}
+
+qup_return_t qup_recv_data(gsbi_id_t gsbi_id, qup_data_t *p_rx_obj)
+{
+	qup_return_t ret = QUP_ERR_UNDEFINED;
+
+	if (p_rx_obj->protocol == ((read32(QUP_ADDR(gsbi_id, QUP_CONFIG)) >>
+			QUP_MINI_CORE_PROTO_SHFT) & QUP_MINI_CORE_PROTO_MASK)) {
+		switch (p_rx_obj->protocol) {
+		case QUP_MINICORE_I2C_MASTER:
+			ret = qup_i2c_recv_data(gsbi_id, p_rx_obj);
+			break;
+		default:
+			ret = QUP_ERR_UNSUPPORTED;
+		}
+	}
+
+	return ret;
+}
diff --git a/src/soc/qualcomm/ipq40xx/soc.c b/src/soc/qualcomm/ipq40xx/soc.c
new file mode 100644
index 0000000..8ca0f97
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/soc.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 coresystems GmbH
+ * Copyright (C) 2011 The ChromiumOS Authors.  All rights reserved.
+ * Copyright 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.
+ */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <symbols.h>
+#include <soc/ipq_uart.h>
+
+#define RESERVED_SIZE_KB	(0x01500000 / KiB)
+
+static void soc_read_resources(device_t dev)
+{
+	/* Reserve bottom 0x150_0000 bytes for NSS, SMEM, etc. */
+	reserved_ram_resource(dev, 0, (uintptr_t)_dram / KiB, RESERVED_SIZE_KB);
+	ram_resource(dev, 0, (uintptr_t)_dram / KiB + RESERVED_SIZE_KB,
+		     (CONFIG_DRAM_SIZE_MB * KiB) - RESERVED_SIZE_KB);
+}
+
+static void soc_init(device_t dev)
+{
+	/*
+	 * Do this in case console is not enabled: kernel's earlyprintk()
+	 * should work no matter what the firmware console configuration is.
+	 */
+	ipq806x_uart_init();
+
+	printk(BIOS_INFO, "CPU: Qualcomm 8064\n");
+}
+
+static struct device_operations soc_ops = {
+	.read_resources = soc_read_resources,
+	.init		= soc_init,
+};
+
+static void enable_soc_dev(device_t dev)
+{
+	dev->ops = &soc_ops;
+}
+
+struct chip_operations soc_qualcomm_ipq806x_ops = {
+	CHIP_NAME("SOC Qualcomm 8064")
+	.enable_dev = enable_soc_dev,
+};
diff --git a/src/soc/qualcomm/ipq40xx/spi.c b/src/soc/qualcomm/ipq40xx/spi.c
new file mode 100644
index 0000000..be98fba
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/spi.c
@@ -0,0 +1,805 @@
+/*
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <arch/io.h>
+#include <delay.h>
+#include <gpio.h>
+#include <soc/iomap.h>
+#include <soc/spi.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SUCCESS		0
+
+#define DUMMY_DATA_VAL		0
+#define TIMEOUT_CNT		100
+#define CS_ASSERT		1
+#define CS_DEASSERT		0
+#define NUM_PORTS		3
+#define NUM_GSBI_PINS		3
+#define TLMM_ARGS		6
+#define NUM_CS			4
+#define GSBI_PIN_IDX		0
+#define FUNC_SEL_IDX		1
+#define GPIO_DIR_IDX		2
+#define PULL_CONF_IDX		3
+#define DRV_STR_IDX		4
+#define GPIO_EN_IDX		5
+
+/* Arbitrarily assigned error code values */
+#define ETIMEDOUT -10
+#define EINVAL -11
+#define EIO -12
+
+#define GSBI_IDX_TO_GSBI(idx)   (idx + 5)
+
+
+/* MX_INPUT_COUNT and MX_OUTPUT_COUNT are 16-bits. Zero has a special meaning
+ * (count function disabled) and does not hold significance in the count. */
+#define MAX_PACKET_COUNT	((64 * KiB) - 1)
+
+/*
+ * TLMM Configuration for SPI NOR
+ * gsbi_pin_conf[bus_num][GPIO_NUM, FUNC_SEL, I/O,
+ *			       PULL UP/DOWN, DRV_STR, GPIO_FUNC]
+ * gsbi_pin_conf[0][x][y] -- GSBI5
+ * gsbi_pin_conf[1][x][y] -- GSBI6
+ * gsbi_pin_conf[2][x][y] -- GSBI7
+*/
+static unsigned int gsbi_pin_conf[NUM_PORTS][NUM_GSBI_PINS][TLMM_ARGS] = {
+	{
+		/* GSBI5 CLK */
+		{
+			GSBI5_SPI_CLK,  FUNC_SEL_1, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE
+		},
+		/* GSBI5 MISO */
+		{
+			GSBI5_SPI_MISO, FUNC_SEL_1, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
+		},
+		/* GSBI5 MOSI */
+		{
+			GSBI5_SPI_MOSI, FUNC_SEL_1, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
+		}
+	},
+	{
+		/* GSBI6 CLK */
+		{
+			GSBI6_SPI_CLK,  FUNC_SEL_3, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE
+		},
+		/* GSBI6 MISO */
+		{
+			GSBI6_SPI_MISO, FUNC_SEL_3, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
+		},
+		/* GSBI6 MOSI */
+		{
+			GSBI6_SPI_MOSI, FUNC_SEL_3, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
+		}
+	},
+	{
+		/* GSBI7 CLK */
+		{
+			GSBI7_SPI_CLK,  FUNC_SEL_1, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE
+		},
+		/* GSBI7 MISO */
+		{
+			GSBI7_SPI_MISO, FUNC_SEL_1, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
+		},
+		/* GSBI7 MOSI */
+		{
+			GSBI7_SPI_MOSI, FUNC_SEL_1, GPIO_INPUT,
+			GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
+		}
+	}
+};
+
+/*
+ * CS GPIO number array cs_gpio_array[port_num][cs_num]
+ * cs_gpio_array[0][x] -- GSBI5
+ * cs_gpio_array[1][x] -- GSBI6
+ * cs_gpio_array[2][x] -- GSBI7
+ */
+static unsigned int cs_gpio_array[NUM_PORTS][NUM_CS] = {
+	{
+		GSBI5_SPI_CS_0, GSBI5_SPI_CS_1, GSBI5_SPI_CS_2, GSBI5_SPI_CS_3
+	},
+	{
+		GSBI6_SPI_CS_0,              0,              0,              0
+	},
+	{
+		GSBI7_SPI_CS_0,              0,              0,              0
+	}
+};
+
+/*
+ * GSBI HCLK state register bit
+ * hclk_state[0] -- GSBI5
+ * hclk_state[1] -- GSBI6
+ * hclk_state[2] -- GSBI7
+*/
+static unsigned int hclk_state[NUM_PORTS] = {
+	GSBI5_HCLK,
+	GSBI6_HCLK,
+	GSBI7_HCLK
+};
+
+/*
+ * GSBI QUP_APPS_CLK state register bit
+ * qup_apps_clk_state[0] -- GSBI5
+ * qup_apps_clk_state[1] -- GSBI6
+ * qup_apps_clk_state[2] -- GSBI7
+*/
+static unsigned int qup_apps_clk_state[NUM_PORTS] = {
+	GSBI5_QUP_APPS_CLK,
+	GSBI6_QUP_APPS_CLK,
+	GSBI7_QUP_APPS_CLK
+};
+
+
+static int check_bit_state(uint32_t reg_addr, int bit_num,
+				int val, int us_delay)
+{
+	unsigned int count = TIMEOUT_CNT;
+	unsigned int bit_val = ((readl_i(reg_addr) >> bit_num) & 0x01);
+
+	while (bit_val != val) {
+		count--;
+		if (count == 0)
+			return -ETIMEDOUT;
+		udelay(us_delay);
+		bit_val = ((readl_i(reg_addr) >> bit_num) & 0x01);
+	}
+
+	return SUCCESS;
+}
+
+/*
+ * Check whether GSBIn_QUP State is valid
+ */
+static int check_qup_state_valid(struct ipq_spi_slave *ds)
+{
+
+	return check_bit_state(ds->regs->qup_state, QUP_STATE_VALID_BIT,
+				QUP_STATE_VALID, 1);
+
+}
+
+/*
+ * Configure GSBIn Core state
+ */
+static int config_spi_state(struct ipq_spi_slave *ds, unsigned int state)
+{
+	uint32_t val;
+	int ret;
+	uint32_t new_state;
+
+	ret = check_qup_state_valid(ds);
+	if (ret != SUCCESS)
+		return ret;
+
+	switch (state) {
+	case SPI_RUN_STATE:
+		new_state = QUP_STATE_RUN_STATE;
+		break;
+
+	case SPI_RESET_STATE:
+		new_state = QUP_STATE_RESET_STATE;
+		break;
+
+	case SPI_PAUSE_STATE:
+		new_state = QUP_STATE_PAUSE_STATE;
+		break;
+
+	default:
+		printk(BIOS_ERR,
+		       "err: unsupported GSBI SPI state : %d\n", state);
+		return -EINVAL;
+	}
+
+	/* Set the state as requested */
+	val = (readl_i(ds->regs->qup_state) & ~QUP_STATE_MASK)
+		| new_state;
+	writel_i(val, ds->regs->qup_state);
+	return check_qup_state_valid(ds);
+}
+
+/*
+ * Set GSBIn SPI Mode
+ */
+static void spi_set_mode(struct ipq_spi_slave *ds, unsigned int mode)
+{
+	unsigned int clk_idle_state;
+	unsigned int input_first_mode;
+	uint32_t val;
+
+	switch (mode) {
+	case GSBI_SPI_MODE_0:
+		clk_idle_state = 0;
+		input_first_mode = SPI_INPUT_FIRST_MODE;
+		break;
+	case GSBI_SPI_MODE_1:
+		clk_idle_state = 0;
+		input_first_mode = 0;
+		break;
+	case GSBI_SPI_MODE_2:
+		clk_idle_state = 1;
+		input_first_mode = SPI_INPUT_FIRST_MODE;
+		break;
+	case GSBI_SPI_MODE_3:
+		clk_idle_state = 1;
+		input_first_mode = 0;
+		break;
+	default:
+		printk(BIOS_ERR,
+		       "err : unsupported spi mode : %d\n", mode);
+		return;
+	}
+
+	val = readl_i(ds->regs->spi_config);
+	val |= input_first_mode;
+	writel_i(val, ds->regs->spi_config);
+
+	val = readl_i(ds->regs->io_control);
+	if (clk_idle_state)
+		val |= SPI_IO_CONTROL_CLOCK_IDLE_HIGH;
+	else
+		val &= ~SPI_IO_CONTROL_CLOCK_IDLE_HIGH;
+
+	writel_i(val, ds->regs->io_control);
+}
+
+/*
+ * Check for HCLK state
+ */
+static int check_hclk_state(unsigned int core_num, int enable)
+{
+	return check_bit_state(CLK_HALT_CFPB_STATEB_REG,
+		hclk_state[core_num], enable, 5);
+}
+
+/*
+ * Check for QUP APPS CLK state
+ */
+static int check_qup_clk_state(unsigned int core_num, int enable)
+{
+	return check_bit_state(CLK_HALT_CFPB_STATEB_REG,
+		qup_apps_clk_state[core_num], enable, 5);
+}
+
+/*
+ * Function to assert and De-assert chip select
+ */
+static void CS_change(int port_num, int cs_num, int enable)
+{
+	unsigned int cs_gpio = cs_gpio_array[port_num][cs_num];
+	void *addr = GPIO_IN_OUT_ADDR(cs_gpio);
+	uint32_t val = readl_i(addr);
+
+	val &= (~(1 << GPIO_OUTPUT));
+	if (!enable)
+		val |= (1 << GPIO_OUTPUT);
+	write32(addr, val);
+}
+
+/*
+ * GSBIn TLMM configuration
+ */
+static void gsbi_pin_config(unsigned int port_num, int cs_num)
+{
+	unsigned int gpio;
+	unsigned int i;
+	/* Hold the GSBIn (core_num) core in reset */
+	clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(port_num)),
+			GSBI1_RESET_MSK, GSBI1_RESET);
+
+	/*
+	 * Configure SPI_CLK, SPI_MISO and SPI_MOSI
+	 */
+	for (i = 0; i < NUM_GSBI_PINS; i++) {
+		unsigned int func_sel;
+		unsigned int io_config;
+		unsigned int pull_config;
+		unsigned int drv_strength;
+		unsigned int gpio_en;
+		unsigned int *ptr;
+
+		ptr = gsbi_pin_conf[port_num][i];
+		gpio		= *(ptr + GSBI_PIN_IDX);
+		func_sel	= *(ptr + FUNC_SEL_IDX);
+		io_config	= *(ptr + GPIO_DIR_IDX);
+		pull_config	= *(ptr + PULL_CONF_IDX);
+		drv_strength	= *(ptr + DRV_STR_IDX);
+		gpio_en	= *(ptr + GPIO_EN_IDX);
+
+		gpio_tlmm_config(gpio, func_sel, io_config,
+				 pull_config, drv_strength, gpio_en);
+	}
+
+	gpio = cs_gpio_array[port_num][cs_num];
+	/* configure CS */
+	gpio_tlmm_config(gpio, FUNC_SEL_GPIO, GPIO_OUTPUT, GPIO_PULL_UP,
+				GPIO_DRV_STR_10MA, GPIO_FUNC_ENABLE);
+	CS_change(port_num, cs_num, CS_DEASSERT);
+}
+
+/*
+ * Clock configuration for GSBIn Core
+ */
+static int gsbi_clock_init(struct ipq_spi_slave *ds)
+{
+	int ret;
+
+	/* Hold the GSBIn (core_num) core in reset */
+	clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)),
+			GSBI1_RESET_MSK, GSBI1_RESET);
+
+	/* Disable GSBIn (core_num) QUP core clock branch */
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, QUP_CLK_BRANCH_ENA_MSK,
+					QUP_CLK_BRANCH_DIS);
+
+	ret = check_qup_clk_state(ds->slave.bus, 1);
+	if (ret) {
+		printk(BIOS_ERR,
+		       "QUP Clock Halt For GSBI%d failed!\n", ds->slave.bus);
+		return ret;
+	}
+
+	/* Disable M/N:D counter and hold M/N:D counter in reset */
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, (MNCNTR_MSK | MNCNTR_RST_MSK),
+					(MNCNTR_RST_ENA | MNCNTR_DIS));
+
+	/* Disable GSBIn (core_num) QUP core clock root */
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, CLK_ROOT_ENA_MSK, CLK_ROOT_DIS);
+
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_PLL_SRC_MSK,
+					GSBIn_PLL_SRC_PLL8);
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_PRE_DIV_SEL_MSK,
+						(0 << GSBI_PRE_DIV_SEL_SHFT));
+
+	/* Program M/N:D values for GSBIn_QUP_APPS_CLK @50MHz */
+	clrsetbits_le32_i(ds->regs->qup_md_reg, GSBIn_M_VAL_MSK,
+						(0x01 << GSBI_M_VAL_SHFT));
+	clrsetbits_le32_i(ds->regs->qup_md_reg, GSBIn_D_VAL_MSK,
+						(0xF7 << GSBI_D_VAL_SHFT));
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_N_VAL_MSK,
+						(0xF8 << GSBI_N_VAL_SHFT));
+
+	/* Set MNCNTR_MODE = 0: Bypass mode */
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_MODE_MSK,
+					MNCNTR_MODE_DUAL_EDGE);
+
+	/* De-assert the M/N:D counter reset */
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_RST_MSK, MNCNTR_RST_DIS);
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_MSK, MNCNTR_EN);
+
+	/*
+	 * Enable the GSBIn (core_num) QUP core clock root.
+	 * Keep MND counter disabled
+	 */
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, CLK_ROOT_ENA_MSK, CLK_ROOT_ENA);
+
+	/* Enable GSBIn (core_num) QUP core clock branch */
+	clrsetbits_le32_i(ds->regs->qup_ns_reg, QUP_CLK_BRANCH_ENA_MSK,
+						QUP_CLK_BRANCH_ENA);
+
+	ret = check_qup_clk_state(ds->slave.bus, 0);
+	if (ret) {
+		printk(BIOS_ERR,
+		       "QUP Clock Enable For GSBI%d failed!\n", ds->slave.bus);
+		return ret;
+	}
+
+	/* Enable GSBIn (core_num) core clock branch */
+	clrsetbits_le32_i(GSBIn_HCLK_CTL_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)),
+			GSBI_CLK_BRANCH_ENA_MSK, GSBI_CLK_BRANCH_ENA);
+
+	ret = check_hclk_state(ds->slave.bus, 0);
+	if (ret) {
+		printk(BIOS_ERR,
+		       "HCLK Enable For GSBI%d failed!\n", ds->slave.bus);
+		return ret;
+	}
+
+	/* Release GSBIn (core_num) core from reset */
+	clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)),
+						GSBI1_RESET_MSK, 0);
+	udelay(50);
+
+	return SUCCESS;
+}
+
+/*
+ * Reset entire QUP and all mini cores
+ */
+static void spi_reset(struct ipq_spi_slave *ds)
+{
+	writel_i(0x1, ds->regs->qup_sw_reset);
+	udelay(5);
+}
+
+static const struct gsbi_spi spi_reg[] = {
+	/* GSBI5 registers for SPI interface */
+	{
+		GSBI5_SPI_CONFIG_REG,
+		GSBI5_SPI_IO_CONTROL_REG,
+		GSBI5_SPI_ERROR_FLAGS_REG,
+		GSBI5_SPI_ERROR_FLAGS_EN_REG,
+		GSBI5_GSBI_CTRL_REG_REG,
+		GSBI5_QUP_CONFIG_REG,
+		GSBI5_QUP_ERROR_FLAGS_REG,
+		GSBI5_QUP_ERROR_FLAGS_EN_REG,
+		GSBI5_QUP_OPERATIONAL_REG,
+		GSBI5_QUP_IO_MODES_REG,
+		GSBI5_QUP_STATE_REG,
+		GSBI5_QUP_INPUT_FIFOc_REG(0),
+		GSBI5_QUP_OUTPUT_FIFOc_REG(0),
+		GSBI5_QUP_MX_INPUT_COUNT_REG,
+		GSBI5_QUP_MX_OUTPUT_COUNT_REG,
+		GSBI5_QUP_SW_RESET_REG,
+		GSBIn_QUP_APPS_NS_REG(5),
+		GSBIn_QUP_APPS_MD_REG(5),
+	},
+	/* GSBI6 registers for SPI interface */
+	{
+		GSBI6_SPI_CONFIG_REG,
+		GSBI6_SPI_IO_CONTROL_REG,
+		GSBI6_SPI_ERROR_FLAGS_REG,
+		GSBI6_SPI_ERROR_FLAGS_EN_REG,
+		GSBI6_GSBI_CTRL_REG_REG,
+		GSBI6_QUP_CONFIG_REG,
+		GSBI6_QUP_ERROR_FLAGS_REG,
+		GSBI6_QUP_ERROR_FLAGS_EN_REG,
+		GSBI6_QUP_OPERATIONAL_REG,
+		GSBI6_QUP_IO_MODES_REG,
+		GSBI6_QUP_STATE_REG,
+		GSBI6_QUP_INPUT_FIFOc_REG(0),
+		GSBI6_QUP_OUTPUT_FIFOc_REG(0),
+		GSBI6_QUP_MX_INPUT_COUNT_REG,
+		GSBI6_QUP_MX_OUTPUT_COUNT_REG,
+		GSBI6_QUP_SW_RESET_REG,
+		GSBIn_QUP_APPS_NS_REG(6),
+		GSBIn_QUP_APPS_MD_REG(6),
+	},
+	/* GSBI7 registers for SPI interface */
+	{
+		GSBI7_SPI_CONFIG_REG,
+		GSBI7_SPI_IO_CONTROL_REG,
+		GSBI7_SPI_ERROR_FLAGS_REG,
+		GSBI7_SPI_ERROR_FLAGS_EN_REG,
+		GSBI7_GSBI_CTRL_REG_REG,
+		GSBI7_QUP_CONFIG_REG,
+		GSBI7_QUP_ERROR_FLAGS_REG,
+		GSBI7_QUP_ERROR_FLAGS_EN_REG,
+		GSBI7_QUP_OPERATIONAL_REG,
+		GSBI7_QUP_IO_MODES_REG,
+		GSBI7_QUP_STATE_REG,
+		GSBI7_QUP_INPUT_FIFOc_REG(0),
+		GSBI7_QUP_OUTPUT_FIFOc_REG(0),
+		GSBI7_QUP_MX_INPUT_COUNT_REG,
+		GSBI7_QUP_MX_OUTPUT_COUNT_REG,
+		GSBI7_QUP_SW_RESET_REG,
+		GSBIn_QUP_APPS_NS_REG(7),
+		GSBIn_QUP_APPS_MD_REG(7),
+	}
+};
+static struct ipq_spi_slave spi_slave_pool[2];
+
+void spi_init(void)
+{
+	/* just in case */
+	memset(spi_slave_pool, 0, sizeof(spi_slave_pool));
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
+{
+	struct ipq_spi_slave *ds = NULL;
+	int i;
+
+	/*
+	 * IPQ GSBI (Generic Serial Bus Interface) supports SPI Flash
+	 * on different GSBI5, GSBI6 and GSBI7
+	 * with different number of chip selects (CS, channels):
+	*/
+	if ((bus < GSBI5_SPI) || (bus > GSBI7_SPI)
+		|| ((bus == GSBI5_SPI) && (cs > 3))
+		|| ((bus == GSBI6_SPI) && (cs > 0))
+		|| ((bus == GSBI7_SPI) && (cs > 0))) {
+		printk(BIOS_ERR, "SPI error: unsupported bus %d (Supported busses 0,1 and 2) or chipselect\n",
+			bus);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(spi_slave_pool); i++) {
+		if (spi_slave_pool[i].allocated)
+			continue;
+		ds = spi_slave_pool + i;
+		ds->slave.bus	= bus;
+		ds->slave.cs	= cs;
+		ds->regs	= &spi_reg[bus];
+
+		/*
+		 * TODO(vbendeb):
+		 * hardcoded frequency and mode - we might need to find a way
+		 * to configure this
+		 */
+		ds->freq = 10000000;
+		ds->mode = GSBI_SPI_MODE_0;
+		ds->allocated = 1;
+
+		return &ds->slave;
+	}
+
+	printk(BIOS_ERR, "SPI error: all %d pools busy\n", i);
+	return NULL;
+}
+
+/*
+ * GSBIn SPI Hardware Initialisation
+ */
+static int spi_hw_init(struct ipq_spi_slave *ds)
+{
+	int ret;
+
+	if (ds->initialized)
+		return 0;
+
+	/* GSBI module configuration */
+	spi_reset(ds);
+
+	/* Set the GSBIn QUP state */
+	ret = config_spi_state(ds, SPI_RESET_STATE);
+	if (ret)
+		return ret;
+
+	/* Configure GSBI_CTRL register to set protocol_mode to SPI:011 */
+	clrsetbits_le32_i(ds->regs->gsbi_ctrl, PROTOCOL_CODE_MSK,
+					PROTOCOL_CODE_SPI);
+
+	/*
+	 * Configure Mini core to SPI core with Input Output enabled,
+	 * SPI master, N = 8 bits
+	 */
+	clrsetbits_le32_i(ds->regs->qup_config, (QUP_CONFIG_MINI_CORE_MSK |
+					       SPI_QUP_CONF_INPUT_MSK |
+					       SPI_QUP_CONF_OUTPUT_MSK |
+					       SPI_BIT_WORD_MSK),
+					      (QUP_CONFIG_MINI_CORE_SPI |
+					       SPI_QUP_CONF_NO_INPUT |
+					       SPI_QUP_CONF_NO_OUTPUT |
+					       SPI_8_BIT_WORD));
+
+	/*
+	 * Configure Input first SPI protocol,
+	 * SPI master mode and no loopback
+	 */
+	clrsetbits_le32_i(ds->regs->spi_config, (LOOP_BACK_MSK |
+					       SLAVE_OPERATION_MSK),
+					      (NO_LOOP_BACK |
+					       SLAVE_OPERATION));
+
+	/*
+	 * Configure SPI IO Control Register
+	 * CLK_ALWAYS_ON = 0
+	 * MX_CS_MODE = 0
+	 * NO_TRI_STATE = 1
+	 */
+	writel_i((CLK_ALWAYS_ON | MX_CS_MODE | NO_TRI_STATE),
+				ds->regs->io_control);
+
+	/*
+	 * Configure SPI IO Modes.
+	 * OUTPUT_BIT_SHIFT_EN = 1
+	 * INPUT_MODE = Block Mode
+	 * OUTPUT MODE = Block Mode
+	 */
+	clrsetbits_le32_i(ds->regs->qup_io_modes, (OUTPUT_BIT_SHIFT_MSK |
+						 INPUT_BLOCK_MODE_MSK |
+						 OUTPUT_BLOCK_MODE_MSK),
+						(OUTPUT_BIT_SHIFT_EN |
+						 INPUT_BLOCK_MODE |
+						 OUTPUT_BLOCK_MODE));
+
+	spi_set_mode(ds, ds->mode);
+
+	/* Disable Error mask */
+	writel_i(0, ds->regs->error_flags_en);
+	writel_i(0, ds->regs->qup_error_flags_en);
+
+	ds->initialized = 1;
+
+	return SUCCESS;
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct ipq_spi_slave *ds = to_ipq_spi(slave);
+	unsigned int ret;
+
+	if (ds->initialized)
+		return SUCCESS;
+
+	/* GPIO Configuration for SPI port */
+	gsbi_pin_config(ds->slave.bus, ds->slave.cs);
+
+	/* Clock configuration */
+	ret = gsbi_clock_init(ds);
+	if (ret)
+		return ret;
+
+	ret = spi_hw_init(ds);
+	if (ret)
+		return -EIO;
+
+	return SUCCESS;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	struct ipq_spi_slave *ds = to_ipq_spi(slave);
+
+	/* Reset the SPI hardware */
+	spi_reset(ds);
+	ds->initialized = 0;
+}
+
+static int spi_xfer_tx_packet(struct ipq_spi_slave *ds,
+		const uint8_t *dout, unsigned out_bytes)
+{
+	int ret;
+
+	writel_i(out_bytes, ds->regs->qup_mx_output_count);
+
+	ret = config_spi_state(ds, SPI_RUN_STATE);
+	if (ret)
+		return ret;
+
+	while (out_bytes) {
+		if (readl_i(ds->regs->qup_operational) & QUP_OUTPUT_FIFO_FULL)
+			continue;
+
+		writel_i(*dout++, ds->regs->qup_output_fifo);
+		out_bytes--;
+
+		/* Wait for output FIFO to drain. */
+		if (!out_bytes)
+			while (readl_i(ds->regs->qup_operational) &
+			       QUP_OUTPUT_FIFO_NOT_EMPTY)
+				;
+	}
+
+	return config_spi_state(ds, SPI_RESET_STATE);
+}
+
+static int spi_xfer_rx_packet(struct ipq_spi_slave *ds,
+		uint8_t *din, unsigned in_bytes)
+{
+	int ret;
+
+	writel_i(in_bytes, ds->regs->qup_mx_input_count);
+	writel_i(in_bytes, ds->regs->qup_mx_output_count);
+
+	ret = config_spi_state(ds, SPI_RUN_STATE);
+	if (ret)
+		return ret;
+
+	/* Seed clocking */
+	writel_i(0xff, ds->regs->qup_output_fifo);
+	while (in_bytes) {
+		if (!(readl_i(ds->regs->qup_operational) &
+		      QUP_INPUT_FIFO_NOT_EMPTY))
+			continue;
+		/* Keep it clocking */
+		writel_i(0xff, ds->regs->qup_output_fifo);
+
+		*din++ = readl_i(ds->regs->qup_input_fifo) & 0xff;
+		in_bytes--;
+	}
+
+	return config_spi_state(ds, SPI_RESET_STATE);
+}
+
+unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
+{
+	return min(MAX_PACKET_COUNT, buf_len);
+}
+
+int spi_xfer(struct spi_slave *slave, const void *dout,
+	     unsigned out_bytes, void *din, unsigned in_bytes)
+{
+	int ret;
+	struct ipq_spi_slave *ds = to_ipq_spi(slave);
+
+	/* Assert the chip select */
+	CS_change(ds->slave.bus, ds->slave.cs, CS_ASSERT);
+
+	ret = config_spi_state(ds, SPI_RESET_STATE);
+	if (ret)
+		goto out;
+
+	if (!out_bytes)
+		goto spi_receive;
+
+	/*
+	 * Let's do the write side of the transaction first. Enable output
+	 * FIFO.
+	 */
+	clrsetbits_le32_i(ds->regs->qup_config, SPI_QUP_CONF_OUTPUT_MSK,
+			  SPI_QUP_CONF_OUTPUT_ENA);
+
+	while (out_bytes) {
+		unsigned todo = MIN(out_bytes, MAX_PACKET_COUNT);
+
+		ret = spi_xfer_tx_packet(ds, dout, todo);
+		if (ret)
+			break;
+
+		out_bytes -= todo;
+		dout += todo;
+	}
+
+	if (ret)
+		goto out;
+
+spi_receive:
+	if (!in_bytes) /* Nothing to read. */
+		goto out;
+
+	/* Enable input FIFO */
+	clrsetbits_le32_i(ds->regs->qup_config, SPI_QUP_CONF_INPUT_MSK,
+			  SPI_QUP_CONF_INPUT_ENA);
+
+	while (in_bytes) {
+		unsigned todo = MIN(in_bytes, MAX_PACKET_COUNT);
+
+		ret = spi_xfer_rx_packet(ds, din, todo);
+		if (ret)
+			break;
+
+		in_bytes -= todo;
+		din += todo;
+	}
+
+out:
+	/* Deassert CS */
+	CS_change(ds->slave.bus, ds->slave.cs, CS_DEASSERT);
+
+	/*
+	 * Put the SPI Core back in the Reset State
+	 * to end the transfer
+	 */
+	(void)config_spi_state(ds, SPI_RESET_STATE);
+
+	return ret;
+}
diff --git a/src/soc/qualcomm/ipq40xx/timer.c b/src/soc/qualcomm/ipq40xx/timer.c
new file mode 100644
index 0000000..7b8c1f0
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/timer.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2011 - 2014 The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <delay.h>
+#include <soc/iomap.h>
+#include <soc/ipq_timer.h>
+#include <timer.h>
+
+/*
+ * DGT runs at 25 MHz / 4, or 6.25 ticks per microsecond
+ */
+#define DGT_MHZ_NUM	25
+#define DGT_MHZ_DEN	4
+
+#define TIMER_TICKS(us) ((DGT_MHZ_NUM*(us) + (DGT_MHZ_DEN - 1)) / DGT_MHZ_DEN)
+#define TIMER_USECS(ticks) (DGT_MHZ_DEN*(ticks) / DGT_MHZ_NUM)
+
+/* Clock divider values for the timer. */
+#define DGT_CLK_DIV_1	0
+#define DGT_CLK_DIV_2	1
+#define DGT_CLK_DIV_3	2
+#define DGT_CLK_DIV_4	3
+
+/**
+ * init_timer - initialize timer
+ */
+void init_timer(void)
+{
+	/* disable timer */
+	writel_i(0, DGT_ENABLE);
+
+	/* DGT uses TCXO source which is 25MHz.
+	 * The timer should run at 1/4th the frequency of TCXO
+	 * according to clock plan.
+	 * Set clock divider to 4.
+	 */
+	writel_i(DGT_CLK_DIV_4, DGT_CLK_CTL);
+
+	/* Enable timer */
+	writel_i(0, DGT_CLEAR);
+	writel_i(DGT_ENABLE_EN, DGT_ENABLE);
+}
+
+/**
+ * udelay -  generates micro second delay.
+ * @param usec: delay duration in microseconds
+ */
+void udelay(unsigned usec)
+{
+	uint32_t now;
+	uint32_t last;
+	uint32_t ticks;
+	uint32_t curr_ticks = 0;
+
+	/* Calculate number of ticks required. */
+	ticks = TIMER_TICKS(usec);
+
+	/* Obtain the current timer value. */
+	last = readl_i(DGT_COUNT_VAL);
+
+	/* Loop until the right number of ticks. */
+	while (curr_ticks < ticks) {
+		now = readl_i(DGT_COUNT_VAL);
+		curr_ticks += now - last;
+		last = now;
+	}
+}
+
+void timer_monotonic_get(struct mono_time *mt)
+{
+	mono_time_set_usecs(mt, TIMER_USECS(readl_i(DGT_COUNT_VAL)));
+}
diff --git a/src/soc/qualcomm/ipq40xx/tz_wrapper.S b/src/soc/qualcomm/ipq40xx/tz_wrapper.S
new file mode 100644
index 0000000..70cc170
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/tz_wrapper.S
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * TZ expects the ARM core to be in 'ARM' mode. However, coreboot seems
+ * to be compiled in mixed thumb/arm mode. Hence create a glue function
+ * to invoke TZ.
+ */
+
+#include <arch/asm.h>
+
+/*
+ * Force ARM mode. Else this gets assembled with mixed ARM and
+ * Thumb instructions. We set up everything and jump to TZBSP
+ * using the 'blx' instruction. For 'blx' if the last bit of the
+ * destination address is zero, it switches to ARM mode. Since,
+ * we are already in ARM mode, nothing to switch as such.
+ *
+ * However, when TZBSP returns, the CPU is still in ARM mode.
+ * If the assembler inserts Thumb instructions between the point
+ * of return from TZBSP to the 'bx' instruction we are hosed.
+ * Hence forcing ARM mode.
+ *
+ * Rest of the code can be compiled in mixed ARM/Thumb mode.
+ * Since tz_init_wrapper is being forced as an ARM symbol,
+ * callers will use 'blx' to come here forcing a switch to
+ * ARM mode. The wrapper does its job and returns back to the
+ * Thumb caller.
+ */
+.arm
+/*
+ * int tz_init_wrapper(int, int, void *);
+ */
+ENTRY(tz_init_wrapper)
+	.global tz_init_wrapper
+
+	/*
+	 *      r0 = tz_arg1
+	 *      r1 = tz_arg2
+	 *      r2 = tz_load_addr
+	 */
+
+	/*
+	 * Per the AAPCS
+	 *	r0, r1, r2, r3, r12 can be clobbered
+	 *	r4, r5, r6, r7, r8, r9, r10, r11 have to be preserved
+	 *
+	 * Following code clobbers
+	 *	r0 - Setting return value to zero
+	 *	r1 - For doing a thumb return
+	 *	r3 - Passing 'SP' from current mode to 'svc' mode
+	 *	r4 - To save & restore CPSR
+	 *
+	 * Per AAPCS, save and restore r4, rest are 'clobberable' :)
+	 * The invoked code takes care of saving and restoring the other
+	 * preserved registers (i.e. r5 - r11)
+	 *
+	 * Stack Usage:
+	 *	SP ->	| LR	|	(Lower address)
+	 *		| r4	|
+	 *		| CPSR	|
+	 *		|-------|
+	 *		|   .   |
+	 *		|   .   |
+	 *		|   .   |	(Higher address)
+	 */
+
+	sub	sp, sp, #12	/* Allocate stack frame */
+	str	lr, [sp]	/* Save return address */
+	str	r4, [sp, #4]	/* Use r4 to hold the new CPSR value */
+
+	mov	r3, sp		/* Get current stack pointer */
+
+	mrs	r4, CPSR	/* save CPSR */
+	str	r4, [sp, #8]
+
+	bic	r4, r4, 0x1f	/* Clear mode bits */
+	orr	r4, r4, 0x13	/* 'svc' mode */
+	msr	cpsr_cxf, r4	/* Switch to Supervisor mode. */
+	mov	sp, r3		/* Use the same stack as the previous mode */
+
+	blx	r2		/* Jump to TZ in ARM mode */
+
+	nop			/* back from TZ, in ARM mode */
+
+	ldr	r4, [sp, #8]	/* restore CPSR */
+	msr	cpsr_cxf, r4
+
+	ldr	r4, [sp, #4]	/* restore r4 */
+
+	ldr	lr, [sp]	/* saved return address */
+	add	sp, sp, #12	/* free stack frame */
+
+	bx	lr		/* back to thumb caller */
+
+ENDPROC(tz_init_wrapper)
diff --git a/src/soc/qualcomm/ipq40xx/uart.c b/src/soc/qualcomm/ipq40xx/uart.c
new file mode 100644
index 0000000..bd9d071
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/uart.c
@@ -0,0 +1,406 @@
+/*
+ * Copyright (c) 2012 The Linux Foundation. All rights reserved.
+ * Source : APQ8064 LK boot
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER 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 <arch/io.h>
+#include <boot/coreboot_tables.h>
+#include <console/console.h>
+#include <console/uart.h>
+#include <delay.h>
+#include <gpio.h>
+#include <soc/clock.h>
+#include <soc/gsbi.h>
+#include <soc/ipq_uart.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#define FIFO_DATA_SIZE	4
+
+typedef struct {
+	void *uart_dm_base;
+	void *uart_gsbi_base;
+	unsigned uart_gsbi;
+	uart_clk_mnd_t mnd_value;
+	gpio_func_data_t dbg_uart_gpio[NO_OF_DBG_UART_GPIOS];
+} uart_params_t;
+
+/*
+ * All constants lifted from u-boot's
+ * board/qcom/ipq806x_cdp/ipq806x_board_param.h
+ */
+static const uart_params_t uart_board_param = {
+	.uart_dm_base = (void *)UART4_DM_BASE,
+	.uart_gsbi_base = (void *)UART_GSBI4_BASE,
+	.uart_gsbi = GSBI_4,
+	.mnd_value = { 12, 625, 313 },
+		.dbg_uart_gpio = {
+			{
+				.gpio = 10,
+				.func = 1,
+				.dir = GPIO_OUTPUT,
+				.pull = GPIO_NO_PULL,
+				.drvstr = GPIO_12MA,
+				.enable = GPIO_DISABLE
+			},
+			{
+				.gpio = 11,
+				.func = 1,
+				.dir = GPIO_INPUT,
+				.pull = GPIO_NO_PULL,
+				.drvstr = GPIO_12MA,
+				.enable = GPIO_DISABLE
+			},
+		}
+};
+
+/**
+ * msm_boot_uart_dm_init_rx_transfer - Init Rx transfer
+ * @uart_dm_base: UART controller base address
+ */
+static unsigned int msm_boot_uart_dm_init_rx_transfer(void *uart_dm_base)
+{
+	/* Reset receiver */
+	write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
+		MSM_BOOT_UART_DM_CMD_RESET_RX);
+
+	/* Enable receiver */
+	write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
+		MSM_BOOT_UART_DM_CR_RX_ENABLE);
+	write32(MSM_BOOT_UART_DM_DMRX(uart_dm_base),
+		MSM_BOOT_UART_DM_DMRX_DEF_VALUE);
+
+	/* Clear stale event */
+	write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
+		MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
+
+	/* Enable stale event */
+	write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
+		MSM_BOOT_UART_DM_GCMD_ENA_STALE_EVT);
+
+	return MSM_BOOT_UART_DM_E_SUCCESS;
+}
+
+#if IS_ENABLED(CONFIG_DRIVERS_UART)
+static unsigned int msm_boot_uart_dm_init(void  *uart_dm_base);
+
+/* Received data is valid or not */
+static int valid_data = 0;
+
+/* Received data */
+static unsigned int word = 0;
+
+/**
+ * msm_boot_uart_dm_read - reads a word from the RX FIFO.
+ * @data: location where the read data is stored
+ * @count: no of valid data in the FIFO
+ * @wait: indicates blocking call or not blocking call
+ *
+ * Reads a word from the RX FIFO. If no data is available blocks if
+ * @wait is true, else returns %MSM_BOOT_UART_DM_E_RX_NOT_READY.
+ */
+ #if 0 /* Not used yet */
+static unsigned int
+msm_boot_uart_dm_read(unsigned int *data, int *count, int wait)
+{
+	static int total_rx_data = 0;
+	static int rx_data_read = 0;
+	void *base;
+	uint32_t status_reg;
+
+	base = uart_board_param.uart_dm_base;
+
+	if (data == NULL)
+		return MSM_BOOT_UART_DM_E_INVAL;
+
+	status_reg = readl(MSM_BOOT_UART_DM_MISR(base));
+
+	/* Check for DM_RXSTALE for RX transfer to finish */
+	while (!(status_reg & MSM_BOOT_UART_DM_RXSTALE)) {
+		status_reg = readl(MSM_BOOT_UART_DM_MISR(base));
+		if (!wait)
+			return MSM_BOOT_UART_DM_E_RX_NOT_READY;
+	}
+
+	/* Check for Overrun error. We'll just reset Error Status */
+	if (readl(MSM_BOOT_UART_DM_SR(base)) &
+			MSM_BOOT_UART_DM_SR_UART_OVERRUN) {
+		writel(MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT,
+			MSM_BOOT_UART_DM_CR(base));
+		total_rx_data = rx_data_read = 0;
+		msm_boot_uart_dm_init(base);
+		return MSM_BOOT_UART_DM_E_RX_NOT_READY;
+	}
+
+	/* Read UART_DM_RX_TOTAL_SNAP for actual number of bytes received */
+	if (total_rx_data == 0)
+		total_rx_data =  readl(MSM_BOOT_UART_DM_RX_TOTAL_SNAP(base));
+
+	/* Data available in FIFO; read a word. */
+	*data = readl(MSM_BOOT_UART_DM_RF(base, 0));
+
+	/* WAR for http://prism/CR/548280 */
+	if (*data == 0)
+		return MSM_BOOT_UART_DM_E_RX_NOT_READY;
+
+	/* increment the total count of chars we've read so far */
+	rx_data_read += FIFO_DATA_SIZE;
+
+	/* actual count of valid data in word */
+	*count = ((total_rx_data < rx_data_read) ?
+			(FIFO_DATA_SIZE - (rx_data_read - total_rx_data)) :
+			FIFO_DATA_SIZE);
+
+	/* If there are still data left in FIFO we'll read them before
+	 * initializing RX Transfer again
+	 */
+	if (rx_data_read < total_rx_data)
+		return MSM_BOOT_UART_DM_E_SUCCESS;
+
+	msm_boot_uart_dm_init_rx_transfer(base);
+	total_rx_data = rx_data_read = 0;
+
+	return MSM_BOOT_UART_DM_E_SUCCESS;
+}
+#endif
+
+void uart_tx_byte(int idx, unsigned char data)
+{
+	int num_of_chars = 1;
+	unsigned tx_data = 0;
+	void *base = uart_board_param.uart_dm_base;
+
+	/* Wait until transmit FIFO is empty. */
+	while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
+		 MSM_BOOT_UART_DM_SR_TXEMT))
+		udelay(1);
+	/*
+	 * TX FIFO is ready to accept new character(s). First write number of
+	 * characters to be transmitted.
+	 */
+	write32(MSM_BOOT_UART_DM_NO_CHARS_FOR_TX(base), num_of_chars);
+
+	/* And now write the character(s) */
+	write32(MSM_BOOT_UART_DM_TF(base, 0), tx_data);
+}
+#endif /* CONFIG_SERIAL_UART */
+
+/*
+ * msm_boot_uart_dm_reset - resets UART controller
+ * @base: UART controller base address
+ */
+static unsigned int msm_boot_uart_dm_reset(void *base)
+{
+	write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_RX);
+	write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RESET_TX);
+	write32(MSM_BOOT_UART_DM_CR(base),
+		MSM_BOOT_UART_DM_CMD_RESET_ERR_STAT);
+	write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_TX_ERR);
+	write32(MSM_BOOT_UART_DM_CR(base), MSM_BOOT_UART_DM_CMD_RES_STALE_INT);
+
+	return MSM_BOOT_UART_DM_E_SUCCESS;
+}
+
+/*
+ * msm_boot_uart_dm_init - initilaizes UART controller
+ * @uart_dm_base: UART controller base address
+ */
+static unsigned int msm_boot_uart_dm_init(void  *uart_dm_base)
+{
+	/* Configure UART mode registers MR1 and MR2 */
+	/* Hardware flow control isn't supported */
+	write32(MSM_BOOT_UART_DM_MR1(uart_dm_base), 0x0);
+
+	/* 8-N-1 configuration: 8 data bits - No parity - 1 stop bit */
+	write32(MSM_BOOT_UART_DM_MR2(uart_dm_base),
+		MSM_BOOT_UART_DM_8_N_1_MODE);
+
+	/* Configure Interrupt Mask register IMR */
+	write32(MSM_BOOT_UART_DM_IMR(uart_dm_base),
+		MSM_BOOT_UART_DM_IMR_ENABLED);
+
+	/*
+	 * Configure Tx and Rx watermarks configuration registers
+	 * TX watermark value is set to 0 - interrupt is generated when
+	 * FIFO level is less than or equal to 0
+	 */
+	write32(MSM_BOOT_UART_DM_TFWR(uart_dm_base),
+		MSM_BOOT_UART_DM_TFW_VALUE);
+
+	/* RX watermark value */
+	write32(MSM_BOOT_UART_DM_RFWR(uart_dm_base),
+		MSM_BOOT_UART_DM_RFW_VALUE);
+
+	/* Configure Interrupt Programming Register */
+	/* Set initial Stale timeout value */
+	write32(MSM_BOOT_UART_DM_IPR(uart_dm_base),
+		MSM_BOOT_UART_DM_STALE_TIMEOUT_LSB);
+
+	/* Configure IRDA if required */
+	/* Disabling IRDA mode */
+	write32(MSM_BOOT_UART_DM_IRDA(uart_dm_base), 0x0);
+
+	/* Configure hunt character value in HCR register */
+	/* Keep it in reset state */
+	write32(MSM_BOOT_UART_DM_HCR(uart_dm_base), 0x0);
+
+	/*
+	 * Configure Rx FIFO base address
+	 * Both TX/RX shares same SRAM and default is half-n-half.
+	 * Sticking with default value now.
+	 * As such RAM size is (2^RAM_ADDR_WIDTH, 32-bit entries).
+	 * We have found RAM_ADDR_WIDTH = 0x7f
+	 */
+
+	/* Issue soft reset command */
+	msm_boot_uart_dm_reset(uart_dm_base);
+
+	/* Enable/Disable Rx/Tx DM interfaces */
+	/* Data Mover not currently utilized. */
+	write32(MSM_BOOT_UART_DM_DMEN(uart_dm_base), 0x0);
+
+	/* Enable transmitter */
+	write32(MSM_BOOT_UART_DM_CR(uart_dm_base),
+		MSM_BOOT_UART_DM_CR_TX_ENABLE);
+
+	/* Initialize Receive Path */
+	msm_boot_uart_dm_init_rx_transfer(uart_dm_base);
+
+	return 0;
+}
+
+/**
+ * ipq806x_uart_init - initializes UART
+ *
+ * Initializes clocks, GPIO and UART controller.
+ */
+void uart_init(int idx)
+{
+	/* Note int idx isn't used in this driver. */
+	void *dm_base;
+	void *gsbi_base;
+
+	dm_base = uart_board_param.uart_dm_base;
+
+	if (read32(MSM_BOOT_UART_DM_CSR(dm_base)) == UART_DM_CLK_RX_TX_BIT_RATE)
+		return; /* UART must have been already initialized. */
+
+	gsbi_base = uart_board_param.uart_gsbi_base;
+	ipq_configure_gpio(uart_board_param.dbg_uart_gpio,
+			   NO_OF_DBG_UART_GPIOS);
+
+	/* Configure the uart clock */
+	uart_clock_config(uart_board_param.uart_gsbi,
+		uart_board_param.mnd_value.m_value,
+		uart_board_param.mnd_value.n_value,
+		uart_board_param.mnd_value.d_value,
+		0);
+
+	write32(GSBI_CTRL_REG(gsbi_base),
+		GSBI_PROTOCOL_CODE_I2C_UART << GSBI_CTRL_REG_PROTOCOL_CODE_S);
+	write32(MSM_BOOT_UART_DM_CSR(dm_base), UART_DM_CLK_RX_TX_BIT_RATE);
+
+	/* Initialize UART_DM */
+	msm_boot_uart_dm_init(dm_base);
+}
+
+/* for the benefit of non-console uart init */
+void ipq806x_uart_init(void)
+{
+	uart_init(0);
+}
+
+#if 0 /* Not used yet */
+uint32_t uartmem_getbaseaddr(void)
+{
+	return (uint32_t)uart_board_param.uart_dm_base;
+}
+#endif
+
+/**
+ * uart_tx_flush - transmits a string of data
+ * @s: string to transmit
+ */
+void uart_tx_flush(int idx)
+{
+	void *base = uart_board_param.uart_dm_base;
+
+	while (!(read32(MSM_BOOT_UART_DM_SR(base)) &
+		 MSM_BOOT_UART_DM_SR_TXEMT))
+		;
+}
+
+/**
+ * uart_can_rx_byte - checks if data available for reading
+ *
+ * Returns 1 if data available, 0 otherwise
+ */
+ #if 0 /* Not used yet */
+int uart_can_rx_byte(void)
+{
+	/* Return if data is already read */
+	if (valid_data)
+		return 1;
+
+	/* Read data from the FIFO */
+	if (msm_boot_uart_dm_read(&word, &valid_data, 0) !=
+	    MSM_BOOT_UART_DM_E_SUCCESS)
+		return 0;
+
+	return 1;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_DRIVERS_UART)
+/**
+ * ipq806x_serial_getc - reads a character
+ *
+ * Returns the character read from serial port.
+ */
+uint8_t uart_rx_byte(int idx)
+{
+	uint8_t byte;
+
+#if 0 /* Not used yet */
+	while (!uart_can_rx_byte())
+		;	/* wait for incoming data */
+#endif
+	byte = (uint8_t)(word & 0xff);
+	word = word >> 8;
+	valid_data--;
+
+	return byte;
+}
+#endif
+
+#ifndef __PRE_RAM__
+/* TODO: Implement function */
+void uart_fill_lb(void *data)
+{
+}
+#endif
diff --git a/src/soc/qualcomm/ipq40xx/usb.c b/src/soc/qualcomm/ipq40xx/usb.c
new file mode 100644
index 0000000..b48f5e2
--- /dev/null
+++ b/src/soc/qualcomm/ipq40xx/usb.c
@@ -0,0 +1,226 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 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.
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <delay.h>
+#include <soc/clock.h>
+#include <soc/iomap.h>
+#include <soc/usb.h>
+
+#define CRPORT_TX_OVRD_DRV_LO	0x1002
+#define CRPORT_RX_OVRD_IN_HI	0x1006
+#define CRPORT_TX_ALT_BLOCK	0x102d
+
+static u32 * const tcsr_usb_sel = (void *)0x1a4000b0;
+
+struct usb_qc_phy {
+	u32 ipcat;
+	u32 ctrl;
+	u32 general_cfg;
+	u32 ram1;
+	u32 hs_phy_ctrl;
+	u32 param_ovrd;
+	u32 chrg_det_ctrl;
+	u32 chrg_det_output;
+	u32 alt_irq_en;
+	u32 hs_phy_irq_stat;
+	u32 cgctl;
+	u32 dbg_bus;
+	u32 ss_phy_ctrl;
+	u32 ss_phy_param1;
+	u32 ss_phy_param2;
+	u32 crport_data_in;
+	u32 crport_data_out;
+	u32 crport_cap_addr;
+	u32 crport_cap_data;
+	u32 crport_ack_read;
+	u32 crport_ack_write;
+};
+check_member(usb_qc_phy, crport_ack_write, 0x50);
+
+static struct usb_qc_phy * const usb_host1_phy = (void *)USB_HOST1_PHY_BASE;
+static struct usb_qc_phy * const usb_host2_phy = (void *)USB_HOST2_PHY_BASE;
+
+struct usb_dwc3 {
+	u32 sbuscfg0;
+	u32 sbuscfg1;
+	u32 txthrcfg;
+	u32 rxthrcfg;
+	u32 ctl;
+	u32 evten;
+	u32 sts;
+	u8 reserved0[4];
+	u32 snpsid;
+	u32 gpio;
+	u32 uid;
+	u32 uctl;
+	u64 buserraddr;
+	u64 prtbimap;
+	u8 reserved1[32];
+	u32 dbgfifospace;
+	u32 dbgltssm;
+	u32 dbglnmcc;
+	u32 dbgbmu;
+	u32 dbglspmux;
+	u32 dbglsp;
+	u32 dbgepinfo0;
+	u32 dbgepinfo1;
+	u64 prtbimap_hs;
+	u64 prtbimap_fs;
+	u8 reserved2[112];
+	u32 usb2phycfg;
+	u8 reserved3[60];
+	u32 usb2i2cctl;
+	u8 reserved4[60];
+	u32 usb2phyacc;
+	u8 reserved5[60];
+	u32 usb3pipectl;
+	u8 reserved6[60];
+};
+check_member(usb_dwc3, usb3pipectl, 0x1c0);
+
+static struct usb_dwc3 * const usb_host1_dwc3 = (void *)USB_HOST1_DWC3_BASE;
+static struct usb_dwc3 * const usb_host2_dwc3 = (void *)USB_HOST2_DWC3_BASE;
+
+static void setup_dwc3(struct usb_dwc3 *dwc3)
+{
+	write32(&dwc3->usb3pipectl,
+		0x1 << 31 |	/* assert PHY soft reset */
+		0x1 << 25 |	/* (default) U1/U2 exit fail -> recovery? */
+		0x1 << 24 |	/* (default) activate PHY low power states */
+		0x1 << 19 |	/* (default) PHY low power delay value */
+		0x1 << 18 |	/* (default) activate PHY low power delay */
+		0x1 <<  1 |	/* (default) Tx deemphasis value */
+		0x1 <<  0);	/* (default) elastic buffer mode */
+
+	write32(&dwc3->usb2phycfg,
+		0x1 << 31 |	/* assert PHY soft reset */
+		0x9 << 10 |	/* (default) PHY clock turnaround 8-bit UTMI+ */
+		0x1 <<  8 |	/* (default) enable PHY sleep in L1 */
+		0x1 <<  6);	/* (default) enable PHY suspend */
+
+	write32(&dwc3->ctl,
+		0x2 << 19 |	/* (default) suspend clock scaling */
+		0x1 << 16 |	/* retry SS three times before HS downgrade */
+		0x1 << 12 |	/* port capability HOST */
+		0x1 << 11 |	/* assert core soft reset */
+		0x1 << 10 |	/* (default) sync ITP to refclk */
+		0x1 <<  2);	/* U2 exit after 8us LFPS (instead of 248ns) */
+
+	write32(&dwc3->uctl,
+		0x32 << 22 |	/* (default) reference clock period in ns */
+		 0x1 << 15 |	/* (default) XHCI compliant device addressing */
+		0x10 << 0); 	/* (default) devices time out after 32us */
+
+	udelay(5);
+
+	clrbits_le32(&dwc3->ctl, 0x1 << 11);	/* deassert core soft reset */
+	clrbits_le32(&dwc3->usb2phycfg, 0x1 << 31);	/* PHY soft reset */
+	clrbits_le32(&dwc3->usb3pipectl, 0x1 << 31);	/* PHY soft reset */
+}
+
+static void setup_phy(struct usb_qc_phy *phy)
+{
+	write32(&phy->ss_phy_ctrl,
+		0x1 << 24 |	/* Indicate VBUS power present */
+		0x1 <<  8 |	/* Enable USB3 ref clock to prescaler */
+		0x1 <<  7 |	/* assert SS PHY reset */
+		0x19 << 0);	/* (default) reference clock multiplier */
+
+	write32(&phy->hs_phy_ctrl,
+		0x1 << 26 |	/* (default) unclamp DPSE/DMSE VLS */
+		0x1 << 25 |	/* (default) select freeclk for utmi_clk */
+		0x1 << 24 |	/* (default) unclamp DMSE VLS */
+		0x1 << 21 |	/* (default) enable UTMI clock */
+		0x1 << 20 |	/* set OTG VBUS as valid */
+		0x1 << 18 |	/* use ref clock from core */
+		0x1 << 17 |	/* (default) unclamp DPSE VLS */
+		0x1 << 11 |	/* force xo/bias/pll to stay on in suspend */
+		0x1 <<  9 | 	/* (default) unclamp IDHV */
+		0x1 <<  8 |	/* (default) unclamp VLS (again???) */
+		0x1 <<  7 |	/* (default) unclamp HV VLS */
+		0x7 <<  4 |	/* select frequency (no idea which one) */
+		0x1 <<  1);	/* (default) "retention enable" */
+
+	write32(&phy->ss_phy_param1,
+		0x6e << 20 |	/* full TX swing amplitude */
+		0x20 << 14 |	/* (default) 6dB TX deemphasis */
+		0x17 <<  8 |	/* 3.5dB TX deemphasis */
+		 0x9 <<  3);	/* (default) LoS detector level */
+
+	write32(&phy->general_cfg, 0x1 << 2);	/* set XHCI 1.00 compliance */
+
+	udelay(5);
+	clrbits_le32(&phy->ss_phy_ctrl, 0x1 << 7); /* deassert SS PHY reset */
+}
+
+static void crport_handshake(void *capture_reg, void *acknowledge_bit, u32 data)
+{
+	int usec = 100;
+
+	if (capture_reg)
+		write32(capture_reg, data);
+
+	write32(acknowledge_bit, 0x1 << 0);
+	while (read32(acknowledge_bit) && --usec)
+		udelay(1);
+
+	if (!usec)
+		printk(BIOS_ERR, "CRPORT handshake timed out (0x%08x)\n", data);
+}
+
+static void crport_write(struct usb_qc_phy *phy, u16 addr, u16 data)
+{
+	crport_handshake(&phy->crport_data_in, &phy->crport_cap_addr, addr);
+	crport_handshake(&phy->crport_data_in, &phy->crport_cap_data, data);
+	crport_handshake(NULL, &phy->crport_ack_write, 0);
+}
+
+static void tune_phy(struct usb_qc_phy *phy)
+{
+	crport_write(phy, CRPORT_RX_OVRD_IN_HI,
+		      0x1 << 11 |	/* Set RX_EQ override? */
+		      0x4 <<  8 |	/* Set RX_EQ to 4? */
+		      0x1 <<  7);	/* Enable RX_EQ override */
+	crport_write(phy, CRPORT_TX_OVRD_DRV_LO,
+		      0x1 << 14 |	/* Enable amplitude (override?) */
+		     0x17 <<  7 |	/* Set TX deemphasis to 23 */
+		     0x6e <<  0);	/* Set amplitude to 110 */
+	crport_write(phy, CRPORT_TX_ALT_BLOCK,
+		      0x1 <<  7);	/* ALT block? ("partial RX reset") */
+}
+
+void setup_usb_host1(void)
+{
+	printk(BIOS_INFO, "Setting up USB HOST1 controller...\n");
+	setbits_le32(tcsr_usb_sel, 1 << 0);	/* Select DWC3 controller */
+	setup_phy(usb_host1_phy);
+	setup_dwc3(usb_host1_dwc3);
+	tune_phy(usb_host1_phy);
+}
+
+void setup_usb_host2(void)
+{
+	printk(BIOS_INFO, "Setting up USB HOST2 controller...\n");
+	setbits_le32(tcsr_usb_sel, 1 << 1);	/* Select DWC3 controller */
+	setup_phy(usb_host2_phy);
+	setup_dwc3(usb_host2_dwc3);
+	tune_phy(usb_host2_phy);
+}



More information about the coreboot-gerrit mailing list