[U-Boot] [PATCH v3] Marvell Kirkwood family SOC support

Jean-Christophe PLAGNIOL-VILLARD plagnioj at jcrosoft.com
Thu Apr 23 18:21:35 CEST 2009


On 07:16 Thu 23 Apr     , Prafulla Wadaskar wrote:
> Kirkwood family controllers are highly integrated SOCs
> based on Feroceon-88FR131/Sheeva-88SV131 cpu core.
> 
> SOC versions supported:-
> 1) 88F6281-A0       define CONFIG_KW88F6281_A0
> 2) 88F6192-A0       define CONFIG_KW88F6192_A0
> 
> Other supported features:-
> 1) get_random_hex() function
> 2) SPI port controller driver
> 3) PCI Express port initialization
> 
> Contributors:
> Yotam Admon <yotam at marvell.com>
> Michael Blostein <michaelbl at marvell.com
> 
> Reviewed-by: Ronen Shitrit <rshitrit at marvell.com>
> Signed-off-by: Prafulla Wadaskar <prafulla at marvell.com>
a general comment please sue tab for indentation not space
> ---
> Change log:
> v2: crated arch-kirkwood and moved some header files there
> renamed and moved spi.c to drivers/spi/
> renamed and moved serial.c to drivers/serial/
> doimage utility removed
> soc_init.S renamed as lowlevel_init.S
> debug prints removed
> 
> v3: lowlevel_init.S converted to lowlevel_init.c
> removed BITxx macros, removed entire assembly code
> Added CONFIG_ARCH_LOWLEVE_INIT support for arm926ejs core
> updated as per review comments for v2
> 
>  board/Marvell/include/core.h              |    4 +
>  cpu/arm926ejs/kirkwood/Makefile           |   49 +++++
>  cpu/arm926ejs/kirkwood/config.mk          |   25 +++
>  cpu/arm926ejs/kirkwood/dram.c             |   57 ++++++
>  cpu/arm926ejs/kirkwood/kwcore.c           |  304 +++++++++++++++++++++++++++++
>  cpu/arm926ejs/kirkwood/kwcore.h           |  112 +++++++++++
>  cpu/arm926ejs/kirkwood/lowlevel_init.c    |   93 +++++++++
>  cpu/arm926ejs/kirkwood/timer.c            |  165 ++++++++++++++++
>  cpu/arm926ejs/start.S                     |    7 +-
>  drivers/serial/kirkwood_serial.c          |  187 ++++++++++++++++++
>  drivers/spi/Makefile                      |    1 +
>  drivers/spi/kirkwood_spi.c                |  199 +++++++++++++++++++
>  include/asm-arm/arch-kirkwood/kirkwood.h  |  140 +++++++++++++
>  include/asm-arm/arch-kirkwood/kw88f6192.h |   37 ++++
>  include/asm-arm/arch-kirkwood/kw88f6281.h |   37 ++++
> +       } else
> +               temp &= ~1<<4;
> +       writel(KW_REG_CPU_L2_CONFIG, temp);
> +
> +       /* L2Cache settings */
> +       asm("mrc p15, 1, %0, c15, c1, 0":"=r"(temp));
> +
> +       /* Disable L2C pre fetch - Set bit 24 */
> +       env = getenv("disL2Prefetch");
sorry I've forget about it precedently btw please add a doc about all this env
var
> +       if (env && ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0)))
> +               temp &= ~1<<24;
> +       else
> +               temp |= 1<<24;
> +
> +       /* enable L2C - Set bit 22 */
> +       env = getenv("disL2Cache");
> +       if (!env || ((strcmp(env, "no") == 0) || (strcmp(env, "No") == 0)))
> +               temp |= 1<<22;
> +       else
> +               temp &= ~1<<22;
> +
> +       asm("mcr p15, 1, %0, c15, c1, 0": :"r"(temp));
please use set/get_cr

> +
> +       /* Enable i cache */
we have a cache management framework now
please take a look on the lib_arm/cache-cp15.c

