diff options
26 files changed, 680 insertions, 375 deletions
diff --git a/arch/microblaze/config.mk b/arch/microblaze/config.mk index abea70b..aca79e2 100644 --- a/arch/microblaze/config.mk +++ b/arch/microblaze/config.mk @@ -29,3 +29,5 @@ CROSS_COMPILE ?= mb- CONFIG_STANDALONE_LOAD_ADDR ?= 0x80F00000 PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__ + +LDSCRIPT ?= $(SRCTREE)/$(CPUDIR)/u-boot.lds diff --git a/arch/microblaze/cpu/interrupts.c b/arch/microblaze/cpu/interrupts.c index e7ca859..ee67082 100644 --- a/arch/microblaze/cpu/interrupts.c +++ b/arch/microblaze/cpu/interrupts.c @@ -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"); - - 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); + if (irq_no) { + puts("\nInterrupt-Information:\n\n" + "Nr Routine Arg Count\n" + "-----------------------------\n"); + + 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 diff --git a/arch/microblaze/cpu/start.S b/arch/microblaze/cpu/start.S index 9077f74..8a2f634 100644 --- a/arch/microblaze/cpu/start.S +++ b/arch/microblaze/cpu/start.S @@ -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 */ diff --git a/arch/microblaze/cpu/timer.c b/arch/microblaze/cpu/timer.c index 1952804..cc6b897 100644 --- a/arch/microblaze/cpu/timer.c +++ b/arch/microblaze/cpu/timer.c @@ -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). diff --git a/board/xilinx/microblaze-generic/u-boot.lds b/arch/microblaze/cpu/u-boot.lds index ee41145..ee41145 100644 --- a/board/xilinx/microblaze-generic/u-boot.lds +++ b/arch/microblaze/cpu/u-boot.lds diff --git a/arch/microblaze/include/asm/gpio.h b/arch/microblaze/include/asm/gpio.h new file mode 100644 index 0000000..883f4d4 --- /dev/null +++ b/arch/microblaze/include/asm/gpio.h @@ -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 + diff --git a/arch/microblaze/include/asm/microblaze_intc.h b/arch/microblaze/include/asm/microblaze_intc.h index 4c385aa..6142b9c 100644 --- a/arch/microblaze/include/asm/microblaze_intc.h +++ b/arch/microblaze/include/asm/microblaze_intc.h @@ -41,3 +41,6 @@ struct irq_action { void install_interrupt_handler (int irq, interrupt_handler_t * hdlr, void *arg); + +int interrupts_init(void); + diff --git a/arch/microblaze/lib/Makefile b/arch/microblaze/lib/Makefile index de0a7d3..7730695 100644 --- a/arch/microblaze/lib/Makefile +++ b/arch/microblaze/lib/Makefile @@ -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)) diff --git a/arch/microblaze/lib/board.c b/arch/microblaze/lib/board.c index f3679d5..b80250a 100644 --- a/arch/microblaze/lib/board.c +++ b/arch/microblaze/lib/board.c @@ -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) { diff --git a/arch/microblaze/lib/time.c b/arch/microblaze/lib/time.c index da016a0..e69de29 100644 --- a/arch/microblaze/lib/time.c +++ b/arch/microblaze/lib/time.c @@ -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 diff --git a/board/xilinx/dts/microblaze.dts b/board/xilinx/dts/microblaze.dts new file mode 100644 index 0000000..bf984b0 --- /dev/null +++ b/board/xilinx/dts/microblaze.dts @@ -0,0 +1 @@ +/include/ BOARD_DTS diff --git a/board/xilinx/microblaze-generic/dts/microblaze.dts b/board/xilinx/microblaze-generic/dts/microblaze.dts new file mode 100644 index 0000000..2033309 --- /dev/null +++ b/board/xilinx/microblaze-generic/dts/microblaze.dts @@ -0,0 +1,7 @@ +/dts-v1/; +/ { + #address-cells = <1>; + #size-cells = <1>; + aliases { + } ; +} ; diff --git a/common/cmd_sf.c b/common/cmd_sf.c index 9c76464..5ac1d0c 100644 --- a/common/cmd_sf.c +++ b/common/cmd_sf.c @@ -211,6 +211,13 @@ static int do_spi_flash_read_write(int argc, char * const argv[]) if (*argv[3] == 0 || *endp != 0) return -1; + /* Consistency checking */ + if (offset + len > flash->size) { + printf("ERROR: attempting %s past flash size (%#x)\n", + argv[0], flash->size); + return 1; + } + buf = map_physmem(addr, len, MAP_WRBACK); if (!buf) { puts("Failed to map physical memory\n"); @@ -252,6 +259,13 @@ static int do_spi_flash_erase(int argc, char * const argv[]) if (ret != 1) return -1; + /* Consistency checking */ + if (offset + len > flash->size) { + printf("ERROR: attempting %s past flash size (%#x)\n", + argv[0], flash->size); + return 1; + } + ret = spi_flash_erase(flash, offset, len); if (ret) { printf("SPI flash %s failed\n", argv[0]); diff --git a/drivers/mtd/spi/eon.c b/drivers/mtd/spi/eon.c index 6a3bf0f..691ed4e 100644 --- a/drivers/mtd/spi/eon.c +++ b/drivers/mtd/spi/eon.c @@ -10,15 +10,8 @@ #include "spi_flash_internal.h" -/* EN25Q128-specific commands */ -#define CMD_EN25Q128_SE 0x20 /* Sector Erase */ -#define CMD_EN25Q128_BE 0xd8 /* Block Erase */ - struct eon_spi_flash_params { u8 idcode1; - u16 page_size; - u16 pages_per_sector; - u16 sectors_per_block; u16 nr_sectors; const char *name; }; @@ -26,35 +19,16 @@ struct eon_spi_flash_params { static const struct eon_spi_flash_params eon_spi_flash_table[] = { { .idcode1 = 0x16, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_sectors = 1024, .name = "EN25Q32B", }, { .idcode1 = 0x18, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_sectors = 4096, .name = "EN25Q128", }, - { - .idcode1 = 0x16, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, - .nr_sectors = 1024, - .name = "EN25Q32B", - }, }; -static int eon_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_EN25Q128_BE, offset, len); -} - struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) { const struct eon_spi_flash_params *params; @@ -82,12 +56,11 @@ struct spi_flash *spi_flash_probe_eon(struct spi_slave *spi, u8 *idcode) flash->name = params->name; flash->write = spi_flash_cmd_write_multi; - flash->erase = eon_erase; + flash->erase = spi_flash_cmd_erase; flash->read = spi_flash_cmd_read_fast; - flash->page_size = params->page_size; - flash->sector_size = params->page_size * params->pages_per_sector - * params->sectors_per_block; - flash->size = params->page_size * params->pages_per_sector + flash->page_size = 256; + flash->sector_size = 256 * 16 * 16; + flash->size = 256 * 16 * params->nr_sectors; return flash; diff --git a/drivers/mtd/spi/macronix.c b/drivers/mtd/spi/macronix.c index 87a3ad0..c97a39d 100644 --- a/drivers/mtd/spi/macronix.c +++ b/drivers/mtd/spi/macronix.c @@ -35,16 +35,8 @@ #include "spi_flash_internal.h" -/* MX25xx-specific commands */ -#define CMD_MX25XX_SE 0x20 /* Sector Erase */ -#define CMD_MX25XX_BE 0xD8 /* Block Erase */ -#define CMD_MX25XX_CE 0xc7 /* Chip Erase */ - struct macronix_spi_flash_params { u16 idcode; - u16 page_size; - u16 pages_per_sector; - u16 sectors_per_block; u16 nr_blocks; const char *name; }; @@ -52,106 +44,41 @@ struct macronix_spi_flash_params { static const struct macronix_spi_flash_params macronix_spi_flash_table[] = { { .idcode = 0x2013, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 8, .name = "MX25L4005", }, { .idcode = 0x2014, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 16, .name = "MX25L8005", }, { .idcode = 0x2015, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 32, .name = "MX25L1605D", }, { .idcode = 0x2016, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 64, .name = "MX25L3205D", }, { .idcode = 0x2017, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 128, .name = "MX25L6405D", }, { .idcode = 0x2018, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 256, .name = "MX25L12805D", }, { .idcode = 0x2618, - .page_size = 256, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 256, .name = "MX25L12855E", }, }; -static int macronix_write_status(struct spi_flash *flash, u8 sr) -{ - u8 cmd; - int ret; - - ret = spi_flash_cmd_write_enable(flash); - if (ret < 0) { - debug("SF: enabling write failed\n"); - return ret; - } - - cmd = CMD_WRITE_STATUS; - ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1); - if (ret) { - debug("SF: fail to write status register\n"); - return ret; - } - - ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); - if (ret < 0) { - debug("SF: write status register timed out\n"); - return ret; - } - - return 0; -} - -static int macronix_unlock(struct spi_flash *flash) -{ - int ret; - - /* Enable status register writing and clear BP# bits */ - ret = macronix_write_status(flash, 0); - if (ret) - debug("SF: fail to disable write protection\n"); - - return ret; -} - -static int macronix_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_MX25XX_BE, offset, len); -} - struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) { const struct macronix_spi_flash_params *params; @@ -180,15 +107,14 @@ struct spi_flash *spi_flash_probe_macronix(struct spi_slave *spi, u8 *idcode) flash->name = params->name; flash->write = spi_flash_cmd_write_multi; - flash->erase = macronix_erase; + flash->erase = spi_flash_cmd_erase; flash->read = spi_flash_cmd_read_fast; - flash->page_size = params->page_size; - flash->sector_size = params->page_size * params->pages_per_sector - * params->sectors_per_block; + flash->page_size = 256; + flash->sector_size = 256 * 16 * 16; flash->size = flash->sector_size * params->nr_blocks; /* Clear BP# bits for read-only flash */ - macronix_unlock(flash); + spi_flash_cmd_write_status(flash, 0); return flash; } diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c index 457cc06..9a114ac 100644 --- a/drivers/mtd/spi/spansion.c +++ b/drivers/mtd/spi/spansion.c @@ -31,14 +31,9 @@ #include "spi_flash_internal.h" -/* S25FLxx-specific commands */ -#define CMD_S25FLXX_SE 0xd8 /* Sector Erase */ -#define CMD_S25FLXX_BE 0xc7 /* Bulk Erase */ - struct spansion_spi_flash_params { u16 idcode1; u16 idcode2; - u16 page_size; u16 pages_per_sector; u16 nr_sectors; const char *name; @@ -48,7 +43,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x0213, .idcode2 = 0, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 16, .name = "S25FL008A", @@ -56,7 +50,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x0214, .idcode2 = 0, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 32, .name = "S25FL016A", @@ -64,7 +57,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x0215, .idcode2 = 0, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 64, .name = "S25FL032A", @@ -72,7 +64,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x0216, .idcode2 = 0, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 128, .name = "S25FL064A", @@ -80,7 +71,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x2018, .idcode2 = 0x0301, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 256, .name = "S25FL128P_64K", @@ -88,7 +78,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x2018, .idcode2 = 0x0300, - .page_size = 256, .pages_per_sector = 1024, .nr_sectors = 64, .name = "S25FL128P_256K", @@ -96,7 +85,6 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x0215, .idcode2 = 0x4d00, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 64, .name = "S25FL032P", @@ -104,18 +92,12 @@ static const struct spansion_spi_flash_params spansion_spi_flash_table[] = { { .idcode1 = 0x2018, .idcode2 = 0x4d01, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 256, .name = "S25FL129P_64K", }, }; -static int spansion_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_S25FLXX_SE, offset, len); -} - struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) { const struct spansion_spi_flash_params *params; @@ -149,10 +131,10 @@ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode) flash->name = params->name; flash->write = spi_flash_cmd_write_multi; - flash->erase = spansion_erase; + flash->erase = spi_flash_cmd_erase; flash->read = spi_flash_cmd_read_fast; - flash->page_size = params->page_size; - flash->sector_size = params->page_size * params->pages_per_sector; + flash->page_size = 256; + flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; return flash; diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index f689cc4..00aece9 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -190,8 +190,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout) CMD_READ_STATUS, STATUS_WIP); } -int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, - u32 offset, size_t len) +int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len) { u32 start, end, erase_size; int ret; @@ -209,7 +208,10 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, return ret; } - cmd[0] = erase_cmd; + if (erase_size == 4096) + cmd[0] = CMD_ERASE_4K; + else + cmd[0] = CMD_ERASE_64K; start = offset; end = start + len; @@ -240,6 +242,33 @@ int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, return ret; } +int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr) +{ + u8 cmd; + int ret; + + ret = spi_flash_cmd_write_enable(flash); + if (ret < 0) { + debug("SF: enabling write failed\n"); + return ret; + } + + cmd = CMD_WRITE_STATUS; + ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &sr, 1); + if (ret) { + debug("SF: fail to write status register\n"); + return ret; + } + + ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret < 0) { + debug("SF: write status register timed out\n"); + return ret; + } + + return 0; +} + /* * The following table holds all device probe functions * diff --git a/drivers/mtd/spi/spi_flash_internal.h b/drivers/mtd/spi/spi_flash_internal.h index 0c78249..141cfa8 100644 --- a/drivers/mtd/spi/spi_flash_internal.h +++ b/drivers/mtd/spi/spi_flash_internal.h @@ -23,6 +23,10 @@ #define CMD_WRITE_DISABLE 0x04 #define CMD_READ_STATUS 0x05 #define CMD_WRITE_ENABLE 0x06 +#define CMD_ERASE_4K 0x20 +#define CMD_ERASE_32K 0x52 +#define CMD_ERASE_64K 0xd8 +#define CMD_ERASE_CHIP 0xc7 /* Common status */ #define STATUS_WIP 0x01 @@ -70,6 +74,9 @@ static inline int spi_flash_cmd_write_disable(struct spi_flash *flash) return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); } +/* Program the status register. */ +int spi_flash_cmd_write_status(struct spi_flash *flash, u8 sr); + /* * Same as spi_flash_cmd_read() except it also claims/releases the SPI * bus. Used as common part of the ->read() operation. @@ -88,8 +95,7 @@ int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout, int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); /* Erase sectors. */ -int spi_flash_cmd_erase(struct spi_flash *flash, u8 erase_cmd, - u32 offset, size_t len); +int spi_flash_cmd_erase(struct spi_flash *flash, u32 offset, size_t len); /* Manufacturer-specific probe functions */ struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode); diff --git a/drivers/mtd/spi/sst.c b/drivers/mtd/spi/sst.c index e51dfc7..ced4f24 100644 --- a/drivers/mtd/spi/sst.c +++ b/drivers/mtd/spi/sst.c @@ -20,7 +20,6 @@ #define CMD_SST_BP 0x02 /* Byte Program */ #define CMD_SST_AAI_WP 0xAD /* Auto Address Increment Word Program */ -#define CMD_SST_SE 0x20 /* Sector Erase */ #define SST_SR_WIP (1 << 0) /* Write-in-Progress */ #define SST_SR_WEL (1 << 1) /* Write enable */ @@ -45,13 +44,6 @@ struct sst_spi_flash { const struct sst_spi_flash_params *params; }; -static inline struct sst_spi_flash *to_sst_spi_flash(struct spi_flash *flash) -{ - return container_of(flash, struct sst_spi_flash, flash); -} - -#define SST_SECTOR_SIZE (4 * 1024) -#define SST_PAGE_SIZE 256 static const struct sst_spi_flash_params sst_spi_flash_table[] = { { .idcode1 = 0x8d, @@ -102,24 +94,6 @@ static const struct sst_spi_flash_params sst_spi_flash_table[] = { }; static int -sst_enable_writing(struct spi_flash *flash) -{ - int ret = spi_flash_cmd_write_enable(flash); - if (ret) - debug("SF: Enabling Write failed\n"); - return ret; -} - -static int -sst_disable_writing(struct spi_flash *flash) -{ - int ret = spi_flash_cmd_write_disable(flash); - if (ret) - debug("SF: Disabling Write failed\n"); - return ret; -} - -static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) { int ret; @@ -133,7 +107,7 @@ sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset); - ret = sst_enable_writing(flash); + ret = spi_flash_cmd_write_enable(flash); if (ret) return ret; @@ -166,7 +140,7 @@ sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf) } offset += actual; - ret = sst_enable_writing(flash); + ret = spi_flash_cmd_write_enable(flash); if (ret) goto done; @@ -197,7 +171,7 @@ sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf) } if (!ret) - ret = sst_disable_writing(flash); + ret = spi_flash_cmd_write_disable(flash); /* If there is a single trailing byte, write it out */ if (!ret && actual != len) @@ -211,32 +185,6 @@ sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, const void *buf) return ret; } -static int sst_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_SST_SE, offset, len); -} - -static int -sst_unlock(struct spi_flash *flash) -{ - int ret; - u8 cmd, status; - - ret = sst_enable_writing(flash); - if (ret) - return ret; - - cmd = CMD_WRITE_STATUS; - status = 0; - ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &status, 1); - if (ret) - debug("SF: Unable to set status byte\n"); - - debug("SF: sst: status = %x\n", spi_w8r8(flash->spi, CMD_READ_STATUS)); - - return ret; -} - struct spi_flash * spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode) { @@ -269,14 +217,14 @@ spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode) stm->flash.write = sst_write_wp; else stm->flash.write = spi_flash_cmd_write_multi; - stm->flash.erase = sst_erase; + stm->flash.erase = spi_flash_cmd_erase; stm->flash.read = spi_flash_cmd_read_fast; - stm->flash.page_size = SST_PAGE_SIZE; - stm->flash.sector_size = SST_SECTOR_SIZE; + stm->flash.page_size = 256; + stm->flash.sector_size = 4096; stm->flash.size = stm->flash.sector_size * params->nr_sectors; /* Flash powers up read-only, so clear BP# bits */ - sst_unlock(&stm->flash); + spi_flash_cmd_write_status(&stm->flash, 0); return &stm->flash; } diff --git a/drivers/mtd/spi/stmicro.c b/drivers/mtd/spi/stmicro.c index 5b68479..dbd1fc1 100644 --- a/drivers/mtd/spi/stmicro.c +++ b/drivers/mtd/spi/stmicro.c @@ -34,13 +34,10 @@ #include "spi_flash_internal.h" /* M25Pxx-specific commands */ -#define CMD_M25PXX_SE 0xd8 /* Sector Erase */ -#define CMD_M25PXX_BE 0xc7 /* Bulk Erase */ #define CMD_M25PXX_RES 0xab /* Release from DP, and Read Signature */ struct stmicro_spi_flash_params { u8 idcode1; - u16 page_size; u16 pages_per_sector; u16 nr_sectors; const char *name; @@ -49,67 +46,60 @@ struct stmicro_spi_flash_params { static const struct stmicro_spi_flash_params stmicro_spi_flash_table[] = { { .idcode1 = 0x11, - .page_size = 256, .pages_per_sector = 128, .nr_sectors = 4, .name = "M25P10", }, { .idcode1 = 0x15, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 32, .name = "M25P16", }, { .idcode1 = 0x12, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 4, .name = "M25P20", }, { .idcode1 = 0x16, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 64, .name = "M25P32", }, { .idcode1 = 0x13, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 8, .name = "M25P40", }, { .idcode1 = 0x17, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 128, .name = "M25P64", }, { .idcode1 = 0x14, - .page_size = 256, .pages_per_sector = 256, .nr_sectors = 16, .name = "M25P80", }, { .idcode1 = 0x18, - .page_size = 256, .pages_per_sector = 1024, .nr_sectors = 64, .name = "M25P128", }, + { + .idcode1 = 0x19, + .pages_per_sector = 256, + .nr_sectors = 512, + .name = "N25Q256", + }, }; -static int stmicro_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_M25PXX_SE, offset, len); -} - struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) { const struct stmicro_spi_flash_params *params; @@ -151,10 +141,10 @@ struct spi_flash *spi_flash_probe_stmicro(struct spi_slave *spi, u8 * idcode) flash->name = params->name; flash->write = spi_flash_cmd_write_multi; - flash->erase = stmicro_erase; + flash->erase = spi_flash_cmd_erase; flash->read = spi_flash_cmd_read_fast; - flash->page_size = params->page_size; - flash->sector_size = params->page_size * params->pages_per_sector; + flash->page_size = 256; + flash->sector_size = 256 * params->pages_per_sector; flash->size = flash->sector_size * params->nr_sectors; return flash; diff --git a/drivers/mtd/spi/winbond.c b/drivers/mtd/spi/winbond.c index 0e126f4..427b71f 100644 --- a/drivers/mtd/spi/winbond.c +++ b/drivers/mtd/spi/winbond.c @@ -10,17 +10,8 @@ #include "spi_flash_internal.h" -/* M25Pxx-specific commands */ -#define CMD_W25_SE 0x20 /* Sector (4K) Erase */ -#define CMD_W25_BE 0xd8 /* Block (64K) Erase */ -#define CMD_W25_CE 0xc7 /* Chip Erase */ - struct winbond_spi_flash_params { uint16_t id; - /* Log2 of page size in power-of-two mode */ - uint8_t l2_page_size; - uint16_t pages_per_sector; - uint16_t sectors_per_block; uint16_t nr_blocks; const char *name; }; @@ -28,89 +19,56 @@ struct winbond_spi_flash_params { static const struct winbond_spi_flash_params winbond_spi_flash_table[] = { { .id = 0x3013, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 8, .name = "W25X40", }, { .id = 0x3015, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 32, .name = "W25X16", }, { .id = 0x3016, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 64, .name = "W25X32", }, { .id = 0x3017, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 128, .name = "W25X64", }, { .id = 0x4014, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 16, .name = "W25Q80BL", }, { .id = 0x4015, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 32, .name = "W25Q16", }, { .id = 0x4016, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 64, .name = "W25Q32", }, { .id = 0x4017, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 128, .name = "W25Q64", }, { .id = 0x4018, - .l2_page_size = 8, - .pages_per_sector = 16, - .sectors_per_block = 16, .nr_blocks = 256, .name = "W25Q128", }, }; -static int winbond_erase(struct spi_flash *flash, u32 offset, size_t len) -{ - return spi_flash_cmd_erase(flash, CMD_W25_SE, offset, len); -} - struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) { const struct winbond_spi_flash_params *params; struct spi_flash *flash; unsigned int i; - unsigned page_size; for (i = 0; i < ARRAY_SIZE(winbond_spi_flash_table); i++) { params = &winbond_spi_flash_table[i]; @@ -133,17 +91,12 @@ struct spi_flash *spi_flash_probe_winbond(struct spi_slave *spi, u8 *idcode) flash->spi = spi; flash->name = params->name; - /* Assuming power-of-two page size initially. */ - page_size = 1 << params->l2_page_size; - flash->write = spi_flash_cmd_write_multi; - flash->erase = winbond_erase; + flash->erase = spi_flash_cmd_erase; flash->read = spi_flash_cmd_read_fast; - flash->page_size = page_size; - flash->sector_size = page_size * params->pages_per_sector; - flash->size = page_size * params->pages_per_sector - * params->sectors_per_block - * params->nr_blocks; + flash->page_size = 4096; + flash->sector_size = 4096; + flash->size = 4096 * 16 * params->nr_blocks; return flash; } diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index c20f1f2..cd3f9fa 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -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) diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c new file mode 100644 index 0000000..e563c19 --- /dev/null +++ b/drivers/spi/xilinx_spi.c @@ -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; +} diff --git a/drivers/spi/xilinx_spi.h b/drivers/spi/xilinx_spi.h new file mode 100644 index 0000000..32610d2 --- /dev/null +++ b/drivers/spi/xilinx_spi.h @@ -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_ */ diff --git a/dts/Makefile b/dts/Makefile index 402dfe1..055b8ac 100644 --- a/dts/Makefile +++ b/dts/Makefile @@ -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) diff --git a/include/configs/microblaze-generic.h b/include/configs/microblaze-generic.h index 295d123..1266cf7 100644 --- a/include/configs/microblaze-generic.h +++ b/include/configs/microblaze-generic.h @@ -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 |