Ronald G. Minnich ([email protected]) just uploaded a new patch set to gerrit, 
which you can find at http://review.coreboot.org/2142

-gerrit

commit d705de651e3b4c1c1925cf2e202e0c74b7c2eada
Author: David Hendricks <[email protected]>
Date:   Fri Jan 11 15:31:56 2013 -0800

    WIP: first attempt at porting SPI driver into bootblock
    
    ** do not submit **
    
    This is just a lame attempt at copying the necessary code into
    snow's bootblock so that we can copy SPI content into SRAM.
    
    Change-Id: I2a33605504abecee5ed2689400cf6c555da3f2c3
    Signed-off-by: David Hendricks <[email protected]>
---
 src/arch/armv7/Makefile.inc            |   2 +-
 src/arch/armv7/bootblock_simple.c      |   1 +
 src/arch/armv7/include/arch/cbfs.h     |  62 ++++-
 src/cpu/samsung/exynos5250/bootblock.c |  16 ++
 src/cpu/samsung/exynos5250/clk.h       |   2 +
 src/mainboard/google/snow/Kconfig      |   4 +
 src/mainboard/google/snow/bootblock.c  | 431 +++++++++++++++++++++++++++++++++
 7 files changed, 513 insertions(+), 5 deletions(-)

diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc
index cc30633..1dfd3ca 100644
--- a/src/arch/armv7/Makefile.inc
+++ b/src/arch/armv7/Makefile.inc
@@ -257,7 +257,7 @@ $(objcbfs)/bootblock.debug: $(objgenerated)/bootblock.o 
$(objgenerated)/bootbloc
 ifeq ($(CONFIG_COMPILER_LLVM_CLANG),y)
        $(LD) -m armelf_linux_eabi -static -o [email protected] -L$(obj) $< -T 
$(objgenerated)/bootblock.ld
 else
-       $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T 
$(objgenerated)/bootblock.ld $<
+       $(CC) -nostdlib -nostartfiles -static -o $@ -L$(obj) -T 
$(objgenerated)/bootblock.ld -Wl,--start-group $< $(LIBGCC_FILE_NAME) 
-Wl,--end-group
 endif
 
 
################################################################################
diff --git a/src/arch/armv7/bootblock_simple.c 
b/src/arch/armv7/bootblock_simple.c
index c10ee1f..6897e15 100644
--- a/src/arch/armv7/bootblock_simple.c
+++ b/src/arch/armv7/bootblock_simple.c
@@ -40,6 +40,7 @@ void main(unsigned long bist)
 
        if (boot_cpu()) {
                bootblock_mainboard_init();
+               bootblock_cpu_init();
        }
 
        entry = findstage(target1);
diff --git a/src/arch/armv7/include/arch/cbfs.h 
b/src/arch/armv7/include/arch/cbfs.h
index afcfa6a..5ade67b 100644
--- a/src/arch/armv7/include/arch/cbfs.h
+++ b/src/arch/armv7/include/arch/cbfs.h
@@ -31,23 +31,71 @@ static int cbfs_check_magic(struct cbfs_file *file)
        return !strcmp(file->magic, CBFS_FILE_MAGIC) ? 1 : 0;
 }
 