> +       asm("mrc p15, 0, %0, c1, c0, 0":"=r"(temp));
> +       temp |= 1<<12;
> +       asm("mcr p15, 0, %0, c1, c0, 0": :"r"(temp));
> +       /* Change reset vector to address 0x0 */
> +       asm("mrc p15, 0, %0, c1, c0, 0":"=r"(temp));
> +       temp &= ~1<<13;
> +       asm("mcr p15, 0, %0, c1, c0, 0": :"r"(temp));
> +
> +       return (0);
> +}
> +
> diff --git a/cpu/arm926ejs/kirkwood/kwcore.h b/cpu/arm926ejs/kirkwood/kwcore.h
> new file mode 100644
> index 0000000..feec86b
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/kwcore.h
> +       asm volatile("mcr p15, 1, %0, c15, c1, 0        @ writefr exfr"
> +         : : "r" (val) : "cc");
> +       isb();
> +}
> +
> +/*
> + * Invalidate L2 Cache using co-proc instruction
> + */
> +static inline void invalidate_l2_cache(void)
we need to have the same api for l2_cache management so please add it in
include/asm-arm/cache.h 
> +{
> +       unsigned int val=0;
> +
> +       asm volatile("mcr p15, 1, %0, c15, c11, 0       @ invl l2 cache"
> +         : : "r" (val) : "cc");
> +       isb();
> +}
> +
> +/*
> + * functions
> + */
> +void reset_cpu(unsigned long ignored);
> +unsigned char get_random_hex(void);
> +unsigned int kw_sdram_bar(enum memory_bank bank);
> +unsigned int kw_sdram_bs(enum memory_bank bank);
> +int kw_window_ctrl_reg_init(void);
> +void kw_gpio_init(unsigned int gpp0_oe_val, unsigned int gpp1_oe_val,
> +                 unsigned int gpp0_oe, unsigned int gpp1_oe);
> +int kw_mpp_control_init(unsigned int mpp0_7, unsigned int mpp8_15,
> +                       unsigned int mpp16_23, unsigned int mpp24_31,
> +                       unsigned int mpp32_39, unsigned int mpp40_47,
> +                       unsigned int mpp48_55);
> +int kw_misc_init_r(void);
> +#endif /* __ASSEMBLY__ */
> +
> +#endif /* _KWCORE_H */
> diff --git a/cpu/arm926ejs/kirkwood/lowlevel_init.c b/cpu/arm926ejs/kirkwood/lowlevel_init.c
> new file mode 100644
> index 0000000..21bfc81
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/lowlevel_init.c
> @@ -0,0 +1,93 @@
> +/*
> + * (C) Copyright 2009
> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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 Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
I'm not a fan of c init but if you prefer ok
> +#include <config.h>
> +
> +void kw_cpu_if_pre_init(void)
> +{
> +       u32 reg;
> +
> +#ifdef CONFIG_KIRKWOOD_RGMII_PAD_1V8
> +       /*
> +        * Configures the I/O voltage of the pads connected to Egigabit
> +        * Ethernet interface to 1.8V
> +        * By defult it is set to 3.3V
> +        */
> +       reg = readl(KW_REG_MPP_OUT_DRV_REG);
> +       reg |= 1 << 7;
> +       writel(KW_REG_MPP_OUT_DRV_REG, &reg);
> +#endif
> +#ifdef CONFIG_KIRKWOOD_EGIGA_INIT
> +       /*
> +        * Set egiga port0/1 in normal functional mode
> +        * This is required becasue on kirkwood by default ports are in reset mode
> +        * OS egiga driver may not have provision to set them in normal mode
> +        * and if u-boot is build without network support, network may fail at OS level
> +        */
> +       reg = readl((KW_EGIGA0_BASE + 0x44c));  /* PORT_SERIAL_CONTROL1_REG */
> +       reg &= ~(1 << 4);       /* Clear PortReset Bit */
> +       writel((KW_EGIGA0_BASE + 0x44c), &reg); /* PORT_SERIAL_CONTROL1_REG */

