mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-25 06:00:43 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-microblaze
* 'master' of git://git.denx.de/u-boot-microblaze: microblaze: Wire up SPI driver spi: microblaze: Adds driver for Xilinx SPI controller microblaze: intc: Clear interrupt code microblaze: Call serial multi initialization microblaze: Move __udelay implementation microblaze: Remove extern from board.c microblaze: Wire up dts configuration fdt: Add board specific dts inclusion microblaze: Move individual board linker scripts to common script in cpu tree. microblaze: Add gpio.h microblaze: Add missing undefs for UBI and UBIFS microblaze: Expand and correct configuration comments microblaze: Enable ubi support microblaze: Avoid compile error on systems without cfi flash microblaze: Remove wrong define CONFIG_SYS_FLASH_PROTECTION Conflicts: drivers/spi/Makefile Signed-off-by: Wolfgang Denk <wd@denx.de>
This commit is contained in:
commit
d978780b2e
17 changed files with 594 additions and 110 deletions
|
@ -29,3 +29,5 @@ CROSS_COMPILE ?= mb-
|
|||
CONFIG_STANDALONE_LOAD_ADDR ?= 0x80F00000
|
||||
|
||||
PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
|
||||
|
||||
LDSCRIPT ?= $(SRCTREE)/$(CPUDIR)/u-boot.lds
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <malloc.h>
|
||||
#include <asm/microblaze_intc.h>
|
||||
#include <asm/asm.h>
|
||||
|
||||
|
@ -48,20 +49,19 @@ int disable_interrupts (void)
|
|||
return (msr & 0x2) != 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYS_INTC_0
|
||||
|
||||
static struct irq_action vecs[CONFIG_SYS_INTC_0_NUM];
|
||||
static struct irq_action *vecs;
|
||||
static u32 irq_no;
|
||||
|
||||
/* mapping structure to interrupt controller */
|
||||
microblaze_intc_t *intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR);
|
||||
microblaze_intc_t *intc;
|
||||
|
||||
/* default handler */
|
||||
void def_hdlr (void)
|
||||
static void def_hdlr(void)
|
||||
{
|
||||
puts ("def_hdlr\n");
|
||||
}
|
||||
|
||||
void enable_one_interrupt (int irq)
|
||||
static void enable_one_interrupt(int irq)
|
||||
{
|
||||
int mask;
|
||||
int offset = 1;
|
||||
|
@ -76,7 +76,7 @@ void enable_one_interrupt (int irq)
|
|||
#endif
|
||||
}
|
||||
|
||||
void disable_one_interrupt (int irq)
|
||||
static void disable_one_interrupt(int irq)
|
||||
{
|
||||
int mask;
|
||||
int offset = 1;
|
||||
|
@ -96,7 +96,7 @@ void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
|
|||
{
|
||||
struct irq_action *act;
|
||||
/* irq out of range */
|
||||
if ((irq < 0) || (irq > CONFIG_SYS_INTC_0_NUM)) {
|
||||
if ((irq < 0) || (irq > irq_no)) {
|
||||
puts ("IRQ out of range\n");
|
||||
return;
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg)
|
|||
}
|
||||
|
||||
/* initialization interrupt controller - hardware */
|
||||
void intc_init (void)
|
||||
static void intc_init(void)
|
||||
{
|
||||
intc->mer = 0;
|
||||
intc->ier = 0;
|
||||
|
@ -127,18 +127,33 @@ void intc_init (void)
|
|||
#endif
|
||||
}
|
||||
|
||||
int interrupts_init (void)
|
||||
int interrupts_init(void)
|
||||
{
|
||||
int i;
|
||||
/* initialize irq list */
|
||||
for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) {
|
||||
vecs[i].handler = (interrupt_handler_t *) def_hdlr;
|
||||
vecs[i].arg = (void *)i;
|
||||
vecs[i].count = 0;
|
||||
|
||||
#if defined(CONFIG_SYS_INTC_0_ADDR) && defined(CONFIG_SYS_INTC_0_NUM)
|
||||
intc = (microblaze_intc_t *) (CONFIG_SYS_INTC_0_ADDR);
|
||||
irq_no = CONFIG_SYS_INTC_0_NUM;
|
||||
#endif
|
||||
if (irq_no) {
|
||||
vecs = calloc(1, sizeof(struct irq_action) * irq_no);
|
||||
if (vecs == NULL) {
|
||||
puts("Interrupt vector allocation failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* initialize irq list */
|
||||
for (i = 0; i < irq_no; i++) {
|
||||
vecs[i].handler = (interrupt_handler_t *) def_hdlr;
|
||||
vecs[i].arg = (void *)i;
|
||||
vecs[i].count = 0;
|
||||
}
|
||||
/* initialize intc controller */
|
||||
intc_init();
|
||||
enable_interrupts();
|
||||
} else {
|
||||
puts("Undefined interrupt controller\n");
|
||||
}
|
||||
/* initialize intc controller */
|
||||
intc_init ();
|
||||
enable_interrupts ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -172,33 +187,30 @@ void interrupt_handler (void)
|
|||
printf ("Interrupt handler on %x line, r14 %x\n", irqs, value);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_IRQ)
|
||||
#ifdef CONFIG_SYS_INTC_0
|
||||
int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, const char *argv[])
|
||||
{
|
||||
int i;
|
||||
struct irq_action *act = vecs;
|
||||
|
||||
puts ("\nInterrupt-Information:\n\n"
|
||||
"Nr Routine Arg Count\n"
|
||||
"-----------------------------\n");
|
||||
if (irq_no) {
|
||||
puts("\nInterrupt-Information:\n\n"
|
||||
"Nr Routine Arg Count\n"
|
||||
"-----------------------------\n");
|
||||
|
||||
for (i = 0; i < CONFIG_SYS_INTC_0_NUM; i++) {
|
||||
if (act->handler != (interrupt_handler_t*) def_hdlr) {
|
||||
printf ("%02d %08x %08x %d\n", i,
|
||||
(int)act->handler, (int)act->arg, act->count);
|
||||
for (i = 0; i < irq_no; i++) {
|
||||
if (act->handler != (interrupt_handler_t *) def_hdlr) {
|
||||
printf("%02d %08x %08x %d\n", i,
|
||||
(int)act->handler, (int)act->arg,
|
||||
act->count);
|
||||
}
|
||||
act++;
|
||||
}
|
||||
act++;
|
||||
puts("\n");
|
||||
} else {
|
||||
puts("Undefined interrupt controller\n");
|
||||
}
|
||||
puts ("\n");
|
||||
return (0);
|
||||
}
|
||||
#else
|
||||
int do_irqinfo (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
puts ("Undefined interrupt controller\n");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -108,7 +108,6 @@ _start:
|
|||
sh r6, r0, r8
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_INTC_0
|
||||
/* interrupt_handler */
|
||||
swi r2, r0, 0x10 /* interrupt - imm opcode */
|
||||
swi r3, r0, 0x14 /* interrupt - brai opcode */
|
||||
|
@ -120,7 +119,6 @@ _start:
|
|||
sh r7, r0, r8
|
||||
rsubi r8, r10, 0x16
|
||||
sh r6, r0, r8
|
||||
#endif
|
||||
|
||||
/* hardware exception */
|
||||
swi r2, r0, 0x20 /* hardware exception - imm opcode */
|
||||
|
|
|
@ -40,7 +40,25 @@ ulong get_timer (ulong base)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_INTC_0
|
||||
#ifdef CONFIG_SYS_TIMER_0
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = get_timer(0);
|
||||
while ((get_timer(0) - i) < (usec / 1000))
|
||||
;
|
||||
}
|
||||
#else
|
||||
void __udelay(unsigned long usec)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < (usec * CONFIG_XILINX_CLOCK_FREQ / 10000000); i++)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYS_TIMER_0
|
||||
microblaze_timer_t *tmr = (microblaze_timer_t *) (CONFIG_SYS_TIMER_0_ADDR);
|
||||
|
||||
|
@ -61,7 +79,6 @@ int timer_init (void)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is derived from PowerPC code (read timebase as long long).
|
||||
|
|
41
arch/microblaze/include/asm/gpio.h
Normal file
41
arch/microblaze/include/asm/gpio.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef _ASM_MICROBLAZE_GPIO_H_
|
||||
#define _ASM_MICROBLAZE_GPIO_H_
|
||||
|
||||
#include <asm/io.h>
|
||||
|
||||
static inline int gpio_request(unsigned gpio, const char *label)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpio_free(unsigned gpio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpio_direction_input(unsigned gpio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpio_direction_output(unsigned gpio, int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpio_get_value(unsigned gpio)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpio_set_value(unsigned gpio, int value)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int gpio_is_valid(int number)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -41,3 +41,6 @@ struct irq_action {
|
|||
|
||||
void install_interrupt_handler (int irq, interrupt_handler_t * hdlr,
|
||||
void *arg);
|
||||
|
||||
int interrupts_init(void);
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ SOBJS-y +=
|
|||
|
||||
COBJS-y += board.o
|
||||
COBJS-y += bootm.o
|
||||
COBJS-y += time.o
|
||||
|
||||
SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
|
||||
OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
|
||||
|
|
|
@ -30,21 +30,16 @@
|
|||
#include <version.h>
|
||||
#include <watchdog.h>
|
||||
#include <stdio_dev.h>
|
||||
#include <serial.h>
|
||||
#include <net.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/microblaze_intc.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
#ifdef CONFIG_SYS_GPIO_0
|
||||
extern int gpio_init (void);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_INTC_0
|
||||
extern int interrupts_init (void);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_NET)
|
||||
extern int eth_init (bd_t * bis);
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_TIMER_0
|
||||
extern int timer_init (void);
|
||||
#endif
|
||||
|
@ -73,9 +68,7 @@ init_fnc_t *init_sequence[] = {
|
|||
#ifdef CONFIG_SYS_GPIO_0
|
||||
gpio_init,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_INTC_0
|
||||
interrupts_init,
|
||||
#endif
|
||||
#ifdef CONFIG_SYS_TIMER_0
|
||||
timer_init,
|
||||
#endif
|
||||
|
@ -117,6 +110,10 @@ void board_init (void)
|
|||
*/
|
||||
mem_malloc_init (CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
|
||||
|
||||
#ifdef CONFIG_SERIAL_MULTI
|
||||
serial_initialize();
|
||||
#endif
|
||||
|
||||
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
|
||||
WATCHDOG_RESET ();
|
||||
if ((*init_fnc_ptr) () != 0) {
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2007 Michal Simek
|
||||
* (C) Copyright 2004 Atmark Techno, Inc.
|
||||
*
|
||||
* Michal SIMEK <monstr@monstr.eu>
|
||||
* Yasushi SHOJI <yashi@atmark-techno.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., 59 Temple Place, Suite 330, Boston,
|
||||
* MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#ifdef CONFIG_SYS_TIMER_0
|
||||
void __udelay (unsigned long usec)
|
||||
{
|
||||
int i;
|
||||
i = get_timer (0);
|
||||
while ((get_timer (0) - i) < (usec / 1000)) ;
|
||||
}
|
||||
#else
|
||||
void __udelay (unsigned long usec)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < (usec * CONFIG_XILINX_CLOCK_FREQ / 10000000); i++);
|
||||
}
|
||||
#endif
|
1
board/xilinx/dts/microblaze.dts
Normal file
1
board/xilinx/dts/microblaze.dts
Normal file
|
@ -0,0 +1 @@
|
|||
/include/ BOARD_DTS
|
7
board/xilinx/microblaze-generic/dts/microblaze.dts
Normal file
7
board/xilinx/microblaze-generic/dts/microblaze.dts
Normal file
|
@ -0,0 +1,7 @@
|
|||
/dts-v1/;
|
||||
/ {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
aliases {
|
||||
} ;
|
||||
} ;
|
|
@ -44,6 +44,8 @@ COBJS-$(CONFIG_SOFT_SPI) += soft_spi.o
|
|||
COBJS-$(CONFIG_SH_SPI) += sh_spi.o
|
||||
COBJS-$(CONFIG_FSL_ESPI) += fsl_espi.o
|
||||
COBJS-$(CONFIG_TEGRA_SPI) += tegra_spi.o
|
||||
COBJS-$(CONFIG_TEGRA2_SPI) += tegra2_spi.o
|
||||
COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
|
||||
|
||||
COBJS := $(COBJS-y)
|
||||
SRCS := $(COBJS:.o=.c)
|
||||
|
|
214
drivers/spi/xilinx_spi.c
Normal file
214
drivers/spi/xilinx_spi.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Xilinx SPI driver
|
||||
*
|
||||
* supports 8 bit SPI transfers only, with or w/o FIFO
|
||||
*
|
||||
* based on bfin_spi.c, by way of altera_spi.c
|
||||
* Copyright (c) 2005-2008 Analog Devices Inc.
|
||||
* Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
|
||||
* Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
|
||||
* Copyright (c) 2012 Stephan Linz <linz@li-pro.net>
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*
|
||||
* [0]: http://www.xilinx.com/support/documentation
|
||||
*
|
||||
* [S]: [0]/ip_documentation/xps_spi.pdf
|
||||
* [0]/ip_documentation/axi_spi_ds742.pdf
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <malloc.h>
|
||||
#include <spi.h>
|
||||
|
||||
#include "xilinx_spi.h"
|
||||
|
||||
#ifndef CONFIG_SYS_XILINX_SPI_LIST
|
||||
#define CONFIG_SYS_XILINX_SPI_LIST { CONFIG_SYS_SPI_BASE }
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_XILINX_SPI_IDLE_VAL
|
||||
#define CONFIG_XILINX_SPI_IDLE_VAL 0xff
|
||||
#endif
|
||||
|
||||
#define XILSPI_SPICR_DFLT_ON (SPICR_MANUAL_SS | \
|
||||
SPICR_MASTER_MODE | \
|
||||
SPICR_SPE)
|
||||
|
||||
#define XILSPI_SPICR_DFLT_OFF (SPICR_MASTER_INHIBIT | \
|
||||
SPICR_MANUAL_SS)
|
||||
|
||||
#define XILSPI_MAX_XFER_BITS 8
|
||||
|
||||
static unsigned long xilinx_spi_base_list[] = CONFIG_SYS_XILINX_SPI_LIST;
|
||||
|
||||
__attribute__((weak))
|
||||
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
|
||||
{
|
||||
return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32;
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void spi_cs_activate(struct spi_slave *slave)
|
||||
{
|
||||
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
|
||||
|
||||
writel(SPISSR_ACT(slave->cs), &xilspi->regs->spissr);
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void spi_cs_deactivate(struct spi_slave *slave)
|
||||
{
|
||||
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
|
||||
|
||||
writel(SPISSR_OFF, &xilspi->regs->spissr);
|
||||
}
|
||||
|
||||
void spi_init(void)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
void spi_set_speed(struct spi_slave *slave, uint hz)
|
||||
{
|
||||
/* xilinx spi core does not support programmable speed */
|
||||
}
|
||||
|
||||
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int mode)
|
||||
{
|
||||
struct xilinx_spi_slave *xilspi;
|
||||
struct xilinx_spi_reg *regs;
|
||||
|
||||
if (!spi_cs_is_valid(bus, cs)) {
|
||||
printf("XILSPI error: %s: unsupported bus %d / cs %d\n",
|
||||
__func__, bus, cs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xilspi = malloc(sizeof(*xilspi));
|
||||
if (!xilspi) {
|
||||
printf("XILSPI error: %s: malloc of SPI structure failed\n",
|
||||
__func__);
|
||||
return NULL;
|
||||
}
|
||||
xilspi->slave.bus = bus;
|
||||
xilspi->slave.cs = cs;
|
||||
xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus];
|
||||
xilspi->freq = max_hz;
|
||||
xilspi->mode = mode;
|
||||
debug("%s: bus:%i cs:%i base:%p mode:%x max_hz:%d\n", __func__,
|
||||
bus, cs, xilspi->regs, xilspi->mode, xilspi->freq);
|
||||
|
||||
return &xilspi->slave;
|
||||
}
|
||||
|
||||
void spi_free_slave(struct spi_slave *slave)
|
||||
{
|
||||
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
|
||||
|
||||
free(xilspi);
|
||||
}
|
||||
|
||||
int spi_claim_bus(struct spi_slave *slave)
|
||||
{
|
||||
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
|
||||
u32 spicr;
|
||||
|
||||
debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
|
||||
writel(SPISSR_OFF, &xilspi->regs->spissr);
|
||||
|
||||
spicr = XILSPI_SPICR_DFLT_ON;
|
||||
if (xilspi->mode & SPI_LSB_FIRST)
|
||||
spicr |= SPICR_LSB_FIRST;
|
||||
if (xilspi->mode & SPI_CPHA)
|
||||
spicr |= SPICR_CPHA;
|
||||
if (xilspi->mode & SPI_CPOL)
|
||||
spicr |= SPICR_CPOL;
|
||||
if (xilspi->mode & SPI_LOOP)
|
||||
spicr |= SPICR_LOOP;
|
||||
|
||||
writel(spicr, &xilspi->regs->spicr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spi_release_bus(struct spi_slave *slave)
|
||||
{
|
||||
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
|
||||
|
||||
debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
|
||||
writel(SPISSR_OFF, &xilspi->regs->spissr);
|
||||
writel(XILSPI_SPICR_DFLT_OFF, &xilspi->regs->spicr);
|
||||
}
|
||||
|
||||
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
|
||||
void *din, unsigned long flags)
|
||||
{
|
||||
struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
|
||||
/* assume spi core configured to do 8 bit transfers */
|
||||
unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS;
|
||||
const unsigned char *txp = dout;
|
||||
unsigned char *rxp = din;
|
||||
unsigned rxecount = 17; /* max. 16 elements in FIFO, leftover 1 */
|
||||
|
||||
debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
|
||||
slave->bus, slave->cs, bitlen, bytes, flags);
|
||||
if (bitlen == 0)
|
||||
goto done;
|
||||
|
||||
if (bitlen % XILSPI_MAX_XFER_BITS) {
|
||||
printf("XILSPI warning: %s: Not a multiple of %d bits\n",
|
||||
__func__, XILSPI_MAX_XFER_BITS);
|
||||
flags |= SPI_XFER_END;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* empty read buffer */
|
||||
while (rxecount && !(readl(&xilspi->regs->spisr) & SPISR_RX_EMPTY)) {
|
||||
readl(&xilspi->regs->spidrr);
|
||||
rxecount--;
|
||||
}
|
||||
|
||||
if (!rxecount) {
|
||||
printf("XILSPI error: %s: Rx buffer not empty\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & SPI_XFER_BEGIN)
|
||||
spi_cs_activate(slave);
|
||||
|
||||
while (bytes--) {
|
||||
unsigned timeout = /* at least 1usec or greater, leftover 1 */
|
||||
xilspi->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 :
|
||||
(XILSPI_MAX_XFER_BITS * 1000000 / xilspi->freq) + 1;
|
||||
|
||||
/* get Tx element from data out buffer and count up */
|
||||
unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL;
|
||||
debug("%s: tx:%x ", __func__, d);
|
||||
|
||||
/* write out and wait for processing (receive data) */
|
||||
writel(d & SPIDTR_8BIT_MASK, &xilspi->regs->spidtr);
|
||||
while (timeout && readl(&xilspi->regs->spisr)
|
||||
& SPISR_RX_EMPTY) {
|
||||
timeout--;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (!timeout) {
|
||||
printf("XILSPI error: %s: Xfer timeout\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* read Rx element and push into data in buffer */
|
||||
d = readl(&xilspi->regs->spidrr) & SPIDRR_8BIT_MASK;
|
||||
if (rxp)
|
||||
*rxp++ = d;
|
||||
debug("rx:%x\n", d);
|
||||
}
|
||||
|
||||
done:
|
||||
if (flags & SPI_XFER_END)
|
||||
spi_cs_deactivate(slave);
|
||||
|
||||
return 0;
|
||||
}
|
135
drivers/spi/xilinx_spi.h
Normal file
135
drivers/spi/xilinx_spi.h
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Xilinx SPI driver
|
||||
*
|
||||
* XPS/AXI bus interface
|
||||
*
|
||||
* based on bfin_spi.c, by way of altera_spi.c
|
||||
* Copyright (c) 2005-2008 Analog Devices Inc.
|
||||
* Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
|
||||
* Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
|
||||
* Copyright (c) 2012 Stephan Linz <linz@li-pro.net>
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*
|
||||
* [0]: http://www.xilinx.com/support/documentation
|
||||
*
|
||||
* [S]: [0]/ip_documentation/xps_spi.pdf
|
||||
* [0]/ip_documentation/axi_spi_ds742.pdf
|
||||
*/
|
||||
#ifndef _XILINX_SPI_
|
||||
#define _XILINX_SPI_
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
/*
|
||||
* Xilinx SPI Register Definition
|
||||
*
|
||||
* [1]: [0]/ip_documentation/xps_spi.pdf
|
||||
* page 8, Register Descriptions
|
||||
* [2]: [0]/ip_documentation/axi_spi_ds742.pdf
|
||||
* page 7, Register Overview Table
|
||||
*/
|
||||
struct xilinx_spi_reg {
|
||||
u32 __space0__[7];
|
||||
u32 dgier; /* Device Global Interrupt Enable Register (DGIER) */
|
||||
u32 ipisr; /* IP Interrupt Status Register (IPISR) */
|
||||
u32 __space1__;
|
||||
u32 ipier; /* IP Interrupt Enable Register (IPIER) */
|
||||
u32 __space2__[5];
|
||||
u32 srr; /* Softare Reset Register (SRR) */
|
||||
u32 __space3__[7];
|
||||
u32 spicr; /* SPI Control Register (SPICR) */
|
||||
u32 spisr; /* SPI Status Register (SPISR) */
|
||||
u32 spidtr; /* SPI Data Transmit Register (SPIDTR) */
|
||||
u32 spidrr; /* SPI Data Receive Register (SPIDRR) */
|
||||
u32 spissr; /* SPI Slave Select Register (SPISSR) */
|
||||
u32 spitfor; /* SPI Transmit FIFO Occupancy Register (SPITFOR) */
|
||||
u32 spirfor; /* SPI Receive FIFO Occupancy Register (SPIRFOR) */
|
||||
};
|
||||
|
||||
/* Device Global Interrupt Enable Register (dgier), [1] p15, [2] p15 */
|
||||
#define DGIER_GIE (1 << 31)
|
||||
|
||||
/* IP Interrupt Status Register (ipisr), [1] p15, [2] p15 */
|
||||
#define IPISR_DRR_NOT_EMPTY (1 << 8)
|
||||
#define IPISR_SLAVE_SELECT (1 << 7)
|
||||
#define IPISR_TXF_HALF_EMPTY (1 << 6)
|
||||
#define IPISR_DRR_OVERRUN (1 << 5)
|
||||
#define IPISR_DRR_FULL (1 << 4)
|
||||
#define IPISR_DTR_UNDERRUN (1 << 3)
|
||||
#define IPISR_DTR_EMPTY (1 << 2)
|
||||
#define IPISR_SLAVE_MODF (1 << 1)
|
||||
#define IPISR_MODF (1 << 0)
|
||||
|
||||
/* IP Interrupt Enable Register (ipier), [1] p17, [2] p18 */
|
||||
#define IPIER_DRR_NOT_EMPTY (1 << 8)
|
||||
#define IPIER_SLAVE_SELECT (1 << 7)
|
||||
#define IPIER_TXF_HALF_EMPTY (1 << 6)
|
||||
#define IPIER_DRR_OVERRUN (1 << 5)
|
||||
#define IPIER_DRR_FULL (1 << 4)
|
||||
#define IPIER_DTR_UNDERRUN (1 << 3)
|
||||
#define IPIER_DTR_EMPTY (1 << 2)
|
||||
#define IPIER_SLAVE_MODF (1 << 1)
|
||||
#define IPIER_MODF (1 << 0)
|
||||
|
||||
/* Softare Reset Register (srr), [1] p9, [2] p8 */
|
||||
#define SRR_RESET_CODE 0x0000000A
|
||||
|
||||
/* SPI Control Register (spicr), [1] p9, [2] p8 */
|
||||
#define SPICR_LSB_FIRST (1 << 9)
|
||||
#define SPICR_MASTER_INHIBIT (1 << 8)
|
||||
#define SPICR_MANUAL_SS (1 << 7)
|
||||
#define SPICR_RXFIFO_RESEST (1 << 6)
|
||||
#define SPICR_TXFIFO_RESEST (1 << 5)
|
||||
#define SPICR_CPHA (1 << 4)
|
||||
#define SPICR_CPOL (1 << 3)
|
||||
#define SPICR_MASTER_MODE (1 << 2)
|
||||
#define SPICR_SPE (1 << 1)
|
||||
#define SPICR_LOOP (1 << 0)
|
||||
|
||||
/* SPI Status Register (spisr), [1] p11, [2] p10 */
|
||||
#define SPISR_SLAVE_MODE_SELECT (1 << 5)
|
||||
#define SPISR_MODF (1 << 4)
|
||||
#define SPISR_TX_FULL (1 << 3)
|
||||
#define SPISR_TX_EMPTY (1 << 2)
|
||||
#define SPISR_RX_FULL (1 << 1)
|
||||
#define SPISR_RX_EMPTY (1 << 0)
|
||||
|
||||
/* SPI Data Transmit Register (spidtr), [1] p12, [2] p12 */
|
||||
#define SPIDTR_8BIT_MASK (0xff << 0)
|
||||
#define SPIDTR_16BIT_MASK (0xffff << 0)
|
||||
#define SPIDTR_32BIT_MASK (0xffffffff << 0)
|
||||
|
||||
/* SPI Data Receive Register (spidrr), [1] p12, [2] p12 */
|
||||
#define SPIDRR_8BIT_MASK (0xff << 0)
|
||||
#define SPIDRR_16BIT_MASK (0xffff << 0)
|
||||
#define SPIDRR_32BIT_MASK (0xffffffff << 0)
|
||||
|
||||
/* SPI Slave Select Register (spissr), [1] p13, [2] p13 */
|
||||
#define SPISSR_MASK(cs) (1 << (cs))
|
||||
#define SPISSR_ACT(cs) ~SPISSR_MASK(cs)
|
||||
#define SPISSR_OFF ~0UL
|
||||
|
||||
/* SPI Transmit FIFO Occupancy Register (spitfor), [1] p13, [2] p14 */
|
||||
#define SPITFOR_OCYVAL_POS 0
|
||||
#define SPITFOR_OCYVAL_MASK (0xf << SPITFOR_OCYVAL_POS)
|
||||
|
||||
/* SPI Receive FIFO Occupancy Register (spirfor), [1] p14, [2] p14 */
|
||||
#define SPIRFOR_OCYVAL_POS 0
|
||||
#define SPIRFOR_OCYVAL_MASK (0xf << SPIRFOR_OCYVAL_POS)
|
||||
|
||||
struct xilinx_spi_slave {
|
||||
struct spi_slave slave;
|
||||
struct xilinx_spi_reg *regs;
|
||||
unsigned int freq;
|
||||
unsigned int mode;
|
||||
};
|
||||
|
||||
static inline struct xilinx_spi_slave *to_xilinx_spi_slave(
|
||||
struct spi_slave *slave)
|
||||
{
|
||||
return container_of(slave, struct xilinx_spi_slave, slave);
|
||||
}
|
||||
|
||||
#endif /* _XILINX_SPI_ */
|
|
@ -36,7 +36,8 @@ $(error Your architecture does not have device tree support enabled. \
|
|||
Please define CONFIG_ARCH_DEVICE_TREE))
|
||||
|
||||
# We preprocess the device tree file provide a useful define
|
||||
DTS_CPPFLAGS := -DARCH_CPU_DTS=\"$(SRCTREE)/arch/$(ARCH)/dts/$(CONFIG_ARCH_DEVICE_TREE).dtsi\"
|
||||
DTS_CPPFLAGS := -DARCH_CPU_DTS=\"$(SRCTREE)/arch/$(ARCH)/dts/$(CONFIG_ARCH_DEVICE_TREE).dtsi\" \
|
||||
-DBOARD_DTS=\"$(SRCTREE)/board/$(VENDOR)/$(BOARD)/dts/$(DEVICE_TREE).dts\"
|
||||
|
||||
all: $(obj).depend $(LIB)
|
||||
|
||||
|
|
|
@ -31,6 +31,28 @@
|
|||
#define CONFIG_MICROBLAZE 1
|
||||
#define MICROBLAZE_V5 1
|
||||
|
||||
/* Open Firmware DTS */
|
||||
#define CONFIG_OF_CONTROL 1
|
||||
#define CONFIG_OF_EMBED 1
|
||||
#define CONFIG_DEFAULT_DEVICE_TREE microblaze
|
||||
|
||||
/* linear and spi flash memory */
|
||||
#ifdef XILINX_FLASH_START
|
||||
#define FLASH
|
||||
#undef SPIFLASH
|
||||
#undef RAMENV /* hold environment in flash */
|
||||
#else
|
||||
#ifdef XILINX_SPI_FLASH_BASEADDR
|
||||
#undef FLASH
|
||||
#define SPIFLASH
|
||||
#undef RAMENV /* hold environment in flash */
|
||||
#else
|
||||
#undef FLASH
|
||||
#undef SPIFLASH
|
||||
#define RAMENV /* hold environment in RAM */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* uart */
|
||||
#ifdef XILINX_UARTLITE_BASEADDR
|
||||
# define CONFIG_XILINX_UARTLITE
|
||||
|
@ -88,7 +110,6 @@
|
|||
|
||||
/* interrupt controller */
|
||||
#ifdef XILINX_INTC_BASEADDR
|
||||
# define CONFIG_SYS_INTC_0 1
|
||||
# define CONFIG_SYS_INTC_0_ADDR XILINX_INTC_BASEADDR
|
||||
# define CONFIG_SYS_INTC_0_NUM XILINX_INTC_NUM_INTR_INPUTS
|
||||
#endif
|
||||
|
@ -113,15 +134,19 @@
|
|||
|
||||
/*
|
||||
* memory layout - Example
|
||||
* CONFIG_SYS_TEXT_BASE = 0x1200_0000;
|
||||
* CONFIG_SYS_TEXT_BASE = 0x1200_0000; defined in config.mk
|
||||
* CONFIG_SYS_SRAM_BASE = 0x1000_0000;
|
||||
* CONFIG_SYS_SRAM_SIZE = 0x0400_0000;
|
||||
* CONFIG_SYS_SRAM_SIZE = 0x0400_0000; 64MB
|
||||
*
|
||||
* CONFIG_SYS_MONITOR_LEN = 0x40000
|
||||
* CONFIG_SYS_MALLOC_LEN = 3 * CONFIG_SYS_MONITOR_LEN = 0xC0000
|
||||
*
|
||||
* CONFIG_SYS_GBL_DATA_OFFSET = 0x1000_0000 + 0x0400_0000 - 0x1000 = 0x13FF_F000
|
||||
* CONFIG_SYS_MONITOR_BASE = 0x13FF_F000 - 0x40000 = 0x13FB_F000
|
||||
* CONFIG_SYS_MALLOC_BASE = 0x13FB_F000 - 0x40000 = 0x13F7_F000
|
||||
* CONFIG_SYS_MONITOR_BASE = 0x13FF_F000 - CONFIG_SYS_MONITOR_LEN = 0x13FB_F000
|
||||
* CONFIG_SYS_MALLOC_BASE = 0x13FB_F000 - CONFIG_SYS_MALLOC_LEN = 0x13EF_F000
|
||||
*
|
||||
* 0x1000_0000 CONFIG_SYS_SDRAM_BASE
|
||||
* MEMTEST_AREA 64kB
|
||||
* FREE
|
||||
* 0x1200_0000 CONFIG_SYS_TEXT_BASE
|
||||
* U-BOOT code
|
||||
|
@ -129,9 +154,9 @@
|
|||
* FREE
|
||||
*
|
||||
* STACK
|
||||
* 0x13F7_F000 CONFIG_SYS_MALLOC_BASE
|
||||
* MALLOC_AREA 256kB Alloc
|
||||
* 0x11FB_F000 CONFIG_SYS_MONITOR_BASE
|
||||
* 0x13EF_F000 CONFIG_SYS_MALLOC_BASE
|
||||
* MALLOC_AREA 768kB Alloc
|
||||
* 0x13FB_F000 CONFIG_SYS_MONITOR_BASE
|
||||
* MONITOR_CODE 256kB Env
|
||||
* 0x13FF_F000 CONFIG_SYS_GBL_DATA_OFFSET
|
||||
* GLOBAL_DATA 4kB bd, gd
|
||||
|
@ -157,15 +182,30 @@
|
|||
- CONFIG_SYS_MONITOR_LEN - GENERATED_BD_INFO_SIZE)
|
||||
#define CONFIG_SYS_MONITOR_END \
|
||||
(CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)
|
||||
#define CONFIG_SYS_MALLOC_LEN SIZE
|
||||
#define CONFIG_SYS_MALLOC_LEN (SIZE * 3)
|
||||
#define CONFIG_SYS_MALLOC_BASE \
|
||||
(CONFIG_SYS_MONITOR_BASE - CONFIG_SYS_MALLOC_LEN)
|
||||
|
||||
/* stack */
|
||||
#define CONFIG_SYS_INIT_SP_OFFSET CONFIG_SYS_MALLOC_BASE
|
||||
|
||||
/*#define RAMENV */
|
||||
#define FLASH
|
||||
/*
|
||||
* CFI flash memory layout - Example
|
||||
* CONFIG_SYS_FLASH_BASE = 0x2200_0000;
|
||||
* CONFIG_SYS_FLASH_SIZE = 0x0080_0000; 8MB
|
||||
*
|
||||
* SECT_SIZE = 0x20000; 128kB is one sector
|
||||
* CONFIG_ENV_SIZE = SECT_SIZE; 128kB environment store
|
||||
*
|
||||
* 0x2200_0000 CONFIG_SYS_FLASH_BASE
|
||||
* FREE 256kB
|
||||
* 0x2204_0000 CONFIG_ENV_ADDR
|
||||
* ENV_AREA 128kB
|
||||
* 0x2206_0000
|
||||
* FREE
|
||||
* 0x2280_0000 CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_SIZE
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef FLASH
|
||||
# define CONFIG_SYS_FLASH_BASE XILINX_FLASH_START
|
||||
|
@ -186,22 +226,51 @@
|
|||
# define CONFIG_ENV_SIZE 0x1000
|
||||
# define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
|
||||
|
||||
# else /* !RAMENV */
|
||||
# else /* FLASH && !RAMENV */
|
||||
# define CONFIG_ENV_IS_IN_FLASH 1
|
||||
/* 128K(one sector) for env */
|
||||
# define CONFIG_ENV_SECT_SIZE 0x20000
|
||||
# define CONFIG_ENV_ADDR \
|
||||
(CONFIG_SYS_FLASH_BASE + (2 * CONFIG_ENV_SECT_SIZE))
|
||||
# define CONFIG_ENV_SIZE 0x20000
|
||||
# endif /* !RAMBOOT */
|
||||
# endif /* FLASH && !RAMBOOT */
|
||||
#else /* !FLASH */
|
||||
|
||||
#ifdef SPIFLASH
|
||||
# define CONFIG_SYS_NO_FLASH 1
|
||||
# define CONFIG_SYS_SPI_BASE XILINX_SPI_FLASH_BASEADDR
|
||||
# define CONFIG_XILINX_SPI 1
|
||||
# define CONFIG_SPI 1
|
||||
# define CONFIG_SPI_FLASH 1
|
||||
# define CONFIG_SPI_FLASH_STMICRO 1
|
||||
# define CONFIG_SF_DEFAULT_MODE SPI_MODE_3
|
||||
# define CONFIG_SF_DEFAULT_SPEED XILINX_SPI_FLASH_MAX_FREQ
|
||||
# define CONFIG_SF_DEFAULT_CS XILINX_SPI_FLASH_CS
|
||||
|
||||
# ifdef RAMENV
|
||||
# define CONFIG_ENV_IS_NOWHERE 1
|
||||
# define CONFIG_ENV_SIZE 0x1000
|
||||
# define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
|
||||
|
||||
# else /* SPIFLASH && !RAMENV */
|
||||
# define CONFIG_ENV_IS_IN_SPI_FLASH 1
|
||||
# define CONFIG_ENV_SPI_MODE SPI_MODE_3
|
||||
# define CONFIG_ENV_SPI_MAX_HZ CONFIG_SF_DEFAULT_SPEED
|
||||
# define CONFIG_ENV_SPI_CS CONFIG_SF_DEFAULT_CS
|
||||
/* 128K(two sectors) for env */
|
||||
# define CONFIG_ENV_SECT_SIZE 0x10000
|
||||
# define CONFIG_ENV_SIZE (2 * CONFIG_ENV_SECT_SIZE)
|
||||
/* Warning: adjust the offset in respect of other flash content and size */
|
||||
# define CONFIG_ENV_OFFSET (128 * CONFIG_ENV_SECT_SIZE) /* at 8MB */
|
||||
# endif /* SPIFLASH && !RAMBOOT */
|
||||
#else /* !SPIFLASH */
|
||||
|
||||
/* ENV in RAM */
|
||||
# define CONFIG_SYS_NO_FLASH 1
|
||||
# define CONFIG_ENV_IS_NOWHERE 1
|
||||
# define CONFIG_ENV_SIZE 0x1000
|
||||
# define CONFIG_ENV_ADDR (CONFIG_SYS_MONITOR_BASE - CONFIG_ENV_SIZE)
|
||||
/* hardware flash protection */
|
||||
# define CONFIG_SYS_FLASH_PROTECTION
|
||||
#endif /* !SPIFLASH */
|
||||
#endif /* !FLASH */
|
||||
|
||||
/* system ace */
|
||||
|
@ -269,6 +338,17 @@
|
|||
# define CONFIG_CMD_FLASH
|
||||
# define CONFIG_CMD_IMLS
|
||||
# define CONFIG_CMD_JFFS2
|
||||
# define CONFIG_CMD_UBI
|
||||
# undef CONFIG_CMD_UBIFS
|
||||
|
||||
# if !defined(RAMENV)
|
||||
# define CONFIG_CMD_SAVEENV
|
||||
# define CONFIG_CMD_SAVES
|
||||
# endif
|
||||
|
||||
#else
|
||||
#if defined(SPIFLASH)
|
||||
# define CONFIG_CMD_SF
|
||||
|
||||
# if !defined(RAMENV)
|
||||
# define CONFIG_CMD_SAVEENV
|
||||
|
@ -278,10 +358,27 @@
|
|||
# undef CONFIG_CMD_IMLS
|
||||
# undef CONFIG_CMD_FLASH
|
||||
# undef CONFIG_CMD_JFFS2
|
||||
# undef CONFIG_CMD_UBI
|
||||
# undef CONFIG_CMD_UBIFS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_JFFS2)
|
||||
/* JFFS2 partitions */
|
||||
# define CONFIG_MTD_PARTITIONS
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_UBIFS)
|
||||
# define CONFIG_CMD_UBI
|
||||
# define CONFIG_LZO
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_CMD_UBI)
|
||||
# define CONFIG_MTD_PARTITIONS
|
||||
# define CONFIG_RBTREE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MTD_PARTITIONS)
|
||||
/* MTD partitions */
|
||||
#define CONFIG_CMD_MTDPARTS /* mtdparts command line support */
|
||||
#define CONFIG_MTD_DEVICE /* needed for mtdparts commands */
|
||||
#define CONFIG_FLASH_CFI_MTD
|
||||
|
|
Loading…
Reference in a new issue