From a5a614c129eaa6b9f0bdc2ea5da01789e18033b1 Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:13 +0000 Subject: km/common: remove unneeded ifdefs for I2C All boards from this serie use i2c. There is no need to #ifdef the header. Signed-off-by: Holger Brunck --- board/keymile/common/common.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/board/keymile/common/common.c b/board/keymile/common/common.c index 6f407b78f2..468c755d67 100644 --- a/board/keymile/common/common.c +++ b/board/keymile/common/common.c @@ -38,9 +38,7 @@ #include "post.h" #endif #include "common.h" -#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) #include -#endif #if !defined(CONFIG_MPC83xx) static void i2c_write_start_seq(void); -- cgit v1.2.3 From 811c8cad7196acb0ae2dd6bf04919689e9d803dc Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:14 +0000 Subject: km/common/ivm: remove obsolete code EEprom_ivm_addr isn't set in our environment, so remove the usage of this. Signed-off-by: Holger Brunck --- board/keymile/common/ivm.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/board/keymile/common/ivm.c b/board/keymile/common/ivm.c index eaa924f0e6..7fe3b0fc09 100644 --- a/board/keymile/common/ivm.c +++ b/board/keymile/common/ivm.c @@ -325,14 +325,6 @@ int ivm_read_eeprom(void) } i2c_set_bus_num(dev->busid); #endif - - buf = (unsigned char *) getenv("EEprom_ivm_addr"); - if (buf != NULL) { - ret = strict_strtoul((char *)buf, 16, &dev_addr); - if (ret != 0) - return -3; - } - /* add deblocking here */ i2c_make_abort(); -- cgit v1.2.3 From cf976ce478b8d7fd62184eac24caa1d31c7d8c55 Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:15 +0000 Subject: km/common/ivm: remove CONFIG_SYS_I2C_IVM_BUS related code This define isn't set within our setup files. So we can safely remove the affected code. Signed-off-by: Holger Brunck --- board/keymile/common/ivm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/board/keymile/common/ivm.c b/board/keymile/common/ivm.c index 7fe3b0fc09..607daa6d65 100644 --- a/board/keymile/common/ivm.c +++ b/board/keymile/common/ivm.c @@ -312,13 +312,9 @@ int ivm_read_eeprom(void) #if defined(CONFIG_I2C_MUX) /* First init the Bus, select the Bus */ -#if defined(CONFIG_SYS_I2C_IVM_BUS) - dev = i2c_mux_ident_muxstring((uchar *)CONFIG_SYS_I2C_IVM_BUS); -#else buf = (unsigned char *) getenv("EEprom_ivm"); if (buf != NULL) dev = i2c_mux_ident_muxstring(buf); -#endif if (dev == NULL) { printf("Error couldnt add Bus for IVM\n"); return -1; -- cgit v1.2.3 From 1eb95ebe0d466d793fcf1f689fc20f6cc83c7fe1 Mon Sep 17 00:00:00 2001 From: Karlheinz Jerg Date: Mon, 21 Jan 2013 03:55:16 +0000 Subject: km82xx, km83xx: move ethernet_present() from common to cpu specific For kmvect1 we need a special solution and for km_arm boards we already have. So move the common code to the architectur specific file. Signed-off-by: Karlheinz Jerg Signed-off-by: Holger Brunck --- board/keymile/common/common.c | 11 ----------- board/keymile/km82xx/km82xx.c | 8 ++++++++ board/keymile/km83xx/km83xx.c | 24 +++++++++++++++++++++++- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/board/keymile/common/common.c b/board/keymile/common/common.c index 468c755d67..ef93ed3f66 100644 --- a/board/keymile/common/common.c +++ b/board/keymile/common/common.c @@ -183,17 +183,6 @@ void i2c_init_board(void) } #endif - -#if !defined(MACH_TYPE_KM_KIRKWOOD) -int ethernet_present(void) -{ - struct km_bec_fpga *base = - (struct km_bec_fpga *)CONFIG_SYS_KMBEC_FPGA_BASE; - - return in_8(&base->bprth) & PIGGY_PRESENT; -} -#endif - int board_eth_init(bd_t *bis) { if (ethernet_present()) diff --git a/board/keymile/km82xx/km82xx.c b/board/keymile/km82xx/km82xx.c index 67b69f6cb3..defc885db7 100644 --- a/board/keymile/km82xx/km82xx.c +++ b/board/keymile/km82xx/km82xx.c @@ -385,6 +385,14 @@ void handle_mgcoge3un_reset(void) } #endif +int ethernet_present(void) +{ + struct km_bec_fpga *base = + (struct km_bec_fpga *)CONFIG_SYS_KMBEC_FPGA_BASE; + + return in_8(&base->bprth) & PIGGY_PRESENT; +} + /* * Early board initalization. */ diff --git a/board/keymile/km83xx/km83xx.c b/board/keymile/km83xx/km83xx.c index 83a8753e5a..b027173725 100644 --- a/board/keymile/km83xx/km83xx.c +++ b/board/keymile/km83xx/km83xx.c @@ -133,6 +133,28 @@ const uint upma_table[] = { }; #endif +static int piggy_present(void) +{ + struct km_bec_fpga __iomem *base = + (struct km_bec_fpga __iomem *)CONFIG_SYS_KMBEC_FPGA_BASE; + + return in_8(&base->bprth) & PIGGY_PRESENT; +} + +#if defined(CONFIG_KMVECT1) +int ethernet_present(void) +{ + /* ethernet port connected to simple switch without piggy */ + return 1; +} +#else +int ethernet_present(void) +{ + return piggy_present(); +} +#endif + + int board_early_init_r(void) { struct km_bec_fpga *base = @@ -280,7 +302,7 @@ int checkboard(void) { puts("Board: Keymile " CONFIG_KM_BOARD_NAME); - if (ethernet_present()) + if (piggy_present()) puts(" with PIGGY."); puts("\n"); return 0; -- cgit v1.2.3 From 322bb2056ba90d55603f081ae57a652a06357bac Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:17 +0000 Subject: km/common/ivm: rework piggy mac adress offset generation For the the kmvect1 board we will also need a functionality to add an offset to the IVMs MAC address, because these board will have two valid ethernet ports for debugging purpose. So move the code to an own function. Signed-off-by: Holger Brunck --- board/keymile/common/ivm.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/board/keymile/common/ivm.c b/board/keymile/common/ivm.c index 607daa6d65..d568fd9def 100644 --- a/board/keymile/common/ivm.c +++ b/board/keymile/common/ivm.c @@ -201,6 +201,22 @@ static int ivm_check_crc(unsigned char *buf, int block) return 0; } +static int calculate_mac_offset(unsigned char *valbuf, unsigned char *buf, + int offset) +{ + unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6]; + + if (offset == 0) + return 0; + + val += offset; + buf[4] = (val >> 16) & 0xff; + buf[5] = (val >> 8) & 0xff; + buf[6] = val & 0xff; + sprintf((char *)valbuf, "%pM", buf + 1); + return 0; +} + static int ivm_analyze_block2(unsigned char *buf, int len) { unsigned char valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN]; @@ -210,17 +226,7 @@ static int ivm_analyze_block2(unsigned char *buf, int len) sprintf((char *)valbuf, "%pM", buf + 1); ivm_set_value("IVM_MacAddress", (char *)valbuf); /* if an offset is defined, add it */ -#if defined(CONFIG_PIGGY_MAC_ADRESS_OFFSET) - if (CONFIG_PIGGY_MAC_ADRESS_OFFSET > 0) { - unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6]; - - val += CONFIG_PIGGY_MAC_ADRESS_OFFSET; - buf[4] = (val >> 16) & 0xff; - buf[5] = (val >> 8) & 0xff; - buf[6] = val & 0xff; - sprintf((char *)valbuf, "%pM", buf + 1); - } -#endif + calculate_mac_offset(buf, valbuf, CONFIG_PIGGY_MAC_ADRESS_OFFSET); #ifdef MACH_TYPE_KM_KIRKWOOD setenv((char *)"ethaddr", (char *)valbuf); #else -- cgit v1.2.3 From 5bcd64cf5c5510365a14d11043033eb7b6144ead Mon Sep 17 00:00:00 2001 From: Karlheinz Jerg Date: Mon, 21 Jan 2013 03:55:18 +0000 Subject: powerpc/83xx/km: add MV88E6122 switch support for kmvect1 kmvect1 has a UEC2 connection to the piggy board and a UEC0 connection to the switch MV88E6122. This switch has a connection to a frontport ethernet interface. The ethernet port used for network booting is automatically selected by u-boot. If a Piggy is plugged, the Piggy port is selected (UEC2, eth1). If the Piggy isn't present, the Frontport is selected (UEC0, eth0). The switch reset is connected to a GPIO on the PRIO3 board FPGA (GPIO28) and released at startup. Signed-off-by: Karlheinz Jerg Signed-off-by: Holger Brunck --- board/keymile/common/ivm.c | 8 ++++- board/keymile/km83xx/km83xx.c | 67 ++++++++++++++++++++++++++++++++++++++ include/configs/km/km83xx-common.h | 8 ++--- include/configs/suvd3.h | 37 +++++++++++++++++++++ 4 files changed, 113 insertions(+), 7 deletions(-) diff --git a/board/keymile/common/ivm.c b/board/keymile/common/ivm.c index d568fd9def..22d525602a 100644 --- a/board/keymile/common/ivm.c +++ b/board/keymile/common/ivm.c @@ -233,7 +233,13 @@ static int ivm_analyze_block2(unsigned char *buf, int len) if (getenv("ethaddr") == NULL) setenv((char *)"ethaddr", (char *)valbuf); #endif - +#ifdef CONFIG_KMVECT1 +/* KMVECT1 has two ethernet interfaces */ + if (getenv("eth1addr") == NULL) { + calculate_mac_offset(buf, valbuf, 1); + setenv((char *)"eth1addr", (char *)valbuf); + } +#endif /* IVM_MacCount */ count = (buf[10] << 24) + (buf[11] << 16) + diff --git a/board/keymile/km83xx/km83xx.c b/board/keymile/km83xx/km83xx.c index b027173725..1e8e2cc360 100644 --- a/board/keymile/km83xx/km83xx.c +++ b/board/keymile/km83xx/km83xx.c @@ -215,8 +215,75 @@ int misc_init_r(void) return 0; } +#if defined(CONFIG_KMVECT1) +#include +/* Marvell MV88E6122 switch configuration */ +static struct mv88e_sw_reg extsw_conf[] = { + /* port 1, FRONT_MDI, autoneg */ + { PORT(1), PORT_PHY, NO_SPEED_FOR }, + { PORT(1), PORT_CTRL, FORWARDING | EGRS_FLD_ALL }, + { PHY(1), PHY_1000_CTRL, NO_ADV }, + { PHY(1), PHY_SPEC_CTRL, AUTO_MDIX_EN }, + { PHY(1), PHY_CTRL, PHY_100_MBPS | AUTONEG_EN | AUTONEG_RST | + FULL_DUPLEX }, + /* port 2, unused */ + { PORT(2), PORT_CTRL, PORT_DIS }, + { PHY(2), PHY_CTRL, PHY_PWR_DOWN }, + { PHY(2), PHY_SPEC_CTRL, SPEC_PWR_DOWN }, + /* port 3, BP_MII (CPU), PHY mode, 100BASE */ + { PORT(3), PORT_CTRL, FORWARDING | EGRS_FLD_ALL }, + /* port 4, ESTAR to slot 11, SerDes, 1000BASE-X */ + { PORT(4), PORT_STATUS, NO_PHY_DETECT }, + { PORT(4), PORT_PHY, SPEED_1000_FOR }, + { PORT(4), PORT_CTRL, FORWARDING | EGRS_FLD_ALL }, + /* port 5, ESTAR to slot 13, SerDes, 1000BASE-X */ + { PORT(5), PORT_STATUS, NO_PHY_DETECT }, + { PORT(5), PORT_PHY, SPEED_1000_FOR }, + { PORT(5), PORT_CTRL, FORWARDING | EGRS_FLD_ALL }, + /* + * Errata Fix: 1.9V Output from Internal 1.8V Regulator, + * acc . MV-S300889-00D.pdf , clause 4.5 + */ + { PORT(5), 0x1A, 0xADB1 }, + /* port 6, unused, this port has no phy */ + { PORT(6), PORT_CTRL, PORT_DIS }, +}; +#endif + int last_stage_init(void) { +#if defined(CONFIG_KMVECT1) + struct km_bec_fpga __iomem *base = + (struct km_bec_fpga __iomem *)CONFIG_SYS_KMBEC_FPGA_BASE; + u8 tmp_reg; + + /* Release mv88e6122 from reset */ + tmp_reg = in_8(&base->res1[0]) | 0x10; /* DIRECT3 register */ + out_8(&base->res1[0], tmp_reg); /* GP28 as output */ + tmp_reg = in_8(&base->gprt3) | 0x10; /* GP28 to high */ + out_8(&base->gprt3, tmp_reg); + + /* configure MV88E6122 switch */ + char *name = "UEC2"; + + if (miiphy_set_current_dev(name)) + return 0; + + mv88e_sw_program(name, CONFIG_KM_MVEXTSW_ADDR, extsw_conf, + ARRAY_SIZE(extsw_conf)); + + mv88e_sw_reset(name, CONFIG_KM_MVEXTSW_ADDR); + + if (piggy_present()) { + setenv("ethact", "UEC2"); + setenv("netdev", "eth1"); + puts("using PIGGY for network boot\n"); + } else { + setenv("netdev", "eth0"); + puts("using frontport for network boot\n"); + } +#endif + #if defined(CONFIG_KMCOGE5NE) struct bfticu_iomap *base = (struct bfticu_iomap *)CONFIG_SYS_BFTIC3_BASE; diff --git a/include/configs/km/km83xx-common.h b/include/configs/km/km83xx-common.h index a9823d6ef9..1e596c860a 100644 --- a/include/configs/km/km83xx-common.h +++ b/include/configs/km/km83xx-common.h @@ -165,19 +165,15 @@ #define CONFIG_UEC_ETH #define CONFIG_ETHPRIME "UEC0" +#if !defined(CONFIG_MPC8309) #define CONFIG_UEC_ETH1 /* GETH1 */ #define UEC_VERBOSE_DEBUG 1 +#endif #ifdef CONFIG_UEC_ETH1 -#if defined(CONFIG_MPC8309) -#define CONFIG_SYS_UEC1_UCC_NUM 2 /* UCC3 */ -#define CONFIG_SYS_UEC1_RX_CLK QE_CLK_NONE /* not used in RMII Mode */ -#define CONFIG_SYS_UEC1_TX_CLK QE_CLK12 -#else #define CONFIG_SYS_UEC1_UCC_NUM 3 /* UCC4 */ #define CONFIG_SYS_UEC1_RX_CLK QE_CLK_NONE /* not used in RMII Mode */ #define CONFIG_SYS_UEC1_TX_CLK QE_CLK17 -#endif #define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH #define CONFIG_SYS_UEC1_PHY_ADDR 0 #define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII diff --git a/include/configs/suvd3.h b/include/configs/suvd3.h index c50832c1e0..bbf9da545b 100644 --- a/include/configs/suvd3.h +++ b/include/configs/suvd3.h @@ -110,4 +110,41 @@ BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) #define CONFIG_SYS_DBAT6U CONFIG_SYS_IBAT6U +/* + * QE UEC ethernet configuration + */ +#if defined(CONFIG_KMVECT1) +#define CONFIG_MV88E6352_SWITCH +#define CONFIG_KM_MVEXTSW_ADDR 0x10 + +/* ethernet port connected to simple switch 88e6122 (UEC0) */ +#define CONFIG_UEC_ETH1 +#define CONFIG_SYS_UEC1_UCC_NUM 0 /* UCC1 */ +#define CONFIG_SYS_UEC1_RX_CLK QE_CLK9 +#define CONFIG_SYS_UEC1_TX_CLK QE_CLK10 + +#define CONFIG_FIXED_PHY 0xFFFFFFFF +#define CONFIG_SYS_FIXED_PHY_ADDR 0x1E /* unused address */ +#define CONFIG_SYS_FIXED_PHY_PORT(devnum, speed, duplex) \ + {devnum, speed, duplex} +#define CONFIG_SYS_FIXED_PHY_PORTS \ + CONFIG_SYS_FIXED_PHY_PORT("UEC0", SPEED_100, DUPLEX_FULL) + +#define CONFIG_SYS_UEC1_ETH_TYPE FAST_ETH +#define CONFIG_SYS_UEC1_PHY_ADDR CONFIG_SYS_FIXED_PHY_ADDR +#define CONFIG_SYS_UEC1_INTERFACE_TYPE PHY_INTERFACE_MODE_MII +#define CONFIG_SYS_UEC1_INTERFACE_SPEED 100 + +/* ethernet port connected to piggy (UEC2) */ +#define CONFIG_HAS_ETH1 +#define CONFIG_UEC_ETH2 +#define CONFIG_SYS_UEC2_UCC_NUM 2 /* UCC3 */ +#define CONFIG_SYS_UEC2_RX_CLK QE_CLK_NONE /* not used in RMII Mode */ +#define CONFIG_SYS_UEC2_TX_CLK QE_CLK12 +#define CONFIG_SYS_UEC2_ETH_TYPE FAST_ETH +#define CONFIG_SYS_UEC2_PHY_ADDR 0 +#define CONFIG_SYS_UEC2_INTERFACE_TYPE PHY_INTERFACE_MODE_RMII +#define CONFIG_SYS_UEC2_INTERFACE_SPEED 100 +#endif /* CONFIG_KMVECT1 */ + #endif /* __CONFIG_H */ -- cgit v1.2.3 From 6515139bfb9bac1e1aab07bfcf86239206d277bf Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:19 +0000 Subject: powerpc/83xx: use ppc_6xx as arch variable for kmvect1 On this board we are using hard floating point, so select the correct toolchain. Signed-off-by: Holger Brunck --- include/configs/km/km8309-common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/configs/km/km8309-common.h b/include/configs/km/km8309-common.h index b36e892cbe..7bd1e92c22 100644 --- a/include/configs/km/km8309-common.h +++ b/include/configs/km/km8309-common.h @@ -22,7 +22,7 @@ #define CONFIG_MPC830x 1 /* MPC830x family */ #define CONFIG_MPC8309 1 /* MPC8309 CPU specific */ -#define CONFIG_KM_DEF_ARCH "arch=ppc_8xx\0" +#define CONFIG_KM_DEF_ARCH "arch=ppc_82xx\0" #define CONFIG_CMD_DIAG 1 /* include common defines/options for all 83xx Keymile boards */ -- cgit v1.2.3 From dacc109c41f82fcce68bd77e531663b485708f7a Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 21 Jan 2013 03:55:20 +0000 Subject: km/common: introduce $uimage variable Replace the hardcoded string with a variable. If CONFIG_NAND_ECC_BCH is set we use a specific name for the uImage (ecc_bch_uImage). Signed-off-by: Andreas Huber Signed-off-by: Holger Brunck --- include/configs/km/keymile-common.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/include/configs/km/keymile-common.h b/include/configs/km/keymile-common.h index f64748e349..ae88759240 100644 --- a/include/configs/km/keymile-common.h +++ b/include/configs/km/keymile-common.h @@ -148,6 +148,12 @@ "ubi part " CONFIG_KM_UBI_PARTITION_NAME_APP "; fi\0" #endif /* CONFIG_KM_UBI_PARTITION_NAME_APP */ +#ifdef CONFIG_NAND_ECC_BCH +#define CONFIG_KM_UIMAGE_NAME "ecc_bch_uImage\0" +#else +#define CONFIG_KM_UIMAGE_NAME "uImage\0" +#endif + /* * boottargets * - set 'subbootcmds' @@ -210,9 +216,10 @@ */ #define CONFIG_KM_DEF_ENV_FLASH_BOOT \ "cramfsaddr=" __stringify(CONFIG_KM_CRAMFS_ADDR) "\0" \ - "cramfsloadkernel=cramfsload ${load_addr_r} uImage\0" \ + "cramfsloadkernel=cramfsload ${load_addr_r} ${uimage}\0" \ "ubicopy=ubi read "__stringify(CONFIG_KM_CRAMFS_ADDR) \ " bootfs${boot_bank}\0" \ + "uimage=" CONFIG_KM_UIMAGE_NAME \ CONFIG_KM_DEV_ENV_FLASH_BOOT_UBI /* -- cgit v1.2.3 From d42a3b74980e65e72185a07f9f556e00587e7349 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Mon, 21 Jan 2013 03:55:21 +0000 Subject: km/scripts: replace hardcoded uImage Replace uImage with ${uimage}. If uimage is not set, default it to uImage. Signed-off-by: Andreas Huber Signed-off-by: Holger Brunck --- board/keymile/scripts/develop-common.txt | 5 +++-- board/keymile/scripts/ramfs-common.txt | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/board/keymile/scripts/develop-common.txt b/board/keymile/scripts/develop-common.txt index aa3d659527..a6bb1b1d4a 100644 --- a/board/keymile/scripts/develop-common.txt +++ b/board/keymile/scripts/develop-common.txt @@ -1,8 +1,9 @@ altbootcmd=run ${subbootcmds} bootcmd=run ${subbootcmds} -configure=km_setboardid && saveenv && reset +configure=run set_uimage; km_setboardid && saveenv && reset subbootcmds=tftpfdt tftpkernel nfsargs add_default boot nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${toolchain}/${arch} -tftpkernel=tftpboot ${load_addr_r} ${hostname}/uImage +tftpkernel=tftpboot ${load_addr_r} ${hostname}/${uimage} toolchain=/opt/eldk rootfssize=0 +set_uimage=printenv uimage || setenv uimage uImage diff --git a/board/keymile/scripts/ramfs-common.txt b/board/keymile/scripts/ramfs-common.txt index c1b45ab029..8a8d287558 100644 --- a/board/keymile/scripts/ramfs-common.txt +++ b/board/keymile/scripts/ramfs-common.txt @@ -4,8 +4,9 @@ altbootcmd=run ${subbootcmds} bootcmd=run ${subbootcmds} subbootcmds=tftpfdt tftpkernel setrootfsaddr tftpramfs flashargs add_default addpanic addramfs boot nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} -configure=km_setboardid && saveenv && reset +configure=run set_uimage; km_setboardid && saveenv && reset rootfsfile=${hostname}/rootfsImage setrootfsaddr=setexpr value ${pnvramaddr} - ${rootfssize} && setenv rootfsaddr 0x${value} -tftpkernel=tftpboot ${load_addr_r} ${hostname}/uImage +tftpkernel=tftpboot ${load_addr_r} ${hostname}/${uimage} tftpramfs=tftpboot ${rootfsaddr} ${hostname}/rootfsImage +set_uimage=printenv uimage || setenv uimage uImage -- cgit v1.2.3 From 938187329afa437407fd19831ce2fde7cbb0869c Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:22 +0000 Subject: kmeter1_nand: allow uasge of NAND_ECC_SOFT_BCH If CONFIG_NAND_ECC_BCH is set we use 4-bit error corretion code instead of the 1-bit error correction code on the NAND device within this driver. Signed-off-by: Holger Brunck Acked-by: Scott Wood --- drivers/mtd/nand/kmeter1_nand.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mtd/nand/kmeter1_nand.c b/drivers/mtd/nand/kmeter1_nand.c index e8e5b7b85e..f044597237 100644 --- a/drivers/mtd/nand/kmeter1_nand.c +++ b/drivers/mtd/nand/kmeter1_nand.c @@ -119,7 +119,11 @@ static int kpn_nand_dev_ready(struct mtd_info *mtd) int board_nand_init(struct nand_chip *nand) { +#if defined(CONFIG_NAND_ECC_BCH) + nand->ecc.mode = NAND_ECC_SOFT_BCH; +#else nand->ecc.mode = NAND_ECC_SOFT; +#endif /* Reference hardware control function */ nand->cmd_ctrl = kpn_nand_hwcontrol; -- cgit v1.2.3 From be7576fa15498e6874bbc901f0aefb7f2f17943d Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:23 +0000 Subject: powerpc/83xx: use NAND_ECC_BCH for kmcoge5ne Switch from 1-bit ecc to 4-bit ecc. Signed-off-by: Holger Brunck --- include/configs/km8360.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/configs/km8360.h b/include/configs/km8360.h index 7631ab6a65..5b191bcdcd 100644 --- a/include/configs/km8360.h +++ b/include/configs/km8360.h @@ -25,6 +25,8 @@ #define CONFIG_KM_BOARD_NAME "kmcoge5ne" #define CONFIG_KM_DEF_NETDEV "netdev=eth1\0" #define CONFIG_CMD_NAND +#define CONFIG_NAND_ECC_BCH +#define CONFIG_BCH #define CONFIG_NAND_KMETER1 #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define NAND_MAX_CHIPS 1 -- cgit v1.2.3 From a7bc914446b46407bb478d4c7b6cb616e1cddb49 Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:24 +0000 Subject: km/common: add eccmode to kernel commandline If CONFIG_NAND_ECC_BCH is chosen from in the board configuration we add an ecc mode to the kernel commandline. Signed-off-by: Holger Brunck --- include/configs/km/keymile-common.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/configs/km/keymile-common.h b/include/configs/km/keymile-common.h index ae88759240..796f33080d 100644 --- a/include/configs/km/keymile-common.h +++ b/include/configs/km/keymile-common.h @@ -150,8 +150,10 @@ #ifdef CONFIG_NAND_ECC_BCH #define CONFIG_KM_UIMAGE_NAME "ecc_bch_uImage\0" +#define CONFIG_KM_ECC_MODE " eccmode=bch" #else #define CONFIG_KM_UIMAGE_NAME "uImage\0" +#define CONFIG_KM_ECC_MODE #endif /* @@ -190,6 +192,7 @@ ":${hostname}:${netdev}:off3" \ " console=" CONFIG_KM_CONSOLE_TTY ",${baudrate}" \ " mem=${kernelmem} init=${init}" \ + CONFIG_KM_ECC_MODE \ " phram.phram=phvar,${varaddr}," __stringify(CONFIG_KM_PHRAM)\ " " CONFIG_KM_UBI_LINUX_MTD " " \ CONFIG_KM_DEF_BOOT_ARGS_CPU \ -- cgit v1.2.3 From 47f53649a2086bf9c351e86cf5481d14c7ea5720 Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:25 +0000 Subject: powerpc/83xx/km: cleanup tuxx1 support This is a preparation for the upcoming kmopti2 board. This board has also a second fpga on board which is different to the tuxx1 target. But we want to use the same header file. So remove the config option KM_DISABLE_APP2 and simply use the board names to distinguish the features. Signed-off-by: Holger Brunck --- boards.cfg | 6 +++--- include/configs/tuxx1.h | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/boards.cfg b/boards.cfg index b1319aace0..c1ed138b3c 100644 --- a/boards.cfg +++ b/boards.cfg @@ -705,9 +705,9 @@ SIMPC8313_SP powerpc mpc83xx simpc8313 sheldon TQM834x powerpc mpc83xx tqm834x tqc suvd3 powerpc mpc83xx km83xx keymile - suvd3:SUVD3 kmvect1 powerpc mpc83xx km83xx keymile - suvd3:KMVECT1 -tuge1 powerpc mpc83xx km83xx keymile - tuxx1:KM_DISABLE_APP2,TUGE1 -tuxx1 powerpc mpc83xx km83xx keymile -kmsupx5 powerpc mpc83xx km83xx keymile - tuxx1:KM_DISABLE_APP2,KMSUPX5 +tuge1 powerpc mpc83xx km83xx keymile - tuxx1:TUGE1 +tuxx1 powerpc mpc83xx km83xx keymile - tuxx1:TUXX1 +kmsupx5 powerpc mpc83xx km83xx keymile - tuxx1:KMSUPX5 sbc8548 powerpc mpc85xx sbc8548 - - sbc8548 sbc8548_PCI_33 powerpc mpc85xx sbc8548 - - sbc8548:PCI,33 sbc8548_PCI_33_PCIE powerpc mpc85xx sbc8548 - - sbc8548:PCI,33,PCIE diff --git a/include/configs/tuxx1.h b/include/configs/tuxx1.h index 90d2e61147..3997717193 100644 --- a/include/configs/tuxx1.h +++ b/include/configs/tuxx1.h @@ -11,7 +11,7 @@ * (C) Copyright 2008 * Heiko Schocher, DENX Software Engineering, hs@denx.de. * - * (C) Copyright 2010-2012 + * (C) Copyright 2010-2013 * Lukas Roggli, KEYMILE Ltd, lukas.roggli@keymile.com * Holger Brunck, Keymile GmbH, holger.bruncl@keymile.com * @@ -27,16 +27,17 @@ /* * High Level Configuration Options */ -#ifdef CONFIG_KMSUPX5 +#if defined(CONFIG_KMSUPX5) #define CONFIG_KM_BOARD_NAME "kmsupx5" #define CONFIG_HOSTNAME kmsupx5 -#elif defined CONFIG_TUGE1 +#elif defined(CONFIG_TUGE1) #define CONFIG_KM_BOARD_NAME "tuge1" #define CONFIG_HOSTNAME tuge1 -#else -#define CONFIG_TUXXX /* TUXX1 board (tuxa1/tuda1) specific */ +#elif defined(CONFIG_TUXX1) /* TUXX1 board (tuxa1/tuda1) specific */ #define CONFIG_KM_BOARD_NAME "tuxx1" #define CONFIG_HOSTNAME tuxx1 +#else +#error ("Board not supported") #endif #define CONFIG_SYS_TEXT_BASE 0xF0000000 @@ -46,7 +47,7 @@ #define CONFIG_SYS_APP1_BASE 0xA0000000 /* PAXG */ #define CONFIG_SYS_APP1_SIZE 256 /* Megabytes */ -#ifndef CONFIG_KM_DISABLE_APP2 +#if defined(CONFIG_TUXX1) #define CONFIG_SYS_APP2_BASE 0xB0000000 /* PINC3 */ #define CONFIG_SYS_APP2_SIZE 256 /* Megabytes */ #endif @@ -81,7 +82,7 @@ OR_GPCM_TRLX_SET | \ OR_GPCM_EHTR_CLEAR | \ OR_GPCM_EAD) -#ifndef CONFIG_KM_DISABLE_APP2 +#if defined(CONFIG_TUXX1) /* * Configuration for C3 on the local bus */ @@ -125,7 +126,7 @@ BATL_GUARDEDSTORAGE) #define CONFIG_SYS_DBAT5U CONFIG_SYS_IBAT5U -#ifdef CONFIG_KM_DISABLE_APP2 +#if defined(CONFIG_TUGE1) || defined(CONFIG_KMSUPX5) #define CONFIG_SYS_IBAT6L (0) #define CONFIG_SYS_IBAT6U (0) #define CONFIG_SYS_DBAT6L CONFIG_SYS_IBAT6L -- cgit v1.2.3 From 4714f8e4d5335306dd75d97936c852994bd02f8b Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:26 +0000 Subject: powerpc/83xx/km: add support for kmopti2 board This board is similar to TUXX1 but it has a different sized second FPGA. Therefore the configuration for the third chipselect is different. Signed-off-by: Holger Brunck --- boards.cfg | 1 + include/configs/tuxx1.h | 31 +++++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/boards.cfg b/boards.cfg index c1ed138b3c..7f772a0840 100644 --- a/boards.cfg +++ b/boards.cfg @@ -707,6 +707,7 @@ suvd3 powerpc mpc83xx km83xx keymile kmvect1 powerpc mpc83xx km83xx keymile - suvd3:KMVECT1 tuge1 powerpc mpc83xx km83xx keymile - tuxx1:TUGE1 tuxx1 powerpc mpc83xx km83xx keymile - tuxx1:TUXX1 +kmopti2 powerpc mpc83xx km83xx keymile - tuxx1:KMOPTI2 kmsupx5 powerpc mpc83xx km83xx keymile - tuxx1:KMSUPX5 sbc8548 powerpc mpc85xx sbc8548 - - sbc8548 sbc8548_PCI_33 powerpc mpc85xx sbc8548 - - sbc8548:PCI,33 diff --git a/include/configs/tuxx1.h b/include/configs/tuxx1.h index 3997717193..6caf23a478 100644 --- a/include/configs/tuxx1.h +++ b/include/configs/tuxx1.h @@ -36,6 +36,9 @@ #elif defined(CONFIG_TUXX1) /* TUXX1 board (tuxa1/tuda1) specific */ #define CONFIG_KM_BOARD_NAME "tuxx1" #define CONFIG_HOSTNAME tuxx1 +#elif defined(CONFIG_KMOPTI2) +#define CONFIG_KM_BOARD_NAME "kmopti2" +#define CONFIG_HOSTNAME kmopti2 #else #error ("Board not supported") #endif @@ -47,18 +50,18 @@ #define CONFIG_SYS_APP1_BASE 0xA0000000 /* PAXG */ #define CONFIG_SYS_APP1_SIZE 256 /* Megabytes */ -#if defined(CONFIG_TUXX1) +#if defined(CONFIG_TUXX1) || defined(CONFIG_KMOPTI2) #define CONFIG_SYS_APP2_BASE 0xB0000000 /* PINC3 */ #define CONFIG_SYS_APP2_SIZE 256 /* Megabytes */ #endif /* * Init Local Bus Memory Controller: - * - * Bank Bus Machine PortSz Size Device on TUDA1 TUXA1 TUGE1 KMSUPX4 - * ---- --- ------- ------ ----- --------------------------------------- - * 2 Local GPCM 8 bit 256MB PAXG LPXF PAXI LPXF - * 3 Local GPCM 8 bit 256MB PINC3 PINC2 unused unused + * Device on + * Bank Bus Machine PortSz Size TUDA1 TUXA1 TUGE1 KMSUPX4 KMOPTI2 + * ---- --- ------- ------ ----- --------------------------------------- + * 2 Local GPCM 8 bit 256MB PAXG LPXF PAXI LPXF PAXE + * 3 Local GPCM 8 bit 256MB PINC3 PINC2 unused unused OPI2(16 bit) * */ @@ -108,6 +111,22 @@ MxMR_WLFx_2X) #endif +#if defined(CONFIG_KMOPTI2) +/* + * Configuration for C3 on the local bus + */ +#define CONFIG_SYS_LBLAWBAR3_PRELIM CONFIG_SYS_APP2_BASE +#define CONFIG_SYS_LBLAWAR3_PRELIM (LBLAWAR_EN | LBLAWAR_256MB) +#define CONFIG_SYS_BR3_PRELIM (CONFIG_SYS_APP2_BASE | \ + BR_PS_16 | \ + BR_MS_GPCM | \ + BR_V) +#define CONFIG_SYS_OR3_PRELIM (MEG_TO_AM(CONFIG_SYS_APP2_SIZE) | \ + OR_GPCM_SCY_4 | \ + OR_GPCM_TRLX_CLEAR | \ + OR_GPCM_EHTR_CLEAR) +#endif + /* * MMU Setup */ -- cgit v1.2.3 From 25b29921b2f5a9a133c6196afaf05fce1be9927b Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:27 +0000 Subject: powerpc/83xx/km: remove uneeded CONFIG_MISC_INIT_R Remove it from the processor specific headers. This is already defined in the common header km83xx.h. Signed-off-by: Holger Brunck --- include/configs/km/km8309-common.h | 2 -- include/configs/km/km8321-common.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/include/configs/km/km8309-common.h b/include/configs/km/km8309-common.h index 7bd1e92c22..7f9cffa3b7 100644 --- a/include/configs/km/km8309-common.h +++ b/include/configs/km/km8309-common.h @@ -33,8 +33,6 @@ /* at end of uboot partition, before env */ #define CONFIG_SYS_QE_FMAN_FW_ADDR 0xF00B0000 -#define CONFIG_MISC_INIT_R - /* * System IO Config */ diff --git a/include/configs/km/km8321-common.h b/include/configs/km/km8321-common.h index 8ad6fc3a33..abb908162a 100644 --- a/include/configs/km/km8321-common.h +++ b/include/configs/km/km8321-common.h @@ -38,8 +38,6 @@ /* include common defines/options for all 83xx Keymile boards */ #include "km83xx-common.h" -#define CONFIG_MISC_INIT_R - /* * System IO Config */ -- cgit v1.2.3 From 411190cb16b63e39345a608b68b3d1be5168117a Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Mon, 21 Jan 2013 03:55:28 +0000 Subject: powerpc/83xx/km: drop uneeded dtt_bus environment var There is no need for a environment variable to configure the dtt bus. Signed-off-by: Holger Brunck --- board/keymile/km83xx/km83xx.c | 12 ++++-------- include/configs/km/km83xx-common.h | 1 - 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/board/keymile/km83xx/km83xx.c b/board/keymile/km83xx/km83xx.c index 1e8e2cc360..faaa39bc20 100644 --- a/board/keymile/km83xx/km83xx.c +++ b/board/keymile/km83xx/km83xx.c @@ -98,17 +98,13 @@ const qe_iop_conf_t qe_iop_conf_tab[] = { static int board_init_i2c_busses(void) { I2C_MUX_DEVICE *dev = NULL; - uchar *buf; + uchar *dtt_bus = (uchar *)"pca9547:70:a"; /* Set up the Bus for the DTTs */ - buf = (unsigned char *) getenv("dtt_bus"); - if (buf != NULL) - dev = i2c_mux_ident_muxstring(buf); - if (dev == NULL) { + dev = i2c_mux_ident_muxstring(dtt_bus); + if (dev == NULL) printf("Error couldn't add Bus for DTT\n"); - printf("please setup dtt_bus to where your\n"); - printf("DTT is found.\n"); - } + return 0; } diff --git a/include/configs/km/km83xx-common.h b/include/configs/km/km83xx-common.h index 1e596c860a..eb0e5b6f32 100644 --- a/include/configs/km/km83xx-common.h +++ b/include/configs/km/km83xx-common.h @@ -312,7 +312,6 @@ #define CONFIG_EXTRA_ENV_SETTINGS \ CONFIG_KM_DEF_ENV \ CONFIG_KM_DEF_ARCH \ - "dtt_bus=pca9547:70:a\0" \ "EEprom_ivm=pca9547:70:9\0" \ "newenv=" \ "prot off 0xF00C0000 +0x40000 && " \ -- cgit v1.2.3 From ea6bd08b7717bf0d3f69ad9f016bf3b03b3eaf16 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 5 Jan 2013 10:48:23 +0000 Subject: nds32: Add a basic errno.h This is available on other architectures, and nds32 will start to break without it as code starts to use error numbers more. Signed-off-by: Simon Glass --- arch/nds32/include/asm/errno.h | 1 + 1 file changed, 1 insertion(+) create mode 100644 arch/nds32/include/asm/errno.h diff --git a/arch/nds32/include/asm/errno.h b/arch/nds32/include/asm/errno.h new file mode 100644 index 0000000000..4c82b503d9 --- /dev/null +++ b/arch/nds32/include/asm/errno.h @@ -0,0 +1 @@ +#include -- cgit v1.2.3 From 55db9ccae38866c627e64b497deda73547a1e84b Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Fri, 18 Jan 2013 15:42:16 +0000 Subject: serial/ns16550: don't generate functions for undefined ports This saved 640 bytes on MPC8536DS (a board with two of the six ports defined). Signed-off-by: Scott Wood --- drivers/serial/serial_ns16550.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index fc01a3c516..b92eef4db9 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -247,24 +247,36 @@ serial_setbrg_dev(unsigned int dev_index) _serial_setbrg(dev_index); } +#if defined(CONFIG_SYS_NS16550_COM1) DECLARE_ESERIAL_FUNCTIONS(1); struct serial_device eserial1_device = INIT_ESERIAL_STRUCTURE(1, "eserial0"); +#endif +#if defined(CONFIG_SYS_NS16550_COM2) DECLARE_ESERIAL_FUNCTIONS(2); struct serial_device eserial2_device = INIT_ESERIAL_STRUCTURE(2, "eserial1"); +#endif +#if defined(CONFIG_SYS_NS16550_COM3) DECLARE_ESERIAL_FUNCTIONS(3); struct serial_device eserial3_device = INIT_ESERIAL_STRUCTURE(3, "eserial2"); +#endif +#if defined(CONFIG_SYS_NS16550_COM4) DECLARE_ESERIAL_FUNCTIONS(4); struct serial_device eserial4_device = INIT_ESERIAL_STRUCTURE(4, "eserial3"); +#endif +#if defined(CONFIG_SYS_NS16550_COM5) DECLARE_ESERIAL_FUNCTIONS(5); struct serial_device eserial5_device = INIT_ESERIAL_STRUCTURE(5, "eserial4"); +#endif +#if defined(CONFIG_SYS_NS16550_COM6) DECLARE_ESERIAL_FUNCTIONS(6); struct serial_device eserial6_device = INIT_ESERIAL_STRUCTURE(6, "eserial5"); +#endif __weak struct serial_device *default_serial_console(void) { -- cgit v1.2.3 From 7b395232da84ae59bd32985bf944a0a9f417a543 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Mon, 21 Jan 2013 21:10:38 +0000 Subject: malloc: make malloc_bin_reloc static MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On architectures where manual relocation is needed, the 'malloc_bin_reloc' function must be called after 'mem_malloc_init'. Make the 'malloc_bin_reloc' function static and call it directly from 'mem_malloc_init' instead of calling that from board_init_{r,f} functions of the affected architectures. Signed-off-by: Gabor Juhos Cc: Wolfgang Denk Cc: Andreas Bießmann Cc: Jason Jin Cc: Macpaul Lin Cc: Daniel Hellstrom Cc: Daniel Schwierzeck --- arch/avr32/lib/board.c | 1 - arch/m68k/lib/board.c | 1 - arch/nds32/lib/board.c | 1 - arch/sparc/lib/board.c | 1 - common/dlmalloc.c | 6 +++++- include/malloc.h | 1 - 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/avr32/lib/board.c b/arch/avr32/lib/board.c index d3c8cb76dd..bd1be73ae4 100644 --- a/arch/avr32/lib/board.c +++ b/arch/avr32/lib/board.c @@ -286,7 +286,6 @@ void board_init_r(gd_t *new_gd, ulong dest_addr) /* The malloc area is right below the monitor image in RAM */ mem_malloc_init(CONFIG_SYS_MONITOR_BASE + gd->reloc_off - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN); - malloc_bin_reloc(); dma_alloc_init(); enable_interrupts(); diff --git a/arch/m68k/lib/board.c b/arch/m68k/lib/board.c index c372ae228b..33acffe431 100644 --- a/arch/m68k/lib/board.c +++ b/arch/m68k/lib/board.c @@ -449,7 +449,6 @@ void board_init_r (gd_t *id, ulong dest_addr) /* The Malloc area is immediately below the monitor copy in DRAM */ mem_malloc_init (CONFIG_SYS_MONITOR_BASE + gd->reloc_off - TOTAL_MALLOC_LEN, TOTAL_MALLOC_LEN); - malloc_bin_reloc (); #if !defined(CONFIG_SYS_NO_FLASH) puts ("Flash: "); diff --git a/arch/nds32/lib/board.c b/arch/nds32/lib/board.c index 09feaf3733..c919928a37 100644 --- a/arch/nds32/lib/board.c +++ b/arch/nds32/lib/board.c @@ -320,7 +320,6 @@ void board_init_r(gd_t *id, ulong dest_addr) /* The Malloc area is immediately below the monitor copy in DRAM */ malloc_start = dest_addr - TOTAL_MALLOC_LEN; mem_malloc_init(malloc_start, TOTAL_MALLOC_LEN); - malloc_bin_reloc(); #ifndef CONFIG_SYS_NO_FLASH /* configure available FLASH banks */ diff --git a/arch/sparc/lib/board.c b/arch/sparc/lib/board.c index 1b5e995b15..79fb4c87ef 100644 --- a/arch/sparc/lib/board.c +++ b/arch/sparc/lib/board.c @@ -271,7 +271,6 @@ void board_init_f(ulong bootflag) /* The Malloc area is immediately below the monitor copy in RAM */ mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_END - CONFIG_SYS_MALLOC_BASE); - malloc_bin_reloc(); #if !defined(CONFIG_SYS_NO_FLASH) puts("Flash: "); diff --git a/common/dlmalloc.c b/common/dlmalloc.c index b2f0a1ad52..2a9d169f92 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -1485,7 +1485,7 @@ static mbinptr av_[NAV * 2 + 2] = { }; #ifdef CONFIG_NEEDS_MANUAL_RELOC -void malloc_bin_reloc (void) +static void malloc_bin_reloc(void) { mbinptr *p = &av_[2]; size_t i; @@ -1493,6 +1493,8 @@ void malloc_bin_reloc (void) for (i = 2; i < ARRAY_SIZE(av_); ++i, ++p) *p = (mbinptr)((ulong)*p + gd->reloc_off); } +#else +static inline void malloc_bin_reloc(void) {} #endif ulong mem_malloc_start = 0; @@ -1526,6 +1528,8 @@ void mem_malloc_init(ulong start, ulong size) mem_malloc_brk = start; memset((void *)mem_malloc_start, 0, size); + + malloc_bin_reloc(); } /* field-extraction macros */ diff --git a/include/malloc.h b/include/malloc.h index 84ecf79344..6295929ea3 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -937,7 +937,6 @@ extern ulong mem_malloc_end; extern ulong mem_malloc_brk; void mem_malloc_init(ulong start, ulong size); -void malloc_bin_reloc(void); #ifdef __cplusplus }; /* end of extern "C" */ -- cgit v1.2.3 From 7df54d316e70e2d6ae080ef98aa9d2388bbb8af9 Mon Sep 17 00:00:00 2001 From: Piotr Wilczek Date: Sun, 27 Jan 2013 22:59:24 +0000 Subject: vsprintf: add ustrtoll function Add 'ustrtoull' function to convert size from string (ex: 1GiB) to unsigned long long type Signed-off-by: Piotr Wilczek Signed-off-by: Kyungmin Park --- include/exports.h | 1 + lib/vsprintf.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/include/exports.h b/include/exports.h index 6cf31aa5e7..41d5085e16 100644 --- a/include/exports.h +++ b/include/exports.h @@ -24,6 +24,7 @@ int setenv (const char *varname, const char *varvalue); long simple_strtol(const char *cp,char **endp,unsigned int base); int strcmp(const char * cs,const char * ct); unsigned long ustrtoul(const char *cp, char **endp, unsigned int base); +unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base); #if defined(CONFIG_CMD_I2C) int i2c_write (uchar, uint, int , uchar* , int); int i2c_read (uchar, uint, int , uchar* , int); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3c432f8764..533a96b85e 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -126,6 +126,29 @@ unsigned long ustrtoul(const char *cp, char **endp, unsigned int base) return result; } +unsigned long long ustrtoull(const char *cp, char **endp, unsigned int base) +{ + unsigned long long result = simple_strtoull(cp, endp, base); + switch (**endp) { + case 'G': + result *= 1024; + /* fall through */ + case 'M': + result *= 1024; + /* fall through */ + case 'K': + case 'k': + result *= 1024; + if ((*endp)[1] == 'i') { + if ((*endp)[2] == 'B') + (*endp) += 3; + else + (*endp) += 2; + } + } + return result; +} + unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) { -- cgit v1.2.3 From 7789df9dc61a043bd9a2d647e2e212fb2d3c3d7e Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Thu, 31 Jan 2013 02:06:40 +0000 Subject: fw_env.config: Correct "fw_saveenv" to "fw_setenv". Fix a comment in the fw_env.config file, no functional change. Signed-off-by: Robert P. J. Day --- tools/env/fw_env.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/env/fw_env.config b/tools/env/fw_env.config index 8e21d5a5ab..9d3b1a4692 100644 --- a/tools/env/fw_env.config +++ b/tools/env/fw_env.config @@ -1,4 +1,4 @@ -# Configuration file for fw_(printenv/saveenv) utility. +# Configuration file for fw_(printenv/setenv) utility. # Up to two entries are valid, in this case the redundant # environment sector is assumed present. # Notice, that the "Number of sectors" is ignored on NOR and SPI-dataflash. -- cgit v1.2.3 From 85de63e2e68d314bea2119b817669034d397f64b Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sun, 3 Feb 2013 02:29:54 +0000 Subject: cmd_mem.c: Fix some typoes, no functional changes Signed-off-by: Robert P. J. Day --- common/cmd_mem.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 0f3ffc84ff..d44aa1d733 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -462,7 +462,8 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc, if (argc < 3) return CMD_RET_USAGE; - /* Check for a size spefication. + /* + * Check for a size specification. * Defaults to long if no or incorrect specification. */ if ((size = cmd_get_data_size(argv[0], 4)) < 0) @@ -531,7 +532,8 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc < 4) return CMD_RET_USAGE; - /* Check for a size spefication. + /* + * Check for a size specification. * Defaults to long if no or incorrect specification. */ if ((size = cmd_get_data_size(argv[0], 4)) < 0) @@ -683,7 +685,7 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, * Data line test: write a pattern to the first * location, write the 1's complement to a 'parking' * address (changes the state of the data bus so a - * floating bus doen't give a false OK), and then + * floating bus doesn't give a false OK), and then * read the value back. Note that we read it back * into a variable because the next time we read it, * it might be right (been there, tough to explain to @@ -747,7 +749,7 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, * 1's test on the relevant bits of the * address and checking for aliasing. * This test will find single-bit - * address failures such as stuck -high, + * address failures such as stuck-high, * stuck-low, and shorted pins. The base * address and size of the region are * selected by the caller. -- cgit v1.2.3 From 70d7cb92528c88b7e0db841d94383d8d0fb350f3 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Sun, 3 Feb 2013 05:46:13 +0000 Subject: cmd_load.c: Add #endif comments to reduce confusion Signed-off-by: Robert P. J. Day --- common/cmd_load.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/cmd_load.c b/common/cmd_load.c index 2c8dab1a0a..46db9626eb 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -1064,8 +1064,8 @@ U_BOOT_CMD( " - save S-Record file over serial line with offset 'off' and size 'size'" ); #endif /* CONFIG_SYS_LOADS_BAUD_CHANGE */ -#endif -#endif +#endif /* CONFIG_CMD_SAVES */ +#endif /* CONFIG_CMD_LOADS */ #if defined(CONFIG_CMD_LOADB) @@ -1085,7 +1085,7 @@ U_BOOT_CMD( " with offset 'off' and baudrate 'baud'" ); -#endif +#endif /* CONFIG_CMD_LOADB */ /* -------------------------------------------------------------------- */ @@ -1115,4 +1115,4 @@ U_BOOT_CMD( "[on|off]" ); -#endif +#endif /* CONFIG_CMD_HWFLOW */ -- cgit v1.2.3 From 1b3e0b191a3b93dee79226a276748c6e9aa1d071 Mon Sep 17 00:00:00 2001 From: Reinhard Arlt Date: Mon, 4 Feb 2013 09:37:11 +0000 Subject: cmd_elf: Fix broken bootvx command Fix broken bootvx command. Signed-off-by: Reinhard Arlt --- common/cmd_elf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmd_elf.c b/common/cmd_elf.c index a667a469b5..ab9c7e332d 100644 --- a/common/cmd_elf.c +++ b/common/cmd_elf.c @@ -198,7 +198,7 @@ int do_bootvx(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * defaults to 0x4200 */ tmp = getenv("bootaddr"); - if (tmp) + if (!tmp) bootaddr = CONFIG_SYS_VXWORKS_BOOT_ADDR; else bootaddr = simple_strtoul(tmp, NULL, 16); -- cgit v1.2.3 From 03414ac45e119496e2475aeacbb968bb67da24f8 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 7 Feb 2013 23:41:01 +0000 Subject: gpio: Build the da8xx_gpio code for the davinci644x device The differences include the number of GPIOs and that one is not required to set the pinmux on request. Signed-off-by: Holger Hans Peter Freyther --- arch/arm/include/asm/arch-davinci/gpio.h | 8 +++++++- drivers/gpio/Makefile | 1 + drivers/gpio/da8xx_gpio.c | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/arch-davinci/gpio.h b/arch/arm/include/asm/arch-davinci/gpio.h index ef65ffbb9f..5206b12211 100644 --- a/arch/arm/include/asm/arch-davinci/gpio.h +++ b/arch/arm/include/asm/arch-davinci/gpio.h @@ -65,9 +65,15 @@ struct davinci_gpio_bank { #define davinci_gpio_bank67 ((struct davinci_gpio *)DAVINCI_GPIO_BANK67) #define davinci_gpio_bank8 ((struct davinci_gpio *)DAVINCI_GPIO_BANK8) +#if defined(CONFIG_SOC_DM644X) +/* GPIO0 to GPIO53, omit the V3.3 volts one */ +#define MAX_NUM_GPIOS 70 +#else +#define MAX_NUM_GPIOS 144 +#endif + #define gpio_status() gpio_info() #define GPIO_NAME_SIZE 20 -#define MAX_NUM_GPIOS 144 #define GPIO_BANK(gp) (davinci_gpio_bank01 + ((gp) >> 5)) #define GPIO_BIT(gp) ((gp) & 0x1F) diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 2d97b4f1e4..9df1e2632f 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -39,6 +39,7 @@ COBJS-$(CONFIG_SANDBOX_GPIO) += sandbox.o COBJS-$(CONFIG_SPEAR_GPIO) += spear_gpio.o COBJS-$(CONFIG_TEGRA_GPIO) += tegra_gpio.o COBJS-$(CONFIG_DA8XX_GPIO) += da8xx_gpio.o +COBJS-$(CONFIG_DM644X_GPIO) += da8xx_gpio.o COBJS-$(CONFIG_ALTERA_PIO) += altera_pio.o COBJS-$(CONFIG_MPC83XX_GPIO) += mpc83xx_gpio.o COBJS-$(CONFIG_SH_GPIO_PFC) += sh_pfc.o diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c index 84d2b77d92..ed6a1180d4 100644 --- a/drivers/gpio/da8xx_gpio.c +++ b/drivers/gpio/da8xx_gpio.c @@ -31,6 +31,7 @@ static struct gpio_registry { char name[GPIO_NAME_SIZE]; } gpio_registry[MAX_NUM_GPIOS]; +#if defined(CONFIG_SOC_DA8XX) #define pinmux(x) (&davinci_syscfg_regs->pinmux[x]) static const struct pinmux_config gpio_pinmux[] = { @@ -179,6 +180,9 @@ static const struct pinmux_config gpio_pinmux[] = { { pinmux(18), 8, 3 }, { pinmux(18), 8, 2 }, }; +#else +#define davinci_configure_pin_mux(a, b) +#endif int gpio_request(unsigned gpio, const char *label) { -- cgit v1.2.3 From 4f47aceb118b291831a603d7e6ca651d76bf88e0 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 7 Feb 2013 23:41:02 +0000 Subject: led: The gpio_led.c code expects that LED state is from the enum u-boot is not consistent if state should be 0|1 or of the enum, the GPIO driver expects this to be one of the enum values. Update the caller. Signed-off-by: Holger Hans Peter Freyther --- common/cmd_led.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/cmd_led.c b/common/cmd_led.c index 7f5ab43c7f..c725f95ac1 100644 --- a/common/cmd_led.c +++ b/common/cmd_led.c @@ -110,13 +110,13 @@ int do_led (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (led_commands[i].on) led_commands[i].on(); else - __led_set(led_commands[i].mask, 1); + __led_set(led_commands[i].mask, STATUS_LED_ON); break; case LED_OFF: if (led_commands[i].off) led_commands[i].off(); else - __led_set(led_commands[i].mask, 0); + __led_set(led_commands[i].mask, STATUS_LED_OFF); break; case LED_TOGGLE: if (led_commands[i].toggle) -- cgit v1.2.3 From c8876f1c72ac36879436278892e6c20a93174b6a Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 7 Feb 2013 23:41:03 +0000 Subject: mac: Fix the condition check for setting the MAC from the EEPROM The issue got introduced in a cleanup by Manjunath Hadli in commit 826e99136e2bce61f3f6572e32d7aa724c116e6d. The eth_getenv_enetaddr_by_index method will validate the MAC addr and if none is set in the environment 0 will be returned. Set the MAC from the eeprom if no valid address is found in environment. Signed-off-by: Holger Hans Peter Freyther --- arch/arm/cpu/arm926ejs/davinci/misc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/cpu/arm926ejs/davinci/misc.c b/arch/arm/cpu/arm926ejs/davinci/misc.c index c310c69ad4..162c1e0ff4 100644 --- a/arch/arm/cpu/arm926ejs/davinci/misc.c +++ b/arch/arm/cpu/arm926ejs/davinci/misc.c @@ -104,7 +104,7 @@ void davinci_sync_env_enetaddr(uint8_t *rom_enetaddr) int ret; ret = eth_getenv_enetaddr_by_index("eth", 0, env_enetaddr); - if (ret) { + if (!ret) { /* * There is no MAC address in the environment, so we * initialize it from the value in the EEPROM. @@ -115,7 +115,7 @@ void davinci_sync_env_enetaddr(uint8_t *rom_enetaddr) ret = !eth_setenv_enetaddr("ethaddr", rom_enetaddr); } if (!ret) - printf("Failed to set mac address from EEPROM\n"); + printf("Failed to set mac address from EEPROM: %d\n", ret); } #endif /* CONFIG_DRIVER_TI_EMAC */ -- cgit v1.2.3 From 3e34cf7bffb87f3a96a87a4d1e0a76df7322b3c1 Mon Sep 17 00:00:00 2001 From: Piotr Wilczek Date: Sun, 27 Jan 2013 22:59:25 +0000 Subject: gpt: fix partion size limit Currently, in gpt command, partion size is converted from string to unsigned long type using 'ustrtol' function. That type limits the partition size to 4GB. This patch changes the conversion function to 'ustrtoll' to return unsigned long long type. Signed-off-by: Piotr Wilczek Signed-off-by: Kyungmin Park --- common/cmd_gpt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/cmd_gpt.c b/common/cmd_gpt.c index da7705da69..efd7934bd7 100644 --- a/common/cmd_gpt.c +++ b/common/cmd_gpt.c @@ -27,6 +27,7 @@ #include #include #include +#include #ifndef CONFIG_PARTITION_UUIDS #error CONFIG_PARTITION_UUIDS must be enabled for CONFIG_CMD_GPT to be enabled @@ -131,6 +132,7 @@ static int set_gpt_info(block_dev_desc_t *dev_desc, int p_count; disk_partition_t *parts; int errno = 0; + uint64_t size_ll, start_ll; debug("%s: MMC lba num: 0x%x %d\n", __func__, (unsigned int)dev_desc->lba, (unsigned int)dev_desc->lba); @@ -217,8 +219,8 @@ static int set_gpt_info(block_dev_desc_t *dev_desc, } if (extract_env(val, &p)) p = val; - parts[i].size = ustrtoul(p, &p, 0); - parts[i].size /= dev_desc->blksz; + size_ll = ustrtoull(p, &p, 0); + parts[i].size = lldiv(size_ll, dev_desc->blksz); free(val); /* start address */ @@ -226,8 +228,8 @@ static int set_gpt_info(block_dev_desc_t *dev_desc, if (val) { /* start address is optional */ if (extract_env(val, &p)) p = val; - parts[i].start = ustrtoul(p, &p, 0); - parts[i].start /= dev_desc->blksz; + start_ll = ustrtoull(p, &p, 0); + parts[i].start = lldiv(start_ll, dev_desc->blksz); free(val); } } -- cgit v1.2.3 From 47104c37de076e2be35ae1b3d144614f4d24a766 Mon Sep 17 00:00:00 2001 From: Allen Martin Date: Tue, 29 Jan 2013 14:34:58 +0000 Subject: MAKEALL: add support for per architecture toolchains Add support for per architecture CROSS_COMPILE toolchain definitions via CROSS_COMPILE_ARCH where "ARCH" is any of the supported u-boot architectures. This allows building every supported u-boot board in a single pass of MAKEALL. Signed-off-by: Allen Martin Acked-by: Simon Glass Reviewed-by: Stephen Warren --- MAKEALL | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/MAKEALL b/MAKEALL index 5b06c5477d..397adef920 100755 --- a/MAKEALL +++ b/MAKEALL @@ -35,6 +35,9 @@ usage() Environment variables: BUILD_NCPUS number of parallel make jobs (default: auto) CROSS_COMPILE cross-compiler toolchain prefix (default: "") + CROSS_COMPILE_ cross-compiler toolchain prefix for + architecture "ARCH". Substitute "ARCH" for any + supported architecture (default: "") MAKEALL_LOGDIR output all logs to here (default: ./LOG/) BUILD_DIR output build directory (default: ./) BUILD_NBUILDS number of parallel targets (default: 1) @@ -180,13 +183,6 @@ else JOBS="" fi - -if [ "${CROSS_COMPILE}" ] ; then - MAKE="make CROSS_COMPILE=${CROSS_COMPILE}" -else - MAKE=make -fi - if [ "${MAKEALL_LOGDIR}" ] ; then LOG_DIR=${MAKEALL_LOGDIR} else @@ -585,6 +581,18 @@ get_target_maintainers() { echo "$mail" } +get_target_arch() { + local target=$1 + + # Automatic mode + local line=`egrep -i "^[[:space:]]*${target}[[:space:]]" boards.cfg` + + if [ -z "${line}" ] ; then echo "" ; return ; fi + + set ${line} + echo "$2" +} + list_target() { if [ "$PRINT_MAINTS" != 'y' ] ; then echo "$1" @@ -655,6 +663,16 @@ build_target() { export BUILD_DIR="${output_dir}" + target_arch=$(get_target_arch ${target}) + eval cross_toolchain=\$CROSS_COMPILE_${target_arch^^} + if [ "${cross_toolchain}" ] ; then + MAKE="make CROSS_COMPILE=${cross_toolchain}" + elif [ "${CROSS_COMPILE}" ] ; then + MAKE="make CROSS_COMPILE=${CROSS_COMPILE}" + else + MAKE=make + fi + ${MAKE} distclean >/dev/null ${MAKE} -s ${target}_config -- cgit v1.2.3 From 8fdf1e0f6d645f79a9b0677e062bf48d786c5b9e Mon Sep 17 00:00:00 2001 From: Vipin Kumar Date: Sun, 16 Dec 2012 22:32:48 +0000 Subject: imls: Add support to list images in NAND device This patch adds support to list images in NAND flash through imls Signed-off-by: Vipin Kumar --- README | 3 +- common/cmd_bootm.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 166 insertions(+), 4 deletions(-) diff --git a/README b/README index d8cb3940d4..0070694438 100644 --- a/README +++ b/README @@ -842,7 +842,8 @@ The following options need to be configured: CONFIG_CMD_I2C * I2C serial bus support CONFIG_CMD_IDE * IDE harddisk support CONFIG_CMD_IMI iminfo - CONFIG_CMD_IMLS List all found images + CONFIG_CMD_IMLS List all images found in NOR flash + CONFIG_CMD_IMLS_NAND List all images found in NAND flash CONFIG_CMD_IMMAP * IMMR dump support CONFIG_CMD_IMPORTENV * import an environment CONFIG_CMD_INI * import data from an ini file into the env diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index f0338babeb..1312a0db8a 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -79,9 +79,15 @@ static int image_info(unsigned long addr); #include #include extern flash_info_t flash_info[]; /* info for FLASH chips */ +#endif + +#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); #endif +#include +#include + #ifdef CONFIG_SILENT_CONSOLE static void fixup_silent_linux(void); #endif @@ -1192,7 +1198,7 @@ U_BOOT_CMD( /* imls - list all images found in flash */ /*******************************************************************/ #if defined(CONFIG_CMD_IMLS) -static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_imls_nor(void) { flash_info_t *info; int i, j; @@ -1241,6 +1247,161 @@ next_sector: ; } next_bank: ; } + return 0; +} +#endif + +#if defined(CONFIG_CMD_IMLS_NAND) +static int nand_imls_legacyimage(nand_info_t *nand, int nand_dev, loff_t off, + size_t len) +{ + void *imgdata; + int ret; + + imgdata = malloc(len); + if (!imgdata) { + printf("May be a Legacy Image at NAND device %d offset %08llX:\n", + nand_dev, off); + printf(" Low memory(cannot allocate memory for image)\n"); + return -ENOMEM; + } + + ret = nand_read_skip_bad(nand, off, &len, + imgdata); + if (ret < 0 && ret != -EUCLEAN) { + free(imgdata); + return ret; + } + + if (!image_check_hcrc(imgdata)) { + free(imgdata); + return 0; + } + + printf("Legacy Image at NAND device %d offset %08llX:\n", + nand_dev, off); + image_print_contents(imgdata); + + puts(" Verifying Checksum ... "); + if (!image_check_dcrc(imgdata)) + puts("Bad Data CRC\n"); + else + puts("OK\n"); + + free(imgdata); + + return 0; +} + +static int nand_imls_fitimage(nand_info_t *nand, int nand_dev, loff_t off, + size_t len) +{ + void *imgdata; + int ret; + + imgdata = malloc(len); + if (!imgdata) { + printf("May be a FIT Image at NAND device %d offset %08llX:\n", + nand_dev, off); + printf(" Low memory(cannot allocate memory for image)\n"); + return -ENOMEM; + } + + ret = nand_read_skip_bad(nand, off, &len, + imgdata); + if (ret < 0 && ret != -EUCLEAN) { + free(imgdata); + return ret; + } + + if (!fit_check_format(imgdata)) { + free(imgdata); + return 0; + } + + printf("FIT Image at NAND device %d offset %08llX:\n", nand_dev, off); + + fit_print_contents(imgdata); + free(imgdata); + + return 0; +} + +static int do_imls_nand(void) +{ + nand_info_t *nand; + int nand_dev = nand_curr_device; + size_t len; + loff_t off; + u32 buffer[16]; + + if (nand_dev < 0 || nand_dev >= CONFIG_SYS_MAX_NAND_DEVICE) { + puts("\nNo NAND devices available\n"); + return -ENODEV; + } + + printf("\n"); + + for (nand_dev = 0; nand_dev < CONFIG_SYS_MAX_NAND_DEVICE; nand_dev++) { + nand = &nand_info[nand_dev]; + if (!nand->name || !nand->size) + continue; + + for (off = 0; off < nand->size; off += nand->erasesize) { + const image_header_t *header; + int ret; + + if (nand_block_isbad(nand, off)) + continue; + + len = sizeof(buffer); + + ret = nand_read(nand, off, &len, (u8 *)buffer); + if (ret < 0 && ret != -EUCLEAN) { + printf("NAND read error %d at offset %08llX\n", + ret, off); + continue; + } + + switch (genimg_get_format(buffer)) { + case IMAGE_FORMAT_LEGACY: + header = (const image_header_t *)buffer; + + len = image_get_image_size(header); + nand_imls_legacyimage(nand, nand_dev, off, len); + break; +#if defined(CONFIG_FIT) + case IMAGE_FORMAT_FIT: + len = fit_get_size(buffer); + nand_imls_fitimage(nand, nand_dev, off, len); + break; +#endif + } + } + } + + return 0; +} +#endif + +#if defined(CONFIG_CMD_IMLS) || defined(CONFIG_CMD_IMLS_NAND) +static int do_imls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int ret_nor = 0, ret_nand = 0; + +#if defined(CONFIG_CMD_IMLS) + ret_nor = do_imls_nor(); +#endif + +#if defined(CONFIG_CMD_IMLS_NAND) + ret_nand = do_imls_nand(); +#endif + + if (ret_nor) + return ret_nor; + + if (ret_nand) + return ret_nand; return (0); } @@ -1249,8 +1410,8 @@ U_BOOT_CMD( imls, 1, 1, do_imls, "list all images found in flash", "\n" - " - Prints information about all images found at sector\n" - " boundaries in flash." + " - Prints information about all images found at sector/block\n" + " boundaries in nor/nand flash." ); #endif -- cgit v1.2.3 From ced199dc858d57e807d3ec2a511c4bd9a4bd8765 Mon Sep 17 00:00:00 2001 From: Harvey Chapman Date: Thu, 7 Feb 2013 11:34:44 +0000 Subject: nand: fix nand read.option parsing "nand read.part addr off size" would be treated as "nand read.raw addr off 1" It now fails as intended stating "Unknown nand command suffix '.part'" Signed-off-by: Harvey Chapman --- common/cmd_nand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 1568594ca4..495610c405 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -608,7 +608,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) size_t rwsize; ulong pagecount = 1; int read; - int raw; + int raw = 0; if (argc < 4) goto usage; -- cgit v1.2.3 From fcecb4a52c780d5fa7e8781db7ef5440aff0b48c Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Fri, 8 Feb 2013 09:27:19 +0000 Subject: mtd: nand: Check if NAND is locked tight before lock cmds If the NAND is locked tight, commands such as lock and unlock will not work, but the NAND chip may not report an error. Check the lock tight status before attempting such operations so that an error status can be reported if we know the operation will not succeed. Signed-off-by: Joe Hershberger --- drivers/mtd/nand/nand_util.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 2ba0c5ef95..ff2d348307 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -237,6 +237,14 @@ int nand_lock(struct mtd_info *mtd, int tight) /* select the NAND device */ chip->select_chip(mtd, 0); + /* check the Lock Tight Status */ + chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, 0); + if (chip->read_byte(mtd) & NAND_LOCK_STATUS_TIGHT) { + printf("nand_lock: Device is locked tight!\n"); + ret = -1; + goto out; + } + chip->cmdfunc(mtd, (tight ? NAND_CMD_LOCK_TIGHT : NAND_CMD_LOCK), -1, -1); @@ -249,6 +257,7 @@ int nand_lock(struct mtd_info *mtd, int tight) ret = -1; } + out: /* de-select the NAND device */ chip->select_chip(mtd, -1); return ret; @@ -337,6 +346,15 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length, goto out; } + /* check the Lock Tight Status */ + page = (int)(start >> chip->page_shift); + chip->cmdfunc(mtd, NAND_CMD_LOCK_STATUS, -1, page & chip->pagemask); + if (chip->read_byte(mtd) & NAND_LOCK_STATUS_TIGHT) { + printf("nand_unlock: Device is locked tight!\n"); + ret = -1; + goto out; + } + if ((start & (mtd->erasesize - 1)) != 0) { printf("nand_unlock: Start address must be beginning of " "nand block!\n"); @@ -358,7 +376,6 @@ int nand_unlock(struct mtd_info *mtd, loff_t start, size_t length, length -= mtd->erasesize; /* submit address of first page to unlock */ - page = (int)(start >> chip->page_shift); chip->cmdfunc(mtd, NAND_CMD_UNLOCK1, -1, page & chip->pagemask); /* submit ADDRESS of LAST page to unlock */ -- cgit v1.2.3 From b76a147b722565bde046f707a5cc92df8ea29738 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 21 Feb 2013 18:21:55 +0100 Subject: env_nand.c: clarify log messages when env reading fails The single message is misleading, since there is no equivalent success note when reading the other copy succeeds. Instead, warn if one of the redundant copies could not be loaded and emphasise on the error when reading both fails. Signed-off-by: Phil Sutter --- common/env_nand.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/common/env_nand.c b/common/env_nand.c index 22e72a20b0..382e8aec5e 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -331,6 +331,7 @@ int get_nand_env_oob(nand_info_t *nand, unsigned long *result) void env_relocate_spec(void) { #if !defined(ENV_IS_EMBEDDED) + int read1_fail = 0, read2_fail = 0; int crc1_ok = 0, crc2_ok = 0; env_t *ep, *tmp_env1, *tmp_env2; @@ -342,11 +343,14 @@ void env_relocate_spec(void) goto done; } - if (readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1)) - puts("No Valid Environment Area found\n"); + read1_fail = readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1); + read2_fail = readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2); - if (readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2)) - puts("No Valid Redundant Environment Area found\n"); + if (read1_fail && read2_fail) + puts("*** Error - No Valid Environment Area found\n"); + else if (read1_fail || read2_fail) + puts("*** Warning - some problems detected " + "reading environment; recovered successfully\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; -- cgit v1.2.3 From a1eac57a2001ecf86a46f520cd85ef8e9c8b3687 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 21 Feb 2013 18:21:56 +0100 Subject: common/env_nand.c: calculate crc only when readenv was OK Calculating the checksum of incompletely read data is useless. Signed-off-by: Phil Sutter [scottwood@freescale.com: minor formatting fix] Signed-off-by: Scott Wood --- common/env_nand.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/env_nand.c b/common/env_nand.c index 382e8aec5e..5b69889c02 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -352,8 +352,10 @@ void env_relocate_spec(void) puts("*** Warning - some problems detected " "reading environment; recovered successfully\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; + crc1_ok = !read1_fail && + (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); + crc2_ok = !read2_fail && + (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); if (!crc1_ok && !crc2_ok) { set_default_env("!bad CRC"); -- cgit v1.2.3 From 8ec21bbe5c45fc80ca74eb403ab5b00a9e1f699f Mon Sep 17 00:00:00 2001 From: Allen Martin Date: Tue, 22 Jan 2013 13:11:21 +0000 Subject: sandbox: fix compiler warning Add back return statement to fix compiler warning about control flow reaching end of non void function that was introduced with: e05e5de arm: move C runtime setup code in crt0.S Signed-off-by: Allen Martin Acked-by: Simon Glass --- arch/sandbox/cpu/start.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 7603bf9008..5287fd5ee8 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -122,4 +122,7 @@ int main(int argc, char *argv[]) * never return. */ board_init_f(0); + + /* NOTREACHED - board_init_f() does not return */ + return 0; } -- cgit v1.2.3 From 6b3ff98da41a084658877282057adeb59ff6e9f2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:11 +0000 Subject: Tidy up error checking and fix bug in hash command There are two problems: 1. The argument count needs to be checked before argv is used 2. When verify is not enabled, we need to define a constant zero value Signed-off-by: Simon Glass --- common/cmd_hash.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/cmd_hash.c b/common/cmd_hash.c index 689c608572..eb6a33873b 100644 --- a/common/cmd_hash.c +++ b/common/cmd_hash.c @@ -32,11 +32,15 @@ static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #ifdef CONFIG_HASH_VERIFY int verify = 0; + if (argc < 4) + return CMD_RET_USAGE; if (!strcmp(argv[1], "-v")) { verify = 1; argc--; argv++; } +#else + const int verify = 0; #endif /* Move forward to 'algorithm' parameter */ argc--; -- cgit v1.2.3 From bda32ffcf712806c7880ded25a012fbeede35e80 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:12 +0000 Subject: Update print_buffer() to use const The buffer cannot be changed by this function, so change the buffer pointer to a const. This allows callers with const pointer to use the function without a cast. Signed-off-by: Simon Glass --- include/common.h | 3 ++- lib/display_options.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/include/common.h b/include/common.h index 4ad17eafb9..170f4391a6 100644 --- a/include/common.h +++ b/include/common.h @@ -270,7 +270,8 @@ int cpu_init(void); phys_size_t initdram (int); int display_options (void); void print_size(unsigned long long, const char *); -int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen); +int print_buffer(ulong addr, const void *data, uint width, uint count, + uint linelen); /* common/main.c */ void main_loop (void); diff --git a/lib/display_options.c b/lib/display_options.c index 694d2f22e8..0339970e7d 100644 --- a/lib/display_options.c +++ b/lib/display_options.c @@ -98,7 +98,8 @@ void print_size(unsigned long long size, const char *s) */ #define MAX_LINE_LENGTH_BYTES (64) #define DEFAULT_LINE_LENGTH_BYTES (16) -int print_buffer (ulong addr, void* data, uint width, uint count, uint linelen) +int print_buffer(ulong addr, const void *data, uint width, uint count, + uint linelen) { /* linebuf as a union causes proper alignment */ union linebuf { -- cgit v1.2.3 From e101550a9a8b956434cf2a73f66afbb42f4654bd Mon Sep 17 00:00:00 2001 From: Taylor Hutt Date: Sun, 24 Feb 2013 17:33:13 +0000 Subject: sandbox: Improve sandbox serial port keyboard interface Implements the tstc() interface for the serial driver. Multiplexing the console between the serial port and a keyboard uses a polling method of checking if characters are available; this means that the serial console must be non-blocking when attempting to read characters. Signed-off-by: Taylor Hutt Signed-off-by: Simon Glass --- arch/sandbox/cpu/os.c | 8 ++++++++ drivers/serial/sandbox.c | 44 ++++++++++++++++++++++++++++++++++++++------ include/os.h | 10 ++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 36637af6ce..3e37c930b0 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -44,6 +44,14 @@ ssize_t os_read(int fd, void *buf, size_t count) return read(fd, buf, count); } +ssize_t os_read_no_block(int fd, void *buf, size_t count) +{ + const int flags = fcntl(fd, F_GETFL, 0); + + fcntl(fd, F_SETFL, flags | O_NONBLOCK); + return os_read(fd, buf, count); +} + ssize_t os_write(int fd, const void *buf, size_t count) { return write(fd, buf, count); diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index cb19401df6..b73520ca94 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -30,6 +30,19 @@ #include #include +/* + * + * serial_buf: A buffer that holds keyboard characters for the + * Sandbox U-boot. + * + * invariants: + * serial_buf_write == serial_buf_read -> empty buffer + * (serial_buf_write + 1) % 16 == serial_buf_read -> full buffer + */ +static char serial_buf[16]; +static unsigned int serial_buf_write; +static unsigned int serial_buf_read; + static int sandbox_serial_init(void) { os_tty_raw(0); @@ -50,18 +63,37 @@ static void sandbox_serial_puts(const char *str) os_write(1, str, strlen(str)); } -static int sandbox_serial_getc(void) +static unsigned int increment_buffer_index(unsigned int index) +{ + return (index + 1) % ARRAY_SIZE(serial_buf); +} + +static int sandbox_serial_tstc(void) { - char buf; + const unsigned int next_index = + increment_buffer_index(serial_buf_write); ssize_t count; - count = os_read(0, &buf, 1); - return count == 1 ? buf : 0; + os_usleep(100); + if (next_index == serial_buf_read) + return 1; /* buffer full */ + + count = os_read_no_block(0, &serial_buf[serial_buf_write], 1); + if (count == 1) + serial_buf_write = next_index; + return serial_buf_write != serial_buf_read; } -static int sandbox_serial_tstc(void) +static int sandbox_serial_getc(void) { - return 0; + int result; + + while (!sandbox_serial_tstc()) + ; /* buffer empty */ + + result = serial_buf[serial_buf_read]; + serial_buf_read = increment_buffer_index(serial_buf_read); + return result; } static struct serial_device sandbox_serial_drv = { diff --git a/include/os.h b/include/os.h index 699682a408..c452d1b56e 100644 --- a/include/os.h +++ b/include/os.h @@ -39,6 +39,16 @@ struct sandbox_state; */ ssize_t os_read(int fd, void *buf, size_t count); +/** + * Access to the OS read() system call with non-blocking access + * + * \param fd File descriptor as returned by os_open() + * \param buf Buffer to place data + * \param count Number of bytes to read + * \return number of bytes read, or -1 on error + */ +ssize_t os_read_no_block(int fd, void *buf, size_t count); + /** * Access to the OS write() system call * -- cgit v1.2.3 From 4213fc2913722045eb2c327a64b99e3e3178aa5c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:14 +0000 Subject: sandbox: Add un/map_sysmen() to deal with sandbox's ram_buf Sandbox doesn't actually provide U-Boot access to the machine's physical memory. Instead it provides a RAM buffer of configurable size, and all memory accesses are within that buffer. Sandbox memory starts at 0 and is CONFIG_DRAM_SIZE bytes in size. Allowing access outside this buffer might produce unpredictable results in the event of an error, and would expose the host machine's memory architecture to the sandbox U-Boot. Most U-Boot functions assume that they can just access memory at given address. For sandbox this is not true. Add a map_sysmem() call which converts a U-Boot address to a system address. In most cases this is a NOP, but for sandbox it returns a pointer to that memory inside the RAM buffer. To get a U-Boot feature to work correctly within sandbox, you should call map_sysmem() to get a pointer to the address, and then use that address for any U-Boot memory accesses. Signed-off-by: Simon Glass --- README | 9 +++++++++ arch/sandbox/config.mk | 1 + arch/sandbox/include/asm/io.h | 10 ++++++++++ include/common.h | 12 ++++++++++++ 4 files changed, 32 insertions(+) diff --git a/README b/README index 0070694438..51eb71b27c 100644 --- a/README +++ b/README @@ -3811,6 +3811,15 @@ Low Level (hardware related) configuration options: that is executed before the actual U-Boot. E.g. when compiling a NAND SPL. +- CONFIG_ARCH_MAP_SYSMEM + Generally U-Boot (and in particular the md command) uses + effective address. It is therefore not necessary to regard + U-Boot address as virtual addresses that need to be translated + to physical addresses. However, sandbox requires this, since + it maintains its own little RAM buffer which contains all + addressable memory. This option causes some memory accesses + to be mapped through map_sysmem() / unmap_sysmem(). + - CONFIG_USE_ARCH_MEMCPY CONFIG_USE_ARCH_MEMSET If these options are used a optimized version of memcpy/memset will diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk index 02ce4a4410..4fd0d4e58f 100644 --- a/arch/sandbox/config.mk +++ b/arch/sandbox/config.mk @@ -18,4 +18,5 @@ # MA 02111-1307 USA PLATFORM_CPPFLAGS += -DCONFIG_SANDBOX -D__SANDBOX__ -U_FORTIFY_SOURCE +PLATFORM_CPPFLAGS += -DCONFIG_ARCH_MAP_SYSMEM PLATFORM_LIBS += -lrt diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index 0392d218ec..d8c02364d9 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -39,3 +39,13 @@ static inline void unmap_physmem(void *vaddr, unsigned long flags) { } + +/* For sandbox, we want addresses to point into our RAM buffer */ +static inline void *map_sysmem(phys_addr_t paddr, unsigned long len) +{ + return map_physmem(paddr, len, MAP_WRBACK); +} + +static inline void unmap_sysmem(const void *vaddr) +{ +} diff --git a/include/common.h b/include/common.h index 170f4391a6..1d0728f847 100644 --- a/include/common.h +++ b/include/common.h @@ -870,6 +870,18 @@ int cpu_disable(int nr); int cpu_release(int nr, int argc, char * const argv[]); #endif +/* Define a null map_sysmem() if the architecture doesn't use it */ +# ifndef CONFIG_ARCH_MAP_SYSMEM +static inline void *map_sysmem(phys_addr_t paddr, unsigned long len) +{ + return (void *)(uintptr_t)paddr; +} + +static inline void unmap_sysmem(const void *vaddr) +{ +} +# endif + #endif /* __ASSEMBLY__ */ #ifdef CONFIG_PPC -- cgit v1.2.3 From 0628ab8ec59834f98ede267edd21ddb8ba0bb57b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:15 +0000 Subject: sandbox: Change memory commands to use map_physmem Sandbox wants to support commands which use memory. The map_sysmen() call provides this feature, so use this in the memory commands. Signed-off-by: Simon Glass --- common/cmd_mem.c | 122 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 43 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index d44aa1d733..ee7bf9ad33 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -33,6 +33,7 @@ #include #endif #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -138,9 +139,13 @@ static int do_mem_md(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) # endif { + ulong bytes = size * length; + const void *buf = map_sysmem(addr, bytes); + /* Print the lines. */ - print_buffer(addr, (void*)addr, size, length, DISP_LINE_LEN/size); - addr += size*length; + print_buffer(addr, buf, size, length, DISP_LINE_LEN / size); + addr += bytes; + unmap_sysmem(buf); } #endif @@ -163,6 +168,8 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr, writeval, count; int size; + void *buf; + ulong bytes; if ((argc < 3) || (argc > 4)) return CMD_RET_USAGE; @@ -188,15 +195,18 @@ static int do_mem_mw(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) count = 1; } + bytes = size * count; + buf = map_sysmem(addr, bytes); while (count-- > 0) { if (size == 4) - *((ulong *)addr) = (ulong )writeval; + *((ulong *)buf) = (ulong)writeval; else if (size == 2) - *((ushort *)addr) = (ushort)writeval; + *((ushort *)buf) = (ushort)writeval; else - *((u_char *)addr) = (u_char)writeval; - addr += size; + *((u_char *)buf) = (u_char)writeval; + buf += size; } + unmap_sysmem(buf); return 0; } @@ -258,10 +268,11 @@ int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - ulong addr1, addr2, count, ngood; + ulong addr1, addr2, count, ngood, bytes; int size; int rcode = 0; const char *type; + const void *buf1, *buf2, *base; if (argc != 4) return CMD_RET_USAGE; @@ -294,33 +305,40 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif + bytes = size * count; + base = buf1 = map_sysmem(addr1, bytes); + buf2 = map_sysmem(addr2, bytes); for (ngood = 0; ngood < count; ++ngood) { ulong word1, word2; if (size == 4) { - word1 = *(ulong *)addr1; - word2 = *(ulong *)addr2; + word1 = *(ulong *)buf1; + word2 = *(ulong *)buf2; } else if (size == 2) { - word1 = *(ushort *)addr1; - word2 = *(ushort *)addr2; + word1 = *(ushort *)buf1; + word2 = *(ushort *)buf2; } else { - word1 = *(u_char *)addr1; - word2 = *(u_char *)addr2; + word1 = *(u_char *)buf1; + word2 = *(u_char *)buf2; } if (word1 != word2) { + ulong offset = buf1 - base; + printf("%s at 0x%08lx (%#0*lx) != %s at 0x%08lx (%#0*lx)\n", - type, addr1, size, word1, - type, addr2, size, word2); + type, (ulong)(addr1 + offset), size, word1, + type, (ulong)(addr2 + offset), size, word2); rcode = 1; break; } - addr1 += size; - addr2 += size; + buf1 += size; + buf2 += size; /* reset watchdog from time to time */ if ((ngood % (64 << 10)) == 0) WATCHDOG_RESET(); } + unmap_sysmem(buf1); + unmap_sysmem(buf2); printf("Total of %ld %s(s) were the same\n", ngood, type); return rcode; @@ -328,8 +346,10 @@ static int do_mem_cmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - ulong addr, dest, count; + ulong addr, dest, count, bytes; int size; + const void *src; + void *buf; if (argc != 4) return CMD_RET_USAGE; @@ -419,15 +439,18 @@ static int do_mem_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif + bytes = size * count; + buf = map_sysmem(addr, bytes); + src = map_sysmem(addr, bytes); while (count-- > 0) { if (size == 4) - *((ulong *)dest) = *((ulong *)addr); + *((ulong *)buf) = *((ulong *)src); else if (size == 2) - *((ushort *)dest) = *((ushort *)addr); + *((ushort *)buf) = *((ushort *)src); else - *((u_char *)dest) = *((u_char *)addr); - addr += size; - dest += size; + *((u_char *)buf) = *((u_char *)src); + src += size; + buf += size; /* reset watchdog from time to time */ if ((count % (64 << 10)) == 0) @@ -453,11 +476,12 @@ static int do_mem_base(cmd_tbl_t *cmdtp, int flag, int argc, static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - ulong addr, length, i; + ulong addr, length, i, bytes; int size; volatile uint *longp; volatile ushort *shortp; volatile u_char *cp; + const void *buf; if (argc < 3) return CMD_RET_USAGE; @@ -477,28 +501,31 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc, */ length = simple_strtoul(argv[2], NULL, 16); + bytes = size * length; + buf = map_sysmem(addr, bytes); + /* We want to optimize the loops to run as fast as possible. * If we have only one object, just run infinite loops. */ if (length == 1) { if (size == 4) { - longp = (uint *)addr; + longp = (uint *)buf; for (;;) i = *longp; } if (size == 2) { - shortp = (ushort *)addr; + shortp = (ushort *)buf; for (;;) i = *shortp; } - cp = (u_char *)addr; + cp = (u_char *)buf; for (;;) i = *cp; } if (size == 4) { for (;;) { - longp = (uint *)addr; + longp = (uint *)buf; i = length; while (i-- > 0) *longp++; @@ -506,28 +533,30 @@ static int do_mem_loop(cmd_tbl_t *cmdtp, int flag, int argc, } if (size == 2) { for (;;) { - shortp = (ushort *)addr; + shortp = (ushort *)buf; i = length; while (i-- > 0) *shortp++; } } for (;;) { - cp = (u_char *)addr; + cp = (u_char *)buf; i = length; while (i-- > 0) *cp++; } + unmap_sysmem(buf); } #ifdef CONFIG_LOOPW int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - ulong addr, length, i, data; + ulong addr, length, i, data, bytes; int size; volatile uint *longp; volatile ushort *shortp; volatile u_char *cp; + void *buf; if (argc < 4) return CMD_RET_USAGE; @@ -550,28 +579,31 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* data to write */ data = simple_strtoul(argv[3], NULL, 16); + bytes = size * length; + buf = map_sysmem(addr, bytes); + /* We want to optimize the loops to run as fast as possible. * If we have only one object, just run infinite loops. */ if (length == 1) { if (size == 4) { - longp = (uint *)addr; + longp = (uint *)buf; for (;;) *longp = data; } if (size == 2) { - shortp = (ushort *)addr; + shortp = (ushort *)buf; for (;;) *shortp = data; } - cp = (u_char *)addr; + cp = (u_char *)buf; for (;;) *cp = data; } if (size == 4) { for (;;) { - longp = (uint *)addr; + longp = (uint *)buf; i = length; while (i-- > 0) *longp++ = data; @@ -579,14 +611,14 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } if (size == 2) { for (;;) { - shortp = (ushort *)addr; + shortp = (ushort *)buf; i = length; while (i-- > 0) *shortp++ = data; } } for (;;) { - cp = (u_char *)addr; + cp = (u_char *)buf; i = length; while (i-- > 0) *cp++ = data; @@ -962,6 +994,7 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) { ulong addr, i; int nbytes, size; + void *ptr = NULL; if (argc != 2) return CMD_RET_USAGE; @@ -1006,13 +1039,14 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) * the next value. A non-converted value exits. */ do { + ptr = map_sysmem(addr, size); printf("%08lx:", addr); if (size == 4) - printf(" %08x", *((uint *)addr)); + printf(" %08x", *((uint *)ptr)); else if (size == 2) - printf(" %04x", *((ushort *)addr)); + printf(" %04x", *((ushort *)ptr)); else - printf(" %02x", *((u_char *)addr)); + printf(" %02x", *((u_char *)ptr)); nbytes = readline (" ? "); if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { @@ -1042,16 +1076,18 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) reset_cmd_timeout(); #endif if (size == 4) - *((uint *)addr) = i; + *((uint *)ptr) = i; else if (size == 2) - *((ushort *)addr) = i; + *((ushort *)ptr) = i; else - *((u_char *)addr) = i; + *((u_char *)ptr) = i; if (incrflag) addr += size; } } } while (nbytes); + if (ptr) + unmap_sysmem(ptr); mm_last_addr = addr; mm_last_size = size; -- cgit v1.2.3 From c9638f50fbd8e6973c296f6a8f2d5b91a4324c97 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:16 +0000 Subject: Split out the memory tests into separate functions Half of the code is currently hidden behind an #ifdef. Move the two memory tests into their own functions and use the compiler to eliminate the unused code. Signed-off-by: Simon Glass --- common/cmd_mem.c | 217 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 116 insertions(+), 101 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index ee7bf9ad33..0e7a4c67c2 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -626,36 +626,26 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif /* CONFIG_LOOPW */ -/* - * Perform a memory test. A more complete alternative test can be - * configured using CONFIG_SYS_ALT_MEMTEST. The complete test loops until - * interrupted by ctrl-c or by a failure of one of the sub-tests. - */ -static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[]) +static int mem_test_alt(vu_long *start, vu_long *end, + int iteration_limit) { - vu_long *addr, *start, *end; - ulong val; - ulong readback; - ulong errs = 0; + vu_long *addr; int iterations = 1; - int iteration_limit; - -#if defined(CONFIG_SYS_ALT_MEMTEST) - vu_long len; - vu_long offset; - vu_long test_offset; - vu_long pattern; - vu_long temp; - vu_long anti_pattern; - vu_long num_words; + ulong errs = 0; + ulong val, readback; + int j; + vu_long len; + vu_long offset; + vu_long test_offset; + vu_long pattern; + vu_long temp; + vu_long anti_pattern; + vu_long num_words; #if defined(CONFIG_SYS_MEMTEST_SCRATCH) - vu_long *dummy = (vu_long*)CONFIG_SYS_MEMTEST_SCRATCH; + vu_long *dummy = (vu_long *)CONFIG_SYS_MEMTEST_SCRATCH; #else vu_long *dummy = NULL; /* yes, this is address 0x0, not NULL */ #endif - int j; - static const ulong bitpattern[] = { 0x00000001, /* single bit */ 0x00000003, /* two adjacent bits */ @@ -666,43 +656,18 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, 0x00000055, /* four non-adjacent bits */ 0xaaaaaaaa, /* alternating 1/0 */ }; -#else - ulong incr; - ulong pattern; -#endif - if (argc > 1) - start = (ulong *)simple_strtoul(argv[1], NULL, 16); - else - start = (ulong *)CONFIG_SYS_MEMTEST_START; - - if (argc > 2) - end = (ulong *)simple_strtoul(argv[2], NULL, 16); - else - end = (ulong *)(CONFIG_SYS_MEMTEST_END); - - if (argc > 3) - pattern = (ulong)simple_strtoul(argv[3], NULL, 16); - else - pattern = 0; - - if (argc > 4) - iteration_limit = (ulong)simple_strtoul(argv[4], NULL, 16); - else - iteration_limit = 0; - -#if defined(CONFIG_SYS_ALT_MEMTEST) - printf ("Testing %08x ... %08x:\n", (uint)start, (uint)end); + printf("Testing %08x ... %08x:\n", (uint)(uintptr_t)start, + (uint)(uintptr_t)end); debug("%s:%d: start 0x%p end 0x%p\n", - __FUNCTION__, __LINE__, start, end); + __func__, __LINE__, start, end); for (;;) { if (ctrlc()) { - putc ('\n'); + putc('\n'); return 1; } - if (iteration_limit && iterations > iteration_limit) { printf("Tested %d iteration(s) with %lu errors.\n", iterations-1, errs); @@ -731,34 +696,35 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, * pattern and ~pattern). */ addr = start; - for (j = 0; j < sizeof(bitpattern)/sizeof(bitpattern[0]); j++) { + for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); + j++) { val = bitpattern[j]; - for(; val != 0; val <<= 1) { + for (; val != 0; val <<= 1) { *addr = val; - *dummy = ~val; /* clear the test data off of the bus */ + *dummy = ~val; /* clear the test data off the bus */ readback = *addr; if(readback != val) { - printf ("FAILURE (data line): " - "expected %08lx, actual %08lx\n", - val, readback); - errs++; - if (ctrlc()) { - putc ('\n'); - return 1; - } + printf("FAILURE (data line): " + "expected %08lx, actual %08lx\n", + val, readback); + errs++; + if (ctrlc()) { + putc('\n'); + return 1; + } } *addr = ~val; *dummy = val; readback = *addr; - if(readback != ~val) { - printf ("FAILURE (data line): " - "Is %08lx, should be %08lx\n", - readback, ~val); - errs++; - if (ctrlc()) { - putc ('\n'); - return 1; - } + if (readback != ~val) { + printf("FAILURE (data line): " + "Is %08lx, should be %08lx\n", + readback, ~val); + errs++; + if (ctrlc()) { + putc('\n'); + return 1; + } } } } @@ -802,15 +768,13 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, anti_pattern = (vu_long) 0x55555555; debug("%s:%d: length = 0x%.8lx\n", - __FUNCTION__, __LINE__, - len); + __func__, __LINE__, len); /* * Write the default pattern at each of the * power-of-two offsets. */ - for (offset = 1; offset < len; offset <<= 1) { + for (offset = 1; offset < len; offset <<= 1) start[offset] = pattern; - } /* * Check for address bits stuck high. @@ -821,12 +785,12 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, for (offset = 1; offset < len; offset <<= 1) { temp = start[offset]; if (temp != pattern) { - printf ("\nFAILURE: Address bit stuck high @ 0x%.8lx:" + printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx\n", (ulong)&start[offset], pattern, temp); errs++; if (ctrlc()) { - putc ('\n'); + putc('\n'); return 1; } } @@ -843,12 +807,12 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, for (offset = 1; offset < len; offset <<= 1) { temp = start[offset]; if ((temp != pattern) && (offset != test_offset)) { - printf ("\nFAILURE: Address bit stuck low or shorted @" + printf("\nFAILURE: Address bit stuck low or shorted @" " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n", (ulong)&start[offset], pattern, temp); errs++; if (ctrlc()) { - putc ('\n'); + putc('\n'); return 1; } } @@ -885,13 +849,13 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, WATCHDOG_RESET(); temp = start[offset]; if (temp != pattern) { - printf ("\nFAILURE (read/write) @ 0x%.8lx:" + printf("\nFAILURE (read/write) @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx)\n", (ulong)&start[offset], pattern, temp); errs++; if (ctrlc()) { - putc ('\n'); - return 1; + putc('\n'); + return 1; } } @@ -907,24 +871,33 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, anti_pattern = ~pattern; temp = start[offset]; if (temp != anti_pattern) { - printf ("\nFAILURE (read/write): @ 0x%.8lx:" + printf("\nFAILURE (read/write): @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx)\n", (ulong)&start[offset], anti_pattern, temp); errs++; if (ctrlc()) { - putc ('\n'); - return 1; + putc('\n'); + return 1; } } start[offset] = 0; } } +} + +static int mem_test_quick(vu_long *start, vu_long *end, + int iteration_limit, vu_long pattern) +{ + vu_long *addr; + int iterations = 1; + ulong errs = 0; + ulong incr; + ulong val, readback; -#else /* The original, quickie test */ incr = 1; for (;;) { if (ctrlc()) { - putc ('\n'); + putc('\n'); return 1; } @@ -935,29 +908,29 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, } ++iterations; - printf ("\rPattern %08lX Writing..." + printf("\rPattern %08lX Writing..." "%12s" "\b\b\b\b\b\b\b\b\b\b", pattern, ""); - for (addr=start,val=pattern; addr 1) + start = (ulong *)simple_strtoul(argv[1], NULL, 16); + else + start = (ulong *)CONFIG_SYS_MEMTEST_START; + + if (argc > 2) + end = (ulong *)simple_strtoul(argv[2], NULL, 16); + else + end = (ulong *)(CONFIG_SYS_MEMTEST_END); + + if (argc > 3) + pattern = (ulong)simple_strtoul(argv[3], NULL, 16); + else + pattern = 0; + + if (argc > 4) + iteration_limit = (ulong)simple_strtoul(argv[4], NULL, 16); + else + iteration_limit = 0; + + if (alt_test) + ret = mem_test_alt(start, end, iteration_limit); + else + ret = mem_test_quick(start, end, iteration_limit, pattern); + + return ret; /* not reached */ } -- cgit v1.2.3 From 51209b1f42cb6d1a7ce7c70be08aef2c988656cc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:17 +0000 Subject: Use common mtest iteration counting The iteration code is the same for each version of the memory test, so pull it out into the common function. Signed-off-by: Simon Glass --- common/cmd_mem.c | 123 ++++++++++++++++++++++++++----------------------------- 1 file changed, 59 insertions(+), 64 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 0e7a4c67c2..02ff65843a 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -626,11 +626,9 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif /* CONFIG_LOOPW */ -static int mem_test_alt(vu_long *start, vu_long *end, - int iteration_limit) +static ulong mem_test_alt(vu_long *start, vu_long *end) { vu_long *addr; - int iterations = 1; ulong errs = 0; ulong val, readback; int j; @@ -657,27 +655,6 @@ static int mem_test_alt(vu_long *start, vu_long *end, 0xaaaaaaaa, /* alternating 1/0 */ }; - printf("Testing %08x ... %08x:\n", (uint)(uintptr_t)start, - (uint)(uintptr_t)end); - debug("%s:%d: start 0x%p end 0x%p\n", - __func__, __LINE__, start, end); - - for (;;) { - if (ctrlc()) { - putc('\n'); - return 1; - } - - if (iteration_limit && iterations > iteration_limit) { - printf("Tested %d iteration(s) with %lu errors.\n", - iterations-1, errs); - return errs != 0; - } - - printf("Iteration: %6d\r", iterations); - debug("\n"); - iterations++; - /* * Data line test: write a pattern to the first * location, write the 1's complement to a 'parking' @@ -710,7 +687,7 @@ static int mem_test_alt(vu_long *start, vu_long *end, errs++; if (ctrlc()) { putc('\n'); - return 1; + return -1; } } *addr = ~val; @@ -723,7 +700,7 @@ static int mem_test_alt(vu_long *start, vu_long *end, errs++; if (ctrlc()) { putc('\n'); - return 1; + return -1; } } } @@ -791,7 +768,7 @@ static int mem_test_alt(vu_long *start, vu_long *end, errs++; if (ctrlc()) { putc('\n'); - return 1; + return -1; } } } @@ -813,7 +790,7 @@ static int mem_test_alt(vu_long *start, vu_long *end, errs++; if (ctrlc()) { putc('\n'); - return 1; + return -1; } } } @@ -855,7 +832,7 @@ static int mem_test_alt(vu_long *start, vu_long *end, errs++; if (ctrlc()) { putc('\n'); - return 1; + return -1; } } @@ -877,37 +854,38 @@ static int mem_test_alt(vu_long *start, vu_long *end, errs++; if (ctrlc()) { putc('\n'); - return 1; + return -1; } } start[offset] = 0; } - } + + return 0; } -static int mem_test_quick(vu_long *start, vu_long *end, - int iteration_limit, vu_long pattern) +static ulong mem_test_quick(vu_long *start, vu_long *end, vu_long pattern, + int iteration) { vu_long *addr; - int iterations = 1; ulong errs = 0; ulong incr; ulong val, readback; + /* Alternate the pattern */ incr = 1; - for (;;) { - if (ctrlc()) { - putc('\n'); - return 1; - } - - if (iteration_limit && iterations > iteration_limit) { - printf("Tested %d iteration(s) with %lu errors.\n", - iterations-1, errs); - return errs != 0; - } - ++iterations; - + if (iteration & 1) { + incr = -incr; + /* + * Flip the pattern each time to make lots of zeros and + * then, the next time, lots of ones. We decrement + * the "negative" patterns and increment the "positive" + * patterns to preserve this feature. + */ + if (pattern & 0x80000000) + pattern = -pattern; /* complement & increment */ + else + pattern = ~pattern; + } printf("\rPattern %08lX Writing..." "%12s" "\b\b\b\b\b\b\b\b\b\b", @@ -931,24 +909,13 @@ static int mem_test_quick(vu_long *start, vu_long *end, errs++; if (ctrlc()) { putc('\n'); - return 1; + return -1; } } val += incr; } - /* - * Flip the pattern each time to make lots of zeros and - * then, the next time, lots of ones. We decrement - * the "negative" patterns and increment the "positive" - * patterns to preserve this feature. - */ - if (pattern & 0x80000000) - pattern = -pattern; /* complement & increment */ - else - pattern = ~pattern; - incr = -incr; - } + return 0; } /* @@ -962,7 +929,9 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, vu_long *start, *end; int iteration_limit; int ret; + ulong errs = 0; /* number of errors, or -1 if interrupted */ ulong pattern; + int iteration; #if defined(CONFIG_SYS_ALT_MEMTEST) const int alt_test = 1; #else @@ -989,10 +958,36 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, else iteration_limit = 0; - if (alt_test) - ret = mem_test_alt(start, end, iteration_limit); - else - ret = mem_test_quick(start, end, iteration_limit, pattern); + printf("Testing %08x ... %08x:\n", (uint)(uintptr_t)start, + (uint)(uintptr_t)end); + debug("%s:%d: start 0x%p end 0x%p\n", + __func__, __LINE__, start, end); + + for (iteration = 0; + !iteration_limit || iteration < iteration_limit; + iteration++) { + if (ctrlc()) { + putc('\n'); + errs = -1UL; + break; + } + + printf("Iteration: %6d\r", iteration + 1); + debug("\n"); + if (alt_test) + errs = mem_test_alt(start, end); + else + errs = mem_test_quick(start, end, pattern, iteration); + } + + if (errs == -1UL) { + /* Memory test was aborted */ + ret = 1; + } else { + printf("Tested %d iteration(s) with %lu errors.\n", + iteration, errs); + ret = errs != 0; + } return ret; /* not reached */ } -- cgit v1.2.3 From 7ecbd4d70842362c3a8ad9393e9d9aab7e13afbf Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:18 +0000 Subject: Fix mtest indenting Some of the inner loops are not indented correctly. Fix this. Signed-off-by: Simon Glass --- common/cmd_mem.c | 322 +++++++++++++++++++++++++++---------------------------- 1 file changed, 161 insertions(+), 161 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 02ff65843a..5235bfe581 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -655,32 +655,31 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) 0xaaaaaaaa, /* alternating 1/0 */ }; - /* - * Data line test: write a pattern to the first - * location, write the 1's complement to a 'parking' - * address (changes the state of the data bus so a - * floating bus doesn't give a false OK), and then - * read the value back. Note that we read it back - * into a variable because the next time we read it, - * it might be right (been there, tough to explain to - * the quality guys why it prints a failure when the - * "is" and "should be" are obviously the same in the - * error message). - * - * Rather than exhaustively testing, we test some - * patterns by shifting '1' bits through a field of - * '0's and '0' bits through a field of '1's (i.e. - * pattern and ~pattern). - */ - addr = start; - for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); - j++) { - val = bitpattern[j]; - for (; val != 0; val <<= 1) { + /* + * Data line test: write a pattern to the first + * location, write the 1's complement to a 'parking' + * address (changes the state of the data bus so a + * floating bus doesn't give a false OK), and then + * read the value back. Note that we read it back + * into a variable because the next time we read it, + * it might be right (been there, tough to explain to + * the quality guys why it prints a failure when the + * "is" and "should be" are obviously the same in the + * error message). + * + * Rather than exhaustively testing, we test some + * patterns by shifting '1' bits through a field of + * '0's and '0' bits through a field of '1's (i.e. + * pattern and ~pattern). + */ + addr = start; + for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) { + val = bitpattern[j]; + for (; val != 0; val <<= 1) { *addr = val; *dummy = ~val; /* clear the test data off the bus */ readback = *addr; - if(readback != val) { + if (readback != val) { printf("FAILURE (data line): " "expected %08lx, actual %08lx\n", val, readback); @@ -703,129 +702,130 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) return -1; } } - } } + } - /* - * Based on code whose Original Author and Copyright - * information follows: Copyright (c) 1998 by Michael - * Barr. This software is placed into the public - * domain and may be used for any purpose. However, - * this notice must not be changed or removed and no - * warranty is either expressed or implied by its - * publication or distribution. - */ + /* + * Based on code whose Original Author and Copyright + * information follows: Copyright (c) 1998 by Michael + * Barr. This software is placed into the public + * domain and may be used for any purpose. However, + * this notice must not be changed or removed and no + * warranty is either expressed or implied by its + * publication or distribution. + */ - /* - * Address line test - * - * Description: Test the address bus wiring in a - * memory region by performing a walking - * 1's test on the relevant bits of the - * address and checking for aliasing. - * This test will find single-bit - * address failures such as stuck-high, - * stuck-low, and shorted pins. The base - * address and size of the region are - * selected by the caller. - * - * Notes: For best results, the selected base - * address should have enough LSB 0's to - * guarantee single address bit changes. - * For example, to test a 64-Kbyte - * region, select a base address on a - * 64-Kbyte boundary. Also, select the - * region size as a power-of-two if at - * all possible. - * - * Returns: 0 if the test succeeds, 1 if the test fails. - */ - len = ((ulong)end - (ulong)start)/sizeof(vu_long); - pattern = (vu_long) 0xaaaaaaaa; - anti_pattern = (vu_long) 0x55555555; + /* + * Address line test + + * Description: Test the address bus wiring in a + * memory region by performing a walking + * 1's test on the relevant bits of the + * address and checking for aliasing. + * This test will find single-bit + * address failures such as stuck-high, + * stuck-low, and shorted pins. The base + * address and size of the region are + * selected by the caller. + + * Notes: For best results, the selected base + * address should have enough LSB 0's to + * guarantee single address bit changes. + * For example, to test a 64-Kbyte + * region, select a base address on a + * 64-Kbyte boundary. Also, select the + * region size as a power-of-two if at + * all possible. + * + * Returns: 0 if the test succeeds, 1 if the test fails. + */ + len = ((ulong)end - (ulong)start)/sizeof(vu_long); + pattern = (vu_long) 0xaaaaaaaa; + anti_pattern = (vu_long) 0x55555555; - debug("%s:%d: length = 0x%.8lx\n", - __func__, __LINE__, len); - /* - * Write the default pattern at each of the - * power-of-two offsets. - */ - for (offset = 1; offset < len; offset <<= 1) - start[offset] = pattern; + debug("%s:%d: length = 0x%.8lx\n", + __func__, __LINE__, len); + /* + * Write the default pattern at each of the + * power-of-two offsets. + */ + for (offset = 1; offset < len; offset <<= 1) + start[offset] = pattern; - /* - * Check for address bits stuck high. - */ - test_offset = 0; - start[test_offset] = anti_pattern; + /* + * Check for address bits stuck high. + */ + test_offset = 0; + start[test_offset] = anti_pattern; - for (offset = 1; offset < len; offset <<= 1) { - temp = start[offset]; - if (temp != pattern) { + for (offset = 1; offset < len; offset <<= 1) { + temp = start[offset]; + if (temp != pattern) { printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx\n", (ulong)&start[offset], pattern, temp); errs++; if (ctrlc()) { - putc('\n'); - return -1; + putc('\n'); + return -1; } - } } - start[test_offset] = pattern; - WATCHDOG_RESET(); + } + start[test_offset] = pattern; + WATCHDOG_RESET(); - /* - * Check for addr bits stuck low or shorted. - */ - for (test_offset = 1; test_offset < len; test_offset <<= 1) { - start[test_offset] = anti_pattern; + /* + * Check for addr bits stuck low or shorted. + */ + for (test_offset = 1; test_offset < len; test_offset <<= 1) { + start[test_offset] = anti_pattern; - for (offset = 1; offset < len; offset <<= 1) { + for (offset = 1; offset < len; offset <<= 1) { temp = start[offset]; if ((temp != pattern) && (offset != test_offset)) { - printf("\nFAILURE: Address bit stuck low or shorted @" - " 0x%.8lx: expected 0x%.8lx, actual 0x%.8lx\n", - (ulong)&start[offset], pattern, temp); - errs++; - if (ctrlc()) { - putc('\n'); - return -1; - } + printf("\nFAILURE: Address bit stuck low or" + " shorted @ 0x%.8lx: expected 0x%.8lx," + " actual 0x%.8lx\n", + (ulong)&start[offset], pattern, temp); + errs++; + if (ctrlc()) { + putc('\n'); + return -1; + } } - } - start[test_offset] = pattern; } + start[test_offset] = pattern; + } - /* - * Description: Test the integrity of a physical - * memory device by performing an - * increment/decrement test over the - * entire region. In the process every - * storage bit in the device is tested - * as a zero and a one. The base address - * and the size of the region are - * selected by the caller. - * - * Returns: 0 if the test succeeds, 1 if the test fails. - */ - num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1; + /* + * Description: Test the integrity of a physical + * memory device by performing an + * increment/decrement test over the + * entire region. In the process every + * storage bit in the device is tested + * as a zero and a one. The base address + * and the size of the region are + * selected by the caller. + * + * Returns: 0 if the test succeeds, 1 if the test fails. + */ + num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1; - /* - * Fill memory with a known pattern. - */ - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { - WATCHDOG_RESET(); - start[offset] = pattern; - } + /* + * Fill memory with a known pattern. + */ + for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { + WATCHDOG_RESET(); + start[offset] = pattern; + } - /* - * Check each location and invert it for the second pass. - */ - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { - WATCHDOG_RESET(); - temp = start[offset]; - if (temp != pattern) { + /* + * Check each location and invert it for the second pass. + */ + for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { + WATCHDOG_RESET(); + temp = start[offset]; + if (temp != pattern) { printf("\nFAILURE (read/write) @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx)\n", (ulong)&start[offset], pattern, temp); @@ -834,20 +834,20 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) putc('\n'); return -1; } - } - - anti_pattern = ~pattern; - start[offset] = anti_pattern; } - /* - * Check each location for the inverted pattern and zero it. - */ - for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { - WATCHDOG_RESET(); - anti_pattern = ~pattern; - temp = start[offset]; - if (temp != anti_pattern) { + anti_pattern = ~pattern; + start[offset] = anti_pattern; + } + + /* + * Check each location for the inverted pattern and zero it. + */ + for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { + WATCHDOG_RESET(); + anti_pattern = ~pattern; + temp = start[offset]; + if (temp != anti_pattern) { printf("\nFAILURE (read/write): @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx)\n", (ulong)&start[offset], anti_pattern, temp); @@ -856,9 +856,9 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) putc('\n'); return -1; } - } - start[offset] = 0; } + start[offset] = 0; + } return 0; } @@ -886,34 +886,34 @@ static ulong mem_test_quick(vu_long *start, vu_long *end, vu_long pattern, else pattern = ~pattern; } - printf("\rPattern %08lX Writing..." - "%12s" - "\b\b\b\b\b\b\b\b\b\b", - pattern, ""); + printf("\rPattern %08lX Writing..." + "%12s" + "\b\b\b\b\b\b\b\b\b\b", + pattern, ""); - for (addr = start, val = pattern; addr < end; addr++) { - WATCHDOG_RESET(); - *addr = val; - val += incr; - } + for (addr = start, val = pattern; addr < end; addr++) { + WATCHDOG_RESET(); + *addr = val; + val += incr; + } - puts("Reading..."); + puts("Reading..."); - for (addr = start, val = pattern; addr < end; addr++) { - WATCHDOG_RESET(); - readback = *addr; - if (readback != val) { - printf("\nMem error @ 0x%08X: " - "found %08lX, expected %08lX\n", - (uint)(uintptr_t)addr, readback, val); - errs++; - if (ctrlc()) { - putc('\n'); - return -1; - } + for (addr = start, val = pattern; addr < end; addr++) { + WATCHDOG_RESET(); + readback = *addr; + if (readback != val) { + printf("\nMem error @ 0x%08X: " + "found %08lX, expected %08lX\n", + (uint)(uintptr_t)addr, readback, val); + errs++; + if (ctrlc()) { + putc('\n'); + return -1; } - val += incr; } + val += incr; + } return 0; } -- cgit v1.2.3 From c44d4386e67ac6dd57ddd60fdde54bf7ed581b6e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:19 +0000 Subject: Bring mtest putc() into common code If we get a Ctrl-C abort, we always print a newline. Move this repeated code out of the functions and into a single place in the caller. Signed-off-by: Simon Glass --- common/cmd_mem.c | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 5235bfe581..f5dd56db54 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -684,10 +684,8 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) "expected %08lx, actual %08lx\n", val, readback); errs++; - if (ctrlc()) { - putc('\n'); + if (ctrlc()) return -1; - } } *addr = ~val; *dummy = val; @@ -697,10 +695,8 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) "Is %08lx, should be %08lx\n", readback, ~val); errs++; - if (ctrlc()) { - putc('\n'); + if (ctrlc()) return -1; - } } } } @@ -765,10 +761,8 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) " expected 0x%.8lx, actual 0x%.8lx\n", (ulong)&start[offset], pattern, temp); errs++; - if (ctrlc()) { - putc('\n'); + if (ctrlc()) return -1; - } } } start[test_offset] = pattern; @@ -788,10 +782,8 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) " actual 0x%.8lx\n", (ulong)&start[offset], pattern, temp); errs++; - if (ctrlc()) { - putc('\n'); + if (ctrlc()) return -1; - } } } start[test_offset] = pattern; @@ -830,10 +822,8 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) " expected 0x%.8lx, actual 0x%.8lx)\n", (ulong)&start[offset], pattern, temp); errs++; - if (ctrlc()) { - putc('\n'); + if (ctrlc()) return -1; - } } anti_pattern = ~pattern; @@ -852,10 +842,8 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) " expected 0x%.8lx, actual 0x%.8lx)\n", (ulong)&start[offset], anti_pattern, temp); errs++; - if (ctrlc()) { - putc('\n'); + if (ctrlc()) return -1; - } } start[offset] = 0; } @@ -907,10 +895,8 @@ static ulong mem_test_quick(vu_long *start, vu_long *end, vu_long pattern, "found %08lX, expected %08lX\n", (uint)(uintptr_t)addr, readback, val); errs++; - if (ctrlc()) { - putc('\n'); + if (ctrlc()) return -1; - } } val += incr; } @@ -967,7 +953,6 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, !iteration_limit || iteration < iteration_limit; iteration++) { if (ctrlc()) { - putc('\n'); errs = -1UL; break; } @@ -981,7 +966,8 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, } if (errs == -1UL) { - /* Memory test was aborted */ + /* Memory test was aborted - write a newline to finish off */ + putc('\n'); ret = 1; } else { printf("Tested %d iteration(s) with %lu errors.\n", -- cgit v1.2.3 From 8c86bbe00f927de0655a65e43344ca0678d1bc34 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:20 +0000 Subject: Reduce casting in mtest Use a ulong for the command arguments, and only cast to an address when needed. This fixes warnings in sandbox where pointers are typically 64 bits long. Signed-off-by: Simon Glass --- common/cmd_mem.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index f5dd56db54..12dbc1609c 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -626,8 +626,9 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif /* CONFIG_LOOPW */ -static ulong mem_test_alt(vu_long *start, vu_long *end) +static ulong mem_test_alt(ulong start_addr, ulong end_addr) { + vu_long *start, *end; vu_long *addr; ulong errs = 0; ulong val, readback; @@ -655,6 +656,9 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) 0xaaaaaaaa, /* alternating 1/0 */ }; + start = (vu_long *)start_addr; + end = (vu_long *)end_addr; + /* * Data line test: write a pattern to the first * location, write the 1's complement to a 'parking' @@ -735,7 +739,7 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) * * Returns: 0 if the test succeeds, 1 if the test fails. */ - len = ((ulong)end - (ulong)start)/sizeof(vu_long); + len = (end_addr - start_addr) / sizeof(vu_long); pattern = (vu_long) 0xaaaaaaaa; anti_pattern = (vu_long) 0x55555555; @@ -851,9 +855,10 @@ static ulong mem_test_alt(vu_long *start, vu_long *end) return 0; } -static ulong mem_test_quick(vu_long *start, vu_long *end, vu_long pattern, +static ulong mem_test_quick(ulong start_addr, ulong end_addr, vu_long pattern, int iteration) { + vu_long *start, *end; vu_long *addr; ulong errs = 0; ulong incr; @@ -874,6 +879,8 @@ static ulong mem_test_quick(vu_long *start, vu_long *end, vu_long pattern, else pattern = ~pattern; } + start = (vu_long *)start_addr; + end = (vu_long *)end_addr; printf("\rPattern %08lX Writing..." "%12s" "\b\b\b\b\b\b\b\b\b\b", @@ -912,7 +919,7 @@ static ulong mem_test_quick(vu_long *start, vu_long *end, vu_long pattern, static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - vu_long *start, *end; + ulong start, end; int iteration_limit; int ret; ulong errs = 0; /* number of errors, or -1 if interrupted */ @@ -925,14 +932,14 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, #endif if (argc > 1) - start = (ulong *)simple_strtoul(argv[1], NULL, 16); + start = simple_strtoul(argv[1], NULL, 16); else - start = (ulong *)CONFIG_SYS_MEMTEST_START; + start = CONFIG_SYS_MEMTEST_START; if (argc > 2) - end = (ulong *)simple_strtoul(argv[2], NULL, 16); + end = simple_strtoul(argv[2], NULL, 16); else - end = (ulong *)(CONFIG_SYS_MEMTEST_END); + end = CONFIG_SYS_MEMTEST_END; if (argc > 3) pattern = (ulong)simple_strtoul(argv[3], NULL, 16); @@ -944,10 +951,9 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, else iteration_limit = 0; - printf("Testing %08x ... %08x:\n", (uint)(uintptr_t)start, - (uint)(uintptr_t)end); - debug("%s:%d: start 0x%p end 0x%p\n", - __func__, __LINE__, start, end); + printf("Testing %08x ... %08x:\n", (uint)start, (uint)end); + debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__, + start, end); for (iteration = 0; !iteration_limit || iteration < iteration_limit; -- cgit v1.2.3 From bfc59966431e6335fd5be0589eec073902cc7bb3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:21 +0000 Subject: Update set_working_fdt_addr() to use setenv_addr() We might as well use this common function instead of repeating the same code. Signed-off-by: Simon Glass --- common/cmd_fdt.c | 11 ++--------- common/cmd_nvedit.c | 8 ++++---- include/common.h | 14 +++++++++++++- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 6eec947fcb..ac77a08b77 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -55,12 +55,8 @@ struct fdt_header *working_fdt; void set_working_fdt_addr(void *addr) { - char buf[17]; - working_fdt = addr; - - sprintf(buf, "%lx", (unsigned long)addr); - setenv("fdtaddr", buf); + setenv_addr("fdtaddr", addr); } /* @@ -347,10 +343,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } if (subcmd[0] == 's') { /* get the num nodes at this level */ - char buf[11]; - - sprintf(buf, "%d", curIndex + 1); - setenv(var, buf); + setenv_ulong(var, curIndex + 1); } else { /* node index not found */ printf("libfdt node not found\n"); diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 7633f0c44a..44e88aa401 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -295,17 +295,17 @@ int setenv_ulong(const char *varname, ulong value) } /** - * Set an environment variable to an address in hex + * Set an environment variable to an value in hex * * @param varname Environmet variable to set - * @param addr Value to set it to + * @param value Value to set it to * @return 0 if ok, 1 on error */ -int setenv_addr(const char *varname, const void *addr) +int setenv_hex(const char *varname, ulong value) { char str[17]; - sprintf(str, "%lx", (uintptr_t)addr); + sprintf(str, "%lx", value); return setenv(varname, str); } diff --git a/include/common.h b/include/common.h index 1d0728f847..6d52924225 100644 --- a/include/common.h +++ b/include/common.h @@ -358,7 +358,19 @@ int getenv_yesno(const char *var); int saveenv (void); int setenv (const char *, const char *); int setenv_ulong(const char *varname, ulong value); -int setenv_addr(const char *varname, const void *addr); +int setenv_hex(const char *varname, ulong value); +/** + * setenv_addr - Set an environment variable to an address in hex + * + * @varname: Environmet variable to set + * @addr: Value to set it to + * @return 0 if ok, 1 on error + */ +static inline int setenv_addr(const char *varname, const void *addr) +{ + return setenv_hex(varname, (ulong)addr); +} + #ifdef CONFIG_ARM # include # include -- cgit v1.2.3 From 41ef372c1a2d344621c74aa4bce5cdb0970ba5f1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:22 +0000 Subject: common: Use new numeric setenv functions Use setenv_ulong(), setenv_hex() and setenv_addr() in common/ Signed-off-by: Simon Glass --- common/cmd_bootm.c | 11 +++-------- common/cmd_cbfs.c | 4 +--- common/cmd_cramfs.c | 4 +--- common/cmd_fdos.c | 4 +--- common/cmd_jffs2.c | 4 +--- common/cmd_load.c | 12 +++--------- common/cmd_mtdparts.c | 4 +--- common/cmd_nand.c | 12 +++--------- common/cmd_nvedit.c | 3 +-- common/cmd_reiser.c | 4 +--- common/cmd_setexpr.c | 39 +++++++++++++++++++++++++++------------ common/cmd_unzip.c | 4 +--- common/cmd_ximg.c | 7 ++----- common/cmd_zfs.c | 3 +-- common/cmd_zip.c | 4 +--- 15 files changed, 48 insertions(+), 71 deletions(-) diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 1312a0db8a..b32991da0d 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -452,9 +452,7 @@ static int bootm_start_standalone(ulong iflag, int argc, char * const argv[]) /* Don't start if "autostart" is set to "no" */ if (((s = getenv("autostart")) != NULL) && (strcmp(s, "no") == 0)) { - char buf[32]; - sprintf(buf, "%lX", images.os.image_len); - setenv("filesize", buf); + setenv_hex("filesize", images.os.image_len); return 0; } appl = (int (*)(int, char * const []))(ulong)ntohl(images.ep); @@ -529,17 +527,14 @@ static int do_bootm_subcommand(cmd_tbl_t *cmdtp, int flag, int argc, case BOOTM_STATE_RAMDISK: { ulong rd_len = images.rd_end - images.rd_start; - char str[17]; ret = boot_ramdisk_high(&images.lmb, images.rd_start, rd_len, &images.initrd_start, &images.initrd_end); if (ret) return ret; - sprintf(str, "%lx", images.initrd_start); - setenv("initrd_start", str); - sprintf(str, "%lx", images.initrd_end); - setenv("initrd_end", str); + setenv_hex("initrd_start", images.initrd_start); + setenv_hex("initrd_end", images.initrd_end); } break; #endif diff --git a/common/cmd_cbfs.c b/common/cmd_cbfs.c index 3b6cfd879b..f51534b07e 100644 --- a/common/cmd_cbfs.c +++ b/common/cmd_cbfs.c @@ -65,7 +65,6 @@ int do_cbfs_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) const struct cbfs_cachenode *file; unsigned long offset; unsigned long count; - char buf[12]; long size; if (argc < 3) { @@ -95,8 +94,7 @@ int do_cbfs_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) printf("\n%ld bytes read\n", size); - sprintf(buf, "%lX", size); - setenv("filesize", buf); + setenv_hex("filesize", size); return 0; } diff --git a/common/cmd_cramfs.c b/common/cmd_cramfs.c index e7f496e4ea..0e43ab67c0 100644 --- a/common/cmd_cramfs.c +++ b/common/cmd_cramfs.c @@ -146,11 +146,9 @@ int do_cramfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) size = cramfs_load ((char *) offset, &part, filename); if (size > 0) { - char buf[10]; printf("### CRAMFS load complete: %d bytes loaded to 0x%lx\n", size, offset); - sprintf(buf, "%x", size); - setenv("filesize", buf); + setenv_hex("filesize", size); } else { printf("### CRAMFS LOAD ERROR<%x> for %s!\n", size, filename); } diff --git a/common/cmd_fdos.c b/common/cmd_fdos.c index fbee8614ca..8ea1140e7f 100644 --- a/common/cmd_fdos.c +++ b/common/cmd_fdos.c @@ -40,7 +40,6 @@ int do_fdosboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) char *name; char *ep; int size; - char buf [12]; int drive = CONFIG_SYS_FDC_DRIVE_NUMBER; /* pre-set load_addr */ @@ -91,8 +90,7 @@ int do_fdosboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } flush_cache (load_addr, size); - sprintf(buf, "%x", size); - setenv("filesize", buf); + setenv_hex("filesize", size); printf("Floppy DOS load complete: %d bytes loaded to 0x%lx\n", size, load_addr); diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 27296ddd7d..4a4a0000b4 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -525,11 +525,9 @@ int do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } if (size > 0) { - char buf[10]; printf("### %s load complete: %d bytes loaded to 0x%lx\n", fsname, size, offset); - sprintf(buf, "%x", size); - setenv("filesize", buf); + setenv_hex("filesize", size); } else { printf("### %s LOAD ERROR<%x> for %s!\n", fsname, size, filename); } diff --git a/common/cmd_load.c b/common/cmd_load.c index 46db9626eb..0832e92b17 100644 --- a/common/cmd_load.c +++ b/common/cmd_load.c @@ -149,7 +149,6 @@ static ulong load_serial(long offset) int type; /* return code for record type */ ulong addr; /* load address from S-Record */ ulong size; /* number of bytes transferred */ - char buf[32]; ulong store_addr; ulong start_addr = ~0; ulong end_addr = 0; @@ -198,8 +197,7 @@ static ulong load_serial(long offset) start_addr, end_addr, size, size ); flush_cache(start_addr, size); - sprintf(buf, "%lX", size); - setenv("filesize", buf); + setenv_hex("filesize", size); return (addr); case SREC_START: break; @@ -519,7 +517,6 @@ static int do_load_serial_bin(cmd_tbl_t *cmdtp, int flag, int argc, static ulong load_serial_bin(ulong offset) { int size, i; - char buf[32]; set_kerm_bin_mode((ulong *) offset); size = k_recv(); @@ -539,8 +536,7 @@ static ulong load_serial_bin(ulong offset) flush_cache(offset, size); printf("## Total Size = 0x%08x = %d Bytes\n", size, size); - sprintf(buf, "%X", size); - setenv("filesize", buf); + setenv_hex("filesize", size); return offset; } @@ -965,7 +961,6 @@ static int getcxmodem(void) { static ulong load_serial_ymodem(ulong offset) { int size; - char buf[32]; int err; int res; connection_info_t info; @@ -1012,8 +1007,7 @@ static ulong load_serial_ymodem(ulong offset) flush_cache(offset, size); printf("## Total Size = 0x%08x = %d Bytes\n", size, size); - sprintf(buf, "%X", size); - setenv("filesize", buf); + setenv_hex("filesize", size); return offset; } diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c index 06fc171fe3..0cfca0c46b 100644 --- a/common/cmd_mtdparts.c +++ b/common/cmd_mtdparts.c @@ -230,7 +230,6 @@ static void memsize_format(char *buf, u32 size) */ static void index_partitions(void) { - char buf[16]; u16 mtddevnum; struct part_info *part; struct list_head *dentry; @@ -244,8 +243,7 @@ static void index_partitions(void) dev = list_entry(dentry, struct mtd_device, link); if (dev == current_mtd_dev) { mtddevnum += current_mtd_partnum; - sprintf(buf, "%d", mtddevnum); - setenv("mtddevnum", buf); + setenv_ulong("mtddevnum", mtddevnum); break; } mtddevnum += dev->num_parts; diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 495610c405..32348f3773 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -373,7 +373,6 @@ static void nand_print_and_set_info(int idx) { nand_info_t *nand = &nand_info[idx]; struct nand_chip *chip = nand->priv; - char buf[32]; printf("Device %d: ", idx); if (chip->numchips > 1) @@ -385,14 +384,9 @@ static void nand_print_and_set_info(int idx) printf(" Erase size %8d b\n", nand->erasesize); /* Set geometry info */ - sprintf(buf, "%x", nand->writesize); - setenv("nand_writesize", buf); - - sprintf(buf, "%x", nand->oobsize); - setenv("nand_oobsize", buf); - - sprintf(buf, "%x", nand->erasesize); - setenv("nand_erasesize", buf); + setenv_hex("nand_writesize", nand->writesize); + setenv_hex("nand_oobsize", nand->oobsize); + setenv_hex("nand_erasesize", nand->erasesize); } static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count, diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 44e88aa401..d646d90880 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -891,8 +891,7 @@ NXTARG: ; envp->flags = ACTIVE_FLAG; #endif } - sprintf(buf, "%zX", (size_t)(len + offsetof(env_t, data))); - setenv("filesize", buf); + setenv_hex("filesize", len + offsetof(env_t, data)); return 0; diff --git a/common/cmd_reiser.c b/common/cmd_reiser.c index e658618c6d..717c7f657b 100644 --- a/common/cmd_reiser.c +++ b/common/cmd_reiser.c @@ -100,7 +100,6 @@ int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong addr = 0, filelen; disk_partition_t info; block_dev_desc_t *dev_desc = NULL; - char buf [12]; unsigned long count; char *addr_str; @@ -175,8 +174,7 @@ int do_reiserload (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) load_addr = addr; printf ("\n%ld bytes read\n", filelen); - sprintf(buf, "%lX", filelen); - setenv("filesize", buf); + setenv_hex("filesize", filelen); return filelen; } diff --git a/common/cmd_setexpr.c b/common/cmd_setexpr.c index 5a042951da..7a38e94507 100644 --- a/common/cmd_setexpr.c +++ b/common/cmd_setexpr.c @@ -53,7 +53,7 @@ static ulong get_arg(char *s, int w) static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong a, b; - char buf[16]; + ulong value; int w; /* Validate arguments */ @@ -67,8 +67,7 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) a = get_arg(argv[2], w); if (argc == 3) { - sprintf(buf, "%lx", a); - setenv(argv[1], buf); + setenv_hex(argv[1], a); return 0; } @@ -76,20 +75,36 @@ static int do_setexpr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) b = get_arg(argv[4], w); switch (argv[3][0]) { - case '|': sprintf(buf, "%lx", (a | b)); break; - case '&': sprintf(buf, "%lx", (a & b)); break; - case '+': sprintf(buf, "%lx", (a + b)); break; - case '^': sprintf(buf, "%lx", (a ^ b)); break; - case '-': sprintf(buf, "%lx", (a - b)); break; - case '*': sprintf(buf, "%lx", (a * b)); break; - case '/': sprintf(buf, "%lx", (a / b)); break; - case '%': sprintf(buf, "%lx", (a % b)); break; + case '|': + value = a | b; + break; + case '&': + value = a & b; + break; + case '+': + value = a + b; + break; + case '^': + value = a ^ b; + break; + case '-': + value = a - b; + break; + case '*': + value = a * b; + break; + case '/': + value = a / b; + break; + case '%': + value = a % b; + break; default: printf("invalid op\n"); return 1; } - setenv(argv[1], buf); + setenv_hex(argv[1], value); return 0; } diff --git a/common/cmd_unzip.c b/common/cmd_unzip.c index 43ed7915fd..7470c2b12e 100644 --- a/common/cmd_unzip.c +++ b/common/cmd_unzip.c @@ -28,7 +28,6 @@ static int do_unzip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned long src, dst; unsigned long src_len = ~0UL, dst_len = ~0UL; - char buf[32]; switch (argc) { case 4: @@ -46,8 +45,7 @@ static int do_unzip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; printf("Uncompressed size: %ld = 0x%lX\n", src_len, src_len); - sprintf(buf, "%lX", src_len); - setenv("filesize", buf); + setenv_hex("filesize", src_len); return 0; } diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c index 42a7eba766..ea0a26e784 100644 --- a/common/cmd_ximg.c +++ b/common/cmd_ximg.c @@ -50,7 +50,6 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) ulong data, len, count; int verify; int part = 0; - char pbuf[10]; image_header_t *hdr; #if defined(CONFIG_FIT) const char *uname = NULL; @@ -256,10 +255,8 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) puts("OK\n"); } - sprintf(pbuf, "%8lx", data); - setenv("fileaddr", pbuf); - sprintf(pbuf, "%8lx", len); - setenv("filesize", pbuf); + setenv_hex("fileaddr", data); + setenv_hex("filesize", len); return 0; } diff --git a/common/cmd_zfs.c b/common/cmd_zfs.c index 1df0c4d72a..900e977c1c 100644 --- a/common/cmd_zfs.c +++ b/common/cmd_zfs.c @@ -129,8 +129,7 @@ static int do_zfs_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[] load_addr = addr; printf("%llu bytes read\n", zfile.size); - sprintf(buf, "%llX", zfile.size); - setenv("filesize", buf); + setenv_hex("filesize", zfile.size); return 0; } diff --git a/common/cmd_zip.c b/common/cmd_zip.c index a73c86d592..8607da81e2 100644 --- a/common/cmd_zip.c +++ b/common/cmd_zip.c @@ -28,7 +28,6 @@ static int do_zip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { unsigned long src, dst; unsigned long src_len, dst_len = ~0UL; - char buf[32]; switch (argc) { case 5: @@ -47,8 +46,7 @@ static int do_zip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; printf("Compressed size: %ld = 0x%lX\n", dst_len, dst_len); - sprintf(buf, "%lX", dst_len); - setenv("filesize", buf); + setenv_hex("filesize", dst_len); return 0; } -- cgit v1.2.3 From 49c4f0370ba917a2608e933ca541898e9c098397 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:23 +0000 Subject: fs: Use new numeric setenv functions Use setenv_ulong(), setenv_hex() and setenv_addr() in fs/ Signed-off-by: Simon Glass --- fs/fs.c | 4 +--- fs/ubifs/ubifs.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 023e7ef16a..2c9f2c5ac1 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -256,7 +256,6 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], unsigned long bytes; unsigned long pos; int len_read; - char buf[12]; unsigned long time; if (argc < 2) @@ -308,8 +307,7 @@ int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], } puts("\n"); - sprintf(buf, "0x%x", len_read); - setenv("filesize", buf); + setenv_hex("filesize", len_read); return 0; } diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c index 44be3f53e0..273c0a9638 100644 --- a/fs/ubifs/ubifs.c +++ b/fs/ubifs/ubifs.c @@ -687,7 +687,6 @@ int ubifs_load(char *filename, u32 addr, u32 size) int i; int count; int last_block_size = 0; - char buf [10]; c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); /* ubifs_findfile will resolve symlinks, so we know that we get @@ -740,8 +739,7 @@ int ubifs_load(char *filename, u32 addr, u32 size) if (err) printf("Error reading file '%s'\n", filename); else { - sprintf(buf, "%X", size); - setenv("filesize", buf); + setenv_hex("filesize", size); printf("Done\n"); } -- cgit v1.2.3 From 978226da5eb46bac23695d96a4ce8113b12640d5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:24 +0000 Subject: net: Use new numeric setenv functions Use setenv_ulong(), setenv_hex() and setenv_addr() in net/ Signed-off-by: Simon Glass --- drivers/net/fm/fm.c | 4 +--- net/net.c | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 49c74c278a..8d70586937 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -362,7 +362,6 @@ static void fm_init_qmi(struct fm_qmi_common *qmi) int fm_init_common(int index, struct ccsr_fman *reg) { int rc; - char env_addr[32]; #if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR) void *addr = (void *)CONFIG_SYS_QE_FMAN_FW_ADDR; #elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND) @@ -416,8 +415,7 @@ int fm_init_common(int index, struct ccsr_fman *reg) rc = fman_upload_firmware(index, ®->fm_imem, addr); if (rc) return rc; - sprintf(env_addr, "0x%lx", (long unsigned int)addr); - setenv("fman_ucode", env_addr); + setenv_addr("fman_ucode", addr); fm_init_muram(index, ®->muram); fm_init_qmi(®->fm_qmi_common); diff --git a/net/net.c b/net/net.c index a40cde1e94..df94789de9 100644 --- a/net/net.c +++ b/net/net.c @@ -528,15 +528,11 @@ restart: case NETLOOP_SUCCESS: net_cleanup_loop(); if (NetBootFileXferSize > 0) { - char buf[20]; printf("Bytes transferred = %ld (%lx hex)\n", NetBootFileXferSize, NetBootFileXferSize); - sprintf(buf, "%lX", NetBootFileXferSize); - setenv("filesize", buf); - - sprintf(buf, "%lX", (unsigned long)load_addr); - setenv("fileaddr", buf); + setenv_hex("filesize", NetBootFileXferSize); + setenv_hex("fileaddr", load_addr); } if (protocol != NETCONS) eth_halt(); -- cgit v1.2.3 From 0ccff500cf787bb71e514eb2904d773ec84bf11d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:25 +0000 Subject: image: Use crc header file instead of C prototypes We have an existing header which the crc32 definitions, so use it. Signed-off-by: Simon Glass --- common/image.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/image.c b/common/image.c index ae1a9d3bd1..6afbb40a98 100644 --- a/common/image.c +++ b/common/image.c @@ -74,6 +74,8 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, #include #endif /* !USE_HOSTCC*/ +#include + static const table_entry_t uimage_arch[] = { { IH_ARCH_INVALID, NULL, "Invalid ARCH", }, { IH_ARCH_ALPHA, "alpha", "Alpha", }, @@ -160,8 +162,6 @@ static const table_entry_t uimage_comp[] = { { -1, "", "", }, }; -uint32_t crc32(uint32_t, const unsigned char *, uint); -uint32_t crc32_wd(uint32_t, const unsigned char *, uint, uint); #if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC) static void genimg_print_time(time_t timestamp); #endif -- cgit v1.2.3 From d5b76673a5dfe0b5250baea3c36cdfa7a9fd5230 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:26 +0000 Subject: hash: Add a flag to support saving hashes in the environment Some hashing commands permit saving the hash in an environment variable, and verifying a hash from there. But the crc32 command does not support this. In order to permit crc32 to use the generic hashing infrastructure, add a flag to select which behaviour to use. Signed-off-by: Simon Glass --- common/cmd_hash.c | 8 +++--- common/cmd_sha1sum.c | 6 ++--- common/hash.c | 69 +++++++++++++++++++++++++++++++++++++++------------- include/hash.h | 9 +++++-- 4 files changed, 66 insertions(+), 26 deletions(-) diff --git a/common/cmd_hash.c b/common/cmd_hash.c index eb6a33873b..8c03b5c723 100644 --- a/common/cmd_hash.c +++ b/common/cmd_hash.c @@ -30,22 +30,22 @@ static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { #ifdef CONFIG_HASH_VERIFY - int verify = 0; + int flags = HASH_FLAG_ENV; if (argc < 4) return CMD_RET_USAGE; if (!strcmp(argv[1], "-v")) { - verify = 1; + flags |= HASH_FLAG_VERIFY; argc--; argv++; } #else - const int verify = 0; + const int flags = HASH_FLAG_ENV; #endif /* Move forward to 'algorithm' parameter */ argc--; argv++; - return hash_command(*argv, verify, cmdtp, flag, argc - 1, argv + 1); + return hash_command(*argv, flags, cmdtp, flag, argc - 1, argv + 1); } #ifdef CONFIG_HASH_VERIFY diff --git a/common/cmd_sha1sum.c b/common/cmd_sha1sum.c index fe927ab248..9f08629b87 100644 --- a/common/cmd_sha1sum.c +++ b/common/cmd_sha1sum.c @@ -31,7 +31,7 @@ int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - int verify = 0; + int flags = HASH_FLAG_ENV; int ac; char * const *av; @@ -42,13 +42,13 @@ int do_sha1sum(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ac = argc - 1; #ifdef CONFIG_SHA1SUM_VERIFY if (strcmp(*av, "-v") == 0) { - verify = 1; + flags |= HASH_FLAG_VERIFY; av++; ac--; } #endif - return hash_command("sha1", verify, cmdtp, flag, ac, av); + return hash_command("sha1", flags, cmdtp, flag, ac, av); } #ifdef CONFIG_SHA1SUM_VERIFY diff --git a/common/hash.c b/common/hash.c index e3a6e438a3..462853d172 100644 --- a/common/hash.c +++ b/common/hash.c @@ -58,19 +58,31 @@ static struct hash_algo hash_algo[] = { * @algo: Hash algorithm being used * @sum: Hash digest (algo->digest_size bytes) * @dest: Destination, interpreted as a hex address if it starts - * with * or otherwise as an environment variable. + * with * (or allow_env_vars is 0) or otherwise as an + * environment variable. + * @allow_env_vars: non-zero to permit storing the result to an + * variable environment */ static void store_result(struct hash_algo *algo, const u8 *sum, - const char *dest) + const char *dest, int allow_env_vars) { unsigned int i; + int env_var = 0; - if (*dest == '*') { - u8 *ptr; + /* + * If environment variables are allowed, then we assume that 'dest' + * is an environment variable, unless it starts with *, in which + * case we assume it is an address. If not allowed, it is always an + * address. This is to support the crc32 command. + */ + if (allow_env_vars) { + if (*dest == '*') + dest++; + else + env_var = 1; + } - ptr = (u8 *)simple_strtoul(dest + 1, NULL, 16); - memcpy(ptr, sum, algo->digest_size); - } else { + if (env_var) { char str_output[HASH_MAX_DIGEST_SIZE * 2 + 1]; char *str_ptr = str_output; @@ -80,6 +92,11 @@ static void store_result(struct hash_algo *algo, const u8 *sum, } str_ptr = '\0'; setenv(dest, str_output); + } else { + u8 *ptr; + + ptr = (u8 *)simple_strtoul(dest, NULL, 16); + memcpy(ptr, sum, algo->digest_size); } } @@ -94,14 +111,28 @@ static void store_result(struct hash_algo *algo, const u8 *sum, * Otherwise we assume it is an environment variable, and * look up its value (it must contain a hex digest). * @vsum: Returns binary digest value (algo->digest_size bytes) + * @allow_env_vars: non-zero to permit storing the result to an environment + * variable. If 0 then verify_str is assumed to be an + * address, and the * prefix is not expected. * @return 0 if ok, non-zero on error */ -static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum) +static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum, + int allow_env_vars) { - if (*verify_str == '*') { + int env_var = 0; + + /* See comment above in store_result() */ + if (allow_env_vars) { + if (*verify_str == '*') + verify_str++; + else + env_var = 1; + } + + if (env_var) { u8 *ptr; - ptr = (u8 *)simple_strtoul(verify_str + 1, NULL, 16); + ptr = (u8 *)simple_strtoul(verify_str, NULL, 16); memcpy(vsum, ptr, algo->digest_size); } else { unsigned int i; @@ -158,7 +189,7 @@ static void show_hash(struct hash_algo *algo, ulong addr, ulong len, printf("%02x", output[i]); } -int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, +int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct hash_algo *algo; @@ -169,13 +200,14 @@ int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, if (argc < 2) return CMD_RET_USAGE; + addr = simple_strtoul(*argv++, NULL, 16); + len = simple_strtoul(*argv++, NULL, 16); + algo = find_hash_algo(algo_name); if (!algo) { printf("Unknown hash algorithm '%s'\n", algo_name); return CMD_RET_USAGE; } - addr = simple_strtoul(*argv++, NULL, 16); - len = simple_strtoul(*argv++, NULL, 16); argc -= 2; if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { @@ -188,13 +220,14 @@ int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, /* Try to avoid code bloat when verify is not needed */ #ifdef CONFIG_HASH_VERIFY - if (verify) { + if (flags & HASH_FLAG_VERIFY) { #else if (0) { #endif if (!argc) return CMD_RET_USAGE; - if (parse_verify_sum(algo, *argv, vsum)) { + if (parse_verify_sum(algo, *argv, vsum, + flags & HASH_FLAG_ENV)) { printf("ERROR: %s does not contain a valid %s sum\n", *argv, algo->name); return 1; @@ -213,8 +246,10 @@ int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, show_hash(algo, addr, len, output); printf("\n"); - if (argc) - store_result(algo, output, *argv); + if (argc) { + store_result(algo, output, *argv, + flags & HASH_FLAG_ENV); + } } return 0; diff --git a/include/hash.h b/include/hash.h index 34ba558bd0..88fa2b5a57 100644 --- a/include/hash.h +++ b/include/hash.h @@ -51,19 +51,24 @@ struct hash_algo { */ #define HASH_MAX_DIGEST_SIZE 32 +enum { + HASH_FLAG_VERIFY = 1 << 0, /* Enable verify mode */ + HASH_FLAG_ENV = 1 << 1, /* Allow env vars */ +}; + /** * hash_command: Process a hash command for a particular algorithm * * This common function is used to implement specific hash commands. * * @algo_name: Hash algorithm being used - * @verify: Non-zero to enable verify mode + * @flags: Flags value (HASH_FLAG_...) * @cmdtp: Pointer to command table entry * @flag: Some flags normally 0 (see CMD_FLAG_.. above) * @argc: Number of arguments (arg 0 must be the command text) * @argv: Arguments */ -int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, +int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); #endif -- cgit v1.2.3 From d20a40de9db07de1f1f06a79a4da1cdda5379b75 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 20:30:22 +0000 Subject: Roll crc32 into hash infrastructure Add the CRC32 algorithm to the list of available hashes, and make the crc32 command use hash_command(). Add a new crc32_wd_buf() to make this possible, which puts its result in a buffer rather than returning it as a 32-bit value. Note: For some boards the hash command is not enabled, neither are sha1, sha256 or the verify option. In this case the full hash implementation adds about 500 bytes of overhead. So as a special case, we use #ifdef to select very simple bahaviour in that case. The justification for this is that it is currently a very common case (virtually all boards enable crc32 but only some enable more advanced features). Signed-off-by: Simon Glass --- common/cmd_mem.c | 75 +++----------------------------- common/hash.c | 118 ++++++++++++++++++++++++++++++++++----------------- include/hash.h | 2 +- include/u-boot/crc.h | 11 +++++ lib/crc32.c | 9 ++++ 5 files changed, 108 insertions(+), 107 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 12dbc1609c..95b49b2100 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -32,6 +32,7 @@ #ifdef CONFIG_HAS_DATAFLASH #include #endif +#include #include #include #include @@ -1098,89 +1099,27 @@ mod_mem(cmd_tbl_t *cmdtp, int incrflag, int flag, int argc, char * const argv[]) #ifdef CONFIG_CMD_CRC32 -#ifndef CONFIG_CRC32_VERIFY - static int do_mem_crc(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - ulong addr, length; - ulong crc; - ulong *ptr; - - if (argc < 3) - return CMD_RET_USAGE; - - addr = simple_strtoul (argv[1], NULL, 16); - addr += base_address; - - length = simple_strtoul (argv[2], NULL, 16); - - crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32); - - printf ("CRC32 for %08lx ... %08lx ==> %08lx\n", - addr, addr + length - 1, crc); - - if (argc > 3) { - ptr = (ulong *) simple_strtoul (argv[3], NULL, 16); - *ptr = crc; - } - - return 0; -} - -#else /* CONFIG_CRC32_VERIFY */ - -int do_mem_crc (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - ulong addr, length; - ulong crc; - ulong *ptr; - ulong vcrc; - int verify; + int flags = 0; int ac; char * const *av; - if (argc < 3) { -usage: + if (argc < 3) return CMD_RET_USAGE; - } av = argv + 1; ac = argc - 1; +#ifdef CONFIG_HASH_VERIFY if (strcmp(*av, "-v") == 0) { - verify = 1; + flags |= HASH_FLAG_VERIFY; av++; ac--; - if (ac < 3) - goto usage; - } else - verify = 0; - - addr = simple_strtoul(*av++, NULL, 16); - addr += base_address; - length = simple_strtoul(*av++, NULL, 16); - - crc = crc32_wd (0, (const uchar *) addr, length, CHUNKSZ_CRC32); - - if (!verify) { - printf ("CRC32 for %08lx ... %08lx ==> %08lx\n", - addr, addr + length - 1, crc); - if (ac > 2) { - ptr = (ulong *) simple_strtoul (*av++, NULL, 16); - *ptr = crc; - } - } else { - vcrc = simple_strtoul(*av++, NULL, 16); - if (vcrc != crc) { - printf ("CRC32 for %08lx ... %08lx ==> %08lx != %08lx ** ERROR **\n", - addr, addr + length - 1, crc, vcrc); - return 1; - } } +#endif - return 0; - + return hash_command("crc32", flags, cmdtp, flag, ac, av); } -#endif /* CONFIG_CRC32_VERIFY */ #endif diff --git a/common/hash.c b/common/hash.c index 462853d172..ef6fe375d2 100644 --- a/common/hash.c +++ b/common/hash.c @@ -34,13 +34,19 @@ * crypto could perhaps add named version of these algorithms here. */ static struct hash_algo hash_algo[] = { -#ifdef CONFIG_SHA1 + /* + * This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since otherwise + * it bloats the code for boards which use SHA1 but not the 'hash' + * or 'sha1sum' commands. + */ +#ifdef CONFIG_CMD_SHA1SUM { "SHA1", SHA1_SUM_LEN, sha1_csum_wd, CHUNKSZ_SHA1, }, +#define MULTI_HASH #endif #ifdef CONFIG_SHA256 { @@ -49,9 +55,27 @@ static struct hash_algo hash_algo[] = { sha256_csum_wd, CHUNKSZ_SHA256, }, +#define MULTI_HASH #endif + { + "CRC32", + 4, + crc32_wd_buf, + CHUNKSZ_CRC32, + }, }; +#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH) +#define MULTI_HASH +#endif + +/* Try to minimize code size for boards that don't want much hashing */ +#ifdef MULTI_HASH +#define multi_hash() 1 +#else +#define multi_hash() 0 +#endif + /** * store_result: Store the resulting sum to an address or variable * @@ -192,10 +216,7 @@ static void show_hash(struct hash_algo *algo, ulong addr, ulong len, int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct hash_algo *algo; ulong addr, len; - u8 output[HASH_MAX_DIGEST_SIZE]; - u8 vsum[HASH_MAX_DIGEST_SIZE]; if (argc < 2) return CMD_RET_USAGE; @@ -203,52 +224,73 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, addr = simple_strtoul(*argv++, NULL, 16); len = simple_strtoul(*argv++, NULL, 16); - algo = find_hash_algo(algo_name); - if (!algo) { - printf("Unknown hash algorithm '%s'\n", algo_name); - return CMD_RET_USAGE; - } - argc -= 2; + if (multi_hash()) { + struct hash_algo *algo; + u8 output[HASH_MAX_DIGEST_SIZE]; + u8 vsum[HASH_MAX_DIGEST_SIZE]; - if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { - puts("HASH_MAX_DIGEST_SIZE exceeded\n"); - return 1; - } + algo = find_hash_algo(algo_name); + if (!algo) { + printf("Unknown hash algorithm '%s'\n", algo_name); + return CMD_RET_USAGE; + } + argc -= 2; + + if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { + puts("HASH_MAX_DIGEST_SIZE exceeded\n"); + return 1; + } - algo->hash_func_ws((const unsigned char *)addr, len, output, - algo->chunk_size); + algo->hash_func_ws((const unsigned char *)addr, len, output, + algo->chunk_size); - /* Try to avoid code bloat when verify is not needed */ + /* Try to avoid code bloat when verify is not needed */ #ifdef CONFIG_HASH_VERIFY - if (flags & HASH_FLAG_VERIFY) { + if (flags & HASH_FLAG_VERIFY) { #else - if (0) { + if (0) { #endif - if (!argc) - return CMD_RET_USAGE; - if (parse_verify_sum(algo, *argv, vsum, + if (!argc) + return CMD_RET_USAGE; + if (parse_verify_sum(algo, *argv, vsum, flags & HASH_FLAG_ENV)) { - printf("ERROR: %s does not contain a valid %s sum\n", - *argv, algo->name); - return 1; - } - if (memcmp(output, vsum, algo->digest_size) != 0) { - int i; + printf("ERROR: %s does not contain a valid " + "%s sum\n", *argv, algo->name); + return 1; + } + if (memcmp(output, vsum, algo->digest_size) != 0) { + int i; + show_hash(algo, addr, len, output); + printf(" != "); + for (i = 0; i < algo->digest_size; i++) + printf("%02x", vsum[i]); + puts(" ** ERROR **\n"); + return 1; + } + } else { show_hash(algo, addr, len, output); - printf(" != "); - for (i = 0; i < algo->digest_size; i++) - printf("%02x", vsum[i]); - puts(" ** ERROR **\n"); - return 1; + printf("\n"); + + if (argc) { + store_result(algo, output, *argv, + flags & HASH_FLAG_ENV); + } } + + /* Horrible code size hack for boards that just want crc32 */ } else { - show_hash(algo, addr, len, output); - printf("\n"); + ulong crc; + ulong *ptr; + + crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32); + + printf("CRC32 for %08lx ... %08lx ==> %08lx\n", + addr, addr + len - 1, crc); - if (argc) { - store_result(algo, output, *argv, - flags & HASH_FLAG_ENV); + if (argc > 3) { + ptr = (ulong *)simple_strtoul(argv[3], NULL, 16); + *ptr = crc; } } diff --git a/include/hash.h b/include/hash.h index 88fa2b5a57..f2b2c4520d 100644 --- a/include/hash.h +++ b/include/hash.h @@ -22,7 +22,7 @@ #ifndef _HASH_H #define _HASH_H -#ifdef CONFIG_SHA1SUM_VERIFY +#if defined(CONFIG_SHA1SUM_VERIFY) || defined(CONFIG_CRC32_VERIFY) #define CONFIG_HASH_VERIFY #endif diff --git a/include/u-boot/crc.h b/include/u-boot/crc.h index 07badbfc5a..08e509edb4 100644 --- a/include/u-boot/crc.h +++ b/include/u-boot/crc.h @@ -30,4 +30,15 @@ uint32_t crc32 (uint32_t, const unsigned char *, uint); uint32_t crc32_wd (uint32_t, const unsigned char *, uint, uint); uint32_t crc32_no_comp (uint32_t, const unsigned char *, uint); +/** + * crc32_wd_buf - Perform CRC32 on a buffer and return result in buffer + * + * @input: Input buffer + * @ilen: Input buffer length + * @output: Place to put checksum result (4 bytes) + * @chunk_sz: Trigger watchdog after processing this many bytes + */ +void crc32_wd_buf(const unsigned char *input, uint ilen, + unsigned char *output, uint chunk_sz); + #endif /* _UBOOT_CRC_H */ diff --git a/lib/crc32.c b/lib/crc32.c index 27335a3ed9..76205da4f3 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -249,3 +249,12 @@ uint32_t ZEXPORT crc32_wd (uint32_t crc, return crc; } + +void crc32_wd_buf(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + uint32_t crc; + + crc = crc32_wd(0, input, ilen, chunk_sz); + memcpy(output, &crc, sizeof(crc)); +} -- cgit v1.2.3 From ecdbf419f9c979cb6417df261c324c5beb63300d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 20:29:23 +0000 Subject: sandbox: config: Enable hash functions and mtest Enable the hash command and sha1/256 hashing for sandbox. Also use a better address for memory testing (since the existing one is set up for linux host memory space). Signed-off-by: Simon Glass --- include/configs/sandbox.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 9c431bf27a..9f51a0b813 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -63,8 +63,8 @@ #define CONFIG_SYS_HZ 1000 /* Memory things - we don't really want a memory test */ -#define CONFIG_SYS_LOAD_ADDR 0x10000000 -#define CONFIG_SYS_MEMTEST_START 0x10000000 +#define CONFIG_SYS_LOAD_ADDR 0x00000000 +#define CONFIG_SYS_MEMTEST_START 0x00100000 #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_MEMTEST_START + 0x1000) #define CONFIG_PHYS_64BIT @@ -85,6 +85,11 @@ #undef CONFIG_CMD_NET #undef CONFIG_CMD_NFS +#define CONFIG_CMD_HASH +#define CONFIG_HASH_VERIFY +#define CONFIG_SHA1 +#define CONFIG_SHA256 + #define CONFIG_BOOTARGS "" #define CONFIG_EXTRA_ENV_SETTINGS "stdin=serial\0" \ -- cgit v1.2.3 From 8e169cc943fcf93dd803adc70433b2c587db8796 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:29 +0000 Subject: Move CONFIG_SYS_MEMTEST_SCRATCH #ifdef to top of file This config effectively has a default value of 0, so add this setting at the top of the code to remove an #ifdef in the C function. Signed-off-by: Simon Glass --- common/cmd_mem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 95b49b2100..50838a7614 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -39,6 +39,10 @@ DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_SYS_MEMTEST_SCRATCH +#define CONFIG_SYS_MEMTEST_SCRATCH 0 +#endif + static int mod_mem(cmd_tbl_t *, int, int, int, char * const []); /* Display values from last command. @@ -641,11 +645,7 @@ static ulong mem_test_alt(ulong start_addr, ulong end_addr) vu_long temp; vu_long anti_pattern; vu_long num_words; -#if defined(CONFIG_SYS_MEMTEST_SCRATCH) vu_long *dummy = (vu_long *)CONFIG_SYS_MEMTEST_SCRATCH; -#else - vu_long *dummy = NULL; /* yes, this is address 0x0, not NULL */ -#endif static const ulong bitpattern[] = { 0x00000001, /* single bit */ 0x00000003, /* two adjacent bits */ -- cgit v1.2.3 From 5512d5b034d3f199f16f7c18171cae7732bb05eb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 17:47:14 +0000 Subject: sandbox: Update mtest to fix crashes Use map_sysmem() in the memory tester so that it works as expected on sandbox. Signed-off-by: Simon Glass --- common/cmd_mem.c | 108 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/common/cmd_mem.c b/common/cmd_mem.c index 50838a7614..042c994a1b 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -631,21 +631,19 @@ int do_mem_loopw (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } #endif /* CONFIG_LOOPW */ -static ulong mem_test_alt(ulong start_addr, ulong end_addr) +static ulong mem_test_alt(vu_long *buf, ulong start_addr, ulong end_addr, + vu_long *dummy) { - vu_long *start, *end; vu_long *addr; ulong errs = 0; ulong val, readback; int j; - vu_long len; vu_long offset; vu_long test_offset; vu_long pattern; vu_long temp; vu_long anti_pattern; vu_long num_words; - vu_long *dummy = (vu_long *)CONFIG_SYS_MEMTEST_SCRATCH; static const ulong bitpattern[] = { 0x00000001, /* single bit */ 0x00000003, /* two adjacent bits */ @@ -657,8 +655,7 @@ static ulong mem_test_alt(ulong start_addr, ulong end_addr) 0xaaaaaaaa, /* alternating 1/0 */ }; - start = (vu_long *)start_addr; - end = (vu_long *)end_addr; + num_words = (end_addr - start_addr) / sizeof(vu_long); /* * Data line test: write a pattern to the first @@ -677,11 +674,11 @@ static ulong mem_test_alt(ulong start_addr, ulong end_addr) * '0's and '0' bits through a field of '1's (i.e. * pattern and ~pattern). */ - addr = start; + addr = buf; for (j = 0; j < sizeof(bitpattern) / sizeof(bitpattern[0]); j++) { val = bitpattern[j]; for (; val != 0; val <<= 1) { - *addr = val; + *addr = val; *dummy = ~val; /* clear the test data off the bus */ readback = *addr; if (readback != val) { @@ -740,58 +737,56 @@ static ulong mem_test_alt(ulong start_addr, ulong end_addr) * * Returns: 0 if the test succeeds, 1 if the test fails. */ - len = (end_addr - start_addr) / sizeof(vu_long); pattern = (vu_long) 0xaaaaaaaa; anti_pattern = (vu_long) 0x55555555; - debug("%s:%d: length = 0x%.8lx\n", - __func__, __LINE__, len); + debug("%s:%d: length = 0x%.8lx\n", __func__, __LINE__, num_words); /* * Write the default pattern at each of the * power-of-two offsets. */ - for (offset = 1; offset < len; offset <<= 1) - start[offset] = pattern; + for (offset = 1; offset < num_words; offset <<= 1) + addr[offset] = pattern; /* * Check for address bits stuck high. */ test_offset = 0; - start[test_offset] = anti_pattern; + addr[test_offset] = anti_pattern; - for (offset = 1; offset < len; offset <<= 1) { - temp = start[offset]; + for (offset = 1; offset < num_words; offset <<= 1) { + temp = addr[offset]; if (temp != pattern) { printf("\nFAILURE: Address bit stuck high @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx\n", - (ulong)&start[offset], pattern, temp); + start_addr + offset, pattern, temp); errs++; if (ctrlc()) return -1; } } - start[test_offset] = pattern; + addr[test_offset] = pattern; WATCHDOG_RESET(); /* * Check for addr bits stuck low or shorted. */ - for (test_offset = 1; test_offset < len; test_offset <<= 1) { - start[test_offset] = anti_pattern; + for (test_offset = 1; test_offset < num_words; test_offset <<= 1) { + addr[test_offset] = anti_pattern; - for (offset = 1; offset < len; offset <<= 1) { - temp = start[offset]; + for (offset = 1; offset < num_words; offset <<= 1) { + temp = addr[offset]; if ((temp != pattern) && (offset != test_offset)) { printf("\nFAILURE: Address bit stuck low or" " shorted @ 0x%.8lx: expected 0x%.8lx," " actual 0x%.8lx\n", - (ulong)&start[offset], pattern, temp); + start_addr + offset, pattern, temp); errs++; if (ctrlc()) return -1; } } - start[test_offset] = pattern; + addr[test_offset] = pattern; } /* @@ -806,14 +801,14 @@ static ulong mem_test_alt(ulong start_addr, ulong end_addr) * * Returns: 0 if the test succeeds, 1 if the test fails. */ - num_words = ((ulong)end - (ulong)start)/sizeof(vu_long) + 1; + num_words++; /* * Fill memory with a known pattern. */ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { WATCHDOG_RESET(); - start[offset] = pattern; + addr[offset] = pattern; } /* @@ -821,18 +816,18 @@ static ulong mem_test_alt(ulong start_addr, ulong end_addr) */ for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { WATCHDOG_RESET(); - temp = start[offset]; + temp = addr[offset]; if (temp != pattern) { printf("\nFAILURE (read/write) @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx)\n", - (ulong)&start[offset], pattern, temp); + start_addr + offset, pattern, temp); errs++; if (ctrlc()) return -1; } anti_pattern = ~pattern; - start[offset] = anti_pattern; + addr[offset] = anti_pattern; } /* @@ -841,28 +836,28 @@ static ulong mem_test_alt(ulong start_addr, ulong end_addr) for (pattern = 1, offset = 0; offset < num_words; pattern++, offset++) { WATCHDOG_RESET(); anti_pattern = ~pattern; - temp = start[offset]; + temp = addr[offset]; if (temp != anti_pattern) { printf("\nFAILURE (read/write): @ 0x%.8lx:" " expected 0x%.8lx, actual 0x%.8lx)\n", - (ulong)&start[offset], anti_pattern, temp); + start_addr + offset, anti_pattern, temp); errs++; if (ctrlc()) return -1; } - start[offset] = 0; + addr[offset] = 0; } return 0; } -static ulong mem_test_quick(ulong start_addr, ulong end_addr, vu_long pattern, - int iteration) +static ulong mem_test_quick(vu_long *buf, ulong start_addr, ulong end_addr, + vu_long pattern, int iteration) { - vu_long *start, *end; + vu_long *end; vu_long *addr; ulong errs = 0; - ulong incr; + ulong incr, length; ulong val, readback; /* Alternate the pattern */ @@ -880,14 +875,14 @@ static ulong mem_test_quick(ulong start_addr, ulong end_addr, vu_long pattern, else pattern = ~pattern; } - start = (vu_long *)start_addr; - end = (vu_long *)end_addr; + length = (end_addr - start_addr) / sizeof(ulong); + end = buf + length; printf("\rPattern %08lX Writing..." "%12s" "\b\b\b\b\b\b\b\b\b\b", pattern, ""); - for (addr = start, val = pattern; addr < end; addr++) { + for (addr = buf, val = pattern; addr < end; addr++) { WATCHDOG_RESET(); *addr = val; val += incr; @@ -895,13 +890,16 @@ static ulong mem_test_quick(ulong start_addr, ulong end_addr, vu_long pattern, puts("Reading..."); - for (addr = start, val = pattern; addr < end; addr++) { + for (addr = buf, val = pattern; addr < end; addr++) { WATCHDOG_RESET(); readback = *addr; if (readback != val) { + ulong offset = addr - buf; + printf("\nMem error @ 0x%08X: " "found %08lX, expected %08lX\n", - (uint)(uintptr_t)addr, readback, val); + (uint)(uintptr_t)(start_addr + offset), + readback, val); errs++; if (ctrlc()) return -1; @@ -921,6 +919,7 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong start, end; + vu_long *buf, *dummy; int iteration_limit; int ret; ulong errs = 0; /* number of errors, or -1 if interrupted */ @@ -956,6 +955,8 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, debug("%s:%d: start %#08lx end %#08lx\n", __func__, __LINE__, start, end); + buf = map_sysmem(start, end - start); + dummy = map_sysmem(CONFIG_SYS_MEMTEST_SCRATCH, sizeof(vu_long)); for (iteration = 0; !iteration_limit || iteration < iteration_limit; iteration++) { @@ -966,10 +967,27 @@ static int do_mem_mtest(cmd_tbl_t *cmdtp, int flag, int argc, printf("Iteration: %6d\r", iteration + 1); debug("\n"); - if (alt_test) - errs = mem_test_alt(start, end); - else - errs = mem_test_quick(start, end, pattern, iteration); + if (alt_test) { + errs = mem_test_alt(buf, start, end, dummy); + } else { + errs = mem_test_quick(buf, start, end, pattern, + iteration); + } + if (errs == -1UL) + break; + } + + /* + * Work-around for eldk-4.2 which gives this warning if we try to + * case in the unmap_sysmem() call: + * warning: initialization discards qualifiers from pointer target type + */ + { + void *vbuf = (void *)buf; + void *vdummy = (void *)dummy; + + unmap_sysmem(vbuf); + unmap_sysmem(vdummy); } if (errs == -1UL) { -- cgit v1.2.3 From bd091b67d0ef2959ed0ff2aa6575ddb0d21c1f71 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:31 +0000 Subject: sandbox: Allow hash functions to work correctly Use map_sysmem() so that hashing is possible on sandbox. Signed-off-by: Simon Glass --- common/hash.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/common/hash.c b/common/hash.c index ef6fe375d2..0d04c4c9a0 100644 --- a/common/hash.c +++ b/common/hash.c @@ -28,6 +28,7 @@ #include #include #include +#include /* * These are the hash algorithms we support. Chips which support accelerated @@ -117,10 +118,13 @@ static void store_result(struct hash_algo *algo, const u8 *sum, str_ptr = '\0'; setenv(dest, str_output); } else { - u8 *ptr; + ulong addr; + void *buf; - ptr = (u8 *)simple_strtoul(dest, NULL, 16); - memcpy(ptr, sum, algo->digest_size); + addr = simple_strtoul(dest, NULL, 16); + buf = map_sysmem(addr, algo->digest_size); + memcpy(buf, sum, algo->digest_size); + unmap_sysmem(buf); } } @@ -154,10 +158,12 @@ static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum, } if (env_var) { - u8 *ptr; + ulong addr; + void *buf; - ptr = (u8 *)simple_strtoul(verify_str, NULL, 16); - memcpy(vsum, ptr, algo->digest_size); + addr = simple_strtoul(verify_str, NULL, 16); + buf = map_sysmem(addr, algo->digest_size); + memcpy(vsum, buf, algo->digest_size); } else { unsigned int i; char *vsum_str; @@ -228,6 +234,7 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, struct hash_algo *algo; u8 output[HASH_MAX_DIGEST_SIZE]; u8 vsum[HASH_MAX_DIGEST_SIZE]; + void *buf; algo = find_hash_algo(algo_name); if (!algo) { @@ -241,8 +248,9 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, return 1; } - algo->hash_func_ws((const unsigned char *)addr, len, output, - algo->chunk_size); + buf = map_sysmem(addr, len); + algo->hash_func_ws(buf, len, output, algo->chunk_size); + unmap_sysmem(buf); /* Try to avoid code bloat when verify is not needed */ #ifdef CONFIG_HASH_VERIFY -- cgit v1.2.3 From 218da0f35f4b5e5bf13d3dba6d975d4d5d65516f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 24 Feb 2013 17:33:32 +0000 Subject: hash: Use lower case for hash algorithm names Rather than use strcasecmp() in the hash algorithm search, require the caller to do this first. Most of U-Boot can use lower case anyway, and the hash command can convert to lower case before calling hash_command(). This saves needing strcasecmp() for boards that use hashing but not the hash command. Signed-off-by: Simon Glass --- common/cmd_hash.c | 4 ++++ common/hash.c | 11 ++++++----- include/hash.h | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/common/cmd_hash.c b/common/cmd_hash.c index 8c03b5c723..4fe0e78613 100644 --- a/common/cmd_hash.c +++ b/common/cmd_hash.c @@ -26,9 +26,11 @@ #include #include #include +#include static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + char *s; #ifdef CONFIG_HASH_VERIFY int flags = HASH_FLAG_ENV; @@ -45,6 +47,8 @@ static int do_hash(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* Move forward to 'algorithm' parameter */ argc--; argv++; + for (s = *argv; *s; s++) + *s = tolower(*s); return hash_command(*argv, flags, cmdtp, flag, argc - 1, argv + 1); } diff --git a/common/hash.c b/common/hash.c index 0d04c4c9a0..f5badcb930 100644 --- a/common/hash.c +++ b/common/hash.c @@ -32,7 +32,8 @@ /* * These are the hash algorithms we support. Chips which support accelerated - * crypto could perhaps add named version of these algorithms here. + * crypto could perhaps add named version of these algorithms here. Note that + * algorithm names must be in lower case. */ static struct hash_algo hash_algo[] = { /* @@ -42,7 +43,7 @@ static struct hash_algo hash_algo[] = { */ #ifdef CONFIG_CMD_SHA1SUM { - "SHA1", + "sha1", SHA1_SUM_LEN, sha1_csum_wd, CHUNKSZ_SHA1, @@ -51,7 +52,7 @@ static struct hash_algo hash_algo[] = { #endif #ifdef CONFIG_SHA256 { - "SHA256", + "sha256", SHA256_SUM_LEN, sha256_csum_wd, CHUNKSZ_SHA256, @@ -59,7 +60,7 @@ static struct hash_algo hash_algo[] = { #define MULTI_HASH #endif { - "CRC32", + "crc32", 4, crc32_wd_buf, CHUNKSZ_CRC32, @@ -202,7 +203,7 @@ static struct hash_algo *find_hash_algo(const char *name) int i; for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { - if (!strcasecmp(name, hash_algo[i].name)) + if (!strcmp(name, hash_algo[i].name)) return &hash_algo[i]; } diff --git a/include/hash.h b/include/hash.h index f2b2c4520d..2dbbd9b7d5 100644 --- a/include/hash.h +++ b/include/hash.h @@ -61,7 +61,7 @@ enum { * * This common function is used to implement specific hash commands. * - * @algo_name: Hash algorithm being used + * @algo_name: Hash algorithm being used (lower case!) * @flags: Flags value (HASH_FLAG_...) * @cmdtp: Pointer to command table entry * @flag: Some flags normally 0 (see CMD_FLAG_.. above) -- cgit v1.2.3 From 3e1b393976ba59045e477fdea0beb69bd29b9102 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Sat, 23 Feb 2013 00:53:25 +0000 Subject: Add README for the "Falcon" mode Simple howto to add support to a board for booting the kernel from SPL ("Falcon" mode). Signed-off-by: Stefano Babic Reviewed-by: Tom Rini --- doc/README.falcon | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 doc/README.falcon diff --git a/doc/README.falcon b/doc/README.falcon new file mode 100644 index 0000000000..93e855d20e --- /dev/null +++ b/doc/README.falcon @@ -0,0 +1,209 @@ +U-Boot Falcon Mode +==================== + +Introduction +------------ + +This document provides an overview of how to add support for Falcon Mode +to a board. + +Falcon Mode is introduced to speed up the booting process, allowing +to boot a Linux kernel (or whatever image) without a full blown U-Boot. + +Falcon Mode relies on the SPL framework. In fact, to make booting faster, +U-Boot is split into two parts: the SPL (Secondary Program Loader) and U-Boot +image. In most implementations, SPL is used to start U-Boot when booting from +a mass storage, such as NAND or SD-Card. SPL has now support for other media, +and can generally be seen as a way to start an image performing the minimum +required initialization. SPL mainly initializes the RAM controller, and then +copies U-Boot image into the memory. + +The Falcon Mode extends this way allowing to start the Linux kernel directly +from SPL. A new command is added to U-Boot to prepare the parameters that SPL +must pass to the kernel, using ATAGS or Device Tree. + +In normal mode, these parameters are generated each time before +loading the kernel, passing to Linux the address in memory where +the parameters can be read. +With Falcon Mode, this snapshot can be saved into persistent storage and SPL is +informed to load it before running the kernel. + +To boot the kernel, these steps under a Falcon-aware U-Boot are required: + +1. Boot the board into U-Boot. +Use the "spl export" command to generate the kernel parameters area or the DT. +U-Boot runs as when it boots the kernel, but stops before passing the control +to the kernel. + +2. Save the prepared snapshot into persistent media. +The address where to save it must be configured into board configuration +file (CONFIG_CMD_SPL_NAND_OFS for NAND). + +3. Boot the board into Falcon Mode. SPL will load the kernel and copy +the parameters which are saved in the persistent area to the required address. + +It is required to implement a custom mechanism to select if SPL loads U-Boot +or another image. + +The value of a GPIO is a simple way to operate the selection, as well as +reading a character from the SPL console if CONFIG_SPL_CONSOLE is set. + +Falcon Mode is generally activated by setting CONFIG_SPL_OS_BOOT. This tells +SPL that U-Boot is not the only available image that SPL is able to start. + +Configuration +---------------------------- +CONFIG_CMD_SPL Enable the "spl export" command. + The command "spl export" is then available in U-Boot + mode +CONFIG_SYS_SPL_ARGS_ADDR Address in RAM where the parameters must be + copied by SPL. + In most cases, it is + 0x100 + +CONFIG_SYS_NAND_SPL_KERNEL_OFFS Offset in NAND where the kernel is stored + +CONFIG_CMD_SPL_NAND_OFS Offset in NAND where the parameters area was saved. + +CONFIG_CMD_SPL_WRITE_SIZE Size of the parameters area to be copied + +CONFIG_SPL_OS_BOOT Activate Falcon Mode. + +Function that a board must implement +------------------------------------ + +void spl_board_prepare_for_linux(void) : optional + Called from SPL before starting the kernel + +spl_start_uboot() : required + Returns "0" if SPL should start the kernel, "1" if U-Boot + must be started. + + +Using spl command +----------------- + +spl - SPL configuration + +Usage: + +spl export [kernel_addr] [initrd_addr] [fdt_addr ] + +img : "atags" or "fdt" +kernel_addr : kernel is loaded as part of the boot process, but it is not started. + This is the address where a kernel image is stored. +initrd_addr : Address of initial ramdisk + can be set to "-" if fdt_addr without initrd_addr is used +fdt_addr : in case of fdt, the address of the device tree. + +The spl export command does not write to a storage media. The user is +responsible to transfer the gathered information (assembled ATAGS list +or prepared FDT) from temporary storage in RAM into persistant storage +after each run of 'spl export'. Unfortunately the position of temporary +storage can not be predicted nor provided at commandline, it depends +highly on your system setup and your provided data (ATAGS or FDT). +However at the end of an succesful 'spl export' run it will print the +RAM address of temporary storage. +Now the user have to save the generated BLOB from that printed address +to the pre-defined address in persistent storage +(CONFIG_CMD_SPL_NAND_OFS in case of NAND). +The following example shows how to prepare the data for Falcon Mode on +twister board with ATAGS BLOB. + +The "spl export" command is prepared to work with ATAGS and FDT. However, +using FDT is at the moment untested. The ppc port (see a3m071 example +later) prepares the fdt blob with the fdt command instead. + + +Usage on the twister board: +-------------------------------- + +Using mtd names with the following (default) configuration +for mtdparts: + +device nand0 , # parts = 9 + #: name size offset mask_flags + 0: MLO 0x00080000 0x00000000 0 + 1: u-boot 0x00100000 0x00080000 0 + 2: env1 0x00040000 0x00180000 0 + 3: env2 0x00040000 0x001c0000 0 + 4: kernel 0x00600000 0x00200000 0 + 5: bootparms 0x00040000 0x00800000 0 + 6: splashimg 0x00200000 0x00840000 0 + 7: mini 0x02800000 0x00a40000 0 + 8: rootfs 0x1cdc0000 0x03240000 0 + + +twister => nand read 82000000 kernel + +NAND read: device 0 offset 0x200000, size 0x600000 + 6291456 bytes read: OK + +Now the kernel is in RAM at address 0x82000000 + +twister => spl export atags 0x82000000 +## Booting kernel from Legacy Image at 82000000 ... + Image Name: Linux-3.5.0-rc4-14089-gda0b7f4 + Image Type: ARM Linux Kernel Image (uncompressed) + Data Size: 3654808 Bytes = 3.5 MiB + Load Address: 80008000 + Entry Point: 80008000 + Verifying Checksum ... OK + Loading Kernel Image ... OK +OK +cmdline subcommand not supported +bdt subcommand not supported +Argument image is now in RAM at: 0x80000100 + +The result can be checked at address 0x80000100: + +twister => md 0x80000100 +80000100: 00000005 54410001 00000000 00000000 ......AT........ +80000110: 00000000 00000067 54410009 746f6f72 ....g.....ATroot +80000120: 65642f3d 666e2f76 77722073 73666e20 =/dev/nfs rw nfs + +The parameters generated with this step can be saved into NAND at the offset +0x800000 (value for twister for CONFIG_CMD_SPL_NAND_OFS) + +nand erase.part bootparms +nand write 0x80000100 bootparms 0x4000 + +Now the parameters are stored into the NAND flash at the address +CONFIG_CMD_SPL_NAND_OFS (=0x800000). + +Next time, the board can be started into Falcon Mode moving the +setting the gpio (on twister gpio 55 is used) to kernel mode. + +The kernel is loaded directly by the SPL without passing through U-Boot. + +Example with FDT: a3m071 board +------------------------------- + +To boot the Linux kernel from the SPL, the DT blob (fdt) needs to get +prepard/patched first. U-Boot usually inserts some dynamic values into +the DT binary (blob), e.g. autodetected memory size, MAC addresses, +clocks speeds etc. To generate this patched DT blob, you can use +the following command: + +1. Load fdt blob to SDRAM: +=> tftp 1800000 a3m071/a3m071.dtb + +2. Set bootargs as desired for Linux booting (e.g. flash_mtd): +=> run mtdargs addip2 addtty + +3. Use "fdt" commands to patch the DT blob: +=> fdt addr 1800000 +=> fdt boardsetup +=> fdt chosen + +4. Display patched DT blob (optional): +=> fdt print + +5. Save fdt to NOR flash: +=> erase fc060000 fc07ffff +=> cp.b 1800000 fc060000 10000 +... + + +Falcon Mode was presented at the RMLL 2012. Slides are available at: + +http://schedule2012.rmll.info/IMG/pdf/LSM2012_UbootFalconMode_Babic.pdf -- cgit v1.2.3 From 30372965d3d5d42258ebc39d7d06522b4c18472a Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Sat, 23 Feb 2013 00:53:26 +0000 Subject: OMAP3: drop CONFIG_SPL_OS_BOOT_KEY and use local define CONFIG_SPL_OS_BOOT_KEY is used only in board files. It is not required to have a general CONFIG_ option. Rename it and define it in board directory. Signed-off-by: Stefano Babic Reviewed-by: Tom Rini --- board/technexion/twister/twister.c | 8 ++++---- board/technexion/twister/twister.h | 2 ++ board/timll/devkit8000/devkit8000.c | 8 ++++---- board/timll/devkit8000/devkit8000.h | 3 +++ include/configs/devkit8000.h | 1 - include/configs/twister.h | 1 - 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/board/technexion/twister/twister.c b/board/technexion/twister/twister.c index c9eea9b304..fa0ace019a 100644 --- a/board/technexion/twister/twister.c +++ b/board/technexion/twister/twister.c @@ -165,10 +165,10 @@ void spl_board_prepare_for_linux(void) int spl_start_uboot(void) { int val = 0; - if (!gpio_request(CONFIG_SPL_OS_BOOT_KEY, "U-Boot key")) { - gpio_direction_input(CONFIG_SPL_OS_BOOT_KEY); - val = gpio_get_value(CONFIG_SPL_OS_BOOT_KEY); - gpio_free(CONFIG_SPL_OS_BOOT_KEY); + if (!gpio_request(SPL_OS_BOOT_KEY, "U-Boot key")) { + gpio_direction_input(SPL_OS_BOOT_KEY); + val = gpio_get_value(SPL_OS_BOOT_KEY); + gpio_free(SPL_OS_BOOT_KEY); } return val; } diff --git a/board/technexion/twister/twister.h b/board/technexion/twister/twister.h index a2051c0044..cff479c07f 100644 --- a/board/technexion/twister/twister.h +++ b/board/technexion/twister/twister.h @@ -38,6 +38,8 @@ const omap3_sysinfo sysinfo = { #define XR16L2751_UART1_BASE 0x21000000 #define XR16L2751_UART2_BASE 0x23000000 +/* GPIO used to select between U-Boot and kernel */ +#define SPL_OS_BOOT_KEY 55 /* * IEN - Input Enable diff --git a/board/timll/devkit8000/devkit8000.c b/board/timll/devkit8000/devkit8000.c index 85685ee7c0..b88d9783cb 100644 --- a/board/timll/devkit8000/devkit8000.c +++ b/board/timll/devkit8000/devkit8000.c @@ -172,10 +172,10 @@ void spl_board_prepare_for_linux(void) int spl_start_uboot(void) { int val = 0; - if (!gpio_request(CONFIG_SPL_OS_BOOT_KEY, "U-Boot key")) { - gpio_direction_input(CONFIG_SPL_OS_BOOT_KEY); - val = gpio_get_value(CONFIG_SPL_OS_BOOT_KEY); - gpio_free(CONFIG_SPL_OS_BOOT_KEY); + if (!gpio_request(SPL_OS_BOOT_KEY, "U-Boot key")) { + gpio_direction_input(SPL_OS_BOOT_KEY); + val = gpio_get_value(SPL_OS_BOOT_KEY); + gpio_free(SPL_OS_BOOT_KEY); } return !val; } diff --git a/board/timll/devkit8000/devkit8000.h b/board/timll/devkit8000/devkit8000.h index aa69e6c965..c1965e2704 100644 --- a/board/timll/devkit8000/devkit8000.h +++ b/board/timll/devkit8000/devkit8000.h @@ -32,6 +32,9 @@ const omap3_sysinfo sysinfo = { "NAND", }; +/* GPIO used to select between U-Boot and kernel */ +#define SPL_OS_BOOT_KEY 26 + /* * IEN - Input Enable * IDIS - Input Disable diff --git a/include/configs/devkit8000.h b/include/configs/devkit8000.h index d926f74026..788227d79d 100644 --- a/include/configs/devkit8000.h +++ b/include/configs/devkit8000.h @@ -354,7 +354,6 @@ /* SPL OS boot options */ #define CONFIG_SPL_OS_BOOT -#define CONFIG_SPL_OS_BOOT_KEY 26 #define CONFIG_CMD_SPL #define CONFIG_CMD_SPL_WRITE_SIZE 0x400 /* 1024 byte */ diff --git a/include/configs/twister.h b/include/configs/twister.h index a8524816a8..4205a11bca 100644 --- a/include/configs/twister.h +++ b/include/configs/twister.h @@ -58,7 +58,6 @@ #define CONFIG_CMD_SPL_NAND_OFS (CONFIG_SYS_NAND_SPL_KERNEL_OFFS+\ 0x600000) #define CONFIG_SPL_OS_BOOT -#define CONFIG_SPL_OS_BOOT_KEY 55 #define CONFIG_SYS_SPL_ARGS_ADDR (PHYS_SDRAM_1 + 0x100) #define CONFIG_SPL_BOARD_INIT -- cgit v1.2.3 From 28786eb960a8def9f2bd321c488c71ce96166ae3 Mon Sep 17 00:00:00 2001 From: Stefano Babic Date: Sat, 23 Feb 2013 00:53:27 +0000 Subject: SPL: Change description for spl command Add a more descriptive text to the help of the spl command. Signed-off-by: Stefano Babic Reviewed-by: Tom Rini --- common/cmd_spl.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/common/cmd_spl.c b/common/cmd_spl.c index e3c543b46a..94b0a17156 100644 --- a/common/cmd_spl.c +++ b/common/cmd_spl.c @@ -184,7 +184,11 @@ static int do_spl(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( spl, 6 , 1, do_spl, "SPL configuration", - "export [kernel_addr] [initrd_addr] " - "[fdt_addr if = fdt] - export a kernel parameter image\n" - "\t initrd_img can be set to \"-\" if fdt_addr without initrd img is" - "used"); + "export [kernel_addr] [initrd_addr] [fdt_addr]\n" + "\timg\t\t\"atags\" or \"fdt\"\n" + "\tkernel_addr\taddress where a kernel image is stored.\n" + "\t\t\tkernel is loaded as part of the boot process, but it is not started.\n" + "\tinitrd_addr\taddress of initial ramdisk\n" + "\t\t\tcan be set to \"-\" if fdt_addr without initrd_addr is used.\n" + "\tfdt_addr\tin case of fdt, the address of the device tree.\n" + ); -- cgit v1.2.3 From 3ead92c571e7e17ca1c525c0fcd40e58901c5655 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Thu, 16 Aug 2012 11:10:41 +0800 Subject: blackfin: bf60x: new processor header files Add header files for blackfin new processor bf60x. Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang --- arch/blackfin/include/asm/blackfin_cdef.h | 3 + arch/blackfin/include/asm/blackfin_def.h | 5 + arch/blackfin/include/asm/blackfin_local.h | 3 + arch/blackfin/include/asm/mach-bf609/BF609_cdef.h | 192 ++++++++++++++++ arch/blackfin/include/asm/mach-bf609/BF609_def.h | 247 +++++++++++++++++++++ arch/blackfin/include/asm/mach-bf609/anomaly.h | 97 ++++++++ arch/blackfin/include/asm/mach-bf609/def_local.h | 5 + arch/blackfin/include/asm/mach-bf609/portmux.h | 257 ++++++++++++++++++++++ arch/blackfin/include/asm/mach-bf609/ports.h | 103 +++++++++ arch/blackfin/include/asm/mach-common/bits/cgu.h | 80 +++++++ arch/blackfin/include/asm/mach-common/bits/dde.h | 88 ++++++++ arch/blackfin/include/asm/mach-common/bits/mpu.h | 6 +- arch/blackfin/include/asm/mach-common/bits/pll.h | 5 + 13 files changed, 1090 insertions(+), 1 deletion(-) create mode 100644 arch/blackfin/include/asm/mach-bf609/BF609_cdef.h create mode 100644 arch/blackfin/include/asm/mach-bf609/BF609_def.h create mode 100644 arch/blackfin/include/asm/mach-bf609/anomaly.h create mode 100644 arch/blackfin/include/asm/mach-bf609/def_local.h create mode 100644 arch/blackfin/include/asm/mach-bf609/portmux.h create mode 100644 arch/blackfin/include/asm/mach-bf609/ports.h create mode 100644 arch/blackfin/include/asm/mach-common/bits/cgu.h create mode 100644 arch/blackfin/include/asm/mach-common/bits/dde.h diff --git a/arch/blackfin/include/asm/blackfin_cdef.h b/arch/blackfin/include/asm/blackfin_cdef.h index a19f0f74e6..86087117ef 100644 --- a/arch/blackfin/include/asm/blackfin_cdef.h +++ b/arch/blackfin/include/asm/blackfin_cdef.h @@ -84,5 +84,8 @@ #ifdef __ADSPBF561__ # include "mach-bf561/BF561_cdef.h" #endif +#ifdef __ADSPBF609__ +# include "mach-bf609/BF609_cdef.h" +#endif #endif /* __MACH_CDEF_BLACKFIN__ */ diff --git a/arch/blackfin/include/asm/blackfin_def.h b/arch/blackfin/include/asm/blackfin_def.h index f06d1f12cc..c96a3ecbba 100644 --- a/arch/blackfin/include/asm/blackfin_def.h +++ b/arch/blackfin/include/asm/blackfin_def.h @@ -136,5 +136,10 @@ # include "mach-bf561/anomaly.h" # include "mach-bf561/def_local.h" #endif +#ifdef __ADSPBF609__ +# include "mach-bf609/BF609_def.h" +# include "mach-bf609/anomaly.h" +# include "mach-bf609/def_local.h" +#endif #endif /* __MACH_DEF_BLACKFIN__ */ diff --git a/arch/blackfin/include/asm/blackfin_local.h b/arch/blackfin/include/asm/blackfin_local.h index 49d0c9ec3a..fc46ef4d11 100644 --- a/arch/blackfin/include/asm/blackfin_local.h +++ b/arch/blackfin/include/asm/blackfin_local.h @@ -61,6 +61,9 @@ extern u_long get_vco(void); extern u_long get_cclk(void); extern u_long get_sclk(void); +extern u_long get_sclk0(void); +extern u_long get_sclk1(void); +extern u_long get_dclk(void); # define bfin_revid() (bfin_read_CHIPID() >> 28) diff --git a/arch/blackfin/include/asm/mach-bf609/BF609_cdef.h b/arch/blackfin/include/asm/mach-bf609/BF609_cdef.h new file mode 100644 index 0000000000..c5900319f2 --- /dev/null +++ b/arch/blackfin/include/asm/mach-bf609/BF609_cdef.h @@ -0,0 +1,192 @@ +/* DO NOT EDIT THIS FILE + * Automatically generated by generate-cdef-headers.xsl + * DO NOT EDIT THIS FILE + */ + +#ifndef __BFIN_CDEF_ADSP_BF609_proc__ +#define __BFIN_CDEF_ADSP_BF609_proc__ + +#include "../mach-common/ADSP-EDN-core_cdef.h" + +#define bfin_read_CGU_STAT() bfin_read32(CGU_STAT) +#define bfin_read_CGU_CLKOUTSEL() bfin_read32(CGU_CLKOUTSEL) +#define bfin_read_CGU_CTL() bfin_read32(CGU_CTL) +#define bfin_write_CGU_CTL(val) bfin_write32(CGU_CTL, val) +#define bfin_read_CGU_DIV() bfin_read32(CGU_DIV) +#define bfin_write_CGU_DIV(val) bfin_write32(CGU_DIV, val) + +#define bfin_read_RCU0_CTL() bfin_read32(RCU0_CTL) +#define bfin_write_RCU0_CTL(val) bfin_write32(RCU0_CTL, val) + +#define bfin_read_CHIPID() bfin_read32(CHIPID) +#define bfin_write_CHIPID(val) bfin_write32(CHIPID, val) + +#define bfin_read_DMC0_CFG() bfin_read32(DMC0_CFG) +#define bfin_write_DMC0_CFG(val) bfin_write32(DMC0_CFG, val) +#define bfin_read_DMC0_TR0() bfin_read32(DMC0_TR0) +#define bfin_write_DMC0_TR0(val) bfin_write32(DMC0_TR0, val) +#define bfin_read_DMC0_TR1() bfin_read32(DMC0_TR1) +#define bfin_write_DMC0_TR1(val) bfin_write32(DMC0_TR1, val) +#define bfin_read_DMC0_TR2() bfin_read32(DMC0_TR2) +#define bfin_write_DMC0_TR2(val) bfin_write32(DMC0_TR2, val) +#define bfin_read_DMC0_MR() bfin_read32(DMC0_MR) +#define bfin_write_DMC0_MR(val) bfin_write32(DMC0_MR, val) +#define bfin_read_DMC0_EMR1() bfin_read32(DMC0_EMR1) +#define bfin_write_DMC0_EMR1(val) bfin_write32(DMC0_EMR1, val) +#define bfin_read_DMC0_CTL() bfin_read32(DMC0_CTL) +#define bfin_write_DMC0_CTL(val) bfin_write32(DMC0_CTL, val) +#define bfin_read_DMC0_STAT() bfin_read32(DMC0_STAT) +#define bfin_write_DMC0_STAT(val) bfin_write32(DMC0_STAT, val) +#define bfin_read_DMC0_DLLCTL() bfin_read32(DMC0_DLLCTL) +#define bfin_write_DMC0_DLLCTL(val) bfin_write32(DMC0_DLLCTL, val) + +#define bfin_read_SEC_CCTL() bfin_read32(SEC0_CCTL0) +#define bfin_write_SEC_CCTL(val) bfin_write32(SEC0_CCTL0, val) +#define bfin_read_SEC_GCTL() bfin_read32(SEC0_GCTL) +#define bfin_write_SEC_GCTL(val) bfin_write32(SEC0_GCTL, val) + +#define bfin_read_SEC_FCTL() bfin_read32(SEC0_FCTL) +#define bfin_write_SEC_FCTL(val) bfin_write32(SEC0_FCTL, val) +#define bfin_read_SEC_SCTL(sid) bfin_read32((SEC0_SCTL0 + (sid) * 8)) +#define bfin_write_SEC_SCTL(sid, val) bfin_write32((SEC0_SCTL0 \ + + (sid) * 8), val) + +#define bfin_read_SMC_GCTL() bfin_read32(SMC_GCTL) +#define bfin_write_SMC_GCTL(val) bfin_write32(SMC_GCTL, val) +#define bfin_read_SMC_GSTAT() bfin_read32(SMC_GSTAT) +#define bfin_read_SMC_B0CTL() bfin_read32(SMC_B0CTL) +#define bfin_write_SMC_B0CTL(val) bfin_write32(SMC_B0CTL, val) +#define bfin_read_SMC_B0TIM() bfin_read32(SMC_B0TIM) +#define bfin_write_SMC_B0TIM(val) bfin_write32(SMC_B0TIM, val) +#define bfin_read_SMC_B0ETIM() bfin_read32(SMC_B0ETIM) +#define bfin_write_SMC_B0ETIM(val) bfin_write32(SMC_B0ETIM, val) +#define bfin_read_SMC_B1CTL() bfin_read32(SMC_B1CTL) +#define bfin_write_SMC_B1CTL(val) bfin_write32(SMC_B1CTL, val) +#define bfin_read_SMC_B1TIM() bfin_read32(SMC_B1TIM) +#define bfin_write_SMC_B1TIM(val) bfin_write32(SMC_B1TIM, val) +#define bfin_read_SMC_B1ETIM() bfin_read32(SMC_B1ETIM) +#define bfin_write_SMC_B1ETIM(val) bfin_write32(SMC_B1ETIM, val) +#define bfin_read_SMC_B2CTL() bfin_read32(SMC_B2CTL) +#define bfin_write_SMC_B2CTL(val) bfin_write32(SMC_B2CTL, val) +#define bfin_read_SMC_B2TIM() bfin_read32(SMC_B2TIM) +#define bfin_write_SMC_B2TIM(val) bfin_write32(SMC_B2TIM, val) +#define bfin_read_SMC_B2ETIM() bfin_read32(SMC_B2ETIM) +#define bfin_write_SMC_B2ETIM(val) bfin_write32(SMC_B2ETIM, val) +#define bfin_read_SMC_B3CTL() bfin_read32(SMC_B3CTL) +#define bfin_write_SMC_B3CTL(val) bfin_write32(SMC_B3CTL, val) +#define bfin_read_SMC_B3TIM() bfin_read32(SMC_B3TIM) +#define bfin_write_SMC_B3TIM(val) bfin_write32(SMC_B3TIM, val) +#define bfin_read_SMC_B3ETIM() bfin_read32(SMC_B3ETIM) +#define bfin_write_SMC_B3ETIM(val) bfin_write32(SMC_B3ETIM, val) + +#define bfin_read_USB_PLLOSC_CTRL() bfin_read16(USB_PLL_OSC) +#define bfin_write_USB_PLLOSC_CTRL(val) bfin_write16(USB_PLL_OSC, val) +#define bfin_write_USB_VBUS_CTL(val) bfin_write8(USB_VBUS_CTL, val) +#define bfin_read_USB_DMA_INTERRUPT() bfin_read8(USB_DMA_IRQ) +#define bfin_write_USB_DMA_INTERRUPT(val) bfin_write8(USB_DMA_IRQ, val) +#define bfin_write_USB_APHY_CNTRL(val) bfin_write8(USB_PHY_CTL, val) +#define bfin_read_USB_APHY_CNTRL() bfin_read8(USB_PHY_CTL) + +#define bfin_read_DMA10_NEXT_DESC_PTR() bfin_readPTR(DMA10_DSCPTR_NXT) +#define bfin_write_DMA10_NEXT_DESC_PTR(val) bfin_writePTR(DMA10_DSCPTR_NXT, val) +#define bfin_read_DMA10_START_ADDR() bfin_readPTR(DMA10_ADDRSTART) +#define bfin_write_DMA10_START_ADDR(val) bfin_writePTR(DMA10_ADDRSTART, val) +#define bfin_read_DMA10_CONFIG() bfin_read32(DMA10_CFG) +#define bfin_write_DMA10_CONFIG(val) bfin_write32(DMA10_CFG, val) +#define bfin_read_DMA10_X_COUNT() bfin_read32(DMA10_XCNT) +#define bfin_write_DMA10_X_COUNT(val) bfin_write32(DMA10_XCNT, val) +#define bfin_read_DMA10_X_MODIFY() bfin_read32(DMA10_XMOD) +#define bfin_write_DMA10_X_MODIFY(val) bfin_write32(DMA10_XMOD, val) +#define bfin_read_DMA10_Y_COUNT() bfin_read32(DMA10_YCNT) +#define bfin_write_DMA10_Y_COUNT(val) bfin_write32(DMA10_YCNT, val) +#define bfin_read_DMA10_Y_MODIFY() bfin_read32(DMA10_YMOD) +#define bfin_write_DMA10_Y_MODIFY(val) bfin_write32(DMA10_YMOD, val) +#define bfin_read_DMA10_CURR_DESC_PTR() bfin_readPTR(DMA10_DSCPTR_CUR) +#define bfin_write_DMA10_CURR_DESC_PTR(val) bfin_writePTR(DMA10_DSCPTR_CUR, val) +#define bfin_read_DMA10_CURR_ADDR() bfin_readPTR(DMA10_ADDR_CUR) +#define bfin_write_DMA10_CURR_ADDR(val) bfin_writePTR(DMA10_ADDR_CUR, val) +#define bfin_read_DMA10_IRQ_STATUS() bfin_read32(DMA10_STAT) +#define bfin_write_DMA10_IRQ_STATUS(val) bfin_write32(DMA10_STAT, val) +#define bfin_read_DMA10_CURR_X_COUNT() bfin_read32(DMA10_XCNT_CUR) +#define bfin_write_DMA10_CURR_X_COUNT(val) bfin_write32(DMA10_XCNT_CUR, val) +#define bfin_read_DMA10_CURR_Y_COUNT() bfin_read32(DMA10_YCNT_CUR) +#define bfin_write_DMA10_CURR_Y_COUNT(val) bfin_write32(DMA10_YCNT_CUR, val) + +#define bfin_read_WDOG_CNT() bfin_read32(WDOG_CNT) +#define bfin_write_WDOG_CNT(val) bfin_write32(WDOG_CNT, val) +#define bfin_read_WDOG_CTL() bfin_read32(WDOG_CTL) +#define bfin_write_WDOG_CTL(val) bfin_write32(WDOG_CTL, val) +#define bfin_read_WDOG_STAT() bfin_read32(WDOG_STAT) +#define bfin_write_WDOG_STAT(val) bfin_write32(WDOG_STAT, val) +#define bfin_read_SPI_BAUD() bfin_read32(SPI0_CLK) +#define bfin_write_SPI_BAUD(val) bfin_write32(SPI0_CLK, val) + +#define bfin_read_PORTD_FER() bfin_read32(PORTD_FER) +#define bfin_write_PORTD_FER_SET(val) bfin_write32(PORTD_FER_SET, val) +#define bfin_write_PORTD_FER_CLR(val) bfin_write32(PORTD_FER_CLR, val) +#define bfin_read_PORTD_MUX() bfin_read32(PORTD_MUX) +#define bfin_write_PORTD_MUX(val) bfin_write32(PORTD_MUX, val) +#define bfin_read_PORTG_FER() bfin_read32(PORTG_FER) +#define bfin_write_PORTG_FER_SET(val) bfin_write32(PORTG_FER_SET, val) +#define bfin_write_PORTG_FER_CLR(val) bfin_write32(PORTG_FER_CLR, val) +#define bfin_read_PORTG_MUX() bfin_read32(PORTG_MUX) +#define bfin_write_PORTG_MUX(val) bfin_write32(PORTG_MUX, val) + +#define bfin_read_RSI_CLK_CONTROL() bfin_read16(RSI_CLK_CONTROL) +#define bfin_write_RSI_CLK_CONTROL(val) bfin_write16(RSI_CLK_CONTROL, val) +#define bfin_read_RSI_ARGUMENT() bfin_read32(RSI_ARGUMENT) +#define bfin_write_RSI_ARGUMENT(val) bfin_write32(RSI_ARGUMENT, val) +#define bfin_read_RSI_COMMAND() bfin_read16(RSI_COMMAND) +#define bfin_write_RSI_COMMAND(val) bfin_write16(RSI_COMMAND, val) +#define bfin_read_RSI_RESP_CMD() bfin_read16(RSI_RESP_CMD) +#define bfin_write_RSI_RESP_CMD(val) bfin_write16(RSI_RESP_CMD, val) +#define bfin_read_RSI_RESPONSE0() bfin_read32(RSI_RESPONSE0) +#define bfin_write_RSI_RESPONSE0(val) bfin_write32(RSI_RESPONSE0, val) +#define bfin_read_RSI_RESPONSE1() bfin_read32(RSI_RESPONSE1) +#define bfin_write_RSI_RESPONSE1(val) bfin_write32(RSI_RESPONSE1, val) +#define bfin_read_RSI_RESPONSE2() bfin_read32(RSI_RESPONSE2) +#define bfin_write_RSI_RESPONSE2(val) bfin_write32(RSI_RESPONSE2, val) +#define bfin_read_RSI_RESPONSE3() bfin_read32(RSI_RESPONSE3) +#define bfin_write_RSI_RESPONSE3(val) bfin_write32(RSI_RESPONSE3, val) +#define bfin_read_RSI_DATA_TIMER() bfin_read32(RSI_DATA_TIMER) +#define bfin_write_RSI_DATA_TIMER(val) bfin_write32(RSI_DATA_TIMER, val) +#define bfin_read_RSI_DATA_LGTH() bfin_read16(RSI_DATA_LGTH) +#define bfin_write_RSI_DATA_LGTH(val) bfin_write16(RSI_DATA_LGTH, val) +#define bfin_read_RSI_DATA_CONTROL() bfin_read16(RSI_DATA_CONTROL) +#define bfin_write_RSI_DATA_CONTROL(val) bfin_write16(RSI_DATA_CONTROL, val) +#define bfin_read_RSI_DATA_CNT() bfin_read16(RSI_DATA_CNT) +#define bfin_write_RSI_DATA_CNT(val) bfin_write16(RSI_DATA_CNT, val) +#define bfin_read_RSI_STATUS() bfin_read32(RSI_STATUS) +#define bfin_write_RSI_STATUS(val) bfin_write32(RSI_STATUS, val) +#define bfin_read_RSI_STATUSCL() bfin_read16(RSI_STATUSCL) +#define bfin_write_RSI_STATUSCL(val) bfin_write16(RSI_STATUSCL, val) +#define bfin_read_RSI_MASK0() bfin_read32(RSI_MASK0) +#define bfin_write_RSI_MASK0(val) bfin_write32(RSI_MASK0, val) +#define bfin_read_RSI_MASK1() bfin_read32(RSI_MASK1) +#define bfin_write_RSI_MASK1(val) bfin_write32(RSI_MASK1, val) +#define bfin_read_RSI_FIFO_CNT() bfin_read16(RSI_FIFO_CNT) +#define bfin_write_RSI_FIFO_CNT(val) bfin_write16(RSI_FIFO_CNT, val) +#define bfin_read_RSI_CEATA_CONTROL() bfin_read16(RSI_CEATA_CONTROL) +#define bfin_write_RSI_CEATA_CONTROL(val) bfin_write16(RSI_CEATA_CONTROL, val) +#define bfin_read_RSI_BLKSZ() bfin_read16(RSI_BLKSZ) +#define bfin_write_RSI_BLKSZ(val) bfin_write16(RSI_BLKSZ, val) +#define bfin_read_RSI_FIFO() bfin_read32(RSI_FIFO) +#define bfin_write_RSI_FIFO(val) bfin_write32(RSI_FIFO, val) +#define bfin_read_RSI_ESTAT() bfin_read32(RSI_ESTAT) +#define bfin_write_RSI_ESTAT(val) bfin_write32(RSI_ESTAT, val) +#define bfin_read_RSI_EMASK() bfin_read32(RSI_EMASK) +#define bfin_write_RSI_EMASK(val) bfin_write32(RSI_EMASK, val) +#define bfin_read_RSI_CONFIG() bfin_read16(RSI_CONFIG) +#define bfin_write_RSI_CONFIG(val) bfin_write16(RSI_CONFIG, val) +#define bfin_read_RSI_RD_WAIT_EN() bfin_read16(RSI_RD_WAIT_EN) +#define bfin_write_RSI_RD_WAIT_EN(val) bfin_write16(RSI_RD_WAIT_EN, val) +#define bfin_read_RSI_PID0() bfin_read16(RSI_PID0) +#define bfin_write_RSI_PID0(val) bfin_write16(RSI_PID0, val) +#define bfin_read_RSI_PID1() bfin_read16(RSI_PID1) +#define bfin_write_RSI_PID1(val) bfin_write16(RSI_PID1, val) +#define bfin_read_RSI_PID2() bfin_read16(RSI_PID2) +#define bfin_write_RSI_PID2(val) bfin_write16(RSI_PID2, val) +#define bfin_read_RSI_PID3() bfin_read16(RSI_PID3) +#define bfin_write_RSI_PID3(val) bfin_write16(RSI_PID3, val) + +#endif /* __BFIN_CDEF_ADSP_BF609_proc__ */ diff --git a/arch/blackfin/include/asm/mach-bf609/BF609_def.h b/arch/blackfin/include/asm/mach-bf609/BF609_def.h new file mode 100644 index 0000000000..8c1dcd006e --- /dev/null +++ b/arch/blackfin/include/asm/mach-bf609/BF609_def.h @@ -0,0 +1,247 @@ +/* DO NOT EDIT THIS FILE + * Automatically generated by generate-def-headers.xsl + * DO NOT EDIT THIS FILE + */ + +#ifndef __BFIN_DEF_ADSP_BF609_proc__ +#define __BFIN_DEF_ADSP_BF609_proc__ + +#include "../mach-common/ADSP-EDN-core_def.h" + +#define RSI_CLK_CONTROL 0xFFC00604 /* RSI0 Clock Control Register */ +#define RSI_ARGUMENT 0xFFC00608 /* RSI0 Argument Register */ +#define RSI_COMMAND 0xFFC0060C /* RSI0 Command Register */ +#define RSI_RESP_CMD 0xFFC00610 /* RSI0 Response Command Register */ +#define RSI_RESPONSE0 0xFFC00614 /* RSI0 Response 0 Register */ +#define RSI_RESPONSE1 0xFFC00618 /* RSI0 Response 1 Register */ +#define RSI_RESPONSE2 0xFFC0061C /* RSI0 Response 2 Register */ +#define RSI_RESPONSE3 0xFFC00620 /* RSI0 Response 3 Register */ +#define RSI_DATA_TIMER 0xFFC00624 /* RSI0 Data Timer Register */ +#define RSI_DATA_LGTH 0xFFC00628 /* RSI0 Data Length Register */ +#define RSI_DATA_CONTROL 0xFFC0062C /* RSI0 Data Control Register */ +#define RSI_DATA_CNT 0xFFC00630 /* RSI0 Data Count Register */ +#define RSI_STATUS 0xFFC00634 /* RSI0 Status Register */ +#define RSI_STATUSCL 0xFFC00638 /* RSI0 Status Clear Register */ +#define RSI_IMSK0 0xFFC0063C /* RSI0 Interrupt 0 Mask Register */ +#define RSI_IMSK1 0xFFC00640 /* RSI0 Interrupt 1 Mask Register */ +#define RSI_FIFO_CNT 0xFFC00648 /* RSI0 FIFO Counter Register */ +#define RSI_CEATA_CONTROL 0xFFC0064C /* RSI0 contains bit to dis CCS gen */ +#define RSI_BOOT_TCNTR 0xFFC00650 /* RSI0 Boot Timing Counter Register */ +#define RSI_BACK_TOUT 0xFFC00654 /* RSI0 Boot Ack Timeout Register */ +#define RSI_SLP_WKUP_TOUT 0xFFC00658 /* RSI0 Sleep Wakeup Timeout Register */ +#define RSI_BLKSZ 0xFFC0065C /* RSI0 Block Size Register */ +#define RSI_FIFO 0xFFC00680 /* RSI0 Data FIFO Register */ +#define RSI_ESTAT 0xFFC006C0 /* RSI0 Exception Status Register */ +#define RSI_EMASK 0xFFC006C4 /* RSI0 Exception Mask Register */ +#define RSI_CONFIG 0xFFC006C8 /* RSI0 Configuration Register */ +#define RSI_RD_WAIT_EN 0xFFC006CC /* RSI0 Read Wait Enable Register */ +#define RSI_PID0 0xFFC006D0 /* RSI0 Peripheral Id Register */ +#define RSI_PID1 0xFFC006D4 /* RSI0 Peripheral Id Register */ +#define RSI_PID2 0xFFC006D8 /* RSI0 Peripheral Id Register */ +#define RSI_PID3 0xFFC006DC /* RSI0 Peripheral Id Register */ + +#define TWI0_CLKDIV 0xFFC01E00 /* TWI0 SCL Clock Divider */ +#define TWI1_CLKDIV 0xFFC01F00 /* TWI1 SCL Clock Divider */ + +#define UART0_REVID 0xFFC02000 /* UART0 Revision ID Register */ +#define UART0_CTL 0xFFC02004 /* UART0 Control Register */ +#define UART0_STAT 0xFFC02008 /* UART0 Status Register */ +#define UART0_SCR 0xFFC0200C /* UART0 Scratch Register */ +#define UART0_CLK 0xFFC02010 /* UART0 Clock Rate Register */ +#define UART0_IMSK 0xFFC02014 /* UART0 Interrupt Mask Register */ +#define UART0_IMSK_SET 0xFFC02018 /* UART0 Interrupt Mask Set Register */ +#define UART0_IMSK_CLR 0xFFC0201C /* UART0 Interrupt Mask Clear Register */ +#define UART0_RBR 0xFFC02020 /* UART0 Receive Buffer Register */ +#define UART0_THR 0xFFC02024 /* UART0 Transmit Hold Register */ +#define UART0_TAIP 0xFFC02028 /* UART0 TX Address/Insert Pulse Reg */ +#define UART0_TSR 0xFFC0202C /* UART0 Transmit Shift Register */ +#define UART0_RSR 0xFFC02030 /* UART0 Receive Shift Register */ +#define UART0_TXCNT 0xFFC02034 /* UART0 Transmit Counter Register */ +#define UART0_RXCNT 0xFFC02038 /* UART0 Receive Counter Register */ +#define UART1_REVID 0xFFC02400 /* UART1 Revision ID Register */ +#define UART1_CTL 0xFFC02404 /* UART1 Control Register */ +#define UART1_STAT 0xFFC02408 /* UART1 Status Register */ +#define UART1_SCR 0xFFC0240C /* UART1 Scratch Register */ +#define UART1_CLK 0xFFC02410 /* UART1 Clock Rate Register */ +#define UART1_IMSK 0xFFC02414 /* UART1 Interrupt Mask Register */ +#define UART1_IMSK_SET 0xFFC02418 /* UART1 Interrupt Mask Set Register */ +#define UART1_IMSK_CLR 0xFFC0241C /* UART1 Interrupt Mask Clear Register */ +#define UART1_RBR 0xFFC02420 /* UART1 Receive Buffer Register */ +#define UART1_THR 0xFFC02424 /* UART1 Transmit Hold Register */ +#define UART1_TAIP 0xFFC02428 /* UART1 TX Address/Insert Pulse Reg */ +#define UART1_TSR 0xFFC0242C /* UART1 Transmit Shift Register */ +#define UART1_RSR 0xFFC02430 /* UART1 Receive Shift Register */ +#define UART1_TXCNT 0xFFC02434 /* UART1 Transmit Counter Register */ +#define UART1_RXCNT 0xFFC02438 /* UART1 Receive Counter Register */ + +#define PORTA_FER 0xFFC03000 /* PORTA Port x Function Enable */ +#define PORTA_FER_SET 0xFFC03004 /* PORTA Port x Function Enable Set */ +#define PORTA_FER_CLR 0xFFC03008 /* PORTA Port x Function Enable Clear */ +#define PORTA_MUX 0xFFC03030 /* PORTA Port x Multiplexer Control */ +#define PORTB_FER 0xFFC03080 /* PORTB Port x Function Enable */ +#define PORTB_FER_SET 0xFFC03084 /* PORTB Port x Function Enable Set */ +#define PORTB_FER_CLR 0xFFC03088 /* PORTB Port x Function Enable Clear */ +#define PORTB_MUX 0xFFC030B0 /* PORTB Port x Multiplexer Control */ +#define PORTC_FER 0xFFC03100 /* PORTC Port x Function Enable */ +#define PORTC_FER_SET 0xFFC03104 /* PORTC Port x Function Enable Set */ +#define PORTC_FER_CLR 0xFFC03108 /* PORTC Port x Function Enable Clear */ +#define PORTC_MUX 0xFFC03130 /* PORTC Port x Multiplexer Control */ +#define PORTD_FER 0xFFC03180 /* PORTD Port x Function Enable */ +#define PORTD_FER_SET 0xFFC03184 /* PORTD Port x Function Enable Set */ +#define PORTD_FER_CLR 0xFFC03188 /* PORTD Port x Function Enable Clear */ +#define PORTD_MUX 0xFFC031B0 /* PORTD Port x Multiplexer Control */ +#define PORTE_FER 0xFFC03200 /* PORTE Port x Function Enable */ +#define PORTE_FER_SET 0xFFC03204 /* PORTE Port x Function Enable Set */ +#define PORTE_FER_CLR 0xFFC03208 /* PORTE Port x Function Enable Clear */ +#define PORTE_MUX 0xFFC03230 /* PORTE Port x Multiplexer Control */ +#define PORTF_FER 0xFFC03280 /* PORTF Port x Function Enable */ +#define PORTF_FER_SET 0xFFC03284 /* PORTF Port x Function Enable Set */ +#define PORTF_FER_CLR 0xFFC03288 /* PORTF Port x Function Enable Clear */ +#define PORTF_MUX 0xFFC032B0 /* PORTF Port x Multiplexer Control */ +#define PORTG_FER 0xFFC03300 /* PORTG Port x Function Enable */ +#define PORTG_FER_SET 0xFFC03304 /* PORTG Port x Function Enable Set */ +#define PORTG_FER_CLR 0xFFC03308 /* PORTG Port x Function Enable Clear */ +#define PORTG_MUX 0xFFC03330 /* PORTG Port x Multiplexer Control */ + +#define SMC_GCTL 0xFFC16004 /* SMC Control Register */ +#define SMC_GSTAT 0xFFC16008 /* SMC Status Register */ +#define SMC_B0CTL 0xFFC1600C /* SMC Bank0 Control Register */ +#define SMC_B0TIM 0xFFC16010 /* SMC Bank0 Timing Register */ +#define SMC_B0ETIM 0xFFC16014 /* SMC Bank0 Extended Timing Register */ +#define SMC_B1CTL 0xFFC1601C /* SMC BANK1 Control Register */ +#define SMC_B1TIM 0xFFC16020 /* SMC BANK1 Timing Register */ +#define SMC_B1ETIM 0xFFC16024 /* SMC BANK1 Extended Timing Register */ +#define SMC_B2CTL 0xFFC1602C /* SMC BANK2 Control Register */ +#define SMC_B2TIM 0xFFC16030 /* SMC BANK2 Timing Register */ +#define SMC_B2ETIM 0xFFC16034 /* SMC BANK2 Extended Timing Register */ +#define SMC_B3CTL 0xFFC1603C /* SMC BANK3 Control Register */ +#define SMC_B3TIM 0xFFC16040 /* SMC BANK3 Timing Register */ +#define SMC_B3ETIM 0xFFC16044 /* SMC BANK3 Extended Timing Register */ + +#define WDOG_CTL 0xFFC17000 /* WDOG0 Control Register */ +#define WDOG_CNT 0xFFC17004 /* WDOG0 Count Register */ +#define WDOG_STAT 0xFFC17008 /* WDOG0 Watchdog Timer Status Register */ +#define WDOG1_CTL 0xFFC17800 /* WDOG1 Control Register */ +#define WDOG1_CNT 0xFFC17804 /* WDOG1 Count Register */ +#define WDOG1_STAT 0xFFC17808 /* WDOG1 Watchdog Timer Status Register */ + +#define EMAC0_MACCFG 0xFFC20000 /* EMAC0 MAC Configuration Register */ +#define EMAC1_MACCFG 0xFFC22000 /* EMAC1 MAC Configuration Register */ + +#define DMA10_DSCPTR_NXT 0xFFC05000 /* DMA10 Pointer to Next Initial Desc */ +#define DMA10_ADDRSTART 0xFFC05004 /* DMA10 Start Address of Current Buf */ +#define DMA10_CFG 0xFFC05008 /* DMA10 Configuration Register */ +#define DMA10_XCNT 0xFFC0500C /* DMA10 Inner Loop Count Start Value */ +#define DMA10_XMOD 0xFFC05010 /* DMA10 Inner Loop Address Increment */ +#define DMA10_YCNT 0xFFC05014 /* DMA10 Outer Loop Count Start Value */ +#define DMA10_YMOD 0xFFC05018 /* DMA10 Outer Loop Address Increment */ +#define DMA10_DSCPTR_CUR 0xFFC05024 /* DMA10 Current Descriptor Pointer */ +#define DMA10_DSCPTR_PRV 0xFFC05028 /* DMA10 Previous Initial Desc Pointer */ +#define DMA10_ADDR_CUR 0xFFC0502C /* DMA10 Current Address */ +#define DMA10_STAT 0xFFC05030 /* DMA10 Status Register */ +#define DMA10_XCNT_CUR 0xFFC05034 /* DMA10 Curr Count(1D) or intra-row(2D)*/ +#define DMA10_YCNT_CUR 0xFFC05038 /* DMA10 Curr Row Count (2D only) */ +#define DMA10_BWLCNT 0xFFC05040 /* DMA10 Bandwidth Limit Count */ +#define DMA10_BWLCNT_CUR 0xFFC05044 /* DMA10 Bandwidth Limit Count Current */ +#define DMA10_BWMCNT 0xFFC05048 /* DMA10 Bandwidth Monitor Count */ +#define DMA10_BWMCNT_CUR 0xFFC0504C /* DMA10 Bandwidth Monitor Count Current*/ + +#define MDMA_S0_NEXT_DESC_PTR DMA21_DSCPTR_NXT +#define DMA21_DSCPTR_NXT 0xFFC09000 /* DMA21 Pointer to Next Initial Desc */ +#define MDMA_D0_NEXT_DESC_PTR DMA22_DSCPTR_NXT +#define DMA22_DSCPTR_NXT 0xFFC09080 /* DMA22 Pointer to Next Initial Desc */ + +#define DMC0_ID 0xFFC80000 /* DMC0 Identification Register */ +#define DMC0_CTL 0xFFC80004 /* DMC0 Control Register */ +#define DMC0_STAT 0xFFC80008 /* DMC0 Status Register */ +#define DMC0_EFFCTL 0xFFC8000C /* DMC0 Efficiency Controller */ +#define DMC0_PRIO 0xFFC80010 /* DMC0 Priority ID Register */ +#define DMC0_PRIOMSK 0xFFC80014 /* DMC0 Priority ID Mask */ +#define DMC0_CFG 0xFFC80040 /* DMC0 SDRAM Configuration */ +#define DMC0_TR0 0xFFC80044 /* DMC0 Timing Register 0 */ +#define DMC0_TR1 0xFFC80048 /* DMC0 Timing Register 1 */ +#define DMC0_TR2 0xFFC8004C /* DMC0 Timing Register 2 */ +#define DMC0_MSK 0xFFC8005C /* DMC0 Mode Register Mask */ +#define DMC0_MR 0xFFC80060 /* DMC0 Mode Shadow register */ +#define DMC0_EMR1 0xFFC80064 /* DMC0 EMR1 Shadow Register */ +#define DMC0_EMR2 0xFFC80068 /* DMC0 EMR2 Shadow Register */ +#define DMC0_EMR3 0xFFC8006C /* DMC0 EMR3 Shadow Register */ +#define DMC0_DLLCTL 0xFFC80080 /* DMC0 DLL Control Register */ +#define DMC0_PADCTL 0xFFC800C0 /* DMC0 PAD Control Register 0 */ + +#define SEC0_CCTL0 0xFFCA4400 /* SEC0 Core Control Register n */ +#define SEC0_CCTL1 0xFFCA4440 /* SEC0 Core Control Register n */ +#define SEC0_FCTL 0xFFCA4010 /* SEC0 Fault Control Register */ +#define SEC0_GCTL 0xFFCA4000 /* SEC0 Global Control Register */ +#define SEC0_SCTL0 0xFFCA4800 /* SEC0 IRQ Source Control Register n */ + +#define RCU0_CTL 0xFFCA6000 /* RCU0 Control Register */ +#define RCU0_STAT 0xFFCA6004 /* RCU0 Status Register */ +#define RCU0_CRCTL 0xFFCA6008 /* RCU0 Core Reset Control Register */ +#define RCU0_CRSTAT 0xFFCA600C /* RCU0 Core Reset Status Register */ +#define RCU0_SIDIS 0xFFCA6010 /* RCU0 Sys Interface Disable Register */ +#define RCU0_SISTAT 0xFFCA6014 /* RCU0 Sys Interface Status Register */ +#define RCU0_SVECT_LCK 0xFFCA6018 /* RCU0 SVECT Lock Register */ +#define RCU0_BCODE 0xFFCA601C /* RCU0 Boot Code Register */ +#define RCU0_SVECT0 0xFFCA6020 /* RCU0 Software Vector Register n */ +#define RCU0_SVECT1 0xFFCA6024 /* RCU0 Software Vector Register n */ + +#define CGU_CTL 0xFFCA8000 /* CGU0 Control Register */ +#define CGU_STAT 0xFFCA8004 /* CGU0 Status Register */ +#define CGU_DIV 0xFFCA8008 /* CGU0 Divisor Register */ +#define CGU_CLKOUTSEL 0xFFCA800C /* CGU0 CLKOUT Select Register */ + +#define DPM0_CTL 0xFFCA9000 /* DPM0 Control Register */ +#define DPM0_STAT 0xFFCA9004 /* DPM0 Status Register */ +#define DPM0_CCBF_DIS 0xFFCA9008 /* DPM0 Core Clock Buffer Disable */ +#define DPM0_CCBF_EN 0xFFCA900C /* DPM0 Core Clock Buffer Enable */ +#define DPM0_CCBF_STAT 0xFFCA9010 /* DPM0 Core Clock Buffer Status */ +#define DPM0_CCBF_STAT_STKY 0xFFCA9014 /* DPM0 Core Clock Buffer Stat Sticky */ +#define DPM0_SCBF_DIS 0xFFCA9018 /* DPM0 System Clock Buffer Disable */ +#define DPM0_WAKE_EN 0xFFCA901C /* DPM0 Wakeup Enable Register */ +#define DPM0_WAKE_POL 0xFFCA9020 /* DPM0 Wakeup Polarity Register */ +#define DPM0_WAKE_STAT 0xFFCA9024 /* DPM0 Wakeup Status Register */ +#define DPM0_HIB_DIS 0xFFCA9028 /* DPM0 Hibernate Disable Register */ +#define DPM0_PGCNTR 0xFFCA902C /* DPM0 Power Good Counter Register */ +#define DPM0_RESTORE0 0xFFCA9030 /* DPM0 Restore Register */ +#define DPM0_RESTORE1 0xFFCA9034 /* DPM0 Restore Register */ +#define DPM0_RESTORE2 0xFFCA9038 /* DPM0 Restore Register */ +#define DPM0_RESTORE3 0xFFCA903C /* DPM0 Restore Register */ +#define DPM0_RESTORE4 0xFFCA9040 /* DPM0 Restore Register */ +#define DPM0_RESTORE5 0xFFCA9044 /* DPM0 Restore Register */ +#define DPM0_RESTORE6 0xFFCA9048 /* DPM0 Restore Register */ +#define DPM0_RESTORE7 0xFFCA904C /* DPM0 Restore Register */ +#define DPM0_RESTORE8 0xFFCA9050 /* DPM0 Restore Register */ +#define DPM0_RESTORE9 0xFFCA9054 /* DPM0 Restore Register */ +#define DPM0_RESTORE10 0xFFCA9058 /* DPM0 Restore Register */ +#define DPM0_RESTORE11 0xFFCA905C /* DPM0 Restore Register */ +#define DPM0_RESTORE12 0xFFCA9060 /* DPM0 Restore Register */ +#define DPM0_RESTORE13 0xFFCA9064 /* DPM0 Restore Register */ +#define DPM0_RESTORE14 0xFFCA9068 /* DPM0 Restore Register */ +#define DPM0_RESTORE15 0xFFCA906C /* DPM0 Restore Register */ + +#define USB_FADDR 0xFFCC1000 /* USB Device Address in Peripheral Mode*/ +#define USB_DMA_IRQ 0xFFCC1200 /* USB Interrupt Register */ +#define USB_VBUS_CTL 0xFFCC1380 /* USB VBus Control */ +#define USB_PHY_CTL 0xFFCC1394 /* USB PHY Control */ +#define USB_PLL_OSC 0xFFCC1398 /* USB PLL and Oscillator Control */ + + +#define CHIPID 0xffc00014 +/* CHIPID Masks */ +#define CHIPID_VERSION 0xF0000000 +#define CHIPID_FAMILY 0x0FFFF000 +#define CHIPID_MANUFACTURE 0x00000FFE + +#define L1_DATA_A_SRAM 0xFF800000 /* 0xFF800000->0xFF803FFF Data Bank A SRAM */ +#define L1_DATA_A_SRAM_SIZE 0x8000 +#define L1_DATA_A_SRAM_END (L1_DATA_A_SRAM + L1_DATA_A_SRAM_SIZE) +#define L1_DATA_B_SRAM 0xFF900000 /* 0xFF900000->0xFF903FFF Data Bank B SRAM */ +#define L1_DATA_B_SRAM_SIZE 0x4000 +#define L1_DATA_B_SRAM_END (L1_DATA_B_SRAM + L1_DATA_B_SRAM_SIZE) + +#define L1_INST_SRAM 0xFFA00000 /* 0xFFA00000->0xFFA07FFF Inst Bank A SRAM */ +#define L1_INST_SRAM_SIZE 0x8000 +#define L1_INST_SRAM_END (L1_INST_SRAM + L1_INST_SRAM_SIZE) + +#endif /* __BFIN_DEF_ADSP_BF609_proc__ */ diff --git a/arch/blackfin/include/asm/mach-bf609/anomaly.h b/arch/blackfin/include/asm/mach-bf609/anomaly.h new file mode 100644 index 0000000000..0a70f082af --- /dev/null +++ b/arch/blackfin/include/asm/mach-bf609/anomaly.h @@ -0,0 +1,97 @@ +/* + * Copyright 2004-2012 Analog Devices Inc. + * Licensed under the ADI BSD license. + * https://docs.blackfin.uclinux.org/doku.php?id=adi_bsd + */ + +/* This file should be up to date with: + * - Revision A, 15/06/2012; ADSP-BF609 Blackfin Processor Anomaly List + */ + +#if __SILICON_REVISION__ < 0 +# error will not work on BF609 silicon version +#endif + +#ifndef _MACH_ANOMALY_H_ +#define _MACH_ANOMALY_H_ + +/* TRU_STAT.ADDRERR and TRU_ERRADDR.ADDR May Not Reflect the Correct Status */ +#define ANOMALY_16000003 (1) +/* The EPPI Data Enable (DEN) Signal is Not Functional */ +#define ANOMALY_16000004 (1) +/* Using L1 Instruction Cache with Parity Enabled is Unreliable */ +#define ANOMALY_16000005 (1) +/* SEQSTAT.SYSNMI Clears Upon Entering the NMI ISR */ +#define ANOMALY_16000006 (1) +/* DDR2 Memory Reads May Fail Intermittently */ +#define ANOMALY_16000007 (1) +/* Instruction Memory Stalls Can Cause IFLUSH to Fail */ +#define ANOMALY_16000008 (1) +/* TestSET Instruction Cannot Be Interrupted */ +#define ANOMALY_16000009 (1) +/* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */ +#define ANOMALY_16000010 (1) +/* False Hardware Error when RETI Points to Invalid Memory */ +#define ANOMALY_16000011 (1) +/* Speculative Fetches of Indirect-Pointer Inst Can Cause False Hw Errors */ +#define ANOMALY_16000012 (1) +/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */ +#define ANOMALY_16000013 (1) +/* False Hardware Error from an Access in the Shadow of a Conditional Branch */ +#define ANOMALY_16000014 (1) +/* Multi-Issue Inst with dsp32shiftimm in slot1 and P in slot2 Not Supported */ +#define ANOMALY_16000015 (1) +/* Speculative Fetches Can Cause Undesired External FIFO Operations */ +#define ANOMALY_16000017 (1) +/* RSI Boot Cleanup Routine Does Not Clear Registers */ +#define ANOMALY_16000018 (1) +/* SPI Master Boot Device Auto-detection Frequency is Set Incorrectly */ +#define ANOMALY_16000019 (1) +/* rom_SysControl() Fails to Set DDR0_CTL.INIT for Wakeup From Hibernate */ +#define ANOMALY_16000020 (1) +/* rom_SysControl() Fails to Save and Restore DDR0_PHYCTL3 for Hb/Wk Sequence */ +#define ANOMALY_16000021 (1) +/* Boot Code Fails to Enable Parity Fault Detection */ +#define ANOMALY_16000022 (1) +/* USB DMA interrupt status do not show the DMA channel intr in the DMA ISR */ +#define ANOMALY_16000027 (1) +/* Interrupted Core Reads of MMRs May Cause Data Loss */ +#define ANOMALY_16000030 (1) + +/* Anomalies that don't exist on this proc */ +#define ANOMALY_05000158 (0) +#define ANOMALY_05000189 (0) +#define ANOMALY_05000198 (0) +#define ANOMALY_05000219 (0) +#define ANOMALY_05000230 (0) +#define ANOMALY_05000231 (0) +#define ANOMALY_05000244 (0) +#define ANOMALY_05000261 (0) +#define ANOMALY_05000263 (0) +#define ANOMALY_05000273 (0) +#define ANOMALY_05000274 (0) +#define ANOMALY_05000278 (0) +#define ANOMALY_05000281 (0) +#define ANOMALY_05000287 (0) +#define ANOMALY_05000311 (0) +#define ANOMALY_05000312 (0) +#define ANOMALY_05000323 (0) +#define ANOMALY_05000353 (1) +#define ANOMALY_05000363 (0) +#define ANOMALY_05000386 (0) +#define ANOMALY_05000480 (0) +#define ANOMALY_05000481 (1) + +/* Reuse BF5xx anomalies IDs for the same anomaly in BF60x */ +#define ANOMALY_05000491 ANOMALY_16000008 +#define ANOMALY_05000477 ANOMALY_16000009 +#define ANOMALY_05000443 ANOMALY_16000010 +#define ANOMALY_05000461 ANOMALY_16000011 +#define ANOMALY_05000426 ANOMALY_16000012 +#define ANOMALY_05000310 ANOMALY_16000013 +#define ANOMALY_05000245 ANOMALY_16000014 +#define ANOMALY_05000074 ANOMALY_16000015 +#define ANOMALY_05000416 ANOMALY_16000017 + + +#endif diff --git a/arch/blackfin/include/asm/mach-bf609/def_local.h b/arch/blackfin/include/asm/mach-bf609/def_local.h new file mode 100644 index 0000000000..d4250e6f99 --- /dev/null +++ b/arch/blackfin/include/asm/mach-bf609/def_local.h @@ -0,0 +1,5 @@ +#include "gpio.h" +#include "portmux.h" +#include "ports.h" + +#define CONFIG_BF60x 1 /* Linux glue */ diff --git a/arch/blackfin/include/asm/mach-bf609/portmux.h b/arch/blackfin/include/asm/mach-bf609/portmux.h new file mode 100644 index 0000000000..757570f2ef --- /dev/null +++ b/arch/blackfin/include/asm/mach-bf609/portmux.h @@ -0,0 +1,257 @@ +/* + * Copyright 2008-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later + */ + +#ifndef _MACH_PORTMUX_H_ +#define _MACH_PORTMUX_H_ + +#define MAX_RESOURCES MAX_BLACKFIN_GPIOS + +/* EMAC RMII Port Mux */ +#define P_MII0_MDC (P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(0)) +#define P_MII0_MDIO (P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(0)) +#define P_MII0_ETxD0 (P_DEFINED | P_IDENT(GPIO_PC2) | P_FUNCT(0)) +#define P_MII0_ERxD0 (P_DEFINED | P_IDENT(GPIO_PC0) | P_FUNCT(0)) +#define P_MII0_ETxD1 (P_DEFINED | P_IDENT(GPIO_PC3) | P_FUNCT(0)) +#define P_MII0_ERxD1 (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(0)) +#define P_MII0_ETxEN (P_DEFINED | P_IDENT(GPIO_PB13) | P_FUNCT(0)) +#define P_MII0_PHYINT (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(0)) +#define P_MII0_CRS (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(0)) +#define P_MII0_ERxER (P_DEFINED | P_IDENT(GPIO_PC4) | P_FUNCT(0)) +#define P_MII0_TxCLK (P_DEFINED | P_IDENT(GPIO_PB14) | P_FUNCT(0)) + +#define P_RMII0 {\ + P_MII0_ETxD0, \ + P_MII0_ETxD1, \ + P_MII0_ETxEN, \ + P_MII0_ERxD0, \ + P_MII0_ERxD1, \ + P_MII0_ERxER, \ + P_MII0_TxCLK, \ + P_MII0_PHYINT, \ + P_MII0_CRS, \ + P_MII0_MDC, \ + P_PTP0_PPS, \ + P_PTP1_PPS, \ + P_MII0_MDIO, 0} + +#define P_MII1_MDC (P_DEFINED | P_IDENT(GPIO_PE10) | P_FUNCT(0)) +#define P_MII1_MDIO (P_DEFINED | P_IDENT(GPIO_PE11) | P_FUNCT(0)) +#define P_MII1_ETxD0 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(0)) +#define P_MII1_ERxD0 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(0)) +#define P_MII1_ETxD1 (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(0)) +#define P_MII1_ERxD1 (P_DEFINED | P_IDENT(GPIO_PE15) | P_FUNCT(0)) +#define P_MII1_ETxEN (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(0)) +#define P_MII1_PHYINT (P_DEFINED | P_IDENT(GPIO_PE12) | P_FUNCT(0)) +#define P_MII1_CRS (P_DEFINED | P_IDENT(GPIO_PE13) | P_FUNCT(0)) +#define P_MII1_ERxER (P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(0)) +#define P_MII1_TxCLK (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(0)) + +#define P_RMII1 {\ + P_MII1_ETxD0, \ + P_MII1_ETxD1, \ + P_MII1_ETxEN, \ + P_MII1_ERxD0, \ + P_MII1_ERxD1, \ + P_MII1_ERxER, \ + P_MII1_TxCLK, \ + P_MII1_PHYINT, \ + P_MII1_CRS, \ + P_MII1_MDC, \ + P_MII1_MDIO, 0} + +/* PPI Port Mux */ +#define P_PPI0_D0 (P_DEFINED | P_IDENT(GPIO_PF0) | P_FUNCT(1)) +#define P_PPI0_D1 (P_DEFINED | P_IDENT(GPIO_PF1) | P_FUNCT(1)) +#define P_PPI0_D2 (P_DEFINED | P_IDENT(GPIO_PF2) | P_FUNCT(1)) +#define P_PPI0_D3 (P_DEFINED | P_IDENT(GPIO_PF3) | P_FUNCT(1)) +#define P_PPI0_D4 (P_DEFINED | P_IDENT(GPIO_PF4) | P_FUNCT(1)) +#define P_PPI0_D5 (P_DEFINED | P_IDENT(GPIO_PF5) | P_FUNCT(1)) +#define P_PPI0_D6 (P_DEFINED | P_IDENT(GPIO_PF6) | P_FUNCT(1)) +#define P_PPI0_D7 (P_DEFINED | P_IDENT(GPIO_PF7) | P_FUNCT(1)) +#define P_PPI0_D8 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(1)) +#define P_PPI0_D9 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(1)) +#define P_PPI0_D10 (P_DEFINED | P_IDENT(GPIO_PF10) | P_FUNCT(1)) +#define P_PPI0_D11 (P_DEFINED | P_IDENT(GPIO_PF11) | P_FUNCT(1)) +#define P_PPI0_D12 (P_DEFINED | P_IDENT(GPIO_PF12) | P_FUNCT(1)) +#define P_PPI0_D13 (P_DEFINED | P_IDENT(GPIO_PF13) | P_FUNCT(1)) +#define P_PPI0_D14 (P_DEFINED | P_IDENT(GPIO_PF14) | P_FUNCT(1)) +#define P_PPI0_D15 (P_DEFINED | P_IDENT(GPIO_PF15) | P_FUNCT(1)) +#define P_PPI0_D16 (P_DEFINED | P_IDENT(GPIO_PE3) | P_FUNCT(1)) +#define P_PPI0_D17 (P_DEFINED | P_IDENT(GPIO_PE4) | P_FUNCT(1)) +#define P_PPI0_D18 (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(1)) +#define P_PPI0_D19 (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(1)) +#define P_PPI0_D20 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(1)) +#define P_PPI0_D21 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(1)) +#define P_PPI0_D22 (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(1)) +#define P_PPI0_D23 (P_DEFINED | P_IDENT(GPIO_PE5) | P_FUNCT(1)) +#define P_PPI0_CLK (P_DEFINED | P_IDENT(GPIO_PE9) | P_FUNCT(1)) +#define P_PPI0_FS1 (P_DEFINED | P_IDENT(GPIO_PE8) | P_FUNCT(1)) +#define P_PPI0_FS2 (P_DEFINED | P_IDENT(GPIO_PE7) | P_FUNCT(1)) +#define P_PPI0_FS3 (P_DEFINED | P_IDENT(GPIO_PE6) | P_FUNCT(1)) + +#define P_PPI1_D0 (P_DEFINED | P_IDENT(GPIO_PC0) | P_FUNCT(1)) +#define P_PPI1_D1 (P_DEFINED | P_IDENT(GPIO_PC1) | P_FUNCT(1)) +#define P_PPI1_D2 (P_DEFINED | P_IDENT(GPIO_PC2) | P_FUNCT(1)) +#define P_PPI1_D3 (P_DEFINED | P_IDENT(GPIO_PC3) | P_FUNCT(1)) +#define P_PPI1_D4 (P_DEFINED | P_IDENT(GPIO_PC4) | P_FUNCT(1)) +#define P_PPI1_D5 (P_DEFINED | P_IDENT(GPIO_PC5) | P_FUNCT(1)) +#define P_PPI1_D6 (P_DEFINED | P_IDENT(GPIO_PC6) | P_FUNCT(1)) +#define P_PPI1_D7 (P_DEFINED | P_IDENT(GPIO_PC7) | P_FUNCT(1)) +#define P_PPI1_D8 (P_DEFINED | P_IDENT(GPIO_PC8) | P_FUNCT(1)) +#define P_PPI1_D9 (P_DEFINED | P_IDENT(GPIO_PC9) | P_FUNCT(1)) +#define P_PPI1_D10 (P_DEFINED | P_IDENT(GPIO_PC10) | P_FUNCT(1)) +#define P_PPI1_D11 (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(1)) +#define P_PPI1_D12 (P_DEFINED | P_IDENT(GPIO_PC12) | P_FUNCT(1)) +#define P_PPI1_D13 (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(1)) +#define P_PPI1_D14 (P_DEFINED | P_IDENT(GPIO_PC14) | P_FUNCT(1)) +#define P_PPI1_D15 (P_DEFINED | P_IDENT(GPIO_PC15) | P_FUNCT(1)) +#define P_PPI1_D16 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(1)) +#define P_PPI1_D17 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(1)) +#define P_PPI1_CLK (P_DEFINED | P_IDENT(GPIO_PB14) | P_FUNCT(1)) +#define P_PPI1_FS1 (P_DEFINED | P_IDENT(GPIO_PB13) | P_FUNCT(1)) +#define P_PPI1_FS2 (P_DEFINED | P_IDENT(GPIO_PD6) | P_FUNCT(1)) +#define P_PPI1_FS3 (P_DEFINED | P_IDENT(GPIO_PB15) | P_FUNCT(1)) + +#define P_PPI2_D0 (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(1)) +#define P_PPI2_D1 (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(1)) +#define P_PPI2_D2 (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(1)) +#define P_PPI2_D3 (P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(1)) +#define P_PPI2_D4 (P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(1)) +#define P_PPI2_D5 (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(1)) +#define P_PPI2_D6 (P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(1)) +#define P_PPI2_D7 (P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(1)) +#define P_PPI2_D8 (P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(1)) +#define P_PPI2_D9 (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(1)) +#define P_PPI2_D10 (P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(1)) +#define P_PPI2_D11 (P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(1)) +#define P_PPI2_D12 (P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(1)) +#define P_PPI2_D13 (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(1)) +#define P_PPI2_D14 (P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(1)) +#define P_PPI2_D15 (P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(1)) +#define P_PPI2_D16 (P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(1)) +#define P_PPI2_D17 (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(1)) +#define P_PPI2_CLK (P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(1)) +#define P_PPI2_FS1 (P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(1)) +#define P_PPI2_FS2 (P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(1)) +#define P_PPI2_FS3 (P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(1)) + +/* SPI Port Mux */ +#define P_SPI0_SS (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(3)) +#define P_SPI0_SCK (P_DEFINED | P_IDENT(GPIO_PD4) | P_FUNCT(0)) +#define P_SPI0_MISO (P_DEFINED | P_IDENT(GPIO_PD2) | P_FUNCT(0)) +#define P_SPI0_MOSI (P_DEFINED | P_IDENT(GPIO_PD3) | P_FUNCT(0)) +#define P_SPI0_RDY (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(0)) +#define P_SPI0_D2 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(0)) +#define P_SPI0_D3 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(0)) + +#define P_SPI0_SSEL1 (P_DEFINED | P_IDENT(GPIO_PD11) | P_FUNCT(0)) +#define P_SPI0_SSEL2 (P_DEFINED | P_IDENT(GPIO_PD1) | P_FUNCT(2)) +#define P_SPI0_SSEL3 (P_DEFINED | P_IDENT(GPIO_PD0) | P_FUNCT(2)) +#define P_SPI0_SSEL4 (P_DEFINED | P_IDENT(GPIO_PC15) | P_FUNCT(0)) +#define P_SPI0_SSEL5 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(0)) +#define P_SPI0_SSEL6 (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(0)) +#define P_SPI0_SSEL7 (P_DEFINED | P_IDENT(GPIO_PC12) | P_FUNCT(0)) + +#define P_SPI1_SS (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(3)) +#define P_SPI1_SCK (P_DEFINED | P_IDENT(GPIO_PD5) | P_FUNCT(0)) +#define P_SPI1_MISO (P_DEFINED | P_IDENT(GPIO_PD14) | P_FUNCT(0)) +#define P_SPI1_MOSI (P_DEFINED | P_IDENT(GPIO_PD13) | P_FUNCT(0)) +#define P_SPI1_RDY (P_DEFINED | P_IDENT(GPIO_PE2) | P_FUNCT(0)) +#define P_SPI1_D2 (P_DEFINED | P_IDENT(GPIO_PE1) | P_FUNCT(0)) +#define P_SPI1_D3 (P_DEFINED | P_IDENT(GPIO_PE0) | P_FUNCT(0)) + +#define P_SPI1_SSEL1 (P_DEFINED | P_IDENT(GPIO_PD12) | P_FUNCT(0)) +#define P_SPI1_SSEL2 (P_DEFINED | P_IDENT(GPIO_PD15) | P_FUNCT(2)) +#define P_SPI1_SSEL3 (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(2)) +#define P_SPI1_SSEL4 (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(2)) +#define P_SPI1_SSEL5 (P_DEFINED | P_IDENT(GPIO_PF8) | P_FUNCT(0)) +#define P_SPI1_SSEL6 (P_DEFINED | P_IDENT(GPIO_PF9) | P_FUNCT(0)) +#define P_SPI1_SSEL7 (P_DEFINED | P_IDENT(GPIO_PC14) | P_FUNCT(0)) + +#define GPIO_DEFAULT_BOOT_SPI_CS +#define P_DEFAULT_BOOT_SPI_CS + +/* UART Port Mux */ +#define P_UART0_TX (P_DEFINED | P_IDENT(GPIO_PD7) | P_FUNCT(1)) +#define P_UART0_RX (P_DEFINED | P_IDENT(GPIO_PD8) | P_FUNCT(1)) +#define P_UART0_RTS (P_DEFINED | P_IDENT(GPIO_PD9) | P_FUNCT(1)) +#define P_UART0_CTS (P_DEFINED | P_IDENT(GPIO_PD10) | P_FUNCT(1)) + +#define P_UART1_TX (P_DEFINED | P_IDENT(GPIO_PG15) | P_FUNCT(0)) +#define P_UART1_RX (P_DEFINED | P_IDENT(GPIO_PG14) | P_FUNCT(0)) +#define P_UART1_RTS (P_DEFINED | P_IDENT(GPIO_PG10) | P_FUNCT(0)) +#define P_UART1_CTS (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(0)) + +/* Timer */ +#define P_TMRCLK (P_DEFINED | P_IDENT(GPIO_PG13) | P_FUNCT(3)) +#define P_TMR0 (P_DEFINED | P_IDENT(GPIO_PE14) | P_FUNCT(2)) +#define P_TMR1 (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(1)) +#define P_TMR2 (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(1)) +#define P_TMR3 (P_DEFINED | P_IDENT(GPIO_PG8) | P_FUNCT(1)) +#define P_TMR4 (P_DEFINED | P_IDENT(GPIO_PG9) | P_FUNCT(1)) +#define P_TMR5 (P_DEFINED | P_IDENT(GPIO_PG7) | P_FUNCT(1)) +#define P_TMR6 (P_DEFINED | P_IDENT(GPIO_PG11) | P_FUNCT(1)) +#define P_TMR7 (P_DEFINED | P_IDENT(GPIO_PG12) | P_FUNCT(1)) + +/* RSI */ +#define P_RSI_DATA0 (P_DEFINED | P_IDENT(GPIO_PG3) | P_FUNCT(2)) +#define P_RSI_DATA1 (P_DEFINED | P_IDENT(GPIO_PG2) | P_FUNCT(2)) +#define P_RSI_DATA2 (P_DEFINED | P_IDENT(GPIO_PG0) | P_FUNCT(2)) +#define P_RSI_DATA3 (P_DEFINED | P_IDENT(GPIO_PE15) | P_FUNCT(2)) +#define P_RSI_DATA4 (P_DEFINED | P_IDENT(GPIO_PE13) | P_FUNCT(2)) +#define P_RSI_DATA5 (P_DEFINED | P_IDENT(GPIO_PE12) | P_FUNCT(2)) +#define P_RSI_DATA6 (P_DEFINED | P_IDENT(GPIO_PE10) | P_FUNCT(2)) +#define P_RSI_DATA7 (P_DEFINED | P_IDENT(GPIO_PE11) | P_FUNCT(2)) +#define P_RSI_CMD (P_DEFINED | P_IDENT(GPIO_PG5) | P_FUNCT(1)) +#define P_RSI_CLK (P_DEFINED | P_IDENT(GPIO_PG6) | P_FUNCT(1)) + +/* PTP */ +#define P_PTP0_PPS (P_DEFINED | P_IDENT(GPIO_PB15) | P_FUNCT(0)) +#define P_PTP0_CLKIN (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(2)) +#define P_PTP0_AUXIN (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(2)) + +#define P_PTP1_PPS (P_DEFINED | P_IDENT(GPIO_PC9) | P_FUNCT(0)) +#define P_PTP1_CLKIN (P_DEFINED | P_IDENT(GPIO_PC13) | P_FUNCT(2)) +#define P_PTP1_AUXIN (P_DEFINED | P_IDENT(GPIO_PC11) | P_FUNCT(2)) + +/* SMC Port Mux */ +#define P_A3 (P_DEFINED | P_IDENT(GPIO_PA0) | P_FUNCT(0)) +#define P_A4 (P_DEFINED | P_IDENT(GPIO_PA1) | P_FUNCT(0)) +#define P_A5 (P_DEFINED | P_IDENT(GPIO_PA2) | P_FUNCT(0)) +#define P_A6 (P_DEFINED | P_IDENT(GPIO_PA3) | P_FUNCT(0)) +#define P_A7 (P_DEFINED | P_IDENT(GPIO_PA4) | P_FUNCT(0)) +#define P_A8 (P_DEFINED | P_IDENT(GPIO_PA5) | P_FUNCT(0)) +#define P_A9 (P_DEFINED | P_IDENT(GPIO_PA6) | P_FUNCT(0)) +#define P_A10 (P_DEFINED | P_IDENT(GPIO_PA7) | P_FUNCT(0)) +#define P_A11 (P_DEFINED | P_IDENT(GPIO_PA8) | P_FUNCT(0)) +#define P_A12 (P_DEFINED | P_IDENT(GPIO_PA9) | P_FUNCT(0)) +#define P_A13 (P_DEFINED | P_IDENT(GPIO_PB2) | P_FUNCT(0)) +#define P_A14 (P_DEFINED | P_IDENT(GPIO_PA10) | P_FUNCT(0)) +#define P_A15 (P_DEFINED | P_IDENT(GPIO_PA11) | P_FUNCT(0)) +#define P_A16 (P_DEFINED | P_IDENT(GPIO_PB3) | P_FUNCT(0)) +#define P_A17 (P_DEFINED | P_IDENT(GPIO_PA12) | P_FUNCT(0)) +#define P_A18 (P_DEFINED | P_IDENT(GPIO_PA13) | P_FUNCT(0)) +#define P_A19 (P_DEFINED | P_IDENT(GPIO_PA14) | P_FUNCT(0)) +#define P_A20 (P_DEFINED | P_IDENT(GPIO_PA15) | P_FUNCT(0)) +#define P_A21 (P_DEFINED | P_IDENT(GPIO_PB6) | P_FUNCT(0)) +#define P_A22 (P_DEFINED | P_IDENT(GPIO_PB7) | P_FUNCT(0)) +#define P_A23 (P_DEFINED | P_IDENT(GPIO_PB8) | P_FUNCT(0)) +#define P_A24 (P_DEFINED | P_IDENT(GPIO_PB10) | P_FUNCT(0)) +#define P_A25 (P_DEFINED | P_IDENT(GPIO_PB11) | P_FUNCT(0)) +#define P_NORCK (P_DEFINED | P_IDENT(GPIO_PB0) | P_FUNCT(0)) + +#define P_AMS1 (P_DEFINED | P_IDENT(GPIO_PB1) | P_FUNCT(0)) +#define P_AMS2 (P_DEFINED | P_IDENT(GPIO_PB4) | P_FUNCT(0)) +#define P_AMS3 (P_DEFINED | P_IDENT(GPIO_PB5) | P_FUNCT(0)) + +#define P_ABE0 (P_DEFINED | P_IDENT(GPIO_PB4) | P_FUNCT(1)) +#define P_ABE1 (P_DEFINED | P_IDENT(GPIO_PB5) | P_FUNCT(1)) + +/* CAN */ +#define P_CAN0_TX (P_DEFINED | P_IDENT(GPIO_PG1) | P_FUNCT(2)) +#define P_CAN0_RX (P_DEFINED | P_IDENT(GPIO_PG4) | P_FUNCT(2)) + +#endif /* _MACH_PORTMUX_H_ */ diff --git a/arch/blackfin/include/asm/mach-bf609/ports.h b/arch/blackfin/include/asm/mach-bf609/ports.h new file mode 100644 index 0000000000..b361c7bcbe --- /dev/null +++ b/arch/blackfin/include/asm/mach-bf609/ports.h @@ -0,0 +1,103 @@ +/* + * Port Masks + */ + +#ifndef __BFIN_PERIPHERAL_PORT__ +#define __BFIN_PERIPHERAL_PORT__ + +/* PORTx_MUX Masks */ +#define PORT_x_MUX_0_MASK 0x00000003 +#define PORT_x_MUX_1_MASK 0x0000000C +#define PORT_x_MUX_2_MASK 0x00000030 +#define PORT_x_MUX_3_MASK 0x000000C0 +#define PORT_x_MUX_4_MASK 0x00000300 +#define PORT_x_MUX_5_MASK 0x00000C00 +#define PORT_x_MUX_6_MASK 0x00003000 +#define PORT_x_MUX_7_MASK 0x0000C000 +#define PORT_x_MUX_8_MASK 0x00030000 +#define PORT_x_MUX_9_MASK 0x000C0000 +#define PORT_x_MUX_10_MASK 0x00300000 +#define PORT_x_MUX_11_MASK 0x00C00000 +#define PORT_x_MUX_12_MASK 0x03000000 +#define PORT_x_MUX_13_MASK 0x0C000000 +#define PORT_x_MUX_14_MASK 0x30000000 +#define PORT_x_MUX_15_MASK 0xC0000000 + +#define PORT_x_MUX_FUNC_1 (0x0) +#define PORT_x_MUX_FUNC_2 (0x1) +#define PORT_x_MUX_FUNC_3 (0x2) +#define PORT_x_MUX_FUNC_4 (0x3) +#define PORT_x_MUX_0_FUNC_1 (PORT_x_MUX_FUNC_1 << 0) +#define PORT_x_MUX_0_FUNC_2 (PORT_x_MUX_FUNC_2 << 0) +#define PORT_x_MUX_0_FUNC_3 (PORT_x_MUX_FUNC_3 << 0) +#define PORT_x_MUX_0_FUNC_4 (PORT_x_MUX_FUNC_4 << 0) +#define PORT_x_MUX_1_FUNC_1 (PORT_x_MUX_FUNC_1 << 2) +#define PORT_x_MUX_1_FUNC_2 (PORT_x_MUX_FUNC_2 << 2) +#define PORT_x_MUX_1_FUNC_3 (PORT_x_MUX_FUNC_3 << 2) +#define PORT_x_MUX_1_FUNC_4 (PORT_x_MUX_FUNC_4 << 2) +#define PORT_x_MUX_2_FUNC_1 (PORT_x_MUX_FUNC_1 << 4) +#define PORT_x_MUX_2_FUNC_2 (PORT_x_MUX_FUNC_2 << 4) +#define PORT_x_MUX_2_FUNC_3 (PORT_x_MUX_FUNC_3 << 4) +#define PORT_x_MUX_2_FUNC_4 (PORT_x_MUX_FUNC_4 << 4) +#define PORT_x_MUX_3_FUNC_1 (PORT_x_MUX_FUNC_1 << 6) +#define PORT_x_MUX_3_FUNC_2 (PORT_x_MUX_FUNC_2 << 6) +#define PORT_x_MUX_3_FUNC_3 (PORT_x_MUX_FUNC_3 << 6) +#define PORT_x_MUX_3_FUNC_4 (PORT_x_MUX_FUNC_4 << 6) +#define PORT_x_MUX_4_FUNC_1 (PORT_x_MUX_FUNC_1 << 8) +#define PORT_x_MUX_4_FUNC_2 (PORT_x_MUX_FUNC_2 << 8) +#define PORT_x_MUX_4_FUNC_3 (PORT_x_MUX_FUNC_3 << 8) +#define PORT_x_MUX_4_FUNC_4 (PORT_x_MUX_FUNC_4 << 8) +#define PORT_x_MUX_5_FUNC_1 (PORT_x_MUX_FUNC_1 << 10) +#define PORT_x_MUX_5_FUNC_2 (PORT_x_MUX_FUNC_2 << 10) +#define PORT_x_MUX_5_FUNC_3 (PORT_x_MUX_FUNC_3 << 10) +#define PORT_x_MUX_5_FUNC_4 (PORT_x_MUX_FUNC_4 << 10) +#define PORT_x_MUX_6_FUNC_1 (PORT_x_MUX_FUNC_1 << 12) +#define PORT_x_MUX_6_FUNC_2 (PORT_x_MUX_FUNC_2 << 12) +#define PORT_x_MUX_6_FUNC_3 (PORT_x_MUX_FUNC_3 << 12) +#define PORT_x_MUX_6_FUNC_4 (PORT_x_MUX_FUNC_4 << 12) +#define PORT_x_MUX_7_FUNC_1 (PORT_x_MUX_FUNC_1 << 14) +#define PORT_x_MUX_7_FUNC_2 (PORT_x_MUX_FUNC_2 << 14) +#define PORT_x_MUX_7_FUNC_3 (PORT_x_MUX_FUNC_3 << 14) +#define PORT_x_MUX_7_FUNC_4 (PORT_x_MUX_FUNC_4 << 14) +#define PORT_x_MUX_8_FUNC_1 (PORT_x_MUX_FUNC_1 << 16) +#define PORT_x_MUX_8_FUNC_2 (PORT_x_MUX_FUNC_2 << 16) +#define PORT_x_MUX_8_FUNC_3 (PORT_x_MUX_FUNC_3 << 16) +#define PORT_x_MUX_8_FUNC_4 (PORT_x_MUX_FUNC_4 << 16) +#define PORT_x_MUX_9_FUNC_1 (PORT_x_MUX_FUNC_1 << 18) +#define PORT_x_MUX_9_FUNC_2 (PORT_x_MUX_FUNC_2 << 18) +#define PORT_x_MUX_9_FUNC_3 (PORT_x_MUX_FUNC_3 << 18) +#define PORT_x_MUX_9_FUNC_4 (PORT_x_MUX_FUNC_4 << 18) +#define PORT_x_MUX_10_FUNC_1 (PORT_x_MUX_FUNC_1 << 20) +#define PORT_x_MUX_10_FUNC_2 (PORT_x_MUX_FUNC_2 << 20) +#define PORT_x_MUX_10_FUNC_3 (PORT_x_MUX_FUNC_3 << 20) +#define PORT_x_MUX_10_FUNC_4 (PORT_x_MUX_FUNC_4 << 20) +#define PORT_x_MUX_11_FUNC_1 (PORT_x_MUX_FUNC_1 << 22) +#define PORT_x_MUX_11_FUNC_2 (PORT_x_MUX_FUNC_2 << 22) +#define PORT_x_MUX_11_FUNC_3 (PORT_x_MUX_FUNC_3 << 22) +#define PORT_x_MUX_11_FUNC_4 (PORT_x_MUX_FUNC_4 << 22) +#define PORT_x_MUX_12_FUNC_1 (PORT_x_MUX_FUNC_1 << 24) +#define PORT_x_MUX_12_FUNC_2 (PORT_x_MUX_FUNC_2 << 24) +#define PORT_x_MUX_12_FUNC_3 (PORT_x_MUX_FUNC_3 << 24) +#define PORT_x_MUX_12_FUNC_4 (PORT_x_MUX_FUNC_4 << 24) +#define PORT_x_MUX_13_FUNC_1 (PORT_x_MUX_FUNC_1 << 26) +#define PORT_x_MUX_13_FUNC_2 (PORT_x_MUX_FUNC_2 << 26) +#define PORT_x_MUX_13_FUNC_3 (PORT_x_MUX_FUNC_3 << 26) +#define PORT_x_MUX_13_FUNC_4 (PORT_x_MUX_FUNC_4 << 26) +#define PORT_x_MUX_14_FUNC_1 (PORT_x_MUX_FUNC_1 << 28) +#define PORT_x_MUX_14_FUNC_2 (PORT_x_MUX_FUNC_2 << 28) +#define PORT_x_MUX_14_FUNC_3 (PORT_x_MUX_FUNC_3 << 28) +#define PORT_x_MUX_14_FUNC_4 (PORT_x_MUX_FUNC_4 << 28) +#define PORT_x_MUX_15_FUNC_1 (PORT_x_MUX_FUNC_1 << 30) +#define PORT_x_MUX_15_FUNC_2 (PORT_x_MUX_FUNC_2 << 30) +#define PORT_x_MUX_15_FUNC_3 (PORT_x_MUX_FUNC_3 << 30) +#define PORT_x_MUX_15_FUNC_4 (PORT_x_MUX_FUNC_4 << 30) + +#include "../mach-common/bits/ports-a.h" +#include "../mach-common/bits/ports-b.h" +#include "../mach-common/bits/ports-c.h" +#include "../mach-common/bits/ports-d.h" +#include "../mach-common/bits/ports-e.h" +#include "../mach-common/bits/ports-f.h" +#include "../mach-common/bits/ports-g.h" + +#endif diff --git a/arch/blackfin/include/asm/mach-common/bits/cgu.h b/arch/blackfin/include/asm/mach-common/bits/cgu.h new file mode 100644 index 0000000000..cdf7349925 --- /dev/null +++ b/arch/blackfin/include/asm/mach-common/bits/cgu.h @@ -0,0 +1,80 @@ +/* + * CGU Masks + */ + +#ifndef __BFIN_PERIPHERAL_CGU__ +#define __BFIN_PERIPHERAL_CGU__ + +/* CGU_CTL Masks */ +#define DF (1 << 0) +#define MSEL (0x7f << MSEL_P) +#define WIDLE (1 << WIDLE_P) +#define LOCK (1 << LOCK_P) + +#define DF_P 0 +#define MSEL_P 8 +#define WIDLE_P 30 +#define LOCK_P 31 +#define MSEL_MASK 0x7F00 +#define DF_MASK 0x1 + +/* CGU_STAT Masks */ +#define PLLEN (1 << 0) +#define PLLBP (1 << 1) +#define PLLLK (1 << 2) +#define CLKSALGN (1 << 3) +#define CCBF0EN (1 << 4) +#define CCBF1EN (1 << 5) +#define SCBF0EN (1 << 6) +#define SCBF1EN (1 << 7) +#define DCBFEN (1 << 8) +#define OCBFEN (1 << 9) +#define ADRERR (1 << 16) +#define LWERR (1 << 17) +#define DIVERR (1 << 18) +#define WDFMSERR (1 << 19) +#define WDIVERR (1 << 20) +#define PLLLKERR (1 << 21) + +/* CGU_DIV Masks */ +#define CSEL (0x1f << CSEL_P) +#define S0SEL (3 << S0SEL_P) +#define SYSSEL (0x1f << SYSSEL_P) +#define S1SEL (3 << S1SEL_P) +#define DSEL (0x1f << DSEL_P) +#define OSEL (0x7f << OSEL_P) +#define ALGN (1 << ALGN_P) +#define UPDT (1 << UPDT_P) +#define LOCK (1 << LOCK_P) + +#define CSEL_P 0 +#define S0SEL_P 5 +#define SYSSEL_P 8 +#define S1SEL_P 13 +#define DSEL_P 16 +#define OSEL_P 22 +#define ALGN_P 29 +#define UPDT_P 30 +#define LOCK_P 31 + +/* CGU_CLKOUTSEL Masks */ +#define CLKOUTSEL (0xf << 0) +#define USBCLKSEL (0x3f << 16) +#define LOCK (1 << LOCK_P) + +#define LOCK_P 31 + +#define CLKOUTSEL_CLKIN 0x0 +#define CLKOUTSEL_CCLK 0x1 +#define CLKOUTSEL_SYSCLK 0x2 +#define CLKOUTSEL_SCLK0 0x3 +#define CLKOUTSEL_SCLK1 0x4 +#define CLKOUTSEL_DCLK 0x5 +#define CLKOUTSEL_USB_PLL 0x6 +#define CLKOUTSEL_OUTCLK 0x7 +#define CLKOUTSEL_USB_CLKIN 0x8 +#define CLKOUTSEL_WDOG 0x9 +#define CLKOUTSEL_PMON 0xA +#define CLKOUTSEL_GND 0xB + +#endif diff --git a/arch/blackfin/include/asm/mach-common/bits/dde.h b/arch/blackfin/include/asm/mach-common/bits/dde.h new file mode 100644 index 0000000000..f7b0bb90f3 --- /dev/null +++ b/arch/blackfin/include/asm/mach-common/bits/dde.h @@ -0,0 +1,88 @@ +/* + * Distributed DMA Engine (DDE) Masks + */ + +#ifndef __BFIN_PERIPHERAL_DDE__ +#define __BFIN_PERIPHERAL_DDE__ + +/* DMA_CONFIG Masks */ +#define DMAEN (1 << DMAEN_P) /* DMA Channel Enable */ +#define WNR (1 << WNR_P) /* Channel Direction (W/R*) */ +#define SYNC (1 << SYNC_P) /* Sync Work Unit Transitions */ +#define CADDR (1 << CADDR_P) /* Use Current Address */ +#define PSIZE (7 << PSIZE_P) /* Peripheral Word Size */ +#define PSIZE_1 (0 << PSIZE_P) +#define PSIZE_2 (1 << PSIZE_P) +#define PSIZE_4 (2 << PSIZE_P) +#define PSIZE_8 (3 << PSIZE_P) +#define MSIZE (7 << MSIZE_P) /* Memory Transfer Size */ +#define MSIZE_1 (0 << MSIZE_P) +#define MSIZE_2 (1 << MSIZE_P) +#define MSIZE_4 (2 << MSIZE_P) +#define MSIZE_8 (3 << MSIZE_P) +#define MSIZE_16 (4 << MSIZE_P) +#define MSIZE_32 (5 << MSIZE_P) +#define FLOW (7 << FLOW_P) /* Next Operation */ +#define FLOW_STOP (0 << FLOW_P) /* Stop Mode */ +#define FLOW_AUTO (1 << FLOW_P) /* Autobuffer Mode */ +#define FLOW_DSCL (4 << FLOW_P) /* Descriptor List */ +#define FLOW_DSCA (5 << FLOW_P) /* Descriptor Array */ +#define FLOW_DSDL (6 << FLOW_P) /* Descriptor On Demand List */ +#define FLOW_DSDA (7 << FLOW_P) /* Descriptor On Demand Array */ +#define NDSIZE (7 << NDSIZE_P) /* Next Descriptor Set Size */ +#define NDSIZE_1 (0 << NDSIZE_P) +#define NDSIZE_2 (1 << NDSIZE_P) +#define NDSIZE_3 (2 << NDSIZE_P) +#define NDSIZE_4 (3 << NDSIZE_P) +#define NDSIZE_5 (4 << NDSIZE_P) +#define NDSIZE_6 (5 << NDSIZE_P) +#define NDSIZE_7 (6 << NDSIZE_P) +#define DI_EN_X (1 << INT_P) +#define DI_EN_Y (2 << INT_P) +#define DI_EN_P (3 << INT_P) +#define DI_EN (DI_EN_X) +#define DI_XCOUNT_EN (1 << INT_P) /* xcount expires interrupt */ +#define TRIG (3 << TRIG_P) /* Generate Trigger */ +#define TOVEN (1 << TOVEN_P) +#define DESCIDCPY (1 << DESCIDCPY_P) +#define TWOD (1 << TWOD_P) +#define PDRF (1 << PDRF_P) + +#define DMAEN_P 0 +#define WNR_P 1 +#define SYNC_P 2 +#define CADDR_P 3 +#define PSIZE_P 4 +#define MSIZE_P 8 +#define FLOW_P 12 +#define TWAIT_P 15 +#define NDSIZE_P 16 +#define INT_P 20 +#define TRIG_P 22 +#define TOVEN_P 24 +#define DESCIDCPY_P 25 +#define TWOD_P 26 +#define PDRF_P 28 + +/* DMA_STATUS Masks */ +#define DMA_DONE (1 << DMA_DONE_P) /* Work Unit/Row Done */ +#define DMA_ERR (1 << DMA_ERR_P) /* Error Interrupt */ +#define DMA_PIRQ (1 << DMA_PIRQ_P) /* Peri Intr Request */ +#define DMA_ERRC (7 << DMA_ERRC_P) /* Error Cause */ +#define DMA_RUN (7 << DMA_RUN_P) /* Run Status */ +#define DMA_PBWIDTH (3 << DMA_PBWIDTH_P) /* Peri Bus Width */ +#define DMA_MBWIDTH (3 << DMA_MBWIDTH_P) /* Memory Bus Width */ +#define DMA_FIFOFILL (7 << DMA_FIFOFILL_P) /* FIFO Fill Status */ +#define DMA_TWAIT (1 << DMA_TWAIT_P) /* Trigger Wait Stat */ + +#define DMA_DONE_P 0 +#define DMA_ERR_P 1 +#define DMA_PIRQ_P 2 +#define DMA_ERRC_P 4 +#define DMA_RUN_P 8 +#define DMA_PBWIDTH_P 12 +#define DMA_MBWIDTH_P 14 +#define DMA_FIFOFILL_P 16 +#define DMA_TWAIT_P 20 + +#endif diff --git a/arch/blackfin/include/asm/mach-common/bits/mpu.h b/arch/blackfin/include/asm/mach-common/bits/mpu.h index 39998f82aa..cfde2364d7 100644 --- a/arch/blackfin/include/asm/mach-common/bits/mpu.h +++ b/arch/blackfin/include/asm/mach-common/bits/mpu.h @@ -70,7 +70,11 @@ #define PAGE_SIZE_4KB 0x00010000 /* 4 KB page size */ #define PAGE_SIZE_1MB 0x00020000 /* 1 MB page size */ #define PAGE_SIZE_4MB 0x00030000 /* 4 MB page size */ -#define PAGE_SIZE_MASK 0x00030000 /* the bits for the page_size field */ +#define PAGE_SIZE_16KB 0x00040000 /* 16 KB page size */ +#define PAGE_SIZE_64KB 0x00050000 /* 64 KB page size */ +#define PAGE_SIZE_16MB 0x00060000 /* 16 MB page size */ +#define PAGE_SIZE_64MB 0x00070000 /* 64 MB page size */ +#define PAGE_SIZE_MASK 0x00070000 /* page_size field mask */ #define PAGE_SIZE_SHIFT 16 #define CPLB_L1SRAM 0x00000020 /* 0=SRAM mapped in L1, 0=SRAM not mapped to L1 */ #define CPLB_PORTPRIO 0x00000200 /* 0=low priority port, 1= high priority port */ diff --git a/arch/blackfin/include/asm/mach-common/bits/pll.h b/arch/blackfin/include/asm/mach-common/bits/pll.h index 9009f26401..fe0ba0f543 100644 --- a/arch/blackfin/include/asm/mach-common/bits/pll.h +++ b/arch/blackfin/include/asm/mach-common/bits/pll.h @@ -16,6 +16,8 @@ #define MSEL 0x7E00 /* Multiplier Select For CCLK/VCO Factors */ #define SPORT_HYST 0x8000 /* Enable Additional Hysteresis on SPORT Input Pins */ +#define MSEL_P 9 + /* PLL_DIV Masks */ #define SSEL 0x000F /* System Select */ #define CSEL 0x0030 /* Core Select */ @@ -29,6 +31,9 @@ #define CCLK_DIV4 CSEL_DIV4 #define CCLK_DIV8 CSEL_DIV8 +#define SSEL_P 0 +#define CSEL_P 4 + /* PLL_STAT Masks */ #define ACTIVE_PLLENABLED 0x0001 /* Processor In Active Mode With PLL Enabled */ #define FULL_ON 0x0002 /* Processor In Full On Mode */ -- cgit v1.2.3 From a2979dcdbeb39a01dc888090d2c736c2ad3f548d Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 16 Aug 2012 11:56:14 +0800 Subject: blackfin: bf60x: Port blackfin core architecture code to boot on bf60x. Set up clocks, DDR controller, Nor flash controller, reboot, serial port. Add new SPI boot modes. Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang --- arch/blackfin/cpu/cpu.c | 4 +- arch/blackfin/cpu/initcode.c | 325 +++++++++++++++++++++++++++++++-- arch/blackfin/cpu/initcode.h | 52 ++++++ arch/blackfin/cpu/reset.c | 6 + arch/blackfin/include/asm/config-pre.h | 4 + arch/blackfin/lib/board.c | 6 + arch/blackfin/lib/clocks.c | 112 +++++++++--- common/cmd_reginfo.c | 19 +- 8 files changed, 486 insertions(+), 42 deletions(-) diff --git a/arch/blackfin/cpu/cpu.c b/arch/blackfin/cpu/cpu.c index 6a0bcca9f9..b9fdb078bd 100644 --- a/arch/blackfin/cpu/cpu.c +++ b/arch/blackfin/cpu/cpu.c @@ -68,7 +68,9 @@ void cpu_init_f(ulong bootflag, ulong loaded_from_ldr) /* Reset upon a double exception rather than just hanging. * Do not do bfin_read on SWRST as that will reset status bits. */ +# ifdef SWRST bfin_write_SWRST(DOUBLE_FAULT); +# endif #endif serial_early_puts("Board init flash\n"); @@ -92,7 +94,7 @@ int irq_init(void) #elif defined(SICA_IMASK0) bfin_write_SICA_IMASK0(0); bfin_write_SICA_IMASK1(0); -#else +#elif defined(SIC_IMASK) bfin_write_SIC_IMASK(0); #endif /* Set up a dummy NMI handler if needed. */ diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index fb3a101c79..a717148651 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -15,20 +15,141 @@ #include #include #include -#include -#include -#include #define BUG() while (1) { asm volatile("emuexcpt;"); } #include "serial.h" +#ifndef __ADSPBF60x__ +#include +#include +#else /* __ADSPBF60x__ */ +#include + +#define CONFIG_BFIN_GET_DCLK_M \ + ((CONFIG_CLKIN_HZ*CONFIG_VCO_MULT)/(CONFIG_DCLK_DIV*1000000)) + +#ifndef CONFIG_DMC_DDRCFG +#if ((CONFIG_BFIN_GET_DCLK_M != 125) && \ + (CONFIG_BFIN_GET_DCLK_M != 133) && \ + (CONFIG_BFIN_GET_DCLK_M != 150) && \ + (CONFIG_BFIN_GET_DCLK_M != 166) && \ + (CONFIG_BFIN_GET_DCLK_M != 200) && \ + (CONFIG_BFIN_GET_DCLK_M != 225) && \ + (CONFIG_BFIN_GET_DCLK_M != 250)) +#error "DDR2 CLK must be in (125, 133, 150, 166, 200, 225, 250)MHz" +#endif +#endif + +/* DMC control bits */ +#define SRREQ 0x8 + +/* DMC status bits */ +#define IDLE 0x1 +#define MEMINITDONE 0x4 +#define SRACK 0x8 +#define PDACK 0x10 +#define DPDACK 0x20 +#define DLLCALDONE 0x2000 +#define PENDREF 0xF0000 +#define PHYRDPHASE 0xF00000 +#define PHYRDPHASE_OFFSET 20 + +/* DMC DLL control bits */ +#define DLLCALRDCNT 0xFF +#define DATACYC_OFFSET 8 + +struct ddr_config { + u32 ddr_clk; + u32 dmc_ddrctl; + u32 dmc_ddrcfg; + u32 dmc_ddrtr0; + u32 dmc_ddrtr1; + u32 dmc_ddrtr2; + u32 dmc_ddrmr; + u32 dmc_ddrmr1; +}; + +static struct ddr_config ddr_config_table[] = { + [0] = { + .ddr_clk = 125, /* 125MHz */ + .dmc_ddrctl = 0x00000904, + .dmc_ddrcfg = 0x00000422, + .dmc_ddrtr0 = 0x20705212, + .dmc_ddrtr1 = 0x201003CF, + .dmc_ddrtr2 = 0x00320107, + .dmc_ddrmr = 0x00000422, + .dmc_ddrmr1 = 0x4, + }, + [1] = { + .ddr_clk = 133, /* 133MHz */ + .dmc_ddrctl = 0x00000904, + .dmc_ddrcfg = 0x00000422, + .dmc_ddrtr0 = 0x20806313, + .dmc_ddrtr1 = 0x2013040D, + .dmc_ddrtr2 = 0x00320108, + .dmc_ddrmr = 0x00000632, + .dmc_ddrmr1 = 0x4, + }, + [2] = { + .ddr_clk = 150, /* 150MHz */ + .dmc_ddrctl = 0x00000904, + .dmc_ddrcfg = 0x00000422, + .dmc_ddrtr0 = 0x20A07323, + .dmc_ddrtr1 = 0x20160492, + .dmc_ddrtr2 = 0x00320209, + .dmc_ddrmr = 0x00000632, + .dmc_ddrmr1 = 0x4, + }, + [3] = { + .ddr_clk = 166, /* 166MHz */ + .dmc_ddrctl = 0x00000904, + .dmc_ddrcfg = 0x00000422, + .dmc_ddrtr0 = 0x20A07323, + .dmc_ddrtr1 = 0x2016050E, + .dmc_ddrtr2 = 0x00320209, + .dmc_ddrmr = 0x00000632, + .dmc_ddrmr1 = 0x4, + }, + [4] = { + .ddr_clk = 200, /* 200MHz */ + .dmc_ddrctl = 0x00000904, + .dmc_ddrcfg = 0x00000422, + .dmc_ddrtr0 = 0x20a07323, + .dmc_ddrtr1 = 0x2016050f, + .dmc_ddrtr2 = 0x00320509, + .dmc_ddrmr = 0x00000632, + .dmc_ddrmr1 = 0x4, + }, + [5] = { + .ddr_clk = 225, /* 225MHz */ + .dmc_ddrctl = 0x00000904, + .dmc_ddrcfg = 0x00000422, + .dmc_ddrtr0 = 0x20E0A424, + .dmc_ddrtr1 = 0x302006DB, + .dmc_ddrtr2 = 0x0032020D, + .dmc_ddrmr = 0x00000842, + .dmc_ddrmr1 = 0x4, + }, + [6] = { + .ddr_clk = 250, /* 250MHz */ + .dmc_ddrctl = 0x00000904, + .dmc_ddrcfg = 0x00000422, + .dmc_ddrtr0 = 0x20E0A424, + .dmc_ddrtr1 = 0x3020079E, + .dmc_ddrtr2 = 0x0032050D, + .dmc_ddrmr = 0x00000842, + .dmc_ddrmr1 = 0x4, + }, +}; +#endif /* __ADSPBF60x__ */ + __attribute__((always_inline)) static inline void serial_init(void) { - uint32_t uart_base = UART_DLL; + uint32_t uart_base = UART_BASE; -#ifdef __ADSPBF54x__ +#if defined(__ADSPBF54x__) || defined(__ADSPBF60x__) # ifdef BFIN_BOOT_UART_USE_RTS # define BFIN_UART_USE_RTS 1 # else @@ -38,7 +159,12 @@ static inline void serial_init(void) size_t i; /* force RTS rather than relying on auto RTS */ +#if BFIN_UART_HW_VER < 4 bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) | FCPOL); +#else + bfin_write32(&pUART->control, bfin_read32(&pUART->control) | + FCPOL); +#endif /* Wait for the line to clear up. We cannot rely on UART * registers as none of them reflect the status of the RSR. @@ -68,13 +194,14 @@ static inline void serial_init(void) #endif if (BFIN_DEBUG_EARLY_SERIAL) { - int ucen = bfin_read16(&pUART->gctl) & UCEN; + int enabled = serial_early_enabled(uart_base); + serial_early_init(uart_base); /* If the UART is off, that means we need to program * the baud rate ourselves initially. */ - if (ucen != UCEN) + if (!enabled) serial_early_set_baud(uart_base, CONFIG_BAUDRATE); } } @@ -82,12 +209,17 @@ static inline void serial_init(void) __attribute__((always_inline)) static inline void serial_deinit(void) { -#ifdef __ADSPBF54x__ - uint32_t uart_base = UART_DLL; +#if defined(__ADSPBF54x__) || defined(__ADSPBF60x__) + uint32_t uart_base = UART_BASE; if (BFIN_UART_USE_RTS && CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { /* clear forced RTS rather than relying on auto RTS */ +#if BFIN_UART_HW_VER < 4 bfin_write16(&pUART->mcr, bfin_read16(&pUART->mcr) & ~FCPOL); +#else + bfin_write32(&pUART->control, bfin_read32(&pUART->control) & + ~FCPOL); +#endif } #endif } @@ -95,7 +227,7 @@ static inline void serial_deinit(void) __attribute__((always_inline)) static inline void serial_putc(char c) { - uint32_t uart_base = UART_DLL; + uint32_t uart_base = UART_BASE; if (!BFIN_DEBUG_EARLY_SERIAL) return; @@ -103,9 +235,9 @@ static inline void serial_putc(char c) if (c == '\n') serial_putc('\r'); - bfin_write16(&pUART->thr, c); + bfin_write(&pUART->thr, c); - while (!(bfin_read16(&pUART->lsr) & TEMT)) + while (!(_lsr_read(pUART) & TEMT)) continue; } @@ -152,6 +284,24 @@ program_nmi_handler(void) # define bfin_write_SPI_BAUD bfin_write_SPI0_BAUD #endif +#ifdef __ADSPBF60x__ + +#ifndef CONFIG_CGU_CTL_VAL +# define CONFIG_CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CONFIG_CLKIN_HALF) +#endif + +#ifndef CONFIG_CGU_DIV_VAL +# define CONFIG_CGU_DIV_VAL \ + ((CONFIG_CCLK_DIV << CSEL_P) | \ + (CONFIG_SCLK0_DIV << S0SEL_P) | \ + (CONFIG_SCLK_DIV << SYSSEL_P) | \ + (CONFIG_SCLK1_DIV << S1SEL_P) | \ + (CONFIG_DCLK_DIV << DSEL_P) | \ + (CONFIG_OCLK_DIV << OSEL_P)) +#endif + +#else /* __ADSPBF60x__ */ + /* PLL_DIV defines */ #ifndef CONFIG_PLL_DIV_VAL # if (CONFIG_CCLK_DIV == 1) @@ -275,6 +425,8 @@ program_nmi_handler(void) # endif #endif +#endif /* __ADSPBF60x__ */ + __attribute__((always_inline)) static inline void program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) { @@ -283,8 +435,14 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) /* Save the clock pieces that are used in baud rate calculation */ if (BFIN_DEBUG_EARLY_SERIAL || CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { serial_putc('b'); +#ifdef __ADSPBF60x__ + *sdivB = bfin_read_CGU_DIV(); + *sdivB = ((*sdivB >> 8) & 0x1f) * ((*sdivB >> 5) & 0x7); + *vcoB = (bfin_read_CGU_CTL() >> 8) & 0x7f; +#else *sdivB = bfin_read_PLL_DIV() & 0xf; *vcoB = (bfin_read_PLL_CTL() >> 9) & 0x3f; +#endif *divB = serial_early_get_div(); serial_putc('c'); } @@ -316,6 +474,7 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) * boot. Once we switch over to u-boot's SPI flash driver, we'll * increase the speed appropriately. */ +#ifdef SPI_BAUD if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) { serial_putc('h'); if (BOOTROM_SUPPORTS_SPI_FAST_READ && CONFIG_SPI_BAUD_INITBLOCK < 4) @@ -323,6 +482,7 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) bfin_write_SPI_BAUD(CONFIG_SPI_BAUD_INITBLOCK); serial_putc('i'); } +#endif serial_putc('j'); } @@ -335,6 +495,10 @@ maybe_self_refresh(ADI_BOOT_DATA *bs) if (!CONFIG_MEM_SIZE) return false; +#ifdef __ADSPBF60x__ + +#else /* __ADSPBF60x__ */ + /* If external memory is enabled, put it into self refresh first. */ #if defined(EBIU_RSTCTL) if (bfin_read_EBIU_RSTCTL() & DDR_SRESET) { @@ -350,6 +514,7 @@ maybe_self_refresh(ADI_BOOT_DATA *bs) } #endif +#endif /* __ADSPBF60x__ */ serial_putc('c'); return false; @@ -362,6 +527,37 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) serial_putc('a'); +#ifdef __ADSPBF60x__ + if (bfin_read_DMC0_STAT() & MEMINITDONE) { + bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() | SRREQ); + SSYNC(); + while (!(bfin_read_DMC0_STAT() & SRACK)) + continue; + } + + /* Don't set the same value of MSEL and DF to CGU_CTL */ + if ((bfin_read_CGU_CTL() & (MSEL_MASK | DF_MASK)) + != CONFIG_CGU_CTL_VAL) { + bfin_write_CGU_DIV(CONFIG_CGU_DIV_VAL); + bfin_write_CGU_CTL(CONFIG_CGU_CTL_VAL); + while ((bfin_read_CGU_STAT() & (CLKSALGN | PLLBP)) || + !(bfin_read_CGU_STAT() & PLLLK)) + continue; + } + + bfin_write_CGU_DIV(CONFIG_CGU_DIV_VAL | UPDT); + while (bfin_read_CGU_STAT() & CLKSALGN) + continue; + + if (bfin_read_DMC0_STAT() & MEMINITDONE) { + bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() & ~SRREQ); + SSYNC(); + while (bfin_read_DMC0_STAT() & SRACK) + continue; + } + +#else /* __ADSPBF60x__ */ + vr_ctl = bfin_read_VR_CTL(); serial_putc('b'); @@ -433,7 +629,7 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) #elif defined(SICA_IWR0) bfin_write_SICA_IWR0(1); bfin_write_SICA_IWR1(0); -#else +#elif defined(SIC_IWR) bfin_write_SIC_IWR(1); #endif @@ -482,13 +678,15 @@ program_clocks(ADI_BOOT_DATA *bs, bool put_into_srfs) #elif defined(SICA_IWR0) bfin_write_SICA_IWR0(-1); bfin_write_SICA_IWR1(-1); -#else +#elif defined(SIC_IWR) bfin_write_SIC_IWR(-1); #endif serial_putc('n'); } +#endif /* __ADSPBF60x__ */ + serial_putc('o'); return vr_ctl; @@ -505,16 +703,25 @@ update_serial_clocks(ADI_BOOT_DATA *bs, uint sdivB, uint divB, uint vcoB) * for dividing which means we'd generate a libgcc reference. */ if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_UART) { - serial_putc('b'); unsigned int sdivR, vcoR; - sdivR = bfin_read_PLL_DIV() & 0xf; - vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; int dividend = sdivB * divB * vcoR; int divisor = vcoB * sdivR; unsigned int quotient; + + serial_putc('b'); + +#ifdef __ADSPBF60x__ + sdivR = bfin_read_CGU_DIV(); + sdivR = ((sdivR >> 8) & 0x1f) * ((sdivR >> 5) & 0x7); + vcoR = (bfin_read_CGU_CTL() >> 8) & 0x7f; +#else + sdivR = bfin_read_PLL_DIV() & 0xf; + vcoR = (bfin_read_PLL_CTL() >> 9) & 0x3f; +#endif + for (quotient = 0; dividend > 0; ++quotient) dividend -= divisor; - serial_early_put_div(UART_DLL, quotient - ANOMALY_05000230); + serial_early_put_div(quotient - ANOMALY_05000230); serial_putc('c'); } @@ -531,6 +738,84 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs) serial_putc('b'); +#ifdef __ADSPBF60x__ + int dlldatacycle; + int dll_ctl; + int i = 0; + + if (CONFIG_BFIN_GET_DCLK_M == 125) + i = 0; + else if (CONFIG_BFIN_GET_DCLK_M == 133) + i = 1; + else if (CONFIG_BFIN_GET_DCLK_M == 150) + i = 2; + else if (CONFIG_BFIN_GET_DCLK_M == 166) + i = 3; + else if (CONFIG_BFIN_GET_DCLK_M == 200) + i = 4; + else if (CONFIG_BFIN_GET_DCLK_M == 225) + i = 5; + else if (CONFIG_BFIN_GET_DCLK_M == 250) + i = 6; + +#if 0 + for (i = 0; i < ARRAY_SIZE(ddr_config_table); i++) + if (CONFIG_BFIN_GET_DCLK_M == ddr_config_table[i].ddr_clk) + break; +#endif + +#ifndef CONFIG_DMC_DDRCFG + bfin_write_DMC0_CFG(ddr_config_table[i].dmc_ddrcfg); +#else + bfin_write_DMC0_CFG(CONFIG_DMC_DDRCFG); +#endif +#ifndef CONFIG_DMC_DDRTR0 + bfin_write_DMC0_TR0(ddr_config_table[i].dmc_ddrtr0); +#else + bfin_write_DMC0_TR0(CONFIG_DMC_DDRTR0); +#endif +#ifndef CONFIG_DMC_DDRTR1 + bfin_write_DMC0_TR1(ddr_config_table[i].dmc_ddrtr1); +#else + bfin_write_DMC0_TR1(CONFIG_DMC_DDRTR1); +#endif +#ifndef CONFIG_DMC_DDRTR2 + bfin_write_DMC0_TR2(ddr_config_table[i].dmc_ddrtr2); +#else + bfin_write_DMC0_TR2(CONFIG_DMC_DDRTR2); +#endif +#ifndef CONFIG_DMC_DDRMR + bfin_write_DMC0_MR(ddr_config_table[i].dmc_ddrmr); +#else + bfin_write_DMC0_MR(CONFIG_DMC_DDRMR); +#endif +#ifndef CONFIG_DMC_DDREMR1 + bfin_write_DMC0_EMR1(ddr_config_table[i].dmc_ddrmr1); +#else + bfin_write_DMC0_EMR1(CONFIG_DMC_DDREMR1); +#endif +#ifndef CONFIG_DMC_DDRCTL + bfin_write_DMC0_CTL(ddr_config_table[i].dmc_ddrctl); +#else + bfin_write_DMC0_CTL(CONFIG_DMC_DDRCTL); +#endif + + SSYNC(); + while (!(bfin_read_DMC0_STAT() & MEMINITDONE)) + continue; + + dlldatacycle = (bfin_read_DMC0_STAT() & PHYRDPHASE) >> + PHYRDPHASE_OFFSET; + dll_ctl = bfin_read_DMC0_DLLCTL(); + dll_ctl &= 0x0ff; + bfin_write_DMC0_DLLCTL(dll_ctl | (dlldatacycle << DATACYC_OFFSET)); + + SSYNC(); + while (!(bfin_read_DMC0_STAT() & DLLCALDONE)) + continue; + serial_putc('!'); +#else /* __ADSPBF60x__ */ + /* Program the external memory controller before we come out of * self-refresh. This only works with our SDRAM controller. */ @@ -583,6 +868,7 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs) # endif #endif +#endif /* __ADSPBF60x__ */ serial_putc('e'); } @@ -606,7 +892,8 @@ check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs) */ if (ANOMALY_05000307 || vr_ctl & 0x8000) { uint32_t *hibernate_magic = 0; - __builtin_bfin_ssync(); /* make sure memory controller is done */ + + SSYNC(); if (hibernate_magic[0] == 0xDEADBEEF) { serial_putc('c'); bfin_write_EVT15(hibernate_magic[1]); diff --git a/arch/blackfin/cpu/initcode.h b/arch/blackfin/cpu/initcode.h index e0aad6de0f..1fec7f3d85 100644 --- a/arch/blackfin/cpu/initcode.h +++ b/arch/blackfin/cpu/initcode.h @@ -15,6 +15,8 @@ # define serial_putc(c) #endif +#ifndef __ADSPBF60x__ + #ifndef CONFIG_EBIU_RSTCTL_VAL # define CONFIG_EBIU_RSTCTL_VAL 0 /* only MDDRENABLE is useful */ #endif @@ -30,6 +32,8 @@ # error invalid EBIU_DDRQUE value: must not set reserved bits #endif +#endif /* __ADSPBF60x__ */ + __attribute__((always_inline)) static inline void program_async_controller(ADI_BOOT_DATA *bs) { @@ -45,10 +49,13 @@ program_async_controller(ADI_BOOT_DATA *bs) serial_putc('a'); +#ifdef __ADSPBF60x__ /* Program the async banks controller. */ +#ifdef EBIU_AMGCTL bfin_write_EBIU_AMBCTL0(CONFIG_EBIU_AMBCTL0_VAL); bfin_write_EBIU_AMBCTL1(CONFIG_EBIU_AMBCTL1_VAL); bfin_write_EBIU_AMGCTL(CONFIG_EBIU_AMGCTL_VAL); +#endif serial_putc('b'); @@ -66,6 +73,51 @@ program_async_controller(ADI_BOOT_DATA *bs) #endif serial_putc('c'); + +#else /* __ADSPBF60x__ */ + /* Program the static memory controller. */ +# ifdef CONFIG_SMC_GCTL_VAL + bfin_write_SMC_GCTL(CONFIG_SMC_GCTL_VAL); +# endif +# ifdef CONFIG_SMC_B0CTL_VAL + bfin_write_SMC_B0CTL(CONFIG_SMC_B0CTL_VAL); +# endif +# ifdef CONFIG_SMC_B0TIM_VAL + bfin_write_SMC_B0TIM(CONFIG_SMC_B0TIM_VAL); +# endif +# ifdef CONFIG_SMC_B0ETIM_VAL + bfin_write_SMC_B0ETIM(CONFIG_SMC_B0ETIM_VAL); +# endif +# ifdef CONFIG_SMC_B1CTL_VAL + bfin_write_SMC_B1CTL(CONFIG_SMC_B1CTL_VAL); +# endif +# ifdef CONFIG_SMC_B1TIM_VAL + bfin_write_SMC_B1TIM(CONFIG_SMC_B1TIM_VAL); +# endif +# ifdef CONFIG_SMC_B1ETIM_VAL + bfin_write_SMC_B1ETIM(CONFIG_SMC_B1ETIM_VAL); +# endif +# ifdef CONFIG_SMC_B2CTL_VAL + bfin_write_SMC_B2CTL(CONFIG_SMC_B2CTL_VAL); +# endif +# ifdef CONFIG_SMC_B2TIM_VAL + bfin_write_SMC_B2TIM(CONFIG_SMC_B2TIM_VAL); +# endif +# ifdef CONFIG_SMC_B2ETIM_VAL + bfin_write_SMC_B2ETIM(CONFIG_SMC_B2ETIM_VAL); +# endif +# ifdef CONFIG_SMC_B3CTL_VAL + bfin_write_SMC_B3CTL(CONFIG_SMC_B3CTL_VAL); +# endif +# ifdef CONFIG_SMC_B3TIM_VAL + bfin_write_SMC_B3TIM(CONFIG_SMC_B3TIM_VAL); +# endif +# ifdef CONFIG_SMC_B3ETIM_VAL + bfin_write_SMC_B3ETIM(CONFIG_SMC_B3ETIM_VAL); +# endif + +#endif + serial_putc('d'); } #endif diff --git a/arch/blackfin/cpu/reset.c b/arch/blackfin/cpu/reset.c index ff39035de2..b6718d3bb5 100644 --- a/arch/blackfin/cpu/reset.c +++ b/arch/blackfin/cpu/reset.c @@ -23,6 +23,7 @@ __attribute__ ((__l1_text__, __noreturn__)) static void bfin_reset(void) { +#ifdef SWRST /* Wait for completion of "system" events such as cache line * line fills so that we avoid infinite stalls later on as * much as possible. This code is in L1, so it won't trigger @@ -66,10 +67,15 @@ static void bfin_reset(void) : "a" (15 * 1) : "LC1", "LB1", "LT1" ); +#endif while (1) +#if defined(__ADSPBF60x__) + bfin_write_RCU0_CTL(0x1); +#else /* Issue core reset */ asm("raise 1"); +#endif } /* We need to trampoline ourselves up into L1 since our linker diff --git a/arch/blackfin/include/asm/config-pre.h b/arch/blackfin/include/asm/config-pre.h index be5687ce6f..d0fd537d88 100644 --- a/arch/blackfin/include/asm/config-pre.h +++ b/arch/blackfin/include/asm/config-pre.h @@ -29,6 +29,8 @@ #define BFIN_BOOT_16HOST_DMA 11 /* boot ldr from 16-bit host dma */ #define BFIN_BOOT_8HOST_DMA 12 /* boot ldr from 8-bit host dma */ #define BFIN_BOOT_NAND 13 /* boot ldr from nand flash */ +#define BFIN_BOOT_RSI_MASTER 14 /* boot ldr from rsi */ +#define BFIN_BOOT_LP_SLAVE 15 /* boot ldr from link port */ #ifndef __ASSEMBLY__ static inline const char *get_bfin_boot_mode(int bfin_boot) @@ -47,6 +49,8 @@ static inline const char *get_bfin_boot_mode(int bfin_boot) case BFIN_BOOT_16HOST_DMA: return "16bit dma"; case BFIN_BOOT_8HOST_DMA: return "8bit dma"; case BFIN_BOOT_NAND: return "nand flash"; + case BFIN_BOOT_RSI_MASTER: return "rsi master"; + case BFIN_BOOT_LP_SLAVE: return "link port slave"; default: return "INVALID"; } } diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 9fbbea0d9b..098f685ccb 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -295,7 +295,13 @@ void board_init_f(ulong bootflag) printf("Clock: VCO: %s MHz, ", strmhz(buf, get_vco())); printf("Core: %s MHz, ", strmhz(buf, get_cclk())); +#if defined(__ADSPBF60x__) + printf("System0: %s MHz, ", strmhz(buf, get_sclk0())); + printf("System1: %s MHz, ", strmhz(buf, get_sclk1())); + printf("Dclk: %s MHz\n", strmhz(buf, get_dclk())); +#else printf("System: %s MHz\n", strmhz(buf, get_sclk())); +#endif if (CONFIG_MEM_SIZE) { printf("RAM: "); diff --git a/arch/blackfin/lib/clocks.c b/arch/blackfin/lib/clocks.c index 0be395bb30..d852f5ebed 100644 --- a/arch/blackfin/lib/clocks.c +++ b/arch/blackfin/lib/clocks.c @@ -9,69 +9,139 @@ #include #include +#ifdef PLL_CTL +# include +# define pll_is_bypassed() (bfin_read_PLL_STAT() & DF) +#else +# include +# define pll_is_bypassed() (bfin_read_CGU_STAT() & PLLBP) +# define bfin_read_PLL_CTL() bfin_read_CGU_CTL() +# define bfin_read_PLL_DIV() bfin_read_CGU_DIV() +#endif + /* Get the voltage input multiplier */ -static u_long cached_vco_pll_ctl, cached_vco; u_long get_vco(void) { - u_long msel; + static u_long cached_vco_pll_ctl, cached_vco; + + u_long msel, pll_ctl; - u_long pll_ctl = bfin_read_PLL_CTL(); + pll_ctl = bfin_read_PLL_CTL(); if (pll_ctl == cached_vco_pll_ctl) return cached_vco; else cached_vco_pll_ctl = pll_ctl; - msel = (pll_ctl >> 9) & 0x3F; + msel = (pll_ctl & MSEL) >> MSEL_P; if (0 == msel) - msel = 64; + msel = (MSEL >> MSEL_P) + 1; cached_vco = CONFIG_CLKIN_HZ; - cached_vco >>= (1 & pll_ctl); /* DF bit */ + cached_vco >>= (pll_ctl & DF); cached_vco *= msel; return cached_vco; } /* Get the Core clock */ -static u_long cached_cclk_pll_div, cached_cclk; u_long get_cclk(void) { - u_long csel, ssel; + static u_long cached_cclk_pll_div, cached_cclk; + u_long div, csel, ssel; - if (bfin_read_PLL_STAT() & 0x1) + if (pll_is_bypassed()) return CONFIG_CLKIN_HZ; - ssel = bfin_read_PLL_DIV(); - if (ssel == cached_cclk_pll_div) + div = bfin_read_PLL_DIV(); + if (div == cached_cclk_pll_div) return cached_cclk; else - cached_cclk_pll_div = ssel; + cached_cclk_pll_div = div; - csel = ((ssel >> 4) & 0x03); - ssel &= 0xf; + csel = (div & CSEL) >> CSEL_P; +#ifndef CGU_DIV + ssel = (div & SSEL) >> SSEL_P; if (ssel && ssel < (1 << csel)) /* SCLK > CCLK */ cached_cclk = get_vco() / ssel; else cached_cclk = get_vco() >> csel; +#else + cached_cclk = get_vco() / csel; +#endif return cached_cclk; } /* Get the System clock */ +#ifdef CGU_DIV + static u_long cached_sclk_pll_div, cached_sclk; +static u_long cached_sclk0, cached_sclk1, cached_dclk; +static u_long _get_sclk(u_long *cache) +{ + u_long div, ssel; + + if (pll_is_bypassed()) + return CONFIG_CLKIN_HZ; + + div = bfin_read_PLL_DIV(); + if (div == cached_sclk_pll_div) + return *cache; + else + cached_sclk_pll_div = div; + + ssel = (div & SYSSEL) >> SYSSEL_P; + cached_sclk = get_vco() / ssel; + + ssel = (div & S0SEL) >> S0SEL_P; + cached_sclk0 = cached_sclk / ssel; + + ssel = (div & S1SEL) >> S1SEL_P; + cached_sclk1 = cached_sclk / ssel; + + ssel = (div & DSEL) >> DSEL_P; + cached_dclk = get_vco() / ssel; + + return *cache; +} + u_long get_sclk(void) { - u_long ssel; + return _get_sclk(&cached_sclk); +} + +u_long get_sclk0(void) +{ + return _get_sclk(&cached_sclk0); +} + +u_long get_sclk1(void) +{ + return _get_sclk(&cached_sclk1); +} + +u_long get_dclk(void) +{ + return _get_sclk(&cached_dclk); +} +#else + +u_long get_sclk(void) +{ + static u_long cached_sclk_pll_div, cached_sclk; + u_long div, ssel; - if (bfin_read_PLL_STAT() & 0x1) + if (pll_is_bypassed()) return CONFIG_CLKIN_HZ; - ssel = bfin_read_PLL_DIV(); - if (ssel == cached_sclk_pll_div) + div = bfin_read_PLL_DIV(); + if (div == cached_sclk_pll_div) return cached_sclk; else - cached_sclk_pll_div = ssel; - - ssel &= 0xf; + cached_sclk_pll_div = div; + ssel = (div & SSEL) >> SSEL_P; cached_sclk = get_vco() / ssel; + return cached_sclk; } + +#endif diff --git a/common/cmd_reginfo.c b/common/cmd_reginfo.c index 08a6563448..b591bd3774 100644 --- a/common/cmd_reginfo.c +++ b/common/cmd_reginfo.c @@ -191,7 +191,7 @@ static int do_reginfo(cmd_tbl_t *cmdtp, int flag, int argc, #elif defined(CONFIG_BLACKFIN) puts("\nSystem Configuration registers\n"); - +#ifndef __ADSPBF60x__ puts("\nPLL Registers\n"); printf("\tPLL_DIV: 0x%04x PLL_CTL: 0x%04x\n", bfin_read_PLL_DIV(), bfin_read_PLL_CTL()); @@ -227,7 +227,24 @@ static int do_reginfo(cmd_tbl_t *cmdtp, int flag, int argc, printf("\tEBIU_SDSTAT: 0x%04x EBIU_SDGCTL: 0x%08x\n", bfin_read_EBIU_SDSTAT(), bfin_read_EBIU_SDGCTL()); # endif +#else + puts("\nCGU Registers\n"); + printf("\tCGU_DIV: 0x%08x CGU_CTL: 0x%08x\n", + bfin_read_CGU_DIV(), bfin_read_CGU_CTL()); + printf("\tCGU_STAT: 0x%08x CGU_LOCKCNT: 0x%08x\n", + bfin_read_CGU_STAT(), bfin_read_CGU_CLKOUTSEL()); + puts("\nSMC DDR Registers\n"); + printf("\tDDR_CFG: 0x%08x DDR_TR0: 0x%08x\n", + bfin_read_DMC0_CFG(), bfin_read_DMC0_TR0()); + printf("\tDDR_TR1: 0x%08x DDR_TR2: 0x%08x\n", + bfin_read_DMC0_TR1(), bfin_read_DMC0_TR2()); + printf("\tDDR_MR: 0x%08x DDR_EMR1: 0x%08x\n", + bfin_read_DMC0_MR(), bfin_read_DMC0_EMR1()); + printf("\tDDR_CTL: 0x%08x DDR_STAT: 0x%08x\n", + bfin_read_DMC0_CTL(), bfin_read_DMC0_STAT()); + printf("\tDDR_DLLCTL:0x%08x\n", bfin_read_DMC0_DLLCTL()); +#endif #endif /* CONFIG_BLACKFIN */ return 0; -- cgit v1.2.3 From a12c51f640c4a28899a6215e938fd01058f06831 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 16 Aug 2012 11:16:02 +0800 Subject: blackfin: bf60x: add serial support Add serial for bf60x. Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang --- arch/blackfin/cpu/serial.c | 81 +++-- arch/blackfin/cpu/serial.h | 222 +------------ arch/blackfin/cpu/serial1.h | 348 +++++++++++++++++++++ arch/blackfin/cpu/serial4.h | 161 ++++++++++ arch/blackfin/include/asm/mach-bf533/BF531_def.h | 1 + arch/blackfin/include/asm/mach-bf561/BF561_def.h | 1 + arch/blackfin/include/asm/mach-common/bits/uart4.h | 66 ++++ 7 files changed, 642 insertions(+), 238 deletions(-) create mode 100644 arch/blackfin/cpu/serial1.h create mode 100644 arch/blackfin/cpu/serial4.h create mode 100644 arch/blackfin/include/asm/mach-common/bits/uart4.h diff --git a/arch/blackfin/cpu/serial.c b/arch/blackfin/cpu/serial.c index 64340ec67d..9847e9f2c5 100644 --- a/arch/blackfin/cpu/serial.c +++ b/arch/blackfin/cpu/serial.c @@ -43,7 +43,6 @@ #include #include #include -#include DECLARE_GLOBAL_DATA_PTR; @@ -52,8 +51,8 @@ DECLARE_GLOBAL_DATA_PTR; #include "serial.h" #ifdef CONFIG_DEBUG_SERIAL -static uint16_t cached_lsr[256]; -static uint16_t cached_rbr[256]; +static uart_lsr_t cached_lsr[256]; +static uart_lsr_t cached_rbr[256]; static size_t cache_count; /* The LSR is read-to-clear on some parts, so we have to make sure status @@ -61,10 +60,10 @@ static size_t cache_count; * works around anomaly 05000099 at the same time by keeping a cumulative * tally of all the status bits. */ -static uint16_t uart_lsr_save; -static uint16_t uart_lsr_read(uint32_t uart_base) +static uart_lsr_t uart_lsr_save; +static uart_lsr_t uart_lsr_read(uint32_t uart_base) { - uint16_t lsr = bfin_read(&pUART->lsr); + uart_lsr_t lsr = _lsr_read(pUART); uart_lsr_save |= (lsr & (OE|PE|FE|BI)); return lsr | uart_lsr_save; } @@ -72,20 +71,20 @@ static uint16_t uart_lsr_read(uint32_t uart_base) static void uart_lsr_clear(uint32_t uart_base) { uart_lsr_save = 0; - bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1); + _lsr_write(pUART, -1); } #else /* When debugging is disabled, we only care about the DR bit, so if other * bits get set/cleared, we don't really care since we don't read them * anyways (and thus anomaly 05000099 is irrelevant). */ -static inline uint16_t uart_lsr_read(uint32_t uart_base) +static inline uart_lsr_t uart_lsr_read(uint32_t uart_base) { - return bfin_read(&pUART->lsr); + return _lsr_read(pUART); } static void uart_lsr_clear(uint32_t uart_base) { - bfin_write(&pUART->lsr, bfin_read(&pUART->lsr) | -1); + _lsr_write(pUART, -1); } #endif @@ -127,20 +126,14 @@ static int uart_getc(uint32_t uart_base) #ifdef CONFIG_DEBUG_SERIAL /* grab & clear the LSR */ - uint16_t uart_lsr_val = uart_lsr_read(uart_base); + uart_lsr_t uart_lsr_val = uart_lsr_read(uart_base); cached_lsr[cache_count] = uart_lsr_val; cached_rbr[cache_count] = uart_rbr_val; cache_count = (cache_count + 1) % ARRAY_SIZE(cached_lsr); if (uart_lsr_val & (OE|PE|FE|BI)) { - uint16_t dll, dlh; printf("\n[SERIAL ERROR]\n"); - ACCESS_LATCH(); - dll = bfin_read(&pUART->dll); - dlh = bfin_read(&pUART->dlh); - ACCESS_PORT_IER(); - printf("\tDLL=0x%x DLH=0x%x\n", dll, dlh); do { --cache_count; printf("\t%3zu: RBR=0x%02x LSR=0x%02x\n", cache_count, @@ -160,6 +153,8 @@ static int uart_getc(uint32_t uart_base) # define LOOP(x) #endif +#if BFIN_UART_HW_VER < 4 + LOOP( static void uart_loop(uint32_t uart_base, int state) { @@ -178,6 +173,28 @@ static void uart_loop(uint32_t uart_base, int state) } ) +#else + +LOOP( +static void uart_loop(uint32_t uart_base, int state) +{ + u32 control; + + /* Drain the TX fifo first so bytes don't come back */ + while (!(uart_lsr_read(uart_base) & TEMT)) + continue; + + control = bfin_read(&pUART->control); + if (state) + control |= LOOP_ENA | MRTS; + else + control &= ~(LOOP_ENA | MRTS); + bfin_write(&pUART->control, control); +} +) + +#endif + #ifdef CONFIG_SYS_BFIN_UART static void uart_puts(uint32_t uart_base, const char *s) @@ -246,16 +263,16 @@ struct serial_device bfin_serial##n##_device = { \ LOOP(.loop = uart##n##_loop) \ }; -#ifdef UART0_DLL +#ifdef UART0_RBR DECL_BFIN_UART(0) #endif -#ifdef UART1_DLL +#ifdef UART1_RBR DECL_BFIN_UART(1) #endif -#ifdef UART2_DLL +#ifdef UART2_RBR DECL_BFIN_UART(2) #endif -#ifdef UART3_DLL +#ifdef UART3_RBR DECL_BFIN_UART(3) #endif @@ -274,16 +291,16 @@ __weak struct serial_device *default_serial_console(void) void bfin_serial_initialize(void) { -#ifdef UART0_DLL +#ifdef UART0_RBR serial_register(&bfin_serial0_device); #endif -#ifdef UART1_DLL +#ifdef UART1_RBR serial_register(&bfin_serial1_device); #endif -#ifdef UART2_DLL +#ifdef UART2_RBR serial_register(&bfin_serial2_device); #endif -#ifdef UART3_DLL +#ifdef UART3_RBR serial_register(&bfin_serial3_device); #endif } @@ -293,7 +310,7 @@ void bfin_serial_initialize(void) /* Symbol for our assembly to call. */ void serial_set_baud(uint32_t baud) { - serial_early_set_baud(UART_DLL, baud); + serial_early_set_baud(UART_BASE, baud); } /* Symbol for common u-boot code to call. @@ -307,7 +324,7 @@ void serial_setbrg(void) /* Symbol for our assembly to call. */ void serial_initialize(void) { - serial_early_init(UART_DLL); + serial_early_init(UART_BASE); } /* Symbol for common u-boot code to call. */ @@ -315,23 +332,23 @@ int serial_init(void) { serial_initialize(); serial_setbrg(); - uart_lsr_clear(UART_DLL); + uart_lsr_clear(UART_BASE); return 0; } int serial_tstc(void) { - return uart_tstc(UART_DLL); + return uart_tstc(UART_BASE); } int serial_getc(void) { - return uart_getc(UART_DLL); + return uart_getc(UART_BASE); } void serial_putc(const char c) { - uart_putc(UART_DLL, c); + uart_putc(UART_BASE, c); } void serial_puts(const char *s) @@ -343,7 +360,7 @@ void serial_puts(const char *s) LOOP( void serial_loop(int state) { - uart_loop(UART_DLL, state); + uart_loop(UART_BASE, state); } ) diff --git a/arch/blackfin/cpu/serial.h b/arch/blackfin/cpu/serial.h index 8a076ddc92..9200339668 100644 --- a/arch/blackfin/cpu/serial.h +++ b/arch/blackfin/cpu/serial.h @@ -3,7 +3,7 @@ * any functions defined here must be always_inline since * initcode cannot have function calls. * - * Copyright (c) 2004-2007 Analog Devices Inc. + * Copyright (c) 2004-2011 Analog Devices Inc. * * Licensed under the GPL-2 or later. */ @@ -12,7 +12,7 @@ #define __BFIN_CPU_SERIAL_H__ #include -#include +#include #ifndef CONFIG_UART_CONSOLE # define CONFIG_UART_CONSOLE 0 @@ -24,88 +24,34 @@ # define BFIN_DEBUG_EARLY_SERIAL 0 #endif -#ifndef __ASSEMBLY__ - -#include - -#define LOB(x) ((x) & 0xFF) -#define HIB(x) (((x) >> 8) & 0xFF) - -#if defined(__ADSPBF50x__) || defined(__ADSPBF54x__) +#if defined(__ADSPBF60x__) +# define BFIN_UART_HW_VER 4 +#elif defined(__ADSPBF50x__) || defined(__ADSPBF54x__) # define BFIN_UART_HW_VER 2 #else # define BFIN_UART_HW_VER 1 #endif -/* - * All Blackfin system MMRs are padded to 32bits even if the register - * itself is only 16bits. So use a helper macro to streamline this. - */ -#define __BFP(m) u16 m; u16 __pad_##m -struct bfin_mmr_serial { -#if BFIN_UART_HW_VER == 2 - __BFP(dll); - __BFP(dlh); - __BFP(gctl); - __BFP(lcr); - __BFP(mcr); - __BFP(lsr); - __BFP(msr); - __BFP(scr); - __BFP(ier_set); - __BFP(ier_clear); - __BFP(thr); - __BFP(rbr); -#else - union { - u16 dll; - u16 thr; - const u16 rbr; - }; - const u16 __spad0; - union { - u16 dlh; - u16 ier; - }; - const u16 __spad1; - const __BFP(iir); - __BFP(lcr); - __BFP(mcr); - __BFP(lsr); - __BFP(msr); - __BFP(scr); - const u32 __spad2; - __BFP(gctl); -#endif -}; -#undef __BFP - #define __PASTE_UART(num, pfx, sfx) pfx##num##_##sfx #define _PASTE_UART(num, pfx, sfx) __PASTE_UART(num, pfx, sfx) -#define MMR_UART(n) _PASTE_UART(n, UART, DLL) #define _P_UART(n, pin) _PASTE_UART(n, P_UART, pin) #define P_UART(pin) _P_UART(CONFIG_UART_CONSOLE, pin) -#ifndef UART_DLL -# define UART_DLL MMR_UART(CONFIG_UART_CONSOLE) -#else -# define UART0_DLL UART_DLL -# if CONFIG_UART_CONSOLE != 0 -# error CONFIG_UART_CONSOLE must be 0 on parts with only one UART -# endif -#endif #define pUART ((volatile struct bfin_mmr_serial *)uart_base) -#if BFIN_UART_HW_VER == 2 -# define ACCESS_LATCH() -# define ACCESS_PORT_IER() +#ifndef __ASSEMBLY__ +__attribute__((always_inline)) +static inline void serial_do_portmux(void); +#endif + +#if BFIN_UART_HW_VER < 4 +# include "serial1.h" #else -# define ACCESS_LATCH() \ - bfin_write(&pUART->lcr, bfin_read(&pUART->lcr) | DLAB) -# define ACCESS_PORT_IER() \ - bfin_write(&pUART->lcr, bfin_read(&pUART->lcr) & ~DLAB) +# include "serial4.h" #endif +#ifndef __ASSEMBLY__ + __attribute__((always_inline)) static inline void serial_do_portmux(void) { @@ -115,143 +61,7 @@ static inline void serial_do_portmux(void) return; } -#if defined(__ADSPBF50x__) -# define DO_MUX(port, mux_tx, mux_rx, tx, rx) \ - bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~(PORT_x_MUX_##mux_tx##_MASK | PORT_x_MUX_##mux_rx##_MASK)) | PORT_x_MUX_##mux_tx##_FUNC_1 | PORT_x_MUX_##mux_rx##_FUNC_1); \ - bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx); - switch (CONFIG_UART_CONSOLE) { - case 0: DO_MUX(G, 7, 7, 12, 13); break; /* Port G; mux 7; PG12 and PG13 */ - case 1: DO_MUX(F, 3, 3, 6, 7); break; /* Port F; mux 3; PF6 and PF7 */ - } - SSYNC(); -#elif defined(__ADSPBF51x__) -# define DO_MUX(port, mux_tx, mux_rx, tx, rx) \ - bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~(PORT_x_MUX_##mux_tx##_MASK | PORT_x_MUX_##mux_rx##_MASK)) | PORT_x_MUX_##mux_tx##_FUNC_2 | PORT_x_MUX_##mux_rx##_FUNC_2); \ - bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx); - switch (CONFIG_UART_CONSOLE) { - case 0: DO_MUX(G, 5, 5, 9, 10); break; /* Port G; mux 5; PG9 and PG10 */ - case 1: DO_MUX(F, 2, 3, 14, 15); break; /* Port H; mux 2/3; PH14 and PH15 */ - } - SSYNC(); -#elif defined(__ADSPBF52x__) -# define DO_MUX(port, mux, tx, rx) \ - bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~PORT_x_MUX_##mux##_MASK) | PORT_x_MUX_##mux##_FUNC_3); \ - bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx); - switch (CONFIG_UART_CONSOLE) { - case 0: DO_MUX(G, 2, 7, 8); break; /* Port G; mux 2; PG2 and PG8 */ - case 1: DO_MUX(F, 5, 14, 15); break; /* Port F; mux 5; PF14 and PF15 */ - } - SSYNC(); -#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) - const uint16_t func[] = { PFDE, PFTE, }; - bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]); - bfin_write_PORTF_FER(bfin_read_PORTF_FER() | - (1 << P_IDENT(P_UART(RX))) | - (1 << P_IDENT(P_UART(TX)))); - SSYNC(); -#elif defined(__ADSPBF54x__) -# define DO_MUX(port, tx, rx) \ - bfin_write_PORT##port##_MUX((bfin_read_PORT##port##_MUX() & ~(PORT_x_MUX_##tx##_MASK | PORT_x_MUX_##rx##_MASK)) | PORT_x_MUX_##tx##_FUNC_1 | PORT_x_MUX_##rx##_FUNC_1); \ - bfin_write_PORT##port##_FER(bfin_read_PORT##port##_FER() | P##port##tx | P##port##rx); - switch (CONFIG_UART_CONSOLE) { - case 0: DO_MUX(E, 7, 8); break; /* Port E; PE7 and PE8 */ - case 1: DO_MUX(H, 0, 1); break; /* Port H; PH0 and PH1 */ - case 2: DO_MUX(B, 4, 5); break; /* Port B; PB4 and PB5 */ - case 3: DO_MUX(B, 6, 7); break; /* Port B; PB6 and PB7 */ - } - SSYNC(); -#elif defined(__ADSPBF561__) - /* UART pins could be GPIO, but they aren't pin muxed. */ -#else -# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED) -# error "missing portmux logic for UART" -# endif -#endif -} - -__attribute__((always_inline)) -static inline int uart_init(uint32_t uart_base) -{ - /* always enable UART -- avoids anomalies 05000309 and 05000350 */ - bfin_write(&pUART->gctl, UCEN); - - /* Set LCR to Word Lengh 8-bit word select */ - bfin_write(&pUART->lcr, WLS_8); - - SSYNC(); - - return 0; -} - -__attribute__((always_inline)) -static inline int serial_early_init(uint32_t uart_base) -{ - /* handle portmux crap on different Blackfins */ - serial_do_portmux(); - - return uart_init(uart_base); -} - -__attribute__((always_inline)) -static inline int serial_early_uninit(uint32_t uart_base) -{ - /* disable the UART by clearing UCEN */ - bfin_write(&pUART->gctl, 0); - - return 0; -} - -__attribute__((always_inline)) -static inline void serial_early_put_div(uint32_t uart_base, uint16_t divisor) -{ - /* Set DLAB in LCR to Access DLL and DLH */ - ACCESS_LATCH(); - SSYNC(); - - /* Program the divisor to get the baud rate we want */ - bfin_write(&pUART->dll, LOB(divisor)); - bfin_write(&pUART->dlh, HIB(divisor)); - SSYNC(); - - /* Clear DLAB in LCR to Access THR RBR IER */ - ACCESS_PORT_IER(); - SSYNC(); -} - -__attribute__((always_inline)) -static inline uint16_t serial_early_get_div(void) -{ - uint32_t uart_base = UART_DLL; - - /* Set DLAB in LCR to Access DLL and DLH */ - ACCESS_LATCH(); - SSYNC(); - - uint8_t dll = bfin_read(&pUART->dll); - uint8_t dlh = bfin_read(&pUART->dlh); - uint16_t divisor = (dlh << 8) | dll; - - /* Clear DLAB in LCR to Access THR RBR IER */ - ACCESS_PORT_IER(); - SSYNC(); - - return divisor; -} - -/* We cannot use get_sclk() early on as it uses caches in external memory */ -#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL) -# define get_sclk() (CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV) -#endif - -__attribute__((always_inline)) -static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) -{ - /* Translate from baud into divisor in terms of SCLK. The - * weird multiplication is to make sure we over sample just - * a little rather than under sample the incoming signals. - */ - serial_early_put_div(uart_base, - (get_sclk() + (baud * 8)) / (baud * 16) - ANOMALY_05000230); + serial_early_do_portmux(); } #ifndef BFIN_IN_INITCODE diff --git a/arch/blackfin/cpu/serial1.h b/arch/blackfin/cpu/serial1.h new file mode 100644 index 0000000000..a20175bc7f --- /dev/null +++ b/arch/blackfin/cpu/serial1.h @@ -0,0 +1,348 @@ +/* + * serial.h - common serial defines for early debug and serial driver. + * any functions defined here must be always_inline since + * initcode cannot have function calls. + * + * Copyright (c) 2004-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_CPU_SERIAL1_H__ +#define __BFIN_CPU_SERIAL1_H__ + +#include + +#ifndef __ASSEMBLY__ + +#define MMR_UART(n) _PASTE_UART(n, UART, DLL) +#ifdef UART_DLL +# define UART0_DLL UART_DLL +# if CONFIG_UART_CONSOLE != 0 +# error CONFIG_UART_CONSOLE must be 0 on parts with only one UART +# endif +#endif +#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE) + +#define LOB(x) ((x) & 0xFF) +#define HIB(x) (((x) >> 8) & 0xFF) + +/* + * All Blackfin system MMRs are padded to 32bits even if the register + * itself is only 16bits. So use a helper macro to streamline this. + */ +struct bfin_mmr_serial { +#if BFIN_UART_HW_VER == 2 + u16 dll; + u16 __pad_0; + u16 dlh; + u16 __pad_1; + u16 gctl; + u16 __pad_2; + u16 lcr; + u16 __pad_3; + u16 mcr; + u16 __pad_4; + u16 lsr; + u16 __pad_5; + u16 msr; + u16 __pad_6; + u16 scr; + u16 __pad_7; + u16 ier_set; + u16 __pad_8; + u16 ier_clear; + u16 __pad_9; + u16 thr; + u16 __pad_10; + u16 rbr; + u16 __pad_11; +#else + union { + u16 dll; + u16 thr; + const u16 rbr; + }; + const u16 __spad0; + union { + u16 dlh; + u16 ier; + }; + const u16 __spad1; + const u16 iir; + u16 __pad_0; + u16 lcr; + u16 __pad_1; + u16 mcr; + u16 __pad_2; + u16 lsr; + u16 __pad_3; + u16 msr; + u16 __pad_4; + u16 scr; + u16 __pad_5; + const u32 __spad2; + u16 gctl; + u16 __pad_6; +#endif +}; + +#define uart_lsr_t uint32_t +#define _lsr_read(p) bfin_read(&p->lsr) +#define _lsr_write(p, v) bfin_write(&p->lsr, v) + +#if BFIN_UART_HW_VER == 2 +# define ACCESS_LATCH() +# define ACCESS_PORT_IER() +#else +# define ACCESS_LATCH() bfin_write_or(&pUART->lcr, DLAB) +# define ACCESS_PORT_IER() bfin_write_and(&pUART->lcr, ~DLAB) +#endif + +__attribute__((always_inline)) +static inline void serial_early_do_mach_portmux(char port, int mux_mask, + int mux_func, int port_pin) +{ + switch (port) { +#if defined(__ADSPBF54x__) + case 'B': + bfin_write_PORTB_MUX((bfin_read_PORTB_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTB_FER(bfin_read_PORTB_FER() | port_pin); + break; + case 'E': + bfin_write_PORTE_MUX((bfin_read_PORTE_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTE_FER(bfin_read_PORTE_FER() | port_pin); + break; +#endif +#if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF52x__) + case 'F': + bfin_write_PORTF_MUX((bfin_read_PORTF_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | port_pin); + break; + case 'G': + bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTG_FER(bfin_read_PORTG_FER() | port_pin); + break; + case 'H': + bfin_write_PORTH_MUX((bfin_read_PORTH_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTH_FER(bfin_read_PORTH_FER() | port_pin); + break; +#endif + default: + break; + } +} + +__attribute__((always_inline)) +static inline void serial_early_do_portmux(void) +{ +#if defined(__ADSPBF50x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PG12); /* TX: G; mux 7; func 1; PG12 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PG13); /* RX: G; mux 7; func 1; PG13 */ + break; + case 1: + serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_1, PF7); /* TX: F; mux 3; func 1; PF6 */ + serial_early_do_mach_portmux('F', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_1, PF6); /* RX: F; mux 3; func 1; PF7 */ + break; + } +#elif defined(__ADSPBF51x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_2, PG9); /* TX: G; mux 5; func 2; PG9 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_2, PG10); /* RX: G; mux 5; func 2; PG10 */ + break; + case 1: + serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_2, PH7); /* TX: H; mux 3; func 2; PH6 */ + serial_early_do_mach_portmux('H', PORT_x_MUX_3_MASK, + PORT_x_MUX_3_FUNC_2, PH6); /* RX: H; mux 3; func 2; PH7 */ + break; + } +#elif defined(__ADSPBF52x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK, + PORT_x_MUX_2_FUNC_3, PG7); /* TX: G; mux 2; func 3; PG7 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_2_MASK, + PORT_x_MUX_2_FUNC_3, PG8); /* RX: G; mux 2; func 3; PG8 */ + break; + case 1: + serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_3, PF14); /* TX: F; mux 5; func 3; PF14 */ + serial_early_do_mach_portmux('F', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_3, PF15); /* RX: F; mux 5; func 3; PF15 */ + break; + } +#elif defined(__ADSPBF537__) || defined(__ADSPBF536__) || defined(__ADSPBF534__) + const uint16_t func[] = { PFDE, PFTE, }; + bfin_write_PORT_MUX(bfin_read_PORT_MUX() & ~func[CONFIG_UART_CONSOLE]); + bfin_write_PORTF_FER(bfin_read_PORTF_FER() | + (1 << P_IDENT(P_UART(RX))) | + (1 << P_IDENT(P_UART(TX)))); +#elif defined(__ADSPBF54x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('E', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PE7); /* TX: E; mux 7; func 1; PE7 */ + serial_early_do_mach_portmux('E', PORT_x_MUX_8_MASK, + PORT_x_MUX_8_FUNC_1, PE8); /* RX: E; mux 8; func 1; PE8 */ + break; + case 1: + serial_early_do_mach_portmux('H', PORT_x_MUX_0_MASK, + PORT_x_MUX_0_FUNC_1, PH0); /* TX: H; mux 0; func 1; PH0 */ + serial_early_do_mach_portmux('H', PORT_x_MUX_1_MASK, + PORT_x_MUX_1_FUNC_1, PH1); /* RX: H; mux 1; func 1; PH1 */ + break; + case 2: + serial_early_do_mach_portmux('B', PORT_x_MUX_4_MASK, + PORT_x_MUX_4_FUNC_1, PB4); /* TX: B; mux 4; func 1; PB4 */ + serial_early_do_mach_portmux('B', PORT_x_MUX_5_MASK, + PORT_x_MUX_5_FUNC_1, PB5); /* RX: B; mux 5; func 1; PB5 */ + break; + case 3: + serial_early_do_mach_portmux('B', PORT_x_MUX_6_MASK, + PORT_x_MUX_6_FUNC_1, PB6); /* TX: B; mux 6; func 1; PB6 */ + serial_early_do_mach_portmux('B', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_1, PB7); /* RX: B; mux 7; func 1; PB7 */ + break; + } +#elif defined(__ADSPBF561__) + /* UART pins could be GPIO, but they aren't pin muxed. */ +#else +# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED) +# error "missing portmux logic for UART" +# endif +#endif + SSYNC(); +} + +__attribute__((always_inline)) +static inline uint32_t uart_sclk(void) +{ +#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL) + /* We cannot use get_sclk() early on as it uses + * caches in external memory + */ + return CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV; +#else + return get_sclk(); +#endif +} + +__attribute__((always_inline)) +static inline int uart_init(uint32_t uart_base) +{ + /* always enable UART -- avoids anomalies 05000309 and 05000350 */ + bfin_write(&pUART->gctl, UCEN); + + /* Set LCR to Word Lengh 8-bit word select */ + bfin_write(&pUART->lcr, WLS_8); + + SSYNC(); + + return 0; +} + +__attribute__((always_inline)) +static inline int serial_early_init(uint32_t uart_base) +{ + /* handle portmux crap on different Blackfins */ + serial_do_portmux(); + + return uart_init(uart_base); +} + +__attribute__((always_inline)) +static inline int serial_early_uninit(uint32_t uart_base) +{ + /* disable the UART by clearing UCEN */ + bfin_write(&pUART->gctl, 0); + + return 0; +} + +__attribute__((always_inline)) +static inline int serial_early_enabled(uint32_t uart_base) +{ + return bfin_read(&pUART->gctl) & UCEN; +} + +__attribute__((always_inline)) +static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) +{ + /* Translate from baud into divisor in terms of SCLK. The + * weird multiplication is to make sure we over sample just + * a little rather than under sample the incoming signals. + */ + uint16_t divisor = (uart_sclk() + (baud * 8)) / (baud * 16) - + ANOMALY_05000230; + + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); + + /* Program the divisor to get the baud rate we want */ + bfin_write(&pUART->dll, LOB(divisor)); + bfin_write(&pUART->dlh, HIB(divisor)); + SSYNC(); + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); +} + +__attribute__((always_inline)) +static inline void serial_early_put_div(uint16_t divisor) +{ + uint32_t uart_base = UART_BASE; + + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); + + /* Program the divisor to get the baud rate we want */ + bfin_write(&pUART->dll, LOB(divisor)); + bfin_write(&pUART->dlh, HIB(divisor)); + SSYNC(); + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); +} + +__attribute__((always_inline)) +static inline uint16_t serial_early_get_div(void) +{ + uint32_t uart_base = UART_BASE; + + /* Set DLAB in LCR to Access DLL and DLH */ + ACCESS_LATCH(); + SSYNC(); + + uint8_t dll = bfin_read(&pUART->dll); + uint8_t dlh = bfin_read(&pUART->dlh); + uint16_t divisor = (dlh << 8) | dll; + + /* Clear DLAB in LCR to Access THR RBR IER */ + ACCESS_PORT_IER(); + SSYNC(); + + return divisor; +} + +#endif + +#endif diff --git a/arch/blackfin/cpu/serial4.h b/arch/blackfin/cpu/serial4.h new file mode 100644 index 0000000000..887845c186 --- /dev/null +++ b/arch/blackfin/cpu/serial4.h @@ -0,0 +1,161 @@ +/* + * serial.h - common serial defines for early debug and serial driver. + * any functions defined here must be always_inline since + * initcode cannot have function calls. + * + * Copyright (c) 2004-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_CPU_SERIAL4_H__ +#define __BFIN_CPU_SERIAL4_H__ + +#include + +#ifndef __ASSEMBLY__ + +#define MMR_UART(n) _PASTE_UART(n, UART, REVID) +#define UART_BASE MMR_UART(CONFIG_UART_CONSOLE) + +struct bfin_mmr_serial { + u32 revid; + u32 control; + u32 status; + u32 scr; + u32 clock; + u32 emask; + u32 emaskst; + u32 emaskcl; + u32 rbr; + u32 thr; + u32 taip; + u32 tsr; + u32 rsr; + u32 txdiv_cnt; + u32 rxdiv_cnt; +}; +#define uart_lsr_t uint32_t +#define _lsr_read(p) bfin_read(&p->status) +#define _lsr_write(p, v) bfin_write(&p->status, v) + +__attribute__((always_inline)) +static inline void serial_early_do_mach_portmux(char port, int mux_mask, + int mux_func, int port_pin) +{ + switch (port) { + case 'D': + bfin_write_PORTD_MUX((bfin_read_PORTD_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTD_FER_SET(port_pin); + break; + case 'G': + bfin_write_PORTG_MUX((bfin_read_PORTG_MUX() & + ~mux_mask) | mux_func); + bfin_write_PORTG_FER_SET(port_pin); + break; + } +} + +__attribute__((always_inline)) +static inline void serial_early_do_portmux(void) +{ +#if defined(__ADSPBF60x__) + switch (CONFIG_UART_CONSOLE) { + case 0: + serial_early_do_mach_portmux('D', PORT_x_MUX_7_MASK, + PORT_x_MUX_7_FUNC_2, PD7); /* TX: D; mux 7; func 2; PD7 */ + serial_early_do_mach_portmux('D', PORT_x_MUX_8_MASK, + PORT_x_MUX_8_FUNC_2, PD8); /* RX: D; mux 8; func 2; PD8 */ + break; + case 1: + serial_early_do_mach_portmux('G', PORT_x_MUX_15_MASK, + PORT_x_MUX_15_FUNC_1, PG15); /* TX: G; mux 15; func 1; PG15 */ + serial_early_do_mach_portmux('G', PORT_x_MUX_14_MASK, + PORT_x_MUX_14_FUNC_1, PG14); /* RX: G; mux 14; func 1; PG14 */ + break; + } +#else +# if (P_UART(RX) & P_DEFINED) || (P_UART(TX) & P_DEFINED) +# error "missing portmux logic for UART" +# endif +#endif + SSYNC(); +} + +__attribute__((always_inline)) +static inline uint32_t uart_sclk(void) +{ +#if defined(BFIN_IN_INITCODE) || defined(CONFIG_DEBUG_EARLY_SERIAL) + /* We cannot use get_sclk() early on as it uses caches in + * external memory + */ + return CONFIG_CLKIN_HZ * CONFIG_VCO_MULT / CONFIG_SCLK_DIV / + CONFIG_SCLK0_DIV; +#else + return get_sclk0(); +#endif +} + +__attribute__((always_inline)) +static inline int uart_init(uint32_t uart_base) +{ + /* always enable UART to 8-bit mode */ + bfin_write(&pUART->control, UEN | UMOD_UART | WLS_8); + + SSYNC(); + + return 0; +} + +__attribute__((always_inline)) +static inline int serial_early_init(uint32_t uart_base) +{ + /* handle portmux crap on different Blackfins */ + serial_do_portmux(); + + return uart_init(uart_base); +} + +__attribute__((always_inline)) +static inline int serial_early_uninit(uint32_t uart_base) +{ + /* disable the UART by clearing UEN */ + bfin_write(&pUART->control, 0); + + return 0; +} + +__attribute__((always_inline)) +static inline int serial_early_enabled(uint32_t uart_base) +{ + return bfin_read(&pUART->control) & UEN; +} + +__attribute__((always_inline)) +static inline void serial_early_set_baud(uint32_t uart_base, uint32_t baud) +{ + uint32_t divisor = uart_sclk() / (baud * 16); + + /* Program the divisor to get the baud rate we want */ + bfin_write(&pUART->clock, divisor); + SSYNC(); +} + +__attribute__((always_inline)) +static inline void serial_early_put_div(uint32_t divisor) +{ + uint32_t uart_base = UART_BASE; + bfin_write(&pUART->clock, divisor); +} + +__attribute__((always_inline)) +static inline uint32_t serial_early_get_div(void) +{ + uint32_t uart_base = UART_BASE; + return bfin_read(&pUART->clock); +} + +#endif + +#endif diff --git a/arch/blackfin/include/asm/mach-bf533/BF531_def.h b/arch/blackfin/include/asm/mach-bf533/BF531_def.h index 3b61aafcc9..2bcd2d88dc 100644 --- a/arch/blackfin/include/asm/mach-bf533/BF531_def.h +++ b/arch/blackfin/include/asm/mach-bf533/BF531_def.h @@ -149,6 +149,7 @@ #define UART_LSR 0xFFC00414 #define UART_SCR 0xFFC0041C #define UART_RBR 0xFFC00400 /* Receive Buffer */ +#define UART0_RBR UART_RBR #define UART_GCTL 0xFFC00424 #define SPT0_TX_CONFIG0 0xFFC00800 #define SPT0_TX_CONFIG1 0xFFC00804 diff --git a/arch/blackfin/include/asm/mach-bf561/BF561_def.h b/arch/blackfin/include/asm/mach-bf561/BF561_def.h index 46925f8c07..a7ff5a3feb 100644 --- a/arch/blackfin/include/asm/mach-bf561/BF561_def.h +++ b/arch/blackfin/include/asm/mach-bf561/BF561_def.h @@ -690,6 +690,7 @@ #define PPI1_FRAME 0xFFC01310 #define UART_THR 0xFFC00400 #define UART_RBR 0xFFC00400 +#define UART0_RBR UART_RBR #define UART_DLL 0xFFC00400 #define UART_DLH 0xFFC00404 #define UART_IER 0xFFC00404 diff --git a/arch/blackfin/include/asm/mach-common/bits/uart4.h b/arch/blackfin/include/asm/mach-common/bits/uart4.h new file mode 100644 index 0000000000..37808de243 --- /dev/null +++ b/arch/blackfin/include/asm/mach-common/bits/uart4.h @@ -0,0 +1,66 @@ +/* + * UART4 Masks + */ + +#ifndef __BFIN_PERIPHERAL_UART4__ +#define __BFIN_PERIPHERAL_UART4__ + +/* UART_CONTROL */ +#define UEN (1 << 0) +#define LOOP_ENA (1 << 1) +#define UMOD (3 << 4) +#define UMOD_UART (0 << 4) +#define UMOD_MDB (1 << 4) +#define UMOD_IRDA (1 << 4) +#define WLS (3 << 8) +#define WLS_5 (0 << 8) +#define WLS_6 (1 << 8) +#define WLS_7 (2 << 8) +#define WLS_8 (3 << 8) +#define STB (1 << 12) +#define STBH (1 << 13) +#define PEN (1 << 14) +#define EPS (1 << 15) +#define STP (1 << 16) +#define FPE (1 << 17) +#define FFE (1 << 18) +#define SB (1 << 19) +#define FCPOL (1 << 22) +#define RPOLC (1 << 23) +#define TPOLC (1 << 24) +#define MRTS (1 << 25) +#define XOFF (1 << 26) +#define ARTS (1 << 27) +#define ACTS (1 << 28) +#define RFIT (1 << 29) +#define RFRT (1 << 30) + +/* UART_STATUS */ +#define DR (1 << 0) +#define OE (1 << 1) +#define PE (1 << 2) +#define FE (1 << 3) +#define BI (1 << 4) +#define THRE (1 << 5) +#define TEMT (1 << 7) +#define TFI (1 << 8) +#define ASTKY (1 << 9) +#define ADDR (1 << 10) +#define RO (1 << 11) +#define SCTS (1 << 12) +#define CTS (1 << 16) +#define RFCS (1 << 17) + +/* UART_EMASK */ +#define ERBFI (1 << 0) +#define ETBEI (1 << 1) +#define ELSI (1 << 2) +#define EDSSI (1 << 3) +#define EDTPTI (1 << 4) +#define ETFI (1 << 5) +#define ERFCI (1 << 6) +#define EAWI (1 << 7) +#define ERXS (1 << 8) +#define ETXS (1 << 9) + +#endif -- cgit v1.2.3 From ee8259623e57acf738aee548a8e9bee0a543f3f0 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Thu, 16 Aug 2012 11:19:08 +0800 Subject: blackfin: bf60x: add dma support Add dma support for bf60x. Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang --- arch/blackfin/include/asm/dma.h | 81 +++++++++++++------- arch/blackfin/include/asm/mach-common/bits/dma.h | 54 +++++++++++-- arch/blackfin/lib/string.c | 97 +++++++++++++----------- 3 files changed, 156 insertions(+), 76 deletions(-) diff --git a/arch/blackfin/include/asm/dma.h b/arch/blackfin/include/asm/dma.h index 21ff1cf9fb..ef1db6e99c 100644 --- a/arch/blackfin/include/asm/dma.h +++ b/arch/blackfin/include/asm/dma.h @@ -8,7 +8,12 @@ #ifndef _BLACKFIN_DMA_H_ #define _BLACKFIN_DMA_H_ +#include +#ifdef __ADSPBF60x__ +#include +#else #include +#endif struct dmasg_large { void *next_desc_addr; @@ -30,46 +35,70 @@ struct dmasg { } __attribute__((packed)); struct dma_register { +#ifdef __ADSPBF60x__ + void *next_desc_ptr; /* DMA Next Descriptor Pointer register */ + u32 start_addr; /* DMA Start address register */ + u32 config; /* DMA Configuration register */ + + u32 x_count; /* DMA x_count register */ + s32 x_modify; /* DMA x_modify register */ + u32 y_count; /* DMA y_count register */ + s32 y_modify; /* DMA y_modify register */ + u32 __pad0[2]; + + void *curr_desc_ptr; /* DMA Curr Descriptor Pointer register */ + void *prev_desc_ptr; /* DMA Prev Descriptor Pointer register */ + void *curr_addr; /* DMA Current Address Pointer register */ + u32 status; /* DMA irq status register */ + u32 curr_x_count; /* DMA Current x-count register */ + u32 curr_y_count; /* DMA Current y-count register */ + u32 __pad1[2]; + + u32 bw_limit; /* DMA Bandwidth Limit Count */ + u32 curr_bw_limit; /* DMA curr Bandwidth Limit Count */ + u32 bw_monitor; /* DMA Bandwidth Monitor Count */ + u32 curr_bw_monitor; /* DMA curr Bandwidth Monitor Count */ +#else void *next_desc_ptr; /* DMA Next Descriptor Pointer register */ - unsigned long start_addr; /* DMA Start address register */ + u32 start_addr; /* DMA Start address register */ - unsigned short cfg; /* DMA Configuration register */ - unsigned short dummy1; /* DMA Configuration register */ + u16 config; /* DMA Configuration register */ + u16 dummy1; /* DMA Configuration register */ - unsigned long reserved; + u32 reserved; - unsigned short x_count; /* DMA x_count register */ - unsigned short dummy2; + u16 x_count; /* DMA x_count register */ + u16 dummy2; - short x_modify; /* DMA x_modify register */ - unsigned short dummy3; + s16 x_modify; /* DMA x_modify register */ + u16 dummy3; - unsigned short y_count; /* DMA y_count register */ - unsigned short dummy4; + u16 y_count; /* DMA y_count register */ + u16 dummy4; - short y_modify; /* DMA y_modify register */ - unsigned short dummy5; + s16 y_modify; /* DMA y_modify register */ + u16 dummy5; - void *curr_desc_ptr; /* DMA Current Descriptor Pointer - register */ - unsigned long curr_addr_ptr; /* DMA Current Address Pointer - register */ - unsigned short irq_status; /* DMA irq status register */ - unsigned short dummy6; + void *curr_desc_ptr; /* DMA Current Descriptor Pointer register */ - unsigned short peripheral_map; /* DMA peripheral map register */ - unsigned short dummy7; + u32 curr_addr_ptr; /* DMA Current Address Pointer register */ - unsigned short curr_x_count; /* DMA Current x-count register */ - unsigned short dummy8; + u16 status; /* DMA irq status register */ + u16 dummy6; - unsigned long reserved2; + u16 peripheral_map; /* DMA peripheral map register */ + u16 dummy7; - unsigned short curr_y_count; /* DMA Current y-count register */ - unsigned short dummy9; + u16 curr_x_count; /* DMA Current x-count register */ + u16 dummy8; - unsigned long reserved3; + u32 reserved2; + u16 curr_y_count; /* DMA Current y-count register */ + u16 dummy9; + + u32 reserved3; +#endif }; #endif diff --git a/arch/blackfin/include/asm/mach-common/bits/dma.h b/arch/blackfin/include/asm/mach-common/bits/dma.h index 136313e613..ac426addd4 100644 --- a/arch/blackfin/include/asm/mach-common/bits/dma.h +++ b/arch/blackfin/include/asm/mach-common/bits/dma.h @@ -9,14 +9,54 @@ #define DMAEN 0x0001 /* DMA Channel Enable */ #define WNR 0x0002 /* Channel Direction (W/R*) */ #define WDSIZE_8 0x0000 /* Transfer Word Size = 8 */ + +#ifdef CONFIG_BF60x + +#define PSIZE_8 0x00000000 /* Transfer Word Size = 16 */ +#define PSIZE_16 0x00000010 /* Transfer Word Size = 16 */ +#define PSIZE_32 0x00000020 /* Transfer Word Size = 32 */ +#define PSIZE_64 0x00000030 /* Transfer Word Size = 32 */ +#define WDSIZE_16 0x00000100 /* Transfer Word Size = 16 */ +#define WDSIZE_32 0x00000200 /* Transfer Word Size = 32 */ +#define WDSIZE_64 0x00000300 /* Transfer Word Size = 32 */ +#define WDSIZE_128 0x00000400 /* Transfer Word Size = 32 */ +#define WDSIZE_256 0x00000500 /* Transfer Word Size = 32 */ +#define DMA2D 0x04000000 /* DMA Mode (2D/1D*) */ +#define RESTART 0x00000004 /* DMA Buffer Clear SYNC */ +#define DI_EN_X 0x00100000 /* Data Int Enable in X count */ +#define DI_EN_Y 0x00200000 /* Data Int Enable in Y count */ +#define DI_EN_P 0x00300000 /* Data Int Enable in Peri */ +#define DI_EN DI_EN_X /* Data Int Enable */ +#define NDSIZE_0 0x00000000 /* Next Desc Size = 0 */ +#define NDSIZE_1 0x00010000 /* Next Desc Size = 1 */ +#define NDSIZE_2 0x00020000 /* Next Desc Size = 2 */ +#define NDSIZE_3 0x00030000 /* Next Desc Size = 3 */ +#define NDSIZE_4 0x00040000 /* Next Desc Size = 4 */ +#define NDSIZE_5 0x00050000 /* Next Desc Size = 5 */ +#define NDSIZE_6 0x00060000 /* Next Desc Size = 6 */ +#define NDSIZE 0x00070000 /* Next Desc Size */ +#define NDSIZE_OFFSET 16 /* Next Desc Size Offset */ +#define DMAFLOW_LIST 0x00004000 /* Desc List Mode */ +#define DMAFLOW_ARRAY 0x00005000 /* Desc Array Mode */ +#define DMAFLOW_LIST_DEMAND 0x00006000 /* Desc Demand List Mode */ +#define DMAFLOW_ARRAY_DEMAND 0x00007000 /* Desc Demand Array Mode */ +#define DMA_RUN_DFETCH 0x00000100 /* DMA Channel Run (DFETCH) */ +#define DMA_RUN 0x00000200 /* DMA Channel Run */ +#define DMA_RUN_WAIT_TRIG 0x00000300 /* DMA Channel Run (WAIT TRIG)*/ +#define DMA_RUN_WAIT_ACK 0x00000400 /* DMA Channel Run (WAIT ACK) */ + +#else + #define WDSIZE_16 0x0004 /* Transfer Word Size = 16 */ #define WDSIZE_32 0x0008 /* Transfer Word Size = 32 */ +#define PSIZE_16 WDSIZE_16 +#define PSIZE_32 WDSIZE_32 #define DMA2D 0x0010 /* DMA Mode (2D/1D*) */ #define RESTART 0x0020 /* DMA Buffer Clear */ #define DI_SEL 0x0040 /* Data Interrupt Timing Select */ #define DI_EN 0x0080 /* Data Interrupt Enable */ #define NDSIZE 0x0F00 /* Next Descriptor bitmask */ -#define NDSIZE_0 0x0000 /* Next Descriptor Size = 0 (Stop/Autobuffer) */ +#define NDSIZE_0 0x0000 /* Next Descriptor Size = 0 */ #define NDSIZE_1 0x0100 /* Next Descriptor Size = 1 */ #define NDSIZE_2 0x0200 /* Next Descriptor Size = 2 */ #define NDSIZE_3 0x0300 /* Next Descriptor Size = 3 */ @@ -26,14 +66,13 @@ #define NDSIZE_7 0x0700 /* Next Descriptor Size = 7 */ #define NDSIZE_8 0x0800 /* Next Descriptor Size = 8 */ #define NDSIZE_9 0x0900 /* Next Descriptor Size = 9 */ -#define FLOW_STOP 0x0000 /* Stop Mode */ -#define FLOW_AUTO 0x1000 /* Autobuffer Mode */ #define FLOW_ARRAY 0x4000 /* Descriptor Array Mode */ #define FLOW_SMALL 0x6000 /* Small Model Descriptor List Mode */ #define FLOW_LARGE 0x7000 /* Large Model Descriptor List Mode */ #define DMAEN_P 0 /* Channel Enable */ #define WNR_P 1 /* Channel Direction (W/R*) */ +#define WDSIZE_P 2 /* Transfer Word Size */ #define DMA2D_P 4 /* 2D/1D* Mode */ #define RESTART_P 5 /* Restart */ #define DI_SEL_P 6 /* Data Interrupt Select */ @@ -45,14 +84,19 @@ #define DFETCH 0x0004 /* DMA Descriptor Fetch Indicator */ #define DMA_RUN 0x0008 /* DMA Channel Running Indicator */ +#endif +#define DMAFLOW 0x7000 /* Flow Control */ +#define FLOW_STOP 0x0000 /* Stop Mode */ +#define FLOW_AUTO 0x1000 /* Autobuffer Mode */ + #define DMA_DONE_P 0 /* DMA Done Indicator */ #define DMA_ERR_P 1 /* DMA Error Indicator */ #define DFETCH_P 2 /* Descriptor Fetch Indicator */ #define DMA_RUN_P 3 /* DMA Running Indicator */ /* DMAx_PERIPHERAL_MAP, MDMA_yy_PERIPHERAL_MAP Masks */ -#define CTYPE 0x0040 /* DMA Channel Type Indicator (Memory/Peripheral*) */ -#define CTYPE_P 6 /* DMA Channel Type Indicator BIT POSITION */ +#define CTYPE 0x0040 /* DMA Channel Type (Mem/Peri) */ +#define CTYPE_P 6 /* DMA Channel Type BIT POSITION */ #define PMAP 0xF000 /* Peripheral Mapped To This Channel */ #endif diff --git a/arch/blackfin/lib/string.c b/arch/blackfin/lib/string.c index e344d3b94b..44d8c6d906 100644 --- a/arch/blackfin/lib/string.c +++ b/arch/blackfin/lib/string.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include char *strcpy(char *dest, const char *src) { @@ -117,81 +117,88 @@ int strncmp(const char *cs, const char *ct, size_t count) return __res1; } -#ifdef bfin_write_MDMA1_D0_IRQ_STATUS -# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS -# define bfin_write_MDMA_D0_START_ADDR bfin_write_MDMA1_D0_START_ADDR -# define bfin_write_MDMA_D0_X_COUNT bfin_write_MDMA1_D0_X_COUNT -# define bfin_write_MDMA_D0_X_MODIFY bfin_write_MDMA1_D0_X_MODIFY -# define bfin_write_MDMA_D0_CONFIG bfin_write_MDMA1_D0_CONFIG -# define bfin_write_MDMA_S0_START_ADDR bfin_write_MDMA1_S0_START_ADDR -# define bfin_write_MDMA_S0_X_COUNT bfin_write_MDMA1_S0_X_COUNT -# define bfin_write_MDMA_S0_X_MODIFY bfin_write_MDMA1_S0_X_MODIFY -# define bfin_write_MDMA_S0_CONFIG bfin_write_MDMA1_S0_CONFIG -# define bfin_write_MDMA_D0_IRQ_STATUS bfin_write_MDMA1_D0_IRQ_STATUS -# define bfin_read_MDMA_D0_IRQ_STATUS bfin_read_MDMA1_D0_IRQ_STATUS +#ifdef MDMA1_D0_NEXT_DESC_PTR +# define MDMA_D0_NEXT_DESC_PTR MDMA1_D0_NEXT_DESC_PTR +# define MDMA_S0_NEXT_DESC_PTR MDMA1_S0_NEXT_DESC_PTR #endif + +static void dma_calc_size(unsigned long ldst, unsigned long lsrc, size_t count, + unsigned long *dshift, unsigned long *bpos) +{ + unsigned long limit; + +#ifdef MSIZE + limit = 6; + *dshift = MSIZE_P; +#else + limit = 3; + *dshift = WDSIZE_P; +#endif + + *bpos = min(limit, ffs(ldst | lsrc | count)) - 1; +} + /* This version misbehaves for count values of 0 and 2^16+. * Perhaps we should detect that ? Nowhere do we actually * use dma memcpy for those types of lengths though ... */ void dma_memcpy_nocache(void *dst, const void *src, size_t count) { - uint16_t wdsize, mod; + struct dma_register *mdma_d0 = (void *)MDMA_D0_NEXT_DESC_PTR; + struct dma_register *mdma_s0 = (void *)MDMA_S0_NEXT_DESC_PTR; + unsigned long ldst = (unsigned long)dst; + unsigned long lsrc = (unsigned long)src; + unsigned long dshift, bpos; + uint32_t dsize, mod; /* Disable DMA in case it's still running (older u-boot's did not * always turn them off). Do it before the if statement below so * we can be cheap and not do a SSYNC() due to the forced abort. */ - bfin_write_MDMA_D0_CONFIG(0); - bfin_write_MDMA_S0_CONFIG(0); - bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR); + bfin_write(&mdma_d0->config, 0); + bfin_write(&mdma_s0->config, 0); + bfin_write(&mdma_d0->status, DMA_RUN | DMA_DONE | DMA_ERR); /* Scratchpad cannot be a DMA source or destination */ - if (((unsigned long)src >= L1_SRAM_SCRATCH && - (unsigned long)src < L1_SRAM_SCRATCH_END) || - ((unsigned long)dst >= L1_SRAM_SCRATCH && - (unsigned long)dst < L1_SRAM_SCRATCH_END)) + if ((lsrc >= L1_SRAM_SCRATCH && lsrc < L1_SRAM_SCRATCH_END) || + (ldst >= L1_SRAM_SCRATCH && ldst < L1_SRAM_SCRATCH_END)) hang(); - if (((unsigned long)dst | (unsigned long)src | count) & 0x1) { - wdsize = WDSIZE_8; - mod = 1; - } else if (((unsigned long)dst | (unsigned long)src | count) & 0x2) { - wdsize = WDSIZE_16; - count >>= 1; - mod = 2; - } else { - wdsize = WDSIZE_32; - count >>= 2; - mod = 4; - } + dma_calc_size(ldst, lsrc, count, &dshift, &bpos); + dsize = bpos << dshift; + count >>= bpos; + mod = 1 << bpos; + +#ifdef PSIZE + dsize |= min(3, bpos) << PSIZE_P; +#endif /* Copy sram functions from sdram to sram */ /* Setup destination start address */ - bfin_write_MDMA_D0_START_ADDR(dst); + bfin_write(&mdma_d0->start_addr, ldst); /* Setup destination xcount */ - bfin_write_MDMA_D0_X_COUNT(count); + bfin_write(&mdma_d0->x_count, count); /* Setup destination xmodify */ - bfin_write_MDMA_D0_X_MODIFY(mod); + bfin_write(&mdma_d0->x_modify, mod); /* Setup Source start address */ - bfin_write_MDMA_S0_START_ADDR(src); + bfin_write(&mdma_s0->start_addr, lsrc); /* Setup Source xcount */ - bfin_write_MDMA_S0_X_COUNT(count); + bfin_write(&mdma_s0->x_count, count); /* Setup Source xmodify */ - bfin_write_MDMA_S0_X_MODIFY(mod); + bfin_write(&mdma_s0->x_modify, mod); /* Enable source DMA */ - bfin_write_MDMA_S0_CONFIG(wdsize | DMAEN); - bfin_write_MDMA_D0_CONFIG(wdsize | DMAEN | WNR | DI_EN); + bfin_write(&mdma_s0->config, dsize | DMAEN); + bfin_write(&mdma_d0->config, dsize | DMAEN | WNR | DI_EN); SSYNC(); - while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) + while (!(bfin_read(&mdma_d0->status) & DMA_DONE)) continue; - bfin_write_MDMA_D0_IRQ_STATUS(DMA_RUN | DMA_DONE | DMA_ERR); - bfin_write_MDMA_D0_CONFIG(0); - bfin_write_MDMA_S0_CONFIG(0); + bfin_write(&mdma_d0->status, DMA_RUN | DMA_DONE | DMA_ERR); + bfin_write(&mdma_d0->config, 0); + bfin_write(&mdma_s0->config, 0); } /* We should do a dcache invalidate on the destination after the dma, but since * we lack such hardware capability, we'll flush/invalidate the destination -- cgit v1.2.3 From 7677d65f6522b1a911ac3a24225ec29709106010 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Tue, 25 Oct 2011 18:07:58 +0800 Subject: blackfin: bf60x: support big cplb page BF60x support 16K, 64K, 16M and 64M cplb pages, this patch add support for them. So that bf609-ezkit can use it's 128M memory. Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang --- arch/blackfin/include/asm/cplb.h | 31 +++++++++++++++++++++++++++---- arch/blackfin/lib/board.c | 19 +++++++++++++++++-- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/arch/blackfin/include/asm/cplb.h b/arch/blackfin/include/asm/cplb.h index cc21e93a18..420380dab1 100644 --- a/arch/blackfin/include/asm/cplb.h +++ b/arch/blackfin/include/asm/cplb.h @@ -46,8 +46,13 @@ #define CPLB_IDOCACHE CPLB_INOCACHE | CPLB_L1_CHBL /* Data Attibutes*/ - -#define SDRAM_IGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID) +#if defined(__ADSPBF60x__) +#define SDRAM_IGENERIC (PAGE_SIZE_16MB | CPLB_L1_CHBL | \ + CPLB_USER_RD | CPLB_VALID) +#else +#define SDRAM_IGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | \ + CPLB_USER_RD | CPLB_VALID) +#endif #define SDRAM_IKERNEL (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_VALID | CPLB_LOCK) #define L1_IMEMORY (PAGE_SIZE_1MB | CPLB_USER_RD | CPLB_VALID | CPLB_LOCK) #define SDRAM_INON_CHBL (PAGE_SIZE_4MB | CPLB_USER_RD | CPLB_VALID) @@ -59,14 +64,32 @@ #endif #ifdef CONFIG_DCACHE_WB /*Write Back Policy */ -#define SDRAM_DGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_DIRTY | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND) +#if defined(__ADSPBF60x__) +#define SDRAM_DGENERIC (PAGE_SIZE_16MB | CPLB_L1_CHBL | CPLB_DIRTY | \ + CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | \ + CPLB_VALID | ANOMALY_05000158_WORKAROUND) +#else +#define SDRAM_DGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_DIRTY | \ + CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | \ + CPLB_VALID | ANOMALY_05000158_WORKAROUND) +#endif #define SDRAM_DNON_CHBL (PAGE_SIZE_4MB | CPLB_DIRTY | CPLB_SUPV_WR | CPLB_USER_RD | CPLB_USER_WR | CPLB_VALID | ANOMALY_05000158_WORKAROUND) #define SDRAM_DKERNEL (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_USER_RD | CPLB_USER_WR | CPLB_DIRTY | CPLB_SUPV_WR | CPLB_VALID | CPLB_LOCK | ANOMALY_05000158_WORKAROUND) #define L1_DMEMORY (PAGE_SIZE_4MB | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND) #define SDRAM_EBIU (PAGE_SIZE_4MB | CPLB_DIRTY | CPLB_USER_RD | CPLB_USER_WR | CPLB_SUPV_WR | CPLB_VALID | ANOMALY_05000158_WORKAROUND) #else /*Write Through */ -#define SDRAM_DGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_RD | CPLB_USER_WR | CPLB_VALID | ANOMALY_05000158_WORKAROUND) +#if defined(__ADSPBF60x__) +#define SDRAM_DGENERIC (PAGE_SIZE_16MB | CPLB_L1_CHBL | CPLB_WT | \ + CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_RD | \ + CPLB_USER_WR | CPLB_VALID | \ + ANOMALY_05000158_WORKAROUND) +#else +#define SDRAM_DGENERIC (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_WT | \ + CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_RD | \ + CPLB_USER_WR | CPLB_VALID | \ + ANOMALY_05000158_WORKAROUND) +#endif #define SDRAM_DNON_CHBL (PAGE_SIZE_4MB | CPLB_WT | CPLB_L1_AOW | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_USER_RD | CPLB_VALID | ANOMALY_05000158_WORKAROUND) #define SDRAM_DKERNEL (PAGE_SIZE_4MB | CPLB_L1_CHBL | CPLB_WT | CPLB_L1_AOW | CPLB_USER_RD | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_VALID | CPLB_LOCK | ANOMALY_05000158_WORKAROUND) #define L1_DMEMORY (PAGE_SIZE_4MB | CPLB_SUPV_WR | CPLB_USER_WR | CPLB_VALID | ANOMALY_05000158_WORKAROUND) diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 098f685ccb..288dc829d4 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -96,6 +96,13 @@ static void display_global_data(void) #define CPLB_PAGE_SIZE (4 * 1024 * 1024) #define CPLB_PAGE_MASK (~(CPLB_PAGE_SIZE - 1)) +#if defined(__ADSPBF60x__) +#define CPLB_EX_PAGE_SIZE (16 * 1024 * 1024) +#define CPLB_EX_PAGE_MASK (~(CPLB_EX_PAGE_SIZE - 1)) +#else +#define CPLB_EX_PAGE_SIZE CPLB_PAGE_SIZE +#define CPLB_EX_PAGE_MASK CPLB_PAGE_MASK +#endif void init_cplbtables(void) { volatile uint32_t *ICPLB_ADDR, *ICPLB_DATA; @@ -127,6 +134,11 @@ void init_cplbtables(void) icplb_add(0xFFA00000, L1_IMEMORY); dcplb_add(0xFF800000, L1_DMEMORY); ++i; +#if defined(__ADSPBF60x__) + icplb_add(0x0, 0x0); + dcplb_add(CONFIG_SYS_FLASH_BASE, SDRAM_EBIU); + ++i; +#endif if (CONFIG_MEM_SIZE) { uint32_t mbase = CONFIG_SYS_MONITOR_BASE; @@ -150,9 +162,11 @@ void init_cplbtables(void) } } +#ifndef __ADSPBF60x__ icplb_add(0x20000000, SDRAM_INON_CHBL); dcplb_add(0x20000000, SDRAM_EBIU); ++i; +#endif /* Add entries for the rest of external RAM up to the bootrom */ extern_memory = 0; @@ -167,10 +181,11 @@ void init_cplbtables(void) ++i; #endif - while (i < 16 && extern_memory < (CONFIG_SYS_MONITOR_BASE & CPLB_PAGE_MASK)) { + while (i < 16 && extern_memory < + (CONFIG_SYS_MONITOR_BASE & CPLB_EX_PAGE_MASK)) { icplb_add(extern_memory, SDRAM_IGENERIC); dcplb_add(extern_memory, SDRAM_DGENERIC); - extern_memory += CPLB_PAGE_SIZE; + extern_memory += CPLB_EX_PAGE_SIZE; ++i; } while (i < 16) { -- cgit v1.2.3 From c34346d85dcb3fc84a110bf578b698c6a65af91d Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Thu, 16 Aug 2012 11:40:30 +0800 Subject: blackfin: bf60x: add gpio support Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang --- arch/blackfin/cpu/gpio.c | 36 +++++-- arch/blackfin/include/asm/gpio.h | 2 +- arch/blackfin/include/asm/mach-bf609/gpio.h | 151 ++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+), 8 deletions(-) create mode 100644 arch/blackfin/include/asm/mach-bf609/gpio.h diff --git a/arch/blackfin/cpu/gpio.c b/arch/blackfin/cpu/gpio.c index 5674d42b6d..f684be531c 100644 --- a/arch/blackfin/cpu/gpio.c +++ b/arch/blackfin/cpu/gpio.c @@ -66,6 +66,14 @@ static struct gpio_port_t * const gpio_array[] = { (struct gpio_port_t *)PORTH_FER, (struct gpio_port_t *)PORTI_FER, (struct gpio_port_t *)PORTJ_FER, +#elif defined(CONFIG_BF60x) + (struct gpio_port_t *)PORTA_FER, + (struct gpio_port_t *)PORTB_FER, + (struct gpio_port_t *)PORTC_FER, + (struct gpio_port_t *)PORTD_FER, + (struct gpio_port_t *)PORTE_FER, + (struct gpio_port_t *)PORTF_FER, + (struct gpio_port_t *)PORTG_FER, #else # error no gpio arrays defined #endif @@ -216,6 +224,12 @@ static void port_setup(unsigned gpio, unsigned short usage) else gpio_array[gpio_bank(gpio)]->port_fer |= gpio_bit(gpio); SSYNC(); +#elif defined(CONFIG_BF60x) + if (usage == GPIO_USAGE) + gpio_array[gpio_bank(gpio)]->port_fer_clear = gpio_bit(gpio); + else + gpio_array[gpio_bank(gpio)]->port_fer_set = gpio_bit(gpio); + SSYNC(); #endif } @@ -290,7 +304,7 @@ static void portmux_setup(unsigned short per) } } } -#elif defined(CONFIG_BF54x) +#elif defined(CONFIG_BF54x) || defined(CONFIG_BF60x) inline void portmux_setup(unsigned short per) { u32 pmux; @@ -330,7 +344,7 @@ inline void portmux_setup(unsigned short per) # define portmux_setup(...) do { } while (0) #endif -#ifndef CONFIG_BF54x +#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x) /*********************************************************** * * FUNCTIONS: Blackfin General Purpose Ports Access Functions @@ -534,7 +548,7 @@ int peripheral_request(unsigned short per, const char *label) * be requested and used by several drivers */ -#ifdef CONFIG_BF54x +#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) if (!((per & P_MAYSHARE) && get_portmux(per) == P_FUNCT2MUX(per))) { #else if (!(per & P_MAYSHARE)) { @@ -651,7 +665,7 @@ int bfin_gpio_request(unsigned gpio, const char *label) gpio, get_label(gpio)); return -EBUSY; } -#ifndef CONFIG_BF54x +#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x) else { /* Reset POLAR setting when acquiring a gpio for the first time */ set_gpio_polar(gpio, 0); } @@ -732,12 +746,16 @@ void bfin_special_gpio_free(unsigned gpio) static inline void __bfin_gpio_direction_input(unsigned gpio) { -#ifdef CONFIG_BF54x +#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) gpio_array[gpio_bank(gpio)]->dir_clear = gpio_bit(gpio); #else gpio_array[gpio_bank(gpio)]->dir &= ~gpio_bit(gpio); #endif +#if defined(CONFIG_BF60x) + gpio_array[gpio_bank(gpio)]->inen_set = gpio_bit(gpio); +#else gpio_array[gpio_bank(gpio)]->inen |= gpio_bit(gpio); +#endif } int bfin_gpio_direction_input(unsigned gpio) @@ -785,9 +803,13 @@ int bfin_gpio_direction_output(unsigned gpio, int value) local_irq_save(flags); +#if defined(CONFIG_BF60x) + gpio_array[gpio_bank(gpio)]->inen_clear = gpio_bit(gpio); +#else gpio_array[gpio_bank(gpio)]->inen &= ~gpio_bit(gpio); +#endif gpio_set_value(gpio, value); -#ifdef CONFIG_BF54x +#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) gpio_array[gpio_bank(gpio)]->dir_set = gpio_bit(gpio); #else gpio_array[gpio_bank(gpio)]->dir |= gpio_bit(gpio); @@ -801,7 +823,7 @@ int bfin_gpio_direction_output(unsigned gpio, int value) int bfin_gpio_get_value(unsigned gpio) { -#ifdef CONFIG_BF54x +#if defined(CONFIG_BF54x) || defined(CONFIG_BF60x) return (1 & (gpio_array[gpio_bank(gpio)]->data >> gpio_sub_n(gpio))); #else unsigned long flags; diff --git a/arch/blackfin/include/asm/gpio.h b/arch/blackfin/include/asm/gpio.h index 224688fc54..05131b5e8b 100644 --- a/arch/blackfin/include/asm/gpio.h +++ b/arch/blackfin/include/asm/gpio.h @@ -68,7 +68,7 @@ #ifndef __ASSEMBLY__ -#ifndef CONFIG_BF54x +#if !defined(CONFIG_BF54x) && !defined(CONFIG_BF60x) void set_gpio_dir(unsigned, unsigned short); void set_gpio_inen(unsigned, unsigned short); void set_gpio_polar(unsigned, unsigned short); diff --git a/arch/blackfin/include/asm/mach-bf609/gpio.h b/arch/blackfin/include/asm/mach-bf609/gpio.h new file mode 100644 index 0000000000..e297bcc833 --- /dev/null +++ b/arch/blackfin/include/asm/mach-bf609/gpio.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2008 Analog Devices Inc. + * Licensed under the GPL-2 or later. + */ + +#ifndef _MACH_GPIO_H_ +#define _MACH_GPIO_H_ + +#define MAX_BLACKFIN_GPIOS 112 + +#define GPIO_PA0 0 +#define GPIO_PA1 1 +#define GPIO_PA2 2 +#define GPIO_PA3 3 +#define GPIO_PA4 4 +#define GPIO_PA5 5 +#define GPIO_PA6 6 +#define GPIO_PA7 7 +#define GPIO_PA8 8 +#define GPIO_PA9 9 +#define GPIO_PA10 10 +#define GPIO_PA11 11 +#define GPIO_PA12 12 +#define GPIO_PA13 13 +#define GPIO_PA14 14 +#define GPIO_PA15 15 +#define GPIO_PB0 16 +#define GPIO_PB1 17 +#define GPIO_PB2 18 +#define GPIO_PB3 19 +#define GPIO_PB4 20 +#define GPIO_PB5 21 +#define GPIO_PB6 22 +#define GPIO_PB7 23 +#define GPIO_PB8 24 +#define GPIO_PB9 25 +#define GPIO_PB10 26 +#define GPIO_PB11 27 +#define GPIO_PB12 28 +#define GPIO_PB13 29 +#define GPIO_PB14 30 +#define GPIO_PB15 31 +#define GPIO_PC0 32 +#define GPIO_PC1 33 +#define GPIO_PC2 34 +#define GPIO_PC3 35 +#define GPIO_PC4 36 +#define GPIO_PC5 37 +#define GPIO_PC6 38 +#define GPIO_PC7 39 +#define GPIO_PC8 40 +#define GPIO_PC9 41 +#define GPIO_PC10 42 +#define GPIO_PC11 43 +#define GPIO_PC12 44 +#define GPIO_PC13 45 +#define GPIO_PC14 46 +#define GPIO_PC15 47 +#define GPIO_PD0 48 +#define GPIO_PD1 49 +#define GPIO_PD2 50 +#define GPIO_PD3 51 +#define GPIO_PD4 52 +#define GPIO_PD5 53 +#define GPIO_PD6 54 +#define GPIO_PD7 55 +#define GPIO_PD8 56 +#define GPIO_PD9 57 +#define GPIO_PD10 58 +#define GPIO_PD11 59 +#define GPIO_PD12 60 +#define GPIO_PD13 61 +#define GPIO_PD14 62 +#define GPIO_PD15 63 +#define GPIO_PE0 64 +#define GPIO_PE1 65 +#define GPIO_PE2 66 +#define GPIO_PE3 67 +#define GPIO_PE4 68 +#define GPIO_PE5 69 +#define GPIO_PE6 70 +#define GPIO_PE7 71 +#define GPIO_PE8 72 +#define GPIO_PE9 73 +#define GPIO_PE10 74 +#define GPIO_PE11 75 +#define GPIO_PE12 76 +#define GPIO_PE13 77 +#define GPIO_PE14 78 +#define GPIO_PE15 79 +#define GPIO_PF0 80 +#define GPIO_PF1 81 +#define GPIO_PF2 82 +#define GPIO_PF3 83 +#define GPIO_PF4 84 +#define GPIO_PF5 85 +#define GPIO_PF6 86 +#define GPIO_PF7 87 +#define GPIO_PF8 88 +#define GPIO_PF9 89 +#define GPIO_PF10 90 +#define GPIO_PF11 91 +#define GPIO_PF12 92 +#define GPIO_PF13 93 +#define GPIO_PF14 94 +#define GPIO_PF15 95 +#define GPIO_PG0 96 +#define GPIO_PG1 97 +#define GPIO_PG2 98 +#define GPIO_PG3 99 +#define GPIO_PG4 100 +#define GPIO_PG5 101 +#define GPIO_PG6 102 +#define GPIO_PG7 103 +#define GPIO_PG8 104 +#define GPIO_PG9 105 +#define GPIO_PG10 106 +#define GPIO_PG11 107 +#define GPIO_PG12 108 +#define GPIO_PG13 109 +#define GPIO_PG14 110 +#define GPIO_PG15 111 + +#ifndef __ASSEMBLY__ + +struct gpio_port_t { + unsigned long port_fer; + unsigned long port_fer_set; + unsigned long port_fer_clear; + unsigned long data; + unsigned long data_set; + unsigned long data_clear; + unsigned long dir; + unsigned long dir_set; + unsigned long dir_clear; + unsigned long inen; + unsigned long inen_set; + unsigned long inen_clear; + unsigned long port_mux; + unsigned long toggle; + unsigned long polar; + unsigned long polar_set; + unsigned long polar_clear; + unsigned long lock; + unsigned long spare; + unsigned long revid; +}; + +#endif + +#endif /* _MACH_GPIO_H_ */ -- cgit v1.2.3 From 320ec9dfb72219116f1879d1be0d49e7d3baaad8 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 16 Aug 2012 12:08:31 +0800 Subject: blackfin: bf60x: add board and headers files to support bf609 Board and config header files for bf609-ezkit support. Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang --- MAINTAINERS | 3 +- board/bf609-ezkit/Makefile | 55 +++++++++++++ board/bf609-ezkit/bf609-ezkit.c | 67 ++++++++++++++++ boards.cfg | 1 + include/configs/bf609-ezkit.h | 161 ++++++++++++++++++++++++++++++++++++++ include/configs/bfin_adi_common.h | 8 +- 6 files changed, 291 insertions(+), 4 deletions(-) create mode 100644 board/bf609-ezkit/Makefile create mode 100644 board/bf609-ezkit/bf609-ezkit.c create mode 100644 include/configs/bf609-ezkit.h diff --git a/MAINTAINERS b/MAINTAINERS index 45e2dd4541..8603085f30 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1226,7 +1226,7 @@ Yoshihiro Shimoda # Board CPU # ######################################################################### -Mike Frysinger +Sonic Zhang Blackfin Team BF506F-EZKIT BF506 @@ -1243,6 +1243,7 @@ Blackfin Team BF538F-EZKIT BF538 BF548-EZKIT BF548 BF561-EZKIT BF561 + BF609-EZKIT BF609 M.Hasewinkel (MHA) diff --git a/board/bf609-ezkit/Makefile b/board/bf609-ezkit/Makefile new file mode 100644 index 0000000000..0bb8fe643e --- /dev/null +++ b/board/bf609-ezkit/Makefile @@ -0,0 +1,55 @@ +# +# U-boot - Makefile +# +# Copyright (c) 2005-2008 Analog Device Inc. +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)lib$(BOARD).o + +COBJS-y := $(BOARD).o +COBJS-$(CONFIG_BFIN_SOFT_SWITCH) += soft_switch.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS-y)) +SOBJS := $(addprefix $(obj),$(SOBJS-y)) + +$(LIB): $(obj).depend $(OBJS) $(SOBJS) + $(call cmd_link_o_target, $(OBJS) $(SOBJS)) + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/bf609-ezkit/bf609-ezkit.c b/board/bf609-ezkit/bf609-ezkit.c new file mode 100644 index 0000000000..0388226db4 --- /dev/null +++ b/board/bf609-ezkit/bf609-ezkit.c @@ -0,0 +1,67 @@ +/* + * U-boot - main board file + * + * Copyright (c) 2008-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#include +#include +#include +#include +#include +#include "soft_switch.h" + +int checkboard(void) +{ + printf("Board: ADI BF609 EZ-Kit board\n"); + printf(" Support: http://blackfin.uclinux.org/\n"); + return 0; +} + +int board_early_init_f(void) +{ + static const unsigned short pins[] = { + P_A3, P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12, + P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21, + P_A22, P_A23, P_A24, P_A25, P_NORCK, 0, + }; + peripheral_request_list(pins, "smc0"); + + return 0; +} + +#ifdef CONFIG_DESIGNWARE_ETH +int board_eth_init(bd_t *bis) +{ + int ret = 0; + + if (CONFIG_DW_PORTS & 1) { + static const unsigned short pins[] = P_RMII0; + if (!peripheral_request_list(pins, "emac0")) + ret += designware_initialize(0, EMAC0_MACCFG, 1, 0); + } + if (CONFIG_DW_PORTS & 2) { + static const unsigned short pins[] = P_RMII1; + if (!peripheral_request_list(pins, "emac1")) + ret += designware_initialize(1, EMAC1_MACCFG, 1, 0); + } + + return ret; +} +#endif + +#ifdef CONFIG_BFIN_SDH +int board_mmc_init(bd_t *bis) +{ + return bfin_mmc_init(bis); +} +#endif + +/* miscellaneous platform dependent initialisations */ +int misc_init_r(void) +{ + printf("other init\n"); + return setup_board_switches(); +} diff --git a/boards.cfg b/boards.cfg index 7f772a0840..136ea0ae29 100644 --- a/boards.cfg +++ b/boards.cfg @@ -361,6 +361,7 @@ bf538f-ezkit blackfin blackfin bf548-ezkit blackfin blackfin bf561-acvilon blackfin blackfin bf561-ezkit blackfin blackfin +bf609-ezkit blackfin blackfin blackstamp blackfin blackfin blackvme blackfin blackfin br4 blackfin blackfin diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h new file mode 100644 index 0000000000..6dffab86dc --- /dev/null +++ b/include/configs/bf609-ezkit.h @@ -0,0 +1,161 @@ +/* + * U-boot - Configuration file for BF609 EZ-Kit board + */ + +#ifndef __CONFIG_BF609_EZKIT_H__ +#define __CONFIG_BF609_EZKIT_H__ + +#include + +/* + * Processor Settings + */ +#define CONFIG_BFIN_CPU bf609-0.0 +#define CONFIG_BFIN_BOOT_MODE BFIN_BOOT_PARA + + +/* For ez-board version 1.0, else undef this */ +#define CONFIG_BFIN_BOARD_VERSION_1_0 + +/* + * Clock Settings + * CCLK = (CLKIN * VCO_MULT) / CCLK_DIV + * SCLK = (CLKIN * VCO_MULT) / SYSCLK_DIV + * SCLK0 = SCLK / SCLK0_DIV + * SCLK1 = SCLK / SCLK1_DIV + */ +/* CONFIG_CLKIN_HZ is any value in Hz */ +#define CONFIG_CLKIN_HZ (25000000) +/* CLKIN_HALF controls the DF bit in PLL_CTL 0 = CLKIN */ +/* 1 = CLKIN / 2 */ +#define CONFIG_CLKIN_HALF (0) + +/* VCO_MULT controls the MSEL (multiplier) bits in PLL_CTL */ +/* Values can range from 0-127 (where 0 means 128) */ +#define CONFIG_VCO_MULT (20) + +/* CCLK_DIV controls the core clock divider */ +/* Values can range from 0-31 (where 0 means 32) */ +#define CONFIG_CCLK_DIV (1) +/* SCLK_DIV controls the system clock divider */ +/* Values can range from 0-31 (where 0 means 32) */ +#define CONFIG_SCLK_DIV (4) +/* Values can range from 0-7 (where 0 means 8) */ +#define CONFIG_SCLK0_DIV (1) +#define CONFIG_SCLK1_DIV (1) +/* DCLK_DIV controls the DDR clock divider */ +/* Values can range from 0-31 (where 0 means 32) */ +#define CONFIG_DCLK_DIV (2) +/* OCLK_DIV controls the output clock divider */ +/* Values can range from 0-127 (where 0 means 128) */ +#define CONFIG_OCLK_DIV (16) + +/* + * Memory Settings + */ +#define CONFIG_MEM_SIZE 128 + +#define CONFIG_SMC_GCTL_VAL 0x00000010 +#define CONFIG_SMC_B0CTL_VAL 0x01007011 +#define CONFIG_SMC_B0TIM_VAL 0x08170977 +#define CONFIG_SMC_B0ETIM_VAL 0x00092231 + +#define CONFIG_SYS_MONITOR_LEN (768 * 1024) +#define CONFIG_SYS_MALLOC_LEN (512 * 1024) + +/* + * Network Settings + */ +#define ADI_CMDS_NETWORK +#define CONFIG_NETCONSOLE +#define CONFIG_NET_MULTI +#define CONFIG_HOSTNAME "bf609-ezkit" +#define CONFIG_DESIGNWARE_ETH +#define CONFIG_DW_PORTS 1 +#define CONFIG_DW_AUTONEG +#define CONFIG_DW_ALTDESCRIPTOR +#define CONFIG_CMD_NET +#define CONFIG_CMD_MII +#define CONFIG_MII + +/* i2c Settings */ +#define CONFIG_BFIN_TWI_I2C +#define CONFIG_HARD_I2C + +/* + * Flash Settings + */ +#undef CONFIG_CMD_IMLS +#undef CONFIG_CMD_JFFS2 +#define CONFIG_SYS_FLASH_CFI_WIDTH 2 +#define CONFIG_FLASH_CFI_DRIVER +#define CONFIG_SYS_FLASH_BASE 0xb0000000 +#define CONFIG_SYS_FLASH_CFI +#define CONFIG_SYS_FLASH_PROTECTION +#define CONFIG_SYS_MAX_FLASH_BANKS 1 +#define CONFIG_SYS_MAX_FLASH_SECT 131 +#define CONFIG_CFI_FLASH_USE_WEAK_ACCESSORS + +/* + * SPI Settings + */ +#define CONFIG_BFIN_SPI6XX +#define CONFIG_ENV_SPI_MAX_HZ 25000000 +#define CONFIG_SF_DEFAULT_SPEED 25000000 +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_ALL + +/* + * Env Storage Settings + */ +#if (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_SPI_MASTER) +#define CONFIG_ENV_IS_IN_SPI_FLASH +#define CONFIG_ENV_OFFSET 0x10000 +#define CONFIG_ENV_SIZE 0x2000 +#define CONFIG_ENV_SECT_SIZE 0x10000 +#define CONFIG_ENV_IS_EMBEDDED_IN_LDR +#elif (CONFIG_BFIN_BOOT_MODE == BFIN_BOOT_NAND) +#define CONFIG_ENV_IS_IN_NAND +#define CONFIG_ENV_OFFSET 0x60000 +#define CONFIG_ENV_SIZE 0x20000 +#else +#define CONFIG_ENV_IS_IN_FLASH +#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET) +#define CONFIG_ENV_OFFSET 0x8000 +#define CONFIG_ENV_SIZE 0x8000 +#define CONFIG_ENV_SECT_SIZE 0x8000 +#define CONFIG_ENV_IS_EMBEDDED_IN_LDR +#endif + +#define FLASHBOOT_ENV_SETTINGS "flashboot=bootm 0xB0100000\0" + +/* + * SDH Settings + */ +#define CONFIG_GENERIC_MMC +#define CONFIG_MMC +#define CONFIG_BFIN_SDH + +/* + * Misc Settings + */ +#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_UART_CONSOLE 0 + +#define CONFIG_CMD_MEMORY + +#define CONFIG_SYS_MEMTEST_END (CONFIG_STACKBASE - 20*1024*1024 + 4) +#define CONFIG_BFIN_SOFT_SWITCH + +#if 0 +#define CONFIG_UART_MEM 1024 +#undef CONFIG_UART_CONSOLE +#undef CONFIG_JTAG_CONSOLE +#undef CONFIG_UART_CONSOLE_IS_JTAG +#endif + +/* + * Pull in common ADI header for remaining command/environment setup + */ +#include +#endif diff --git a/include/configs/bfin_adi_common.h b/include/configs/bfin_adi_common.h index ccdec0d564..d3ae3a71cd 100644 --- a/include/configs/bfin_adi_common.h +++ b/include/configs/bfin_adi_common.h @@ -10,7 +10,7 @@ */ #ifndef _CONFIG_CMD_DEFAULT_H # include -# if ADI_CMDS_NETWORK +# ifdef ADI_CMDS_NETWORK # define CONFIG_CMD_DHCP # define CONFIG_BOOTP_SUBNETMASK # define CONFIG_BOOTP_GATEWAY @@ -58,7 +58,7 @@ # endif # ifdef CONFIG_RTC_BFIN # define CONFIG_CMD_DATE -# if ADI_CMDS_NETWORK +# ifdef ADI_CMDS_NETWORK # define CONFIG_CMD_SNTP # endif # endif @@ -193,10 +193,12 @@ "nand erase 0 0x40000;" \ "nand write $(loadaddr) 0 0x40000" # else -# define UBOOT_ENV_UPDATE \ +# ifndef UBOOT_ENV_UPDATE +# define UBOOT_ENV_UPDATE \ "protect off 0x20000000 +$(filesize);" \ "erase 0x20000000 +$(filesize);" \ "cp.b $(loadaddr) 0x20000000 $(filesize)" +# endif # endif # ifdef CONFIG_NETCONSOLE # define NETCONSOLE_ENV \ -- cgit v1.2.3 From 187f32fac33be46177968e7ceeb8ab99836a6601 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 16 Aug 2012 11:26:00 +0800 Subject: blackfin: bf60x: add rsi/sdh support Add rsi/sdh support for bf60x. Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang --- arch/blackfin/include/asm/mach-common/bits/sdh.h | 38 ++++++++++++- drivers/mmc/bfin_sdh.c | 68 ++++++++++++++++++------ 2 files changed, 88 insertions(+), 18 deletions(-) diff --git a/arch/blackfin/include/asm/mach-common/bits/sdh.h b/arch/blackfin/include/asm/mach-common/bits/sdh.h index 8c5dd33f5c..1c60d4b831 100644 --- a/arch/blackfin/include/asm/mach-common/bits/sdh.h +++ b/arch/blackfin/include/asm/mach-common/bits/sdh.h @@ -12,18 +12,35 @@ #define CMD_INT_E 0x100 /* Command Interrupt */ #define CMD_PEND_E 0x200 /* Command Pending */ #define CMD_E 0x400 /* Command Enable */ +#ifdef RSI_BLKSZ +#define CMD_CRC_CHECK_D 0x800 /* CRC Check is disabled */ +#define CMD_DATA0_BUSY 0x1000 /* Check Busy State on DATA0 */ +#endif /* Bit masks for SDH_PWR_CTL */ +#ifndef RSI_BLKSZ #define PWR_ON 0x3 /* Power On */ #define SD_CMD_OD 0x40 /* Open Drain Output */ #define ROD_CTL 0x80 /* Rod Control */ +#endif /* Bit masks for SDH_CLK_CTL */ #define CLKDIV 0xff /* MC_CLK Divisor */ #define CLK_E 0x100 /* MC_CLK Bus Clock Enable */ #define PWR_SV_E 0x200 /* Power Save Enable */ #define CLKDIV_BYPASS 0x400 /* Bypass Divisor */ -#define WIDE_BUS 0x800 /* Wide Bus Mode Enable */ +#define BUS_MODE_MASK 0x1800 /* Bus Mode Mask */ +#define STD_BUS_1 0x000 /* Standard Bus 1 bit mode */ +#define WIDE_BUS_4 0x800 /* Wide Bus 4 bit mode */ +#define BYTE_BUS_8 0x1000 /* Byte Bus 8 bit mode */ +#ifdef RSI_BLKSZ +#define CARD_TYPE_MASK 0xe000 /* Card type mask */ +#define CARD_TYPE_OFFSET 13 /* Card type offset */ +#define CARD_TYPE_SDIO 0 +#define CARD_TYPE_eMMC 1 +#define CARD_TYPE_SD 2 +#define CARD_TYPE_CEATA 3 +#endif /* Bit masks for SDH_RESP_CMD */ #define RESP_CMD 0x3f /* Response Command */ @@ -33,7 +50,13 @@ #define DTX_DIR 0x2 /* Data Transfer Direction */ #define DTX_MODE 0x4 /* Data Transfer Mode */ #define DTX_DMA_E 0x8 /* Data Transfer DMA Enable */ +#ifndef RSI_BLKSZ #define DTX_BLK_LGTH 0xf0 /* Data Transfer Block Length */ +#else + +/* Bit masks for SDH_BLK_SIZE */ +#define DTX_BLK_LGTH 0x1fff /* Data Transfer Block Length */ +#endif /* Bit masks for SDH_STATUS */ #define CMD_CRC_FAIL 0x1 /* CMD CRC Fail */ @@ -102,10 +125,13 @@ /* Bit masks for SDH_E_STATUS */ #define SDIO_INT_DET 0x2 /* SDIO Int Detected */ #define SD_CARD_DET 0x10 /* SD Card Detect */ +#define SD_CARD_BUSYMODE 0x80000000 /* Card is in Busy mode */ +#define SD_CARD_SLPMODE 0x40000000 /* Card in Sleep Mode */ +#define SD_CARD_READY 0x00020000 /* Card Ready */ /* Bit masks for SDH_E_MASK */ #define SDIO_MSK 0x2 /* Mask SDIO Int Detected */ -#define SCD_MSK 0x40 /* Mask Card Detect */ +#define SCD_MSK 0x10 /* Mask Card Detect */ /* Bit masks for SDH_CFG */ #define CLKS_EN 0x1 /* Clocks Enable */ @@ -114,7 +140,15 @@ #define SD_RST 0x10 /* SDMMC Reset */ #define PUP_SDDAT 0x20 /* Pull-up SD_DAT */ #define PUP_SDDAT3 0x40 /* Pull-up SD_DAT3 */ +#ifndef RSI_BLKSZ #define PD_SDDAT3 0x80 /* Pull-down SD_DAT3 */ +#else +#define PWR_ON 0x600 /* Power On */ +#define SD_CMD_OD 0x800 /* Open Drain Output */ +#define BOOT_EN 0x1000 /* Boot Enable */ +#define BOOT_MODE 0x2000 /* Alternate Boot Mode */ +#define BOOT_ACK_EN 0x4000 /* Boot ACK is expected */ +#endif /* Bit masks for SDH_RD_WAIT_EN */ #define RWR 0x1 /* Read Wait Request */ diff --git a/drivers/mmc/bfin_sdh.c b/drivers/mmc/bfin_sdh.c index 8d59d46c64..0f98b961fd 100644 --- a/drivers/mmc/bfin_sdh.c +++ b/drivers/mmc/bfin_sdh.c @@ -19,9 +19,7 @@ #include #include -#if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) -# define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CONTROL -# define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CONTROL +#if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF60x__) # define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CONTROL # define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CONTROL # define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT @@ -38,10 +36,21 @@ # define bfin_write_SDH_STATUS_CLR bfin_write_RSI_STATUSCL # define bfin_read_SDH_CFG bfin_read_RSI_CONFIG # define bfin_write_SDH_CFG bfin_write_RSI_CONFIG +# if defined(__ADSPBF60x__) +# define bfin_read_SDH_BLK_SIZE bfin_read_RSI_BLKSZ +# define bfin_write_SDH_BLK_SIZE bfin_write_RSI_BLKSZ +# define bfin_write_DMA_START_ADDR bfin_write_DMA10_START_ADDR +# define bfin_write_DMA_X_COUNT bfin_write_DMA10_X_COUNT +# define bfin_write_DMA_X_MODIFY bfin_write_DMA10_X_MODIFY +# define bfin_write_DMA_CONFIG bfin_write_DMA10_CONFIG +# else +# define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CONTROL +# define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CONTROL # define bfin_write_DMA_START_ADDR bfin_write_DMA4_START_ADDR # define bfin_write_DMA_X_COUNT bfin_write_DMA4_X_COUNT # define bfin_write_DMA_X_MODIFY bfin_write_DMA4_X_MODIFY # define bfin_write_DMA_CONFIG bfin_write_DMA4_CONFIG +# endif # define PORTMUX_PINS \ { P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3, P_RSI_CMD, P_RSI_CLK, 0 } #elif defined(__ADSPBF54x__) @@ -70,6 +79,9 @@ sdh_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd) sdh_cmd |= CMD_RSP; if (flags & MMC_RSP_136) sdh_cmd |= CMD_L_RSP; +#ifdef RSI_BLKSZ + sdh_cmd |= CMD_DATA0_BUSY; +#endif bfin_write_SDH_ARGUMENT(arg); bfin_write_SDH_COMMAND(sdh_cmd); @@ -104,6 +116,12 @@ sdh_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd) bfin_write_SDH_STATUS_CLR(CMD_SENT_STAT | CMD_RESP_END_STAT | CMD_TIMEOUT_STAT | CMD_CRC_FAIL_STAT); +#ifdef RSI_BLKSZ + /* wait till card ready */ + while (!(bfin_read_RSI_ESTAT() & SD_CARD_READY)) + continue; + bfin_write_RSI_ESTAT(SD_CARD_READY); +#endif return ret; } @@ -113,16 +131,19 @@ static int sdh_setup_data(struct mmc *mmc, struct mmc_data *data) { u16 data_ctl = 0; u16 dma_cfg = 0; - int ret = 0; unsigned long data_size = data->blocksize * data->blocks; /* Don't support write yet. */ if (data->flags & MMC_DATA_WRITE) return UNUSABLE_ERR; +#ifndef RSI_BLKSZ data_ctl |= ((ffs(data_size) - 1) << 4); +#else + bfin_write_SDH_BLK_SIZE(data_size); +#endif data_ctl |= DTX_DIR; bfin_write_SDH_DATA_CTL(data_ctl); - dma_cfg = WDSIZE_32 | RESTART | WNR | DMAEN; + dma_cfg = WDSIZE_32 | PSIZE_32 | RESTART | WNR | DMAEN; bfin_write_SDH_DATA_TIMER(-1); @@ -137,7 +158,7 @@ static int sdh_setup_data(struct mmc *mmc, struct mmc_data *data) /* kick off transfer */ bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E); - return ret; + return 0; } @@ -147,13 +168,23 @@ static int bfin_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd, u32 status; int ret = 0; + if (data) { + ret = sdh_setup_data(mmc, data); + if (ret) + return ret; + } + ret = sdh_send_cmd(mmc, cmd); if (ret) { + bfin_write_SDH_COMMAND(0); + bfin_write_DMA_CONFIG(0); + bfin_write_SDH_DATA_CTL(0); + SSYNC(); printf("sending CMD%d failed\n", cmd->cmdidx); return ret; } + if (data) { - ret = sdh_setup_data(mmc, data); do { udelay(1); status = bfin_read_SDH_STATUS(); @@ -208,10 +239,12 @@ static void bfin_sdh_set_ios(struct mmc *mmc) if (mmc->bus_width == 4) { cfg = bfin_read_SDH_CFG(); - cfg &= ~0x80; - cfg |= 0x40; +#ifndef RSI_BLKSZ + cfg &= ~PD_SDDAT3; +#endif + cfg |= PUP_SDDAT3; bfin_write_SDH_CFG(cfg); - clk_ctl |= WIDE_BUS; + clk_ctl |= WIDE_BUS_4; } bfin_write_SDH_CLK_CTL(clk_ctl); sdh_set_clk(mmc->clock); @@ -220,20 +253,23 @@ static void bfin_sdh_set_ios(struct mmc *mmc) static int bfin_sdh_init(struct mmc *mmc) { const unsigned short pins[] = PORTMUX_PINS; - u16 pwr_ctl = 0; + int ret; /* Initialize sdh controller */ - peripheral_request_list(pins, "bfin_sdh"); + ret = peripheral_request_list(pins, "bfin_sdh"); + if (ret < 0) + return ret; #if defined(__ADSPBF54x__) bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1); #endif bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN); /* Disable card detect pin */ bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | 0x60); - - pwr_ctl |= ROD_CTL; - pwr_ctl |= PWR_ON; - bfin_write_SDH_PWR_CTL(pwr_ctl); +#ifndef RSI_BLKSZ + bfin_write_SDH_PWR_CTL(PWR_ON | ROD_CTL); +#else + bfin_write_SDH_CFG(bfin_read_SDH_CFG() | PWR_ON); +#endif return 0; } -- cgit v1.2.3 From 4a207e8b9a1ecc3e87d5a63bb5442dbcd50bd4b6 Mon Sep 17 00:00:00 2001 From: Scott Jiang Date: Tue, 29 Nov 2011 18:03:26 -0500 Subject: blackfin: add bf6xx spi driver Spi driver for bf60x is different from old one, so implement a new driver for it. Signed-off-by: Scott Jiang Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang --- .../blackfin/include/asm/mach-common/bits/spi6xx.h | 240 ++++++++++++++++ drivers/spi/Makefile | 1 + drivers/spi/bfin_spi6xx.c | 308 +++++++++++++++++++++ 3 files changed, 549 insertions(+) create mode 100644 arch/blackfin/include/asm/mach-common/bits/spi6xx.h create mode 100644 drivers/spi/bfin_spi6xx.c diff --git a/arch/blackfin/include/asm/mach-common/bits/spi6xx.h b/arch/blackfin/include/asm/mach-common/bits/spi6xx.h new file mode 100644 index 0000000000..3368712e3f --- /dev/null +++ b/arch/blackfin/include/asm/mach-common/bits/spi6xx.h @@ -0,0 +1,240 @@ +/* + * Analog Devices bfin_spi3 controller driver + * + * Copyright (c) 2011 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _SPI_CHANNEL_H_ +#define _SPI_CHANNEL_H_ + +#include + +/* SPI_CONTROL */ +#define SPI_CTL_EN 0x00000001 /* Enable */ +#define SPI_CTL_MSTR 0x00000002 /* Master/Slave */ +#define SPI_CTL_PSSE 0x00000004 /* controls modf error in master mode */ +#define SPI_CTL_ODM 0x00000008 /* Open Drain Mode */ +#define SPI_CTL_CPHA 0x00000010 /* Clock Phase */ +#define SPI_CTL_CPOL 0x00000020 /* Clock Polarity */ +#define SPI_CTL_ASSEL 0x00000040 /* Slave Select Pin Control */ +#define SPI_CTL_SELST 0x00000080 /* Slave Select Polarity in transfers */ +#define SPI_CTL_EMISO 0x00000100 /*Enable MISO */ +#define SPI_CTL_SIZE 0x00000600 /*Word Transfer Size */ +#define SPI_CTL_SIZE08 0x00000000 /*SIZE: 8 bits */ +#define SPI_CTL_SIZE16 0x00000200 /*SIZE: 16 bits */ +#define SPI_CTL_SIZE32 0x00000400 /*SIZE: 32 bits */ +#define SPI_CTL_LSBF 0x00001000 /*LSB First */ +#define SPI_CTL_FCEN 0x00002000 /*Flow-Control Enable */ +#define SPI_CTL_FCCH 0x00004000 /*Flow-Control Channel Selection */ +#define SPI_CTL_FCPL 0x00008000 /*Flow-Control Polarity */ +#define SPI_CTL_FCWM 0x00030000 /*Flow-Control Water-Mark */ +#define SPI_CTL_FIFO0 0x00000000 /*FCWM: Tx empty or Rx Full */ +#define SPI_CTL_FIFO1 0x00010000 /*FCWM: Tx empty or Rx full (>=75%) */ +#define SPI_CTL_FIFO2 0x00020000 /*FCWM: Tx empty or Rx full (>=50%) */ +#define SPI_CTL_FMODE 0x00040000 /*Fast-mode Enable */ +#define SPI_CTL_MIOM 0x00300000 /*Multiple I/O Mode */ +#define SPI_CTL_MIO_DIS 0x00000000 /*MIOM: Disable */ +#define SPI_CTL_MIO_DUAL 0x00100000 /*MIOM: Enable DIOM (Dual I/O Mode) */ +#define SPI_CTL_MIO_QUAD 0x00200000 /*MIOM: Enable QUAD (Quad SPI Mode) */ +#define SPI_CTL_SOSI 0x00400000 /*Start on MOSI */ +/* SPI_RX_CONTROL */ +#define SPI_RXCTL_REN 0x00000001 /*Receive Channel Enable */ +#define SPI_RXCTL_RTI 0x00000004 /*Receive Transfer Initiate */ +#define SPI_RXCTL_RWCEN 0x00000008 /*Receive Word Counter Enable */ +#define SPI_RXCTL_RDR 0x00000070 /*Receive Data Request */ +#define SPI_RXCTL_RDR_DIS 0x00000000 /*RDR: Disabled */ +#define SPI_RXCTL_RDR_NE 0x00000010 /*RDR: RFIFO not empty */ +#define SPI_RXCTL_RDR_25 0x00000020 /*RDR: RFIFO 25% full */ +#define SPI_RXCTL_RDR_50 0x00000030 /*RDR: RFIFO 50% full */ +#define SPI_RXCTL_RDR_75 0x00000040 /*RDR: RFIFO 75% full */ +#define SPI_RXCTL_RDR_FULL 0x00000050 /*RDR: RFIFO full */ +#define SPI_RXCTL_RDO 0x00000100 /*Receive Data Over-Run */ +#define SPI_RXCTL_RRWM 0x00003000 /*FIFO Regular Water-Mark */ +#define SPI_RXCTL_RWM_0 0x00000000 /*RRWM: RFIFO Empty */ +#define SPI_RXCTL_RWM_25 0x00001000 /*RRWM: RFIFO 25% full */ +#define SPI_RXCTL_RWM_50 0x00002000 /*RRWM: RFIFO 50% full */ +#define SPI_RXCTL_RWM_75 0x00003000 /*RRWM: RFIFO 75% full */ +#define SPI_RXCTL_RUWM 0x00070000 /*FIFO Urgent Water-Mark */ +#define SPI_RXCTL_UWM_DIS 0x00000000 /*RUWM: Disabled */ +#define SPI_RXCTL_UWM_25 0x00010000 /*RUWM: RFIFO 25% full */ +#define SPI_RXCTL_UWM_50 0x00020000 /*RUWM: RFIFO 50% full */ +#define SPI_RXCTL_UWM_75 0x00030000 /*RUWM: RFIFO 75% full */ +#define SPI_RXCTL_UWM_FULL 0x00040000 /*RUWM: RFIFO full */ +/* SPI_TX_CONTROL */ +#define SPI_TXCTL_TEN 0x00000001 /*Transmit Channel Enable */ +#define SPI_TXCTL_TTI 0x00000004 /*Transmit Transfer Initiate */ +#define SPI_TXCTL_TWCEN 0x00000008 /*Transmit Word Counter Enable */ +#define SPI_TXCTL_TDR 0x00000070 /*Transmit Data Request */ +#define SPI_TXCTL_TDR_DIS 0x00000000 /*TDR: Disabled */ +#define SPI_TXCTL_TDR_NF 0x00000010 /*TDR: TFIFO not full */ +#define SPI_TXCTL_TDR_25 0x00000020 /*TDR: TFIFO 25% empty */ +#define SPI_TXCTL_TDR_50 0x00000030 /*TDR: TFIFO 50% empty */ +#define SPI_TXCTL_TDR_75 0x00000040 /*TDR: TFIFO 75% empty */ +#define SPI_TXCTL_TDR_EMPTY 0x00000050 /*TDR: TFIFO empty */ +#define SPI_TXCTL_TDU 0x00000100 /*Transmit Data Under-Run */ +#define SPI_TXCTL_TRWM 0x00003000 /*FIFO Regular Water-Mark */ +#define SPI_TXCTL_RWM_FULL 0x00000000 /*TRWM: TFIFO full */ +#define SPI_TXCTL_RWM_25 0x00001000 /*TRWM: TFIFO 25% empty */ +#define SPI_TXCTL_RWM_50 0x00002000 /*TRWM: TFIFO 50% empty */ +#define SPI_TXCTL_RWM_75 0x00003000 /*TRWM: TFIFO 75% empty */ +#define SPI_TXCTL_TUWM 0x00070000 /*FIFO Urgent Water-Mark */ +#define SPI_TXCTL_UWM_DIS 0x00000000 /*TUWM: Disabled */ +#define SPI_TXCTL_UWM_25 0x00010000 /*TUWM: TFIFO 25% empty */ +#define SPI_TXCTL_UWM_50 0x00020000 /*TUWM: TFIFO 50% empty */ +#define SPI_TXCTL_UWM_75 0x00030000 /*TUWM: TFIFO 75% empty */ +#define SPI_TXCTL_UWM_EMPTY 0x00040000 /*TUWM: TFIFO empty */ +/* SPI_CLOCK */ +#define SPI_CLK_BAUD 0x0000FFFF /*Baud Rate */ +/* SPI_DELAY */ +#define SPI_DLY_STOP 0x000000FF /*Transfer delay time */ +#define SPI_DLY_LEADX 0x00000100 /*Extended (1 SCK) LEAD Control */ +#define SPI_DLY_LAGX 0x00000200 /*Extended (1 SCK) LAG control */ +/* SPI_SSEL */ +#define SPI_SLVSEL_SSE1 0x00000002 /*SPISSEL1 Enable */ +#define SPI_SLVSEL_SSE2 0x00000004 /*SPISSEL2 Enable */ +#define SPI_SLVSEL_SSE3 0x00000008 /*SPISSEL3 Enable */ +#define SPI_SLVSEL_SSE4 0x00000010 /*SPISSEL4 Enable */ +#define SPI_SLVSEL_SSE5 0x00000020 /*SPISSEL5 Enable */ +#define SPI_SLVSEL_SSE6 0x00000040 /*SPISSEL6 Enable */ +#define SPI_SLVSEL_SSE7 0x00000080 /*SPISSEL7 Enable */ +#define SPI_SLVSEL_SSEL1 0x00000200 /*SPISSEL1 Value */ +#define SPI_SLVSEL_SSEL2 0x00000400 /*SPISSEL2 Value */ +#define SPI_SLVSEL_SSEL3 0x00000800 /*SPISSEL3 Value */ +#define SPI_SLVSEL_SSEL4 0x00001000 /*SPISSEL4 Value */ +#define SPI_SLVSEL_SSEL5 0x00002000 /*SPISSEL5 Value */ +#define SPI_SLVSEL_SSEL6 0x00004000 /*SPISSEL6 Value */ +#define SPI_SLVSEL_SSEL7 0x00008000 /*SPISSEL7 Value */ +/* SPI_RWC */ +#define SPI_RWC_VALUE 0x0000FFFF /*Received Word-Count */ +/* SPI_RWCR */ +#define SPI_RWCR_VALUE 0x0000FFFF /*Received Word-Count Reload */ +/* SPI_TWC */ +#define SPI_TWC_VALUE 0x0000FFFF /*Transmitted Word-Count */ +/* SPI_TWCR */ +#define SPI_TWCR_VALUE 0x0000FFFF /*Transmitted Word-Count Reload */ +/* SPI_IMASK */ +#define SPI_IMSK_RUWM 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_IMASKCL */ +#define SPI_IMSK_CLR_RUW 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_CLR_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_CLR_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_CLR_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_CLR_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_CLR_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_CLR_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_CLR_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_CLR_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_CLR_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_IMASKST */ +#define SPI_IMSK_SET_RUWM 0x00000002 /*Receive Water-Mark Interrupt Mask */ +#define SPI_IMSK_SET_TUWM 0x00000004 /*Transmit Water-Mark Interrupt Mask */ +#define SPI_IMSK_SET_ROM 0x00000010 /*Receive Over-Run Interrupt Mask */ +#define SPI_IMSK_SET_TUM 0x00000020 /*Transmit Under-Run Interrupt Mask */ +#define SPI_IMSK_SET_TCM 0x00000040 /*Transmit Collision Interrupt Mask */ +#define SPI_IMSK_SET_MFM 0x00000080 /*Mode Fault Interrupt Mask */ +#define SPI_IMSK_SET_RSM 0x00000100 /*Receive Start Interrupt Mask */ +#define SPI_IMSK_SET_TSM 0x00000200 /*Transmit Start Interrupt Mask */ +#define SPI_IMSK_SET_RFM 0x00000400 /*Receive Finish Interrupt Mask */ +#define SPI_IMSK_SET_TFM 0x00000800 /*Transmit Finish Interrupt Mask */ +/* SPI_STATUS */ +#define SPI_STAT_SPIF 0x00000001 /*SPI Finished */ +#define SPI_STAT_RUWM 0x00000002 /*Receive Water-Mark Breached */ +#define SPI_STAT_TUWM 0x00000004 /*Transmit Water-Mark Breached */ +#define SPI_STAT_ROE 0x00000010 /*Receive Over-Run Indication */ +#define SPI_STAT_TUE 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_STAT_TCE 0x00000040 /*Transmit Collision Indication */ +#define SPI_STAT_MODF 0x00000080 /*Mode Fault Indication */ +#define SPI_STAT_RS 0x00000100 /*Receive Start Indication */ +#define SPI_STAT_TS 0x00000200 /*Transmit Start Indication */ +#define SPI_STAT_RF 0x00000400 /*Receive Finish Indication */ +#define SPI_STAT_TF 0x00000800 /*Transmit Finish Indication */ +#define SPI_STAT_RFS 0x00007000 /*SPI_RFIFO status */ +#define SPI_STAT_RFIFO_EMPTY 0x00000000 /*RFS: RFIFO Empty */ +#define SPI_STAT_RFIFO_25 0x00001000 /*RFS: RFIFO 25% Full */ +#define SPI_STAT_RFIFO_50 0x00002000 /*RFS: RFIFO 50% Full */ +#define SPI_STAT_RFIFO_75 0x00003000 /*RFS: RFIFO 75% Full */ +#define SPI_STAT_RFIFO_FULL 0x00004000 /*RFS: RFIFO Full */ +#define SPI_STAT_TFS 0x00070000 /*SPI_TFIFO status */ +#define SPI_STAT_TFIFO_FULL 0x00000000 /*TFS: TFIFO full */ +#define SPI_STAT_TFIFO_25 0x00010000 /*TFS: TFIFO 25% empty */ +#define SPI_STAT_TFIFO_50 0x00020000 /*TFS: TFIFO 50% empty */ +#define SPI_STAT_TFIFO_75 0x00030000 /*TFS: TFIFO 75% empty */ +#define SPI_STAT_TFIFO_EMPTY 0x00040000 /*TFS: TFIFO empty */ +#define SPI_STAT_FCS 0x00100000 /*Flow-Control Stall Indication */ +#define SPI_STAT_RFE 0x00400000 /*SPI_RFIFO Empty */ +#define SPI_STAT_TFF 0x00800000 /*SPI_TFIFO Full */ +/* SPI_ILAT */ +#define SPI_ILAT_RUWMI 0x00000002 /*Receive Water Mark Interrupt */ +#define SPI_ILAT_TUWMI 0x00000004 /*Transmit Water Mark Interrupt */ +#define SPI_ILAT_ROI 0x00000010 /*Receive Over-Run Indication */ +#define SPI_ILAT_TUI 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_ILAT_TCI 0x00000040 /*Transmit Collision Indication */ +#define SPI_ILAT_MFI 0x00000080 /*Mode Fault Indication */ +#define SPI_ILAT_RSI 0x00000100 /*Receive Start Indication */ +#define SPI_ILAT_TSI 0x00000200 /*Transmit Start Indication */ +#define SPI_ILAT_RFI 0x00000400 /*Receive Finish Indication */ +#define SPI_ILAT_TFI 0x00000800 /*Transmit Finish Indication */ +/* SPI_ILATCL */ +#define SPI_ILAT_CLR_RUWMI 0x00000002 /*Receive Water Mark Interrupt */ +#define SPI_ILAT_CLR_TUWMI 0x00000004 /*Transmit Water Mark Interrupt */ +#define SPI_ILAT_CLR_ROI 0x00000010 /*Receive Over-Run Indication */ +#define SPI_ILAT_CLR_TUI 0x00000020 /*Transmit Under-Run Indication */ +#define SPI_ILAT_CLR_TCI 0x00000040 /*Transmit Collision Indication */ +#define SPI_ILAT_CLR_MFI 0x00000080 /*Mode Fault Indication */ +#define SPI_ILAT_CLR_RSI 0x00000100 /*Receive Start Indication */ +#define SPI_ILAT_CLR_TSI 0x00000200 /*Transmit Start Indication */ +#define SPI_ILAT_CLR_RFI 0x00000400 /*Receive Finish Indication */ +#define SPI_ILAT_CLR_TFI 0x00000800 /*Transmit Finish Indication */ + +/* + * bfin spi3 registers layout + */ +struct bfin_spi_regs { + u32 revid; + u32 control; + u32 rx_control; + u32 tx_control; + u32 clock; + u32 delay; + u32 ssel; + u32 rwc; + u32 rwcr; + u32 twc; + u32 twcr; + u32 reserved0; + u32 emask; + u32 emaskcl; + u32 emaskst; + u32 reserved1; + u32 status; + u32 elat; + u32 elatcl; + u32 reserved2; + u32 rfifo; + u32 reserved3; + u32 tfifo; +}; + +#endif /* _SPI_CHANNEL_H_ */ diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 83abcbda28..b8264df3a9 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -31,6 +31,7 @@ COBJS-$(CONFIG_ARMADA100_SPI) += armada100_spi.o COBJS-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o COBJS-$(CONFIG_ATMEL_SPI) += atmel_spi.o COBJS-$(CONFIG_BFIN_SPI) += bfin_spi.o +COBJS-$(CONFIG_BFIN_SPI6XX) += bfin_spi6xx.o COBJS-$(CONFIG_CF_SPI) += cf_spi.o COBJS-$(CONFIG_CF_QSPI) += cf_qspi.o COBJS-$(CONFIG_DAVINCI_SPI) += davinci_spi.o diff --git a/drivers/spi/bfin_spi6xx.c b/drivers/spi/bfin_spi6xx.c new file mode 100644 index 0000000000..fde3447426 --- /dev/null +++ b/drivers/spi/bfin_spi6xx.c @@ -0,0 +1,308 @@ +/* + * Analog Devices SPI3 controller driver + * + * Copyright (c) 2011 Analog Devices Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include + +struct bfin_spi_slave { + struct spi_slave slave; + u32 control, clock; + struct bfin_spi_regs *regs; + int cs_pol; +}; + +#define to_bfin_spi_slave(s) container_of(s, struct bfin_spi_slave, slave) + +#define gpio_cs(cs) ((cs) - MAX_CTRL_CS) +#ifdef CONFIG_BFIN_SPI_GPIO_CS +# define is_gpio_cs(cs) ((cs) > MAX_CTRL_CS) +#else +# define is_gpio_cs(cs) 0 +#endif + +int spi_cs_is_valid(unsigned int bus, unsigned int cs) +{ + if (is_gpio_cs(cs)) + return gpio_is_valid(gpio_cs(cs)); + else + return (cs >= 1 && cs <= MAX_CTRL_CS); +} + +void spi_cs_activate(struct spi_slave *slave) +{ + struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); + + if (is_gpio_cs(slave->cs)) { + unsigned int cs = gpio_cs(slave->cs); + gpio_set_value(cs, bss->cs_pol); + } else { + u32 ssel; + ssel = bfin_read32(&bss->regs->ssel); + ssel |= 1 << slave->cs; + if (bss->cs_pol) + ssel |= (1 << 8) << slave->cs; + else + ssel &= ~((1 << 8) << slave->cs); + bfin_write32(&bss->regs->ssel, ssel); + } + + SSYNC(); +} + +void spi_cs_deactivate(struct spi_slave *slave) +{ + struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); + + if (is_gpio_cs(slave->cs)) { + unsigned int cs = gpio_cs(slave->cs); + gpio_set_value(cs, !bss->cs_pol); + } else { + u32 ssel; + ssel = bfin_read32(&bss->regs->ssel); + if (bss->cs_pol) + ssel &= ~((1 << 8) << slave->cs); + else + ssel |= (1 << 8) << slave->cs; + /* deassert cs */ + bfin_write32(&bss->regs->ssel, ssel); + SSYNC(); + /* disable cs */ + ssel &= ~(1 << slave->cs); + bfin_write32(&bss->regs->ssel, ssel); + } + + SSYNC(); +} + +void spi_init() +{ +} + +#define SPI_PINS(n) \ + { 0, P_SPI##n##_SCK, P_SPI##n##_MISO, P_SPI##n##_MOSI, 0 } +static unsigned short pins[][5] = { +#ifdef SPI0_REGBASE + [0] = SPI_PINS(0), +#endif +#ifdef SPI1_REGBASE + [1] = SPI_PINS(1), +#endif +#ifdef SPI2_REGBASE + [2] = SPI_PINS(2), +#endif +}; + +#define SPI_CS_PINS(n) \ + { \ + P_SPI##n##_SSEL1, P_SPI##n##_SSEL2, P_SPI##n##_SSEL3, \ + P_SPI##n##_SSEL4, P_SPI##n##_SSEL5, P_SPI##n##_SSEL6, \ + P_SPI##n##_SSEL7, \ + } +static const unsigned short cs_pins[][7] = { +#ifdef SPI0_REGBASE + [0] = SPI_CS_PINS(0), +#endif +#ifdef SPI1_REGBASE + [1] = SPI_CS_PINS(1), +#endif +#ifdef SPI2_REGBASE + [2] = SPI_CS_PINS(2), +#endif +}; + +void spi_set_speed(struct spi_slave *slave, uint hz) +{ + struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); + ulong sclk; + u32 clock; + + sclk = get_sclk1(); + clock = sclk / hz; + if (clock) + clock--; + bss->clock = clock; +} + +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct bfin_spi_slave *bss; + u32 reg_base; + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + if (bus >= ARRAY_SIZE(pins) || pins[bus] == NULL) { + debug("%s: invalid bus %u\n", __func__, bus); + return NULL; + } + switch (bus) { +#ifdef SPI0_REGBASE + case 0: + reg_base = SPI0_REGBASE; + break; +#endif +#ifdef SPI1_REGBASE + case 1: + reg_base = SPI1_REGBASE; + break; +#endif +#ifdef SPI2_REGBASE + case 2: + reg_base = SPI2_REGBASE; + break; +#endif + default: + return NULL; + } + + bss = malloc(sizeof(*bss)); + if (!bss) + return NULL; + + bss->slave.bus = bus; + bss->slave.cs = cs; + bss->regs = (struct bfin_spi_regs *)reg_base; + bss->control = SPI_CTL_EN | SPI_CTL_MSTR; + if (mode & SPI_CPHA) + bss->control |= SPI_CTL_CPHA; + if (mode & SPI_CPOL) + bss->control |= SPI_CTL_CPOL; + if (mode & SPI_LSB_FIRST) + bss->control |= SPI_CTL_LSBF; + bss->control &= ~SPI_CTL_ASSEL; + bss->cs_pol = mode & SPI_CS_HIGH ? 1 : 0; + spi_set_speed(&bss->slave, max_hz); + + return &bss->slave; +} + +void spi_free_slave(struct spi_slave *slave) +{ + struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); + free(bss); +} + +int spi_claim_bus(struct spi_slave *slave) +{ + struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); + + debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs); + + if (is_gpio_cs(slave->cs)) { + unsigned int cs = gpio_cs(slave->cs); + gpio_request(cs, "bfin-spi"); + gpio_direction_output(cs, !bss->cs_pol); + pins[slave->bus][0] = P_DONTCARE; + } else + pins[slave->bus][0] = cs_pins[slave->bus][slave->cs - 1]; + peripheral_request_list(pins[slave->bus], "bfin-spi"); + + bfin_write32(&bss->regs->control, bss->control); + bfin_write32(&bss->regs->clock, bss->clock); + bfin_write32(&bss->regs->delay, 0x0); + bfin_write32(&bss->regs->rx_control, SPI_RXCTL_REN); + bfin_write32(&bss->regs->tx_control, SPI_TXCTL_TEN | SPI_TXCTL_TTI); + SSYNC(); + + return 0; +} + +void spi_release_bus(struct spi_slave *slave) +{ + struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); + + debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs); + + peripheral_free_list(pins[slave->bus]); + if (is_gpio_cs(slave->cs)) + gpio_free(gpio_cs(slave->cs)); + + bfin_write32(&bss->regs->rx_control, 0x0); + bfin_write32(&bss->regs->tx_control, 0x0); + bfin_write32(&bss->regs->control, 0x0); + SSYNC(); +} + +#ifndef CONFIG_BFIN_SPI_IDLE_VAL +# define CONFIG_BFIN_SPI_IDLE_VAL 0xff +#endif + +static int spi_pio_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx, + uint bytes) +{ + /* discard invalid rx data and empty rfifo */ + while (!(bfin_read32(&bss->regs->status) & SPI_STAT_RFE)) + bfin_read32(&bss->regs->rfifo); + + while (bytes--) { + u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL); + debug("%s: tx:%x ", __func__, value); + bfin_write32(&bss->regs->tfifo, value); + SSYNC(); + while (bfin_read32(&bss->regs->status) & SPI_STAT_RFE) + if (ctrlc()) + return -1; + value = bfin_read32(&bss->regs->rfifo); + if (rx) + *rx++ = value; + debug("rx:%x\n", value); + } + + return 0; +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, + void *din, unsigned long flags) +{ + struct bfin_spi_slave *bss = to_bfin_spi_slave(slave); + const u8 *tx = dout; + u8 *rx = din; + uint bytes = bitlen / 8; + int ret = 0; + + 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; + + /* we can only do 8 bit transfers */ + if (bitlen % 8) { + flags |= SPI_XFER_END; + goto done; + } + + if (flags & SPI_XFER_BEGIN) + spi_cs_activate(slave); + + ret = spi_pio_xfer(bss, tx, rx, bytes); + + done: + if (flags & SPI_XFER_END) + spi_cs_deactivate(slave); + + return ret; +} -- cgit v1.2.3 From 49c2da53b7aa63f68118fa9ffa5c5e546440ebb2 Mon Sep 17 00:00:00 2001 From: Bob Liu Date: Tue, 27 Dec 2011 15:05:53 +0800 Subject: blackfin: bf60x: add hw watchdog support Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang Signed-off-by: Sonic Zhang --- arch/blackfin/cpu/initcode.c | 13 +++++++++++++ arch/blackfin/cpu/start.S | 2 ++ include/configs/bf609-ezkit.h | 1 + 3 files changed, 16 insertions(+) diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index a717148651..ce9a43598c 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -461,8 +461,21 @@ program_early_devices(ADI_BOOT_DATA *bs, uint *sdivB, uint *divB, uint *vcoB) */ if (CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_BYPASS) { serial_putc('e'); +#ifdef __ADSPBF60x__ + bfin_write_SEC_GCTL(0x2); + SSYNC(); + bfin_write_SEC_FCTL(0xc1); + bfin_write_SEC_SCTL(2, bfin_read_SEC_SCTL(2) | 0x6); + + bfin_write_SEC_CCTL(0x2); + SSYNC(); + bfin_write_SEC_GCTL(0x1); + bfin_write_SEC_CCTL(0x1); +#endif bfin_write_WDOG_CNT(MSEC_TO_SCLK(CONFIG_HW_WATCHDOG_TIMEOUT_INITCODE)); +#if CONFIG_BFIN_BOOT_MODE != BFIN_BOOT_UART bfin_write_WDOG_CTL(0); +#endif serial_putc('f'); } #endif diff --git a/arch/blackfin/cpu/start.S b/arch/blackfin/cpu/start.S index 90b4d1ae94..7155fc858b 100644 --- a/arch/blackfin/cpu/start.S +++ b/arch/blackfin/cpu/start.S @@ -65,6 +65,7 @@ ENTRY(_start) p5.h = HI(COREMMR_BASE); #ifdef CONFIG_HW_WATCHDOG +#ifndef __ADSPBF60x__ # ifndef CONFIG_HW_WATCHDOG_TIMEOUT_START # define CONFIG_HW_WATCHDOG_TIMEOUT_START 5000 # endif @@ -77,6 +78,7 @@ ENTRY(_start) [p4 + (WDOG_CNT - SYSMMR_BASE)] = r0; /* fire up the watchdog - R0.L above needs to be 0x0000 */ W[p4 + (WDOG_CTL - SYSMMR_BASE)] = r0; +#endif #endif /* Turn on the serial for debugging the init process */ diff --git a/include/configs/bf609-ezkit.h b/include/configs/bf609-ezkit.h index 6dffab86dc..02149fa94d 100644 --- a/include/configs/bf609-ezkit.h +++ b/include/configs/bf609-ezkit.h @@ -63,6 +63,7 @@ #define CONFIG_SYS_MONITOR_LEN (768 * 1024) #define CONFIG_SYS_MALLOC_LEN (512 * 1024) +#define CONFIG_HW_WATCHDOG /* * Network Settings */ -- cgit v1.2.3 From 9faf4f08e752ca95d0986a200d48b67b59cde5ef Mon Sep 17 00:00:00 2001 From: Steven Miao Date: Sat, 31 Mar 2012 16:01:50 +0800 Subject: blackfin: bf60x: add resume from hibernate Add Bf60x resume from hibernate support Signed-off-by: Steven Miao Signed-off-by: Sonic Zhang Signed-off-by: Bob Liu Signed-off-by: Sonic Zhang --- arch/blackfin/cpu/initcode.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/arch/blackfin/cpu/initcode.c b/arch/blackfin/cpu/initcode.c index ce9a43598c..1a066806d1 100644 --- a/arch/blackfin/cpu/initcode.c +++ b/arch/blackfin/cpu/initcode.c @@ -509,6 +509,11 @@ maybe_self_refresh(ADI_BOOT_DATA *bs) return false; #ifdef __ADSPBF60x__ + /* resume from hibernate, return false let ddr initialize */ + if ((bfin_read32(DPM0_STAT) & 0xF0) == 0x50) { + serial_putc('b'); + return false; + } #else /* __ADSPBF60x__ */ @@ -827,6 +832,7 @@ program_memory_controller(ADI_BOOT_DATA *bs, bool put_into_srfs) while (!(bfin_read_DMC0_STAT() & DLLCALDONE)) continue; serial_putc('!'); + #else /* __ADSPBF60x__ */ /* Program the external memory controller before we come out of @@ -894,7 +900,46 @@ check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs) return; serial_putc('b'); +#ifdef __ADSPBF60x__ + if (bfin_read32(DPM0_RESTORE0) != 0) { + uint32_t reg = bfin_read_DMC0_CTL(); + reg &= ~0x8; + bfin_write_DMC0_CTL(reg); + + while ((bfin_read_DMC0_STAT() & 0x8)) + continue; + while (!(bfin_read_DMC0_STAT() & 0x1)) + continue; + serial_putc('z'); + uint32_t *hibernate_magic = bfin_read32(DPM0_RESTORE4); + SSYNC(); /* make sure memory controller is done */ + if (hibernate_magic[0] == 0xDEADBEEF) { + serial_putc('c'); + SSYNC(); + bfin_write_EVT15(hibernate_magic[1]); + bfin_write_IMASK(EVT_IVG15); + __asm__ __volatile__ ( + /* load reti early to avoid anomaly 281 */ + "reti = %2;" + /* clear hibernate magic */ + "[%0] = %1;" + /* load stack pointer */ + "SP = [%0 + 8];" + /* lower ourselves from reset ivg to ivg15 */ + "raise 15;" + "nop;nop;nop;" + "rti;" + : + : "p"(hibernate_magic), + "d"(0x2000 /* jump.s 0 */), + "d"(0xffa00000) + ); + } + + + } +#else /* Are we coming out of hibernate (suspend to memory) ? * The memory layout is: * 0x0: hibernate magic for anomaly 307 (0xDEADBEEF) @@ -927,6 +972,7 @@ check_hibernation(ADI_BOOT_DATA *bs, u16 vr_ctl, bool put_into_srfs) } serial_putc('d'); } +#endif serial_putc('e'); } -- cgit v1.2.3 From 293d7fbd47f473d8a6b01a5f80d7faa5cd6b67b3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:28 +0000 Subject: ext4: Split write support into its own file This code seems to be entirely othogonal, so remove the #ifdef and put the condition in the Makefile instead. Signed-off-by: Simon Glass --- fs/ext4/Makefile | 2 +- fs/ext4/ext4_write.c | 996 +++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ext4/ext4fs.c | 963 ------------------------------------------------- 3 files changed, 997 insertions(+), 964 deletions(-) create mode 100644 fs/ext4/ext4_write.c diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index bb801f9054..3bde82418e 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile @@ -31,7 +31,7 @@ LIB = $(obj)libext4fs.o AOBJS = COBJS-$(CONFIG_FS_EXT4) := ext4fs.o ext4_common.o dev.o -COBJS-$(CONFIG_EXT4_WRITE) += ext4_journal.o crc16.o +COBJS-$(CONFIG_EXT4_WRITE) += ext4_write.o ext4_journal.o crc16.o SRCS := $(AOBJS:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS-y)) diff --git a/fs/ext4/ext4_write.c b/fs/ext4/ext4_write.c new file mode 100644 index 0000000000..c4e399ccfa --- /dev/null +++ b/fs/ext4/ext4_write.c @@ -0,0 +1,996 @@ +/* + * (C) Copyright 2011 - 2012 Samsung Electronics + * EXT4 filesystem implementation in Uboot by + * Uma Shankar + * Manjunatha C Achar + * + * ext4ls and ext4load : Based on ext2 ls and load support in Uboot. + * Ext4 read optimization taken from Open-Moko + * Qi bootloader + * + * (C) Copyright 2004 + * esd gmbh + * Reinhard Arlt + * + * based on code from grub2 fs/ext2.c and fs/fshelp.c by + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003, 2004 Free Software Foundation, Inc. + * + * ext4write : Based on generic ext4 protocol. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include +#include +#include +#include "ext4_common.h" + +static void ext4fs_update(void) +{ + short i; + ext4fs_update_journal(); + struct ext_filesystem *fs = get_fs(); + + /* update super block */ + put_ext4((uint64_t)(SUPERBLOCK_SIZE), + (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); + + /* update block groups */ + for (i = 0; i < fs->no_blkgrp; i++) { + fs->bgd[i].bg_checksum = ext4fs_checksum_update(i); + put_ext4((uint64_t)(fs->bgd[i].block_id * fs->blksz), + fs->blk_bmaps[i], fs->blksz); + } + + /* update inode table groups */ + for (i = 0; i < fs->no_blkgrp; i++) { + put_ext4((uint64_t) (fs->bgd[i].inode_id * fs->blksz), + fs->inode_bmaps[i], fs->blksz); + } + + /* update the block group descriptor table */ + put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz), + (struct ext2_block_group *)fs->gdtable, + (fs->blksz * fs->no_blk_pergdt)); + + ext4fs_dump_metadata(); + + gindex = 0; + gd_index = 0; +} + +int ext4fs_get_bgdtable(void) +{ + int status; + int grp_desc_size; + struct ext_filesystem *fs = get_fs(); + grp_desc_size = sizeof(struct ext2_block_group); + fs->no_blk_pergdt = (fs->no_blkgrp * grp_desc_size) / fs->blksz; + if ((fs->no_blkgrp * grp_desc_size) % fs->blksz) + fs->no_blk_pergdt++; + + /* allocate memory for gdtable */ + fs->gdtable = zalloc(fs->blksz * fs->no_blk_pergdt); + if (!fs->gdtable) + return -ENOMEM; + /* read the group descriptor table */ + status = ext4fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0, + fs->blksz * fs->no_blk_pergdt, fs->gdtable); + if (status == 0) + goto fail; + + if (ext4fs_log_gdt(fs->gdtable)) { + printf("Error in ext4fs_log_gdt\n"); + return -1; + } + + return 0; +fail: + free(fs->gdtable); + fs->gdtable = NULL; + + return -1; +} + +static void delete_single_indirect_block(struct ext2_inode *inode) +{ + struct ext2_block_group *bgd = NULL; + static int prev_bg_bmap_idx = -1; + long int blknr; + int remainder; + int bg_idx; + int status; + unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; + struct ext_filesystem *fs = get_fs(); + char *journal_buffer = zalloc(fs->blksz); + if (!journal_buffer) { + printf("No memory\n"); + return; + } + /* get block group descriptor table */ + bgd = (struct ext2_block_group *)fs->gdtable; + + /* deleting the single indirect block associated with inode */ + if (inode->b.blocks.indir_block != 0) { + debug("SIPB releasing %u\n", inode->b.blocks.indir_block); + blknr = inode->b.blocks.indir_block; + if (fs->blksz != 1024) { + bg_idx = blknr / blk_per_grp; + } else { + bg_idx = blknr / blk_per_grp; + remainder = blknr % blk_per_grp; + if (!remainder) + bg_idx--; + } + ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + status = + ext4fs_devread(bgd[bg_idx].block_id * + fs->sect_perblk, 0, fs->blksz, + journal_buffer); + if (status == 0) + goto fail; + if (ext4fs_log_journal + (journal_buffer, bgd[bg_idx].block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + } +fail: + free(journal_buffer); +} + +static void delete_double_indirect_block(struct ext2_inode *inode) +{ + int i; + short status; + static int prev_bg_bmap_idx = -1; + long int blknr; + int remainder; + int bg_idx; + unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; + unsigned int *di_buffer = NULL; + unsigned int *DIB_start_addr = NULL; + struct ext2_block_group *bgd = NULL; + struct ext_filesystem *fs = get_fs(); + char *journal_buffer = zalloc(fs->blksz); + if (!journal_buffer) { + printf("No memory\n"); + return; + } + /* get the block group descriptor table */ + bgd = (struct ext2_block_group *)fs->gdtable; + + if (inode->b.blocks.double_indir_block != 0) { + di_buffer = zalloc(fs->blksz); + if (!di_buffer) { + printf("No memory\n"); + return; + } + DIB_start_addr = (unsigned int *)di_buffer; + blknr = inode->b.blocks.double_indir_block; + status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, + (char *)di_buffer); + for (i = 0; i < fs->blksz / sizeof(int); i++) { + if (*di_buffer == 0) + break; + + debug("DICB releasing %u\n", *di_buffer); + if (fs->blksz != 1024) { + bg_idx = (*di_buffer) / blk_per_grp; + } else { + bg_idx = (*di_buffer) / blk_per_grp; + remainder = (*di_buffer) % blk_per_grp; + if (!remainder) + bg_idx--; + } + ext4fs_reset_block_bmap(*di_buffer, + fs->blk_bmaps[bg_idx], bg_idx); + di_buffer++; + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + status = ext4fs_devread(bgd[bg_idx].block_id + * fs->sect_perblk, 0, + fs->blksz, + journal_buffer); + if (status == 0) + goto fail; + + if (ext4fs_log_journal(journal_buffer, + bgd[bg_idx].block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + } + + /* removing the parent double indirect block */ + blknr = inode->b.blocks.double_indir_block; + if (fs->blksz != 1024) { + bg_idx = blknr / blk_per_grp; + } else { + bg_idx = blknr / blk_per_grp; + remainder = blknr % blk_per_grp; + if (!remainder) + bg_idx--; + } + ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + memset(journal_buffer, '\0', fs->blksz); + status = ext4fs_devread(bgd[bg_idx].block_id * + fs->sect_perblk, 0, fs->blksz, + journal_buffer); + if (status == 0) + goto fail; + + if (ext4fs_log_journal(journal_buffer, + bgd[bg_idx].block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + debug("DIPB releasing %ld\n", blknr); + } +fail: + free(DIB_start_addr); + free(journal_buffer); +} + +static void delete_triple_indirect_block(struct ext2_inode *inode) +{ + int i, j; + short status; + static int prev_bg_bmap_idx = -1; + long int blknr; + int remainder; + int bg_idx; + unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; + unsigned int *tigp_buffer = NULL; + unsigned int *tib_start_addr = NULL; + unsigned int *tip_buffer = NULL; + unsigned int *tipb_start_addr = NULL; + struct ext2_block_group *bgd = NULL; + struct ext_filesystem *fs = get_fs(); + char *journal_buffer = zalloc(fs->blksz); + if (!journal_buffer) { + printf("No memory\n"); + return; + } + /* get block group descriptor table */ + bgd = (struct ext2_block_group *)fs->gdtable; + + if (inode->b.blocks.triple_indir_block != 0) { + tigp_buffer = zalloc(fs->blksz); + if (!tigp_buffer) { + printf("No memory\n"); + return; + } + tib_start_addr = (unsigned int *)tigp_buffer; + blknr = inode->b.blocks.triple_indir_block; + status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, + (char *)tigp_buffer); + for (i = 0; i < fs->blksz / sizeof(int); i++) { + if (*tigp_buffer == 0) + break; + debug("tigp buffer releasing %u\n", *tigp_buffer); + + tip_buffer = zalloc(fs->blksz); + if (!tip_buffer) + goto fail; + tipb_start_addr = (unsigned int *)tip_buffer; + status = ext4fs_devread((*tigp_buffer) * + fs->sect_perblk, 0, fs->blksz, + (char *)tip_buffer); + for (j = 0; j < fs->blksz / sizeof(int); j++) { + if (*tip_buffer == 0) + break; + if (fs->blksz != 1024) { + bg_idx = (*tip_buffer) / blk_per_grp; + } else { + bg_idx = (*tip_buffer) / blk_per_grp; + + remainder = (*tip_buffer) % blk_per_grp; + if (!remainder) + bg_idx--; + } + + ext4fs_reset_block_bmap(*tip_buffer, + fs->blk_bmaps[bg_idx], + bg_idx); + + tip_buffer++; + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + status = + ext4fs_devread( + bgd[bg_idx].block_id * + fs->sect_perblk, 0, + fs->blksz, + journal_buffer); + if (status == 0) + goto fail; + + if (ext4fs_log_journal(journal_buffer, + bgd[bg_idx]. + block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + } + free(tipb_start_addr); + tipb_start_addr = NULL; + + /* + * removing the grand parent blocks + * which is connected to inode + */ + if (fs->blksz != 1024) { + bg_idx = (*tigp_buffer) / blk_per_grp; + } else { + bg_idx = (*tigp_buffer) / blk_per_grp; + + remainder = (*tigp_buffer) % blk_per_grp; + if (!remainder) + bg_idx--; + } + ext4fs_reset_block_bmap(*tigp_buffer, + fs->blk_bmaps[bg_idx], bg_idx); + + tigp_buffer++; + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + memset(journal_buffer, '\0', fs->blksz); + status = + ext4fs_devread(bgd[bg_idx].block_id * + fs->sect_perblk, 0, + fs->blksz, journal_buffer); + if (status == 0) + goto fail; + + if (ext4fs_log_journal(journal_buffer, + bgd[bg_idx].block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + } + + /* removing the grand parent triple indirect block */ + blknr = inode->b.blocks.triple_indir_block; + if (fs->blksz != 1024) { + bg_idx = blknr / blk_per_grp; + } else { + bg_idx = blknr / blk_per_grp; + remainder = blknr % blk_per_grp; + if (!remainder) + bg_idx--; + } + ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + memset(journal_buffer, '\0', fs->blksz); + status = ext4fs_devread(bgd[bg_idx].block_id * + fs->sect_perblk, 0, fs->blksz, + journal_buffer); + if (status == 0) + goto fail; + + if (ext4fs_log_journal(journal_buffer, + bgd[bg_idx].block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + debug("tigp buffer itself releasing %ld\n", blknr); + } +fail: + free(tib_start_addr); + free(tipb_start_addr); + free(journal_buffer); +} + +static int ext4fs_delete_file(int inodeno) +{ + struct ext2_inode inode; + short status; + int i; + int remainder; + long int blknr; + int bg_idx; + int ibmap_idx; + char *read_buffer = NULL; + char *start_block_address = NULL; + unsigned int no_blocks; + + static int prev_bg_bmap_idx = -1; + unsigned int inodes_per_block; + long int blkno; + unsigned int blkoff; + unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; + unsigned int inode_per_grp = ext4fs_root->sblock.inodes_per_group; + struct ext2_inode *inode_buffer = NULL; + struct ext2_block_group *bgd = NULL; + struct ext_filesystem *fs = get_fs(); + char *journal_buffer = zalloc(fs->blksz); + if (!journal_buffer) + return -ENOMEM; + /* get the block group descriptor table */ + bgd = (struct ext2_block_group *)fs->gdtable; + status = ext4fs_read_inode(ext4fs_root, inodeno, &inode); + if (status == 0) + goto fail; + + /* read the block no allocated to a file */ + no_blocks = inode.size / fs->blksz; + if (inode.size % fs->blksz) + no_blocks++; + + if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) { + struct ext2fs_node *node_inode = + zalloc(sizeof(struct ext2fs_node)); + if (!node_inode) + goto fail; + node_inode->data = ext4fs_root; + node_inode->ino = inodeno; + node_inode->inode_read = 0; + memcpy(&(node_inode->inode), &inode, sizeof(struct ext2_inode)); + + for (i = 0; i < no_blocks; i++) { + blknr = read_allocated_block(&(node_inode->inode), i); + if (fs->blksz != 1024) { + bg_idx = blknr / blk_per_grp; + } else { + bg_idx = blknr / blk_per_grp; + remainder = blknr % blk_per_grp; + if (!remainder) + bg_idx--; + } + ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], + bg_idx); + debug("EXT4_EXTENTS Block releasing %ld: %d\n", + blknr, bg_idx); + + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + status = + ext4fs_devread(bgd[bg_idx].block_id * + fs->sect_perblk, 0, + fs->blksz, journal_buffer); + if (status == 0) + goto fail; + if (ext4fs_log_journal(journal_buffer, + bgd[bg_idx].block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + } + if (node_inode) { + free(node_inode); + node_inode = NULL; + } + } else { + + delete_single_indirect_block(&inode); + delete_double_indirect_block(&inode); + delete_triple_indirect_block(&inode); + + /* read the block no allocated to a file */ + no_blocks = inode.size / fs->blksz; + if (inode.size % fs->blksz) + no_blocks++; + for (i = 0; i < no_blocks; i++) { + blknr = read_allocated_block(&inode, i); + if (fs->blksz != 1024) { + bg_idx = blknr / blk_per_grp; + } else { + bg_idx = blknr / blk_per_grp; + remainder = blknr % blk_per_grp; + if (!remainder) + bg_idx--; + } + ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], + bg_idx); + debug("ActualB releasing %ld: %d\n", blknr, bg_idx); + + bgd[bg_idx].free_blocks++; + fs->sb->free_blocks++; + /* journal backup */ + if (prev_bg_bmap_idx != bg_idx) { + memset(journal_buffer, '\0', fs->blksz); + status = ext4fs_devread(bgd[bg_idx].block_id + * fs->sect_perblk, + 0, fs->blksz, + journal_buffer); + if (status == 0) + goto fail; + if (ext4fs_log_journal(journal_buffer, + bgd[bg_idx].block_id)) + goto fail; + prev_bg_bmap_idx = bg_idx; + } + } + } + + /* from the inode no to blockno */ + inodes_per_block = fs->blksz / fs->inodesz; + ibmap_idx = inodeno / inode_per_grp; + + /* get the block no */ + inodeno--; + blkno = __le32_to_cpu(bgd[ibmap_idx].inode_table_id) + + (inodeno % __le32_to_cpu(inode_per_grp)) / inodes_per_block; + + /* get the offset of the inode */ + blkoff = ((inodeno) % inodes_per_block) * fs->inodesz; + + /* read the block no containing the inode */ + read_buffer = zalloc(fs->blksz); + if (!read_buffer) + goto fail; + start_block_address = read_buffer; + status = ext4fs_devread(blkno * fs->sect_perblk, + 0, fs->blksz, read_buffer); + if (status == 0) + goto fail; + + if (ext4fs_log_journal(read_buffer, blkno)) + goto fail; + + read_buffer = read_buffer + blkoff; + inode_buffer = (struct ext2_inode *)read_buffer; + memset(inode_buffer, '\0', sizeof(struct ext2_inode)); + + /* write the inode to original position in inode table */ + if (ext4fs_put_metadata(start_block_address, blkno)) + goto fail; + + /* update the respective inode bitmaps */ + inodeno++; + ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx); + bgd[ibmap_idx].free_inodes++; + fs->sb->free_inodes++; + /* journal backup */ + memset(journal_buffer, '\0', fs->blksz); + status = ext4fs_devread(bgd[ibmap_idx].inode_id * + fs->sect_perblk, 0, fs->blksz, journal_buffer); + if (status == 0) + goto fail; + if (ext4fs_log_journal(journal_buffer, bgd[ibmap_idx].inode_id)) + goto fail; + + ext4fs_update(); + ext4fs_deinit(); + + if (ext4fs_init() != 0) { + printf("error in File System init\n"); + goto fail; + } + + free(start_block_address); + free(journal_buffer); + + return 0; +fail: + free(start_block_address); + free(journal_buffer); + + return -1; +} + +int ext4fs_init(void) +{ + short status; + int i; + unsigned int real_free_blocks = 0; + struct ext_filesystem *fs = get_fs(); + + /* populate fs */ + fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root); + fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root); + fs->sect_perblk = fs->blksz / SECTOR_SIZE; + + /* get the superblock */ + fs->sb = zalloc(SUPERBLOCK_SIZE); + if (!fs->sb) + return -ENOMEM; + if (!ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, + (char *)fs->sb)) + goto fail; + + /* init journal */ + if (ext4fs_init_journal()) + goto fail; + + /* get total no of blockgroups */ + fs->no_blkgrp = (uint32_t)ext4fs_div_roundup( + (ext4fs_root->sblock.total_blocks - + ext4fs_root->sblock.first_data_block), + ext4fs_root->sblock.blocks_per_group); + + /* get the block group descriptor table */ + fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1); + if (ext4fs_get_bgdtable() == -1) { + printf("Error in getting the block group descriptor table\n"); + goto fail; + } + fs->bgd = (struct ext2_block_group *)fs->gdtable; + + /* load all the available bitmap block of the partition */ + fs->blk_bmaps = zalloc(fs->no_blkgrp * sizeof(char *)); + if (!fs->blk_bmaps) + goto fail; + for (i = 0; i < fs->no_blkgrp; i++) { + fs->blk_bmaps[i] = zalloc(fs->blksz); + if (!fs->blk_bmaps[i]) + goto fail; + } + + for (i = 0; i < fs->no_blkgrp; i++) { + status = + ext4fs_devread(fs->bgd[i].block_id * fs->sect_perblk, 0, + fs->blksz, (char *)fs->blk_bmaps[i]); + if (status == 0) + goto fail; + } + + /* load all the available inode bitmap of the partition */ + fs->inode_bmaps = zalloc(fs->no_blkgrp * sizeof(unsigned char *)); + if (!fs->inode_bmaps) + goto fail; + for (i = 0; i < fs->no_blkgrp; i++) { + fs->inode_bmaps[i] = zalloc(fs->blksz); + if (!fs->inode_bmaps[i]) + goto fail; + } + + for (i = 0; i < fs->no_blkgrp; i++) { + status = ext4fs_devread(fs->bgd[i].inode_id * fs->sect_perblk, + 0, fs->blksz, + (char *)fs->inode_bmaps[i]); + if (status == 0) + goto fail; + } + + /* + * check filesystem consistency with free blocks of file system + * some time we observed that superblock freeblocks does not match + * with the blockgroups freeblocks when improper + * reboot of a linux kernel + */ + for (i = 0; i < fs->no_blkgrp; i++) + real_free_blocks = real_free_blocks + fs->bgd[i].free_blocks; + if (real_free_blocks != fs->sb->free_blocks) + fs->sb->free_blocks = real_free_blocks; + + return 0; +fail: + ext4fs_deinit(); + + return -1; +} + +void ext4fs_deinit(void) +{ + int i; + struct ext2_inode inode_journal; + struct journal_superblock_t *jsb; + long int blknr; + struct ext_filesystem *fs = get_fs(); + + /* free journal */ + char *temp_buff = zalloc(fs->blksz); + if (temp_buff) { + ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, + &inode_journal); + blknr = read_allocated_block(&inode_journal, + EXT2_JOURNAL_SUPERBLOCK); + ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, + temp_buff); + jsb = (struct journal_superblock_t *)temp_buff; + jsb->s_start = cpu_to_be32(0); + put_ext4((uint64_t) (blknr * fs->blksz), + (struct journal_superblock_t *)temp_buff, fs->blksz); + free(temp_buff); + } + ext4fs_free_journal(); + + /* get the superblock */ + ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, (char *)fs->sb); + fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; + put_ext4((uint64_t)(SUPERBLOCK_SIZE), + (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); + free(fs->sb); + fs->sb = NULL; + + if (fs->blk_bmaps) { + for (i = 0; i < fs->no_blkgrp; i++) { + free(fs->blk_bmaps[i]); + fs->blk_bmaps[i] = NULL; + } + free(fs->blk_bmaps); + fs->blk_bmaps = NULL; + } + + if (fs->inode_bmaps) { + for (i = 0; i < fs->no_blkgrp; i++) { + free(fs->inode_bmaps[i]); + fs->inode_bmaps[i] = NULL; + } + free(fs->inode_bmaps); + fs->inode_bmaps = NULL; + } + + + free(fs->gdtable); + fs->gdtable = NULL; + fs->bgd = NULL; + /* + * reinitiliazed the global inode and + * block bitmap first execution check variables + */ + fs->first_pass_ibmap = 0; + fs->first_pass_bbmap = 0; + fs->curr_inode_no = 0; + fs->curr_blkno = 0; +} + +static int ext4fs_write_file(struct ext2_inode *file_inode, + int pos, unsigned int len, char *buf) +{ + int i; + int blockcnt; + int log2blocksize = LOG2_EXT2_BLOCK_SIZE(ext4fs_root); + unsigned int filesize = __le32_to_cpu(file_inode->size); + struct ext_filesystem *fs = get_fs(); + int previous_block_number = -1; + int delayed_start = 0; + int delayed_extent = 0; + int delayed_next = 0; + char *delayed_buf = NULL; + + /* Adjust len so it we can't read past the end of the file. */ + if (len > filesize) + len = filesize; + + blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz; + + for (i = pos / fs->blksz; i < blockcnt; i++) { + long int blknr; + int blockend = fs->blksz; + int skipfirst = 0; + blknr = read_allocated_block(file_inode, i); + if (blknr < 0) + return -1; + + blknr = blknr << log2blocksize; + + if (blknr) { + if (previous_block_number != -1) { + if (delayed_next == blknr) { + delayed_extent += blockend; + delayed_next += blockend >> SECTOR_BITS; + } else { /* spill */ + put_ext4((uint64_t) (delayed_start * + SECTOR_SIZE), + delayed_buf, + (uint32_t) delayed_extent); + previous_block_number = blknr; + delayed_start = blknr; + delayed_extent = blockend; + delayed_buf = buf; + delayed_next = blknr + + (blockend >> SECTOR_BITS); + } + } else { + previous_block_number = blknr; + delayed_start = blknr; + delayed_extent = blockend; + delayed_buf = buf; + delayed_next = blknr + + (blockend >> SECTOR_BITS); + } + } else { + if (previous_block_number != -1) { + /* spill */ + put_ext4((uint64_t) (delayed_start * + SECTOR_SIZE), delayed_buf, + (uint32_t) delayed_extent); + previous_block_number = -1; + } + memset(buf, 0, fs->blksz - skipfirst); + } + buf += fs->blksz - skipfirst; + } + if (previous_block_number != -1) { + /* spill */ + put_ext4((uint64_t) (delayed_start * SECTOR_SIZE), + delayed_buf, (uint32_t) delayed_extent); + previous_block_number = -1; + } + + return len; +} + +int ext4fs_write(const char *fname, unsigned char *buffer, + unsigned long sizebytes) +{ + int ret = 0; + struct ext2_inode *file_inode = NULL; + unsigned char *inode_buffer = NULL; + int parent_inodeno; + int inodeno; + time_t timestamp = 0; + + uint64_t bytes_reqd_for_file; + unsigned int blks_reqd_for_file; + unsigned int blocks_remaining; + int existing_file_inodeno; + char *temp_ptr = NULL; + long int itable_blkno; + long int parent_itable_blkno; + long int blkoff; + struct ext2_sblock *sblock = &(ext4fs_root->sblock); + unsigned int inodes_per_block; + unsigned int ibmap_idx; + struct ext_filesystem *fs = get_fs(); + ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256); + memset(filename, 0x00, sizeof(filename)); + + g_parent_inode = zalloc(sizeof(struct ext2_inode)); + if (!g_parent_inode) + goto fail; + + if (ext4fs_init() != 0) { + printf("error in File System init\n"); + return -1; + } + inodes_per_block = fs->blksz / fs->inodesz; + parent_inodeno = ext4fs_get_parent_inode_num(fname, filename, F_FILE); + if (parent_inodeno == -1) + goto fail; + if (ext4fs_iget(parent_inodeno, g_parent_inode)) + goto fail; + /* check if the filename is already present in root */ + existing_file_inodeno = ext4fs_filename_check(filename); + if (existing_file_inodeno != -1) { + ret = ext4fs_delete_file(existing_file_inodeno); + fs->first_pass_bbmap = 0; + fs->curr_blkno = 0; + + fs->first_pass_ibmap = 0; + fs->curr_inode_no = 0; + if (ret) + goto fail; + } + /* calucalate how many blocks required */ + bytes_reqd_for_file = sizebytes; + blks_reqd_for_file = lldiv(bytes_reqd_for_file, fs->blksz); + if (do_div(bytes_reqd_for_file, fs->blksz) != 0) { + blks_reqd_for_file++; + debug("total bytes for a file %u\n", blks_reqd_for_file); + } + blocks_remaining = blks_reqd_for_file; + /* test for available space in partition */ + if (fs->sb->free_blocks < blks_reqd_for_file) { + printf("Not enough space on partition !!!\n"); + goto fail; + } + + ext4fs_update_parent_dentry(filename, &inodeno, FILETYPE_REG); + /* prepare file inode */ + inode_buffer = zalloc(fs->inodesz); + if (!inode_buffer) + goto fail; + file_inode = (struct ext2_inode *)inode_buffer; + file_inode->mode = S_IFREG | S_IRWXU | + S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH; + /* ToDo: Update correct time */ + file_inode->mtime = timestamp; + file_inode->atime = timestamp; + file_inode->ctime = timestamp; + file_inode->nlinks = 1; + file_inode->size = sizebytes; + + /* Allocate data blocks */ + ext4fs_allocate_blocks(file_inode, blocks_remaining, + &blks_reqd_for_file); + file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) / SECTOR_SIZE; + + temp_ptr = zalloc(fs->blksz); + if (!temp_ptr) + goto fail; + ibmap_idx = inodeno / ext4fs_root->sblock.inodes_per_group; + inodeno--; + itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) + + (inodeno % __le32_to_cpu(sblock->inodes_per_group)) / + inodes_per_block; + blkoff = (inodeno % inodes_per_block) * fs->inodesz; + ext4fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr); + if (ext4fs_log_journal(temp_ptr, itable_blkno)) + goto fail; + + memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz); + if (ext4fs_put_metadata(temp_ptr, itable_blkno)) + goto fail; + /* copy the file content into data blocks */ + if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) { + printf("Error in copying content\n"); + goto fail; + } + ibmap_idx = parent_inodeno / ext4fs_root->sblock.inodes_per_group; + parent_inodeno--; + parent_itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) + + (parent_inodeno % + __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; + blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz; + if (parent_itable_blkno != itable_blkno) { + memset(temp_ptr, '\0', fs->blksz); + ext4fs_devread(parent_itable_blkno * fs->sect_perblk, + 0, fs->blksz, temp_ptr); + if (ext4fs_log_journal(temp_ptr, parent_itable_blkno)) + goto fail; + + memcpy(temp_ptr + blkoff, g_parent_inode, + sizeof(struct ext2_inode)); + if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno)) + goto fail; + free(temp_ptr); + } else { + /* + * If parent and child fall in same inode table block + * both should be kept in 1 buffer + */ + memcpy(temp_ptr + blkoff, g_parent_inode, + sizeof(struct ext2_inode)); + gd_index--; + if (ext4fs_put_metadata(temp_ptr, itable_blkno)) + goto fail; + free(temp_ptr); + } + ext4fs_update(); + ext4fs_deinit(); + + fs->first_pass_bbmap = 0; + fs->curr_blkno = 0; + fs->first_pass_ibmap = 0; + fs->curr_inode_no = 0; + free(inode_buffer); + free(g_parent_inode); + g_parent_inode = NULL; + + return 0; +fail: + ext4fs_deinit(); + free(inode_buffer); + free(g_parent_inode); + g_parent_inode = NULL; + + return -1; +} diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index f02c215ccc..7fdb4634c7 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -34,13 +34,8 @@ */ #include -#include #include #include -#include -#include -#include -#include #include "ext4_common.h" int ext4fs_symlinknest; @@ -196,961 +191,3 @@ int ext4fs_read(char *buf, unsigned len) return ext4fs_read_file(ext4fs_file, 0, len, buf); } - -#if defined(CONFIG_EXT4_WRITE) -static void ext4fs_update(void) -{ - short i; - ext4fs_update_journal(); - struct ext_filesystem *fs = get_fs(); - - /* update super block */ - put_ext4((uint64_t)(SUPERBLOCK_SIZE), - (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); - - /* update block groups */ - for (i = 0; i < fs->no_blkgrp; i++) { - fs->bgd[i].bg_checksum = ext4fs_checksum_update(i); - put_ext4((uint64_t)(fs->bgd[i].block_id * fs->blksz), - fs->blk_bmaps[i], fs->blksz); - } - - /* update inode table groups */ - for (i = 0; i < fs->no_blkgrp; i++) { - put_ext4((uint64_t) (fs->bgd[i].inode_id * fs->blksz), - fs->inode_bmaps[i], fs->blksz); - } - - /* update the block group descriptor table */ - put_ext4((uint64_t)(fs->gdtable_blkno * fs->blksz), - (struct ext2_block_group *)fs->gdtable, - (fs->blksz * fs->no_blk_pergdt)); - - ext4fs_dump_metadata(); - - gindex = 0; - gd_index = 0; -} - -int ext4fs_get_bgdtable(void) -{ - int status; - int grp_desc_size; - struct ext_filesystem *fs = get_fs(); - grp_desc_size = sizeof(struct ext2_block_group); - fs->no_blk_pergdt = (fs->no_blkgrp * grp_desc_size) / fs->blksz; - if ((fs->no_blkgrp * grp_desc_size) % fs->blksz) - fs->no_blk_pergdt++; - - /* allocate memory for gdtable */ - fs->gdtable = zalloc(fs->blksz * fs->no_blk_pergdt); - if (!fs->gdtable) - return -ENOMEM; - /* read the group descriptor table */ - status = ext4fs_devread(fs->gdtable_blkno * fs->sect_perblk, 0, - fs->blksz * fs->no_blk_pergdt, fs->gdtable); - if (status == 0) - goto fail; - - if (ext4fs_log_gdt(fs->gdtable)) { - printf("Error in ext4fs_log_gdt\n"); - return -1; - } - - return 0; -fail: - free(fs->gdtable); - fs->gdtable = NULL; - - return -1; -} - -static void delete_single_indirect_block(struct ext2_inode *inode) -{ - struct ext2_block_group *bgd = NULL; - static int prev_bg_bmap_idx = -1; - long int blknr; - int remainder; - int bg_idx; - int status; - unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; - struct ext_filesystem *fs = get_fs(); - char *journal_buffer = zalloc(fs->blksz); - if (!journal_buffer) { - printf("No memory\n"); - return; - } - /* get block group descriptor table */ - bgd = (struct ext2_block_group *)fs->gdtable; - - /* deleting the single indirect block associated with inode */ - if (inode->b.blocks.indir_block != 0) { - debug("SIPB releasing %u\n", inode->b.blocks.indir_block); - blknr = inode->b.blocks.indir_block; - if (fs->blksz != 1024) { - bg_idx = blknr / blk_per_grp; - } else { - bg_idx = blknr / blk_per_grp; - remainder = blknr % blk_per_grp; - if (!remainder) - bg_idx--; - } - ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - status = - ext4fs_devread(bgd[bg_idx].block_id * - fs->sect_perblk, 0, fs->blksz, - journal_buffer); - if (status == 0) - goto fail; - if (ext4fs_log_journal - (journal_buffer, bgd[bg_idx].block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - } -fail: - free(journal_buffer); -} - -static void delete_double_indirect_block(struct ext2_inode *inode) -{ - int i; - short status; - static int prev_bg_bmap_idx = -1; - long int blknr; - int remainder; - int bg_idx; - unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; - unsigned int *di_buffer = NULL; - unsigned int *DIB_start_addr = NULL; - struct ext2_block_group *bgd = NULL; - struct ext_filesystem *fs = get_fs(); - char *journal_buffer = zalloc(fs->blksz); - if (!journal_buffer) { - printf("No memory\n"); - return; - } - /* get the block group descriptor table */ - bgd = (struct ext2_block_group *)fs->gdtable; - - if (inode->b.blocks.double_indir_block != 0) { - di_buffer = zalloc(fs->blksz); - if (!di_buffer) { - printf("No memory\n"); - return; - } - DIB_start_addr = (unsigned int *)di_buffer; - blknr = inode->b.blocks.double_indir_block; - status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, - (char *)di_buffer); - for (i = 0; i < fs->blksz / sizeof(int); i++) { - if (*di_buffer == 0) - break; - - debug("DICB releasing %u\n", *di_buffer); - if (fs->blksz != 1024) { - bg_idx = (*di_buffer) / blk_per_grp; - } else { - bg_idx = (*di_buffer) / blk_per_grp; - remainder = (*di_buffer) % blk_per_grp; - if (!remainder) - bg_idx--; - } - ext4fs_reset_block_bmap(*di_buffer, - fs->blk_bmaps[bg_idx], bg_idx); - di_buffer++; - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - status = ext4fs_devread(bgd[bg_idx].block_id - * fs->sect_perblk, 0, - fs->blksz, - journal_buffer); - if (status == 0) - goto fail; - - if (ext4fs_log_journal(journal_buffer, - bgd[bg_idx].block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - } - - /* removing the parent double indirect block */ - blknr = inode->b.blocks.double_indir_block; - if (fs->blksz != 1024) { - bg_idx = blknr / blk_per_grp; - } else { - bg_idx = blknr / blk_per_grp; - remainder = blknr % blk_per_grp; - if (!remainder) - bg_idx--; - } - ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread(bgd[bg_idx].block_id * - fs->sect_perblk, 0, fs->blksz, - journal_buffer); - if (status == 0) - goto fail; - - if (ext4fs_log_journal(journal_buffer, - bgd[bg_idx].block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - debug("DIPB releasing %ld\n", blknr); - } -fail: - free(DIB_start_addr); - free(journal_buffer); -} - -static void delete_triple_indirect_block(struct ext2_inode *inode) -{ - int i, j; - short status; - static int prev_bg_bmap_idx = -1; - long int blknr; - int remainder; - int bg_idx; - unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; - unsigned int *tigp_buffer = NULL; - unsigned int *tib_start_addr = NULL; - unsigned int *tip_buffer = NULL; - unsigned int *tipb_start_addr = NULL; - struct ext2_block_group *bgd = NULL; - struct ext_filesystem *fs = get_fs(); - char *journal_buffer = zalloc(fs->blksz); - if (!journal_buffer) { - printf("No memory\n"); - return; - } - /* get block group descriptor table */ - bgd = (struct ext2_block_group *)fs->gdtable; - - if (inode->b.blocks.triple_indir_block != 0) { - tigp_buffer = zalloc(fs->blksz); - if (!tigp_buffer) { - printf("No memory\n"); - return; - } - tib_start_addr = (unsigned int *)tigp_buffer; - blknr = inode->b.blocks.triple_indir_block; - status = ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, - (char *)tigp_buffer); - for (i = 0; i < fs->blksz / sizeof(int); i++) { - if (*tigp_buffer == 0) - break; - debug("tigp buffer releasing %u\n", *tigp_buffer); - - tip_buffer = zalloc(fs->blksz); - if (!tip_buffer) - goto fail; - tipb_start_addr = (unsigned int *)tip_buffer; - status = ext4fs_devread((*tigp_buffer) * - fs->sect_perblk, 0, fs->blksz, - (char *)tip_buffer); - for (j = 0; j < fs->blksz / sizeof(int); j++) { - if (*tip_buffer == 0) - break; - if (fs->blksz != 1024) { - bg_idx = (*tip_buffer) / blk_per_grp; - } else { - bg_idx = (*tip_buffer) / blk_per_grp; - - remainder = (*tip_buffer) % blk_per_grp; - if (!remainder) - bg_idx--; - } - - ext4fs_reset_block_bmap(*tip_buffer, - fs->blk_bmaps[bg_idx], - bg_idx); - - tip_buffer++; - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - status = - ext4fs_devread( - bgd[bg_idx].block_id * - fs->sect_perblk, 0, - fs->blksz, - journal_buffer); - if (status == 0) - goto fail; - - if (ext4fs_log_journal(journal_buffer, - bgd[bg_idx]. - block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - } - free(tipb_start_addr); - tipb_start_addr = NULL; - - /* - * removing the grand parent blocks - * which is connected to inode - */ - if (fs->blksz != 1024) { - bg_idx = (*tigp_buffer) / blk_per_grp; - } else { - bg_idx = (*tigp_buffer) / blk_per_grp; - - remainder = (*tigp_buffer) % blk_per_grp; - if (!remainder) - bg_idx--; - } - ext4fs_reset_block_bmap(*tigp_buffer, - fs->blk_bmaps[bg_idx], bg_idx); - - tigp_buffer++; - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - memset(journal_buffer, '\0', fs->blksz); - status = - ext4fs_devread(bgd[bg_idx].block_id * - fs->sect_perblk, 0, - fs->blksz, journal_buffer); - if (status == 0) - goto fail; - - if (ext4fs_log_journal(journal_buffer, - bgd[bg_idx].block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - } - - /* removing the grand parent triple indirect block */ - blknr = inode->b.blocks.triple_indir_block; - if (fs->blksz != 1024) { - bg_idx = blknr / blk_per_grp; - } else { - bg_idx = blknr / blk_per_grp; - remainder = blknr % blk_per_grp; - if (!remainder) - bg_idx--; - } - ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], bg_idx); - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread(bgd[bg_idx].block_id * - fs->sect_perblk, 0, fs->blksz, - journal_buffer); - if (status == 0) - goto fail; - - if (ext4fs_log_journal(journal_buffer, - bgd[bg_idx].block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - debug("tigp buffer itself releasing %ld\n", blknr); - } -fail: - free(tib_start_addr); - free(tipb_start_addr); - free(journal_buffer); -} - -static int ext4fs_delete_file(int inodeno) -{ - struct ext2_inode inode; - short status; - int i; - int remainder; - long int blknr; - int bg_idx; - int ibmap_idx; - char *read_buffer = NULL; - char *start_block_address = NULL; - unsigned int no_blocks; - - static int prev_bg_bmap_idx = -1; - unsigned int inodes_per_block; - long int blkno; - unsigned int blkoff; - unsigned int blk_per_grp = ext4fs_root->sblock.blocks_per_group; - unsigned int inode_per_grp = ext4fs_root->sblock.inodes_per_group; - struct ext2_inode *inode_buffer = NULL; - struct ext2_block_group *bgd = NULL; - struct ext_filesystem *fs = get_fs(); - char *journal_buffer = zalloc(fs->blksz); - if (!journal_buffer) - return -ENOMEM; - /* get the block group descriptor table */ - bgd = (struct ext2_block_group *)fs->gdtable; - status = ext4fs_read_inode(ext4fs_root, inodeno, &inode); - if (status == 0) - goto fail; - - /* read the block no allocated to a file */ - no_blocks = inode.size / fs->blksz; - if (inode.size % fs->blksz) - no_blocks++; - - if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FL) { - struct ext2fs_node *node_inode = - zalloc(sizeof(struct ext2fs_node)); - if (!node_inode) - goto fail; - node_inode->data = ext4fs_root; - node_inode->ino = inodeno; - node_inode->inode_read = 0; - memcpy(&(node_inode->inode), &inode, sizeof(struct ext2_inode)); - - for (i = 0; i < no_blocks; i++) { - blknr = read_allocated_block(&(node_inode->inode), i); - if (fs->blksz != 1024) { - bg_idx = blknr / blk_per_grp; - } else { - bg_idx = blknr / blk_per_grp; - remainder = blknr % blk_per_grp; - if (!remainder) - bg_idx--; - } - ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], - bg_idx); - debug("EXT4_EXTENTS Block releasing %ld: %d\n", - blknr, bg_idx); - - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - status = - ext4fs_devread(bgd[bg_idx].block_id * - fs->sect_perblk, 0, - fs->blksz, journal_buffer); - if (status == 0) - goto fail; - if (ext4fs_log_journal(journal_buffer, - bgd[bg_idx].block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - } - if (node_inode) { - free(node_inode); - node_inode = NULL; - } - } else { - - delete_single_indirect_block(&inode); - delete_double_indirect_block(&inode); - delete_triple_indirect_block(&inode); - - /* read the block no allocated to a file */ - no_blocks = inode.size / fs->blksz; - if (inode.size % fs->blksz) - no_blocks++; - for (i = 0; i < no_blocks; i++) { - blknr = read_allocated_block(&inode, i); - if (fs->blksz != 1024) { - bg_idx = blknr / blk_per_grp; - } else { - bg_idx = blknr / blk_per_grp; - remainder = blknr % blk_per_grp; - if (!remainder) - bg_idx--; - } - ext4fs_reset_block_bmap(blknr, fs->blk_bmaps[bg_idx], - bg_idx); - debug("ActualB releasing %ld: %d\n", blknr, bg_idx); - - bgd[bg_idx].free_blocks++; - fs->sb->free_blocks++; - /* journal backup */ - if (prev_bg_bmap_idx != bg_idx) { - memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread(bgd[bg_idx].block_id - * fs->sect_perblk, - 0, fs->blksz, - journal_buffer); - if (status == 0) - goto fail; - if (ext4fs_log_journal(journal_buffer, - bgd[bg_idx].block_id)) - goto fail; - prev_bg_bmap_idx = bg_idx; - } - } - } - - /* from the inode no to blockno */ - inodes_per_block = fs->blksz / fs->inodesz; - ibmap_idx = inodeno / inode_per_grp; - - /* get the block no */ - inodeno--; - blkno = __le32_to_cpu(bgd[ibmap_idx].inode_table_id) + - (inodeno % __le32_to_cpu(inode_per_grp)) / inodes_per_block; - - /* get the offset of the inode */ - blkoff = ((inodeno) % inodes_per_block) * fs->inodesz; - - /* read the block no containing the inode */ - read_buffer = zalloc(fs->blksz); - if (!read_buffer) - goto fail; - start_block_address = read_buffer; - status = ext4fs_devread(blkno * fs->sect_perblk, - 0, fs->blksz, read_buffer); - if (status == 0) - goto fail; - - if (ext4fs_log_journal(read_buffer, blkno)) - goto fail; - - read_buffer = read_buffer + blkoff; - inode_buffer = (struct ext2_inode *)read_buffer; - memset(inode_buffer, '\0', sizeof(struct ext2_inode)); - - /* write the inode to original position in inode table */ - if (ext4fs_put_metadata(start_block_address, blkno)) - goto fail; - - /* update the respective inode bitmaps */ - inodeno++; - ext4fs_reset_inode_bmap(inodeno, fs->inode_bmaps[ibmap_idx], ibmap_idx); - bgd[ibmap_idx].free_inodes++; - fs->sb->free_inodes++; - /* journal backup */ - memset(journal_buffer, '\0', fs->blksz); - status = ext4fs_devread(bgd[ibmap_idx].inode_id * - fs->sect_perblk, 0, fs->blksz, journal_buffer); - if (status == 0) - goto fail; - if (ext4fs_log_journal(journal_buffer, bgd[ibmap_idx].inode_id)) - goto fail; - - ext4fs_update(); - ext4fs_deinit(); - - if (ext4fs_init() != 0) { - printf("error in File System init\n"); - goto fail; - } - - free(start_block_address); - free(journal_buffer); - - return 0; -fail: - free(start_block_address); - free(journal_buffer); - - return -1; -} - -int ext4fs_init(void) -{ - short status; - int i; - unsigned int real_free_blocks = 0; - struct ext_filesystem *fs = get_fs(); - - /* populate fs */ - fs->blksz = EXT2_BLOCK_SIZE(ext4fs_root); - fs->inodesz = INODE_SIZE_FILESYSTEM(ext4fs_root); - fs->sect_perblk = fs->blksz / SECTOR_SIZE; - - /* get the superblock */ - fs->sb = zalloc(SUPERBLOCK_SIZE); - if (!fs->sb) - return -ENOMEM; - if (!ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, - (char *)fs->sb)) - goto fail; - - /* init journal */ - if (ext4fs_init_journal()) - goto fail; - - /* get total no of blockgroups */ - fs->no_blkgrp = (uint32_t)ext4fs_div_roundup( - (ext4fs_root->sblock.total_blocks - - ext4fs_root->sblock.first_data_block), - ext4fs_root->sblock.blocks_per_group); - - /* get the block group descriptor table */ - fs->gdtable_blkno = ((EXT2_MIN_BLOCK_SIZE == fs->blksz) + 1); - if (ext4fs_get_bgdtable() == -1) { - printf("Error in getting the block group descriptor table\n"); - goto fail; - } - fs->bgd = (struct ext2_block_group *)fs->gdtable; - - /* load all the available bitmap block of the partition */ - fs->blk_bmaps = zalloc(fs->no_blkgrp * sizeof(char *)); - if (!fs->blk_bmaps) - goto fail; - for (i = 0; i < fs->no_blkgrp; i++) { - fs->blk_bmaps[i] = zalloc(fs->blksz); - if (!fs->blk_bmaps[i]) - goto fail; - } - - for (i = 0; i < fs->no_blkgrp; i++) { - status = - ext4fs_devread(fs->bgd[i].block_id * fs->sect_perblk, 0, - fs->blksz, (char *)fs->blk_bmaps[i]); - if (status == 0) - goto fail; - } - - /* load all the available inode bitmap of the partition */ - fs->inode_bmaps = zalloc(fs->no_blkgrp * sizeof(unsigned char *)); - if (!fs->inode_bmaps) - goto fail; - for (i = 0; i < fs->no_blkgrp; i++) { - fs->inode_bmaps[i] = zalloc(fs->blksz); - if (!fs->inode_bmaps[i]) - goto fail; - } - - for (i = 0; i < fs->no_blkgrp; i++) { - status = ext4fs_devread(fs->bgd[i].inode_id * fs->sect_perblk, - 0, fs->blksz, - (char *)fs->inode_bmaps[i]); - if (status == 0) - goto fail; - } - - /* - * check filesystem consistency with free blocks of file system - * some time we observed that superblock freeblocks does not match - * with the blockgroups freeblocks when improper - * reboot of a linux kernel - */ - for (i = 0; i < fs->no_blkgrp; i++) - real_free_blocks = real_free_blocks + fs->bgd[i].free_blocks; - if (real_free_blocks != fs->sb->free_blocks) - fs->sb->free_blocks = real_free_blocks; - - return 0; -fail: - ext4fs_deinit(); - - return -1; -} - -void ext4fs_deinit(void) -{ - int i; - struct ext2_inode inode_journal; - struct journal_superblock_t *jsb; - long int blknr; - struct ext_filesystem *fs = get_fs(); - - /* free journal */ - char *temp_buff = zalloc(fs->blksz); - if (temp_buff) { - ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO, - &inode_journal); - blknr = read_allocated_block(&inode_journal, - EXT2_JOURNAL_SUPERBLOCK); - ext4fs_devread(blknr * fs->sect_perblk, 0, fs->blksz, - temp_buff); - jsb = (struct journal_superblock_t *)temp_buff; - jsb->s_start = cpu_to_be32(0); - put_ext4((uint64_t) (blknr * fs->blksz), - (struct journal_superblock_t *)temp_buff, fs->blksz); - free(temp_buff); - } - ext4fs_free_journal(); - - /* get the superblock */ - ext4fs_devread(SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, (char *)fs->sb); - fs->sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER; - put_ext4((uint64_t)(SUPERBLOCK_SIZE), - (struct ext2_sblock *)fs->sb, (uint32_t)SUPERBLOCK_SIZE); - free(fs->sb); - fs->sb = NULL; - - if (fs->blk_bmaps) { - for (i = 0; i < fs->no_blkgrp; i++) { - free(fs->blk_bmaps[i]); - fs->blk_bmaps[i] = NULL; - } - free(fs->blk_bmaps); - fs->blk_bmaps = NULL; - } - - if (fs->inode_bmaps) { - for (i = 0; i < fs->no_blkgrp; i++) { - free(fs->inode_bmaps[i]); - fs->inode_bmaps[i] = NULL; - } - free(fs->inode_bmaps); - fs->inode_bmaps = NULL; - } - - - free(fs->gdtable); - fs->gdtable = NULL; - fs->bgd = NULL; - /* - * reinitiliazed the global inode and - * block bitmap first execution check variables - */ - fs->first_pass_ibmap = 0; - fs->first_pass_bbmap = 0; - fs->curr_inode_no = 0; - fs->curr_blkno = 0; -} - -static int ext4fs_write_file(struct ext2_inode *file_inode, - int pos, unsigned int len, char *buf) -{ - int i; - int blockcnt; - int log2blocksize = LOG2_EXT2_BLOCK_SIZE(ext4fs_root); - unsigned int filesize = __le32_to_cpu(file_inode->size); - struct ext_filesystem *fs = get_fs(); - int previous_block_number = -1; - int delayed_start = 0; - int delayed_extent = 0; - int delayed_next = 0; - char *delayed_buf = NULL; - - /* Adjust len so it we can't read past the end of the file. */ - if (len > filesize) - len = filesize; - - blockcnt = ((len + pos) + fs->blksz - 1) / fs->blksz; - - for (i = pos / fs->blksz; i < blockcnt; i++) { - long int blknr; - int blockend = fs->blksz; - int skipfirst = 0; - blknr = read_allocated_block(file_inode, i); - if (blknr < 0) - return -1; - - blknr = blknr << log2blocksize; - - if (blknr) { - if (previous_block_number != -1) { - if (delayed_next == blknr) { - delayed_extent += blockend; - delayed_next += blockend >> SECTOR_BITS; - } else { /* spill */ - put_ext4((uint64_t) (delayed_start * - SECTOR_SIZE), - delayed_buf, - (uint32_t) delayed_extent); - previous_block_number = blknr; - delayed_start = blknr; - delayed_extent = blockend; - delayed_buf = buf; - delayed_next = blknr + - (blockend >> SECTOR_BITS); - } - } else { - previous_block_number = blknr; - delayed_start = blknr; - delayed_extent = blockend; - delayed_buf = buf; - delayed_next = blknr + - (blockend >> SECTOR_BITS); - } - } else { - if (previous_block_number != -1) { - /* spill */ - put_ext4((uint64_t) (delayed_start * - SECTOR_SIZE), delayed_buf, - (uint32_t) delayed_extent); - previous_block_number = -1; - } - memset(buf, 0, fs->blksz - skipfirst); - } - buf += fs->blksz - skipfirst; - } - if (previous_block_number != -1) { - /* spill */ - put_ext4((uint64_t) (delayed_start * SECTOR_SIZE), - delayed_buf, (uint32_t) delayed_extent); - previous_block_number = -1; - } - - return len; -} - -int ext4fs_write(const char *fname, unsigned char *buffer, - unsigned long sizebytes) -{ - int ret = 0; - struct ext2_inode *file_inode = NULL; - unsigned char *inode_buffer = NULL; - int parent_inodeno; - int inodeno; - time_t timestamp = 0; - - uint64_t bytes_reqd_for_file; - unsigned int blks_reqd_for_file; - unsigned int blocks_remaining; - int existing_file_inodeno; - char *temp_ptr = NULL; - long int itable_blkno; - long int parent_itable_blkno; - long int blkoff; - struct ext2_sblock *sblock = &(ext4fs_root->sblock); - unsigned int inodes_per_block; - unsigned int ibmap_idx; - struct ext_filesystem *fs = get_fs(); - ALLOC_CACHE_ALIGN_BUFFER(char, filename, 256); - memset(filename, 0x00, sizeof(filename)); - - g_parent_inode = zalloc(sizeof(struct ext2_inode)); - if (!g_parent_inode) - goto fail; - - if (ext4fs_init() != 0) { - printf("error in File System init\n"); - return -1; - } - inodes_per_block = fs->blksz / fs->inodesz; - parent_inodeno = ext4fs_get_parent_inode_num(fname, filename, F_FILE); - if (parent_inodeno == -1) - goto fail; - if (ext4fs_iget(parent_inodeno, g_parent_inode)) - goto fail; - /* check if the filename is already present in root */ - existing_file_inodeno = ext4fs_filename_check(filename); - if (existing_file_inodeno != -1) { - ret = ext4fs_delete_file(existing_file_inodeno); - fs->first_pass_bbmap = 0; - fs->curr_blkno = 0; - - fs->first_pass_ibmap = 0; - fs->curr_inode_no = 0; - if (ret) - goto fail; - } - /* calucalate how many blocks required */ - bytes_reqd_for_file = sizebytes; - blks_reqd_for_file = lldiv(bytes_reqd_for_file, fs->blksz); - if (do_div(bytes_reqd_for_file, fs->blksz) != 0) { - blks_reqd_for_file++; - debug("total bytes for a file %u\n", blks_reqd_for_file); - } - blocks_remaining = blks_reqd_for_file; - /* test for available space in partition */ - if (fs->sb->free_blocks < blks_reqd_for_file) { - printf("Not enough space on partition !!!\n"); - goto fail; - } - - ext4fs_update_parent_dentry(filename, &inodeno, FILETYPE_REG); - /* prepare file inode */ - inode_buffer = zalloc(fs->inodesz); - if (!inode_buffer) - goto fail; - file_inode = (struct ext2_inode *)inode_buffer; - file_inode->mode = S_IFREG | S_IRWXU | - S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH; - /* ToDo: Update correct time */ - file_inode->mtime = timestamp; - file_inode->atime = timestamp; - file_inode->ctime = timestamp; - file_inode->nlinks = 1; - file_inode->size = sizebytes; - - /* Allocate data blocks */ - ext4fs_allocate_blocks(file_inode, blocks_remaining, - &blks_reqd_for_file); - file_inode->blockcnt = (blks_reqd_for_file * fs->blksz) / SECTOR_SIZE; - - temp_ptr = zalloc(fs->blksz); - if (!temp_ptr) - goto fail; - ibmap_idx = inodeno / ext4fs_root->sblock.inodes_per_group; - inodeno--; - itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) + - (inodeno % __le32_to_cpu(sblock->inodes_per_group)) / - inodes_per_block; - blkoff = (inodeno % inodes_per_block) * fs->inodesz; - ext4fs_devread(itable_blkno * fs->sect_perblk, 0, fs->blksz, temp_ptr); - if (ext4fs_log_journal(temp_ptr, itable_blkno)) - goto fail; - - memcpy(temp_ptr + blkoff, inode_buffer, fs->inodesz); - if (ext4fs_put_metadata(temp_ptr, itable_blkno)) - goto fail; - /* copy the file content into data blocks */ - if (ext4fs_write_file(file_inode, 0, sizebytes, (char *)buffer) == -1) { - printf("Error in copying content\n"); - goto fail; - } - ibmap_idx = parent_inodeno / ext4fs_root->sblock.inodes_per_group; - parent_inodeno--; - parent_itable_blkno = __le32_to_cpu(fs->bgd[ibmap_idx].inode_table_id) + - (parent_inodeno % - __le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block; - blkoff = (parent_inodeno % inodes_per_block) * fs->inodesz; - if (parent_itable_blkno != itable_blkno) { - memset(temp_ptr, '\0', fs->blksz); - ext4fs_devread(parent_itable_blkno * fs->sect_perblk, - 0, fs->blksz, temp_ptr); - if (ext4fs_log_journal(temp_ptr, parent_itable_blkno)) - goto fail; - - memcpy(temp_ptr + blkoff, g_parent_inode, - sizeof(struct ext2_inode)); - if (ext4fs_put_metadata(temp_ptr, parent_itable_blkno)) - goto fail; - free(temp_ptr); - } else { - /* - * If parent and child fall in same inode table block - * both should be kept in 1 buffer - */ - memcpy(temp_ptr + blkoff, g_parent_inode, - sizeof(struct ext2_inode)); - gd_index--; - if (ext4fs_put_metadata(temp_ptr, itable_blkno)) - goto fail; - free(temp_ptr); - } - ext4fs_update(); - ext4fs_deinit(); - - fs->first_pass_bbmap = 0; - fs->curr_blkno = 0; - fs->first_pass_ibmap = 0; - fs->curr_inode_no = 0; - free(inode_buffer); - free(g_parent_inode); - g_parent_inode = NULL; - - return 0; -fail: - ext4fs_deinit(); - free(inode_buffer); - free(g_parent_inode); - g_parent_inode = NULL; - - return -1; -} -#endif -- cgit v1.2.3 From 436e2b731979afc904b2a39f1b2fbb2370f08cb4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:29 +0000 Subject: fs: Fully populate the filesystem method struct There is a structure in fs.c with just a probe method. By adding methods for other operations, we can avoid lots of #ifdefs and switch()s. As a first step, create the structure ready for use. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- fs/fs.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 2c9f2c5ac1..66835e2c74 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -27,6 +27,12 @@ static block_dev_desc_t *fs_dev_desc; static disk_partition_t fs_partition; static int fs_type = FS_TYPE_ANY; +static inline int fs_probe_unsupported(void) +{ + printf("** Unrecognized filesystem type **\n"); + return -1; +} + static inline int fs_ls_unsupported(const char *dirname) { printf("** Unrecognized filesystem type **\n"); @@ -40,6 +46,10 @@ static inline int fs_read_unsupported(const char *filename, ulong addr, return -1; } +static inline void fs_close_unsupported(void) +{ +} + #ifdef CONFIG_FS_FAT static int fs_probe_fat(void) { @@ -143,29 +153,57 @@ static inline void fs_close_ext(void) #define fs_read_ext fs_read_unsupported #endif -static struct { +struct fstype_info { int fstype; int (*probe)(void); -} fstypes[] = { + int (*ls)(const char *dirname); + int (*read)(const char *filename, ulong addr, int offset, int len); + void (*close)(void); +}; + +static struct fstype_info fstypes[] = { +#ifdef CONFIG_FS_FAT { .fstype = FS_TYPE_FAT, .probe = fs_probe_fat, + .close = fs_close_fat, + .ls = file_fat_ls, + .read = fs_read_fat, }, +#endif +#ifdef CONFIG_FS_EXT4 { .fstype = FS_TYPE_EXT, .probe = fs_probe_ext, + .close = fs_close_ext, + .ls = ext4fs_ls, + .read = fs_read_ext, + }, +#endif + { + .fstype = FS_TYPE_ANY, + .probe = fs_probe_unsupported, + .close = fs_close_unsupported, + .ls = fs_ls_unsupported, + .read = fs_read_unsupported, }, }; int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) { + struct fstype_info *info; int part, i; #ifdef CONFIG_NEEDS_MANUAL_RELOC static int relocated; if (!relocated) { - for (i = 0; i < ARRAY_SIZE(fstypes); i++) - fstypes[i].probe += gd->reloc_off; + for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); + i++, info++) { + info->probe += gd->reloc_off; + info->close += gd->reloc_off; + info->ls += gd->reloc_off; + info->read += gd->reloc_off; + } relocated = 1; } #endif @@ -175,17 +213,17 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) if (part < 0) return -1; - for (i = 0; i < ARRAY_SIZE(fstypes); i++) { - if ((fstype != FS_TYPE_ANY) && (fstype != fstypes[i].fstype)) + for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, info++) { + if (fstype != FS_TYPE_ANY && info->fstype != FS_TYPE_ANY && + fstype != info->fstype) continue; - if (!fstypes[i].probe()) { - fs_type = fstypes[i].fstype; + if (!info->probe()) { + fs_type = info->fstype; return 0; } } - printf("** Unrecognized filesystem type **\n"); return -1; } -- cgit v1.2.3 From c6f548d232c47a1691124d05c90fe9fb652e6874 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:30 +0000 Subject: fs: Use filesystem methods instead of switch() We can use the available methods and avoid using switch(). When the filesystem is not supported, we fall through to the 'unsupported' methods: fs_probe_unsupported() prints an error, so the others do not need to. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- fs/fs.c | 60 ++++++++++++++++++++++++++---------------------------------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 66835e2c74..856d8baf92 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -35,14 +35,12 @@ static inline int fs_probe_unsupported(void) static inline int fs_ls_unsupported(const char *dirname) { - printf("** Unrecognized filesystem type **\n"); return -1; } static inline int fs_read_unsupported(const char *filename, ulong addr, int offset, int len) { - printf("** Unrecognized filesystem type **\n"); return -1; } @@ -189,6 +187,20 @@ static struct fstype_info fstypes[] = { }, }; +static struct fstype_info *fs_get_info(int fstype) +{ + struct fstype_info *info; + int i; + + for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes) - 1; i++, info++) { + if (fstype == info->fstype) + return info; + } + + /* Return the 'unsupported' sentinel */ + return info; +} + int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) { struct fstype_info *info; @@ -229,17 +241,9 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) static void fs_close(void) { - switch (fs_type) { - case FS_TYPE_FAT: - fs_close_fat(); - break; - case FS_TYPE_EXT: - fs_close_ext(); - break; - default: - break; - } + struct fstype_info *info = fs_get_info(fs_type); + info->close(); fs_type = FS_TYPE_ANY; } @@ -247,17 +251,9 @@ int fs_ls(const char *dirname) { int ret; - switch (fs_type) { - case FS_TYPE_FAT: - ret = fs_ls_fat(dirname); - break; - case FS_TYPE_EXT: - ret = fs_ls_ext(dirname); - break; - default: - ret = fs_ls_unsupported(dirname); - break; - } + struct fstype_info *info = fs_get_info(fs_type); + + ret = info->ls(dirname); fs_close(); @@ -266,20 +262,16 @@ int fs_ls(const char *dirname) int fs_read(const char *filename, ulong addr, int offset, int len) { + struct fstype_info *info = fs_get_info(fs_type); int ret; - switch (fs_type) { - case FS_TYPE_FAT: - ret = fs_read_fat(filename, addr, offset, len); - break; - case FS_TYPE_EXT: - ret = fs_read_ext(filename, addr, offset, len); - break; - default: - ret = fs_read_unsupported(filename, addr, offset, len); - break; - } + ret = info->read(filename, addr, offset, len); + /* If we requested a specific number of bytes, check we got it */ + if (ret >= 0 && len && ret != len) { + printf("** Unable to read file %s **\n", filename); + ret = -1; + } fs_close(); return ret; -- cgit v1.2.3 From 2ded0d471912a7d6510899b1858cd9913f12b912 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:31 +0000 Subject: fs: Tell probe functions where to put their results Rather than rely on global variables for the probe functions, pass in the information that we need filled in. This allows us to potentially keep the variables private to fs.c in the future, and the meaning of the probe function is clearer. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- fs/fs.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 856d8baf92..3561727a5a 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -27,7 +27,8 @@ static block_dev_desc_t *fs_dev_desc; static disk_partition_t fs_partition; static int fs_type = FS_TYPE_ANY; -static inline int fs_probe_unsupported(void) +static inline int fs_probe_unsupported(block_dev_desc_t *fs_dev_desc, + disk_partition_t *fs_partition) { printf("** Unrecognized filesystem type **\n"); return -1; @@ -49,9 +50,10 @@ static inline void fs_close_unsupported(void) } #ifdef CONFIG_FS_FAT -static int fs_probe_fat(void) +static int fs_probe_fat(block_dev_desc_t *fs_dev_desc, + disk_partition_t *fs_partition) { - return fat_set_blk_dev(fs_dev_desc, &fs_partition); + return fat_set_blk_dev(fs_dev_desc, fs_partition); } static void fs_close_fat(void) @@ -88,11 +90,12 @@ static inline void fs_close_fat(void) #endif #ifdef CONFIG_FS_EXT4 -static int fs_probe_ext(void) +static int fs_probe_ext(block_dev_desc_t *fs_dev_desc, + disk_partition_t *fs_partition) { - ext4fs_set_blk_dev(fs_dev_desc, &fs_partition); + ext4fs_set_blk_dev(fs_dev_desc, fs_partition); - if (!ext4fs_mount(fs_partition.size)) { + if (!ext4fs_mount(fs_partition->size)) { ext4fs_close(); return -1; } @@ -153,7 +156,8 @@ static inline void fs_close_ext(void) struct fstype_info { int fstype; - int (*probe)(void); + int (*probe)(block_dev_desc_t *fs_dev_desc, + disk_partition_t *fs_partition); int (*ls)(const char *dirname); int (*read)(const char *filename, ulong addr, int offset, int len); void (*close)(void); @@ -230,7 +234,7 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) fstype != info->fstype) continue; - if (!info->probe()) { + if (!info->probe(fs_dev_desc, &fs_partition)) { fs_type = info->fstype; return 0; } -- cgit v1.2.3 From 117e050727d1f76bfc465f23eb3aa10f9f15cc1b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:32 +0000 Subject: fs: Use map_sysmem() on read This allows us to use filesystems on sandbox. It has no effect on other architectures. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- fs/fs.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/fs.c b/fs/fs.c index 3561727a5a..0cbec9958e 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -20,6 +20,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -39,7 +40,7 @@ static inline int fs_ls_unsupported(const char *dirname) return -1; } -static inline int fs_read_unsupported(const char *filename, ulong addr, +static inline int fs_read_unsupported(const char *filename, void *buf, int offset, int len) { return -1; @@ -62,12 +63,11 @@ static void fs_close_fat(void) #define fs_ls_fat file_fat_ls -static int fs_read_fat(const char *filename, ulong addr, int offset, int len) +static int fs_read_fat(const char *filename, void *buf, int offset, int len) { int len_read; - len_read = file_fat_read_at(filename, offset, - (unsigned char *)addr, len); + len_read = file_fat_read_at(filename, offset, buf, len); if (len_read == -1) { printf("** Unable to read file %s **\n", filename); return -1; @@ -110,7 +110,7 @@ static void fs_close_ext(void) #define fs_ls_ext ext4fs_ls -static int fs_read_ext(const char *filename, ulong addr, int offset, int len) +static int fs_read_ext(const char *filename, void *buf, int offset, int len) { int file_len; int len_read; @@ -130,7 +130,7 @@ static int fs_read_ext(const char *filename, ulong addr, int offset, int len) if (len == 0) len = file_len; - len_read = ext4fs_read((char *)addr, len); + len_read = ext4fs_read(buf, len); ext4fs_close(); if (len_read != len) { @@ -159,7 +159,7 @@ struct fstype_info { int (*probe)(block_dev_desc_t *fs_dev_desc, disk_partition_t *fs_partition); int (*ls)(const char *dirname); - int (*read)(const char *filename, ulong addr, int offset, int len); + int (*read)(const char *filename, void *buf, int offset, int len); void (*close)(void); }; @@ -267,9 +267,16 @@ int fs_ls(const char *dirname) int fs_read(const char *filename, ulong addr, int offset, int len) { struct fstype_info *info = fs_get_info(fs_type); + void *buf; int ret; - ret = info->read(filename, addr, offset, len); + /* + * We don't actually know how many bytes are being read, since len==0 + * means read the whole file. + */ + buf = map_sysmem(addr, len); + ret = info->read(filename, buf, offset, len); + unmap_sysmem(buf); /* If we requested a specific number of bytes, check we got it */ if (ret >= 0 && len && ret != len) { -- cgit v1.2.3 From e6d5241534486effa116bf685f7707041492ec7b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:33 +0000 Subject: fs: Move ls and read methods into ext4, fat It doesn't make a lot of sense to have these methods in fs.c. They are filesystem-specific, not generic code. Add each to the relevant filesystem and remove the associated #ifdefs in fs.c. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- fs/ext4/ext4fs.c | 37 +++++++++++++++++ fs/fat/fat.c | 17 ++++++++ fs/fs.c | 118 ++++--------------------------------------------------- include/ext4fs.h | 3 ++ include/fat.h | 2 + 5 files changed, 67 insertions(+), 110 deletions(-) diff --git a/fs/ext4/ext4fs.c b/fs/ext4/ext4fs.c index 7fdb4634c7..4dddde2476 100644 --- a/fs/ext4/ext4fs.c +++ b/fs/ext4/ext4fs.c @@ -191,3 +191,40 @@ int ext4fs_read(char *buf, unsigned len) return ext4fs_read_file(ext4fs_file, 0, len, buf); } + +int ext4fs_probe(block_dev_desc_t *fs_dev_desc, + disk_partition_t *fs_partition) +{ + ext4fs_set_blk_dev(fs_dev_desc, fs_partition); + + if (!ext4fs_mount(fs_partition->size)) { + ext4fs_close(); + return -1; + } + + return 0; +} + +int ext4_read_file(const char *filename, void *buf, int offset, int len) +{ + int file_len; + int len_read; + + if (offset != 0) { + printf("** Cannot support non-zero offset **\n"); + return -1; + } + + file_len = ext4fs_open(filename); + if (file_len < 0) { + printf("** File not found %s **\n", filename); + return -1; + } + + if (len == 0) + len = file_len; + + len_read = ext4fs_read(buf, len); + + return len_read; +} diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 66d54738a0..b0fac5e1ed 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1260,3 +1260,20 @@ long file_fat_read(const char *filename, void *buffer, unsigned long maxsize) { return file_fat_read_at(filename, 0, buffer, maxsize); } + +int fat_read_file(const char *filename, void *buf, int offset, int len) +{ + int len_read; + + len_read = file_fat_read_at(filename, offset, buf, len); + if (len_read == -1) { + printf("** Unable to read file %s **\n", filename); + return -1; + } + + return len_read; +} + +void fat_close(void) +{ +} diff --git a/fs/fs.c b/fs/fs.c index 0cbec9958e..95c882e202 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -50,110 +50,6 @@ static inline void fs_close_unsupported(void) { } -#ifdef CONFIG_FS_FAT -static int fs_probe_fat(block_dev_desc_t *fs_dev_desc, - disk_partition_t *fs_partition) -{ - return fat_set_blk_dev(fs_dev_desc, fs_partition); -} - -static void fs_close_fat(void) -{ -} - -#define fs_ls_fat file_fat_ls - -static int fs_read_fat(const char *filename, void *buf, int offset, int len) -{ - int len_read; - - len_read = file_fat_read_at(filename, offset, buf, len); - if (len_read == -1) { - printf("** Unable to read file %s **\n", filename); - return -1; - } - - return len_read; -} -#else -static inline int fs_probe_fat(void) -{ - return -1; -} - -static inline void fs_close_fat(void) -{ -} - -#define fs_ls_fat fs_ls_unsupported -#define fs_read_fat fs_read_unsupported -#endif - -#ifdef CONFIG_FS_EXT4 -static int fs_probe_ext(block_dev_desc_t *fs_dev_desc, - disk_partition_t *fs_partition) -{ - ext4fs_set_blk_dev(fs_dev_desc, fs_partition); - - if (!ext4fs_mount(fs_partition->size)) { - ext4fs_close(); - return -1; - } - - return 0; -} - -static void fs_close_ext(void) -{ - ext4fs_close(); -} - -#define fs_ls_ext ext4fs_ls - -static int fs_read_ext(const char *filename, void *buf, int offset, int len) -{ - int file_len; - int len_read; - - if (offset != 0) { - printf("** Cannot support non-zero offset **\n"); - return -1; - } - - file_len = ext4fs_open(filename); - if (file_len < 0) { - printf("** File not found %s **\n", filename); - ext4fs_close(); - return -1; - } - - if (len == 0) - len = file_len; - - len_read = ext4fs_read(buf, len); - ext4fs_close(); - - if (len_read != len) { - printf("** Unable to read file %s **\n", filename); - return -1; - } - - return len_read; -} -#else -static inline int fs_probe_ext(void) -{ - return -1; -} - -static inline void fs_close_ext(void) -{ -} - -#define fs_ls_ext fs_ls_unsupported -#define fs_read_ext fs_read_unsupported -#endif - struct fstype_info { int fstype; int (*probe)(block_dev_desc_t *fs_dev_desc, @@ -167,19 +63,19 @@ static struct fstype_info fstypes[] = { #ifdef CONFIG_FS_FAT { .fstype = FS_TYPE_FAT, - .probe = fs_probe_fat, - .close = fs_close_fat, + .probe = fat_set_blk_dev, + .close = fat_close, .ls = file_fat_ls, - .read = fs_read_fat, + .read = fat_read_file, }, #endif #ifdef CONFIG_FS_EXT4 { .fstype = FS_TYPE_EXT, - .probe = fs_probe_ext, - .close = fs_close_ext, + .probe = ext4fs_probe, + .close = ext4fs_close, .ls = ext4fs_ls, - .read = fs_read_ext, + .read = ext4_read_file, }, #endif { @@ -248,6 +144,7 @@ static void fs_close(void) struct fstype_info *info = fs_get_info(fs_type); info->close(); + fs_type = FS_TYPE_ANY; } @@ -259,6 +156,7 @@ int fs_ls(const char *dirname) ret = info->ls(dirname); + fs_type = FS_TYPE_ANY; fs_close(); return ret; diff --git a/include/ext4fs.h b/include/ext4fs.h index 3b59d15aab..025a2e89c2 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -138,4 +138,7 @@ void ext4fs_free_node(struct ext2fs_node *node, struct ext2fs_node *currroot); int ext4fs_devread(int sector, int byte_offset, int byte_len, char *buf); void ext4fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); long int read_allocated_block(struct ext2_inode *inode, int fileblock); +int ext4fs_probe(block_dev_desc_t *fs_dev_desc, + disk_partition_t *fs_partition); +int ext4_read_file(const char *filename, void *buf, int offset, int len); #endif diff --git a/include/fat.h b/include/fat.h index b28c3fd668..9701323748 100644 --- a/include/fat.h +++ b/include/fat.h @@ -213,4 +213,6 @@ int fat_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); int fat_register_device(block_dev_desc_t *dev_desc, int part_no); int file_fat_write(const char *filename, void *buffer, unsigned long maxsize); +int fat_read_file(const char *filename, void *buf, int offset, int len); +void fat_close(void); #endif /* _FAT_H_ */ -- cgit v1.2.3 From 62584db191013f13133be0f6702d0c935a7c85a6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:34 +0000 Subject: sandbox: Add a way of obtaining directory listings This implementation uses opendir()/readdir() to access the directory information and then puts it in a linked list for the caller's use. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- arch/sandbox/cpu/os.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/os.h | 48 ++++++++++++++++++++++++ 2 files changed, 149 insertions(+) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 3e37c930b0..d07540776c 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -19,10 +19,13 @@ * MA 02111-1307 USA */ +#include #include #include #include +#include #include +#include #include #include #include @@ -261,3 +264,101 @@ int os_parse_args(struct sandbox_state *state, int argc, char *argv[]) return 0; } + +void os_dirent_free(struct os_dirent_node *node) +{ + struct os_dirent_node *next; + + while (node) { + next = node->next; + free(node); + node = next; + } +} + +int os_dirent_ls(const char *dirname, struct os_dirent_node **headp) +{ + struct dirent entry, *result; + struct os_dirent_node *head, *node, *next; + struct stat buf; + DIR *dir; + int ret; + char *fname; + int len; + + *headp = NULL; + dir = opendir(dirname); + if (!dir) + return -1; + + /* Create a buffer for the maximum filename length */ + len = sizeof(entry.d_name) + strlen(dirname) + 2; + fname = malloc(len); + if (!fname) { + ret = -ENOMEM; + goto done; + } + + for (node = head = NULL;; node = next) { + ret = readdir_r(dir, &entry, &result); + if (ret || !result) + break; + next = malloc(sizeof(*node) + strlen(entry.d_name) + 1); + if (!next) { + os_dirent_free(head); + ret = -ENOMEM; + goto done; + } + strcpy(next->name, entry.d_name); + switch (entry.d_type) { + case DT_REG: + next->type = OS_FILET_REG; + break; + case DT_DIR: + next->type = OS_FILET_DIR; + break; + case DT_LNK: + next->type = OS_FILET_LNK; + break; + } + next->size = 0; + snprintf(fname, len, "%s/%s", dirname, next->name); + if (!stat(fname, &buf)) + next->size = buf.st_size; + if (node) + node->next = next; + if (!head) + head = node; + } + *headp = head; + +done: + closedir(dir); + return ret; +} + +const char *os_dirent_typename[OS_FILET_COUNT] = { + " ", + "SYM", + "DIR", + "???", +}; + +const char *os_dirent_get_typename(enum os_dirent_t type) +{ + if (type >= 0 && type < OS_FILET_COUNT) + return os_dirent_typename[type]; + + return os_dirent_typename[OS_FILET_UNKNOWN]; +} + +ssize_t os_get_filesize(const char *fname) +{ + struct stat buf; + int ret; + + ret = stat(fname, &buf); + if (ret) + return ret; + return buf.st_size; +} diff --git a/include/os.h b/include/os.h index c452d1b56e..038aba9e4f 100644 --- a/include/os.h +++ b/include/os.h @@ -146,4 +146,52 @@ u64 os_get_nsec(void); */ int os_parse_args(struct sandbox_state *state, int argc, char *argv[]); +/* + * Types of directory entry that we support. See also os_dirent_typename in + * the C file. + */ +enum os_dirent_t { + OS_FILET_REG, /* Regular file */ + OS_FILET_LNK, /* Symbolic link */ + OS_FILET_DIR, /* Directory */ + OS_FILET_UNKNOWN, /* Something else */ + + OS_FILET_COUNT, +}; + +/** A directory entry node, containing information about a single dirent */ +struct os_dirent_node { + struct os_dirent_node *next; /* Pointer to next node, or NULL */ + ulong size; /* Size of file in bytes */ + enum os_dirent_t type; /* Type of entry */ + char name[0]; /* Name of entry */ +}; + +/** + * Get a directionry listing + * + * This allocates and returns a linked list containing the directory listing. + * + * @param dirname Directory to examine + * @param headp Returns pointer to head of linked list, or NULL if none + * @return 0 if ok, -ve on error + */ +int os_dirent_ls(const char *dirname, struct os_dirent_node **headp); + +/** + * Get the name of a directory entry type + * + * @param type Type to cehck + * @return string containing the name of that type, or "???" if none/invalid + */ +const char *os_dirent_get_typename(enum os_dirent_t type); + +/** + * Get the size of a file + * + * @param fname Filename to check + * @return size of file, or -1 if an error ocurred + */ +ssize_t os_get_filesize(const char *fname); + #endif -- cgit v1.2.3 From 92ccc96bf3cd6c6a3a9a56e03d5ceb4874735d22 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:35 +0000 Subject: sandbox: Add host filesystem This allows reading of files from the host filesystem in sandbox. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- Makefile | 1 + disk/part.c | 17 +++++++++++ fs/fs.c | 10 ++++++ fs/sandbox/Makefile | 47 ++++++++++++++++++++++++++++ fs/sandbox/sandboxfs.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/fs.h | 1 + include/sandboxfs.h | 30 ++++++++++++++++++ 7 files changed, 189 insertions(+) create mode 100644 fs/sandbox/Makefile create mode 100644 fs/sandbox/sandboxfs.c create mode 100644 include/sandboxfs.h diff --git a/Makefile b/Makefile index fc18dd4cc0..8f01ff4e0f 100644 --- a/Makefile +++ b/Makefile @@ -264,6 +264,7 @@ LIBS-y += fs/libfs.o \ fs/fdos/libfdos.o \ fs/jffs2/libjffs2.o \ fs/reiserfs/libreiserfs.o \ + fs/sandbox/libsandboxfs.o \ fs/ubifs/libubifs.o \ fs/yaffs2/libyaffs2.o \ fs/zfs/libzfs.o diff --git a/disk/part.c b/disk/part.c index 7bdc90eff7..58a45637aa 100644 --- a/disk/part.c +++ b/disk/part.c @@ -472,6 +472,23 @@ int get_device_and_partition(const char *ifname, const char *dev_part_str, int part; disk_partition_t tmpinfo; + /* + * For now, we have a special case for sandbox, since there is no + * real block device support. + */ + if (0 == strcmp(ifname, "host")) { + *dev_desc = NULL; + info->start = info->size = info->blksz = 0; + info->bootable = 0; + strcpy((char *)info->type, BOOT_PART_TYPE); + strcpy((char *)info->name, "Sandbox host"); +#ifdef CONFIG_PARTITION_UUIDS + info->uuid[0] = 0; +#endif + + return 0; + } + /* If no dev_part_str, use bootdevice environment variable */ if (!dev_part_str || !strlen(dev_part_str) || !strcmp(dev_part_str, "-")) diff --git a/fs/fs.c b/fs/fs.c index 95c882e202..6f5063c3af 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -20,6 +20,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -77,6 +78,15 @@ static struct fstype_info fstypes[] = { .ls = ext4fs_ls, .read = ext4_read_file, }, +#endif +#ifdef CONFIG_SANDBOX + { + .fstype = FS_TYPE_SANDBOX, + .probe = sandbox_fs_set_blk_dev, + .close = sandbox_fs_close, + .ls = sandbox_fs_ls, + .read = fs_read_sandbox, + }, #endif { .fstype = FS_TYPE_ANY, diff --git a/fs/sandbox/Makefile b/fs/sandbox/Makefile new file mode 100644 index 0000000000..b3155b004c --- /dev/null +++ b/fs/sandbox/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (c) 2012, Google Inc. +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2003 +# Pavel Bartusek, Sysgo Real-Time Solutions AG, pba@sysgo.de +# +# 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 $(TOPDIR)/config.mk + +LIB = $(obj)libsandboxfs.o + +COBJS-$(CONFIG_SANDBOX) := sandboxfs.o + +SRCS := $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS-y)) + +all: $(LIB) $(AOBJS) + +$(LIB): $(obj).depend $(OBJS) + $(call cmd_link_o_target, $(OBJS)) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c new file mode 100644 index 0000000000..02d26ff851 --- /dev/null +++ b/fs/sandbox/sandboxfs.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, Google Inc. + * + * 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 +#include +#include + +int sandbox_fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info) +{ + return 0; +} + +long sandbox_fs_read_at(const char *filename, unsigned long pos, + void *buffer, unsigned long maxsize) +{ + ssize_t size; + int fd, ret; + + fd = os_open(filename, OS_O_RDONLY); + if (fd < 0) + return fd; + ret = os_lseek(fd, pos, OS_SEEK_SET); + if (ret == -1) { + os_close(fd); + return ret; + } + if (!maxsize) + maxsize = os_get_filesize(filename); + size = os_read(fd, buffer, maxsize); + os_close(fd); + + return size; +} + +int sandbox_fs_ls(const char *dirname) +{ + struct os_dirent_node *head, *node; + int ret; + + ret = os_dirent_ls(dirname, &head); + if (ret) + return ret; + + for (node = head; node; node = node->next) { + printf("%s %10lu %s\n", os_dirent_get_typename(node->type), + node->size, node->name); + } + + return 0; +} + +void sandbox_fs_close(void) +{ +} + +int fs_read_sandbox(const char *filename, void *buf, int offset, int len) +{ + int len_read; + + len_read = sandbox_fs_read_at(filename, offset, buf, len); + if (len_read == -1) { + printf("** Unable to read file %s **\n", filename); + return -1; + } + + return len_read; +} diff --git a/include/fs.h b/include/fs.h index 4f30a385a0..b6d69e5ced 100644 --- a/include/fs.h +++ b/include/fs.h @@ -21,6 +21,7 @@ #define FS_TYPE_ANY 0 #define FS_TYPE_FAT 1 #define FS_TYPE_EXT 2 +#define FS_TYPE_SANDBOX 3 /* * Tell the fs layer which block device an partition to use for future diff --git a/include/sandboxfs.h b/include/sandboxfs.h new file mode 100644 index 0000000000..f5213ac107 --- /dev/null +++ b/include/sandboxfs.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012, Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SANDBOX_FS__ +#define __SANDBOX_FS__ + +int sandbox_fs_set_blk_dev(block_dev_desc_t *rbdd, disk_partition_t *info); + +long sandbox_fs_read_at(const char *filename, unsigned long pos, + void *buffer, unsigned long maxsize); + +void sandbox_fs_close(void); +int sandbox_fs_ls(const char *dirname); +int fs_read_sandbox(const char *filename, void *buf, int offset, int len); + +#endif -- cgit v1.2.3 From d304931f236db3af4f6a6f522b140f26e63e3a18 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:36 +0000 Subject: sandbox: Add 'sb' command to access filesystem features The new 'sb' command is intended to deal with sandbox-specific features that have no parallel in other archs. This commit adds two sub-commands to list a directory and read a file from the host filesystem. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- README | 1 + common/Makefile | 1 + common/cmd_sandbox.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ include/config_cmd_all.h | 1 + 4 files changed, 66 insertions(+) create mode 100644 common/cmd_sandbox.c diff --git a/README b/README index 51eb71b27c..42544cead6 100644 --- a/README +++ b/README @@ -877,6 +877,7 @@ The following options need to be configured: CONFIG_CMD_READ * Read raw data from partition CONFIG_CMD_REGINFO * Register dump CONFIG_CMD_RUN run command in env variable + CONFIG_CMD_SANDBOX * sb command to access sandbox features CONFIG_CMD_SAVES * save S record dump CONFIG_CMD_SCSI * SCSI Support CONFIG_CMD_SDRAM * print SDRAM configuration information diff --git a/common/Makefile b/common/Makefile index 54fcc81588..719fc231b8 100644 --- a/common/Makefile +++ b/common/Makefile @@ -152,6 +152,7 @@ COBJS-$(CONFIG_CMD_PXE) += cmd_pxe.o COBJS-$(CONFIG_CMD_READ) += cmd_read.o COBJS-$(CONFIG_CMD_REGINFO) += cmd_reginfo.o COBJS-$(CONFIG_CMD_REISER) += cmd_reiser.o +COBJS-$(CONFIG_SANDBOX) += cmd_sandbox.o COBJS-$(CONFIG_CMD_SATA) += cmd_sata.o COBJS-$(CONFIG_CMD_SF) += cmd_sf.o COBJS-$(CONFIG_CMD_SCSI) += cmd_scsi.o diff --git a/common/cmd_sandbox.c b/common/cmd_sandbox.c new file mode 100644 index 0000000000..206a48614d --- /dev/null +++ b/common/cmd_sandbox.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2012, Google Inc. + * + * 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 +#include + +static int do_sandbox_load(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_load(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX, 16); +} + +static int do_sandbox_ls(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + return do_ls(cmdtp, flag, argc, argv, FS_TYPE_SANDBOX); +} + +static cmd_tbl_t cmd_sandbox_sub[] = { + U_BOOT_CMD_MKENT(load, 3, 0, do_sandbox_load, "", ""), + U_BOOT_CMD_MKENT(ls, 3, 0, do_sandbox_ls, "", ""), +}; + +static int do_sandbox(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + cmd_tbl_t *c; + + /* Skip past 'sandbox' */ + argc--; + argv++; + + c = find_cmd_tbl(argv[0], cmd_sandbox_sub, + ARRAY_SIZE(cmd_sandbox_sub)); + + if (c) + return c->cmd(cmdtp, flag, argc, argv); + else + return CMD_RET_USAGE; +} + +U_BOOT_CMD( + sb, 6, 1, do_sandbox, + "Miscellaneous sandbox commands", + "load host [ ] - load a file from host\n" + "sb ls host - save a file to host" +); diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h index 2a82e19c78..0930781d83 100644 --- a/include/config_cmd_all.h +++ b/include/config_cmd_all.h @@ -76,6 +76,7 @@ #define CONFIG_CMD_RARP /* rarpboot support */ #define CONFIG_CMD_READ /* Read data from partition */ #define CONFIG_CMD_RUN /* run command in env variable */ +#define CONFIG_CMD_SANDBOX /* sb command to access sandbox features */ #define CONFIG_CMD_SAVEENV /* saveenv */ #define CONFIG_CMD_SAVES /* save S record dump */ #define CONFIG_CMD_SCSI /* SCSI Support */ -- cgit v1.2.3 From 10fc12184fe844761380c1a7ce4fd68c9f5b0ba6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:37 +0000 Subject: sandbox: Enable ext4 and fat filesystems These are useful for build-testing code, at least. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- include/configs/sandbox.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 9f51a0b813..2a45c7bf20 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -32,6 +32,13 @@ #define CONFIG_OF_LIBFDT #define CONFIG_LMB +#define CONFIG_FS_FAT +#define CONFIG_FS_EXT4 +#define CONFIG_EXT4_WRITE +#define CONFIG_CMD_FAT +#define CONFIG_CMD_EXT4 +#define CONFIG_CMD_EXT4_WRITE + #define CONFIG_SYS_VSNPRINTF #define CONFIG_CMD_GPIO -- cgit v1.2.3 From e40753b207029dfc9e0a9e2ec4545fbd32e0a8cc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 26 Dec 2012 09:53:38 +0000 Subject: sandbox: config: Enable sandbox command The 'sb' command allows loading files from the host, and listing directories. Signed-off-by: Simon Glass Reviewed-by: Tom Rini --- include/configs/sandbox.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 2a45c7bf20..406da43aa1 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -97,6 +97,8 @@ #define CONFIG_SHA1 #define CONFIG_SHA256 +#define CONFIG_CMD_SANDBOX + #define CONFIG_BOOTARGS "" #define CONFIG_EXTRA_ENV_SETTINGS "stdin=serial\0" \ -- cgit v1.2.3 From 949a77109747d5db7d559359d3ec24bade653be8 Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Thu, 1 Nov 2012 16:54:18 +0000 Subject: ubifs: Allow ubifsmount volume reference by number UBI can mount volumes by name or number The current code forces you to name the volume by prepending every name with "ubi:". >From fs/ubifs/super.c * There are several ways to specify UBI volumes when mounting UBIFS: * o ubiX_Y - UBI device number X, volume Y; * o ubiY - UBI device number 0, volume Y; * o ubiX:NAME - mount UBI device X, volume with name NAME; * o ubi:NAME - mount UBI device 0, volume with name NAME. Now any name passed in any of the above forms are allowed. Also update the configs that referenced ubifsmount. Signed-off-by: Joe Hershberger --- fs/ubifs/super.c | 4 +--- include/configs/apx4devkit.h | 2 +- include/configs/cam_enc_4xx.h | 2 +- include/configs/dockstar.h | 2 +- include/configs/ea20.h | 6 +++--- include/configs/ib62x0.h | 2 +- include/configs/iconnect.h | 2 +- include/configs/omap3_pandora.h | 3 ++- include/configs/tricorder.h | 2 +- include/configs/x600.h | 2 +- 10 files changed, 13 insertions(+), 14 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 30ccd98c22..9acf243eef 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1164,10 +1164,9 @@ static struct file_system_type ubifs_fs_type = { .get_sb = ubifs_get_sb, }; -int ubifs_mount(char *vol_name) +int ubifs_mount(char *name) { int flags; - char name[80] = "ubi:"; void *data; struct vfsmount *mnt; int ret; @@ -1186,7 +1185,6 @@ int ubifs_mount(char *vol_name) * Mount in read-only mode */ flags = MS_RDONLY; - strcat(name, vol_name); data = NULL; mnt = NULL; ret = ubifs_get_sb(&ubifs_fs_type, flags, name, data, mnt); diff --git a/include/configs/apx4devkit.h b/include/configs/apx4devkit.h index 73c66af06d..ab4efa4b03 100644 --- a/include/configs/apx4devkit.h +++ b/include/configs/apx4devkit.h @@ -222,7 +222,7 @@ "root=ubi0:rootfs rootfstype=ubifs ${mtdparts} rw\0" \ "bootcmd_nand=" \ "run bootargs_nand && ubi part root 2048 && " \ - "ubifsmount rootfs && ubifsload 41000000 boot/uImage && " \ + "ubifsmount ubi:rootfs && ubifsload 41000000 boot/uImage && " \ "bootm 41000000\0" \ "bootargs_mmc=" \ "setenv bootargs ${kernelargs} " \ diff --git a/include/configs/cam_enc_4xx.h b/include/configs/cam_enc_4xx.h index a7a698c0ca..56528ddaaf 100644 --- a/include/configs/cam_enc_4xx.h +++ b/include/configs/cam_enc_4xx.h @@ -451,7 +451,7 @@ "bootfile=" __stringify(CONFIG_HOSTNAME) "/uImage \0" \ "kernel_addr_r=80600000\0" \ "load_kernel=tftp ${kernel_addr_r} ${bootfile}\0" \ - "ubi_load_kernel=ubi part ubi 2048;ubifsmount ${img_volume};" \ + "ubi_load_kernel=ubi part ubi 2048;ubifsmount ubi:${img_volume};" \ "ubifsload ${kernel_addr_r} boot/uImage\0" \ "fit_addr_r=" __stringify(CONFIG_BOARD_IMG_ADDR_R) "\0" \ "img_addr_r=" __stringify(CONFIG_BOARD_IMG_ADDR_R) "\0" \ diff --git a/include/configs/dockstar.h b/include/configs/dockstar.h index 249f93bf13..63d5e35e92 100644 --- a/include/configs/dockstar.h +++ b/include/configs/dockstar.h @@ -85,7 +85,7 @@ #define CONFIG_BOOTCOMMAND \ "setenv bootargs ${console} ${mtdparts} ${bootargs_root}; " \ "ubi part root; " \ - "ubifsmount root; " \ + "ubifsmount ubi:root; " \ "ubifsload 0x800000 ${kernel}; " \ "ubifsload 0x1100000 ${initrd}; " \ "bootm 0x800000 0x1100000" diff --git a/include/configs/ea20.h b/include/configs/ea20.h index d3eb5969dc..a8c08e8d95 100644 --- a/include/configs/ea20.h +++ b/include/configs/ea20.h @@ -293,12 +293,12 @@ "bootm ${kernel_addr_r}\0" \ "net_self_load=tftp ${kernel_addr_r} ${bootfile};" \ "tftp ${ramdisk_addr_r} ${ramdisk_file};\0" \ - "nand_nand=ubi part nand0,${as};ubifsmount rootfs;" \ + "nand_nand=ubi part nand0,${as};ubifsmount ubi:rootfs;" \ "ubifsload ${kernel_addr_r} /boot/uImage;" \ "ubifsumount; run nandargs addip addtty " \ "addmtd addmisc addmem;clrlogo;" \ "bootm ${kernel_addr_r}\0" \ - "nand_nandrw=ubi part nand0,${as};ubifsmount rootfs;" \ + "nand_nandrw=ubi part nand0,${as};ubifsmount ubi:rootfs;" \ "ubifsload ${kernel_addr_r} /boot/uImage;" \ "ubifsumount; run nandrwargs addip addtty " \ "addmtd addmisc addmem;clrlogo;" \ @@ -309,7 +309,7 @@ "u-boot=" __stringify(CONFIG_HOSTNAME) "/u-boot.bin\0" \ "load_magic=if sf probe 0;then sf " \ "read c0000000 0x10000 0x60000;fi\0" \ - "load_nand=ubi part nand0,${as};ubifsmount rootfs;" \ + "load_nand=ubi part nand0,${as};ubifsmount ubi:rootfs;" \ "if ubifsload c0000014 /boot/u-boot.bin;" \ "then mw c0000008 ${filesize};else echo Error reading" \ " u-boot from nand!;fi\0" \ diff --git a/include/configs/ib62x0.h b/include/configs/ib62x0.h index f646ae5776..d3c664cd18 100644 --- a/include/configs/ib62x0.h +++ b/include/configs/ib62x0.h @@ -88,7 +88,7 @@ #define CONFIG_BOOTCOMMAND \ "setenv bootargs ${console} ${mtdparts} ${bootargs_root}; " \ "ubi part root; " \ - "ubifsmount root; " \ + "ubifsmount ubi:root; " \ "ubifsload 0x800000 ${kernel}; " \ "ubifsload 0x1100000 ${initrd}; " \ "bootm 0x800000 0x1100000" diff --git a/include/configs/iconnect.h b/include/configs/iconnect.h index ba57849a60..c882bfa606 100644 --- a/include/configs/iconnect.h +++ b/include/configs/iconnect.h @@ -87,7 +87,7 @@ #define CONFIG_BOOTCOMMAND \ "setenv bootargs ${console} ${mtdparts} ${bootargs_root}; " \ "ubi part rootfs; " \ - "ubifsmount rootfs; " \ + "ubifsmount ubi:rootfs; " \ "ubifsload 0x800000 ${kernel}; " \ "bootm 0x800000" diff --git a/include/configs/omap3_pandora.h b/include/configs/omap3_pandora.h index ee888418c5..b77ce25880 100644 --- a/include/configs/omap3_pandora.h +++ b/include/configs/omap3_pandora.h @@ -180,7 +180,8 @@ "ext2load mmc1 0 ${loadaddr} autoboot.scr; then " \ "source ${loadaddr}; " \ "fi; " \ - "ubi part boot && ubifsmount boot && ubifsload ${loadaddr} uImage && bootm ${loadaddr}" + "ubi part boot && ubifsmount ubi:boot && " \ + "ubifsload ${loadaddr} uImage && bootm ${loadaddr}" #define CONFIG_AUTO_COMPLETE 1 /* diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h index 1a665ac3ac..ebd7a257f3 100644 --- a/include/configs/tricorder.h +++ b/include/configs/tricorder.h @@ -193,7 +193,7 @@ "bootm ${loadaddr}\0" \ "loaduimage_ubi=mtd default; " \ "ubi part fs; " \ - "ubifsmount root; " \ + "ubifsmount ubi:root; " \ "ubifsload ${loadaddr} /boot/uImage\0" \ "nandboot=echo Booting from nand ...; " \ "run nandargs; " \ diff --git a/include/configs/x600.h b/include/configs/x600.h index 3082aaa1e6..bb495a1c90 100644 --- a/include/configs/x600.h +++ b/include/configs/x600.h @@ -262,7 +262,7 @@ "nand_ubifs=run ubifs_mount ubifs_load ubifsargs addip" \ " addcon addmisc addmtd;" \ "bootm ${kernel_addr} - ${dtb_addr}\0" \ - "ubifs_mount=ubi part ubi${boot_part};ubifsmount rootfs\0" \ + "ubifs_mount=ubi part ubi${boot_part};ubifsmount ubi:rootfs\0" \ "ubifs_load=ubifsload ${kernel_addr} ${kernel_fs};" \ "ubifsload ${dtb_addr} ${dtb_fs};\0" \ "nand_ubifs=run ubifs_mount ubifs_load ubifsargs addip addcon " \ -- cgit v1.2.3 From 18a3cce9fa9030e0e1fe0678ddcd0ae84d9423ca Mon Sep 17 00:00:00 2001 From: Joe Hershberger Date: Fri, 8 Feb 2013 10:12:34 +0000 Subject: env: Avoid clobbering an edited variable on ctrl-c If readline says there was an error, don't write to the variable! Signed-off-by: Joe Hershberger --- common/cmd_nvedit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index d646d90880..3a05e60103 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -552,7 +552,8 @@ static int do_env_edit(cmd_tbl_t *cmdtp, int flag, int argc, else buffer[0] = '\0'; - readline_into_buffer("edit: ", buffer, 0); + if (readline_into_buffer("edit: ", buffer, 0) < 0) + return 1; return setenv(argv[1], buffer); } -- cgit v1.2.3 From 59af76d9ccccea43b9e07d78291bdf99e759c59a Mon Sep 17 00:00:00 2001 From: Daniel Schwierzeck Date: Tue, 26 Feb 2013 04:54:19 +0000 Subject: bootm: fix conditional compilation for bootm ramdisk subcommand All code related to the bootm ramdisk subcommand is conditionally enabled by CONFIG_SYS_BOOT_RAMDISK_HIGH except for the help message. Replace the CONFIG_ARCH defines by CONFIG_SYS_BOOT_RAMDISK_HIGH to fix this. Signed-off-by: Daniel Schwierzeck --- common/cmd_bootm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index b32991da0d..2e9335207c 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -1056,7 +1056,7 @@ static char bootm_help_text[] = "issued in the order below (it's ok to not issue all sub-commands):\n" "\tstart [addr [arg ...]]\n" "\tloados - load OS image\n" -#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_SPARC) +#if defined(CONFIG_SYS_BOOT_RAMDISK_HIGH) "\tramdisk - relocate initrd, set env initrd_start/initrd_end\n" #endif #if defined(CONFIG_OF_LIBFDT) -- cgit v1.2.3 From 47fa71b87fe5bcbe3eaa3170c8441f2813a6148e Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Thu, 28 Feb 2013 20:21:13 +0000 Subject: kerneldoc: Add Sonic Zhang to alias bfin in git-mailrc. Signed-off-by: Sonic Zhang --- doc/git-mailrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/git-mailrc b/doc/git-mailrc index 6600c150dc..0f23776041 100644 --- a/doc/git-mailrc +++ b/doc/git-mailrc @@ -32,6 +32,7 @@ alias sbabic Stefano Babic alias scottwood Scott Wood alias sjg Simon Glass alias smcnutt Scott McNutt +alias sonic Sonic Zhang alias stroese Stefan Roese alias vapier Mike Frysinger alias wd Wolfgang Denk @@ -57,7 +58,7 @@ alias ti uboot, Tom Rini alias avr32 uboot, abiessmann -alias bfin uboot, vapier +alias bfin uboot, vapier, sonic alias blackfin bfin alias m68k uboot, jasonjin -- cgit v1.2.3 From 2536850d7cd90bdb75bf3ff86838f913392b68db Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 4 Mar 2013 16:29:17 -0500 Subject: Prepare v2013.04-rc1 Signed-off-by: Tom Rini --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8f01ff4e0f..55bd55c8c0 100644 --- a/Makefile +++ b/Makefile @@ -22,9 +22,9 @@ # VERSION = 2013 -PATCHLEVEL = 01 +PATCHLEVEL = 04 SUBLEVEL = -EXTRAVERSION = +EXTRAVERSION = -rc1 ifneq "$(SUBLEVEL)" "" U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) else -- cgit v1.2.3 From 5e98947f9baa5bdc9b819d365f9f8ef65a9b1e4d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:10 +0000 Subject: x86: Add function to get top of usable ram The memory layout calculations are done in calculate_relocation_address(), and coreboot has its own version of this function. But in fact all we really need is to set the top of usable RAM, and then the base version will work as is. So instead of allowing the whole calculate_relocation_address() function to be replaced, create board_get_usable_ram_top() which can be used by a board to specify the top of the area where U-Boot relocations to. Signed-off-by: Simon Glass --- arch/x86/cpu/coreboot/sdram.c | 18 ++++-------------- arch/x86/lib/init_helpers.c | 28 ++++++++++++++++++---------- 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index 76274cb88e..a8136a06ab 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -60,12 +60,8 @@ unsigned install_e820_map(unsigned max_entries, struct e820entry *entries) * address, and how far U-Boot is moved by relocation are set in the global * data structure. */ -int calculate_relocation_address(void) +ulong board_get_usable_ram_top(ulong total_size) { - const uint64_t uboot_size = (uintptr_t)&__bss_end - - (uintptr_t)&__text_start; - const uint64_t total_size = uboot_size + CONFIG_SYS_MALLOC_LEN + - CONFIG_SYS_STACK_SIZE; uintptr_t dest_addr = 0; int i; @@ -87,21 +83,15 @@ int calculate_relocation_address(void) continue; /* Use this address if it's the largest so far. */ - if (end - uboot_size > dest_addr) + if (end > dest_addr) dest_addr = end; } /* If no suitable area was found, return an error. */ if (!dest_addr) - return 1; + panic("No available memory found for relocation"); - dest_addr -= uboot_size; - dest_addr &= ~((1 << 12) - 1); - gd->relocaddr = dest_addr; - gd->reloc_off = dest_addr - (uintptr_t)&__text_start; - gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN; - - return 0; + return (ulong)dest_addr; } int dram_init_f(void) diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 3eec9a61d6..1a097f101c 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -73,26 +73,34 @@ int init_baudrate_f(void) return 0; } -__weak int calculate_relocation_address(void) +/* Get the top of usable RAM */ +__weak ulong board_get_usable_ram_top(ulong total_size) { - ulong text_start = (ulong)&__text_start; - ulong bss_end = (ulong)&__bss_end; + return gd->ram_size; +} + +int calculate_relocation_address(void) +{ + const ulong uboot_size = (uintptr_t)&__bss_end - + (uintptr_t)&__text_start; + ulong total_size; ulong dest_addr; + total_size = ALIGN(uboot_size, 1 << 12) + CONFIG_SYS_MALLOC_LEN + + CONFIG_SYS_STACK_SIZE; + /* * NOTE: All destination address are rounded down to 16-byte * boundary to satisfy various worst-case alignment * requirements */ + dest_addr = board_get_usable_ram_top(total_size); - /* Stack is at top of available memory */ - dest_addr = gd->ram_size; - - /* U-Boot is at the top */ - dest_addr -= (bss_end - text_start); - dest_addr &= ~15; + /* U-Boot is below the FDT */ + dest_addr -= uboot_size; + dest_addr &= ~((1 << 12) - 1); gd->relocaddr = dest_addr; - gd->reloc_off = (dest_addr - text_start); + gd->reloc_off = dest_addr - (uintptr_t)&__text_start; /* Stack is at the bottom, so it can grow down */ gd->start_addr_sp = dest_addr - CONFIG_SYS_MALLOC_LEN; -- cgit v1.2.3 From 8937140957eb91060b766781bb3a9e2b191529a5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:11 +0000 Subject: x86: Add basic cache operations At present most x86 cache operations are undefined. Add a basic implementation for these. Signed-off-by: Simon Glass --- arch/x86/cpu/cpu.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 6a23974ff5..1a2f85c1fe 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -228,3 +228,26 @@ void flush_dcache_range(unsigned long start, unsigned long stop) void invalidate_dcache_range(unsigned long start, unsigned long stop) { } + +void dcache_enable(void) +{ + enable_caches(); +} + +void dcache_disable(void) +{ + disable_caches(); +} + +void icache_enable(void) +{ +} + +void icache_disable(void) +{ +} + +int icache_status(void) +{ + return 1; +} -- cgit v1.2.3 From bc2df1afb92435da6fb16310dac6b722bfaade9f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:12 +0000 Subject: x86: Permit bootstage and timer data to be used prior to relocation It is useful to be able to access the timer before U-Boot has relocated so that we can fully support bootstage. Add new global_data members to support this. Signed-off-by: Simon Glass --- arch/x86/cpu/coreboot/coreboot.c | 15 ++++++--------- arch/x86/cpu/interrupts.c | 7 +++---- arch/x86/include/asm/global_data.h | 3 +++ arch/x86/lib/timer.c | 9 ++++----- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 9c9431e0d9..f8e28f0c82 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -68,24 +68,21 @@ int board_early_init_r(void) void show_boot_progress(int val) { #if MIN_PORT80_KCLOCKS_DELAY - static uint32_t prev_stamp; - static uint32_t base; - /* * Scale the time counter reading to avoid using 64 bit arithmetics. * Can't use get_timer() here becuase it could be not yet * initialized or even implemented. */ - if (!prev_stamp) { - base = rdtsc() / 1000; - prev_stamp = 0; + if (!gd->arch.tsc_prev) { + gd->arch.tsc_base_kclocks = rdtsc() / 1000; + gd->arch.tsc_prev = 0; } else { uint32_t now; do { - now = rdtsc() / 1000 - base; - } while (now < (prev_stamp + MIN_PORT80_KCLOCKS_DELAY)); - prev_stamp = now; + now = rdtsc() / 1000 - gd->arch.tsc_base_kclocks; + } while (now < (gd->arch.tsc_prev + MIN_PORT80_KCLOCKS_DELAY)); + gd->arch.tsc_prev = now; } #endif outb(val, 0x80); diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index dd30a05a9d..6dc74e34c6 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -626,13 +626,12 @@ asm(".globl irq_common_entry\n" \ */ u64 get_ticks(void) { - static u64 tick_base; u64 now_tick = rdtsc(); - if (!tick_base) - tick_base = now_tick; + if (!gd->arch.tsc_base) + gd->arch.tsc_base = now_tick; - return now_tick - tick_base; + return now_tick - gd->arch.tsc_base; } #define PLATFORM_INFO_MSR 0xce diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 8a96fc96e8..2f84abd785 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -29,6 +29,9 @@ /* Architecture-specific global data */ struct arch_global_data { struct global_data *gd_addr; /* Location of Global Data */ + uint64_t tsc_base; /* Initial value returned by rdtsc() */ + uint32_t tsc_base_kclocks; /* Initial tsc as a kclocks value */ + uint32_t tsc_prev; /* For show_boot_progress() */ }; #endif diff --git a/arch/x86/lib/timer.c b/arch/x86/lib/timer.c index a13424b3e3..1f8ce609e2 100644 --- a/arch/x86/lib/timer.c +++ b/arch/x86/lib/timer.c @@ -37,7 +37,6 @@ struct timer_isr_function { static struct timer_isr_function *first_timer_isr; static unsigned long system_ticks; -static uint64_t base_value; /* * register_timer_isr() allows multiple architecture and board specific @@ -102,7 +101,7 @@ ulong get_timer(ulong base) void timer_set_tsc_base(uint64_t new_base) { - base_value = new_base; + gd->arch.tsc_base = new_base; } uint64_t timer_get_tsc(void) @@ -110,8 +109,8 @@ uint64_t timer_get_tsc(void) uint64_t time_now; time_now = rdtsc(); - if (!base_value) - base_value = time_now; + if (!gd->arch.tsc_base) + gd->arch.tsc_base = time_now; - return time_now - base_value; + return time_now - gd->arch.tsc_base; } -- cgit v1.2.3 From 4b491b8ddeaaf6cf6a47d7102188c9a9c6b1b3d8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:13 +0000 Subject: x86: Add an __end symbol to signal the end of the U-Boot binary With this symbol we can easy append something (e.g. an FDT) to the U-Boot binary and access it from within U-Boot. Signed-off-by: Simon Glass --- arch/x86/cpu/u-boot.lds | 2 ++ arch/x86/include/asm/u-boot-x86.h | 1 + arch/x86/lib/init_helpers.c | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index 2313cd793a..8e185f3b22 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -67,6 +67,8 @@ SECTIONS __rel_dyn_start = .; .rel.dyn : { *(.rel.dyn) } __rel_dyn_end = .; + . = ALIGN(4); + _end = .; /DISCARD/ : { *(.dynstr*) } /DISCARD/ : { *(.dynamic*) } diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 99062e5955..948615d438 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -31,6 +31,7 @@ extern ulong __rel_dyn_start; extern ulong __rel_dyn_end; extern ulong __bss_start; extern ulong __bss_end; +extern ulong _end; /* cpu/.../cpu.c */ int x86_cpu_init_r(void); diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 1a097f101c..ff2d21f4c5 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -188,7 +188,7 @@ int find_fdt(void) gd->fdt_blob = _binary_dt_dtb_start; #elif defined CONFIG_OF_SEPARATE /* FDT is at end of image */ - gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE); + gd->fdt_blob = (ulong *)&_end; #endif /* Allow the early environment to override the fdt address */ gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, -- cgit v1.2.3 From f82d15ead1badc329c4c804f0405e32289f46dd8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:14 +0000 Subject: x86: Rearrange the output input to remove BSS At present BSS data is including in the image, which wastes binary space. Remove it by rearranging the sections so that BSS is last. Signed-off-by: Simon Glass --- arch/x86/cpu/u-boot.lds | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index 8e185f3b22..54f2fb76f7 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -45,9 +45,6 @@ SECTIONS . = ALIGN(4); .data : { *(.data*) } - . = ALIGN(4); - .dynsym : { *(.dynsym*) } - . = ALIGN(4); .hash : { *(.hash*) } @@ -58,10 +55,7 @@ SECTIONS __data_end = .; . = ALIGN(4); - __bss_start = ABSOLUTE(.); - .bss (NOLOAD) : { *(.bss) } - . = ALIGN(4); - __bss_end = ABSOLUTE(.); + .dynsym : { *(.dynsym*) } . = ALIGN(4); __rel_dyn_start = .; @@ -70,6 +64,17 @@ SECTIONS . = ALIGN(4); _end = .; + . = ALIGN(4); + + __end = .; + .bss __rel_dyn_start (OVERLAY) : { + __bss_start = .; + *(.bss) + *(COM*) + . = ALIGN(4); + __bss_end = .; + } + /DISCARD/ : { *(.dynstr*) } /DISCARD/ : { *(.dynamic*) } /DISCARD/ : { *(.plt*) } -- cgit v1.2.3 From f697d528caba0c30382b7269fd36f1111e51810d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:15 +0000 Subject: x86: Support relocation of FDT on start-up With CONFIG_OF_CONTROL we may have an FDT in the BSS region. Relocate it up with the rest of U-Boot to keep the rest of memory free. Signed-off-by: Simon Glass --- arch/x86/include/asm/global_data.h | 1 + arch/x86/include/asm/init_helpers.h | 2 ++ arch/x86/include/asm/relocate.h | 1 + arch/x86/lib/board.c | 3 +++ arch/x86/lib/init_helpers.c | 23 +++++++++++++++++++++-- arch/x86/lib/init_wrappers.c | 1 + arch/x86/lib/relocate.c | 17 +++++++++++++++++ 7 files changed, 46 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 2f84abd785..4fdb08090a 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -32,6 +32,7 @@ struct arch_global_data { uint64_t tsc_base; /* Initial value returned by rdtsc() */ uint32_t tsc_base_kclocks; /* Initial tsc as a kclocks value */ uint32_t tsc_prev; /* For show_boot_progress() */ + void *new_fdt; /* Relocated FDT */ }; #endif diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h index 2f437e0343..d018b290c1 100644 --- a/arch/x86/include/asm/init_helpers.h +++ b/arch/x86/include/asm/init_helpers.h @@ -38,5 +38,7 @@ int flash_init_r(void); int status_led_set_r(void); int set_load_addr_r(void); int init_func_spi(void); +int find_fdt(void); +int prepare_fdt(void); #endif /* !_INIT_HELPERS_H_ */ diff --git a/arch/x86/include/asm/relocate.h b/arch/x86/include/asm/relocate.h index 33129ef64b..d371c9d641 100644 --- a/arch/x86/include/asm/relocate.h +++ b/arch/x86/include/asm/relocate.h @@ -27,6 +27,7 @@ #include int copy_uboot_to_ram(void); +int copy_fdt_to_ram(void); int clear_bss(void); int do_elf_reloc_fixups(void); diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index 22bc26dde9..2441a66ae2 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -32,6 +32,7 @@ */ #include +#include #include #include #include @@ -131,6 +132,7 @@ init_fnc_t *init_sequence_f[] = { init_fnc_t *init_sequence_f_r[] = { init_cache_f_r, copy_uboot_to_ram, + copy_fdt_to_ram, clear_bss, do_elf_reloc_fixups, @@ -217,6 +219,7 @@ static void do_init_loop(init_fnc_t **init_fnc_ptr) void board_init_f(ulong boot_flags) { + gd->fdt_blob = gd->arch.new_fdt = NULL; gd->flags = boot_flags; do_init_loop(init_sequence_f); diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index ff2d21f4c5..414fdcc4c9 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -22,6 +22,7 @@ */ #include #include +#include #include #include #include @@ -85,17 +86,35 @@ int calculate_relocation_address(void) (uintptr_t)&__text_start; ulong total_size; ulong dest_addr; + ulong fdt_size = 0; +#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL) + if (gd->fdt_blob) + fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); +#endif total_size = ALIGN(uboot_size, 1 << 12) + CONFIG_SYS_MALLOC_LEN + - CONFIG_SYS_STACK_SIZE; + CONFIG_SYS_STACK_SIZE + fdt_size; + dest_addr = board_get_usable_ram_top(total_size); /* * NOTE: All destination address are rounded down to 16-byte * boundary to satisfy various worst-case alignment * requirements */ - dest_addr = board_get_usable_ram_top(total_size); + dest_addr &= ~15; +#if defined(CONFIG_OF_SEPARATE) && defined(CONFIG_OF_CONTROL) + /* + * If the device tree is sitting immediate above our image then we + * must relocate it. If it is embedded in the data section, then it + * will be relocated with other data. + */ + if (gd->fdt_blob) { + dest_addr -= fdt_size; + gd->arch.new_fdt = (void *)dest_addr; + dest_addr &= ~15; + } +#endif /* U-Boot is below the FDT */ dest_addr -= uboot_size; dest_addr &= ~((1 << 12) - 1); diff --git a/arch/x86/lib/init_wrappers.c b/arch/x86/lib/init_wrappers.c index cca018fa9b..19af875c0e 100644 --- a/arch/x86/lib/init_wrappers.c +++ b/arch/x86/lib/init_wrappers.c @@ -22,6 +22,7 @@ */ #include #include +#include #include #include #include diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index 23edca9526..3a38e52ac9 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -32,6 +32,7 @@ */ #include +#include #include #include #include @@ -46,6 +47,22 @@ int copy_uboot_to_ram(void) return 0; } +int copy_fdt_to_ram(void) +{ + if (gd->arch.new_fdt) { + ulong fdt_size; + + fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob) + 0x1000, 32); + + memcpy(gd->arch.new_fdt, gd->fdt_blob, fdt_size); + debug("Relocated fdt from %p to %p, size %lx\n", + gd->fdt_blob, gd->arch.new_fdt, fdt_size); + gd->fdt_blob = gd->arch.new_fdt; + } + + return 0; +} + int clear_bss(void) { ulong dst_addr = (ulong)&__bss_start + gd->reloc_off; -- cgit v1.2.3 From 62f7970a5a063991a00fb426704bfcf7c9dc9c11 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:16 +0000 Subject: x86: Add error checking to x86 relocation code This does not actually change normal behaviour, but adds a check that should detect corruption of relocation data (e.g. by using BSS data prior to relocation). Also add additional debugging output when enabled. During this investigation, two situations have been seen: 1. calculate_relocation_address(): uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; turns into 111166f: b8 83 c4 17 01 mov $0x117c483,%eax whih is beyond the end of bss: 0117b484 g .bss 00000000 __bss_end Somehow the __bss_end here is 255 bytes ahead. 2. do_elf_reloc_fixups(): uintptr_t size = (uintptr_t)&__bss_end - (uintptr_t)&__text_start; Here the __text_start is 0 in the file: 1111d9f: bb a0 e0 13 01 mov $0x113e0a0,%ebx 1111da4: 81 ef 00 00 00 00 sub $0x0,%edi As it happens, both of these are in pre-relocation code. For these reasons we silent check and ignore bad relocations. Signed-off-by: Simon Glass --- arch/x86/lib/relocate.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/x86/lib/relocate.c b/arch/x86/lib/relocate.c index 3a38e52ac9..3e370f2906 100644 --- a/arch/x86/lib/relocate.c +++ b/arch/x86/lib/relocate.c @@ -73,12 +73,16 @@ int clear_bss(void) return 0; } +/* + * This function has more error checking than you might expect. Please see + * the commit message for more informaiton. + */ int do_elf_reloc_fixups(void) { Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start); Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end); - Elf32_Addr *offset_ptr_rom; + Elf32_Addr *offset_ptr_rom, *last_offset = NULL; Elf32_Addr *offset_ptr_ram; /* The size of the region of u-boot that runs out of RAM. */ @@ -89,7 +93,8 @@ int do_elf_reloc_fixups(void) offset_ptr_rom = (Elf32_Addr *)re_src->r_offset; /* Check that the location of the relocation is in .text */ - if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE) { + if (offset_ptr_rom >= (Elf32_Addr *)CONFIG_SYS_TEXT_BASE && + offset_ptr_rom > last_offset) { /* Switch to the in-RAM version */ offset_ptr_ram = (Elf32_Addr *)((ulong)offset_ptr_rom + @@ -100,8 +105,19 @@ int do_elf_reloc_fixups(void) *offset_ptr_ram <= (CONFIG_SYS_TEXT_BASE + size)) { *offset_ptr_ram += gd->reloc_off; + } else { + debug(" %p: rom reloc %x, ram %p, value %x," + " limit %lx\n", re_src, + re_src->r_offset, offset_ptr_ram, + *offset_ptr_ram, + CONFIG_SYS_TEXT_BASE + size); } + } else { + debug(" %p: rom reloc %x, last %p\n", re_src, + re_src->r_offset, last_offset); } + last_offset = offset_ptr_rom; + } while (++re_src < re_end); return 0; -- cgit v1.2.3 From 26f7621d99e36d947909273b521eb4a8cead0a96 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:17 +0000 Subject: x86: Adjust link device tree include file This is currently set to coreboot.dtsi, but we cannot support this on old device tree compilers (dtc <= 1.3), so adjust to use ARCH_CPU_DTS to let the Makefile preprocessor sort this out. Signed-off-by: Simon Glass --- board/chromebook-x86/dts/link.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/chromebook-x86/dts/link.dts b/board/chromebook-x86/dts/link.dts index af60f59de7..ae8217d02e 100644 --- a/board/chromebook-x86/dts/link.dts +++ b/board/chromebook-x86/dts/link.dts @@ -1,6 +1,6 @@ /dts-v1/; -/include/ "coreboot.dtsi" +/include/ ARCH_CPU_DTS / { #address-cells = <1>; -- cgit v1.2.3 From fc959081d41aab2d6f4614c5fb3dd1b77ffcdcf4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 28 Feb 2013 19:26:18 +0000 Subject: x86: Enable CONFIG_OF_CONTROL on coreboot Make use of a device tree on coreboot boards, and set the default to link. Signed-off-by: Simon Glass --- include/configs/coreboot.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index c7f36ff148..49f05decc0 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -42,6 +42,12 @@ #define CONFIG_ZBOOT_32 #define CONFIG_PHYSMEM +#define CONFIG_LMB +#define CONFIG_OF_LIBFDT +#define CONFIG_OF_CONTROL +#define CONFIG_OF_SEPARATE +#define CONFIG_DEFAULT_DEVICE_TREE link + /*----------------------------------------------------------------------- * Watchdog Configuration */ -- cgit v1.2.3