> +        * so must be done prior to DDR operation
> +        */
> +       kw_cpu_if_pre_init();
> +}
> diff --git a/cpu/arm926ejs/kirkwood/timer.c b/cpu/arm926ejs/kirkwood/timer.c
> new file mode 100644
> index 0000000..c6e1a26
> --- /dev/null
> +++ b/cpu/arm926ejs/kirkwood/timer.c
> @@ -0,0 +1,165 @@
as I've ask for the ARM925T timer update please provice
the precision and resolution on you timer in the code
> +/*
> + * Copyright (C) Marvell International Ltd. and its affiliates
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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 Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +
> +#define UBOOT_CNTR     0       /* counter to use for uboot timer */
> +
> +/*
> + * ARM Timers Registers Map
> + */
> +#define CNTMR_CTRL_REG                 KW_REG_TMR_CTRL
> +#define CNTMR_RELOAD_REG(tmrnum)       (KW_REG_TMR_RELOAD + tmrnum*8)
please add a space before and after the '*'
and so on
> +#define CNTMR_VAL_REG(tmrnum)          (KW_REG_TMR_VAL + tmrnum*8)
> +
> +/*
> + * ARM Timers Control Register
> + * CPU_TIMERS_CTRL_REG (CTCR)
> + */
> +#define TIMER0_NUM                             0
> +#define TIMER1_NUM                             1
> +#define WATCHDOG_NUM                           2
> +
> +#define CTCR_ARM_TIMER_EN_OFFS(cntr)           (cntr * 2)
> +#define CTCR_ARM_TIMER_EN_MASK(cntr)           (1 << CTCR_ARM_TIMER_EN_OFFS)
> +#define CTCR_ARM_TIMER_EN(cntr)                        (1 << CTCR_ARM_TIMER_EN_OFFS(cntr))
> +#define CTCR_ARM_TIMER_DIS(cntr)               (0 << CTCR_ARM_TIMER_EN_OFFS(cntr))
> +
> +#define CTCR_ARM_TIMER_AUTO_OFFS(cntr) ((cntr * 2) + 1)
> +#define CTCR_ARM_TIMER_AUTO_MASK(cntr) 1<<1
> +#define CTCR_ARM_TIMER_AUTO_EN(cntr)   (1 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
> +#define CTCR_ARM_TIMER_AUTO_DIS(cntr)  (0 << CTCR_ARM_TIMER_AUTO_OFFS(cntr))
> +
> +/*
> + * ARM Timer\Watchdog Reload Register
> + * CNTMR_RELOAD_REG (TRR)
> + */
> +#define TRG_ARM_TIMER_REL_OFFS                 0
> +#define TRG_ARM_TIMER_REL_MASK                 0xffffffff
> +
> +/*
> + * ARM Timer\Watchdog Register
> + * CNTMR_VAL_REG (TVRG)
> + */
> +#define TVR_ARM_TIMER_OFFS                     0
> +#define TVR_ARM_TIMER_MASK                     0xffffffff
> +#define TVR_ARM_TIMER_MAX                      0xffffffff
> +#define TIMER_LOAD_VAL                                 0xffffffff
> +
> +/* This enumerator describe counters\watchdog numbers       */
> +typedef enum _kwCntmrID {
please no Uppercase
> +       TIMER0 = 0,
> +       TIMER1,
> +       WATCHDOG
> +} KW_CNTMR_ID;
> +
> +#define READ_TIMER     (readl(CNTMR_VAL_REG(UBOOT_CNTR))/(CONFIG_SYS_TCLK/1000))
please add a space before and after the '/'
> +static ulong timestamp;
> +static ulong lastdec;
> +
> +void reset_timer_masked(void)
> +{
> +       /* reset time */
> +       lastdec = READ_TIMER;
> +       timestamp = 0;
> +}
> +
> +ulong get_timer_masked(void)
> +{
> +       ulong now = READ_TIMER;
> +
> +       if (lastdec >= now) {
> +               /* normal mode */
> +               timestamp += lastdec - now;
> +       } else {
> +               /* we have an overflow ... */
> +               timestamp +=
> +                   lastdec + (TIMER_LOAD_VAL / (CONFIG_SYS_TCLK / 1000)) - now;
> +       }
> +       lastdec = now;
> +
> +       return timestamp;
> +}
> +
> +void reset_timer(void)
> +{
> +       reset_timer_masked();
> +}
> +
> +ulong get_timer(ulong base)
> +{
> +       return get_timer_masked() - base;
> +}
> +
> +void set_timer(ulong t)
> +{
> +       timestamp = t;
> +}
> +
> +void udelay(unsigned long usec)
> +{
> +       uint current;
> +       ulong delayticks;
> +
> +       current = readl(CNTMR_VAL_REG(UBOOT_CNTR));

> +}
> diff --git a/cpu/arm926ejs/start.S b/cpu/arm926ejs/start.S
> index ed4932a..520dcef 100644
> --- a/cpu/arm926ejs/start.S
> +++ b/cpu/arm926ejs/start.S
> @@ -201,7 +201,7 @@ _start_armboot:
>   *
>   *************************************************************************
>   */
> -#ifndef CONFIG_SKIP_LOWLEVEL_INIT
> +#if !defined (CONFIG_SKIP_LOWLEVEL_INIT) || defined (CONFIG_ARCH_LOWLEVEL_INIT)
we will call the ARCH_LOWLEVEL_INIT only if we do not skip the the LOWLEVEL INIT
>  cpu_init_crit:
>         /*
>          * flush v4 I/D caches
> @@ -224,7 +224,12 @@ cpu_init_crit:
>          * Go setup Memory and board specific bits prior to relocation.
>          */
>         mov     ip, lr          /* perserve link reg across call */
> +#ifdef CONFIG_ARCH_LOWLEVEL_INIT
> +       bl      arch_lowlevel_init      /* go setup arch specific init */
> +#endif /* CONFIG_ARCH_LOWLEVEL_INIT */
> +#ifndef CONFIG_SKIP_LOWLEVEL_INIT
>         bl      lowlevel_init   /* go setup pll,mux,memory */
> +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
>         mov     lr, ip          /* restore link */
>         mov     pc, lr          /* back to my caller */
>  #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
> diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
> index bb99a34..dd59ff8 100644
> --- a/drivers/serial/Makefile
> +++ b/drivers/serial/Makefile
> @@ -28,6 +28,7 @@ LIB   := $(obj)libserial.a
>  COBJS-$(CONFIG_ARM_DCC) += arm_dcc.o
>  COBJS-$(CONFIG_AT91RM9200_USART) += at91rm9200_usart.o
>  COBJS-$(CONFIG_ATMEL_USART) += atmel_usart.o
> +COBJS-$(CONFIG_KIRKWOOD) += kirkwood_serial.o
please use the same CONFIG_ as the kernel
>  COBJS-$(CONFIG_MCFUART) += mcfuart.o
>  COBJS-$(CONFIG_NS9750_UART) += ns9750_serial.o
>  COBJS-$(CONFIG_SYS_NS16550) += ns16550.o
> diff --git a/drivers/serial/kirkwood_serial.c b/drivers/serial/kirkwood_serial.c
> new file mode 100644
> index 0000000..6422ab2
> --- /dev/null
> +++ b/drivers/serial/kirkwood_serial.c
> @@ -0,0 +1,187 @@
> +/*
> + * Copyright (C) Marvell International Ltd. and its affiliates
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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 Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +
> +/* registers feilds */
> +#define FCR_FIFO_EN            1<<0    /* fifo enable */
> +#define FCR_RXSR               1<<1    /* receiver soft reset */
> +#define FCR_TXSR               1<<2    /* transmitter soft reset */
> +#define MCR_RTS                1<<1    /* ready to send */
> +
> +#define LCR_WLS_OFFS           0
> +#define LCR_WLS_MASK           0x3 << LCR_WLS_OFFS     /* character length mask  */
> +#define LCR_WLS_5              0x0 << LCR_WLS_OFFS     /* 5 bit character length */
> +#define LCR_WLS_6              0x1 << LCR_WLS_OFFS     /* 6 bit character length */
> +#define LCR_WLS_7              0x2 << LCR_WLS_OFFS     /* 7 bit character length */
> +#define LCR_WLS_8              0x3 << LCR_WLS_OFFS     /* 8 bit character length */
> +#define LCR_STP_OFFS           2
> +#define LCR_1_STB              0x0 << LCR_STP_OFFS     /* Number of stop Bits */
> +#define LCR_2_STB              0x1 << LCR_STP_OFFS     /* Number of stop Bits */
> +#define LCR_PEN                0x8     /* Parity enable */
> +#define LCR_PS_OFFS            4
> +#define LCR_EPS                0x1 << LCR_PS_OFFS      /* Even Parity Select */
> +#define LCR_OPS                0x0 << LCR_PS_OFFS      /* Odd Parity Select */
> +#define LCR_SBRK_OFFS          0x6
> +#define LCR_SBRK               0x1 << LCR_SBRK_OFFS    /* Set Break */
> +#define LCR_DIVL_OFFS          7
> +#define LCR_DIVL_EN                    0x1 << LCR_DIVL_OFFS    /* Divisior latch enable */
> +
> +#define LSR_DR                 1<<0    /* Data ready */
> +#define LSR_OE                 1<<1    /* Overrun */
> +#define LSR_PE                 1<<2    /* Parity error */
> +#define LSR_FE                 1<<3    /* Framing error */
> +#define LSR_BI                 1<<4    /* Break */
> +#define LSR_THRE               1<<5    /* Xmit holding register empty */
> +#define LSR_TEMT               1<<6    /* Xmitter empty */
> +#define LSR_ERR                1<<7    /* Error */
> +
> +/* useful defaults for LCR*/
> +#define LCR_8N1                LCR_WLS_8 | LCR_1_STB
please move this macro to a header
as include/asm/arch/serial.h as example
> +
> +/* This structure describes the registers offsets for one UART port/channel */
> +typedef struct kwUartPort {
> +       u8 rbr;                 /* 0 = 0-3 */
> +       u8 pad1[3];
> +       u8 ier;                 /* 1 = 4-7 */
> +       u8 pad2[3];
> +       u8 fcr;                 /* 2 = 8-b */
> +       u8 pad3[3];
> +       u8 lcr;                 /* 3 = c-f */
> +       u8 pad4[3];
> +       u8 mcr;                 /* 4 = 10-13 */
> +       u8 pad5[3];
> +       u8 lsr;                 /* 5 = 14-17 */
> +       u8 pad6[3];
> +       u8 msr;                 /* 6 =18-1b */
> +       u8 pad7[3];
> +       u8 scr;                 /* 7 =1c-1f */
> +       u8 pad8[3];
> +} kw_uart_port;
> +
> +/* aliases - for registers which has the same offsets */
> +#define thr rbr
> +#define iir fcr
> +#define dll rbr
> +#define dlm ier
> +
> +/* static variables */
> +#if defined (CONFIG_CONS_INDEX)        /* comes from board config */
> +#if (CONFIG_CONS_INDEX == 0 )
> +static volatile kw_uart_port *p_uart_port = (void *)KW_REGISTER(KW_UART0_BASE);
> +#elif (CONFIG_CONS_INDEX == 1 )
> +static volatile kw_uart_port *p_uart_port = (void *)KW_REGISTER(KW_UART1_BASE);
> +#endif
> +#else
> +#error CONFIG_CONS_INDEX not defined correctly
> +#endif
> +
> +#define CONFIG_KW_UART_PORTS   { (void *)KW_UART0_BASE, \
> +                                 (void *)KW_UART1_BASE }
> +
> +/*
> + * Serial init banner is kept simplest one
> + * if required can be created good one
> + */
> +int serial_init(void)
> +{
> +       serial_setbrg();
> +       printf
> +           ("\n*************************************************************");
> +       return (0);
> +}
> +
> +void kwUartPutc(u8 c)
please no upper case
and please add static, this function is not use outside
> +{
> +       while ((p_uart_port->lsr & LSR_THRE) == 0) ;
> +       p_uart_port->thr = c;
> +       return;
> +}
> +
> +void serial_putc(const char c)
> +{
> +       if (c == '\n')
> +               kwUartPutc('\r');
> +
> +       kwUartPutc(c);
> +}
> +
> +int serial_getc(void)
> +{
> +       while ((p_uart_port->lsr & LSR_DR) == 0) ;
> +       return (p_uart_port->rbr);
> +}
> +
> +int serial_tstc(void)
> +{
> +       return ((p_uart_port->lsr & LSR_DR) != 0);
> +}
> +