+#if 0
 static unsigned long findstage(const char* target)
 {
        unsigned long offset;
        void *ptr = (void *)*((unsigned long *) CBFS_HEADPTR_ADDR);
        struct cbfs_header *header = (struct cbfs_header *) ptr;
+       volatile unsigned long *addr = (unsigned long *)0x1004330c;
        // if (ntohl(header->magic) != CBFS_HEADER_MAGIC)
        //      printk(BIOS_ERR, "ERROR: No valid CBFS header found!\n");
 
        /* FIXME(dhendrix,reinauer): should this be ntohl(header->offset)? */
-       offset = 0 - ntohl(header->romsize) + ntohl(header->offset);
+       offset = ntohl(header->offset);
        int align = ntohl(header->align);
        while(1) {
                struct cbfs_file *file = (struct cbfs_file *) offset;
-               if (!cbfs_check_magic(file))
+               if (!cbfs_check_magic(file)) {
                        return 0;
-               if (!strcmp(CBFS_NAME(file), target))
+               }
+               if (!strcmp(CBFS_NAME(file), target)) {
                        return (unsigned long)CBFS_SUBHEADER(file);
+               }
+
+               int flen = ntohl(file->len);
+               int foffset = ntohl(file->offset);
+               unsigned long oldoffset = offset;
+               offset = ALIGN(offset + foffset + flen, align);
+               if (offset <= oldoffset)
+                       return 0;
+               /* FIXME(dhendrix,reinauer): calculate the limit correctly */
+               if (offset < ntohl(header->offset) + ntohl(header->romsize))
+                       return 0;
+       }
+#if 0
+       /* FIXME: for debugging */
+       volatile unsigned long *addr = (unsigned long *)0x1004330c;
+       *addr |= 0x100;
+#endif
+       while(1);       /* FIXME: for debugging */
+}
+#endif
+
+static unsigned long findstage(const char* target)
+{
+       unsigned long offset;
+       /* FIXME: CBFS_HEADPTR_ADDR is completely wrong. */
+       void *ptr = (void *)*((unsigned long *) CBFS_HEADPTR_ADDR);
+       struct cbfs_header *header = (struct cbfs_header *) ptr;
+       volatile unsigned long *addr = (unsigned long *)0x1004330c;
+       // if (ntohl(header->magic) != CBFS_HEADER_MAGIC)
+       //      printk(BIOS_ERR, "ERROR: No valid CBFS header found!\n");
+
+       *addr |= 0x100;
+       while(1);       /* FIXME: for debugging */
+       /* FIXME(dhendrix,reinauer): should this be ntohl(header->offset)? */
+       offset = ntohl(header->offset);
+       int align = ntohl(header->align);
+       while(1) {
+               struct cbfs_file *file = (struct cbfs_file *) offset;
+               if (!cbfs_check_magic(file)) {
+                       return 0;
+               }
+               if (!strcmp(CBFS_NAME(file), target)) {
+                       return (unsigned long)CBFS_SUBHEADER(file);
+               }
+
                int flen = ntohl(file->len);
                int foffset = ntohl(file->offset);
                unsigned long oldoffset = offset;
@@ -55,9 +103,15 @@ static unsigned long findstage(const char* target)
                if (offset <= oldoffset)
                        return 0;
                /* FIXME(dhendrix,reinauer): calculate the limit correctly */
-               if (offset < 0xFFFFFFFF - ntohl(header->romsize))
+               if (offset < ntohl(header->offset) + ntohl(header->romsize))
                        return 0;
        }
+#if 0
+       /* FIXME: for debugging */
+       volatile unsigned long *addr = (unsigned long *)0x1004330c;
+       *addr |= 0x100;
+       while(1);       /* FIXME: for debugging */
+#endif
 }
 
 static inline void call(unsigned long addr)
