diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 3 | ||||
-rw-r--r-- | common/cmd_bdinfo.c | 32 | ||||
-rw-r--r-- | common/cmd_bootm.c | 5 | ||||
-rw-r--r-- | common/cmd_df.c | 37 | ||||
-rw-r--r-- | common/cmd_doc.c | 19 | ||||
-rw-r--r-- | common/cmd_fdc.c | 15 | ||||
-rw-r--r-- | common/cmd_fdt.c | 142 | ||||
-rw-r--r-- | common/cmd_ide.c | 19 | ||||
-rw-r--r-- | common/cmd_log.c | 8 | ||||
-rw-r--r-- | common/cmd_nand.c | 40 | ||||
-rw-r--r-- | common/cmd_nvedit.c | 14 | ||||
-rw-r--r-- | common/cmd_scsi.c | 15 | ||||
-rw-r--r-- | common/cmd_sf.c | 191 | ||||
-rw-r--r-- | common/cmd_spi.c | 42 | ||||
-rw-r--r-- | common/cmd_usb.c | 15 | ||||
-rw-r--r-- | common/dlmalloc.c | 3 | ||||
-rw-r--r-- | common/env_common.c | 56 | ||||
-rw-r--r-- | common/env_nand.c | 141 | ||||
-rw-r--r-- | common/env_sf.c | 131 | ||||
-rw-r--r-- | common/fdt_support.c | 9 | ||||
-rw-r--r-- | common/ft_build.c | 471 | ||||
-rw-r--r-- | common/image.c | 27 | ||||
-rw-r--r-- | common/lcd.c | 78 | ||||
-rw-r--r-- | common/main.c | 8 | ||||
-rw-r--r-- | common/soft_i2c.c | 1 | ||||
-rw-r--r-- | common/soft_spi.c | 124 |
26 files changed, 898 insertions, 748 deletions
diff --git a/common/Makefile b/common/Makefile index 9678799..4287108 100644 --- a/common/Makefile +++ b/common/Makefile @@ -113,12 +113,12 @@ COBJS-y += env_dataflash.o COBJS-y += env_flash.o COBJS-y += env_eeprom.o COBJS-y += env_onenand.o +COBJS-y += env_sf.o COBJS-y += env_nvram.o COBJS-y += env_nowhere.o COBJS-y += exports.o COBJS-y += flash.o COBJS-y += fpga.o -COBJS-y += ft_build.o COBJS-y += hush.o COBJS-y += kgdb.o COBJS-y += lcd.o @@ -143,6 +143,7 @@ COBJS-y += xyzModem.o COBJS-y += cmd_mac.o COBJS-$(CONFIG_CMD_MFSL) += cmd_mfsl.o COBJS-$(CONFIG_MP) += cmd_mp.o +COBJS-$(CONFIG_CMD_SF) += cmd_sf.o COBJS := $(COBJS-y) SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 731c1d2..caa467d 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -33,6 +33,7 @@ DECLARE_GLOBAL_DATA_PTR; static void print_num(const char *, ulong); #ifndef CONFIG_ARM /* PowerPC and other */ +static void print_lnum(const char *, u64); #ifdef CONFIG_PPC static void print_str(const char *, const char *); @@ -47,7 +48,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) print_num ("bd address", (ulong)bd ); #endif print_num ("memstart", bd->bi_memstart ); - print_num ("memsize", bd->bi_memsize ); + print_lnum ("memsize", bd->bi_memsize ); print_num ("flashstart", bd->bi_flashstart ); print_num ("flashsize", bd->bi_flashsize ); print_num ("flashoffset", bd->bi_flashoffset ); @@ -59,18 +60,18 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #endif print_num ("bootflags", bd->bi_bootflags ); #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ - defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300) || \ + defined(CONFIG_405EP) || defined(CONFIG_XILINX_405) || \ defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ defined(CONFIG_440SP) || defined(CONFIG_440SPE) print_str ("procfreq", strmhz(buf, bd->bi_procfreq)); print_str ("plb_busfreq", strmhz(buf, bd->bi_plb_busfreq)); -#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_ML300) || \ +#if defined(CONFIG_405GP) || defined(CONFIG_405EP) || defined(CONFIG_XILINX_405) || \ defined(CONFIG_440EP) || defined(CONFIG_440GR) || defined(CONFIG_440SPE) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) print_str ("pci_busfreq", strmhz(buf, bd->bi_pci_busfreq)); #endif -#else /* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300, CONFIG_440EP CONFIG_440GR */ +#else /* ! CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_405, CONFIG_440EP CONFIG_440GR */ #if defined(CONFIG_CPM2) print_str ("vco", strmhz(buf, bd->bi_vco)); print_str ("sccfreq", strmhz(buf, bd->bi_sccfreq)); @@ -81,7 +82,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) print_str ("cpmfreq", strmhz(buf, bd->bi_cpmfreq)); #endif print_str ("busfreq", strmhz(buf, bd->bi_busfreq)); -#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_ML300, CONFIG_440EP CONFIG_440GR */ +#endif /* CONFIG_405GP, CONFIG_405CR, CONFIG_405EP, CONFIG_XILINX_405, CONFIG_440EP CONFIG_440GR */ #if defined(CONFIG_MPC8220) print_str ("inpfreq", strmhz(buf, bd->bi_inpfreq)); print_str ("flbfreq", strmhz(buf, bd->bi_flbfreq)); @@ -132,7 +133,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) bd_t *bd = gd->bd; print_num ("memstart", (ulong)bd->bi_memstart); - print_num ("memsize", (ulong)bd->bi_memsize); + print_lnum ("memsize", (u64)bd->bi_memsize); print_num ("flashstart", (ulong)bd->bi_flashstart); print_num ("flashsize", (ulong)bd->bi_flashsize); print_num ("flashoffset", (ulong)bd->bi_flashoffset); @@ -158,7 +159,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) bd_t *bd = gd->bd; print_num ("mem start", (ulong)bd->bi_memstart); - print_num ("mem size", (ulong)bd->bi_memsize); + print_lnum ("mem size", (u64)bd->bi_memsize); print_num ("flash start", (ulong)bd->bi_flashstart); print_num ("flash size", (ulong)bd->bi_flashsize); print_num ("flash offset", (ulong)bd->bi_flashoffset); @@ -188,7 +189,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int i; bd_t *bd = gd->bd; print_num ("mem start ", (ulong)bd->bi_memstart); - print_num ("mem size ", (ulong)bd->bi_memsize); + print_lnum ("mem size ", (u64)bd->bi_memsize); print_num ("flash start ", (ulong)bd->bi_flashstart); print_num ("flash size ", (ulong)bd->bi_flashsize); print_num ("flash offset ", (ulong)bd->bi_flashoffset); @@ -220,7 +221,7 @@ int do_bdinfo(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) print_num("bd address ", (ulong) bd); #endif print_num("memstart ", bd->bi_memstart); - print_num("memsize ", bd->bi_memsize); + print_lnum("memsize ", bd->bi_memsize); print_num("flashstart ", bd->bi_flashstart); print_num("CFG_MONITOR_BASE ", CFG_MONITOR_BASE); print_num("CFG_ENV_ADDR ", CFG_ENV_ADDR); @@ -257,7 +258,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char buf[32]; print_num ("memstart", (ulong)bd->bi_memstart); - print_num ("memsize", (ulong)bd->bi_memsize); + print_lnum ("memsize", (u64)bd->bi_memsize); print_num ("flashstart", (ulong)bd->bi_flashstart); print_num ("flashsize", (ulong)bd->bi_flashsize); print_num ("flashoffset", (ulong)bd->bi_flashoffset); @@ -328,7 +329,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) print_num("boot_params", (ulong)bd->bi_boot_params); print_num("memstart", (ulong)bd->bi_memstart); - print_num("memsize", (ulong)bd->bi_memsize); + print_lnum("memsize", (u64)bd->bi_memsize); print_num("flashstart", (ulong)bd->bi_flashstart); print_num("flashsize", (ulong)bd->bi_flashsize); print_num("flashoffset", (ulong)bd->bi_flashoffset); @@ -352,7 +353,7 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) print_num ("boot_params", (ulong)bd->bi_boot_params); print_num ("memstart", (ulong)bd->bi_memstart); - print_num ("memsize", (ulong)bd->bi_memsize); + print_lnum ("memsize", (u64)bd->bi_memsize); print_num ("flashstart", (ulong)bd->bi_flashstart); print_num ("flashsize", (ulong)bd->bi_flashsize); print_num ("flashoffset", (ulong)bd->bi_flashoffset); @@ -408,6 +409,13 @@ static void print_num(const char *name, ulong value) printf ("%-12s= 0x%08lX\n", name, value); } +#ifndef CONFIG_ARM +static void print_lnum(const char *name, u64 value) +{ + printf ("%-12s= 0x%.8llX\n", name, value); +} +#endif + #if defined(CONFIG_PPC) || defined(CONFIG_M68K) static void print_str(const char *name, const char *str) { diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 0d67132..959689e 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -127,7 +127,8 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong os_data, os_len; ulong image_start, image_end; ulong load_start, load_end; - ulong mem_start, mem_size; + ulong mem_start; + phys_size_t mem_size; struct lmb lmb; @@ -141,7 +142,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) mem_start = getenv_bootm_low(); mem_size = getenv_bootm_size(); - lmb_add(&lmb, mem_start, mem_size); + lmb_add(&lmb, (phys_addr_t)mem_start, mem_size); board_lmb_reserve(&lmb); diff --git a/common/cmd_df.c b/common/cmd_df.c new file mode 100644 index 0000000..5f65044 --- /dev/null +++ b/common/cmd_df.c @@ -0,0 +1,37 @@ +/* + * Command for accessing DataFlash. + * + * Copyright (C) 2008 Atmel Corporation + */ +#include <common.h> +#include <df.h> + +static int do_df(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + const char *cmd; + + /* need at least two arguments */ + if (argc < 2) + goto usage; + + cmd = argv[1]; + + if (strcmp(cmd, "init") == 0) { + df_init(0, 0, 1000000); + return 0; + } + + if (strcmp(cmd, "info") == 0) { + df_show_info(); + return 0; + } + +usage: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + sf, 2, 1, do_serial_flash, + "sf - Serial flash sub-system\n", + "probe [bus:]cs - init flash device on given SPI bus and CS\n") diff --git a/common/cmd_doc.c b/common/cmd_doc.c index 83aba37..d7b2f53 100644 --- a/common/cmd_doc.c +++ b/common/cmd_doc.c @@ -206,7 +206,7 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) image_header_t *hdr; int rcode = 0; #if defined(CONFIG_FIT) - const void *fit_hdr; + const void *fit_hdr = NULL; #endif show_boot_progress (34); @@ -275,12 +275,6 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (const void *)addr; - if (!fit_check_format (fit_hdr)) { - show_boot_progress (-130); - puts ("** Bad FIT image format\n"); - return 1; - } - show_boot_progress (131); puts ("Fit image detected...\n"); cnt = fit_get_size (fit_hdr); @@ -304,8 +298,15 @@ int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) - fit_print_contents ((const void *)addr); + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-130); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (131); + fit_print_contents (fit_hdr); + } #endif /* Loading ok, update default load address */ diff --git a/common/cmd_fdc.c b/common/cmd_fdc.c index 0293d18..e4fbf29 100644 --- a/common/cmd_fdc.c +++ b/common/cmd_fdc.c @@ -787,7 +787,7 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) char *ep; int rcode = 0; #if defined(CONFIG_FIT) - const void *fit_hdr; + const void *fit_hdr = NULL; #endif switch (argc) { @@ -847,10 +847,6 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (const void *)addr; - if (!fit_check_format (fit_hdr)) { - puts ("** Bad FIT image format\n"); - return 1; - } puts ("Fit image detected...\n"); imsize = fit_get_size (fit_hdr); @@ -879,8 +875,13 @@ int do_fdcboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) - fit_print_contents ((const void *)addr); + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + fit_print_contents (fit_hdr); + } #endif /* Loading ok, update default load address */ diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index ede65ae..d3b19dd 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -46,6 +46,11 @@ static int fdt_parse_prop(char **newval, int count, char *data, int *len); static int fdt_print(const char *pathp, char *prop, int depth); /* + * The working_fdt points to our working flattened device tree. + */ +struct fdt_header *working_fdt; + +/* * Flattened Device Tree command, see the help for parameter definitions. */ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) @@ -62,7 +67,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* * Set the address [and length] of the fdt. */ - fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); + working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; @@ -75,15 +80,15 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * Optional new length */ len = simple_strtoul(argv[3], NULL, 16); - if (len < fdt_totalsize(fdt)) { + if (len < fdt_totalsize(working_fdt)) { printf ("New length %d < existing length %d, " "ignoring.\n", - len, fdt_totalsize(fdt)); + len, fdt_totalsize(working_fdt)); } else { /* * Open in place with a new length. */ - err = fdt_open_into(fdt, fdt, len); + err = fdt_open_into(working_fdt, working_fdt, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); @@ -92,9 +97,9 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } /******************************************************************** - * Move the fdt + * Move the working_fdt ********************************************************************/ - } else if ((argv[1][0] == 'm') && (argv[1][1] == 'o')) { + } else if (strncmp(argv[1], "mo", 2) == 0) { struct fdt_header *newaddr; int len; int err; @@ -107,7 +112,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* * Set the address and length of the fdt. */ - fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); + working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16); if (!fdt_valid()) { return 1; } @@ -119,13 +124,13 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * current length. */ if (argc <= 4) { - len = fdt_totalsize(fdt); + len = fdt_totalsize(working_fdt); } else { len = simple_strtoul(argv[4], NULL, 16); - if (len < fdt_totalsize(fdt)) { + if (len < fdt_totalsize(working_fdt)) { printf ("New length 0x%X < existing length " "0x%X, aborting.\n", - len, fdt_totalsize(fdt)); + len, fdt_totalsize(working_fdt)); return 1; } } @@ -133,18 +138,18 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /* * Copy to the new location. */ - err = fdt_open_into(fdt, newaddr, len); + err = fdt_open_into(working_fdt, newaddr, len); if (err != 0) { printf ("libfdt fdt_open_into(): %s\n", fdt_strerror(err)); return 1; } - fdt = newaddr; + working_fdt = newaddr; /******************************************************************** * Make a new node ********************************************************************/ - } else if ((argv[1][0] == 'm') && (argv[1][1] == 'k')) { + } else if (strncmp(argv[1], "mk", 2) == 0) { char *pathp; /* path */ char *nodep; /* new node to add */ int nodeoffset; /* node offset from libfdt */ @@ -161,7 +166,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) pathp = argv[2]; nodep = argv[3]; - nodeoffset = fdt_path_offset (fdt, pathp); + nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -170,7 +175,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) fdt_strerror(nodeoffset)); return 1; } - err = fdt_add_subnode(fdt, nodeoffset, nodep); + err = fdt_add_subnode(working_fdt, nodeoffset, nodep); if (err < 0) { printf ("libfdt fdt_add_subnode(): %s\n", fdt_strerror(err)); @@ -178,7 +183,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } /******************************************************************** - * Set the value of a property in the fdt. + * Set the value of a property in the working_fdt. ********************************************************************/ } else if (argv[1][0] == 's') { char *pathp; /* path */ @@ -206,7 +211,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return ret; } - nodeoffset = fdt_path_offset (fdt, pathp); + nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -216,7 +221,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) return 1; } - ret = fdt_setprop(fdt, nodeoffset, prop, data, len); + ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len); if (ret < 0) { printf ("libfdt fdt_setprop(): %s\n", fdt_strerror(ret)); return 1; @@ -259,7 +264,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) /******************************************************************** * Remove a property/node ********************************************************************/ - } else if ((argv[1][0] == 'r') && (argv[1][1] == 'm')) { + } else if (strncmp(argv[1], "rm", 2) == 0) { int nodeoffset; /* node offset from libfdt */ int err; @@ -267,7 +272,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * Get the path. The root node is an oddball, the offset * is zero and has no name. */ - nodeoffset = fdt_path_offset (fdt, argv[2]); + nodeoffset = fdt_path_offset (working_fdt, argv[2]); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -281,14 +286,14 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * otherwise delete the node. */ if (argc > 3) { - err = fdt_delprop(fdt, nodeoffset, argv[3]); + err = fdt_delprop(working_fdt, nodeoffset, argv[3]); if (err < 0) { printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); return err; } } else { - err = fdt_del_node(fdt, nodeoffset); + err = fdt_del_node(working_fdt, nodeoffset); if (err < 0) { printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); @@ -300,38 +305,43 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) * Display header info ********************************************************************/ } else if (argv[1][0] == 'h') { - u32 version = fdt_version(fdt); - printf("magic:\t\t\t0x%x\n", fdt_magic(fdt)); - printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(fdt), fdt_totalsize(fdt)); - printf("off_dt_struct:\t\t0x%x\n", fdt_off_dt_struct(fdt)); - printf("off_dt_strings:\t\t0x%x\n", fdt_off_dt_strings(fdt)); - printf("off_mem_rsvmap:\t\t0x%x\n", fdt_off_mem_rsvmap(fdt)); + u32 version = fdt_version(working_fdt); + printf("magic:\t\t\t0x%x\n", fdt_magic(working_fdt)); + printf("totalsize:\t\t0x%x (%d)\n", fdt_totalsize(working_fdt), + fdt_totalsize(working_fdt)); + printf("off_dt_struct:\t\t0x%x\n", + fdt_off_dt_struct(working_fdt)); + printf("off_dt_strings:\t\t0x%x\n", + fdt_off_dt_strings(working_fdt)); + printf("off_mem_rsvmap:\t\t0x%x\n", + fdt_off_mem_rsvmap(working_fdt)); printf("version:\t\t%d\n", version); - printf("last_comp_version:\t%d\n", fdt_last_comp_version(fdt)); + printf("last_comp_version:\t%d\n", + fdt_last_comp_version(working_fdt)); if (version >= 2) printf("boot_cpuid_phys:\t0x%x\n", - fdt_boot_cpuid_phys(fdt)); + fdt_boot_cpuid_phys(working_fdt)); if (version >= 3) printf("size_dt_strings:\t0x%x\n", - fdt_size_dt_strings(fdt)); + fdt_size_dt_strings(working_fdt)); if (version >= 17) printf("size_dt_struct:\t\t0x%x\n", - fdt_size_dt_struct(fdt)); - printf("number mem_rsv:\t\t0x%x\n", fdt_num_mem_rsv(fdt)); + fdt_size_dt_struct(working_fdt)); + printf("number mem_rsv:\t\t0x%x\n", + fdt_num_mem_rsv(working_fdt)); printf("\n"); /******************************************************************** * Set boot cpu id ********************************************************************/ - } else if ((argv[1][0] == 'b') && (argv[1][1] == 'o') && - (argv[1][2] == 'o')) { + } else if (strncmp(argv[1], "boo", 3) == 0) { unsigned long tmp = simple_strtoul(argv[2], NULL, 16); - fdt_set_boot_cpuid_phys(fdt, tmp); + fdt_set_boot_cpuid_phys(working_fdt, tmp); /******************************************************************** * memory command ********************************************************************/ - } else if ((argv[1][0] == 'm') && (argv[1][1] == 'e')) { + } else if (strncmp(argv[1], "me", 2) == 0) { uint64_t addr, size; int err; #ifdef CFG_64BIT_STRTOUL @@ -341,23 +351,23 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[3], NULL, 16); #endif - err = fdt_fixup_memory(fdt, addr, size); + err = fdt_fixup_memory(working_fdt, addr, size); if (err < 0) return err; /******************************************************************** * mem reserve commands ********************************************************************/ - } else if ((argv[1][0] == 'r') && (argv[1][1] == 's')) { + } else if (strncmp(argv[1], "rs", 2) == 0) { if (argv[2][0] == 'p') { uint64_t addr, size; - int total = fdt_num_mem_rsv(fdt); + int total = fdt_num_mem_rsv(working_fdt); int j, err; printf("index\t\t start\t\t size\n"); printf("-------------------------------" "-----------------\n"); for (j = 0; j < total; j++) { - err = fdt_get_mem_rsv(fdt, j, &addr, &size); + err = fdt_get_mem_rsv(working_fdt, j, &addr, &size); if (err < 0) { printf("libfdt fdt_get_mem_rsv(): %s\n", fdt_strerror(err)); @@ -379,7 +389,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) addr = simple_strtoul(argv[3], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); #endif - err = fdt_add_mem_rsv(fdt, addr, size); + err = fdt_add_mem_rsv(working_fdt, addr, size); if (err < 0) { printf("libfdt fdt_add_mem_rsv(): %s\n", @@ -388,7 +398,7 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } } else if (argv[2][0] == 'd') { unsigned long idx = simple_strtoul(argv[3], NULL, 16); - int err = fdt_del_mem_rsv(fdt, idx); + int err = fdt_del_mem_rsv(working_fdt, idx); if (err < 0) { printf("libfdt fdt_del_mem_rsv(): %s\n", @@ -403,12 +413,12 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) } #ifdef CONFIG_OF_BOARD_SETUP /* Call the board-specific fixup routine */ - else if (argv[1][0] == 'b') - ft_board_setup(fdt, gd->bd); + else if (strncmp(argv[1], "boa", 3) == 0) + ft_board_setup(working_fdt, gd->bd); #endif /* Create a chosen node */ else if (argv[1][0] == 'c') - fdt_chosen(fdt, 0, 0, 1); + fdt_chosen(working_fdt, 0, 0, 1); else { /* Unrecognized command */ printf ("Usage:\n%s\n", cmdtp->usage); @@ -424,12 +434,12 @@ static int fdt_valid(void) { int err; - if (fdt == NULL) { + if (working_fdt == NULL) { printf ("The address of the fdt is invalid (NULL).\n"); return 0; } - err = fdt_check_header(fdt); + err = fdt_check_header(working_fdt); if (err == 0) return 1; /* valid */ @@ -439,17 +449,19 @@ static int fdt_valid(void) * Be more informative on bad version. */ if (err == -FDT_ERR_BADVERSION) { - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) { - printf (" - too old, fdt $d < %d", - fdt_version(fdt), + if (fdt_version(working_fdt) < + FDT_FIRST_SUPPORTED_VERSION) { + printf (" - too old, fdt %d < %d", + fdt_version(working_fdt), FDT_FIRST_SUPPORTED_VERSION); - fdt = NULL; + working_fdt = NULL; } - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) { - printf (" - too new, fdt $d > %d", - fdt_version(fdt), + if (fdt_last_comp_version(working_fdt) > + FDT_LAST_SUPPORTED_VERSION) { + printf (" - too new, fdt %d > %d", + fdt_version(working_fdt), FDT_LAST_SUPPORTED_VERSION); - fdt = NULL; + working_fdt = NULL; } return 0; } @@ -534,7 +546,7 @@ static int fdt_parse_prop(char **newval, int count, char *data, int *len) newp = newval[++stridx]; } if (*newp != ']') { - printf("Unexpected character '%c'\n", *newval); + printf("Unexpected character '%c'\n", *newp); return 1; } } else { @@ -645,7 +657,7 @@ static void print_data(const void *data, int len) /****************************************************************************/ /* - * Recursively print (a portion of) the fdt. The depth parameter + * Recursively print (a portion of) the working_fdt. The depth parameter * determines how deeply nested the fdt is printed. */ static int fdt_print(const char *pathp, char *prop, int depth) @@ -661,7 +673,7 @@ static int fdt_print(const char *pathp, char *prop, int depth) int level = 0; /* keep track of nesting level */ const struct fdt_property *fdt_prop; - nodeoffset = fdt_path_offset (fdt, pathp); + nodeoffset = fdt_path_offset (working_fdt, pathp); if (nodeoffset < 0) { /* * Not found or something else bad happened. @@ -675,7 +687,7 @@ static int fdt_print(const char *pathp, char *prop, int depth) * Print only the given property and then return. */ if (prop) { - nodep = fdt_getprop (fdt, nodeoffset, prop, &len); + nodep = fdt_getprop (working_fdt, nodeoffset, prop, &len); if (len == 0) { /* no property value */ printf("%s %s\n", pathp, prop); @@ -697,10 +709,10 @@ static int fdt_print(const char *pathp, char *prop, int depth) * print the node and all subnodes. */ while(level >= 0) { - tag = fdt_next_tag(fdt, nodeoffset, &nextoffset); + tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); switch(tag) { case FDT_BEGIN_NODE: - pathp = fdt_get_name(fdt, nodeoffset, NULL); + pathp = fdt_get_name(working_fdt, nodeoffset, NULL); if (level <= depth) { if (pathp == NULL) pathp = "/* NULL pointer error */"; @@ -724,9 +736,9 @@ static int fdt_print(const char *pathp, char *prop, int depth) } break; case FDT_PROP: - fdt_prop = fdt_offset_ptr(fdt, nodeoffset, + fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset, sizeof(*fdt_prop)); - pathp = fdt_string(fdt, + pathp = fdt_string(working_fdt, fdt32_to_cpu(fdt_prop->nameoff)); len = fdt32_to_cpu(fdt_prop->len); nodep = fdt_prop->data; @@ -751,7 +763,7 @@ static int fdt_print(const char *pathp, char *prop, int depth) } break; case FDT_NOP: - printf("/* NOP */\n", &tabs[MAX_LEVEL - level]); + printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]); break; case FDT_END: return 1; diff --git a/common/cmd_ide.c b/common/cmd_ide.c index 6560702..97a873d 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -367,7 +367,7 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) image_header_t *hdr; int rcode = 0; #if defined(CONFIG_FIT) - const void *fit_hdr; + const void *fit_hdr = NULL; #endif show_boot_progress (41); @@ -465,12 +465,6 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (const void *)addr; - if (!fit_check_format (fit_hdr)) { - show_boot_progress (-140); - puts ("** Bad FIT image format\n"); - return 1; - } - show_boot_progress (141); puts ("Fit image detected...\n"); cnt = fit_get_size (fit_hdr); @@ -496,8 +490,15 @@ int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) - fit_print_contents ((const void *)addr); + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-140); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (141); + fit_print_contents (fit_hdr); + } #endif /* Loading ok, update default load address */ diff --git a/common/cmd_log.c b/common/cmd_log.c index c6e72ac..fdcc575 100644 --- a/common/cmd_log.c +++ b/common/cmd_log.c @@ -66,6 +66,12 @@ static logbuff_t *log; #endif static char *lbuf; +unsigned long __logbuffer_base(void) +{ + return CFG_SDRAM_BASE + gd->bd->bi_memsize - LOGBUFF_LEN; +} +unsigned long logbuffer_base (void) __attribute__((weak, alias("__logbuffer_base"))); + void logbuff_init_ptrs (void) { unsigned long tag, post_word; @@ -75,7 +81,7 @@ void logbuff_init_ptrs (void) log = (logbuff_t *)CONFIG_ALT_LH_ADDR; lbuf = (char *)CONFIG_ALT_LB_ADDR; #else - log = (logbuff_t *)(gd->bd->bi_memsize-LOGBUFF_LEN) - 1; + log = (logbuff_t *)(logbuffer_base ()) - 1; lbuf = (char *)log->buf; #endif diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 37eb41b..e20c1af 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -37,8 +37,6 @@ int find_dev_and_part(const char *id, struct mtd_device **dev, u8 *part_num, struct part_info **part); #endif -extern nand_info_t nand_info[]; /* info for NAND chips */ - static int nand_dump_oob(nand_info_t *nand, ulong off) { return 0; @@ -486,7 +484,7 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, image_header_t *hdr; int jffs2 = 0; #if defined(CONFIG_FIT) - const void *fit_hdr; + const void *fit_hdr = NULL; #endif s = strchr(cmd, '.'); @@ -528,12 +526,6 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (const void *)addr; - if (!fit_check_format (fit_hdr)) { - show_boot_progress (-150); - puts ("** Bad FIT image format\n"); - return 1; - } - show_boot_progress (151); puts ("Fit image detected...\n"); cnt = fit_get_size (fit_hdr); @@ -566,8 +558,15 @@ static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, #if defined(CONFIG_FIT) /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) - fit_print_contents ((const void *)addr); + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-150); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (151); + fit_print_contents (fit_hdr); + } #endif /* Loading ok, update default load address */ @@ -954,7 +953,7 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) image_header_t *hdr; int rcode = 0; #if defined(CONFIG_FIT) - const void *fit_hdr; + const void *fit_hdr = NULL; #endif show_boot_progress (52); @@ -1023,12 +1022,6 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (const void *)addr; - if (!fit_check_format (fit_hdr)) { - show_boot_progress (-150); - puts ("** Bad FIT image format\n"); - return 1; - } - show_boot_progress (151); puts ("Fit image detected...\n"); cnt = fit_get_size (fit_hdr); @@ -1052,8 +1045,15 @@ int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) - fit_print_contents ((const void *)addr); + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format (fit_hdr)) { + show_boot_progress (-150); + puts ("** Bad FIT image format\n"); + return 1; + } + show_boot_progress (151); + fit_print_contents (fit_hdr); + } #endif /* Loading ok, update default load address */ diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 9c5d1fc..85a0f94 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -58,8 +58,9 @@ DECLARE_GLOBAL_DATA_PTR; !defined(CFG_ENV_IS_IN_DATAFLASH) && \ !defined(CFG_ENV_IS_IN_NAND) && \ !defined(CFG_ENV_IS_IN_ONENAND) && \ + !defined(CFG_ENV_IS_IN_SPI_FLASH) && \ !defined(CFG_ENV_IS_NOWHERE) -# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|NOWHERE} +# error Define one of CFG_ENV_IS_IN_{NVRAM|EEPROM|FLASH|DATAFLASH|ONENAND|SPI_FLASH|NOWHERE} #endif #define XMK_STR(x) #x @@ -179,11 +180,12 @@ int _do_setenv (int flag, int argc, char *argv[]) * Ethernet Address and serial# can be set only once, * ver is readonly. */ + if ( #ifdef CONFIG_HAS_UID /* Allow serial# forced overwrite with 0xdeaf4add flag */ - if ( ((strcmp (name, "serial#") == 0) && (flag != 0xdeaf4add)) || + ((strcmp (name, "serial#") == 0) && (flag != 0xdeaf4add)) || #else - if ( (strcmp (name, "serial#") == 0) || + (strcmp (name, "serial#") == 0) || #endif ((strcmp (name, "ethaddr") == 0) #if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR) @@ -379,13 +381,13 @@ int _do_setenv (int flag, int argc, char *argv[]) return 0; } -void setenv (char *varname, char *varvalue) +int setenv (char *varname, char *varvalue) { char *argv[4] = { "setenv", varname, varvalue, NULL }; if (varvalue == NULL) - _do_setenv (0, 2, argv); + return _do_setenv (0, 2, argv); else - _do_setenv (0, 3, argv); + return _do_setenv (0, 3, argv); } #ifdef CONFIG_HAS_UID diff --git a/common/cmd_scsi.c b/common/cmd_scsi.c index 69028f3..e648f7d 100644 --- a/common/cmd_scsi.c +++ b/common/cmd_scsi.c @@ -212,7 +212,7 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) image_header_t *hdr; int rcode = 0; #if defined(CONFIG_FIT) - const void *fit_hdr; + const void *fit_hdr = NULL; #endif switch (argc) { @@ -291,10 +291,6 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (const void *)addr; - if (!fit_check_format (fit_hdr)) { - puts ("** Bad FIT image format\n"); - return 1; - } puts ("Fit image detected...\n"); cnt = fit_get_size (fit_hdr); @@ -317,8 +313,13 @@ int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) - fit_print_contents ((const void *)addr); + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + fit_print_contents (fit_hdr); + } #endif /* Loading ok, update default load address */ diff --git a/common/cmd_sf.c b/common/cmd_sf.c new file mode 100644 index 0000000..8c0a751 --- /dev/null +++ b/common/cmd_sf.c @@ -0,0 +1,191 @@ +/* + * Command for accessing SPI flash. + * + * Copyright (C) 2008 Atmel Corporation + */ +#include <common.h> +#include <spi_flash.h> + +#include <asm/io.h> + +#ifndef CONFIG_SF_DEFAULT_SPEED +# define CONFIG_SF_DEFAULT_SPEED 1000000 +#endif +#ifndef CONFIG_SF_DEFAULT_MODE +# define CONFIG_SF_DEFAULT_MODE SPI_MODE_3 +#endif + +static struct spi_flash *flash; + +static int do_spi_flash_probe(int argc, char *argv[]) +{ + unsigned int bus = 0; + unsigned int cs; + unsigned int speed = CONFIG_SF_DEFAULT_SPEED; + unsigned int mode = CONFIG_SF_DEFAULT_MODE; + char *endp; + struct spi_flash *new; + + if (argc < 2) + goto usage; + + cs = simple_strtoul(argv[1], &endp, 0); + if (*argv[1] == 0 || (*endp != 0 && *endp != ':')) + goto usage; + if (*endp == ':') { + if (endp[1] == 0) + goto usage; + + bus = cs; + cs = simple_strtoul(endp + 1, &endp, 0); + if (*endp != 0) + goto usage; + } + + if (argc >= 3) { + speed = simple_strtoul(argv[2], &endp, 0); + if (*argv[2] == 0 || *endp != 0) + goto usage; + } + if (argc >= 4) { + mode = simple_strtoul(argv[3], &endp, 0); + if (*argv[3] == 0 || *endp != 0) + goto usage; + } + + new = spi_flash_probe(bus, cs, speed, mode); + if (!new) { + printf("Failed to initialize SPI flash at %u:%u\n", bus, cs); + return 1; + } + + if (flash) + spi_flash_free(flash); + flash = new; + + printf("%u KiB %s at %u:%u is now current device\n", + flash->size >> 10, flash->name, bus, cs); + + return 0; + +usage: + puts("Usage: sf probe [bus:]cs [hz] [mode]\n"); + return 1; +} + +static int do_spi_flash_read_write(int argc, char *argv[]) +{ + unsigned long addr; + unsigned long offset; + unsigned long len; + void *buf; + char *endp; + int ret; + + if (argc < 4) + goto usage; + + addr = simple_strtoul(argv[1], &endp, 16); + if (*argv[1] == 0 || *endp != 0) + goto usage; + offset = simple_strtoul(argv[2], &endp, 16); + if (*argv[2] == 0 || *endp != 0) + goto usage; + len = simple_strtoul(argv[3], &endp, 16); + if (*argv[3] == 0 || *endp != 0) + goto usage; + + buf = map_physmem(addr, len, MAP_WRBACK); + if (!buf) { + puts("Failed to map physical memory\n"); + return 1; + } + + if (strcmp(argv[0], "read") == 0) + ret = spi_flash_read(flash, offset, len, buf); + else + ret = spi_flash_write(flash, offset, len, buf); + + unmap_physmem(buf, len); + + if (ret) { + printf("SPI flash %s failed\n", argv[0]); + return 1; + } + + return 0; + +usage: + printf("Usage: sf %s addr offset len\n", argv[0]); + return 1; +} + +static int do_spi_flash_erase(int argc, char *argv[]) +{ + unsigned long offset; + unsigned long len; + char *endp; + int ret; + + if (argc < 3) + goto usage; + + offset = simple_strtoul(argv[1], &endp, 16); + if (*argv[1] == 0 || *endp != 0) + goto usage; + len = simple_strtoul(argv[2], &endp, 16); + if (*argv[2] == 0 || *endp != 0) + goto usage; + + ret = spi_flash_erase(flash, offset, len); + if (ret) { + printf("SPI flash %s failed\n", argv[0]); + return 1; + } + + return 0; + +usage: + puts("Usage: sf erase offset len\n"); + return 1; +} + +static int do_spi_flash(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + const char *cmd; + + /* need at least two arguments */ + if (argc < 2) + goto usage; + + cmd = argv[1]; + + if (strcmp(cmd, "probe") == 0) + return do_spi_flash_probe(argc - 1, argv + 1); + + /* The remaining commands require a selected device */ + if (!flash) { + puts("No SPI flash selected. Please run `sf probe'\n"); + return 1; + } + + if (strcmp(cmd, "read") == 0 || strcmp(cmd, "write") == 0) + return do_spi_flash_read_write(argc - 1, argv + 1); + if (strcmp(cmd, "erase") == 0) + return do_spi_flash_erase(argc - 1, argv + 1); + +usage: + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +U_BOOT_CMD( + sf, 5, 1, do_spi_flash, + "sf - SPI flash sub-system\n", + "probe [bus:]cs [hz] [mode] - init flash device on given SPI bus\n" + " and chip select\n" + "sf read addr offset len - read `len' bytes starting at\n" + " `offset' to memory at `addr'\n" + "sf write addr offset len - write `len' bytes from memory\n" + " at `addr' to flash at `offset'\n" + "sf erase offset len - erase `len' bytes from `offset'\n"); diff --git a/common/cmd_spi.c b/common/cmd_spi.c index 7604422..40ee7e7 100644 --- a/common/cmd_spi.c +++ b/common/cmd_spi.c @@ -37,20 +37,20 @@ # define MAX_SPI_BYTES 32 /* Maximum number of bytes we can handle */ #endif -/* - * External table of chip select functions (see the appropriate board - * support for the actual definition of the table). - */ -extern spi_chipsel_type spi_chipsel[]; -extern int spi_chipsel_cnt; +#ifndef CONFIG_DEFAULT_SPI_BUS +# define CONFIG_DEFAULT_SPI_BUS 0 +#endif +#ifndef CONFIG_DEFAULT_SPI_MODE +# define CONFIG_DEFAULT_SPI_MODE SPI_MODE_0 +#endif /* * Values from last command. */ -static int device; -static int bitlen; -static uchar dout[MAX_SPI_BYTES]; -static uchar din[MAX_SPI_BYTES]; +static unsigned int device; +static int bitlen; +static uchar dout[MAX_SPI_BYTES]; +static uchar din[MAX_SPI_BYTES]; /* * SPI read/write @@ -65,6 +65,7 @@ static uchar din[MAX_SPI_BYTES]; int do_spi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { + struct spi_slave *slave; char *cp = 0; uchar tmp; int j; @@ -101,19 +102,24 @@ int do_spi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } } - if ((device < 0) || (device >= spi_chipsel_cnt)) { - printf("Invalid device %d, giving up.\n", device); - return 1; - } if ((bitlen < 0) || (bitlen > (MAX_SPI_BYTES * 8))) { printf("Invalid bitlen %d, giving up.\n", bitlen); return 1; } - debug ("spi_chipsel[%d] = %08X\n", - device, (uint)spi_chipsel[device]); + /* FIXME: Make these parameters run-time configurable */ + slave = spi_setup_slave(CONFIG_DEFAULT_SPI_BUS, device, 1000000, + CONFIG_DEFAULT_SPI_MODE); + if (!slave) { + printf("Invalid device %d, giving up.\n", device); + return 1; + } + + debug ("spi chipsel = %08X\n", device); - if(spi_xfer(spi_chipsel[device], bitlen, dout, din) != 0) { + spi_claim_bus(slave); + if(spi_xfer(slave, bitlen, dout, din, + SPI_XFER_BEGIN | SPI_XFER_END) != 0) { printf("Error with the SPI transaction.\n"); rcode = 1; } else { @@ -123,6 +129,8 @@ int do_spi (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) } printf("\n"); } + spi_release_bus(slave); + spi_free_slave(slave); return rcode; } diff --git a/common/cmd_usb.c b/common/cmd_usb.c index 9be86b8..f2795d3 100644 --- a/common/cmd_usb.c +++ b/common/cmd_usb.c @@ -316,7 +316,7 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) image_header_t *hdr; block_dev_desc_t *stor_dev; #if defined(CONFIG_FIT) - const void *fit_hdr; + const void *fit_hdr = NULL; #endif switch (argc) { @@ -404,10 +404,6 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) case IMAGE_FORMAT_FIT: fit_hdr = (const void *)addr; - if (!fit_check_format (fit_hdr)) { - puts ("** Bad FIT image format\n"); - return 1; - } puts ("Fit image detected...\n"); cnt = fit_get_size (fit_hdr); @@ -430,8 +426,13 @@ int do_usbboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) #if defined(CONFIG_FIT) /* This cannot be done earlier, we need complete FIT image in RAM first */ - if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) - fit_print_contents ((const void *)addr); + if (genimg_get_format ((void *)addr) == IMAGE_FORMAT_FIT) { + if (!fit_check_format (fit_hdr)) { + puts ("** Bad FIT image format\n"); + return 1; + } + fit_print_contents (fit_hdr); + } #endif /* Loading ok, update default load address */ diff --git a/common/dlmalloc.c b/common/dlmalloc.c index 20c2069..c51351e 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1,3 +1,5 @@ +#include <common.h> + #if 0 /* Moved to malloc.h */ /* ---------- To make a malloc.h, start cutting here ------------ */ @@ -947,7 +949,6 @@ void malloc_stats(); #endif /* 0 */ #endif /* 0 */ /* Moved to malloc.h */ -#include <common.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/common/env_common.c b/common/env_common.c index a494812..d51c211 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -50,7 +50,6 @@ extern void env_relocate_spec (void); extern uchar env_get_char_spec(int); static uchar env_get_char_init (int index); -uchar (*env_get_char)(int) = env_get_char_init; /************************************************************************ * Default settings to be used when no valid environment is found @@ -134,7 +133,8 @@ uchar default_environment[] = { "\0" }; -#if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */ +#if defined(CFG_ENV_IS_IN_NAND) /* Environment is in Nand Flash */ \ + || defined(CFG_ENV_IS_IN_SPI_FLASH) int default_environment_size = sizeof(default_environment); #endif @@ -182,6 +182,19 @@ uchar env_get_char_memory (int index) } #endif +uchar env_get_char (int index) +{ + uchar c; + + /* if relocated to RAM */ + if (gd->flags & GD_FLG_RELOC) + c = env_get_char_memory(index); + else + c = env_get_char_init(index); + + return (c); +} + uchar *env_get_addr (int index) { if (gd->env_valid) { @@ -191,6 +204,23 @@ uchar *env_get_addr (int index) } } +void set_default_env(void) +{ + if (sizeof(default_environment) > ENV_SIZE) { + puts ("*** Error - default environment is too large\n\n"); + return; + } + + memset(env_ptr, 0, sizeof(env_t)); + memcpy(env_ptr->data, default_environment, + sizeof(default_environment)); +#ifdef CFG_REDUNDAND_ENVIRONMENT + env_ptr->flags = 0xFF; +#endif + env_crc_update (); + gd->env_valid = 1; +} + void env_relocate (void) { DEBUGF ("%s[%d] offset = 0x%lx\n", __FUNCTION__,__LINE__, @@ -215,11 +245,6 @@ void env_relocate (void) DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr); #endif - /* - * After relocation to RAM, we can always use the "memory" functions - */ - env_get_char = env_get_char_memory; - if (gd->env_valid == 0) { #if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE) /* Environment not changable */ puts ("Using default environment\n\n"); @@ -227,22 +252,7 @@ void env_relocate (void) puts ("*** Warning - bad CRC, using default environment\n\n"); show_boot_progress (-60); #endif - - if (sizeof(default_environment) > ENV_SIZE) - { - puts ("*** Error - default environment is too large\n\n"); - return; - } - - memset (env_ptr, 0, sizeof(env_t)); - memcpy (env_ptr->data, - default_environment, - sizeof(default_environment)); -#ifdef CFG_REDUNDAND_ENVIRONMENT - env_ptr->flags = 0xFF; -#endif - env_crc_update (); - gd->env_valid = 1; + set_default_env(); } else { env_relocate_spec (); diff --git a/common/env_nand.c b/common/env_nand.c index 70d05ad..104f085 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -1,4 +1,7 @@ /* + * (C) Copyright 2008 + * Stuart Wood, Lab X Technologies <stuart.wood@labxtechnologies.com> + * * (C) Copyright 2004 * Jian Zhang, Texas Instruments, jzhang@ti.com. @@ -53,13 +56,14 @@ #error CONFIG_INFERNO not supported yet #endif +#ifndef CFG_ENV_RANGE +#define CFG_ENV_RANGE CFG_ENV_SIZE +#endif + int nand_legacy_rw (struct nand_chip* nand, int cmd, size_t start, size_t len, size_t * retlen, u_char * buf); -/* info for NAND chips, defined in drivers/mtd/nand/nand.c */ -extern nand_info_t nand_info[]; - /* references to names in env_common.c */ extern uchar default_environment[]; extern int default_environment_size; @@ -91,8 +95,8 @@ uchar env_get_char_spec (int index) /* this is called before nand_init() * so we can't read Nand to validate env data. * Mark it OK for now. env_relocate() in env_common.c - * will call our relocate function which will does - * the real validation. + * will call our relocate function which does the real + * validation. * * When using a NAND boot image (like sequoia_nand), the environment * can be embedded or attached to the U-Boot image in NAND flash. This way @@ -151,35 +155,71 @@ int env_init(void) * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ +int writeenv(size_t offset, u_char *buf) +{ + size_t end = offset + CFG_ENV_RANGE; + size_t amount_saved = 0; + size_t blocksize; + + u_char *char_ptr; + + blocksize = nand_info[0].erasesize; + + while (amount_saved < CFG_ENV_SIZE && offset < end) { + if (nand_block_isbad(&nand_info[0], offset)) { + offset += blocksize; + } else { + char_ptr = &buf[amount_saved]; + if (nand_write(&nand_info[0], offset, &blocksize, + char_ptr)) + return 1; + offset += blocksize; + amount_saved += blocksize; + } + } + if (amount_saved != CFG_ENV_SIZE) + return 1; + + return 0; +} #ifdef CFG_ENV_OFFSET_REDUND int saveenv(void) { size_t total; int ret = 0; + nand_erase_options_t nand_erase_options; env_ptr->flags++; total = CFG_ENV_SIZE; + nand_erase_options.length = CFG_ENV_RANGE; + nand_erase_options.quiet = 0; + nand_erase_options.jffs2 = 0; + nand_erase_options.scrub = 0; + + if (CFG_ENV_RANGE < CFG_ENV_SIZE) + return 1; if(gd->env_valid == 1) { - puts ("Erasing redundant Nand..."); - if (nand_erase(&nand_info[0], - CFG_ENV_OFFSET_REDUND, CFG_ENV_SIZE)) + puts ("Erasing redundant Nand...\n"); + nand_erase_options.offset = CFG_ENV_OFFSET_REDUND; + if (nand_erase_opts(&nand_info[0], &nand_erase_options)) return 1; + puts ("Writing to redundant Nand... "); - ret = nand_write(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, - (u_char*) env_ptr); + ret = writeenv(CFG_ENV_OFFSET_REDUND, (u_char *) env_ptr); } else { - puts ("Erasing Nand..."); - if (nand_erase(&nand_info[0], - CFG_ENV_OFFSET, CFG_ENV_SIZE)) + puts ("Erasing Nand...\n"); + nand_erase_options.offset = CFG_ENV_OFFSET; + if (nand_erase_opts(&nand_info[0], &nand_erase_options)) return 1; puts ("Writing to Nand... "); - ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, - (u_char*) env_ptr); + ret = writeenv(CFG_ENV_OFFSET, (u_char *) env_ptr); } - if (ret || total != CFG_ENV_SIZE) + if (ret) { + puts("FAILED!\n"); return 1; + } puts ("done\n"); gd->env_valid = (gd->env_valid == 2 ? 1 : 2); @@ -190,16 +230,26 @@ int saveenv(void) { size_t total; int ret = 0; + nand_erase_options_t nand_erase_options; + + nand_erase_options.length = CFG_ENV_RANGE; + nand_erase_options.quiet = 0; + nand_erase_options.jffs2 = 0; + nand_erase_options.scrub = 0; + nand_erase_options.offset = CFG_ENV_OFFSET; - puts ("Erasing Nand..."); - if (nand_erase(&nand_info[0], CFG_ENV_OFFSET, CFG_ENV_SIZE)) + if (CFG_ENV_RANGE < CFG_ENV_SIZE) + return 1; + puts ("Erasing Nand...\n"); + if (nand_erase_opts(&nand_info[0], &nand_erase_options)) return 1; puts ("Writing to Nand... "); total = CFG_ENV_SIZE; - ret = nand_write(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); - if (ret || total != CFG_ENV_SIZE) + if (writeenv(CFG_ENV_OFFSET, (u_char *) env_ptr)) { + puts("FAILED!\n"); return 1; + } puts ("done\n"); return ret; @@ -207,6 +257,33 @@ int saveenv(void) #endif /* CFG_ENV_OFFSET_REDUND */ #endif /* CMD_SAVEENV */ +int readenv (size_t offset, u_char * buf) +{ + size_t end = offset + CFG_ENV_RANGE; + size_t amount_loaded = 0; + size_t blocksize; + + u_char *char_ptr; + + blocksize = nand_info[0].erasesize; + + while (amount_loaded < CFG_ENV_SIZE && offset < end) { + if (nand_block_isbad(&nand_info[0], offset)) { + offset += blocksize; + } else { + char_ptr = &buf[amount_loaded]; + if (nand_read(&nand_info[0], offset, &blocksize, char_ptr)) + return 1; + offset += blocksize; + amount_loaded += blocksize; + } + } + if (amount_loaded != CFG_ENV_SIZE) + return 1; + + return 0; +} + #ifdef CFG_ENV_OFFSET_REDUND void env_relocate_spec (void) { @@ -220,10 +297,10 @@ void env_relocate_spec (void) tmp_env1 = (env_t *) malloc(CFG_ENV_SIZE); tmp_env2 = (env_t *) malloc(CFG_ENV_SIZE); - nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, - (u_char*) tmp_env1); - nand_read(&nand_info[0], CFG_ENV_OFFSET_REDUND, &total, - (u_char*) tmp_env2); + if (readenv(CFG_ENV_OFFSET, (u_char *) tmp_env1)) + puts("No Valid Environment Area Found\n"); + if (readenv(CFG_ENV_OFFSET_REDUND, (u_char *) tmp_env2)) + puts("No Valid Reundant Environment Area Found\n"); crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); @@ -272,7 +349,7 @@ void env_relocate_spec (void) int ret; total = CFG_ENV_SIZE; - ret = nand_read(&nand_info[0], CFG_ENV_OFFSET, &total, (u_char*)env_ptr); + ret = readenv(CFG_ENV_OFFSET, (u_char *) env_ptr); if (ret || total != CFG_ENV_SIZE) return use_default(); @@ -286,19 +363,7 @@ void env_relocate_spec (void) static void use_default() { puts ("*** Warning - bad CRC or NAND, using default environment\n\n"); - - if (default_environment_size > CFG_ENV_SIZE){ - puts ("*** Error - default environment is too large\n\n"); - return; - } - - memset (env_ptr, 0, sizeof(env_t)); - memcpy (env_ptr->data, - default_environment, - default_environment_size); - env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); - gd->env_valid = 1; - + set_default_env(); } #endif diff --git a/common/env_sf.c b/common/env_sf.c new file mode 100644 index 0000000..d641a9a --- /dev/null +++ b/common/env_sf.c @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Andreas Heppel <aheppel@sysgo.de> + * + * (C) Copyright 2008 Atmel Corporation + * + * 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 CFG_ENV_IS_IN_SPI_FLASH + +#include <environment.h> +#include <spi_flash.h> + +#ifndef CFG_ENV_SPI_BUS +# define CFG_ENV_SPI_BUS 0 +#endif +#ifndef CFG_ENV_SPI_CS +# define CFG_ENV_SPI_CS 0 +#endif +#ifndef CFG_ENV_SPI_MAX_HZ +# define CFG_ENV_SPI_MAX_HZ 1000000 +#endif +#ifndef CFG_ENV_SPI_MODE +# define CFG_ENV_SPI_MODE SPI_MODE_3 +#endif + +DECLARE_GLOBAL_DATA_PTR; + +/* references to names in env_common.c */ +extern uchar default_environment[]; +extern int default_environment_size; + +char * env_name_spec = "SPI Flash"; +env_t *env_ptr; + +static struct spi_flash *env_flash; + +uchar env_get_char_spec(int index) +{ + return *((uchar *)(gd->env_addr + index)); +} + +int saveenv(void) +{ + if (!env_flash) { + puts("Environment SPI flash not initialized\n"); + return 1; + } + + puts("Erasing SPI flash..."); + if (spi_flash_erase(env_flash, CFG_ENV_OFFSET, CFG_ENV_SIZE)) + return 1; + + puts("Writing to SPI flash..."); + if (spi_flash_write(env_flash, CFG_ENV_OFFSET, CFG_ENV_SIZE, env_ptr)) + return 1; + + puts("done\n"); + return 0; +} + +void env_relocate_spec(void) +{ + int ret; + + env_flash = spi_flash_probe(CFG_ENV_SPI_BUS, CFG_ENV_SPI_CS, + CFG_ENV_SPI_MAX_HZ, CFG_ENV_SPI_MODE); + if (!env_flash) + goto err_probe; + + ret = spi_flash_read(env_flash, CFG_ENV_OFFSET, CFG_ENV_SIZE, env_ptr); + if (ret) + goto err_read; + + if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc) + goto err_crc; + + gd->env_valid = 1; + + return; + +err_read: + spi_flash_free(env_flash); + env_flash = NULL; +err_probe: +err_crc: + puts("*** Warning - bad CRC, using default environment\n\n"); + + if (default_environment_size > CFG_ENV_SIZE) { + gd->env_valid = 0; + puts("*** Error - default environment is too large\n\n"); + return; + } + + memset(env_ptr, 0, sizeof(env_t)); + memcpy(env_ptr->data, default_environment, default_environment_size); + env_ptr->crc = crc32(0, env_ptr->data, ENV_SIZE); + gd->env_valid = 1; +} + +int env_init(void) +{ + /* SPI flash isn't usable before relocation */ + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 1; + + return 0; +} + +#endif /* CFG_ENV_IS_IN_SPI_FLASH */ diff --git a/common/fdt_support.c b/common/fdt_support.c index 7507744..3828228 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -35,11 +35,6 @@ */ DECLARE_GLOBAL_DATA_PTR; -/* - * fdt points to our working device tree. - */ -struct fdt_header *fdt; - /** * fdt_find_and_setprop: Find a node and set it's property @@ -68,7 +63,7 @@ int fdt_find_and_setprop(void *fdt, const char *node, const char *prop, } #ifdef CONFIG_OF_STDOUT_VIA_ALIAS -static int fdt_fixup_stdout(void *fdt, int choosenoff) +static int fdt_fixup_stdout(void *fdt, int chosenoff) { int err = 0; #ifdef CONFIG_CONS_INDEX @@ -87,7 +82,7 @@ static int fdt_fixup_stdout(void *fdt, int choosenoff) err = -FDT_ERR_NOSPACE; if (p) { memcpy(p, path, len); - err = fdt_setprop(fdt, choosenoff, + err = fdt_setprop(fdt, chosenoff, "linux,stdout-path", p, len); free(p); } diff --git a/common/ft_build.c b/common/ft_build.c deleted file mode 100644 index b951178..0000000 --- a/common/ft_build.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * OF flat tree builder - * Written by: Pantelis Antoniou <pantelis.antoniou@gmail.com> - * Updated by: Matthew McClintock <msm@freescale.com> - * - * 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> -#include <malloc.h> -#include <environment.h> - -#ifdef CONFIG_OF_FLAT_TREE - -#include <asm/errno.h> -#include <stddef.h> - -#include <ft_build.h> -#include <linux/ctype.h> - -#undef DEBUG - -/* align addr on a size boundary - adjust address up if needed -- Cort */ -#define _ALIGN(addr,size) (((addr)+(size)-1)&(~((size)-1))) -#ifndef CONFIG_OF_BOOT_CPU -#define CONFIG_OF_BOOT_CPU 0 -#endif -#define SIZE_OF_RSVMAP_ENTRY (2*sizeof(u64)) - -static void ft_put_word(struct ft_cxt *cxt, u32 v) -{ - memmove(cxt->p + sizeof(u32), cxt->p, cxt->p_end - cxt->p); - - *(u32 *) cxt->p = cpu_to_be32(v); - cxt->p += sizeof(u32); - cxt->p_end += sizeof(u32); -} - -static inline void ft_put_bin(struct ft_cxt *cxt, const void *data, int sz) -{ - int aligned_size = ((u8 *)_ALIGN((unsigned long)cxt->p + sz, - sizeof(u32))) - cxt->p; - - memmove(cxt->p + aligned_size, cxt->p, cxt->p_end - cxt->p); - - /* make sure the last bytes are zeroed */ - memset(cxt->p + aligned_size - (aligned_size % sizeof(u32)), 0, - (aligned_size % sizeof(u32))); - - memcpy(cxt->p, data, sz); - - cxt->p += aligned_size; - cxt->p_end += aligned_size; -} - -void ft_begin_node(struct ft_cxt *cxt, const char *name) -{ - ft_put_word(cxt, OF_DT_BEGIN_NODE); - ft_put_bin(cxt, name, strlen(name) + 1); -} - -void ft_end_node(struct ft_cxt *cxt) -{ - ft_put_word(cxt, OF_DT_END_NODE); -} - -void ft_nop(struct ft_cxt *cxt) -{ - ft_put_word(cxt, OF_DT_NOP); -} - -static int lookup_string(struct ft_cxt *cxt, const char *name) -{ - u8 *p; - - p = cxt->p; - while (p < cxt->p_end) { - if (strcmp((char *)p, name) == 0) - return p - cxt->p; - p += strlen((char *)p) + 1; - } - - return -1; -} - -void ft_prop(struct ft_cxt *cxt, const char *name, const void *data, int sz) -{ - int off = 0; - - off = lookup_string(cxt, name); - if (off == -1) { - memcpy(cxt->p_end, name, strlen(name) + 1); - off = cxt->p_end - cxt->p; - cxt->p_end += strlen(name) + 1; - } - - /* now put offset from beginning of *STRUCTURE* */ - /* will be fixed up at the end */ - ft_put_word(cxt, OF_DT_PROP); - ft_put_word(cxt, sz); - ft_put_word(cxt, off); - ft_put_bin(cxt, data, sz); -} - -void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str) -{ - ft_prop(cxt, name, str, strlen(str) + 1); -} - -void ft_prop_int(struct ft_cxt *cxt, const char *name, int val) -{ - u32 v = cpu_to_be32((u32) val); - - ft_prop(cxt, name, &v, sizeof(u32)); -} - -/* pick up and start working on a tree in place */ -void ft_init_cxt(struct ft_cxt *cxt, void *blob) -{ - struct boot_param_header *bph = blob; - - memset(cxt, 0, sizeof(*cxt)); - - cxt->bph = bph; - bph->boot_cpuid_phys = CONFIG_OF_BOOT_CPU; - - /* find beginning and end of reserve map table (zeros in last entry) */ - cxt->p_rsvmap = (u8 *)bph + bph->off_mem_rsvmap; - while ( ((uint64_t *)cxt->p_rsvmap)[0] != 0 && - ((uint64_t *)cxt->p_rsvmap)[1] != 0 ) { - cxt->p_rsvmap += SIZE_OF_RSVMAP_ENTRY; - } - - cxt->p_start = (u8 *)bph + bph->off_dt_struct; - cxt->p_end = (u8 *)bph + bph->totalsize; - cxt->p = (u8 *)bph + bph->off_dt_strings; -} - -/* add a reserver physical area to the rsvmap */ -void ft_add_rsvmap(struct ft_cxt *cxt, u64 physstart, u64 physend) -{ - memmove(cxt->p_rsvmap + SIZE_OF_RSVMAP_ENTRY, cxt->p_rsvmap, - cxt->p_end - cxt->p_rsvmap); - - ((u64 *)cxt->p_rsvmap)[0] = cpu_to_be64(physstart); - ((u64 *)cxt->p_rsvmap)[1] = cpu_to_be64(physend); - ((u64 *)cxt->p_rsvmap)[2] = 0; - ((u64 *)cxt->p_rsvmap)[3] = 0; - - cxt->p_rsvmap += SIZE_OF_RSVMAP_ENTRY; - cxt->p_start += SIZE_OF_RSVMAP_ENTRY; - cxt->p += SIZE_OF_RSVMAP_ENTRY; - cxt->p_end += SIZE_OF_RSVMAP_ENTRY; -} - -void ft_end_tree(struct ft_cxt *cxt) -{ - ft_put_word(cxt, OF_DT_END); -} - -/* update the boot param header with correct values */ -void ft_finalize_tree(struct ft_cxt *cxt) { - struct boot_param_header *bph = cxt->bph; - - bph->totalsize = cxt->p_end - (u8 *)bph; - bph->off_dt_struct = cxt->p_start - (u8 *)bph; - bph->off_dt_strings = cxt->p - (u8 *)bph; - bph->dt_strings_size = cxt->p_end - cxt->p; -} - -static int is_printable_string(const void *data, int len) -{ - const char *s = data; - const char *ss; - - /* zero length is not */ - if (len == 0) - return 0; - - /* must terminate with zero */ - if (s[len - 1] != '\0') - return 0; - - ss = s; - while (*s && isprint(*s)) - s++; - - /* not zero, or not done yet */ - if (*s != '\0' || (s + 1 - ss) < len) - return 0; - - return 1; -} - -static void print_data(const void *data, int len) -{ - int i; - const u8 *s; - - /* no data, don't print */ - if (len == 0) - return; - - if (is_printable_string(data, len)) { - puts(" = \""); - puts(data); - puts("\""); - return; - } - - switch (len) { - case 1: /* byte */ - printf(" = <%02x>", (*(u8 *) data) & 0xff); - break; - case 2: /* half-word */ - printf(" = <%04x>", be16_to_cpu(*(u16 *) data) & 0xffff); - break; - case 4: /* word */ - printf(" = <%x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU); - break; - case 8: /* double-word */ - printf(" = <%qx>", be64_to_cpu(*(uint64_t *) data)); - break; - default: /* anything else... hexdump */ - printf(" = ["); - for (i = 0, s = data; i < len; i++) - printf("%02x%s", s[i], i < len - 1 ? " " : ""); - printf("]"); - - break; - } -} - -void ft_dump_blob(const void *bphp) -{ - const struct boot_param_header *bph = bphp; - const uint64_t *p_rsvmap = (const uint64_t *) - ((const char *)bph + be32_to_cpu(bph->off_mem_rsvmap)); - const u32 *p_struct = (const u32 *) - ((const char *)bph + be32_to_cpu(bph->off_dt_struct)); - const u32 *p_strings = (const u32 *) - ((const char *)bph + be32_to_cpu(bph->off_dt_strings)); - u32 tag; - const u32 *p; - const char *s, *t; - int depth, sz, shift; - int i; - uint64_t addr, size; - - if (be32_to_cpu(bph->magic) != OF_DT_HEADER) { - /* not valid tree */ - return; - } - - depth = 0; - shift = 4; - - for (i = 0;; i++) { - addr = be64_to_cpu(p_rsvmap[i * 2]); - size = be64_to_cpu(p_rsvmap[i * 2 + 1]); - if (addr == 0 && size == 0) - break; - - printf("/memreserve/ %qx %qx;\n", addr, size); - } - - p = p_struct; - while ((tag = be32_to_cpu(*p++)) != OF_DT_END) { - - /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ - - if (tag == OF_DT_BEGIN_NODE) { - s = (const char *)p; - p = (u32 *) _ALIGN((unsigned long)p + strlen(s) + 1, 4); - - printf("%*s%s {\n", depth * shift, "", s); - - depth++; - continue; - } - - if (tag == OF_DT_END_NODE) { - depth--; - - printf("%*s};\n", depth * shift, ""); - continue; - } - - if (tag == OF_DT_NOP) { - printf("%*s[NOP]\n", depth * shift, ""); - continue; - } - - if (tag != OF_DT_PROP) { - fprintf(stderr, "%*s ** Unknown tag 0x%08x at 0x%x\n", - depth * shift, "", tag, --p); - break; - } - sz = be32_to_cpu(*p++); - s = (const char *)p_strings + be32_to_cpu(*p++); - t = (const char *)p; - p = (const u32 *)_ALIGN((unsigned long)p + sz, 4); - printf("%*s%s", depth * shift, "", s); - print_data(t, sz); - printf(";\n"); - } -} - -void ft_backtrack_node(struct ft_cxt *cxt) -{ - int i = 4; - - while (be32_to_cpu(*(u32 *) (cxt->p - i)) != OF_DT_END_NODE) - i += 4; - - memmove (cxt->p - i, cxt->p, cxt->p_end - cxt->p); - - cxt->p_end -= i; - cxt->p -= i; -} - -void *ft_get_prop(void *bphp, const char *propname, int *szp) -{ - struct boot_param_header *bph = bphp; - uint32_t *p_struct = - (uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_struct)); - uint32_t *p_strings = - (uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_strings)); - uint32_t version = be32_to_cpu(bph->version); - uint32_t tag; - uint32_t *p; - char *s, *t; - char *ss; - int sz; - static char path[256], prop[256]; - - path[0] = '\0'; - - p = p_struct; - while ((tag = be32_to_cpu(*p++)) != OF_DT_END) { - - if (tag == OF_DT_BEGIN_NODE) { - s = (char *)p; - p = (uint32_t *) _ALIGN((unsigned long)p + strlen(s) + - 1, 4); - strcat(path, s); - strcat(path, "/"); - continue; - } - - if (tag == OF_DT_END_NODE) { - path[strlen(path) - 1] = '\0'; - ss = strrchr(path, '/'); - if (ss != NULL) - ss[1] = '\0'; - continue; - } - - if (tag == OF_DT_NOP) - continue; - - if (tag != OF_DT_PROP) - break; - - sz = be32_to_cpu(*p++); - s = (char *)p_strings + be32_to_cpu(*p++); - if (version < 0x10 && sz >= 8) - p = (uint32_t *) _ALIGN((unsigned long)p, 8); - t = (char *)p; - p = (uint32_t *) _ALIGN((unsigned long)p + sz, 4); - - strcpy(prop, path); - strcat(prop, s); - - if (strcmp(prop, propname) == 0) { - *szp = sz; - return t; - } - } - - return NULL; -} - -/********************************************************************/ - -void ft_setup(void *blob, bd_t * bd, ulong initrd_start, ulong initrd_end) -{ - u32 *p; - int len; - struct ft_cxt cxt; - ulong clock; - - /* disable OF tree; booting old kernel */ - if (getenv("disable_of") != NULL) { - memcpy(blob, bd, sizeof(*bd)); - return; - } - -#ifdef DEBUG - printf ("recieved oftree\n"); - ft_dump_blob(blob); -#endif - - ft_init_cxt(&cxt, blob); - - if (initrd_start && initrd_end) - ft_add_rsvmap(&cxt, initrd_start, initrd_end - initrd_start + 1); - - /* back into root */ - ft_backtrack_node(&cxt); - - ft_begin_node(&cxt, "chosen"); - ft_prop_str(&cxt, "name", "chosen"); - - ft_prop_str(&cxt, "bootargs", getenv("bootargs")); - ft_prop_int(&cxt, "linux,platform", 0x600); /* what is this? */ - if (initrd_start && initrd_end) { - ft_prop_int(&cxt, "linux,initrd-start", initrd_start); - ft_prop_int(&cxt, "linux,initrd-end", initrd_end); - } -#ifdef OF_STDOUT_PATH - ft_prop_str(&cxt, "linux,stdout-path", OF_STDOUT_PATH); -#endif - - ft_end_node(&cxt); - - ft_end_node(&cxt); /* end root */ - - ft_end_tree(&cxt); - ft_finalize_tree(&cxt); - -#ifdef CONFIG_PPC - clock = bd->bi_intfreq; - p = ft_get_prop(blob, "/cpus/" OF_CPU "/clock-frequency", &len); - if (p != NULL) - *p = cpu_to_be32(clock); - -#ifdef OF_TBCLK - clock = OF_TBCLK; - p = ft_get_prop(blob, "/cpus/" OF_CPU "/timebase-frequency", &len); - if (p != NULL) - *p = cpu_to_be32(clock); -#endif -#endif /* __powerpc__ */ - -#ifdef CONFIG_OF_BOARD_SETUP - ft_board_setup(blob, bd); -#endif - - /* in case the size changed in the platform code */ - ft_finalize_tree(&cxt); - -#ifdef DEBUG - printf("final OF-tree\n"); - ft_dump_blob(blob); -#endif -} -#endif diff --git a/common/image.c b/common/image.c index 67e594d..ddd9e8b 100644 --- a/common/image.c +++ b/common/image.c @@ -35,6 +35,10 @@ #include <dataflash.h> #endif +#ifdef CONFIG_LOGBUFFER +#include <logbuff.h> +#endif + #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) #include <rtc.h> #endif @@ -431,11 +435,16 @@ ulong getenv_bootm_low(void) #endif } -ulong getenv_bootm_size(void) +phys_size_t getenv_bootm_size(void) { char *s = getenv ("bootm_size"); if (s) { - ulong tmp = simple_strtoul (s, NULL, 16); + phys_size_t tmp; +#ifdef CFG_64BIT_STRTOUL + tmp = (phys_size_t)simple_strtoull (s, NULL, 16); +#else + tmp = (phys_size_t)simple_strtoul (s, NULL, 16); +#endif return tmp; } @@ -1013,6 +1022,12 @@ int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, initrd_high = ~0; } + +#ifdef CONFIG_LOGBUFFER + /* Prevent initrd from overwriting logbuffer */ + lmb_reserve(lmb, logbuffer_base() - LOGBUFF_OVERHEAD, LOGBUFF_RESERVE); +#endif + debug ("## initrd_high = 0x%08lx, copy_to_ram = %d\n", initrd_high, initrd_copy_to_ram); @@ -1024,9 +1039,9 @@ int boot_ramdisk_high (struct lmb *lmb, ulong rd_data, ulong rd_len, lmb_reserve(lmb, rd_data, rd_len); } else { if (initrd_high) - *initrd_start = lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high); + *initrd_start = (ulong)lmb_alloc_base (lmb, rd_len, 0x1000, initrd_high); else - *initrd_start = lmb_alloc (lmb, rd_len, 0x1000); + *initrd_start = (ulong)lmb_alloc (lmb, rd_len, 0x1000); if (*initrd_start == 0) { puts ("ramdisk - allocation error\n"); @@ -1079,7 +1094,7 @@ int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, char *cmdline; char *s; - cmdline = (char *)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, + cmdline = (char *)(ulong)lmb_alloc_base(lmb, CFG_BARGSIZE, 0xf, CFG_BOOTMAPSZ + bootmap_base); if (cmdline == NULL) @@ -1115,7 +1130,7 @@ int boot_get_cmdline (struct lmb *lmb, ulong *cmd_start, ulong *cmd_end, */ int boot_get_kbd (struct lmb *lmb, bd_t **kbd, ulong bootmap_base) { - *kbd = (bd_t *)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, + *kbd = (bd_t *)(ulong)lmb_alloc_base(lmb, sizeof(bd_t), 0xf, CFG_BOOTMAPSZ + bootmap_base); if (*kbd == NULL) return -1; diff --git a/common/lcd.c b/common/lcd.c index 914dc2e..ebf377a 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -50,6 +50,11 @@ #include <lcdvideo.h> #endif +#if defined(CONFIG_ATMEL_LCD) +#include <atmel_lcdc.h> +#include <nand.h> +#endif + #ifdef CONFIG_LCD /************************************************************************/ @@ -474,14 +479,22 @@ ulong lcd_setmem (ulong addr) static void lcd_setfgcolor (int color) { +#ifdef CONFIG_ATMEL_LCD + lcd_color_fg = color; +#else lcd_color_fg = color & 0x0F; +#endif } /*----------------------------------------------------------------------*/ static void lcd_setbgcolor (int color) { +#ifdef CONFIG_ATMEL_LCD + lcd_color_bg = color; +#else lcd_color_bg = color & 0x0F; +#endif } /*----------------------------------------------------------------------*/ @@ -508,7 +521,11 @@ static int lcd_getbgcolor (void) #ifdef CONFIG_LCD_LOGO void bitmap_plot (int x, int y) { +#ifdef CONFIG_ATMEL_LCD + uint *cmap; +#else ushort *cmap; +#endif ushort i, j; uchar *bmap; uchar *fb; @@ -533,6 +550,8 @@ void bitmap_plot (int x, int y) cmap = (ushort *)fbi->palette; #elif defined(CONFIG_MPC823) cmap = (ushort *)&(cp->lcd_cmap[BMP_LOGO_OFFSET*sizeof(ushort)]); +#elif defined(CONFIG_ATMEL_LCD) + cmap = (uint *) (panel_info.mmio + ATMEL_LCDC_LUT(0)); #endif WATCHDOG_RESET(); @@ -540,11 +559,26 @@ void bitmap_plot (int x, int y) /* Set color map */ for (i=0; i<(sizeof(bmp_logo_palette)/(sizeof(ushort))); ++i) { ushort colreg = bmp_logo_palette[i]; +#ifdef CONFIG_ATMEL_LCD + uint lut_entry; +#ifdef CONFIG_ATMEL_LCD_BGR555 + lut_entry = ((colreg & 0x000F) << 11) | + ((colreg & 0x00F0) << 2) | + ((colreg & 0x0F00) >> 7); +#else /* CONFIG_ATMEL_LCD_RGB565 */ + lut_entry = ((colreg & 0x000F) << 1) | + ((colreg & 0x00F0) << 3) | + ((colreg & 0x0F00) << 4); +#endif + *(cmap + BMP_LOGO_OFFSET) = lut_entry; + cmap++; +#else /* !CONFIG_ATMEL_LCD */ #ifdef CFG_INVERT_COLORS *cmap++ = 0xffff - colreg; #else *cmap++ = colreg; #endif +#endif /* CONFIG_ATMEL_LCD */ } WATCHDOG_RESET(); @@ -578,7 +612,9 @@ void bitmap_plot (int x, int y) */ int lcd_display_bitmap(ulong bmp_image, int x, int y) { -#if !defined(CONFIG_MCC200) +#ifdef CONFIG_ATMEL_LCD + uint *cmap; +#elif !defined(CONFIG_MCC200) ushort *cmap; #endif ushort i, j; @@ -633,6 +669,8 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) cmap = (ushort *)fbi->palette; #elif defined(CONFIG_MPC823) cmap = (ushort *)&(cp->lcd_cmap[255*sizeof(ushort)]); +#elif defined(CONFIG_ATMEL_LCD) + cmap = (uint *) (panel_info.mmio + ATMEL_LCDC_LUT(0)); #else # error "Don't know location of color map" #endif @@ -708,6 +746,10 @@ static void *lcd_logo (void) #ifdef CONFIG_LCD_INFO char info[80]; char temp[32]; +#ifdef CONFIG_ATMEL_LCD + int i; + ulong dram_size, nand_size; +#endif #endif /* CONFIG_LCD_INFO */ #ifdef CONFIG_SPLASH_SCREEN @@ -765,6 +807,40 @@ static void *lcd_logo (void) # endif /* CONFIG_LCD_INFO */ #endif /* CONFIG_MPC823 */ +#ifdef CONFIG_ATMEL_LCD +# ifdef CONFIG_LCD_INFO + sprintf (info, "%s", U_BOOT_VERSION); + lcd_drawchars (LCD_INFO_X, LCD_INFO_Y, (uchar *)info, strlen(info)); + + sprintf (info, "(C) 2008 ATMEL Corp"); + lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT, + (uchar *)info, strlen(info)); + + sprintf (info, "at91support@atmel.com"); + lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 2, + (uchar *)info, strlen(info)); + + sprintf (info, "%s CPU at %s MHz", + AT91_CPU_NAME, + strmhz(temp, AT91_MAIN_CLOCK)); + lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 3, + (uchar *)info, strlen(info)); + + dram_size = 0; + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) + dram_size += gd->bd->bi_dram[i].size; + nand_size = 0; + for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) + nand_size += nand_info[i].size; + sprintf (info, " %ld MB SDRAM, %ld MB NAND", + dram_size >> 20, + nand_size >> 20 ); + lcd_drawchars (LCD_INFO_X, LCD_INFO_Y + VIDEO_FONT_HEIGHT * 4, + (uchar *)info, strlen(info)); +# endif /* CONFIG_LCD_INFO */ +#endif /* CONFIG_ATMEL_LCD */ + + #if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO) return ((void *)((ulong)lcd_base + BMP_LOGO_HEIGHT * lcd_line_length)); #else diff --git a/common/main.c b/common/main.c index a17b60b..79ad291 100644 --- a/common/main.c +++ b/common/main.c @@ -509,7 +509,7 @@ void reset_cmd_timeout(void) */ #define putnstr(str,n) do { \ - printf ("%.*s", n, str); \ + printf ("%.*s", (int)n, str); \ } while (0) #define CTL_CH(c) ((c) - 'a' + 1) @@ -940,12 +940,6 @@ int readline_into_buffer (const char *const prompt, char * buffer) int rc; static int initted = 0; - if (!initted) { - hist_init(); - initted = 1; - } - - /* * History uses a global array which is not * writable until after relocation to RAM. diff --git a/common/soft_i2c.c b/common/soft_i2c.c index c5d7e20..5ef7f30 100644 --- a/common/soft_i2c.c +++ b/common/soft_i2c.c @@ -252,6 +252,7 @@ static uchar read_byte(int ack) * Read 8 bits, MSB first. */ I2C_TRISTATE; + I2C_SDA(1); data = 0; for(j = 0; j < 8; j++) { I2C_SCL(0); diff --git a/common/soft_spi.c b/common/soft_spi.c index e425061..c131650 100644 --- a/common/soft_spi.c +++ b/common/soft_spi.c @@ -29,6 +29,8 @@ #if defined(CONFIG_SOFT_SPI) +#include <malloc.h> + /*----------------------------------------------------------------------- * Definitions */ @@ -39,6 +41,15 @@ #define PRINTD(fmt,args...) #endif +struct soft_spi_slave { + struct spi_slave slave; + unsigned int mode; +}; + +static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave) +{ + return container_of(slave, struct soft_spi_slave, slave); +} /*=====================================================================*/ /* Public Functions */ @@ -56,6 +67,57 @@ void spi_init (void) #endif } +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct soft_spi_slave *ss; + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + ss = malloc(sizeof(struct soft_spi_slave)); + if (!ss) + return NULL; + + ss->slave.bus = bus; + ss->slave.cs = cs; + ss->mode = mode; + + /* TODO: Use max_hz to limit the SCK rate */ + + return &ss->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct soft_spi_slave *ss = to_soft_spi(slave); + + free(ss); +} + +int spi_claim_bus(struct spi_slave *slave) +{ +#ifdef CFG_IMMR + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + struct soft_spi_slave *ss = to_soft_spi(slave); + + /* + * Make sure the SPI clock is in idle state as defined for + * this slave. + */ + if (ss->mode & SPI_CPOL) + SPI_SCL(1); + else + SPI_SCL(0); + + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + /* Nothing to do */ +} /*----------------------------------------------------------------------- * SPI transfer @@ -68,50 +130,54 @@ void spi_init (void) * and "din" can point to the same memory location, in which case the * input data overwrites the output data (since both are buffered by * temporary variables, this is OK). - * - * If the chipsel() function is not NULL, it is called with a parameter - * of '1' (chip select active) at the start of the transfer and again with - * a parameter of '0' at the end of the transfer. - * - * If the chipsel() function _is_ NULL, it the responsibility of the - * caller to make the appropriate chip select active before calling - * spi_xfer() and making it inactive after spi_xfer() returns. */ -int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din) +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) { #ifdef CFG_IMMR volatile immap_t *immr = (immap_t *)CFG_IMMR; #endif - uchar tmpdin = 0; - uchar tmpdout = 0; - int j; + struct soft_spi_slave *ss = to_soft_spi(slave); + uchar tmpdin = 0; + uchar tmpdout = 0; + const u8 *txd = dout; + u8 *rxd = din; + int cpol = ss->mode & SPI_CPOL; + int cpha = ss->mode & SPI_CPHA; + unsigned int j; - PRINTD("spi_xfer: chipsel %08X dout %08X din %08X bitlen %d\n", - (int)chipsel, *(uint *)dout, *(uint *)din, bitlen); + PRINTD("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n", + slave->bus, slave->cs, *(uint *)txd, *(uint *)rxd, bitlen); - if(chipsel != NULL) { - (*chipsel)(1); /* select the target chip */ - } + if (flags & SPI_XFER_BEGIN) + spi_cs_activate(slave); for(j = 0; j < bitlen; j++) { /* * Check if it is time to work on a new byte. */ if((j % 8) == 0) { - tmpdout = *dout++; + tmpdout = *txd++; if(j != 0) { - *din++ = tmpdin; + *rxd++ = tmpdin; } tmpdin = 0; } - SPI_SCL(0); + + if (!cpha) + SPI_SCL(!cpol); SPI_SDA(tmpdout & 0x80); SPI_DELAY; - SPI_SCL(1); + if (cpha) + SPI_SCL(!cpol); + else + SPI_SCL(cpol); + tmpdin <<= 1; + tmpdin |= SPI_READ; + tmpdout <<= 1; SPI_DELAY; - tmpdin <<= 1; - tmpdin |= SPI_READ; - tmpdout <<= 1; + if (cpha) + SPI_SCL(cpol); } /* * If the number of bits isn't a multiple of 8, shift the last @@ -120,14 +186,10 @@ int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din) */ if((bitlen % 8) != 0) tmpdin <<= 8 - (bitlen % 8); - *din++ = tmpdin; - - SPI_SCL(0); /* SPI wants the clock left low for idle */ + *rxd++ = tmpdin; - if(chipsel != NULL) { - (*chipsel)(0); /* deselect the target chip */ - - } + if (flags & SPI_XFER_END) + spi_cs_deactivate(slave); return(0); } |