From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jean-Christophe PLAGNIOL-VILLARD Date: Thu, 23 Apr 2009 18:21:35 +0200 Subject: [U-Boot] [PATCH v3] Marvell Kirkwood family SOC support In-Reply-To: <73173D32E9439E4ABB5151606C3E19E201CA9AB597@SC-VEXCH1.marvell.com> References: <73173D32E9439E4ABB5151606C3E19E201C6B9BA43@SC-VEXCH1.marvell.com> <73173D32E9439E4ABB5151606C3E19E201CA9AB597@SC-VEXCH1.marvell.com> Message-ID: <20090423162135.GD18705@game.jcrosoft.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > Michael Blostein > Reviewed-by: Ronen Shitrit > Signed-off-by: Prafulla Wadaskar 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 > + * Prafulla Wadaskar > + * > + * 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 > + > +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, ®); > +#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), ®); /* 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 > + * > + * 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 > + > +#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 > + * > + * 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 > + > +/* 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 > + * Prafulla Wadaskar > + * > + * 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 > +#include > +#include > + > +/* 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 > +#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.