diff --git a/src/cpu/samsung/exynos5250/bootblock.c 
b/src/cpu/samsung/exynos5250/bootblock.c
index 58d0919..46b52b9 100644
--- a/src/cpu/samsung/exynos5250/bootblock.c
+++ b/src/cpu/samsung/exynos5250/bootblock.c
@@ -17,6 +17,22 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#if 0
+/*
+ * Set/clear program flow prediction and return the previous state.
+ */
+static int config_branch_prediction(int set_cr_z)
+{
+       unsigned int cr;
+
+       /* System Control Register: 11th bit Z Branch prediction enable */
+       cr = get_cr();
+       set_cr(set_cr_z ? cr | CR_Z : cr & ~CR_Z);
+
+       return cr & CR_Z;
+}
+#endif
+
 void bootblock_cpu_init(void);
 void bootblock_cpu_init(void)
 {
diff --git a/src/cpu/samsung/exynos5250/clk.h b/src/cpu/samsung/exynos5250/clk.h
index 2de949a..762dbf3 100644
--- a/src/cpu/samsung/exynos5250/clk.h
+++ b/src/cpu/samsung/exynos5250/clk.h
@@ -25,6 +25,8 @@
 #include <cpu/samsung/exynos5-common/clk.h>
 #include <cpu/samsung/exynos5250/pinmux.h>
 
+enum periph_id;
+
 /*
  * Set mshci controller instances clock drivder
  *
diff --git a/src/mainboard/google/snow/Kconfig 
b/src/mainboard/google/snow/Kconfig
index 21cdfa5..8f41c64 100644
--- a/src/mainboard/google/snow/Kconfig
+++ b/src/mainboard/google/snow/Kconfig
@@ -56,6 +56,10 @@ config MAINBOARD_VENDOR
        string
        default "Samsung"
 
+config BOOTBLOCK_MAINBOARD_INIT
+       string
+       default "mainboard/google/snow/bootblock.c"
+
 # SPL (second-phase loader) stuff
 config SPL_TEXT_BASE
        hex
diff --git a/src/mainboard/google/snow/bootblock.c 
b/src/mainboard/google/snow/bootblock.c
new file mode 100644
index 0000000..09f6f74
--- /dev/null
+++ b/src/mainboard/google/snow/bootblock.c
@@ -0,0 +1,431 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 The ChromiumOS Authors.  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <types.h>
+#include <arch/io.h>
+#include "cpu/samsung/exynos5250/clk.h"
+#include "cpu/samsung/exynos5250/cpu.h"
+#include "cpu/samsung/exynos5250/gpio.h"
+#include "cpu/samsung/s5p-common/gpio.h"
+#include "cpu/samsung/exynos5-common/spi.h"
+
+#define EXYNOS5_CLOCK_BASE             0x10010000
+
+/* FIXME(dhendrix): Can we move this SPI stuff elsewhere? */
+static void spi_rx_tx(struct exynos_spi *regs, int todo,
+                       void *dinp, void const *doutp, int i)
+{
+       unsigned int *rxp = (unsigned int *)(dinp + (i * (32 * 1024)));
+       int rx_lvl, tx_lvl;
+       unsigned int out_bytes, in_bytes;
+
+       out_bytes = in_bytes = todo;
+       setbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
+
+       while (in_bytes) {
+               uint32_t spi_sts;
+               int temp;
+
+               spi_sts = readl(&regs->spi_sts);
+               rx_lvl = ((spi_sts >> 15) & 0x7f);
+               tx_lvl = ((spi_sts >> 6) & 0x7f);
+               while (tx_lvl < 32 && out_bytes) {
+                       temp = 0xffffffff;
+                       writel(temp, &regs->tx_data);
+                       out_bytes -= 4;
+                       tx_lvl += 4;
+               }
+               while (rx_lvl >= 4 && in_bytes) {
+                       temp = readl(&regs->rx_data);
+                       if (rxp)
+                               *rxp++ = temp;
+                       in_bytes -= 4;
+                       rx_lvl -= 4;
+               }
+       }
+}
+
+#if 0
+void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor)
+{
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)samsung_get_base_clock();
+       unsigned shift;
+       unsigned mask = 0xff;
+       u32 *reg;
+
+       /*
+        * For now we only handle a very small subset of peipherals here.
+        * Others will need to (and do) mangle the clock registers
+        * themselves, At some point it is hoped that this function can work
+        * from a table or calculated register offset / mask. For now this
+        * is at least better than spreading clock control code around
+        * U-Boot.
+        */
+       switch (periph_id) {
+       case PERIPH_ID_SPI0:
+               reg = &clk->div_peric1;
+               shift = 8;
+               break;
+       case PERIPH_ID_SPI1:
+               reg = &clk->div_peric1;
+               shift = 24;
+               break;
+       case PERIPH_ID_SPI2:
+               reg = &clk->div_peric2;
+               shift = 8;
+               break;
+       case PERIPH_ID_SPI3:
+               reg = &clk->sclk_div_isp;
+               shift = 4;
+               break;
+       case PERIPH_ID_SPI4:
+               reg = &clk->sclk_div_isp;
+               shift = 16;
+               break;
+       default:
+               debug("%s: Unsupported peripheral ID %d\n", __func__,
+                     periph_id);
+               return;
+       }
+}
+#endif
+void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor)
+{
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+       unsigned shift;
+       unsigned mask = 0xff;
+       u32 *reg;
+
+       reg = &clk->div_peric1;
+       shift = 24;
+       clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift);
+}
+
+#if 0
+void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor)
+{
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)samsung_get_base_clock();
+       unsigned shift;
+       unsigned mask = 0xff;
+       u32 *reg;
+
+       switch (periph_id) {
+       case PERIPH_ID_SPI0:
+               reg = &clk->div_peric1;
+               shift = 0;
+               break;
+       case PERIPH_ID_SPI1:
+               reg = &clk->div_peric1;
+               shift = 16;
+               break;
+       case PERIPH_ID_SPI2:
+               reg = &clk->div_peric2;
+               shift = 0;
+               break;
+       case PERIPH_ID_SPI3:
+               reg = &clk->sclk_div_isp;
+               shift = 0;
+               break;
+       case PERIPH_ID_SPI4:
+               reg = &clk->sclk_div_isp;
+               shift = 12;
+               break;
+       default:
+               debug("%s: Unsupported peripheral ID %d\n", __func__,
+                     periph_id);
+               return;
+       }
+}
+#endif
+void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor)
+{
+       struct exynos5_clock *clk =
+               (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+       unsigned shift;
+       unsigned mask = 0xff;
+       u32 *reg;
+
+       reg = &clk->div_peric1;
+       shift = 16;
+       clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift);
+}
+
+/**
+ * Linearly searches for the most accurate main and fine stage clock scalars
+ * (divisors) for a specified target frequency and scalar bit sizes by checking
+ * all multiples of main_scalar_bits values. Will always return scalars up to 
or
+ * slower than target.
+ *
+ * @param main_scalar_bits     Number of main scalar bits, must be > 0 and < 32
+ * @param fine_scalar_bits     Number of fine scalar bits, must be > 0 and < 32
+ * @param input_freq           Clock frequency to be scaled in Hz
+ * @param target_freq          Desired clock frequency in Hz
+ * @param best_fine_scalar     Pointer to store the fine stage divisor
+ *
+ * @return best_main_scalar    Main scalar for desired frequency or -1 if none
+ * found
+ */
+static int clock_calc_best_scalar(unsigned int main_scaler_bits,
+       unsigned int fine_scalar_bits, unsigned int input_rate,
+       unsigned int target_rate, unsigned int *best_fine_scalar)
+{
+       int i;
+       int best_main_scalar = -1;
+       unsigned int best_error = target_rate;
+       const unsigned int cap = (1 << fine_scalar_bits) - 1;
+       const unsigned int loops = 1 << main_scaler_bits;
+
+#if 0
+       debug("Input Rate is %u, Target is %u, Cap is %u\n", input_rate,
+                       target_rate, cap);
+
+       assert(best_fine_scalar != NULL);
+       assert(main_scaler_bits <= fine_scalar_bits);
+#endif
+
+       *best_fine_scalar = 1;
+
+       if (input_rate == 0 || target_rate == 0)
+               return -1;
+
+       if (target_rate >= input_rate)
+               return 1;
+
+       for (i = 1; i <= loops; i++) {
+               const unsigned int effective_div = MAX(MIN(input_rate / i /
+                                                       target_rate, cap), 1);
+               const unsigned int effective_rate = input_rate / i /
+                                                       effective_div;
+               const int error = target_rate - effective_rate;
+
+#if 0
+               debug("%d|effdiv:%u, effrate:%u, error:%d\n", i, effective_div,
+                               effective_rate, error);
+#endif
+
+               if (error >= 0 && error <= best_error) {
+                       best_error = error;
+                       best_main_scalar = i;
+                       *best_fine_scalar = effective_div;
+               }
+       }
+
+       return best_main_scalar;
+}
+
+#if 0
+int clock_set_rate(enum periph_id periph_id, unsigned int rate)
+{
+       int main;
+       unsigned int fine;
+
+       switch (periph_id) {
+       case PERIPH_ID_SPI0:
+       case PERIPH_ID_SPI1:
+       case PERIPH_ID_SPI2:
+       case PERIPH_ID_SPI3:
+       case PERIPH_ID_SPI4:
+               main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
+               if (main < 0) {
+                       debug("%s: Cannot set clock rate for periph %d",
+                                       __func__, periph_id);
+                       return -1;
+               }
+               clock_ll_set_ratio(periph_id, main - 1);
+               clock_ll_set_pre_ratio(periph_id, fine - 1);
+               break;
+       default:
+               debug("%s: Unsupported peripheral ID %d\n", __func__,
+                     periph_id);
+               return -1;
+       }
+       main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
+       if (main < 0) {
+               debug("%s: Cannot set clock rate for periph %d",
+                               __func__, periph_id);
+               return -1;
+       }
+       clock_ll_set_ratio(PERIPH_ID_SPI1, main - 1);
+       clock_ll_set_pre_ratio(PERIPH_ID_SPI1, fine - 1);
+
+       return 0;
+}
+#endif
+int clock_set_rate(enum periph_id periph_id, unsigned int rate)
+{
+       int main;
+       unsigned int fine;
+
+       main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
+       if (main < 0) {
+//             debug("%s: Cannot set clock rate for periph %d",
+//                             __func__, periph_id);
+               return -1;
+       }
+       clock_ll_set_ratio(-1, main - 1);
+       clock_ll_set_pre_ratio(-1, fine - 1);
+
+       return 0;
+}
+
+struct gpio_info {
+       unsigned int reg_addr;  /* Address of register for this part */
+       unsigned int max_gpio;  /* Maximum GPIO in this part */
+};
+
+static const struct gpio_info gpio_data[EXYNOS_GPIO_NUM_PARTS] = {
+       { EXYNOS5_GPIO_PART1_BASE, GPIO_MAX_PORT_PART_1 },
+       { EXYNOS5_GPIO_PART2_BASE, GPIO_MAX_PORT_PART_2 },
+       { EXYNOS5_GPIO_PART3_BASE, GPIO_MAX_PORT_PART_3 },
+       { EXYNOS5_GPIO_PART4_BASE, GPIO_MAX_PORT_PART_4 },
+       { EXYNOS5_GPIO_PART5_BASE, GPIO_MAX_PORT_PART_5 },
+       { EXYNOS5_GPIO_PART6_BASE, GPIO_MAX_PORT },
+};
+
+static struct s5p_gpio_bank *gpio_get_bank(unsigned int gpio)
+{
+       const struct gpio_info *data;
+       unsigned int upto;
+       int i;
+
+       for (i = upto = 0, data = gpio_data; i < EXYNOS_GPIO_NUM_PARTS;
+                       i++, upto = data->max_gpio, data++) {
+               if (gpio < data->max_gpio) {
+                       struct s5p_gpio_bank *bank;
+
+                       bank = (struct s5p_gpio_bank *)data->reg_addr;
+                       bank += (gpio - upto) / GPIO_PER_BANK;
+                       return bank;
+               }
+       }
+
+#ifndef CONFIG_SPL_BUILD
+       assert(gpio < GPIO_MAX_PORT);   /* ...which it will not be */
+#endif
+       return NULL;
+}
+
+#define CON_MASK(x)            (0xf << ((x) << 2))
+#define CON_SFR(x, v)          ((v) << ((x) << 2))
+
+/* This macro gets gpio pin offset from 0..7 */
+#define GPIO_BIT(x)     ((x) & 0x7)
+
+void gpio_cfg_pin(int gpio, int cfg)
+{
+       unsigned int value;
+       struct s5p_gpio_bank *bank = gpio_get_bank(gpio);
+
+       value = readl(&bank->con);
+       value &= ~CON_MASK(GPIO_BIT(gpio));
+       value |= CON_SFR(GPIO_BIT(gpio), cfg);
+       writel(value, &bank->con);
+}
+
+//static void exynos_spi_copy(unsigned int uboot_size)
+static void copy_romstage(uint32_t spi_addr, uint32_t sram_addr, unsigned int 
len)
+{
+       int upto, todo;
+       int i;
+//     struct exynos_spi *regs = (struct exynos_spi *)samsung_get_base_spi1();
+       struct exynos_spi *regs = (struct exynos_spi *)0x12d30000;
+
+       clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */
+       /* set the spi1 GPIO */
+//     exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE);
+       gpio_cfg_pin(GPIO_A24, 0x2);
+       gpio_cfg_pin(GPIO_A25, 0x2);
+       gpio_cfg_pin(GPIO_A26, 0x2);
+       gpio_cfg_pin(GPIO_A27, 0x2);
+
+       /* set pktcnt and enable it */
+       writel(4 | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
+       /* set FB_CLK_SEL */
+       writel(SPI_FB_DELAY_180, &regs->fb_clk);
+       /* set CH_WIDTH and BUS_WIDTH as word */
+       setbits_le32(&regs->mode_cfg, SPI_MODE_CH_WIDTH_WORD |
+                                       SPI_MODE_BUS_WIDTH_WORD);
+       clrbits_le32(&regs->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */
+
+       /* clear rx and tx channel if set priveously */
+       clrbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON);
+
+       setbits_le32(&regs->swap_cfg, SPI_RX_SWAP_EN |
+               SPI_RX_BYTE_SWAP |
+               SPI_RX_HWORD_SWAP);
+
+       /* do a soft reset */
+       setbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+
+       /* now set rx and tx channel ON */
+       setbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN);
+       clrbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */
+
+       /* Send read instruction (0x3h) followed by a 24 bit addr */
+       writel((SF_READ_DATA_CMD << 24) | spi_addr, &regs->tx_data);
+
+       /* waiting for TX done */
+       while (!(readl(&regs->spi_sts) & SPI_ST_TX_DONE));
+
+       for (upto = 0, i = 0; upto < len; upto += todo, i++) {
+               todo = MIN(len - upto, (1 << 15));
+               spi_rx_tx(regs, todo, (void *)(sram_addr),
+                                       (void *)(spi_addr), i);
+       }
+
+       setbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */
+
+       /*
+        * Let put controller mode to BYTE as
+        * SPI driver does not support WORD mode yet
+        */
+       clrbits_le32(&regs->mode_cfg, SPI_MODE_CH_WIDTH_WORD |
+                                       SPI_MODE_BUS_WIDTH_WORD);
+       writel(0, &regs->swap_cfg);
+
+       /*
+        * Flush spi tx, rx fifos and reset the SPI controller
+        * and clear rx/tx channel
+        */
+       clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
+       clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+       clrbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
+}
+
+void bootblock_mainboard_init(void);
+void bootblock_mainboard_init(void)
+{
+       /* Copy romstage data from SPI ROM to SRAM */
+       /* FIXME: magic constant... */
+       copy_romstage(0x2000, CONFIG_ROMSTAGE_BASE, CONFIG_XIP_ROM_SIZE);
+       
+#if 0
+       /* FIXME: for debugging... */
+       volatile unsigned long *addr = (unsigned long *)0x1004330c;
+       *addr |= 0x100;
+       while (1);
+#endif
+}

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to