> + * Marvell Semiconductor <www.marvell.com>
> + * Prafulla Wadaskar <prafulla at marvell.com>
> + *
> + * Derived from drivers/spi/mpc8xxx_spi.c
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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 Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <spi.h>
> +
> +/* SPI Registers on kirkwood SOC */
> +#define KW_REG_SPI_CTRL                (0x10600)
> +#define KW_REG_SPI_CONFIG      (0x10604)
> +#define KW_REG_SPI_DATA_OUT    (0x10608)
> +#define KW_REG_SPI_DATA_IN     (0x1060c)
> +#define KW_REG_SPI_IRQ_CAUSE   (0x10610)
> +#define KW_REG_SPI_IRQ_MASK    (0x10614)
please move this to a header
include/asm/arch/spi.h as example
> +
> +#define KW_SPI_TIMEOUT         10000
> +
> +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> +                                 unsigned int max_hz, unsigned int mode)
> +{
> +       struct spi_slave *slave;
> +       u32 data;
> +
> +       if (!spi_cs_is_valid(bus, cs))
> +               return NULL;
> +
> +       slave = malloc(sizeof(struct spi_slave));
> +       if (!slave)
> +               return NULL;
> +
> +       slave->bus = bus;
> +       slave->cs = cs;
> +
> +       writel(KW_REG_SPI_CTRL, 0x00000002);
> +       /* program spi clock prescaller using max_hz */
> +       data = ((CONFIG_SYS_TCLK / 2) / max_hz) & 0x0000000f;
> +       debug("data = 0x%08x \n", data);
> +       writel(KW_REG_SPI_CONFIG, 0x00000210 | data);
> +       writel(KW_REG_SPI_IRQ_CAUSE, 0x00000001);
> +       writel(KW_REG_SPI_IRQ_MASK, 0x00000000);
> +
> +       /* program mpp registers to select  SPI_CSn */
> +       if (cs)
> +               writel(KW_REG_MPP_CONTROL0,
> +                            ((readl(KW_REG_MPP_CONTROL0) & 0x0fffffff) |
> +                             0x20000000));
> +       else
> +               writel(KW_REG_MPP_CONTROL0,
> +                            ((readl(KW_REG_MPP_CONTROL0) & 0xfffffff0) |
> +                             0x00000002));
> +
> +       return slave;
> +}
> +
> +void spi_free_slave(struct spi_slave *slave)
> +{
> +       free(slave);
> +}
> +
> +int spi_claim_bus(struct spi_slave *slave)
> +{
> +       return 0;
> +}
> +
> +void spi_release_bus(struct spi_slave *slave)
> +{
> +}
> +
> +#ifndef CONFIG_SPI_CS_IS_VALID
> +/*
> + * you can define this function board specific
> + * define above CONFIG in board specific config file and
> + * provide the function in board specific src file
> + */
> +int spi_cs_is_valid(unsigned int bus, unsigned int cs)
> +{
> +       return (bus == 0 && (cs == 0 || cs == 1));
> +}
> +#endif
> +
> +void spi_cs_activate(struct spi_slave *slave)
> +{
> +       writel_set_bits(KW_REG_SPI_CTRL, 1<<0);
I prefer writel(t, readl(t) | 1);
> +}
> +
> +void spi_cs_deactivate(struct spi_slave *slave)
> +{
> +       writel_reset_bits(KW_REG_SPI_CTRL, 1<<0);
please add a space before and after '<<'
> +}
> +
> +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
> +            void *din, unsigned long flags)
> +{
> +       unsigned int tmpdout, tmpdin;
> +       int tm, isRead = 0;
please no upper case
> +
> +       debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
> +                   slave->bus, slave->cs, dout, din, bitlen);
> +
> +       if (flags & SPI_XFER_BEGIN)
> +               spi_cs_activate(slave);
> +
> +       /*
> +        * handle data in 8-bit chunks
> +        * TBD: 2byte xfer mode to be enabled
> +        */
> +       while (bitlen > 4) {
> +               debug("loopstart bitlen %d\n", bitlen);
> +               tmpdout = 0;
> +               if (1) {        //bitlen <= 8) {
please no dead code
> +                       /*1 byte xfer mode */
> +                       writel_reset_bits(KW_REG_SPI_CONFIG, 1<<5);
> +                       /* Shift data so it's msb-justified */
> +                       if (dout) {
> +                               tmpdout = *(u32 *) dout & 0x0ff;
> +                       }
> +               } else {
> +                       /*2 byte xfer mode */
> +                       writel_set_bits(KW_REG_SPI_CONFIG, 1<<5);
> +                       /* Shift data so it's msb-justified */
> +                       if (dout) {
> +                               tmpdout = *(u32 *) dout & 0x0ffff;
> +                       }
> +               }
> +
> +               writel(KW_REG_SPI_IRQ_CAUSE, 0x0);      /* clear bit */
> +               writel(KW_REG_SPI_DATA_OUT, tmpdout);   /* Write the data out */
> +               debug("*** spi_xfer: ... %08x written, bitlen %d\n",
> +                           tmpdout, bitlen);
> +
> +               /*
> +                * Wait for SPI transmit to get out
> +                * or time out (1 second = 1000 ms)
> +                * The NE event must be read and cleared first
> +                */
> +               for (tm = 0, isRead = 0; tm < KW_SPI_TIMEOUT; ++tm) {
> +                       if (readl(KW_REG_SPI_IRQ_CAUSE)) {
> +                               isRead = 1;
> +                               tmpdin = readl(KW_REG_SPI_DATA_IN);
> +                               debug
> +                                   ("*** spi_xfer: din %08X ... %08x read\n",
> +                                    din, tmpdin);
> +
> +                               if (1) {        //bitlen <= 8) {
> +                                       if (din) {
> +                                               *((u8 *) din) = (u8) tmpdin;
> +                                               din += 1;
> +                                       }
> +                                       if (dout)
> +                                               dout += 1;
> +                                       bitlen -= 8;
> +                               } else {
> +                                       if (din) {
> +                                               *((u16 *) din) = (u16) tmpdin;
> +                                               din += 1;
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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 Street, Fifth Floor, Boston,
> + * MA 02110-1301 USA
> + */
> +
> +#ifndef _ASM_ARCH_KIRKWOOD_H
> +#define _ASM_ARCH_KIRKWOOD_H
> +
> +#if defined (__ARMEL__)
> +#define LE
> +#else
> +#define BE
> +#endif /* __ARMEL__ */
no need please remove
> +
> +#ifndef __ASSEMBLY__
> +#include <asm-arm/types.h>
> +#endif /* __ASSEMBLY__ */
> +#include <../board/Marvell/include/core.h>
> +
> +#if defined (CONFIG_FEROCEON_88FR131) || defined (CONFIG_SHEEVA_88SV131)
> +#if defined (CONFIG_KIRKWOOD)
> +#include <../cpu/arm926ejs/kirkwood/kwcore.h>
> +
> +/* SOC specific definations */
> +#define INTREG_BASE                    0xd0000000
> +#define KW_REGISTER(x)                 (KW_REGS_PHY_BASE | x)
> +#define KW_OFFSET_REG                  (INTREG_BASE | 0x20080)
> +
> +#define KW_UART0_BASE                  (0x12000)       /* UArt 0 */
> +#define KW_UART1_BASE                  (0x13000)       /* UArt 1 */
> +
> +/* Controler environment registers offsets */
> +#define KW_REG_MPP_CONTROL0            (0x10000)
> +#define KW_REG_MPP_CONTROL1            (0x10004)
> +#define KW_REG_MPP_CONTROL2            (0x10008)
> +#define KW_REG_MPP_CONTROL3            (0x1000C)
> +#define KW_REG_MPP_CONTROL4            (0x10010)
> +#define KW_REG_MPP_CONTROL5            (0x10014)
> +#define KW_REG_MPP_CONTROL6            (0x10018)
> +#define KW_REG_MPP_SMPL_AT_RST         (0x10030)
> +#define KW_REG_DEVICE_ID               (0x10034)
> +#define KW_REG_MPP_OUT_DRV_REG         (0x100E0)
> +
> +#define KW_REG_GPP0_DATA_OUT           (0x10100)
> +#define KW_REG_GPP0_DATA_OUT_EN                (0x10104)
> +#define KW_REG_GPP0_BLINK_EN           (0x10108)
> +#define KW_REG_GPP0_DATA_IN_POL                (0x1010C)
> +#define KW_REG_GPP0_DATA_IN            (0x10110)
> +#define KW_REG_GPP0_INT_CAUSE          (0x10114)
> +#define KW_REG_GPP0_INT_MASK           (0x10118)
> +#define KW_REG_GPP0_INT_LVL            (0x1011c)
> +
> +#define KW_REG_GPP1_DATA_OUT           (0x10140)
> +#define KW_REG_GPP1_DATA_OUT_EN                (0x10144)
> +#define KW_REG_GPP1_BLINK_EN           (0x10148)
> +#define KW_REG_GPP1_DATA_IN_POL                (0x1014C)
> +#define KW_REG_GPP1_DATA_IN            (0x10150)
> +#define KW_REG_GPP1_INT_CAUSE          (0x10154)
> +#define KW_REG_GPP1_INT_MASK           (0x10158)
> +#define KW_REG_GPP1_INT_LVL            (0x1015c)
> +
> +#define KW_REG_NAND_READ_PARAM         (0x10418)
> +#define KW_REG_NAND_WRITE_PARAM                (0x1041c)
> +#define KW_REG_NAND_CTRL               (0x10470)
> +
> +#define KW_REG_WIN_CTRL(x)             (0x20000+(x*0x10))
please add a space before and after '+' '*'
> +#define KW_REG_WIN_BASE(x)             (0x20004+(x*0x10))
> +#define KW_REG_WIN_REMAP_LOW(x)                (0x20008+(x*0x10))
> +#define KW_REG_WIN_REMAP_HIGH(x)       (0x2000c+(x*0x10))
> +
> +#define KW_REG_CPU_CONFIG              (0x20100)
> +#define KW_REG_CPU_CTRL_STAT           (0x20104)
> +#define KW_REG_CPU_RSTOUTN_MASK                (0x20108)
> +#define KW_REG_CPU_SYS_SOFT_RST                (0x2010C)
> +#define KW_REG_CPU_AHB_MBUS_CAUSE_INT  (0x20110)
> +#define KW_REG_CPU_AHB_MBUS_MASK_INT   (0x20114)
> +#define KW_REG_CPU_FTDLL_CONFIG                (0x20120)
> +#define KW_REG_CPU_L2_CONFIG           (0x20128)
> +#define KW_REG_L2_RAM_TIMING0          (0x20134)
> +#define KW_REG_L2_RAM_TIMING1          (0x20138)
> +
> +#define KW_REG_TMR_CTRL                        (0x20300)
> +#define KW_REG_TMR_RELOAD              (0x20310)
> +#define KW_REG_TMR_VAL                 (0x20314)
> +
> +#define KW_REG_PCIE_BASE               (0x40000)
> +
> +/*
> + * Macros
> + * CPU architecture dependent I/O read/write
> + */
> +#define writel(addr, data)     \
> +    (*((volatile unsigned int*)(KW_REGISTER(addr))) \
> +                = (unsigned int)WORD_SWAP((data)))
no need please use generic arm/io.h (mandatory)
> +
> +#define readl(addr)            \
> +    (WORD_SWAP(*((volatile unsigned int*)(KW_REGISTER(addr)))))
> +
> +#define writel_set_bits(adr, bits)     (writel(adr, readl(adr)\
> +                                       | ((unsigned int)WORD_SWAP(bits))))
> +
> +#define writel_reset_bits(adr, bits)   (writel(adr, readl(adr)\
> +                                       & ~((unsigned int)WORD_SWAP(bits))))
> +
> +/*
> + * Error codes
> + */
> +#define KW_ERROR       (-1)
> +#define KW_OK          (0)
no need please remove
> +
Best Regards,
J.


More information about the U-Boot mailing list