summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/Makefile3
-rw-r--r--arch/arm/boards/animeo_ip/init.c90
-rw-r--r--arch/arm/boards/beaglebone/lowlevel.c14
-rw-r--r--arch/arm/boards/edb93xx/edb93xx.c1
-rw-r--r--arch/arm/boards/freescale-mx23-evk/mx23-evk.c6
-rw-r--r--arch/arm/boards/freescale-mx28-evk/mx28-evk.c21
-rw-r--r--arch/arm/boards/friendlyarm-tiny210/lowlevel.c2
-rw-r--r--arch/arm/boards/karo-tx28/tx28-stk5.c6
-rw-r--r--arch/arm/boards/phytec-pfla02/lowlevel.c2
-rw-r--r--arch/arm/boards/versatile/versatilepb.c7
-rw-r--r--arch/arm/boards/vexpress/init.c2
-rw-r--r--arch/arm/configs/animeo_ip_defconfig5
-rw-r--r--arch/arm/configs/imx28evk_defconfig5
-rw-r--r--arch/arm/cpu/mmu.c2
-rw-r--r--arch/arm/dts/imx6q.dtsi4
-rw-r--r--arch/arm/lib/Makefile2
-rw-r--r--arch/arm/lib/armlinux.c29
-rw-r--r--arch/arm/mach-at91/include/mach/board.h1
-rw-r--r--arch/arm/mach-mxs/include/mach/imx28-regs.h3
-rw-r--r--arch/arm/mach-omap/am33xx_generic.c33
-rw-r--r--arch/arm/mach-omap/include/mach/generic.h10
-rw-r--r--arch/arm/mach-omap/omap_generic.c67
-rw-r--r--arch/arm/mach-omap/xload.c10
-rw-r--r--arch/arm/pbl/Makefile8
-rw-r--r--arch/arm/tools/mach-types585
-rw-r--r--arch/mips/boards/rzx50/Makefile1
-rw-r--r--arch/mips/boards/rzx50/board.c12
-rw-r--r--arch/mips/boards/rzx50/serial.c1
-rw-r--r--arch/mips/configs/rzx50_defconfig6
-rw-r--r--arch/mips/dts/rzx50.dts12
-rw-r--r--arch/mips/mach-bcm47xx/include/mach/debug_ll.h6
-rw-r--r--arch/ppc/mach-mpc85xx/fdt.c4
-rw-r--r--arch/sandbox/board/console.c5
-rw-r--r--arch/sandbox/mach-sandbox/include/mach/linux.h1
-rw-r--r--commands/Kconfig11
-rw-r--r--commands/Makefile2
-rw-r--r--commands/boot.c258
-rw-r--r--commands/bootm.c85
-rw-r--r--commands/crc.c20
-rw-r--r--commands/detect.c1
-rw-r--r--commands/devinfo.c158
-rw-r--r--commands/loadb.c22
-rw-r--r--commands/loads.c7
-rw-r--r--commands/loadxy.c24
-rw-r--r--commands/login.c24
-rw-r--r--commands/mount.c66
-rw-r--r--commands/passwd.c8
-rw-r--r--commands/ubi.c20
-rw-r--r--common/Kconfig25
-rw-r--r--common/Makefile20
-rw-r--r--common/binfmt.c5
-rw-r--r--common/block.c5
-rw-r--r--common/bootm.c74
-rw-r--r--common/console.c24
-rw-r--r--common/console_common.c82
-rw-r--r--common/console_simple.c14
-rw-r--r--common/env.c71
-rw-r--r--common/filetype.c3
-rw-r--r--common/globalvar.c5
-rw-r--r--common/hush.c6
-rw-r--r--common/parser.c9
-rw-r--r--common/password.c94
-rw-r--r--common/startup.c2
-rw-r--r--defaultenv-2/base/bin/_boot44
-rw-r--r--defaultenv-2/base/bin/_boot_help20
-rw-r--r--defaultenv-2/base/bin/_boot_list7
-rw-r--r--defaultenv-2/base/bin/boot65
-rw-r--r--defaultenv-2/base/bin/init37
-rw-r--r--drivers/ata/ide-sff.c3
-rw-r--r--drivers/base/driver.c148
-rw-r--r--drivers/clocksource/arm_smp_twd.c9
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-dw.c159
-rw-r--r--drivers/i2c/busses/i2c-omap.c636
-rw-r--r--drivers/input/gpio_keys.c1
-rw-r--r--drivers/input/imx_keypad.c1
-rw-r--r--drivers/input/qt1070.c1
-rw-r--r--drivers/input/twl6030_pwrbtn.c1
-rw-r--r--drivers/mci/Kconfig8
-rw-r--r--drivers/mci/Makefile1
-rw-r--r--drivers/mci/atmel_mci.c1
-rw-r--r--drivers/mci/dw_mmc.c609
-rw-r--r--drivers/mci/imx-esdhc.c15
-rw-r--r--drivers/mci/omap_hsmmc.c4
-rw-r--r--drivers/mci/sdhci.h1
-rw-r--r--drivers/net/Kconfig6
-rw-r--r--drivers/net/designware.c135
-rw-r--r--drivers/net/designware.h62
-rw-r--r--drivers/net/macb.c22
-rw-r--r--drivers/net/smc91111.c30
-rw-r--r--drivers/pwm/core.c7
-rw-r--r--drivers/serial/amba-pl011.c5
-rw-r--r--drivers/serial/arm_dcc.c1
-rw-r--r--drivers/serial/atmel.c3
-rw-r--r--drivers/serial/linux_console.c10
-rw-r--r--drivers/serial/serial_altera.c1
-rw-r--r--drivers/serial/serial_altera_jtag.c1
-rw-r--r--drivers/serial/serial_auart.c2
-rw-r--r--drivers/serial/serial_blackfin.c1
-rw-r--r--drivers/serial/serial_cadence.c1
-rw-r--r--drivers/serial/serial_clps711x.c4
-rw-r--r--drivers/serial/serial_imx.c2
-rw-r--r--drivers/serial/serial_mpc5xxx.c1
-rw-r--r--drivers/serial/serial_netx.c1
-rw-r--r--drivers/serial/serial_ns16550.c3
-rw-r--r--drivers/serial/serial_omap4_usbboot.c1
-rw-r--r--drivers/serial/serial_pl010.c1
-rw-r--r--drivers/serial/serial_pxa.c1
-rw-r--r--drivers/serial/serial_s3c.c1
-rw-r--r--drivers/serial/stm-serial.c1
-rw-r--r--drivers/usb/core/usb.c8
-rw-r--r--drivers/usb/gadget/u_serial.c1
-rw-r--r--drivers/usb/host/ehci-hcd.c1
-rw-r--r--drivers/usb/host/ohci-hcd.c1
-rw-r--r--fs/Kconfig19
-rw-r--r--fs/Makefile2
-rw-r--r--fs/bpkfs.c514
-rw-r--r--fs/cramfs/cramfs.c18
-rw-r--r--fs/ext4/ext_barebox.c14
-rw-r--r--fs/fat/fat.c17
-rw-r--r--fs/fs.c113
-rw-r--r--fs/ubifs/ubifs.c16
-rw-r--r--fs/uimagefs.c554
-rw-r--r--images/Makefile3
-rw-r--r--include/block.h6
-rw-r--r--include/boot.h18
-rw-r--r--include/console.h8
-rw-r--r--include/environment.h31
-rw-r--r--include/filetype.h1
-rw-r--r--include/fs.h7
-rw-r--r--include/globalvar.h84
-rw-r--r--include/i2c/i2c.h1
-rw-r--r--include/local_mac_address.h42
-rw-r--r--include/lzo.h9
-rw-r--r--include/net/designware.h1
-rw-r--r--include/net/smc91111.h14
-rw-r--r--include/password.h22
-rw-r--r--include/platform_data/dw_mmc.h9
-rw-r--r--include/printk.h9
-rw-r--r--include/shell.h12
-rw-r--r--include/uimagefs.h53
-rw-r--r--include/usb/usb.h1
-rw-r--r--lib/copy_file.c10
-rw-r--r--lib/decompress_unlzo.c4
-rw-r--r--lib/lzo/Makefile2
-rw-r--r--lib/lzo/lzo1x_compress.c335
-rw-r--r--lib/lzo/lzo1x_decompress.c247
-rw-r--r--lib/lzo/lzo1x_decompress_safe.c230
-rw-r--r--lib/lzo/lzodefs.h38
-rw-r--r--lib/process_escape_sequence.c7
-rw-r--r--lib/show_progress.c5
-rw-r--r--net/dhcp.c12
-rw-r--r--net/netconsole.c1
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile31
-rw-r--r--scripts/bareboxenv.c12
-rw-r--r--scripts/fix_size.c81
-rw-r--r--scripts/omap4_usbboot/.gitignore1
-rw-r--r--scripts/omap4_usbboot/Makefile5
-rw-r--r--scripts/omap4_usbboot/omap4_usbboot.c (renamed from scripts/omap4_usbboot.c)0
-rw-r--r--scripts/omap4_usbboot/usb.h (renamed from scripts/usb.h)0
-rw-r--r--scripts/omap4_usbboot/usb_linux.c (renamed from scripts/usb_linux.c)0
-rw-r--r--scripts/omap_signGP.c59
166 files changed, 5459 insertions, 1429 deletions
diff --git a/Makefile b/Makefile
index a379f95adb..190f931310 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
VERSION = 2013
-PATCHLEVEL = 09
+PATCHLEVEL = 10
SUBLEVEL = 0
EXTRAVERSION =
-NAME = Just married Maintainer
+NAME = La tour Eiffel
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 687acca71d..38116becf5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -10,7 +10,7 @@ config ARM
config ARM_LINUX
bool
default y
- depends on CMD_BOOTZ || CMD_BOOTU || CMD_BOOTM
+ depends on CMD_BOOTZ || CMD_BOOTU || BOOTM
config HAVE_MACH_ARM_HEAD
bool
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 590a0d8f7b..7787cfed7d 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -142,8 +142,7 @@ KBUILD_IMAGE := barebox.s5p
endif
quiet_cmd_mlo ?= IFT $@
- cmd_mlo ?= scripts/omap_signGP $< $(TEXT_BASE) 1; \
- test -e $<.ift && mv $<.ift MLO
+ cmd_mlo ?= scripts/omap_signGP -o MLO -l $(TEXT_BASE) -c $<
MLO: $(KBUILD_BINARY)
$(call if_changed,mlo)
diff --git a/arch/arm/boards/animeo_ip/init.c b/arch/arm/boards/animeo_ip/init.c
index d46f64508d..2fee1ff616 100644
--- a/arch/arm/boards/animeo_ip/init.c
+++ b/arch/arm/boards/animeo_ip/init.c
@@ -19,6 +19,7 @@
#include <nand.h>
#include <sizes.h>
#include <linux/mtd/nand.h>
+#include <linux/clk.h>
#include <mach/board.h>
#include <mach/at91sam9_smc.h>
#include <gpio.h>
@@ -26,6 +27,7 @@
#include <mach/io.h>
#include <mach/at91_pmc.h>
#include <mach/at91_rstc.h>
+#include <local_mac_address.h>
static bool animeo_ip_is_buco;
static bool animeo_ip_is_io;
@@ -136,6 +138,7 @@ static struct atmel_mci_platform_data __initdata animeo_ip_mci_data = {
.slot_b = 1,
.detect_pin = -EINVAL,
.wp_pin = -EINVAL,
+ .devname = "microsd",
};
static void animeo_ip_add_device_mci(void)
@@ -146,6 +149,21 @@ static void animeo_ip_add_device_mci(void)
static void animeo_ip_add_device_mci(void) {}
#endif
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata animeo_ip_usbh_data = {
+ .ports = 2,
+ .vbus_pin = {AT91_PIN_PB15, -EINVAL},
+ .vbus_pin_active_low = {0, 0},
+
+};
+
+static void animeo_ip_add_device_usb(void)
+{
+ at91_add_device_usbh_ohci(&animeo_ip_usbh_data);
+}
+
struct gpio_bicolor_led leds[] = {
{
.gpio_c0 = AT91_PIN_PC17,
@@ -210,12 +228,80 @@ static void animeo_ip_power_control(void)
animeo_export_gpio_out(AT91_PIN_PC4, "power_save");
}
+static void animeo_ip_phy_reset(void)
+{
+ unsigned long rstc;
+ int i;
+ struct clk *clk = clk_get(NULL, "macb_clk");
+
+ clk_enable(clk);
+
+ for (i = AT91_PIN_PA12; i <= AT91_PIN_PA29; i++)
+ at91_set_gpio_input(i, 0);
+
+ rstc = at91_sys_read(AT91_RSTC_MR) & AT91_RSTC_ERSTL;
+
+ /* Need to reset PHY -> 500ms reset */
+ at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY |
+ (AT91_RSTC_ERSTL & (0x0d << 8)) |
+ AT91_RSTC_URSTEN);
+
+ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_EXTRST);
+
+ /* Wait for end hardware reset */
+ while (!(at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_NRSTL))
+ ;
+
+ /* Restore NRST value */
+ at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | (rstc) | AT91_RSTC_URSTEN);
+}
+
+#define MACB_SA1B 0x0098
+#define MACB_SA1T 0x009c
+
+static int animeo_ip_get_macb_ethaddr(u8 *addr)
+{
+ u32 top, bottom;
+ void __iomem *base = IOMEM(AT91SAM9260_BASE_EMAC);
+
+ bottom = readl(base + MACB_SA1B);
+ top = readl(base + MACB_SA1T);
+ addr[0] = bottom & 0xff;
+ addr[1] = (bottom >> 8) & 0xff;
+ addr[2] = (bottom >> 16) & 0xff;
+ addr[3] = (bottom >> 24) & 0xff;
+ addr[4] = top & 0xff;
+ addr[5] = (top >> 8) & 0xff;
+
+ /* valid and not private */
+ if (is_valid_ether_addr(addr) && !(addr[0] & 0x02))
+ return 0;
+
+ return -EINVAL;
+}
+
+static void animeo_ip_add_device_eth(void)
+{
+ u8 enetaddr[6];
+
+ if (!animeo_ip_get_macb_ethaddr(enetaddr))
+ eth_register_ethaddr(0, enetaddr);
+ else
+ local_mac_address_register(0, "smf");
+
+ /* for usb asix */
+ local_mac_address_register(1, "smf");
+
+ animeo_ip_phy_reset();
+ at91_add_device_eth(0, &macb_pdata);
+}
+
static int animeo_ip_devices_init(void)
{
animeo_ip_detect_version();
animeo_ip_power_control();
animeo_ip_add_device_nand();
- at91_add_device_eth(0, &macb_pdata);
+ animeo_ip_add_device_usb();
animeo_ip_add_device_mci();
animeo_ip_add_device_buttons();
animeo_ip_add_device_led();
@@ -234,6 +320,8 @@ static int animeo_ip_devices_init(void)
devfs_add_partition("nand0", SZ_256K + SZ_32K, SZ_32K, DEVFS_PARTITION_FIXED, "env_raw");
dev_add_bb_dev("env_raw", "env0");
+ animeo_ip_add_device_eth();
+
return 0;
}
diff --git a/arch/arm/boards/beaglebone/lowlevel.c b/arch/arm/boards/beaglebone/lowlevel.c
index 2ff7c7169c..e993c8928a 100644
--- a/arch/arm/boards/beaglebone/lowlevel.c
+++ b/arch/arm/boards/beaglebone/lowlevel.c
@@ -36,13 +36,13 @@ static const struct am33xx_cmd_control ddr2_cmd_ctrl = {
};
static const struct am33xx_emif_regs ddr2_regs = {
- .emif_read_latency = 0x5,
- .emif_tim1 = 0x0666B3D6,
- .emif_tim2 = 0x143731DA,
- .emif_tim3 = 0x00000347,
- .sdram_config = 0x43805332,
- .sdram_config2 = 0x43805332,
- .sdram_ref_ctrl = 0x0000081a,
+ .emif_read_latency = 0x100005,
+ .emif_tim1 = 0x0666B3C9,
+ .emif_tim2 = 0x243631CA,
+ .emif_tim3 = 0x0000033F,
+ .sdram_config = 0x41805332,
+ .sdram_config2 = 0x41805332,
+ .sdram_ref_ctrl = 0x0000081A,
};
static const struct am33xx_ddr_data ddr2_data = {
diff --git a/arch/arm/boards/edb93xx/edb93xx.c b/arch/arm/boards/edb93xx/edb93xx.c
index 27ba90abfd..1388590267 100644
--- a/arch/arm/boards/edb93xx/edb93xx.c
+++ b/arch/arm/boards/edb93xx/edb93xx.c
@@ -24,6 +24,7 @@
#include <partition.h>
#include <asm/armlinux.h>
#include <io.h>
+#include <malloc.h>
#include <generated/mach-types.h>
#include <mach/ep93xx-regs.h>
#include "edb93xx.h"
diff --git a/arch/arm/boards/freescale-mx23-evk/mx23-evk.c b/arch/arm/boards/freescale-mx23-evk/mx23-evk.c
index 1714fddb6d..9ba32d3a1f 100644
--- a/arch/arm/boards/freescale-mx23-evk/mx23-evk.c
+++ b/arch/arm/boards/freescale-mx23-evk/mx23-evk.c
@@ -19,6 +19,7 @@
#include <gpio.h>
#include <environment.h>
#include <mci.h>
+#include <linux/err.h>
#include <asm/armlinux.h>
#include <generated/mach-types.h>
#include <mach/imx-regs.h>
@@ -95,8 +96,11 @@ static int register_persistant_environment(void)
}
/* use the full partition as our persistent environment storage */
- return devfs_add_partition("disk0.1", 0, cdev->size,
+ cdev = devfs_add_partition("disk0.1", 0, cdev->size,
DEVFS_PARTITION_FIXED, "env0");
+ if (IS_ERR(cdev))
+ return PTR_ERR(cdev);
+ return 0;
}
static int mx23_evk_devices_init(void)
diff --git a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
index 92f0a75655..fa631df95a 100644
--- a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
+++ b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
@@ -32,6 +32,8 @@
#include <mach/iomux.h>
#include <mach/ocotp.h>
#include <mach/devices.h>
+#include <mach/usb.h>
+#include <usb/fsl_usb2.h>
#include <spi/spi.h>
#include <asm/armlinux.h>
@@ -135,6 +137,11 @@ static const uint32_t mx28evk_pads[] = {
SSP2_D3 | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* SS0 !CS */
SSP2_CMD | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* MOSI DIO */
SSP2_SCK | VE_3_3V | PULLUP(1) | STRENGTH(S8MA), /* CLK */
+
+ /* USB VBUS1 ENABLE - default to ON */
+ AUART2_RX_GPIO | VE_3_3V | PULLUP(0) | GPIO_OUT | GPIO_VALUE(1),
+ /* USB VBUS0 ENABLE - default to OFF */
+ AUART2_TX_GPIO | VE_3_3V | PULLUP(0) | GPIO_OUT | GPIO_VALUE(0),
};
static struct mxs_mci_platform_data mci_pdata = {
@@ -247,6 +254,12 @@ static const struct spi_board_info mx28evk_spi_board_info[] = {
}
};
+#ifdef CONFIG_USB_GADGET_DRIVER_ARC
+static struct fsl_usb2_platform_data usb_pdata = {
+ .operating_mode = FSL_USB2_DR_DEVICE,
+ .phy_mode = FSL_USB2_PHY_UTMI,
+};
+#endif
static int mx28_evk_devices_init(void)
{
int i;
@@ -280,6 +293,14 @@ static int mx28_evk_devices_init(void)
add_generic_device("mxs_spi", 2, NULL, IMX_SSP2_BASE, 0x2000,
IORESOURCE_MEM, NULL);
+#ifdef CONFIG_USB_GADGET_DRIVER_ARC
+ imx28_usb_phy0_enable();
+ imx28_usb_phy1_enable();
+ add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, IMX_USB1_BASE, NULL);
+ add_generic_device("fsl-udc", DEVICE_ID_DYNAMIC, NULL, IMX_USB0_BASE,
+ 0x200, IORESOURCE_MEM, &usb_pdata);
+#endif
+
return 0;
}
device_initcall(mx28_evk_devices_init);
diff --git a/arch/arm/boards/friendlyarm-tiny210/lowlevel.c b/arch/arm/boards/friendlyarm-tiny210/lowlevel.c
index 96760945bc..d980957739 100644
--- a/arch/arm/boards/friendlyarm-tiny210/lowlevel.c
+++ b/arch/arm/boards/friendlyarm-tiny210/lowlevel.c
@@ -84,8 +84,6 @@ static __bare_init bool load_stage2(void *dest, size_t size)
void __bare_init barebox_arm_reset_vector(void)
{
- uint32_t r;
-
arm_cpu_lowlevel_init();
#ifdef CONFIG_S3C_PLL_INIT
diff --git a/arch/arm/boards/karo-tx28/tx28-stk5.c b/arch/arm/boards/karo-tx28/tx28-stk5.c
index 2984d101eb..57cb0c3907 100644
--- a/arch/arm/boards/karo-tx28/tx28-stk5.c
+++ b/arch/arm/boards/karo-tx28/tx28-stk5.c
@@ -23,6 +23,7 @@
#include <io.h>
#include <net.h>
#include <asm/sections.h>
+#include <linux/err.h>
#include <mach/imx-regs.h>
#include <mach/clock.h>
#include <mach/mci.h>
@@ -344,8 +345,11 @@ static int register_persistent_environment(void)
}
/* use the full partition as our persistent environment storage */
- return devfs_add_partition("disk0.1", 0, cdev->size,
+ cdev = devfs_add_partition("disk0.1", 0, cdev->size,
DEVFS_PARTITION_FIXED, "env0");
+ if (IS_ERR(cdev))
+ return PTR_ERR(cdev);
+ return 0;
}
void tx28_get_ethaddr(void)
diff --git a/arch/arm/boards/phytec-pfla02/lowlevel.c b/arch/arm/boards/phytec-pfla02/lowlevel.c
index df92dba9bc..6596e924f8 100644
--- a/arch/arm/boards/phytec-pfla02/lowlevel.c
+++ b/arch/arm/boards/phytec-pfla02/lowlevel.c
@@ -50,7 +50,7 @@ static inline void setup_uart(void)
writel(0x0000c34f, uartbase + 0xa8);
writel(0x00000001, uartbase + 0x80);
- PUTC_LL('>');
+ putc_ll('>');
}
extern char __dtb_imx6q_phytec_pbab01_start[];
diff --git a/arch/arm/boards/versatile/versatilepb.c b/arch/arm/boards/versatile/versatilepb.c
index ebf36954e4..3df59bac10 100644
--- a/arch/arm/boards/versatile/versatilepb.c
+++ b/arch/arm/boards/versatile/versatilepb.c
@@ -28,6 +28,7 @@
#include <environment.h>
#include <partition.h>
#include <sizes.h>
+#include <net/smc91111.h>
static int vpb_console_init(void)
{
@@ -47,6 +48,10 @@ static int vpb_mem_init(void)
}
mem_initcall(vpb_mem_init);
+static struct smc91c111_pdata net_pdata = {
+ .qemu_fixup = 1,
+};
+
static int vpb_devices_init(void)
{
add_cfi_flash_device(DEVICE_ID_DYNAMIC, VERSATILE_FLASH_BASE, VERSATILE_FLASH_SIZE, 0);
@@ -55,7 +60,7 @@ static int vpb_devices_init(void)
devfs_add_partition("nor0", 0x40000, 0x20000, DEVFS_PARTITION_FIXED, "env0");
add_generic_device("smc91c111", DEVICE_ID_DYNAMIC, NULL, VERSATILE_ETH_BASE,
- 64 * 1024, IORESOURCE_MEM, NULL);
+ 64 * 1024, IORESOURCE_MEM, &net_pdata);
armlinux_set_architecture(MACH_TYPE_VERSATILE_PB);
armlinux_set_bootparams((void *)(0x00000100));
diff --git a/arch/arm/boards/vexpress/init.c b/arch/arm/boards/vexpress/init.c
index 48bc11efec..72a3b08224 100644
--- a/arch/arm/boards/vexpress/init.c
+++ b/arch/arm/boards/vexpress/init.c
@@ -118,7 +118,7 @@ console_initcall(vexpress_console_init);
static int vexpress_core_init(void)
{
- char *hostname;
+ char *hostname = "vexpress-unknown";
if (amba_is_arm_sp804(IOMEM(0x10011000))) {
v2m_init = &vexpress_init_a9_legacy;
diff --git a/arch/arm/configs/animeo_ip_defconfig b/arch/arm/configs/animeo_ip_defconfig
index b2d73408ef..e076162b45 100644
--- a/arch/arm/configs/animeo_ip_defconfig
+++ b/arch/arm/configs/animeo_ip_defconfig
@@ -55,6 +55,8 @@ CONFIG_NET_NFS=y
CONFIG_NET_PING=y
CONFIG_MICREL_PHY=y
CONFIG_DRIVER_NET_MACB=y
+CONFIG_NET_USB=y
+CONFIG_NET_USB_ASIX=y
# CONFIG_SPI is not set
CONFIG_MTD=y
# CONFIG_MTD_OOB_DEVICE is not set
@@ -64,6 +66,9 @@ CONFIG_NAND=y
# CONFIG_NAND_ECC_HW_NONE is not set
CONFIG_NAND_ATMEL=y
CONFIG_UBI=y
+CONFIG_USB=y
+CONFIG_USB_OHCI=y
+CONFIG_USB_OHCI_AT91=y
CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_ATMEL=y
diff --git a/arch/arm/configs/imx28evk_defconfig b/arch/arm/configs/imx28evk_defconfig
index 3b69d4d9a4..d06bac8236 100644
--- a/arch/arm/configs/imx28evk_defconfig
+++ b/arch/arm/configs/imx28evk_defconfig
@@ -26,8 +26,6 @@ CONFIG_CMD_ECHO_E=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_MTEST=y
-CONFIG_CMD_MTEST_ALTERNATIVE=y
CONFIG_CMD_SPLASH=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
@@ -36,8 +34,9 @@ CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_PING=y
CONFIG_NET_RESOLV=y
+CONFIG_DRIVER_SERIAL_AUART=y
CONFIG_DRIVER_NET_FEC_IMX=y
-# CONFIG_SPI is not set
+CONFIG_DRIVER_SPI_MXS=y
CONFIG_MTD=y
CONFIG_NAND=y
CONFIG_NAND_MXS=y
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index e3ea3b6b9e..fae83f38b5 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -285,7 +285,7 @@ static int mmu_init(void)
ttb = (unsigned long *)((unsigned long)ttb & ~0x3fff);
if (!request_sdram_region("ttb", (unsigned long)ttb, SZ_16K))
- pr_err("Error: Can't request SDRAM region for ttb\n");
+ pr_err("Error: Can't request SDRAM region for ttb at %p\n", ttb);
} else {
ttb = memalign(0x10000, 0x4000);
}
diff --git a/arch/arm/dts/imx6q.dtsi b/arch/arm/dts/imx6q.dtsi
index 5e6c7f35fe..beb8946fe2 100644
--- a/arch/arm/dts/imx6q.dtsi
+++ b/arch/arm/dts/imx6q.dtsi
@@ -18,6 +18,7 @@
cpu@0 {
compatible = "arm,cortex-a9";
+ device_type = "cpu";
reg = <0>;
next-level-cache = <&L2>;
operating-points = <
@@ -39,18 +40,21 @@
cpu@1 {
compatible = "arm,cortex-a9";
+ device_type = "cpu";
reg = <1>;
next-level-cache = <&L2>;
};
cpu@2 {
compatible = "arm,cortex-a9";
+ device_type = "cpu";
reg = <2>;
next-level-cache = <&L2>;
};
cpu@3 {
compatible = "arm,cortex-a9";
+ device_type = "cpu";
reg = <3>;
next-level-cache = <&L2>;
};
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 3ea695c2f3..a32879537c 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_ARM_LINUX) += armlinux.o
-obj-$(CONFIG_CMD_BOOTM) += bootm.o
+obj-$(CONFIG_BOOTM) += bootm.o
obj-$(CONFIG_CMD_BOOTZ) += bootz.o
obj-$(CONFIG_CMD_BOOTU) += bootu.o
obj-y += div0.o
diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c
index 40a63ea7e1..75d751bb4d 100644
--- a/arch/arm/lib/armlinux.c
+++ b/arch/arm/lib/armlinux.c
@@ -42,11 +42,9 @@
static struct tag *params;
static void *armlinux_bootparams = NULL;
-#ifndef CONFIG_ENVIRONMENT_VARIABLES
static int armlinux_architecture;
static u32 armlinux_system_rev;
static u64 armlinux_system_serial;
-#endif
BAREBOX_MAGICVAR(armlinux_architecture, "ARM machine ID");
BAREBOX_MAGICVAR(armlinux_system_rev, "ARM system revision");
@@ -54,56 +52,41 @@ BAREBOX_MAGICVAR(armlinux_system_serial, "ARM system serial");
void armlinux_set_architecture(int architecture)
{
-#ifdef CONFIG_ENVIRONMENT_VARIABLES
export_env_ull("armlinux_architecture", architecture);
-#else
armlinux_architecture = architecture;
-#endif
}
int armlinux_get_architecture(void)
{
-#ifdef CONFIG_ENVIRONMENT_VARIABLES
- return getenv_ull("armlinux_architecture");
-#else
+ getenv_uint("armlinux_architecture", &armlinux_architecture);
+
return armlinux_architecture;
-#endif
}
void armlinux_set_revision(unsigned int rev)
{
-#ifdef CONFIG_ENVIRONMENT_VARIABLES
export_env_ull("armlinux_system_rev", rev);
-#else
armlinux_system_rev = rev;
-#endif
}
unsigned int armlinux_get_revision(void)
{
-#ifdef CONFIG_ENVIRONMENT_VARIABLES
- return getenv_ull("armlinux_system_rev");
-#else
+ getenv_uint("armlinux_system_rev", &armlinux_system_rev);
+
return armlinux_system_rev;
-#endif
}
void armlinux_set_serial(u64 serial)
{
-#ifdef CONFIG_ENVIRONMENT_VARIABLES
export_env_ull("armlinux_system_serial", serial);
-#else
armlinux_system_serial = serial;
-#endif
}
u64 armlinux_get_serial(void)
{
-#ifdef CONFIG_ENVIRONMENT_VARIABLES
- return getenv_ull("armlinux_system_serial");
-#else
+ getenv_ull("armlinux_system_serial", &armlinux_system_serial);
+
return armlinux_system_serial;
-#endif
}
#ifdef CONFIG_ARM_BOARD_APPEND_ATAG
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index d695020b74..aa0fdae141 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -150,6 +150,7 @@ struct atmel_mci_platform_data {
unsigned bus_width;
int detect_pin;
int wp_pin;
+ char *devname;
};
void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data);
diff --git a/arch/arm/mach-mxs/include/mach/imx28-regs.h b/arch/arm/mach-mxs/include/mach/imx28-regs.h
index fa8edd7d4b..088282963d 100644
--- a/arch/arm/mach-mxs/include/mach/imx28-regs.h
+++ b/arch/arm/mach-mxs/include/mach/imx28-regs.h
@@ -41,7 +41,8 @@
#define IMX_DBGUART_BASE 0x80074000
#define IMX_USBPHY0_BASE 0x8007c000
#define IMX_USBPHY1_BASE 0x8007e000
-#define IMX_USB_BASE 0x80080000
+#define IMX_USB0_BASE 0x80080000
+#define IMX_USB1_BASE 0x80090000
#define IMX_FEC0_BASE 0x800F0000
#define IMX_FEC1_BASE 0x800F4000
diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c
index 3690ce1438..3e2b6c4e15 100644
--- a/arch/arm/mach-omap/am33xx_generic.c
+++ b/arch/arm/mach-omap/am33xx_generic.c
@@ -43,30 +43,21 @@ void __noreturn reset_cpu(unsigned long addr)
* The significance of the CPU revision depends upon the cpu type.
* Latest known revision is considered default.
*
+ * This function is called before barebox_arm_entry(), so avoid switch
+ * statements.
+ *
* @return silicon version
*/
u32 am33xx_get_cpu_rev(void)
{
- u32 version, retval;
-
- version = (readl(AM33XX_IDCODE_REG) >> 28) & 0xF;
-
- switch (version) {
- case 0:
- retval = AM335X_ES1_0;
- break;
- case 1:
- retval = AM335X_ES2_0;
- break;
- case 2:
- /*
- * Fall through the default case.
- */
- default:
- retval = AM335X_ES2_1;
- }
-
- return retval;
+ u32 version = (readl(AM33XX_IDCODE_REG) >> 28) & 0xF;
+
+ if (version == 0)
+ return AM335X_ES1_0;
+ else if (version == 1)
+ return AM335X_ES2_0;
+ else
+ return AM335X_ES2_1;
}
/**
@@ -311,7 +302,7 @@ void am33xx_config_sdram(const struct am33xx_emif_regs *regs)
writel(regs->sdram_ref_ctrl, AM33XX_EMIF4_0_REG(SDRAM_REF_CTRL));
writel(regs->sdram_ref_ctrl, AM33XX_EMIF4_0_REG(SDRAM_REF_CTRL_SHADOW));
- writel(regs->sdram_config, CM_EMIF_SDRAM_CONFIG);
+ writel(regs->sdram_config, AM33XX_EMIF4_0_REG(SDRAM_CONFIG));
}
void am33xx_config_io_ctrl(int ioctrl)
diff --git a/arch/arm/mach-omap/include/mach/generic.h b/arch/arm/mach-omap/include/mach/generic.h
index ece8c2baea..b05fdeee91 100644
--- a/arch/arm/mach-omap/include/mach/generic.h
+++ b/arch/arm/mach-omap/include/mach/generic.h
@@ -2,12 +2,13 @@
#define _MACH_GENERIC_H
/* I2C controller revisions */
-#define OMAP_I2C_REV_2 0x20
+#define OMAP_I2C_OMAP1_REV_2 0x20
/* I2C controller revisions present on specific hardware */
-#define OMAP_I2C_REV_ON_2430 0x36
-#define OMAP_I2C_REV_ON_3430 0x3C
-#define OMAP_I2C_REV_ON_4430 0x40
+#define OMAP_I2C_REV_ON_2430 0x00000036
+#define OMAP_I2C_REV_ON_3430_3530 0x0000003C
+#define OMAP_I2C_REV_ON_3630 0x00000040
+#define OMAP_I2C_REV_ON_4430_PLUS 0x50400002
#ifdef CONFIG_ARCH_OMAP
#define cpu_is_omap2430() (1)
@@ -56,6 +57,7 @@ static inline int omap_set_mmc_dev(const char *mmcdev)
extern uint32_t omap_bootinfo[3];
void omap_save_bootinfo(void *data);
+void __noreturn omap_start_barebox(void *barebox);
void omap_set_bootmmc_devname(const char *devname);
const char *omap_get_bootmmc_devname(void);
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index e7ca821212..79e37e2341 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -15,15 +15,70 @@
#include <common.h>
#include <bootsource.h>
#include <envfs.h>
+#include <boot.h>
#include <init.h>
#include <io.h>
#include <fs.h>
#include <malloc.h>
#include <linux/stat.h>
+#include <mach/generic.h>
+#include <mach/am33xx-silicon.h>
+#include <mach/omap3-silicon.h>
+#include <mach/omap4-silicon.h>
-static char *omap_bootmmc_dev;
+static void *omap_sram_start(void)
+{
+ if (cpu_is_am33xx())
+ return (void *)AM33XX_SRAM0_START;
+ if (cpu_is_omap34xx())
+ return (void *)OMAP3_SRAM_BASE;
+ if (cpu_is_omap4xxx())
+ return (void *)OMAP44XX_SRAM_BASE;
+}
+
+void __noreturn omap_start_barebox(void *barebox)
+{
+ int (*func)(void *) = barebox;
+ uint32_t *arg;
+ void *sramadr = omap_sram_start();
+
+ arg = (uint32_t *)&omap_bootinfo;
+
+ memcpy(sramadr, &omap_bootinfo, sizeof(uint32_t) * 3);
+
+ shutdown_barebox();
+ func(sramadr);
+ hang();
+}
+
+#ifdef CONFIG_BOOTM
+static int do_bootm_omap_barebox(struct image_data *data)
+{
+ void (*barebox)(uint32_t);
-void omap_set_bootmmc_devname(char *devname)
+ barebox = read_file(data->os_file, NULL);
+ if (!barebox)
+ return -EINVAL;
+
+ omap_start_barebox(barebox);
+}
+
+static struct image_handler omap_barebox_handler = {
+ .name = "OMAP barebox",
+ .bootm = do_bootm_omap_barebox,
+ .filetype = filetype_arm_barebox,
+};
+
+static int omap_bootm_barebox(void)
+{
+ return register_image_handler(&omap_barebox_handler);
+}
+device_initcall(omap_bootm_barebox);
+#endif
+
+const static char *omap_bootmmc_dev;
+
+void omap_set_bootmmc_devname(const char *devname)
{
omap_bootmmc_dev = devname;
}
@@ -37,7 +92,8 @@ const char *omap_get_bootmmc_devname(void)
static int omap_env_init(void)
{
struct stat s;
- char *diskdev, *partname;
+ char *partname;
+ const char *diskdev;
int ret;
if (bootsource_get() != BOOTSOURCE_MMC)
@@ -68,10 +124,7 @@ static int omap_env_init(void)
return 0;
}
- if (IS_ENABLED(CONFIG_OMAP_BUILD_IFT))
- default_environment_path = "/dev/defaultenv";
- else
- default_environment_path = "/boot/barebox.env";
+ default_environment_path = "/boot/barebox.env";
return 0;
}
diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c
index b4d1b55e57..69e3e42df6 100644
--- a/arch/arm/mach-omap/xload.c
+++ b/arch/arm/mach-omap/xload.c
@@ -188,8 +188,7 @@ static void *omap4_xload_boot_usb(void){
*/
static __noreturn int omap_xload(void)
{
- int (*func)(void *) = NULL;
- uint32_t *arg;
+ void *func;
if (!barebox_part)
barebox_part = &default_part;
@@ -230,12 +229,7 @@ static __noreturn int omap_xload(void)
while (1);
}
- arg = (uint32_t *)&omap_bootinfo;
-
- shutdown_barebox();
- func(arg);
-
- while (1);
+ omap_start_barebox(func);
}
int omap_set_barebox_part(struct omap_barebox_part *part)
diff --git a/arch/arm/pbl/Makefile b/arch/arm/pbl/Makefile
index dd3e94680b..bfa73b91a7 100644
--- a/arch/arm/pbl/Makefile
+++ b/arch/arm/pbl/Makefile
@@ -13,9 +13,17 @@ targets := zbarebox.lds zbarebox zbarebox.bin zbarebox.S \
# Make sure files are removed during clean
extra-y += piggy.gzip piggy.lz4 piggy.lzo piggy.lzma piggy.xzkern piggy.shipped zbarebox.map
+ifeq ($(CONFIG_CPU_BIG_ENDIAN),y)
+FIX_SIZE=-b
+else
+FIX_SIZE=
+endif
+
$(obj)/zbarebox.bin: $(obj)/zbarebox FORCE
$(call if_changed,objcopy)
$(call cmd,check_file_size,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
+ $(Q)$(kecho) ' Barebox: fix size'
+ $(Q)$(objtree)/scripts/fix_size -f $(objtree)/$@ -o 0x2c $(FIX_SIZE)
$(Q)$(kecho) ' Barebox: $@ is ready'
$(obj)/zbarebox.S: $(obj)/zbarebox FORCE
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index 325513f31a..01bc7aa20a 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Mon May 14 09:28:07 2012
+# Last update: Wed Sep 25 08:48:26 2013
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -3006,6 +3006,7 @@ armada_xp_db MACH_ARMADA_XP_DB ARMADA_XP_DB 3036
spdm MACH_SPDM SPDM 3037
gtib MACH_GTIB GTIB 3038
dgm3240 MACH_DGM3240 DGM3240 3039
+iv_atlas_i_lpe MACH_ATLAS_I_LPE ATLAS_I_LPE 3040
htcmega MACH_HTCMEGA HTCMEGA 3041
tricorder MACH_TRICORDER TRICORDER 3042
tx28 MACH_TX28 TX28 3043
@@ -3279,7 +3280,7 @@ shenzhou MACH_SHENZHOU SHENZHOU 3319
cwme9210 MACH_CWME9210 CWME9210 3320
cwme9210js MACH_CWME9210JS CWME9210JS 3321
pgs_v1 MACH_PGS_SITARA PGS_SITARA 3322
-colibri_tegra2 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323
+colibri_t20 MACH_COLIBRI_TEGRA2 COLIBRI_TEGRA2 3323
w21 MACH_W21 W21 3324
polysat1 MACH_POLYSAT1 POLYSAT1 3325
dataway MACH_DATAWAY DATAWAY 3326
@@ -3811,7 +3812,7 @@ farleys MACH_FARLEYS FARLEYS 3856
efm32gg_dk3750 MACH_EFM32GG_DK3750 EFM32GG_DK3750 3857
zeus_board MACH_ZEUS_BOARD ZEUS_BOARD 3858
cc51 MACH_CC51 CC51 3859
-fxi_c210 MACH_FXI_C210 FXI_C210 3860
+cottoncandy MACH_FXI_C210 FXI_C210 3860
msm8627_cdp MACH_MSM8627_CDP MSM8627_CDP 3861
msm8627_mtp MACH_MSM8627_MTP MSM8627_MTP 3862
armadillo800eva MACH_ARMADILLO800EVA ARMADILLO800EVA 3863
@@ -4071,7 +4072,7 @@ tam335x MACH_TAM335X TAM335X 4116
grouper MACH_GROUPER GROUPER 4117
mpcsa21_9g20 MACH_MPCSA21_9G20 MPCSA21_9G20 4118
m6u_cpu MACH_M6U_CPU M6U_CPU 4119
-davinci_dp10 MACH_DAVINCI_DP10 DAVINCI_DP10 4120
+davinci_dp7 MACH_DAVINCI_DP10 DAVINCI_DP10 4120
ginkgo MACH_GINKGO GINKGO 4121
cgt_qmx6 MACH_CGT_QMX6 CGT_QMX6 4122
profpga MACH_PROFPGA PROFPGA 4123
@@ -4121,7 +4122,7 @@ msm8625_ffa MACH_MSM8625_FFA MSM8625_FFA 4166
vpu101 MACH_VPU101 VPU101 4167
operaul MACH_OPERA_UL OPERA_UL 4168
baileys MACH_BAILEYS BAILEYS 4169
-familybox MACH_FAMILYBOX FAMILYBOX 4170
+cloudbox MACH_FAMILYBOX FAMILYBOX 4170
ensemble_mx35 MACH_ENSEMBLE_MX35 ENSEMBLE_MX35 4171
sc_sps_1 MACH_SC_SPS_1 SC_SPS_1 4172
ucsimply_sam9260 MACH_UCSIMPLY_SAM9260 UCSIMPLY_SAM9260 4173
@@ -4148,3 +4149,577 @@ msm8625_evt MACH_MSM8625_EVT MSM8625_EVT 4193
mx53_sellwood MACH_MX53_SELLWOOD MX53_SELLWOOD 4194
somiq_am35 MACH_SOMIQ_AM35 SOMIQ_AM35 4195
somiq_am37 MACH_SOMIQ_AM37 SOMIQ_AM37 4196
+k2_plc_cl MACH_K2_PLC_CL K2_PLC_CL 4197
+tc2 MACH_TC2 TC2 4198
+dulex_j MACH_DULEX_J DULEX_J 4199
+stm_b2044 MACH_STM_B2044 STM_B2044 4200
+deluxe_j MACH_DELUXE_J DELUXE_J 4201
+mango2443 MACH_MANGO2443 MANGO2443 4202
+cp2dcg MACH_CP2DCG CP2DCG 4203
+cp2dtg MACH_CP2DTG CP2DTG 4204
+cp2dug MACH_CP2DUG CP2DUG 4205
+var_som_am33 MACH_VAR_SOM_AM33 VAR_SOM_AM33 4206
+pepper MACH_PEPPER PEPPER 4207
+mango2450 MACH_MANGO2450 MANGO2450 4208
+valente_wx_c9 MACH_VALENTE_WX_C9 VALENTE_WX_C9 4209
+minitv MACH_MINITV MINITV 4210
+u8540 MACH_U8540 U8540 4211
+iv_atlas_i_z7e MACH_IV_ATLAS_I_Z7E IV_ATLAS_I_Z7E 4212
+mx53_csb1733 MACH_COGENT_CSB1733 COGENT_CSB1733 4213
+mach_type_sky MACH_MACH_TYPE_SKY MACH_TYPE_SKY 4214
+bluesky MACH_BLUESKY BLUESKY 4215
+ngrouter MACH_NGROUTER NGROUTER 4216
+mx53_denetim MACH_MX53_DENETIM MX53_DENETIM 4217
+opal MACH_OPAL OPAL 4218
+gnet_us3gref MACH_GNET_US3GREF GNET_US3GREF 4219
+gnet_nc3g MACH_GNET_NC3G GNET_NC3G 4220
+gnet_ge3g MACH_GNET_GE3G GNET_GE3G 4221
+adp2 MACH_ADP2 ADP2 4222
+tqma28 MACH_TQMA28 TQMA28 4223
+kacom3 MACH_KACOM3 KACOM3 4224
+rrhdemo MACH_RRHDEMO RRHDEMO 4225
+protodug MACH_PROTODUG PROTODUG 4226
+lago MACH_LAGO LAGO 4227
+ktt30 MACH_KTT30 KTT30 4228
+ts43xx MACH_TS43XX TS43XX 4229
+mx6q_denso MACH_MX6Q_DENSO MX6Q_DENSO 4230
+comsat_gsmumts8 MACH_COMSAT_GSMUMTS8 COMSAT_GSMUMTS8 4231
+dreamx MACH_DREAMX DREAMX 4232
+thunderstonem MACH_THUNDERSTONEM THUNDERSTONEM 4233
+yoyopad MACH_YOYOPAD YOYOPAD 4234
+yoyopatient MACH_YOYOPATIENT YOYOPATIENT 4235
+a10l MACH_A10L A10L 4236
+mq60 MACH_MQ60 MQ60 4237
+linkstation_lsql MACH_LINKSTATION_LSQL LINKSTATION_LSQL 4238
+am3703gateway MACH_AM3703GATEWAY AM3703GATEWAY 4239
+accipiter MACH_ACCIPITER ACCIPITER 4240
+e1853 MACH_P1853 P1853 4241
+magnidug MACH_MAGNIDUG MAGNIDUG 4242
+hydra MACH_HYDRA HYDRA 4243
+sun3i MACH_SUN3I SUN3I 4244
+stm_b2078 MACH_STM_B2078 STM_B2078 4245
+at91sam9263deskv2 MACH_AT91SAM9263DESKV2 AT91SAM9263DESKV2 4246
+deluxe_r MACH_DELUXE_R DELUXE_R 4247
+p_98_v MACH_P_98_V P_98_V 4248
+p_98_c MACH_P_98_C P_98_C 4249
+davinci_am18xx_omn MACH_DAVINCI_AM18XX_OMN DAVINCI_AM18XX_OMN 4250
+socfpga_cyclone5 MACH_SOCFPGA_CYCLONE5 SOCFPGA_CYCLONE5 4251
+cabatuin MACH_CABATUIN CABATUIN 4252
+yoyopad_ft MACH_YOYOPAD_FT YOYOPAD_FT 4253
+dan2400evb MACH_DAN2400EVB DAN2400EVB 4254
+dan3400evb MACH_DAN3400EVB DAN3400EVB 4255
+edm_sf_imx6 MACH_EDM_SF_IMX6 EDM_SF_IMX6 4256
+edm_cf_imx6 MACH_EDM_CF_IMX6 EDM_CF_IMX6 4257
+vpos3xx MACH_VPOS3XX VPOS3XX 4258
+vulcano_9x5 MACH_VULCANO_9X5 VULCANO_9X5 4259
+spmp8000 MACH_SPMP8000 SPMP8000 4260
+catalina MACH_CATALINA CATALINA 4261
+rd88f5181l_fe MACH_RD88F5181L_FE RD88F5181L_FE 4262
+mx535_mx MACH_MX535_MX MX535_MX 4263
+armadillo840 MACH_ARMADILLO840 ARMADILLO840 4264
+spc9000baseboard MACH_SPC9000BASEBOARD SPC9000BASEBOARD 4265
+iris MACH_IRIS IRIS 4266
+protodcg MACH_PROTODCG PROTODCG 4267
+palmtree MACH_PALMTREE PALMTREE 4268
+novena MACH_NOVENA NOVENA 4269
+ma_um MACH_MA_UM MA_UM 4270
+ma_am MACH_MA_AM MA_AM 4271
+ems348 MACH_EMS348 EMS348 4272
+cm_fx6 MACH_CM_FX6 CM_FX6 4273
+arndale MACH_ARNDALE ARNDALE 4274
+q5xr5 MACH_Q5XR5 Q5XR5 4275
+willow MACH_WILLOW WILLOW 4276
+omap3621_odyv3 MACH_OMAP3621_ODYV3 OMAP3621_ODYV3 4277
+omapl138_presonus MACH_OMAPL138_PRESONUS OMAPL138_PRESONUS 4278
+dvf99 MACH_DVF99 DVF99 4279
+impression_j MACH_IMPRESSION_J IMPRESSION_J 4280
+qblissa9 MACH_QBLISSA9 QBLISSA9 4281
+robin_heliview10 MACH_ROBIN_HELIVIEW10 ROBIN_HELIVIEW10 4282
+sun7i MACH_SUN7I SUN7I 4283
+mx6q_hdmidongle MACH_MX6Q_HDMIDONGLE MX6Q_HDMIDONGLE 4284
+mx6_sid2 MACH_MX6_SID2 MX6_SID2 4285
+helios_v3 MACH_HELIOS_V3 HELIOS_V3 4286
+helios_v4 MACH_HELIOS_V4 HELIOS_V4 4287
+q7_imx6 MACH_Q7_IMX6 Q7_IMX6 4288
+odroidx MACH_ODROIDX ODROIDX 4289
+robpro MACH_ROBPRO ROBPRO 4290
+research59if_mk1 MACH_RESEARCH59IF_MK1 RESEARCH59IF_MK1 4291
+bobsleigh MACH_BOBSLEIGH BOBSLEIGH 4292
+dcshgwt3 MACH_DCSHGWT3 DCSHGWT3 4293
+gld1018 MACH_GLD1018 GLD1018 4294
+ev10 MACH_EV10 EV10 4295
+nitrogen6x MACH_NITROGEN6X NITROGEN6X 4296
+p_107_bb MACH_P_107_BB P_107_BB 4297
+evita_utl MACH_EVITA_UTL EVITA_UTL 4298
+falconwing MACH_FALCONWING FALCONWING 4299
+dct3 MACH_DCT3 DCT3 4300
+cpx2e_cell MACH_CPX2E_CELL CPX2E_CELL 4301
+amiro MACH_AMIRO AMIRO 4302
+mx6q_brassboard MACH_MX6Q_BRASSBOARD MX6Q_BRASSBOARD 4303
+dalmore MACH_DALMORE DALMORE 4304
+omap3_portal7cp MACH_OMAP3_PORTAL7CP OMAP3_PORTAL7CP 4305
+tegra_pluto MACH_TEGRA_PLUTO TEGRA_PLUTO 4306
+mx6sl_evk MACH_MX6SL_EVK MX6SL_EVK 4307
+m7 MACH_M7 M7 4308
+pxm2 MACH_PXM2 PXM2 4309
+haba_knx_lite MACH_HABA_KNX_LITE HABA_KNX_LITE 4310
+tai MACH_TAI TAI 4311
+prototd MACH_PROTOTD PROTOTD 4312
+dst_tonto MACH_DST_TONTO DST_TONTO 4313
+draco MACH_DRACO DRACO 4314
+dxr2 MACH_DXR2 DXR2 4315
+rut MACH_RUT RUT 4316
+am180x_wsc MACH_AM180X_WSC AM180X_WSC 4317
+deluxe_u MACH_DELUXE_U DELUXE_U 4318
+deluxe_ul MACH_DELUXE_UL DELUXE_UL 4319
+at91sam9260medths MACH_AT91SAM9260MEDTHS AT91SAM9260MEDTHS 4320
+matrix516 MACH_MATRIX516 MATRIX516 4321
+vid401x MACH_VID401X VID401X 4322
+helios_v5 MACH_HELIOS_V5 HELIOS_V5 4323
+playpaq2 MACH_PLAYPAQ2 PLAYPAQ2 4324
+igam MACH_IGAM IGAM 4325
+amico_i MACH_AMICO_I AMICO_I 4326
+amico_e MACH_AMICO_E AMICO_E 4327
+sentient_mm3_ck MACH_SENTIENT_MM3_CK SENTIENT_MM3_CK 4328
+smx6 MACH_SMX6 SMX6 4329
+pango MACH_PANGO PANGO 4330
+ns115_stick MACH_NS115_STICK NS115_STICK 4331
+bctrm3 MACH_BCTRM3 BCTRM3 4332
+doctorws MACH_DOCTORWS DOCTORWS 4333
+m2601 MACH_M2601 M2601 4334
+gco_mgmtt MACH_GRIDCO_TRINITY GRIDCO_TRINITY 4335
+pc73032 MACH_PC3032 PC3032 4336
+vgg1111 MACH_VGG1111 VGG1111 4337
+countach MACH_COUNTACH COUNTACH 4338
+visstrim_sm20 MACH_VISSTRIM_SM20 VISSTRIM_SM20 4339
+a639 MACH_A639 A639 4340
+spacemonkey MACH_SPACEMONKEY SPACEMONKEY 4341
+zpdu_stamp MACH_ZPDU_STAMP ZPDU_STAMP 4342
+htc_g7_clone MACH_HTC_G7_CLONE HTC_G7_CLONE 4343
+ft2080_corvus MACH_FT2080_CORVUS FT2080_CORVUS 4344
+fisland MACH_FISLAND FISLAND 4345
+zpdu MACH_ZPDU ZPDU 4346
+urt MACH_URT URT 4347
+conti_ovip MACH_CONTI_OVIP CONTI_OVIP 4348
+omapl138_nagra MACH_OMAPL138_NAGRA OMAPL138_NAGRA 4349
+da850_at3kp1 MACH_DA850_AT3KP1 DA850_AT3KP1 4350
+da850_at3kp2 MACH_DA850_AT3KP2 DA850_AT3KP2 4351
+surma MACH_SURMA SURMA 4352
+stm_b2092 MACH_STM_B2092 STM_B2092 4353
+mx535_ycr MACH_MX535_YCR MX535_YCR 4354
+m7_wl MACH_M7_WL M7_WL 4355
+m7_u MACH_M7_U M7_U 4356
+omap3_stndt_evm MACH_OMAP3_STNDT_EVM OMAP3_STNDT_EVM 4357
+m7_wlv MACH_M7_WLV M7_WLV 4358
+xam3517 MACH_XAM3517 XAM3517 4359
+a220 MACH_A220 A220 4360
+aclima_odie MACH_ACLIMA_ODIE ACLIMA_ODIE 4361
+vibble MACH_VIBBLE VIBBLE 4362
+k2_u MACH_K2_U K2_U 4363
+mx53_egf MACH_MX53_EGF MX53_EGF 4364
+novpek_imx53 MACH_NOVPEK_IMX53 NOVPEK_IMX53 4365
+novpek_imx6x MACH_NOVPEK_IMX6X NOVPEK_IMX6X 4366
+mx25_smartbox MACH_MX25_SMARTBOX MX25_SMARTBOX 4367
+eicg6410 MACH_EICG6410 EICG6410 4368
+picasso_e3 MACH_PICASSO_E3 PICASSO_E3 4369
+motonavigator MACH_MOTONAVIGATOR MOTONAVIGATOR 4370
+varioconnect2 MACH_VARIOCONNECT2 VARIOCONNECT2 4371
+deluxe_tw MACH_DELUXE_TW DELUXE_TW 4372
+kore3 MACH_KORE3 KORE3 4374
+mx6s_drs MACH_MX6S_DRS MX6S_DRS 4375
+cmimx6 MACH_CMIMX6 CMIMX6 4376
+roth MACH_ROTH ROTH 4377
+eq4ux MACH_EQ4UX EQ4UX 4378
+x1plus MACH_X1PLUS X1PLUS 4379
+modimx27 MACH_MODIMX27 MODIMX27 4380
+videon_hduac MACH_VIDEON_HDUAC VIDEON_HDUAC 4381
+blackbird MACH_BLACKBIRD BLACKBIRD 4382
+runmaster MACH_RUNMASTER RUNMASTER 4383
+ceres MACH_CERES CERES 4384
+nad435 MACH_NAD435 NAD435 4385
+ns115_proto_type MACH_NS115_PROTO_TYPE NS115_PROTO_TYPE 4386
+fs20_vcc MACH_FS20_VCC FS20_VCC 4387
+meson6tv_ref MACH_MESON6TV MESON6TV 4388
+meson6tv_skt MACH_MESON6TV_SKT MESON6TV_SKT 4389
+keystone MACH_KEYSTONE KEYSTONE 4390
+pcm052 MACH_PCM052 PCM052 4391
+rainbowg15_q7 MACH_TYPE TYPE 4392
+qrd_skud_prime MACH_QRD_SKUD_PRIME QRD_SKUD_PRIME 4393
+mx6_rainbow MACH_RAINBOWG15 RAINBOWG15 4394
+guf_santaro MACH_GUF_SANTARO GUF_SANTARO 4395
+sheepshead MACH_SHEEPSHEAD SHEEPSHEAD 4396
+mx6_iwg15m_mxm MACH_MX6_IWG15M_MXM MX6_IWG15M_MXM 4397
+mx6_iwg15m_q7 MACH_MX6_IWG15M_Q7 MX6_IWG15M_Q7 4398
+at91sam9263if8mic MACH_AT91SAM9263IF8MIC AT91SAM9263IF8MIC 4399
+ex MACH_EXCEL EXCEL 4400
+marcopolo MACH_MARCOPOLO MARCOPOLO 4401
+mx535_sdcr MACH_MX535_SDCR MX535_SDCR 4402
+mx53_csb2733 MACH_MX53_CSB2733 MX53_CSB2733 4403
+diva MACH_DIVA DIVA 4404
+ncr_7744 MACH_NCR_7744 NCR_7744 4405
+macallan MACH_MACALLAN MACALLAN 4406
+wnr3500 MACH_WNR3500 WNR3500 4407
+pgavrf MACH_PGAVRF PGAVRF 4408
+helios_v6 MACH_HELIOS_V6 HELIOS_V6 4409
+lcct MACH_LCCT LCCT 4410
+csndug MACH_CSNDUG CSNDUG 4411
+wandboard_imx6 MACH_WANDBOARD_IMX6 WANDBOARD_IMX6 4412
+omap4_jet MACH_OMAP4_JET OMAP4_JET 4413
+tegra_roth MACH_TEGRA_ROTH TEGRA_ROTH 4414
+m7dcg MACH_M7DCG M7DCG 4415
+m7dug MACH_M7DUG M7DUG 4416
+m7dtg MACH_M7DTG M7DTG 4417
+ap42x MACH_AP42X AP42X 4418
+var_som_mx6 MACH_VAR_SOM_MX6 VAR_SOM_MX6 4419
+pdlu MACH_PDLU PDLU 4420
+hydrogen MACH_HYDROGEN HYDROGEN 4421
+npa211e MACH_NPA211E NPA211E 4422
+arcadia MACH_ARCADIA ARCADIA 4423
+arcadia_l MACH_ARCADIA_L ARCADIA_L 4424
+msm8930dt MACH_MSM8930DT MSM8930DT 4425
+ktam3874 MACH_KTAM3874 KTAM3874 4426
+cec4 MACH_CEC4 CEC4 4427
+ape6evm MACH_APE6EVM APE6EVM 4428
+tx6 MACH_TX6 TX6 4429
+owen_som MACH_OWENSOM OWENSOM 4430
+cfa10037 MACH_CFA10037 CFA10037 4431
+nbrd_voip MACH_NATEKS_VOIP NATEKS_VOIP 4432
+ezp1000 MACH_EZP1000 EZP1000 4433
+wgr826v MACH_WGR826V WGR826V 4434
+exuma MACH_EXUMA EXUMA 4435
+fregate MACH_FREGATE FREGATE 4436
+osirisimx508 MACH_OSIRISIMX508 OSIRISIMX508 4437
+st_exigo MACH_ST_EXIGO ST_EXIGO 4438
+pismo MACH_PISMO PISMO 4439
+atc7 MACH_ATC7 ATC7 4440
+nspireclp MACH_NSPIRECLP NSPIRECLP 4441
+nspiretp MACH_NSPIRETP NSPIRETP 4442
+nspirecx MACH_NSPIRECX NSPIRECX 4443
+maya MACH_MAYA MAYA 4444
+wecct MACH_WECCT WECCT 4445
+m2s MACH_M2S M2S 4446
+msm8625q_evbd MACH_MSM8625Q_EVBD MSM8625Q_EVBD 4447
+tiny210 MACH_TINY210 TINY210 4448
+g3 MACH_G3 G3 4449
+hurricane MACH_HURRICANE HURRICANE 4450
+mx6_pod MACH_MX6_POD MX6_POD 4451
+elondcn MACH_ELONDCN ELONDCN 4452
+cwmx535 MACH_CWMX535 CWMX535 4453
+m7_wlj MACH_M7_WLJ M7_WLJ 4454
+qsp_arm MACH_QSP_ARM QSP_ARM 4455
+msm8625q_skud MACH_MSM8625Q_SKUD MSM8625Q_SKUD 4456
+htcmondrian MACH_HTCMONDRIAN HTCMONDRIAN 4457
+watson_ead MACH_WATSON_EAD WATSON_EAD 4458
+mitwoa MACH_MITWOA MITWOA 4459
+omap3_wolverine MACH_OMAP3_WOLVERINE OMAP3_WOLVERINE 4460
+mapletree MACH_MAPLETREE MAPLETREE 4461
+msm8625_fih_sae MACH_MSM8625_FIH_SAE MSM8625_FIH_SAE 4462
+epc35 MACH_EPC35 EPC35 4463
+smartrtu MACH_SMARTRTU SMARTRTU 4464
+rcm101 MACH_RCM101 RCM101 4465
+amx_imx53_mxx MACH_AMX_IMX53_MXX AMX_IMX53_MXX 4466
+crius MACH_CP3DCG CP3DCG 4467
+themis MACH_CP3DTG CP3DTG 4468
+uranus MACH_CP3DUG CP3DUG 4469
+acer_a12 MACH_ACER_A12 ACER_A12 4470
+sbc6x MACH_SBC6X SBC6X 4471
+u2 MACH_U2 U2 4472
+smdk4270 MACH_SMDK4270 SMDK4270 4473
+priscillag MACH_PRISCILLAG PRISCILLAG 4474
+priscillac MACH_PRISCILLAC PRISCILLAC 4475
+priscilla MACH_PRISCILLA PRISCILLA 4476
+innova_shpu_v2 MACH_INNOVA_SHPU_V2 INNOVA_SHPU_V2 4477
+auriga MACH_M7CDTU M7CDTU 4478
+mach_type_dep2410 MACH_MACH_TYPE_DEP2410 MACH_TYPE_DEP2410 4479
+bctre3 MACH_BCTRE3 BCTRE3 4480
+omap_m100 MACH_OMAP_M100 OMAP_M100 4481
+flo MACH_FLO FLO 4482
+nanobone MACH_NANOBONE NANOBONE 4483
+stm_b2105 MACH_STM_B2105 STM_B2105 4484
+omap4_bsc_bap_v3 MACH_OMAP4_BSC_BAP_V3 OMAP4_BSC_BAP_V3 4485
+ss1pam MACH_SS1PAM SS1PAM 4486
+caelum MACH_DLXP_WL DLXP_WL 4487
+primominiu MACH_PRIMOMINIU PRIMOMINIU 4488
+mrt_35hd_dualnas_e MACH_MRT_35HD_DUALNAS_E MRT_35HD_DUALNAS_E 4489
+kiwi MACH_KIWI KIWI 4490
+hw90496 MACH_HW90496 HW90496 4491
+mep2440 MACH_MEP2440 MEP2440 4492
+colibri_t30 MACH_COLIBRI_T30 COLIBRI_T30 4493
+cwv1 MACH_CWV1 CWV1 4494
+nsa325 MACH_NSA325 NSA325 4495
+camelopardalis MACH_DLXP_UL DLXP_UL 4496
+dpxmtc MACH_DPXMTC DPXMTC 4497
+tt_stuttgart MACH_TT_STUTTGART TT_STUTTGART 4498
+miranda_apcii MACH_MIRANDA_APCII MIRANDA_APCII 4499
+mx6q_moderox MACH_MX6Q_MODEROX MX6Q_MODEROX 4500
+mudskipper MACH_MUDSKIPPER MUDSKIPPER 4501
+urania MACH_URANIA URANIA 4502
+stm_b2112 MACH_STM_B2112 STM_B2112 4503
+ara MACH_GTOU GTOU 4504
+mx6q_ats_phoenix MACH_MX6Q_ATS_PHOENIX MX6Q_ATS_PHOENIX 4505
+stm_b2116 MACH_STM_B2116 STM_B2116 4506
+mythology MACH_MYTHOLOGY MYTHOLOGY 4507
+fc360v1 MACH_FC360V1 FC360V1 4508
+gps_sensor MACH_GPS_SENSOR GPS_SENSOR 4509
+gazelle MACH_GAZELLE GAZELLE 4510
+mpq8064_dma MACH_MPQ8064_DMA MPQ8064_DMA 4511
+wems_asd01 MACH_WEMS_ASD01 WEMS_ASD01 4512
+apalis_t30 MACH_APALIS_T30 APALIS_T30 4513
+mx6q_sbc35_c398 MACH_MX6Q_QSBC35_C398 MX6Q_QSBC35_C398 4514
+armstonea9 MACH_ARMSTONEA9 ARMSTONEA9 4515
+omap_blazetablet MACH_OMAP_BLAZETABLET OMAP_BLAZETABLET 4516
+ar6mxq MACH_AR6MXQ AR6MXQ 4517
+ar6mxs MACH_AR6MXS AR6MXS 4518
+deto_mx6apos MACH_DETO_APOS_MX6 DETO_APOS_MX6 4519
+gwventana MACH_GWVENTANA GWVENTANA 4520
+igep0033 MACH_IGEP0033 IGEP0033 4521
+antlia MACH_RACA RACA 4522
+apus MACH_APPLESODA APPLESODA 4523
+h52c1_concerto MACH_H52C1_CONCERTO H52C1_CONCERTO 4524
+fcmbrd MACH_FCMBRD FCMBRD 4525
+pcaaxs1 MACH_PCAAXS1 PCAAXS1 4526
+ls_orca MACH_LS_ORCA LS_ORCA 4527
+pcm051lb MACH_PCM051LB PCM051LB 4528
+mx6s_lp507_gvci MACH_MX6S_LP507_GVCI MX6S_LP507_GVCI 4529
+dido MACH_DIDO DIDO 4530
+swarco_itc3_9g20 MACH_SWARCO_ITC3_9G20 SWARCO_ITC3_9G20 4531
+robo_roady MACH_ROBO_ROADY ROBO_ROADY 4532
+rskrza1 MACH_RSKRZA1 RSKRZA1 4533
+swarco_sid MACH_SWARCO_SID SWARCO_SID 4534
+mx6_iwg15s_sbc MACH_MX6_IWG15S_SBC MX6_IWG15S_SBC 4535
+mx6q_camaro MACH_MX6Q_CAMARO MX6Q_CAMARO 4536
+hb6mxs MACH_HB6MXS HB6MXS 4537
+lager MACH_LAGER LAGER 4538
+lp8x4x MACH_LP8X4X LP8X4X 4539
+tegratab7 MACH_TEGRATAB7 TEGRATAB7 4540
+andromeda MACH_ANDROMEDA ANDROMEDA 4541
+bootes MACH_BOOTES BOOTES 4542
+nethmi MACH_NETHMI NETHMI 4543
+tegratab MACH_TEGRATAB TEGRATAB 4544
+som5_evb MACH_SOM5_EVB SOM5_EVB 4545
+venaticorum MACH_VENATICORUM VENATICORUM 4546
+stm_b2110 MACH_STM_B2110 STM_B2110 4547
+elux_hathor MACH_ELUX_HATHOR ELUX_HATHOR 4548
+helios_v7 MACH_HELIOS_V7 HELIOS_V7 4549
+xc10v1 MACH_XC10V1 XC10V1 4550
+cp2u MACH_CP2U CP2U 4551
+iap_f MACH_IAP_F IAP_F 4552
+iap_g MACH_IAP_G IAP_G 4553
+aae MACH_AAE AAE 4554
+pegasus MACH_PEGASUS PEGASUS 4555
+cygnus MACH_CYGNUS CYGNUS 4556
+centaurus MACH_CENTAURUS CENTAURUS 4557
+msm8930_qrd8930 MACH_MSM8930_QRD8930 MSM8930_QRD8930 4558
+quby_tim MACH_QUBY_TIM QUBY_TIM 4559
+zedi3250a MACH_ZEDI3250A ZEDI3250A 4560
+grus MACH_GRUS GRUS 4561
+apollo3 MACH_APOLLO3 APOLLO3 4562
+cowon_r7 MACH_COWON_R7 COWON_R7 4563
+tonga3 MACH_TONGA3 TONGA3 4564
+p535 MACH_P535 P535 4565
+sa3874i MACH_SA3874I SA3874I 4566
+mx6_navico_com MACH_MX6_NAVICO_COM MX6_NAVICO_COM 4567
+proxmobil2 MACH_PROXMOBIL2 PROXMOBIL2 4568
+ubinux1 MACH_UBINUX1 UBINUX1 4569
+istos MACH_ISTOS ISTOS 4570
+benvolio4 MACH_BENVOLIO4 BENVOLIO4 4571
+eco5_bx2 MACH_ECO5_BX2 ECO5_BX2 4572
+eukrea_cpuimx28sd MACH_EUKREA_CPUIMX28SD EUKREA_CPUIMX28SD 4573
+domotab MACH_DOMOTAB DOMOTAB 4574
+pfla03 MACH_PFLA03 PFLA03 4575
+et_cpu_301_16 MACH_ET_CPU_301_16 ET_CPU_301_16 4576
+skywalker MACH_SKYWALKER SKYWALKER 4577
+scorpius MACH_SCORPIUS SCORPIUS 4578
+capricornus MACH_CAPRICORNUS CAPRICORNUS 4579
+lyra MACH_LYRA LYRA 4580
+gatero MACH_GATERO GATERO 4581
+gatero01 MACH_GATERO01 GATERO01 4582
+z4dtg MACH_Z4DTG Z4DTG 4583
+lupus MACH_LUPUS LUPUS 4584
+leap101 MACH_LEAP101 LEAP101 4585
+cm_t335 MACH_CM_T335 CM_T335 4586
+pna MACH_PNA PNA 4587
+ecoforest_cpu2013 MACH_ECOFOREST_CPU2013 ECOFOREST_CPU2013 4588
+apq8064_dma MACH_APQ8064_DMA APQ8064_DMA 4589
+mx53_armour MACH_MX53_ARMOUR MX53_ARMOUR 4590
+eurofunk_aepl3 MACH_EUROFUNK_AEPL3 EUROFUNK_AEPL3 4591
+eurofunk_mhls3 MACH_EUROFUNK_MHLS3 EUROFUNK_MHLS3 4592
+eurofunk_e1if MACH_EUROFUNK_E1IF EUROFUNK_E1IF 4593
+lepus MACH_LEPUS LEPUS 4594
+bora MACH_BORA BORA 4595
+ads4011 MACH_ADS4011 ADS4011 4596
+beaver MACH_BEAVER BEAVER 4597
+imx233_iungo MACH_IMX233_IUNGO IMX233_IUNGO 4598
+cepheus MACH_CEPHEUS CEPHEUS 4599
+cetus MACH_CETUS CETUS 4600
+chamaeleon MACH_CHAMAELEON CHAMAELEON 4601
+ardbeg MACH_ARDBEG ARDBEG 4602
+ixora MACH_IXORA IXORA 4603
+juglans MACH_JUGLANS JUGLANS 4604
+canismajor MACH_CANISMAJOR CANISMAJOR 4605
+at91sam9263mib MACH_AT91SAM9263MIB AT91SAM9263MIB 4606
+cosino_9g35 MACH_COSINO_9G35 COSINO_9G35 4607
+tiny4412 MACH_TINY4412 TINY4412 4608
+balloon4 MACH_BALLOON4 BALLOON4 4609
+pgg MACH_PGG PGG 4610
+xxsq701 MACH_XXSQ701 XXSQ701 4611
+mx6_navico_rdr MACH_MX6_NAVICO_RDR MX6_NAVICO_RDR 4612
+phantom MACH_PHANTOM PHANTOM 4613
+canisminorh MACH_CANISMINORH CANISMINORH 4614
+carina MACH_CARINA CARINA 4615
+e1859 MACH_E1859 E1859 4616
+armstonea5 MACH_ARMSTONEA5 ARMSTONEA5 4617
+picocoma5 MACH_PICOCOMA5 PICOCOMA5 4618
+netdcua5 MACH_NETDCUA5 NETDCUA5 4619
+molly MACH_MOLLY MOLLY 4620
+maserati MACH_MASERATI MASERATI 4621
+mx53_idebx MACH_MX53_IDEBX MX53_IDEBX 4622
+mx53_c2cb MACH_MX53_C2CB MX53_C2CB 4623
+mipsee MACH_MIPSEE MIPSEE 4624
+seeklop MACH_SEEKLOP SEEKLOP 4625
+audisee MACH_AUDISEE AUDISEE 4626
+tx48 MACH_TX48 TX48 4627
+tl7689_pad_aurora MACH_TL7689_PAD_REF TL7689_PAD_REF 4628
+tl7689_pad_test MACH_TL7689_PAD_TEST TL7689_PAD_TEST 4629
+tl7689_phone_ref MACH_TL7689_PHONE_REF TL7689_PHONE_REF 4630
+tl7689_phone_test MACH_TL7689_PHONE_TEST TL7689_PHONE_TEST 4631
+swarco_scc_wks MACH_SWARCO_SCC_WKS SWARCO_SCC_WKS 4632
+accordo2 MACH_ACCORDO2 ACCORDO2 4633
+trizeps7 MACH_TRIZEPS7 TRIZEPS7 4634
+f100 MACH_F100 F100 4635
+armadillo410 MACH_ARMADILLO410 ARMADILLO410 4636
+tiny2416 MACH_TINY2416 TINY2416 4637
+tiny2451 MACH_TINY2451 TINY2451 4638
+mini2451 MACH_MINI2451 MINI2451 4639
+tiny5250 MACH_TINY5250 TINY5250 4640
+tiny3358 MACH_TINY3358 TINY3358 4641
+cassiopeia MACH_T6_UL T6_UL 4642
+columba MACH_T6_U T6_U 4643
+delphinus MACH_T6_ULA T6_ULA 4644
+crater MACH_T6_WL T6_WL 4645
+eridanus MACH_T6_WHL T6_WHL 4646
+circinus MACH_CIRCINUS CIRCINUS 4647
+socpk255 MACH_SOCPK255 SOCPK255 4648
+socprv270 MACH_SOCPRV270 SOCPRV270 4649
+socprc270 MACH_SOCPRC270 SOCPRC270 4650
+induses MACH_MACH_CP5DTU MACH_CP5DTU 4651
+hercules MACH_CP5DTU CP5DTU 4652
+horologium MACH_CP5DUG CP5DUG 4653
+hydrus MACH_CP5DWG CP5DWG 4654
+am335x_egf MACH_AM335X_EGF AM335X_EGF 4655
+azm9g45 MACH_AZM9G45 AZM9G45 4656
+azm335x MACH_AZM335X AZM335X 4657
+lynbrd MACH_LYNBRD LYNBRD 4658
+am35x_egf MACH_AM35X_EGF AM35X_EGF 4659
+sevulcan MACH_SEVULCAN SEVULCAN 4660
+ax8008m MACH_AX8008M AX8008M 4661
+ax8008mr MACH_AX8008MR AX8008MR 4662
+xynix MACH_XYNIX XYNIX 4663
+omap3621_odyv4 MACH_OMAP3621_ODYV4 OMAP3621_ODYV4 4664
+mx6_cameronet MACH_MX6_CAMERONET MX6_CAMERONET 4665
+omap4_dart MACH_OMAP4_DART OMAP4_DART 4666
+mx6q_enzo MACH_MX6Q_ENZO MX6Q_ENZO 4667
+ev_imx287micro MACH_EV_IMX287MICRO EV_IMX287MICRO 4668
+ev_imx287mini MACH_EV_IMX287MINI EV_IMX287MINI 4669
+mx53_cec2 MACH_MX53_CEC2 MX53_CEC2 4670
+helios_v8 MACH_HELIOS_V8 HELIOS_V8 4671
+helios_v9 MACH_HELIOS_V9 HELIOS_V9 4672
+cognac MACH_COGNAC COGNAC 4673
+zest MACH_ZEST ZEST 4674
+gc3 MACH_GC3 GC3 4675
+dad_media MACH_DAD_MEDIA DAD_MEDIA 4676
+htouch MACH_HTOUCH HTOUCH 4677
+spt7500baseboard MACH_SPT7500BASEBOARD SPT7500BASEBOARD 4678
+omap4_dart_evm MACH_OMAP4_DART_EVM OMAP4_DART_EVM 4679
+mx53_tlv MACH_MX53_TLV MX53_TLV 4680
+pdak2h MACH_PDAK2H PDAK2H 4681
+matrix513 MACH_MATRIX513 MATRIX513 4682
+livebox01 MACH_LIVEBOX01 LIVEBOX01 4683
+cevrza1l MACH_CEVRZA1L CEVRZA1L 4684
+b1010 MACH_B1010 B1010 4685
+fwtmk1 MACH_FWTMK1 FWTMK1 4686
+grenada MACH_GRENADA GRENADA 4687
+hassel MACH_HASSEL HASSEL 4688
+odroidxu MACH_ODROIDXU ODROIDXU 4689
+odroidu2 MACH_ODROIDU2 ODROIDU2 4690
+naiad MACH_NAIAD NAIAD 4691
+harrier MACH_HARRIER HARRIER 4692
+pcl052 MACH_PCL052 PCL052 4693
+libra2404 MACH_LIBRA2404 LIBRA2404 4694
+mx6_lemonboard MACH_MX6_LEMONBOARD MX6_LEMONBOARD 4695
+mx6_atlas MACH_MX6_ATLAS MX6_ATLAS 4696
+elecsys_z2 MACH_ELECSYS_Z2 ELECSYS_Z2 4697
+elecsys_z4 MACH_ELECSYS_Z4 ELECSYS_Z4 4698
+ipq806x_db149 MACH_IPQ806X_DB149 IPQ806X_DB149 4699
+pulsar MACH_PULSAR PULSAR 4700
+scalancem MACH_SCALANCEM SCALANCEM 4701
+na11 MACH_NA11 NA11 4702
+ipq806x_db147 MACH_IPQ806X_DB147 IPQ806X_DB147 4703
+ipq806x_ap148 MACH_IPQ806X_AP148 IPQ806X_AP148 4704
+amltd_imx6 MACH_AMLTD_IMX6 AMLTD_IMX6 4705
+pia_am335x MACH_PIA_AM335X PIA_AM335X 4706
+blade MACH_BLADE BLADE 4707
+matisse MACH_MATISSE MATISSE 4708
+ikebana MACH_IKEBANA IKEBANA 4709
+lf3000 MACH_LF3000 LF3000 4710
+carallon_stingray MACH_CARALLON_STINGRAY CARALLON_STINGRAY 4711
+mensa MACH_MENSA MENSA 4712
+ces_coreboard MACH_CES_COREBOARD CES_COREBOARD 4713
+vybrid_iwg16m_umxm MACH_VYBRID_IWG16M_UMXM VYBRID_IWG16M_UMXM 4714
+loki MACH_LOKI LOKI 4715
+pcm053 MACH_PCM053 PCM053 4716
+smm200 MACH_SMM200 SMM200 4717
+m507 MACH_M507 M507 4718
+orsoc_armsoc_8695 MACH_ORSOC_ARMSOC_8695 ORSOC_ARMSOC_8695 4719
+am335x_zy MACH_AM335X_ZY AM335X_ZY 4720
+arrakis MACH_ARRAKIS ARRAKIS 4721
+sxlt MACH_SXLT SXLT 4722
+ylcm MACH_YLCM YLCM 4723
+eagle6d MACH_EAGLE6D EAGLE6D 4724
+lcu1 MACH_LCU1 LCU1 4725
+mx6dl_iwg15m_q7 MACH_MX6DL_IWG15M_Q7 MX6DL_IWG15M_Q7 4726
+sbc_phyflex_am335 MACH_SBCPHYFLEXAM335 SBCPHYFLEXAM335 4727
+sbc_phycard_am335 MACH_SBCPHYCARDAM335 SBCPHYCARDAM335 4728
+sbc_phyflex_imx6 MACH_SBCPHYFLEXIMX6 SBCPHYFLEXIMX6 4729
+homeserverstick MACH_HOMESERVERSTICK HOMESERVERSTICK 4730
+ecxec MACH_ECXEC ECXEC 4731
+hh300 MACH_HH300 HH300 4732
+cpuca8 MACH_CPUCA8 CPUCA8 4733
+a0057_lsembeddedpc MACH_A0057_LSEMBEDDEDPC A0057_LSEMBEDDEDPC 4734
+iproc MACH_IPROC IPROC 4735
+nemesis_nfe MACH_NEMESIS_NFE NEMESIS_NFE 4736
+mabv3x25 MACH_MABV3X25 MABV3X25 4737
+octant MACH_OCTANT OCTANT 4738
+msm7x27_thunder MACH_MSM7X27_THUNDER MSM7X27_THUNDER 4739
+maxim MACH_MAXIM MAXIM 4740
+telematicctrlunit MACH_TELEMATICCTRLUNIT TELEMATICCTRLUNIT 4741
+mx6q_jcdbox MACH_MX6Q_JCDBOX MX6Q_JCDBOX 4742
+ckb_1808 MACH_CKB_1808 CKB_1808 4743
+ckb_3352 MACH_CKB_3352 CKB_3352 4744
+hikirk MACH_HIKIRK HIKIRK 4745
+dns320l MACH_DNS320L DNS320L 4746
+stm_b2120 MACH_STM_B2120 STM_B2120 4747
+stm_b2089 MACH_STM_B2089 STM_B2089 4748
+colibri_vf50 MACH_COLIBRI_VF50 COLIBRI_VF50 4749
+colibri_vf61 MACH_COLIBRI_VF61 COLIBRI_VF61 4750
+synergy2 MACH_SYNERGY2 SYNERGY2 4751
+pcm051_hmi MACH_PCM051_HMI PCM051_HMI 4752
+tek2 MACH_TEK2 TEK2 4753
+duckbill MACH_DUCKBILL DUCKBILL 4754
+mx50_seismic MACH_MX50_SEISMIC MX50_SEISMIC 4755
+twoface MACH_TWOFACE TWOFACE 4756
+t10 MACH_T10 T10 4757
+lib1313 MACH_LIB1313 LIB1313 4758
+himx MACH_HIMX HIMX 4759
+vcm30_t30 MACH_VCM30_T30 VCM30_T30 4760
+cornerview MACH_CORNERVIEW CORNERVIEW 4761
+p01600 MACH_P01600 P01600 4762
+axel MACH_AXEL AXEL 4763
+imx6_andy MACH_IMX6_ANDY IMX6_ANDY 4764
+nsa220 MACH_NSA220 NSA220 4765
+ti8168hsc1 MACH_TI8168HSC1 TI8168HSC1 4766
+dory MACH_DORY DORY 4767
+ecv4 MACH_ECV4 ECV4 4768
+webbg3flight MACH_WEBBG3FLIGHT WEBBG3FLIGHT 4769
+sbc_phycore_am335x MACH_SBC_PHYCORE_AM335X SBC_PHYCORE_AM335X 4770
+tsc MACH_TSC TSC 4771
diff --git a/arch/mips/boards/rzx50/Makefile b/arch/mips/boards/rzx50/Makefile
index 9e14763111..ff1a655afe 100644
--- a/arch/mips/boards/rzx50/Makefile
+++ b/arch/mips/boards/rzx50/Makefile
@@ -1,2 +1 @@
-obj-y += board.o
obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial.o
diff --git a/arch/mips/boards/rzx50/board.c b/arch/mips/boards/rzx50/board.c
deleted file mode 100644
index 9e655aba50..0000000000
--- a/arch/mips/boards/rzx50/board.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <common.h>
-#include <init.h>
-#include <sizes.h>
-#include <asm/memory.h>
-
-static int mem_init(void)
-{
- mips_add_ram0(SZ_64M);
-
- return 0;
-}
-mem_initcall(mem_init);
diff --git a/arch/mips/boards/rzx50/serial.c b/arch/mips/boards/rzx50/serial.c
index 0038c1db40..566356aaa5 100644
--- a/arch/mips/boards/rzx50/serial.c
+++ b/arch/mips/boards/rzx50/serial.c
@@ -22,7 +22,6 @@
static int rzx50_console_init(void)
{
- barebox_set_model("Ritmix RZX-50");
barebox_set_hostname("rzx50");
/* Register the serial port */
diff --git a/arch/mips/configs/rzx50_defconfig b/arch/mips/configs/rzx50_defconfig
index 7b759090f4..7691bae6e6 100644
--- a/arch/mips/configs/rzx50_defconfig
+++ b/arch/mips/configs/rzx50_defconfig
@@ -1,3 +1,5 @@
+CONFIG_BUILTIN_DTB=y
+CONFIG_BUILTIN_DTB_NAME="rzx50"
CONFIG_MACH_MIPS_XBURST=y
CONFIG_JZ4750D_DEBUG_LL_UART1=y
CONFIG_PBL_IMAGE=y
@@ -27,6 +29,10 @@ CONFIG_CMD_UIMAGE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_POWEROFF=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_OFDEVICE=y
# CONFIG_SPI is not set
CONFIG_SHA1=y
CONFIG_SHA224=y
diff --git a/arch/mips/dts/rzx50.dts b/arch/mips/dts/rzx50.dts
new file mode 100644
index 0000000000..69320ddbb3
--- /dev/null
+++ b/arch/mips/dts/rzx50.dts
@@ -0,0 +1,12 @@
+/dts-v1/;
+
+/include/ "skeleton.dtsi"
+
+/ {
+ model = "Ritmix RZX-50";
+ compatible = "ritmix,rzx50";
+
+ memory {
+ reg = <0x00000000 0x4000000>;
+ };
+};
diff --git a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h
index 0703bb0f23..9927b4d945 100644
--- a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h
+++ b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h
@@ -30,8 +30,10 @@
static __inline__ void PUTC_LL(char ch)
{
- while (!(__raw_readb(DEBUG_LL_UART_ADDR + lsr) & LSR_THRE));
- __raw_writeb(ch, DEBUG_LL_UART_ADDR + rbr);
+ void *base = (void *)DEBUG_LL_UART_ADDR;
+
+ while (!(__raw_readb(base + lsr) & LSR_THRE));
+ __raw_writeb(ch, base + rbr);
}
#endif /* __INCLUDE_ARCH_DEBUG_LL_H__ */
diff --git a/arch/ppc/mach-mpc85xx/fdt.c b/arch/ppc/mach-mpc85xx/fdt.c
index 4feae441e6..65de6f1104 100644
--- a/arch/ppc/mach-mpc85xx/fdt.c
+++ b/arch/ppc/mach-mpc85xx/fdt.c
@@ -70,9 +70,7 @@ static int fdt_stdout_setup(struct device_node *blob)
goto error;
}
- for_each_console(cdev)
- if ((cdev->f_active & (CONSOLE_STDIN | CONSOLE_STDOUT)))
- break;
+ cdev = console_get_first_active();
if (cdev)
sprintf(sername, "serial%d", cdev->dev->id);
else
diff --git a/arch/sandbox/board/console.c b/arch/sandbox/board/console.c
index b0afa54d95..cd5ad57235 100644
--- a/arch/sandbox/board/console.c
+++ b/arch/sandbox/board/console.c
@@ -36,11 +36,6 @@ int barebox_register_console(char *name, int stdinfd, int stdoutfd)
strcpy(dev->name, "console");
- if (stdinfd >= 0)
- data->flags = CONSOLE_STDIN;
- if (stdoutfd >= 0)
- data->flags |= CONSOLE_STDOUT | CONSOLE_STDERR;
-
data->stdoutfd = stdoutfd;
data->stdinfd = stdinfd;
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index 50d2721f77..98f9067046 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -23,7 +23,6 @@ int barebox_register_console(char *name_template, int stdinfd, int stdoutfd);
struct linux_console_data {
int stdinfd;
int stdoutfd;
- unsigned int flags;
};
extern int sdl_xres;
diff --git a/commands/Kconfig b/commands/Kconfig
index 55e46a0392..9738ec4630 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -514,6 +514,17 @@ config CMD_LINUX16
Compile the linux16 command to be able to boot bzImages
via real mode.
+config CMD_BOOT
+ tristate
+ select BOOTM
+ prompt "boot"
+ help
+ Select this for booting based on scripts. unlike the bootm command which
+ can boot a single image this command offers the possibility to boot with
+ scripts (by default placed under /env/boot/). This command iterates over
+ multiple scripts until one succeeds. It supersedes the previous 'boot'
+ script.
+
config CMD_RESET
tristate
prompt "reset"
diff --git a/commands/Makefile b/commands/Makefile
index 6acffc8284..58d27fa905 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -91,3 +91,5 @@ obj-$(CONFIG_CMD_FILETYPE) += filetype.o
obj-$(CONFIG_CMD_BAREBOX_UPDATE)+= barebox-update.o
obj-$(CONFIG_CMD_MIITOOL) += miitool.o
obj-$(CONFIG_CMD_DETECT) += detect.o
+obj-$(CONFIG_CMD_BOOT) += boot.o
+obj-$(CONFIG_CMD_DEVINFO) += devinfo.o
diff --git a/commands/boot.c b/commands/boot.c
new file mode 100644
index 0000000000..33d1177861
--- /dev/null
+++ b/commands/boot.c
@@ -0,0 +1,258 @@
+/*
+ * 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.
+ *
+ */
+
+#include <environment.h>
+#include <globalvar.h>
+#include <magicvar.h>
+#include <command.h>
+#include <common.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <malloc.h>
+#include <boot.h>
+#include <fs.h>
+
+#include <linux/stat.h>
+
+static int verbose;
+static int dryrun;
+
+static void bootsources_list(void)
+{
+ DIR *dir;
+ struct dirent *d;
+ const char *path = "/env/boot";
+
+ dir = opendir(path);
+ if (!dir) {
+ printf("cannot open %s: %s\n", path, strerror(-errno));
+ return;
+ }
+
+ printf("Bootsources: ");
+
+ while ((d = readdir(dir))) {
+ if (*d->d_name == '.')
+ continue;
+
+ printf("%s ", d->d_name);
+ }
+
+ printf("\n");
+
+ closedir(dir);
+}
+
+static const char *getenv_or_null(const char *var)
+{
+ const char *val = getenv(var);
+
+ if (val && *val)
+ return val;
+ return NULL;
+}
+
+/*
+ * Start a single boot script. 'path' is a full path to a boot script.
+ */
+static int boot_script(char *path)
+{
+ struct bootm_data data = {};
+ int ret;
+
+ printf("booting %s...\n", basename(path));
+
+ globalvar_set_match("linux.bootargs.dyn.", "");
+ globalvar_set_match("bootm.", "");
+
+ ret = run_command(path, 0);
+ if (ret) {
+ printf("Running %s failed\n", path);
+ goto out;
+ }
+
+ data.initrd_address = UIMAGE_INVALID_ADDRESS;
+ data.os_address = UIMAGE_SOME_ADDRESS;
+ data.oftree_file = getenv_or_null("global.bootm.oftree");
+ data.os_file = getenv_or_null("global.bootm.image");
+ getenv_ul("global.bootm.image.loadaddr", &data.os_address);
+ getenv_ul("global.bootm.initrd.loadaddr", &data.initrd_address);
+ data.initrd_file = getenv_or_null("global.bootm.initrd");
+ data.verbose = verbose;
+ data.dryrun = dryrun;
+
+ ret = bootm_boot(&data);
+ if (ret)
+ pr_err("Booting %s failed: %s\n", basename(path), strerror(-ret));
+out:
+ return ret;
+}
+
+/*
+ * boot a script. 'name' can either be a filename under /env/boot/,
+ * a full path to a boot script or a path to a directory. This function
+ * returns a negative error on failure, or 0 on a successful dryrun boot.
+ */
+static int boot(const char *name)
+{
+ char *path;
+ DIR *dir;
+ struct dirent *d;
+ struct stat s;
+ int ret;
+
+ if (*name == '/')
+ path = xstrdup(name);
+ else
+ path = asprintf("/env/boot/%s", name);
+
+ ret = stat(path, &s);
+ if (ret) {
+ pr_err("%s: %s\n", path, strerror(-ret));
+ goto out;
+ }
+
+ if (S_ISREG(s.st_mode)) {
+ ret = boot_script(path);
+ goto out;
+ }
+
+ dir = opendir(path);
+ if (!dir) {
+ ret = -errno;
+ printf("cannot open %s: %s\n", path, strerror(-errno));
+ goto out;
+ }
+
+ while ((d = readdir(dir))) {
+ char *file;
+ struct stat s;
+
+ if (*d->d_name == '.')
+ continue;
+
+ file = asprintf("%s/%s", path, d->d_name);
+
+ ret = stat(file, &s);
+ if (ret) {
+ free(file);
+ continue;
+ }
+
+ if (!S_ISREG(s.st_mode)) {
+ free(file);
+ continue;
+ }
+
+ ret = boot_script(file);
+
+ free(file);
+
+ if (!ret)
+ break;
+ }
+
+ closedir(dir);
+out:
+ free(path);
+
+ return ret;
+}
+
+static int do_boot(int argc, char *argv[])
+{
+ const char *sources = NULL;
+ char *source, *freep;
+ int opt, ret = 0, do_list = 0;
+
+ verbose = 0;
+ dryrun = 0;
+
+ while ((opt = getopt(argc, argv, "vld")) > 0) {
+ switch (opt) {
+ case 'v':
+ verbose++;
+ break;
+ case 'l':
+ do_list = 1;
+ break;
+ case 'd':
+ dryrun = 1;
+ break;
+ }
+ }
+
+ if (do_list) {
+ bootsources_list();
+ return 0;
+ }
+
+ if (optind < argc) {
+ while (optind < argc) {
+ source = argv[optind];
+ optind++;
+ ret = boot(source);
+ if (!ret)
+ break;
+ }
+ return ret;
+ }
+
+ sources = getenv("global.boot.default");
+ if (!sources)
+ return 0;
+
+ freep = source = xstrdup(sources);
+
+ while (1) {
+ char *sep = strchr(source, ' ');
+ if (sep)
+ *sep = 0;
+ ret = boot(source);
+ if (!ret)
+ break;
+
+ if (sep)
+ source = sep + 1;
+ else
+ break;
+ }
+
+ free(freep);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(boot)
+BAREBOX_CMD_HELP_USAGE("boot [OPTIONS] [BOOTSRC...]\n")
+BAREBOX_CMD_HELP_SHORT("Boot an operating system.\n")
+BAREBOX_CMD_HELP_SHORT("[BOOTSRC...] can be:\n")
+BAREBOX_CMD_HELP_SHORT("- a filename from /env/boot/\n")
+BAREBOX_CMD_HELP_SHORT("- a full path to a file\n")
+BAREBOX_CMD_HELP_SHORT("- a path to a directory. All files in this directory are treated\n")
+BAREBOX_CMD_HELP_SHORT(" as boot scripts.\n")
+BAREBOX_CMD_HELP_SHORT("Multiple bootsources may be given which are probed in order until\n")
+BAREBOX_CMD_HELP_SHORT("one succeeds.\n")
+BAREBOX_CMD_HELP_SHORT("\nOptions:\n")
+BAREBOX_CMD_HELP_OPT ("-v","Increase verbosity\n")
+BAREBOX_CMD_HELP_OPT ("-d","Dryrun. See what happens but do no actually boot\n")
+BAREBOX_CMD_HELP_OPT ("-l","List available boot sources\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(boot)
+ .cmd = do_boot,
+ .usage = "boot the machine",
+ BAREBOX_CMD_HELP(cmd_boot_help)
+BAREBOX_CMD_END
+
+BAREBOX_MAGICVAR_NAMED(global_boot_default, global.boot.default, "default boot order");
diff --git a/commands/bootm.c b/commands/bootm.c
index a4004dfb4c..5dff7dd674 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -46,33 +46,7 @@
#include <magicvar.h>
#include <asm-generic/memory_layout.h>
-/*
- * Additional oftree size for the fixed tree
- */
-#define OFTREE_SIZE_INCREASE 0x8000
-
-static char *bootm_image_name_and_no(const char *name, int *no)
-{
- char *at, *ret;
-
- if (!name || !*name)
- return NULL;
-
- *no = 0;
-
- ret = xstrdup(name);
- at = strchr(ret, '@');
- if (!at)
- return ret;
-
- *at++ = 0;
-
- *no = simple_strtoul(at, NULL, 10);
-
- return ret;
-}
-
-#define BOOTM_OPTS_COMMON "ca:e:vo:f"
+#define BOOTM_OPTS_COMMON "ca:e:vo:fd"
#ifdef CONFIG_CMD_BOOTM_INITRD
#define BOOTM_OPTS BOOTM_OPTS_COMMON "L:r:"
@@ -80,28 +54,13 @@ static char *bootm_image_name_and_no(const char *name, int *no)
#define BOOTM_OPTS BOOTM_OPTS_COMMON
#endif
-unsigned long long getenv_loadaddr(const char *name)
-{
- const char *valstr = getenv(name);
-
- if (!valstr)
- return UIMAGE_SOME_ADDRESS;
-
- if (valstr[0] == '\0')
- return UIMAGE_SOME_ADDRESS;
-
- return simple_strtoull(valstr, NULL, 0);
-}
-
static int do_bootm(int argc, char *argv[])
{
int opt;
- struct image_data data;
+ struct bootm_data data = {};
int ret = 1;
const char *oftree = NULL, *initrd_file = NULL, *os_file = NULL;
- memset(&data, 0, sizeof(struct image_data));
-
data.initrd_address = UIMAGE_INVALID_ADDRESS;
data.os_address = UIMAGE_SOME_ADDRESS;
data.verify = 0;
@@ -109,8 +68,8 @@ static int do_bootm(int argc, char *argv[])
oftree = getenv("global.bootm.oftree");
os_file = getenv("global.bootm.image");
- data.os_address = getenv_loadaddr("global.bootm.image.loadaddr");
- data.initrd_address = getenv_loadaddr("global.bootm.initrd.loadaddr");
+ getenv_ul("global.bootm.image.loadaddr", &data.os_address);
+ getenv_ul("global.bootm.initrd.loadaddr", &data.initrd_address);
if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD))
initrd_file = getenv("global.bootm.initrd");
@@ -142,6 +101,9 @@ static int do_bootm(int argc, char *argv[])
case 'f':
data.force = 1;
break;
+ case 'd':
+ data.dryrun = 1;
+ break;
default:
break;
}
@@ -161,39 +123,28 @@ static int do_bootm(int argc, char *argv[])
if (oftree && !*oftree)
oftree = NULL;
- data.os_file = bootm_image_name_and_no(os_file, &data.os_num);
- data.oftree_file = bootm_image_name_and_no(oftree, &data.oftree_num);
- data.initrd_file = bootm_image_name_and_no(initrd_file, &data.initrd_num);
+ data.os_file = os_file;
+ data.oftree_file = oftree;
+ data.initrd_file = initrd_file;
ret = bootm_boot(&data);
+ if (ret) {
+ printf("handler failed with: %s\n", strerror(-ret));
+ goto err_out;
+ }
- printf("handler failed with %s\n", strerror(-ret));
+ if (data.dryrun)
+ printf("Dryrun. Aborted\n");
err_out:
- free(data.initrd_file);
- free(data.os_file);
-
- return 1;
-}
-
-static int bootm_init(void)
-{
- globalvar_add_simple("bootm.image", NULL);
- globalvar_add_simple("bootm.image.loadaddr", NULL);
- globalvar_add_simple("bootm.oftree", NULL);
- if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD)) {
- globalvar_add_simple("bootm.initrd", NULL);
- globalvar_add_simple("bootm.initrd.loadaddr", NULL);
- }
-
- return 0;
+ return ret ? 1 : 0;
}
-late_initcall(bootm_init);
BAREBOX_CMD_HELP_START(bootm)
BAREBOX_CMD_HELP_USAGE("bootm [OPTIONS] image\n")
BAREBOX_CMD_HELP_SHORT("Boot an application image.\n")
BAREBOX_CMD_HELP_OPT ("-c", "crc check uImage data\n")
+BAREBOX_CMD_HELP_OPT ("-d", "dryrun. Check data, but do not run\n")
#ifdef CONFIG_CMD_BOOTM_INITRD
BAREBOX_CMD_HELP_OPT ("-r <initrd>","specify an initrd image\n")
BAREBOX_CMD_HELP_OPT ("-L <load addr>","specify initrd load address\n")
diff --git a/commands/crc.c b/commands/crc.c
index a0071b0e8b..ee8dacff0b 100644
--- a/commands/crc.c
+++ b/commands/crc.c
@@ -82,6 +82,19 @@ out:
return ret;
}
+static int crc_from_file(const char* file, ulong *crc)
+{
+ char * buf;
+
+ buf= read_file(file, NULL);
+
+ if (!buf)
+ return -ENOMEM;
+
+ *crc = simple_strtoul(buf, NULL, 16);
+ return 0;
+}
+
static int do_crc(int argc, char *argv[])
{
loff_t start = 0, size = ~0;
@@ -92,7 +105,7 @@ static int do_crc(int argc, char *argv[])
#endif
int opt, err = 0, filegiven = 0, verify = 0;
- while((opt = getopt(argc, argv, "f:F:v:")) > 0) {
+ while((opt = getopt(argc, argv, "f:F:v:V:")) > 0) {
switch(opt) {
case 'f':
filename = optarg;
@@ -108,6 +121,10 @@ static int do_crc(int argc, char *argv[])
verify = 1;
vcrc = simple_strtoul(optarg, NULL, 0);
break;
+ case 'V':
+ if (!crc_from_file(optarg, &vcrc))
+ verify = 1;
+ break;
default:
return COMMAND_ERROR_USAGE;
}
@@ -153,6 +170,7 @@ BAREBOX_CMD_HELP_OPT ("-f <file>", "Use file instead of memory.\n")
BAREBOX_CMD_HELP_OPT ("-F <file>", "Use file to compare.\n")
#endif
BAREBOX_CMD_HELP_OPT ("-v <crc>", "Verify\n")
+BAREBOX_CMD_HELP_OPT ("-V <file>", "Verify with crc read from <file>\n")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(crc32)
diff --git a/commands/detect.c b/commands/detect.c
index fbce4eb0ce..15055e78bc 100644
--- a/commands/detect.c
+++ b/commands/detect.c
@@ -82,6 +82,7 @@ BAREBOX_CMD_HELP_START(detect)
BAREBOX_CMD_HELP_USAGE("detect [OPTIONS] [devices]\n")
BAREBOX_CMD_HELP_OPT ("-l", "list detectable devices\n")
BAREBOX_CMD_HELP_OPT ("-e", "bail out if one device fails to detect\n")
+BAREBOX_CMD_HELP_OPT ("-a", "detect all devices\n")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(detect)
diff --git a/commands/devinfo.c b/commands/devinfo.c
new file mode 100644
index 0000000000..806e45c9ba
--- /dev/null
+++ b/commands/devinfo.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2013 Sascha Hauer, Pengutronix
+ *
+ * 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.
+ *
+ */
+
+#include <command.h>
+#include <common.h>
+#include <complete.h>
+#include <driver.h>
+
+static int do_devinfo_subtree(struct device_d *dev, int depth)
+{
+ struct device_d *child;
+ struct cdev *cdev;
+ int i;
+
+ for (i = 0; i < depth; i++)
+ printf(" ");
+
+ printf("`---- %s", dev_name(dev));
+ if (!list_empty(&dev->cdevs)) {
+ printf("\n");
+ list_for_each_entry(cdev, &dev->cdevs, devices_list) {
+ for (i = 0; i < depth + 1; i++)
+ printf(" ");
+ printf("`---- 0x%08llx-0x%08llx: /dev/%s\n",
+ cdev->offset,
+ cdev->offset + cdev->size - 1,
+ cdev->name);
+ }
+ } else {
+ printf("\n");
+ }
+
+ if (!list_empty(&dev->children)) {
+ device_for_each_child(dev, child) {
+ do_devinfo_subtree(child, depth + 1);
+ }
+ }
+
+ return 0;
+}
+
+static int do_devinfo(int argc, char *argv[])
+{
+ struct device_d *dev;
+ struct driver_d *drv;
+ struct param_d *param;
+ int i;
+ struct resource *res;
+
+ if (argc == 1) {
+ printf("devices:\n");
+
+ for_each_device(dev) {
+ if (!dev->parent)
+ do_devinfo_subtree(dev, 0);
+ }
+
+ printf("\ndrivers:\n");
+ for_each_driver(drv)
+ printf("%s\n",drv->name);
+ } else {
+ dev = get_device_by_name(argv[1]);
+
+ if (!dev) {
+ printf("no such device: %s\n",argv[1]);
+ return -1;
+ }
+
+ printf("resources:\n");
+ for (i = 0; i < dev->num_resources; i++) {
+ res = &dev->resource[i];
+ printf("num : %d\n", i);
+ if (res->name)
+ printf("name : %s\n", res->name);
+ printf("start : " PRINTF_CONVERSION_RESOURCE "\nsize : "
+ PRINTF_CONVERSION_RESOURCE "\n",
+ res->start, resource_size(res));
+ }
+
+ printf("driver: %s\n", dev->driver ?
+ dev->driver->name : "none");
+
+ printf("bus: %s\n\n", dev->bus ?
+ dev->bus->name : "none");
+
+ if (dev->info)
+ dev->info(dev);
+
+ printf("%s\n", list_empty(&dev->parameters) ?
+ "no parameters available" : "Parameters:");
+
+ list_for_each_entry(param, &dev->parameters, list) {
+ printf("%16s = %s", param->name, dev_get_param(dev, param->name));
+ if (param->info)
+ param->info(param);
+ printf("\n");
+ }
+#ifdef CONFIG_OFDEVICE
+ if (dev->device_node) {
+ printf("\ndevice node: %s\n", dev->device_node->full_name);
+ of_print_nodes(dev->device_node, 0);
+ }
+#endif
+ }
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(devinfo)
+BAREBOX_CMD_HELP_USAGE("devinfo [DEVICE]\n")
+BAREBOX_CMD_HELP_SHORT("Output device information.\n")
+BAREBOX_CMD_HELP_END
+
+/**
+ * @page devinfo_command
+
+If called without arguments, devinfo shows a summary of the known
+devices and drivers.
+
+If called with a device path being the argument, devinfo shows more
+default information about this device and its parameters.
+
+Example from an MPC5200 based system:
+
+@verbatim
+ barebox:/ devinfo /dev/eth0
+ base : 0x1002b000
+ size : 0x00000000
+ driver: fec_mpc5xxx
+
+ no info available for eth0
+ Parameters:
+ ipaddr = 192.168.23.197
+ ethaddr = 80:81:82:83:84:86
+ gateway = 192.168.23.1
+ netmask = 255.255.255.0
+ serverip = 192.168.23.2
+@endverbatim
+ */
+
+BAREBOX_CMD_START(devinfo)
+ .cmd = do_devinfo,
+ .usage = "Show information about devices and drivers.",
+ BAREBOX_CMD_HELP(cmd_devinfo_help)
+ BAREBOX_CMD_COMPLETE(device_complete)
+BAREBOX_CMD_END
diff --git a/commands/loadb.c b/commands/loadb.c
index a2f3315b64..b527e0095c 100644
--- a/commands/loadb.c
+++ b/commands/loadb.c
@@ -591,26 +591,6 @@ err_quit:
}
/**
- * @brief returns current used console device
- *
- * @return console device which is registered with CONSOLE_STDIN and
- * CONSOLE_STDOUT
- */
-static struct console_device *get_current_console(void)
-{
- struct console_device *cdev;
- /*
- * Assumption to have BOTH CONSOLE_STDIN AND STDOUT in the
- * same output console
- */
- for_each_console(cdev) {
- if ((cdev->f_active & (CONSOLE_STDIN | CONSOLE_STDOUT)))
- return cdev;
- }
- return NULL;
-}
-
-/**
* @brief provide the loadb(Kermit) or loadY mode support
*
* @param cmdtp
@@ -650,7 +630,7 @@ static int do_load_serial_bin(int argc, char *argv[])
}
}
- cdev = get_current_console();
+ cdev = console_get_first_active();
if (NULL == cdev) {
printf("%s:No console device with STDIN and STDOUT\n", argv[0]);
return -ENODEV;
diff --git a/commands/loads.c b/commands/loads.c
index bfc465bdc7..58cd24b572 100644
--- a/commands/loads.c
+++ b/commands/loads.c
@@ -40,14 +40,9 @@ static int do_load_serial(int argc, char *argv[])
ulong offset = 0;
ulong addr;
int i;
- const char *env_echo;
int rcode = 0;
- if (((env_echo = getenv("loads_echo")) != NULL) && (*env_echo == '1')) {
- do_echo = 1;
- } else {
- do_echo = 0;
- }
+ getenv_bool("loads_echo", &do_echo);
if (argc == 2) {
offset = simple_strtoul(argv[1], NULL, 16);
diff --git a/commands/loadxy.c b/commands/loadxy.c
index 52ecdcaa0b..7a912864e3 100644
--- a/commands/loadxy.c
+++ b/commands/loadxy.c
@@ -40,26 +40,6 @@
#define DEF_FILE "image.bin"
-/**
- * @brief returns current used console device
- *
- * @return console device which is registered with CONSOLE_STDIN and
- * CONSOLE_STDOUT
- */
-static struct console_device *get_current_console(void)
-{
- struct console_device *cdev;
- /*
- * Assumption to have BOTH CONSOLE_STDIN AND STDOUT in the
- * same output console
- */
- for_each_console(cdev) {
- if ((cdev->f_active & (CONSOLE_STDIN | CONSOLE_STDOUT)))
- return cdev;
- }
- return NULL;
-}
-
static int console_change_speed(struct console_device *cdev, int baudrate)
{
int current_baudrate;
@@ -134,7 +114,7 @@ static int do_loady(int argc, char *argv[])
if (cname)
cdev = get_named_console(cname);
else
- cdev = get_current_console();
+ cdev = console_get_first_active();
if (!cdev) {
printf("%s:No console device %s with STDIN and STDOUT\n",
argv[0], cname ? cname : "default");
@@ -202,7 +182,7 @@ static int do_loadx(int argc, char *argv[])
if (cname)
cdev = get_named_console(cname);
else
- cdev = get_current_console();
+ cdev = console_get_first_active();
if (!cdev) {
printf("%s:No console device %s with STDIN and STDOUT\n",
argv[0], cname ? cname : "default");
diff --git a/commands/login.c b/commands/login.c
index fb6bb35cfc..b616bf15fc 100644
--- a/commands/login.c
+++ b/commands/login.c
@@ -20,6 +20,11 @@
#include <complete.h>
#include <password.h>
#include <getopt.h>
+#include <environment.h>
+#include <globalvar.h>
+#include <magicvar.h>
+#include <init.h>
+#include <console.h>
#define PASSWD_MAX_LENGTH (128 + 1)
@@ -31,13 +36,16 @@
#define LOGIN_MODE HIDE
#endif
+static int login_timeout = 0;
+
static int do_login(int argc, char *argv[])
{
unsigned char passwd[PASSWD_MAX_LENGTH];
int passwd_len, opt;
- int timeout = 0;
+ int timeout = login_timeout;
char *timeout_cmd = "boot";
+ console_allow_input(true);
if (!is_passwd_enable()) {
puts("login: password not set\n");
return 0;
@@ -58,8 +66,10 @@ static int do_login(int argc, char *argv[])
puts("Password: ");
passwd_len = password(passwd, PASSWD_MAX_LENGTH, LOGIN_MODE, timeout);
- if (passwd_len < 0)
+ if (passwd_len < 0) {
+ console_allow_input(false);
run_command(timeout_cmd, 0);
+ }
if (check_passwd(passwd, passwd_len))
return 0;
@@ -80,3 +90,13 @@ BAREBOX_CMD_START(login)
BAREBOX_CMD_HELP(cmd_login_help)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
+
+static int login_global_init(void)
+{
+ globalvar_add_simple_int("login.timeout", &login_timeout, "%d");
+
+ return 0;
+}
+late_initcall(login_global_init);
+
+BAREBOX_MAGICVAR_NAMED(global_login_timeout, global.login.timeout, "timeout to type the password");
diff --git a/commands/mount.c b/commands/mount.c
index be26af84ab..2e9d4bef5e 100644
--- a/commands/mount.c
+++ b/commands/mount.c
@@ -27,31 +27,70 @@
#include <fs.h>
#include <errno.h>
#include <getopt.h>
+#include <linux/err.h>
static int do_mount(int argc, char *argv[])
{
int opt;
- int ret = 0;
+ int ret = 0, verbose = 0;
struct fs_device_d *fsdev;
+ struct driver_d *drv;
const char *type = NULL;
const char *mountpoint, *dev;
- if (argc == 1) {
+ while ((opt = getopt(argc, argv, "t:va")) > 0) {
+ switch (opt) {
+ case 't':
+ type = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'a':
+ mount_all();
+ break;
+ }
+ }
+
+ if (argc == optind) {
for_each_fs_device(fsdev) {
printf("%s on %s type %s\n",
- fsdev->parent_device ? dev_name(fsdev->parent_device) : "none",
+ fsdev->backingstore ? fsdev->backingstore : "none",
fsdev->path,
fsdev->dev.name);
}
+
+ if (verbose) {
+ printf("\nSupported filesystems:\n\n");
+ bus_for_each_driver(&fs_bus, drv) {
+ struct fs_driver_d * fsdrv = drv_to_fs_driver(drv);
+ printf("%s\n", fsdrv->drv.name);
+ }
+ }
+
return 0;
}
- while ((opt = getopt(argc, argv, "t:")) > 0) {
- switch (opt) {
- case 't':
- type = optarg;
- break;
- }
+ if (argc == optind + 1) {
+ struct cdev *cdev;
+ const char *path, *devstr;
+
+ devstr = argv[optind];
+
+ if (!strncmp(devstr, "/dev/", 5))
+ devstr += 5;
+
+ cdev = cdev_by_name(devstr);
+ if (!cdev)
+ return -ENOENT;
+
+ path = cdev_mount_default(cdev);
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+
+ printf("mounted /dev/%s on %s\n", devstr, path);
+
+ return 0;
}
if (argc < optind + 2)
@@ -77,10 +116,17 @@ static int do_mount(int argc, char *argv[])
}
BAREBOX_CMD_HELP_START(mount)
-BAREBOX_CMD_HELP_USAGE("mount [[-t <fstype] <device> <mountpoint>]\n")
+BAREBOX_CMD_HELP_USAGE("mount [[OPTIONS] <device> [mountpoint]]\n")
+BAREBOX_CMD_HELP_OPT("-t <type>", "specify filesystem type\n")
+BAREBOX_CMD_HELP_OPT("-a", "Mount all blockdevices.\n")
+BAREBOX_CMD_HELP_OPT("-v", "be more verbose\n")
BAREBOX_CMD_HELP_SHORT("Mount a filesystem of a given type to a mountpoint.\n")
BAREBOX_CMD_HELP_SHORT("If no fstype is specified, try to detect it automatically.\n")
BAREBOX_CMD_HELP_SHORT("If no argument is given, list mounted filesystems.\n")
+BAREBOX_CMD_HELP_SHORT("With -a the mount command mounts all block devices whose filesystem\n")
+BAREBOX_CMD_HELP_SHORT("can be detected automatically to /mnt/<partname>\n")
+BAREBOX_CMD_HELP_SHORT("If mountpoint is not given a standard mountpoint of /mnt/devname>\n")
+BAREBOX_CMD_HELP_SHORT("is used. This directoy is created automatically if necessary.\n")
BAREBOX_CMD_HELP_END
/**
diff --git a/commands/passwd.c b/commands/passwd.c
index baccfa6c0c..368c4016b9 100644
--- a/commands/passwd.c
+++ b/commands/passwd.c
@@ -63,7 +63,7 @@ static int do_passwd(int argc, char *argv[])
goto err;
}
- ret = set_passwd(passwd1, passwd1_len);
+ ret = set_env_passwd(passwd1, passwd1_len);
if (ret < 0) {
puts("Sorry, passwords write failed\n");
@@ -78,15 +78,15 @@ err:
return 1;
disable:
- passwd_disable();
+ passwd_env_disable();
puts("passwd: password disabled\n");
return ret;
}
static const __maybe_unused char cmd_passwd_help[] =
"Usage: passwd\n"
-"passwd allow you to specify a password\n"
-"to disable it put an empty password\n"
+"passwd allow you to specify a password in the env\n"
+"to disable it put an empty password will still use the default password if set\n"
;
BAREBOX_CMD_START(passwd)
diff --git a/commands/ubi.c b/commands/ubi.c
index 2041df3fd5..57ae79025d 100644
--- a/commands/ubi.c
+++ b/commands/ubi.c
@@ -58,13 +58,25 @@ BAREBOX_CMD_END
static int do_ubiattach(int argc, char *argv[])
{
+ int opt;
struct mtd_info_user user;
int fd, ret;
+ int vid_hdr_offset = 0;
+
+ while((opt = getopt(argc, argv, "O:")) > 0) {
+ switch(opt) {
+ case 'O':
+ vid_hdr_offset = simple_strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
- if (argc != 2)
+ if (optind == argc)
return COMMAND_ERROR_USAGE;
- fd = open(argv[1], O_RDWR);
+ fd = open(argv[optind], O_RDWR);
if (fd < 0) {
perror("open");
return 1;
@@ -76,7 +88,7 @@ static int do_ubiattach(int argc, char *argv[])
goto err;
}
- ret = ubi_attach_mtd_dev(user.mtd, UBI_DEV_NUM_AUTO, 0, 20);
+ ret = ubi_attach_mtd_dev(user.mtd, UBI_DEV_NUM_AUTO, vid_hdr_offset, 20);
if (ret < 0)
printf("failed to attach: %s\n", strerror(-ret));
else
@@ -88,7 +100,7 @@ err:
}
static const __maybe_unused char cmd_ubiattach_help[] =
-"Usage: ubiattach <mtddev>\n"
+"Usage: ubiattach [-O vid-hdr-offset] <mtddev>\n"
"Attach <mtddev> to ubi\n";
BAREBOX_CMD_START(ubiattach)
diff --git a/common/Kconfig b/common/Kconfig
index dd705782ab..13419dc5bd 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -32,6 +32,7 @@ config GENERIC_GPIO
bool
config BOOTM
+ select UIMAGE
bool
config BLOCK
@@ -385,6 +386,11 @@ config PASSWORD
help
allow you to have password protection framework
+config PASSWORD_DEFAULT
+ string
+ prompt "Password default"
+ depends on PASSWORD
+
if PASSWORD
choice
@@ -549,6 +555,7 @@ config DEFAULT_ENVIRONMENT_GENERIC_NEW
select CMD_READLINK
select CMD_DIRNAME
select FLEXIBLE_BOOTARGS
+ select CMD_BOOT
prompt "Generic environment template"
config DEFAULT_ENVIRONMENT_GENERIC
@@ -602,7 +609,7 @@ endmenu
menu "Debugging"
config COMPILE_LOGLEVEL
- int "loglevel"
+ int "compile loglevel"
default 6
help
This defines the maximum loglevel compiled into the binary. Less important
@@ -617,6 +624,22 @@ config COMPILE_LOGLEVEL
6 informational (info)
7 debug-level messages (debug)
+config DEFAULT_LOGLEVEL
+ int "default loglevel"
+ default 7
+ help
+ This defines the default runtime loglevel. It can be changed using the
+ global.loglevel variable. Available logelevels are:
+
+ 0 system is unusable (emerg)
+ 1 action must be taken immediately (alert)
+ 2 critical conditions (crit)
+ 3 error conditions (err)
+ 4 warning conditions (warn)
+ 5 normal but significant condition (notice)
+ 6 informational (info)
+ 7 debug-level messages (debug)
+
config DEBUG_INFO
bool
prompt "enable debug symbols"
diff --git a/common/Makefile b/common/Makefile
index 64eacc3047..9a9e3fe7d9 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -114,6 +114,26 @@ cmd_env_h = cat $< | (cd $(obj) && $(objtree)/scripts/bin2c default_environment)
$(obj)/barebox_default_env.h: $(obj)/barebox_default_env$(barebox_default_env_comp) FORCE
$(call if_changed,env_h)
+quiet_cmd_pwd_h = PWDH $@
+ifneq ($(CONFIG_PASSWORD_DEFAULT),"")
+PASSWD_FILE := $(shell cd $(srctree); find $(CONFIG_PASSWORD_DEFAULT) -type f)
+cmd_pwd_h = echo -n "const char default_passwd[] = \"" > $@; \
+ cat $< | tr -d '\n' >> $@; \
+ echo "\";" >> $@
+
+include/generated/passwd.h: $(PASSWD_FILE)
+ $(call if_changed,pwd_h)
+else
+cmd_pwd_h = echo "const char default_passwd[] = \"\";" > $@
+
+include/generated/passwd.h: FORCE
+ $(call if_changed,pwd_h)
+endif
+
+targets += include/generated/passwd.h
+
+$(obj)/password.o: include/generated/passwd.h
+
# dependencies on generated files need to be listed explicitly
$(obj)/version.o: include/generated/compile.h
diff --git a/common/binfmt.c b/common/binfmt.c
index 7dcf5d737d..f2ff624587 100644
--- a/common/binfmt.c
+++ b/common/binfmt.c
@@ -60,6 +60,9 @@ int execute_binfmt(int argc, char **argv)
if (strchr(argv[0], '/'))
return binfmt_run(argv[0], argc, argv);
+ if (find_cmd(argv[0]))
+ return execute_command(argc, &argv[0]);
+
path = find_execable(argv[0]);
if (path) {
ret = binfmt_run(path, argc, argv);
@@ -67,7 +70,7 @@ int execute_binfmt(int argc, char **argv)
return ret;
}
- return execute_command(argc, &argv[0]);
+ return -ENOENT;
}
int binfmt_register(struct binfmt_hook *b)
diff --git a/common/block.c b/common/block.c
index ab39a3622c..e522ee425a 100644
--- a/common/block.c
+++ b/common/block.c
@@ -25,6 +25,8 @@
#define BLOCKSIZE(blk) (1 << blk->blockbits)
+LIST_HEAD(block_device_list);
+
/* a chunk of contigous data */
struct chunk {
void *data; /* data buffer */
@@ -367,6 +369,8 @@ int blockdevice_register(struct block_device *blk)
if (ret)
return ret;
+ list_add_tail(&blk->list, &block_device_list);
+
return 0;
}
@@ -387,6 +391,7 @@ int blockdevice_unregister(struct block_device *blk)
}
devfs_remove(&blk->cdev);
+ list_del(&blk->list);
return 0;
}
diff --git a/common/bootm.c b/common/bootm.c
index 1987a09352..2da6e59129 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -16,6 +16,8 @@
#include <fs.h>
#include <malloc.h>
#include <memory.h>
+#include <globalvar.h>
+#include <init.h>
static LIST_HEAD(handler_list);
@@ -167,6 +169,7 @@ static int bootm_open_oftree(struct image_data *data, const char *oftree, int nu
data->of_root_node = of_unflatten_dtb(NULL, fdt);
if (!data->of_root_node) {
pr_err("unable to unflatten devicetree\n");
+ free(fdt);
return -EINVAL;
}
@@ -203,12 +206,55 @@ static void bootm_print_info(struct image_data *data)
}
}
-int bootm_boot(struct image_data *data)
+static char *bootm_image_name_and_no(const char *name, int *no)
{
+ char *at, *ret;
+
+ if (!name || !*name)
+ return NULL;
+
+ *no = 0;
+
+ ret = xstrdup(name);
+ at = strchr(ret, '@');
+ if (!at)
+ return ret;
+
+ *at++ = 0;
+
+ *no = simple_strtoul(at, NULL, 10);
+
+ return ret;
+}
+
+/*
+ * bootm_boot - Boot an application image described by bootm_data
+ */
+int bootm_boot(struct bootm_data *bootm_data)
+{
+ struct image_data *data;
struct image_handler *handler;
int ret;
enum filetype os_type, initrd_type = filetype_unknown;
+ if (!bootm_data->os_file) {
+ printf("no image given\n");
+ return -ENOENT;
+ }
+
+ data = xzalloc(sizeof(*data));
+
+ data->os_file = bootm_image_name_and_no(bootm_data->os_file, &data->os_num);
+ data->oftree_file = bootm_image_name_and_no(bootm_data->oftree_file, &data->oftree_num);
+ data->initrd_file = bootm_image_name_and_no(bootm_data->initrd_file, &data->initrd_num);
+ data->verbose = bootm_data->verbose;
+ data->verify = bootm_data->verify;
+ data->force = bootm_data->force;
+ data->dryrun = bootm_data->dryrun;
+ data->initrd_address = bootm_data->initrd_address;
+ data->os_address = bootm_data->os_address;
+ data->os_entry = bootm_data->os_entry;
+
os_type = file_name_detect_type(data->os_file);
if ((int)os_type < 0) {
printf("could not open %s: %s\n", data->os_file,
@@ -288,7 +334,10 @@ int bootm_boot(struct image_data *data)
printf("Passing control to %s handler\n", handler->name);
}
- ret = handler->bootm(data);
+ if (data->dryrun)
+ ret = 0;
+ else
+ ret = handler->bootm(data);
err_out:
if (data->os_res)
release_sdram_region(data->os_res);
@@ -298,6 +347,27 @@ err_out:
uimage_close(data->initrd);
if (data->os)
uimage_close(data->os);
+ if (data->of_root_node && data->of_root_node != of_get_root_node())
+ of_delete_node(data->of_root_node);
+
+ free(data->os_file);
+ free(data->oftree_file);
+ free(data->initrd_file);
+ free(data);
return ret;
}
+
+static int bootm_init(void)
+{
+ globalvar_add_simple("bootm.image", NULL);
+ globalvar_add_simple("bootm.image.loadaddr", NULL);
+ globalvar_add_simple("bootm.oftree", NULL);
+ if (IS_ENABLED(CONFIG_CMD_BOOTM_INITRD)) {
+ globalvar_add_simple("bootm.initrd", NULL);
+ globalvar_add_simple("bootm.initrd.loadaddr", NULL);
+ }
+
+ return 0;
+}
+late_initcall(bootm_init);
diff --git a/common/console.c b/common/console.c
index 6ca94e2a02..56bc864ad1 100644
--- a/common/console.c
+++ b/common/console.c
@@ -63,19 +63,21 @@ static int console_std_set(struct device_d *dev, struct param_d *param,
unsigned int flag = 0, i = 0;
if (val) {
- if (strchr(val, 'i') && cdev->f_caps & CONSOLE_STDIN) {
+ if (strchr(val, 'i') && cdev->getc) {
active[i++] = 'i';
flag |= CONSOLE_STDIN;
}
- if (strchr(val, 'o') && cdev->f_caps & CONSOLE_STDOUT) {
- active[i++] = 'o';
- flag |= CONSOLE_STDOUT;
- }
+ if (cdev->putc) {
+ if (strchr(val, 'o')) {
+ active[i++] = 'o';
+ flag |= CONSOLE_STDOUT;
+ }
- if (strchr(val, 'e') && cdev->f_caps & CONSOLE_STDERR) {
- active[i++] = 'e';
- flag |= CONSOLE_STDERR;
+ if (strchr(val, 'e')) {
+ active[i++] = 'e';
+ flag |= CONSOLE_STDERR;
+ }
}
}
@@ -236,6 +238,9 @@ int getc(void)
unsigned char ch;
uint64_t start;
+ if (unlikely(!console_is_input_allow()))
+ return -EPERM;
+
/*
* For 100us we read the characters from the serial driver
* into a kfifo. This helps us not to lose characters
@@ -270,6 +275,9 @@ EXPORT_SYMBOL(fgetc);
int tstc(void)
{
+ if (unlikely(!console_is_input_allow()))
+ return 0;
+
return kfifo_len(console_input_fifo) || tstc_raw();
}
EXPORT_SYMBOL(tstc);
diff --git a/common/console_common.c b/common/console_common.c
index 24aa63eea1..cc184dfaef 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -21,9 +21,69 @@
#include <common.h>
#include <fs.h>
#include <errno.h>
+#include <console.h>
+#include <init.h>
+#include <environment.h>
+#include <globalvar.h>
+#include <magicvar.h>
+#include <password.h>
#ifndef CONFIG_CONSOLE_NONE
+static int console_input_allow;
+
+static int console_global_init(void)
+{
+ if (IS_ENABLED(CONFIG_CMD_LOGIN) && is_passwd_enable())
+ console_input_allow = 0;
+ else
+ console_input_allow = 1;
+
+ globalvar_add_simple_bool("console.input_allow", &console_input_allow);
+
+ return 0;
+}
+late_initcall(console_global_init);
+
+BAREBOX_MAGICVAR_NAMED(global_console_input_allow, global.console.input_allow, "console input allowed");
+
+bool console_is_input_allow(void)
+{
+ return console_input_allow;
+}
+
+void console_allow_input(bool val)
+{
+ console_input_allow = val;
+}
+
+int barebox_loglevel = CONFIG_DEFAULT_LOGLEVEL;
+
+int pr_print(int level, const char *fmt, ...)
+{
+ va_list args;
+ uint i;
+ char printbuffer[CFG_PBSIZE];
+
+ if (level > barebox_loglevel)
+ return 0;
+
+ va_start(args, fmt);
+ i = vsprintf(printbuffer, fmt, args);
+ va_end(args);
+
+ /* Print the string */
+ puts(printbuffer);
+
+ return i;
+}
+
+static int loglevel_init(void)
+{
+ return globalvar_add_simple_int("loglevel", &barebox_loglevel, "%d");
+}
+device_initcall(loglevel_init);
+
int printf(const char *fmt, ...)
{
va_list args;
@@ -121,3 +181,25 @@ struct console_device *console_get_by_dev(struct device_d *dev)
return NULL;
}
EXPORT_SYMBOL(console_get_by_dev);
+
+/*
+ * @brief returns current used console device
+ *
+ * @return console device which is registered with CONSOLE_STDIN and
+ * CONSOLE_STDOUT
+ */
+struct console_device *console_get_first_active(void)
+{
+ struct console_device *cdev;
+ /*
+ * Assumption to have BOTH CONSOLE_STDIN AND STDOUT in the
+ * same output console
+ */
+ for_each_console(cdev) {
+ if ((cdev->f_active & (CONSOLE_STDIN | CONSOLE_STDOUT)))
+ return cdev;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(console_get_first_active);
diff --git a/common/console_simple.c b/common/console_simple.c
index 101064b69a..6cb72bb46a 100644
--- a/common/console_simple.c
+++ b/common/console_simple.c
@@ -3,6 +3,7 @@
#include <fs.h>
#include <errno.h>
#include <debug_ll.h>
+#include <console.h>
LIST_HEAD(console_list);
EXPORT_SYMBOL(console_list);
@@ -40,6 +41,9 @@ EXPORT_SYMBOL(console_putc);
int tstc(void)
{
+ if (unlikely(!console_is_input_allow()))
+ return 0;
+
if (!console)
return 0;
@@ -49,6 +53,9 @@ EXPORT_SYMBOL(tstc);
int getc(void)
{
+ if (unlikely(!console_is_input_allow()))
+ return -EPERM;
+
if (!console)
return -EINVAL;
return console->getc(console);
@@ -82,6 +89,13 @@ int console_register(struct console_device *newcdev)
console_list.prev = console_list.next = &newcdev->list;
newcdev->list.prev = newcdev->list.next = &console_list;
+ if (newcdev->setbrg) {
+ newcdev->baudrate = CONFIG_BAUDRATE;
+ newcdev->setbrg(newcdev, newcdev->baudrate);
+ }
+
+ newcdev->f_active = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
+
barebox_banner();
return 0;
diff --git a/common/env.c b/common/env.c
index 33a871f7eb..748b655a6b 100644
--- a/common/env.c
+++ b/common/env.c
@@ -267,13 +267,74 @@ void export_env_ull(const char *name, unsigned long long val)
}
EXPORT_SYMBOL(export_env_ull);
-unsigned long long getenv_ull(const char *name)
+/*
+ * Like regular getenv, but never returns an empty string.
+ * If the string is empty, NULL is returned instead
+ */
+const char *getenv_nonempty(const char *var)
{
- const char *valstr = getenv(name);
+ const char *val = getenv(var);
- if (!valstr)
- return 0;
+ if (val && *val)
+ return val;
- return simple_strtoull(valstr, NULL, 0);
+ return NULL;
+}
+EXPORT_SYMBOL(getenv_nonempty);
+
+int getenv_ull(const char *var , unsigned long long *val)
+{
+ const char *valstr = getenv(var);
+
+ if (!valstr || !*valstr)
+ return -EINVAL;
+
+ *val = simple_strtoull(valstr, NULL, 0);
+
+ return 0;
}
EXPORT_SYMBOL(getenv_ull);
+
+int getenv_ul(const char *var , unsigned long *val)
+{
+ const char *valstr = getenv(var);
+
+ if (!valstr || !*valstr)
+ return -EINVAL;
+
+ *val = simple_strtoul(valstr, NULL, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL(getenv_ul);
+
+int getenv_uint(const char *var , unsigned int *val)
+{
+ const char *valstr = getenv(var);
+
+ if (!valstr || !*valstr)
+ return -EINVAL;
+
+ *val = simple_strtoul(valstr, NULL, 0);
+
+ return 0;
+}
+EXPORT_SYMBOL(getenv_uint);
+
+int getenv_bool(const char *var, int *val)
+{
+ const char *valstr = getenv(var);
+
+ if (!valstr || !*valstr)
+ return -EINVAL;
+
+ if (!*valstr)
+ *val = false;
+ else if (*valstr == '0')
+ *val = false;
+ else
+ *val = true;
+
+ return 0;
+}
+EXPORT_SYMBOL(getenv_bool);
diff --git a/common/filetype.c b/common/filetype.c
index 7507d85de0..8cdf82741a 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -50,6 +50,7 @@ static const struct filetype_str filetype_str[] = {
[filetype_png] = { "PNG image", "png" },
[filetype_ext] = { "ext filesystem", "ext" },
[filetype_gpt] = { "GUID Partition Table", "gpt" },
+ [filetype_bpk] = { "Binary PacKage", "bpk" },
};
const char *file_type_to_string(enum filetype f)
@@ -220,6 +221,8 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
return filetype_png;
if (is_barebox_mips_head(_buf))
return filetype_mips_barebox;
+ if (buf[0] == be32_to_cpu(0x534F4659))
+ return filetype_bpk;
if (bufsize < 64)
return filetype_unknown;
diff --git a/common/globalvar.c b/common/globalvar.c
index edb66ddca6..41ce06e468 100644
--- a/common/globalvar.c
+++ b/common/globalvar.c
@@ -6,7 +6,7 @@
#include <magicvar.h>
#include <generated/utsrelease.h>
-static struct device_d global_device = {
+struct device_d global_device = {
.name = "global",
.id = DEVICE_ID_SINGLE,
};
@@ -72,6 +72,9 @@ int globalvar_add_simple(const char *name, const char *value)
if (ret && ret != -EEXIST)
return ret;
+ if (!value)
+ return 0;
+
return dev_set_param(&global_device, name, value);
}
diff --git a/common/hush.c b/common/hush.c
index a3235ba19f..bf1d9e6fd7 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -123,6 +123,7 @@
#include <linux/list.h>
#include <binfmt.h>
#include <init.h>
+#include <shell.h>
/*cmd_boot.c*/
extern int do_bootd(int flag, int argc, char *argv[]); /* do_bootd */
@@ -226,6 +227,11 @@ static char console_buffer[CONFIG_CBSIZE]; /* console I/O buffer */
* the first three support $?, $#, and $1 */
static unsigned int last_return_code;
+int shell_get_last_return_code(void)
+{
+ return last_return_code;
+}
+
/* "globals" within this file */
static uchar *ifs;
static char map[256];
diff --git a/common/parser.c b/common/parser.c
index 4d993dfd35..d390fb6afe 100644
--- a/common/parser.c
+++ b/common/parser.c
@@ -1,6 +1,15 @@
#include <common.h>
#include <command.h>
#include <environment.h>
+#include <shell.h>
+
+/*
+ * not yet supported
+ */
+int shell_get_last_return_code(void)
+{
+ return 0;
+}
static int parse_line (char *line, char *argv[])
{
diff --git a/common/password.c b/common/password.c
index d157a11b7b..9c1e54a359 100644
--- a/common/password.c
+++ b/common/password.c
@@ -25,6 +25,7 @@
#include <malloc.h>
#include <xfuncs.h>
#include <clock.h>
+#include <generated/passwd.h>
#if defined(CONFIG_PASSWD_SUM_MD5)
#define PASSWD_SUM "md5"
@@ -97,7 +98,13 @@ int password(unsigned char *passwd, size_t length, int flags, int timeout)
}
EXPORT_SYMBOL(password);
-int is_passwd_enable(void)
+int is_passwd_default_enable(void)
+{
+ return strlen(default_passwd) > 0;
+}
+EXPORT_SYMBOL(is_passwd_default_enable);
+
+int is_passwd_env_enable(void)
{
int fd;
@@ -110,13 +117,13 @@ int is_passwd_enable(void)
return 1;
}
-EXPORT_SYMBOL(is_passwd_enable);
+EXPORT_SYMBOL(is_passwd_env_enable);
-int passwd_disable(void)
+int passwd_env_disable(void)
{
return unlink(PASSWD_FILE);
}
-EXPORT_SYMBOL(passwd_disable);
+EXPORT_SYMBOL(passwd_env_disable);
static unsigned char to_digit(unsigned char c)
{
@@ -140,6 +147,43 @@ static unsigned char to_hexa(unsigned char c)
int read_passwd(unsigned char *sum, size_t length)
{
+ if (is_passwd_env_enable())
+ return read_env_passwd(sum, length);
+ else if (is_passwd_default_enable())
+ return read_default_passwd(sum, length);
+ else
+ return -EINVAL;
+}
+
+int read_default_passwd(unsigned char *sum, size_t length)
+{
+ int i = 0;
+ int len = strlen(default_passwd);
+ unsigned char *buf = (unsigned char *)default_passwd;
+ unsigned char c;
+
+ if (!sum || length < 1)
+ return -EINVAL;
+
+ for (i = 0; i < len && length > 0; i++) {
+ c = buf[i];
+ i++;
+
+ *sum = to_digit(c) << 4;
+
+ c = buf[i];
+
+ *sum |= to_digit(c);
+ sum++;
+ length--;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(read_default_passwd);
+
+int read_env_passwd(unsigned char *sum, size_t length)
+{
int fd;
int ret = 0;
unsigned char c;
@@ -178,9 +222,9 @@ exit:
return ret;
}
-EXPORT_SYMBOL(read_passwd);
+EXPORT_SYMBOL(read_env_passwd);
-int write_passwd(unsigned char *sum, size_t length)
+int write_env_passwd(unsigned char *sum, size_t length)
{
int fd;
unsigned char c;
@@ -227,9 +271,9 @@ exit:
return ret;
}
-EXPORT_SYMBOL(write_passwd);
+EXPORT_SYMBOL(write_env_passwd);
-int check_passwd(unsigned char* passwd, size_t length)
+static int __check_passwd(unsigned char* passwd, size_t length, int std)
{
struct digest *d;
unsigned char *passwd1_sum;
@@ -256,7 +300,10 @@ int check_passwd(unsigned char* passwd, size_t length)
d->final(d, passwd1_sum);
- ret = read_passwd(passwd2_sum, d->length);
+ if (std)
+ ret = read_env_passwd(passwd2_sum, d->length);
+ else
+ ret = read_default_passwd(passwd2_sum, d->length);
if (ret < 0)
goto err2;
@@ -271,9 +318,30 @@ err1:
return ret;
}
-EXPORT_SYMBOL(check_passwd);
-int set_passwd(unsigned char* passwd, size_t length)
+int check_default_passwd(unsigned char* passwd, size_t length)
+{
+ return __check_passwd(passwd, length, 0);
+}
+EXPORT_SYMBOL(check_default_passwd);
+
+int check_env_passwd(unsigned char* passwd, size_t length)
+{
+ return __check_passwd(passwd, length, 1);
+}
+EXPORT_SYMBOL(check_env_passwd);
+
+int check_passwd(unsigned char* passwd, size_t length)
+{
+ if (is_passwd_env_enable())
+ return check_env_passwd(passwd, length);
+ else if (is_passwd_default_enable())
+ return check_default_passwd(passwd, length);
+ else
+ return -EINVAL;
+}
+
+int set_env_passwd(unsigned char* passwd, size_t length)
{
struct digest *d;
unsigned char *passwd_sum;
@@ -292,10 +360,10 @@ int set_passwd(unsigned char* passwd, size_t length)
d->final(d, passwd_sum);
- ret = write_passwd(passwd_sum, d->length);
+ ret = write_env_passwd(passwd_sum, d->length);
free(passwd_sum);
return ret;
}
-EXPORT_SYMBOL(set_passwd);
+EXPORT_SYMBOL(set_env_passwd);
diff --git a/common/startup.c b/common/startup.c
index ece852cdd4..2e0a4ba3dc 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -138,6 +138,8 @@ void __noreturn start_barebox(void)
run_command("source /env/bin/init", 0);
} else {
pr_err("/env/bin/init not found\n");
+ if (IS_ENABLED(CONFIG_CMD_LOGIN))
+ while(run_command("login -t 0", 0));
}
}
diff --git a/defaultenv-2/base/bin/_boot b/defaultenv-2/base/bin/_boot
deleted file mode 100644
index 71d149082c..0000000000
--- a/defaultenv-2/base/bin/_boot
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-
-# The real boot script, to be called from _boot_list which is called
-# from boot
-
-. /env/data/ansi-colors
-
-# clear linux.bootargs.dyn.* and bootm.*
-global -r linux.bootargs.dyn.
-global -r bootm.
-
-file="$1"
-
-scr=/env/boot/$file
-if [ ! -f "$scr" ]; then
- scr="$file"
-fi
-
-if [ ! -f "$scr" ]; then
- echo -e "${RED}/env/boot/${file}${NC} or ${RED}${file}${NC} do not exist"
- _boot_help
- exit 2
-fi
-
-if [ -L $scr ]; then
- readlink -f $scr boot
- basename $boot link
- basename $scr boot
- echo -e "${GREEN}boot${NC} ${YELLOW}${boot}${NC} -> ${CYAN}${link}${NC}"
-else
- echo -e "${GREEN}booting ${YELLOW}$file${NC}..."
-fi
-
-$scr
-
-if [ -n "$BOOT_DRYRUN" ]; then
- echo "dryrun. exiting now"
- exit 0
-fi
-
-${global.bootm.image} $BOOT_BOOTM_OPTS
-bootm $BOOT_BOOTM_OPTS
-
-echo -e "${GREEN}booting ${YELLOW}$file${NC} ${RED}failed${NC}"
diff --git a/defaultenv-2/base/bin/_boot_help b/defaultenv-2/base/bin/_boot_help
deleted file mode 100644
index 5679e9121c..0000000000
--- a/defaultenv-2/base/bin/_boot_help
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-for i in /env/boot/*; do
- basename $i s
- sources="$sources$s "
-done
-
-if [ -d /env/boot.d ]; then
- seq_sources="boot sequence:"
- for i in /env/boot.d/*; do
- readlink -f $i s
- basename $s link
- basename $i s
- seq_sources="$seq_sources\n ${YELLOW}${s}${NC} -> ${CYAN}${link}${NC}"
- done
-else
- seq_sources="boot sequence:\n${GREEN}none${NC}"
-fi
-
-echo -e "boot sources:\n$sources\n\n$seq_sources"
diff --git a/defaultenv-2/base/bin/_boot_list b/defaultenv-2/base/bin/_boot_list
deleted file mode 100644
index 17f29bf9ce..0000000000
--- a/defaultenv-2/base/bin/_boot_list
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-# This script is a workaround for buggy globbing in for loops
-
-for i in $*; do
- _boot $i;
-done
diff --git a/defaultenv-2/base/bin/boot b/defaultenv-2/base/bin/boot
deleted file mode 100644
index eed4b3c8b7..0000000000
--- a/defaultenv-2/base/bin/boot
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/sh
-
-BOOT_BOOTM_OPTS=
-BOOT_DRYRUN=
-BOOT_VERBOSE=
-list=
-bootsrc=${global.boot.default}
-
-usage="
-$0 [OPTIONS] [source]\n
- -v verbose\n
- -d dryrun\n
- -l list boot sources\n
- -h help"
-
-. /env/data/ansi-colors
-
-while getopt "vdhl" opt; do
- if [ ${opt} = v ]; then
- BOOT_BOOTM_OPTS="$BOOT_BOOTM_OPTS -v"
- BOOT_VERBOSE=1
- elif [ ${opt} = d ]; then
- BOOT_DRYRUN=1
- elif [ ${opt} = l ]; then
- list=1
- elif [ ${opt} = h ]; then
- echo -e "$usage"
- exit 0
- fi
-done
-
-if [ -n "$list" ]; then
- echo "boot sources:"
- for i in /env/boot/*; do
- basename $i s
- echo $s
- done
- exit 0
-fi
-
-if [ -n "$1" ]; then
- bootsrc="$*"
-fi
-
-export BOOT_BOOTM_OPTS
-export BOOT_DRYRUN
-export BOOT_VERBOSE
-
-for src in $bootsrc; do
- if [ -d ${src} ]; then
- realsrc="$realsrc $src/*"
- else
- realsrc="$realsrc $src"
- fi
-done
-
-if [ -n "$BOOT_VERBOSE" ]; then
- echo -e "\nboot sequence:${YELLOW}$realsrc${NC}\n"
-fi
-
-for s in $realsrc; do
- _boot_list $s
-done
-
-exit $ret
diff --git a/defaultenv-2/base/bin/init b/defaultenv-2/base/bin/init
index ca02ba6427..d7bd0cb140 100644
--- a/defaultenv-2/base/bin/init
+++ b/defaultenv-2/base/bin/init
@@ -2,28 +2,45 @@
export PATH=/env/bin
-global hostname=generic
-global user=none
-global autoboot_timeout=3
-global boot.default=net
-global allow_color=true
+global hostname
+global user
+global autoboot_timeout
+global boot.default
+global allow_color
global linux.bootargs.base
#linux.bootargs.dyn.* will be cleared at the beginning of boot
global linux.bootargs.dyn.ip
global linux.bootargs.dyn.root
-global editcmd=sedit
+global editcmd
+
+[ -z "${global.hostname}" ] && global.hostname=generic
+[ -z "${global.user}" ] && global.user=none
+[ -z "${global.autoboot_timeout}" ] && global.autoboot_timeout=3
+[ -z "${global.boot.default}" ] && global.boot.default=net
+[ -z "${global.allow_color}" ] && global.allow_color=true
+[ -z "${global.editcmd}" ] && global.editcmd=sedit
[ -e /env/config-board ] && /env/config-board
/env/config
+# request password to login if a timeout is specified and password set
+if [ -n ${global.login.timeout} ]; then
+ [ ${global.login.timeout} -gt 0 ] && login_cmd=login
+fi
+# allow the input if not
+[ -n ${global.console.input_allow} ] && global.console.input_allow=1
+
# allow to stop the boot before execute the /env/init/*
# but without waiting
timeout -s -a -v key 0
if [ "${key}" = "q" ]; then
+ ${login_cmd}
exit
fi
+[ -n ${login_cmd} ] && global.console.input_allow=0
+
for i in /env/init/*; do
. $i
done
@@ -34,10 +51,15 @@ else
echo -e -n "\nHit any key to stop autoboot: "
fi
+[ -n ${login_cmd} ] && global.console.input_allow=1
+
timeout -a $global.autoboot_timeout -v key
autoboot="$?"
+[ -n ${login_cmd} ] && global.console.input_allow=0
+
if [ "${key}" = "q" ]; then
+ ${login_cmd}
exit
fi
@@ -46,9 +68,12 @@ if [ "$autoboot" = 0 ]; then
fi
if [ -e /env/menu ]; then
+ ${login_cmd}
if [ "${key}" != "m" ]; then
echo -e "\ntype exit to get to the menu"
sh
fi
/env/menu/mainmenu
fi
+
+${login_cmd}
diff --git a/drivers/ata/ide-sff.c b/drivers/ata/ide-sff.c
index 0e8b744e2e..a7f2647afd 100644
--- a/drivers/ata/ide-sff.c
+++ b/drivers/ata/ide-sff.c
@@ -298,6 +298,9 @@ static int __maybe_unused ide_write(struct ata_port *port,
rc = ata_wr_cmd(ide, ATA_CMD_WRITE);
if (rc != 0)
return rc;
+ rc = ata_wait_ready(ide, MAX_TIMEOUT);
+ if (rc != 0)
+ return rc;
ata_wr_sector(ide, buffer);
num_blocks--;
sector++;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 16b7f06c4a..80e0ea882f 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -26,6 +26,7 @@
#include <command.h>
#include <driver.h>
#include <malloc.h>
+#include <console.h>
#include <linux/ctype.h>
#include <errno.h>
#include <fs.h>
@@ -370,11 +371,14 @@ const char *dev_id(const struct device_d *dev)
return buf;
}
-int dev_printf(const struct device_d *dev, const char *format, ...)
+int dev_printf(int level, const struct device_d *dev, const char *format, ...)
{
va_list args;
int ret = 0;
+ if (level > barebox_loglevel)
+ return 0;
+
if (dev->driver && dev->driver->name)
ret += printf("%s ", dev->driver->name);
@@ -413,145 +417,3 @@ int dev_get_drvdata(struct device_d *dev, unsigned long *data)
return -ENODEV;
}
-
-#ifdef CONFIG_CMD_DEVINFO
-static int do_devinfo_subtree(struct device_d *dev, int depth)
-{
- struct device_d *child;
- struct cdev *cdev;
- int i;
-
- for (i = 0; i < depth; i++)
- printf(" ");
-
- printf("`---- %s", dev_name(dev));
- if (!list_empty(&dev->cdevs)) {
- printf("\n");
- list_for_each_entry(cdev, &dev->cdevs, devices_list) {
- for (i = 0; i < depth + 1; i++)
- printf(" ");
- printf("`---- 0x%08llx-0x%08llx: /dev/%s\n",
- cdev->offset,
- cdev->offset + cdev->size - 1,
- cdev->name);
- }
- } else {
- printf("\n");
- }
-
- if (!list_empty(&dev->children)) {
- device_for_each_child(dev, child) {
- do_devinfo_subtree(child, depth + 1);
- }
- }
-
- return 0;
-}
-
-static int do_devinfo(int argc, char *argv[])
-{
- struct device_d *dev;
- struct driver_d *drv;
- struct param_d *param;
- int i;
- struct resource *res;
-
- if (argc == 1) {
- printf("devices:\n");
-
- for_each_device(dev) {
- if (!dev->parent)
- do_devinfo_subtree(dev, 0);
- }
-
- printf("\ndrivers:\n");
- for_each_driver(drv)
- printf("%s\n",drv->name);
- } else {
- dev = get_device_by_name(argv[1]);
-
- if (!dev) {
- printf("no such device: %s\n",argv[1]);
- return -1;
- }
-
- printf("resources:\n");
- for (i = 0; i < dev->num_resources; i++) {
- res = &dev->resource[i];
- printf("num : %d\n", i);
- if (res->name)
- printf("name : %s\n", res->name);
- printf("start : " PRINTF_CONVERSION_RESOURCE "\nsize : "
- PRINTF_CONVERSION_RESOURCE "\n",
- res->start, resource_size(res));
- }
-
- printf("driver: %s\n", dev->driver ?
- dev->driver->name : "none");
-
- printf("bus: %s\n\n", dev->bus ?
- dev->bus->name : "none");
-
- if (dev->info)
- dev->info(dev);
-
- printf("%s\n", list_empty(&dev->parameters) ?
- "no parameters available" : "Parameters:");
-
- list_for_each_entry(param, &dev->parameters, list) {
- printf("%16s = %s", param->name, dev_get_param(dev, param->name));
- if (param->info)
- param->info(param);
- printf("\n");
- }
-#ifdef CONFIG_OFDEVICE
- if (dev->device_node) {
- printf("\ndevice node: %s\n", dev->device_node->full_name);
- of_print_nodes(dev->device_node, 0);
- }
-#endif
- }
-
- return 0;
-}
-
-BAREBOX_CMD_HELP_START(devinfo)
-BAREBOX_CMD_HELP_USAGE("devinfo [DEVICE]\n")
-BAREBOX_CMD_HELP_SHORT("Output device information.\n")
-BAREBOX_CMD_HELP_END
-
-/**
- * @page devinfo_command
-
-If called without arguments, devinfo shows a summary of the known
-devices and drivers.
-
-If called with a device path being the argument, devinfo shows more
-default information about this device and its parameters.
-
-Example from an MPC5200 based system:
-
-@verbatim
- barebox:/ devinfo /dev/eth0
- base : 0x1002b000
- size : 0x00000000
- driver: fec_mpc5xxx
-
- no info available for eth0
- Parameters:
- ipaddr = 192.168.23.197
- ethaddr = 80:81:82:83:84:86
- gateway = 192.168.23.1
- netmask = 255.255.255.0
- serverip = 192.168.23.2
-@endverbatim
- */
-
-BAREBOX_CMD_START(devinfo)
- .cmd = do_devinfo,
- .usage = "Show information about devices and drivers.",
- BAREBOX_CMD_HELP(cmd_devinfo_help)
- BAREBOX_CMD_COMPLETE(device_complete)
-BAREBOX_CMD_END
-#endif
-
diff --git a/drivers/clocksource/arm_smp_twd.c b/drivers/clocksource/arm_smp_twd.c
index 746d566441..3efe8ddff4 100644
--- a/drivers/clocksource/arm_smp_twd.c
+++ b/drivers/clocksource/arm_smp_twd.c
@@ -89,9 +89,18 @@ static int smp_twd_probe(struct device_d *dev)
return 0;
}
+static __maybe_unused struct of_device_id smp_twd_compatible[] = {
+ {
+ .compatible = "arm,cortex-a9-twd-timer",
+ }, {
+ /* sentinel */
+ }
+};
+
static struct driver_d smp_twd_driver = {
.name = "smp_twd",
.probe = smp_twd_probe,
+ .of_compatible = DRV_OF_COMPAT(smp_twd_compatible),
};
static int smp_twd_init(void)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index d5ac532f7d..18d3135eb8 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -54,6 +54,12 @@ config GPIO_TEGRA
help
Say yes here to include the driver for the GPIO controller found on the
Tegra line of SoCs.
+
+config GPIO_DESIGNWARE
+ tristate "Synopsys DesignWare GPIO driver"
+ help
+ Say Y or M here to build support for the Synopsys DesignWare APB
+ GPIO block.
endmenu
endif
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index adb668f4e5..dc9fb13d29 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_GPIO_ORION) += gpio-orion.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o
+obj-$(CONFIG_GPIO_DESIGNWARE) += gpio-dw.o
diff --git a/drivers/gpio/gpio-dw.c b/drivers/gpio/gpio-dw.c
new file mode 100644
index 0000000000..791488a19d
--- /dev/null
+++ b/drivers/gpio/gpio-dw.c
@@ -0,0 +1,159 @@
+/*
+ * Designware GPIO support functions
+ *
+ * Copyright (C) 2012 Altera
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <gpio.h>
+#include <init.h>
+
+#define DW_GPIO_DR 0x0
+#define DW_GPIO_DDR 0x4
+#define DW_GPIO_EXT 0x50
+#define DW_GPIO_CONFIG2 0x70
+#define DW_GPIO_CONFIG1 0x74
+
+#define DW_GPIO_CONFIG2_WIDTH(val, port) (((val) >> ((port) * 4) & 0x1f) + 1)
+#define DW_GPIO_CONFIG1_NPORTS(val) (((val) >> 2 & 0x3) + 1)
+
+struct dw_gpio_instance {
+ struct gpio_chip chip;
+ u32 gpio_state; /* GPIO state shadow register */
+ u32 gpio_dir; /* GPIO direction shadow register */
+ void __iomem *regs;
+};
+
+static inline struct dw_gpio_instance *to_dw_gpio(struct gpio_chip *gc)
+{
+ return container_of(gc, struct dw_gpio_instance, chip);
+}
+
+static int dw_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+ struct dw_gpio_instance *chip = to_dw_gpio(gc);
+
+ return (readl(chip->regs + DW_GPIO_EXT) >> offset) & 1;
+}
+
+static void dw_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+ struct dw_gpio_instance *chip = to_dw_gpio(gc);
+ u32 data_reg;
+
+ data_reg = readl(chip->regs + DW_GPIO_DR);
+ data_reg = (data_reg & ~(1<<offset)) | (value << offset);
+ writel(data_reg, chip->regs + DW_GPIO_DR);
+}
+
+static int dw_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+ struct dw_gpio_instance *chip = to_dw_gpio(gc);
+ u32 gpio_ddr;
+
+ /* Set pin as input, assumes software controlled IP */
+ gpio_ddr = readl(chip->regs + DW_GPIO_DDR);
+ gpio_ddr &= ~(1 << offset);
+ writel(gpio_ddr, chip->regs + DW_GPIO_DDR);
+
+ return 0;
+}
+
+static int dw_gpio_direction_output(struct gpio_chip *gc,
+ unsigned offset, int value)
+{
+ struct dw_gpio_instance *chip = to_dw_gpio(gc);
+ u32 gpio_ddr;
+
+ dw_gpio_set(gc, offset, value);
+
+ /* Set pin as output, assumes software controlled IP */
+ gpio_ddr = readl(chip->regs + DW_GPIO_DDR);
+ gpio_ddr |= (1 << offset);
+ writel(gpio_ddr, chip->regs + DW_GPIO_DDR);
+
+ return 0;
+}
+
+static struct gpio_ops imx_gpio_ops = {
+ .direction_input = dw_gpio_direction_input,
+ .direction_output = dw_gpio_direction_output,
+ .get = dw_gpio_get,
+ .set = dw_gpio_set,
+};
+
+static int dw_gpio_probe(struct device_d *dev)
+{
+ struct dw_gpio_instance *chip;
+ uint32_t config1, config2;
+ int ngpio, ret;
+
+ chip = xzalloc(sizeof(*chip));
+ chip->regs = dev_request_mem_region(dev, 0);
+ if (!chip->regs)
+ return -EBUSY;
+
+ chip->chip.ops = &imx_gpio_ops;
+ if (dev->id < 0) {
+ chip->chip.base = of_alias_get_id(dev->device_node, "gpio");
+ if (chip->chip.base < 0)
+ return chip->chip.base;
+ chip->chip.base *= 32;
+ } else {
+ chip->chip.base = dev->id * 32;
+ }
+
+ config2 = readl(chip->regs + DW_GPIO_CONFIG2);
+ config1 = readl(chip->regs + DW_GPIO_CONFIG1);
+ ngpio = DW_GPIO_CONFIG2_WIDTH(config2, 0);
+
+ if (DW_GPIO_CONFIG1_NPORTS(config1) > 1)
+ dev_info(dev, "ignoring ports B-D\n");
+
+ chip->chip.ngpio = ngpio;
+ chip->chip.dev = dev;
+
+ ret = gpiochip_add(&chip->chip);
+ if (ret)
+ return ret;
+
+ dev_dbg(dev, "probed gpiochip with %d gpios, base %d\n",
+ chip->chip.ngpio, chip->chip.base);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id dwgpio_match[] = {
+ {
+ .compatible = "snps,dw-apb-gpio",
+ }, {
+ /* sentinel */
+ },
+};
+
+static struct driver_d dwgpio_driver = {
+ .name = "dw-apb-gpio",
+ .probe = dw_gpio_probe,
+ .of_compatible = DRV_OF_COMPAT(dwgpio_match),
+};
+
+static int __init dwgpio_init(void)
+{
+ return platform_driver_register(&dwgpio_driver);
+}
+core_initcall(dwgpio_init);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 2eb5133494..147c753f56 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -131,29 +131,41 @@
#define SYSC_IDLEMODE_SMART 0x2
#define SYSC_CLOCKACTIVITY_FCLK 0x2
+/* Errata definitions */
+#define I2C_OMAP_ERRATA_I207 (1 << 0)
+#define I2C_OMAP_ERRATA_I462 (1 << 1)
+
/* i2c driver flags from kernel */
-#define OMAP_I2C_FLAG_RESET_REGS_POSTIDLE BIT(3)
+#define OMAP_I2C_FLAG_NO_FIFO BIT(0)
+#define OMAP_I2C_FLAG_16BIT_DATA_REG BIT(2)
#define OMAP_I2C_FLAG_BUS_SHIFT_NONE 0
#define OMAP_I2C_FLAG_BUS_SHIFT_1 BIT(7)
#define OMAP_I2C_FLAG_BUS_SHIFT_2 BIT(8)
#define OMAP_I2C_FLAG_BUS_SHIFT__SHIFT 7
+/* timeout waiting for the controller to respond */
+#define OMAP_I2C_TIMEOUT (1000 * MSECOND) /* ms */
+
struct omap_i2c_struct {
void *base;
u8 reg_shift;
struct omap_i2c_driver_data *data;
struct resource *ioarea;
u32 speed; /* Speed of bus in Khz */
+ u16 scheme;
u16 cmd_err;
u8 *buf;
+ u8 *regs;
size_t buf_len;
struct i2c_adapter adapter;
+ u8 threshold;
u8 fifo_size; /* use as flag and value
* fifo_size==0 implies no fifo
* if set, should be trsh+1
*/
- u8 rev;
+ u32 rev;
unsigned b_hw:1; /* bad h/w fixes */
+ unsigned receiver:1; /* true for receiver mode */
u16 iestate; /* Saved interrupt register */
u16 pscstate;
u16 scllstate;
@@ -161,6 +173,7 @@ struct omap_i2c_struct {
u16 bufstate;
u16 syscstate;
u16 westate;
+ u16 errata;
};
#define to_omap_i2c_struct(a) container_of(a, struct omap_i2c_struct, adapter)
@@ -183,14 +196,15 @@ enum {
OMAP_I2C_SCLH_REG,
OMAP_I2C_SYSTEST_REG,
OMAP_I2C_BUFSTAT_REG,
- OMAP_I2C_REVNB_LO,
- OMAP_I2C_REVNB_HI,
- OMAP_I2C_IRQSTATUS_RAW,
- OMAP_I2C_IRQENABLE_SET,
- OMAP_I2C_IRQENABLE_CLR,
+ /* only on OMAP4430 */
+ OMAP_I2C_IP_V2_REVNB_LO,
+ OMAP_I2C_IP_V2_REVNB_HI,
+ OMAP_I2C_IP_V2_IRQSTATUS_RAW,
+ OMAP_I2C_IP_V2_IRQENABLE_SET,
+ OMAP_I2C_IP_V2_IRQENABLE_CLR,
};
-static const u8 reg_map[] = {
+static const u8 reg_map_ip_v1[] = {
[OMAP_I2C_REV_REG] = 0x00,
[OMAP_I2C_IE_REG] = 0x01,
[OMAP_I2C_STAT_REG] = 0x02,
@@ -211,7 +225,7 @@ static const u8 reg_map[] = {
[OMAP_I2C_BUFSTAT_REG] = 0x10,
};
-static const u8 omap4_reg_map[] = {
+static const u8 reg_map_ip_v2[] = {
[OMAP_I2C_REV_REG] = 0x04,
[OMAP_I2C_IE_REG] = 0x2c,
[OMAP_I2C_STAT_REG] = 0x28,
@@ -230,92 +244,104 @@ static const u8 omap4_reg_map[] = {
[OMAP_I2C_SCLH_REG] = 0xb8,
[OMAP_I2C_SYSTEST_REG] = 0xbc,
[OMAP_I2C_BUFSTAT_REG] = 0xc0,
- [OMAP_I2C_REVNB_LO] = 0x00,
- [OMAP_I2C_REVNB_HI] = 0x04,
- [OMAP_I2C_IRQSTATUS_RAW] = 0x24,
- [OMAP_I2C_IRQENABLE_SET] = 0x2c,
- [OMAP_I2C_IRQENABLE_CLR] = 0x30,
+ [OMAP_I2C_IP_V2_REVNB_LO] = 0x00,
+ [OMAP_I2C_IP_V2_REVNB_HI] = 0x04,
+ [OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24,
+ [OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c,
+ [OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30,
};
struct omap_i2c_driver_data {
u32 flags;
u32 fclk_rate;
- u8 *regs;
};
static struct omap_i2c_driver_data omap3_data = {
- .flags = OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
- OMAP_I2C_FLAG_BUS_SHIFT_2,
+ .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
.fclk_rate = 96000,
- .regs = (u8 *) reg_map,
};
static struct omap_i2c_driver_data omap4_data = {
.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
.fclk_rate = 96000,
- .regs = (u8 *) omap4_reg_map,
};
static struct omap_i2c_driver_data am33xx_data = {
- .flags = OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
- OMAP_I2C_FLAG_BUS_SHIFT_NONE,
+ .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
.fclk_rate = 48000,
- .regs = (u8 *) omap4_reg_map,
};
static inline void omap_i2c_write_reg(struct omap_i2c_struct *i2c_omap,
int reg, u16 val)
{
__raw_writew(val, i2c_omap->base +
- (i2c_omap->data->regs[reg] << i2c_omap->reg_shift));
+ (i2c_omap->regs[reg] << i2c_omap->reg_shift));
}
static inline u16 omap_i2c_read_reg(struct omap_i2c_struct *i2c_omap, int reg)
{
return __raw_readw(i2c_omap->base +
- (i2c_omap->data->regs[reg] << i2c_omap->reg_shift));
+ (i2c_omap->regs[reg] << i2c_omap->reg_shift));
}
-static void omap_i2c_unidle(struct omap_i2c_struct *i2c_omap)
+static void __omap_i2c_init(struct omap_i2c_struct *dev)
{
- struct omap_i2c_driver_data *i2c_data = i2c_omap->data;
- if (i2c_data->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG, 0);
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_PSC_REG, i2c_omap->pscstate);
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_SCLL_REG, i2c_omap->scllstate);
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_SCLH_REG, i2c_omap->sclhstate);
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_BUF_REG, i2c_omap->bufstate);
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSC_REG, i2c_omap->syscstate);
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_WE_REG, i2c_omap->westate);
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
- }
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+
+ /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
+ omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
+
+ /* SCL low and high time values */
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
+ omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate);
+ if (dev->rev >= OMAP_I2C_REV_ON_3430_3530)
+ omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+
+ /* Take the I2C module out of reset: */
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/*
* Don't write to this register if the IE state is 0 as it can
* cause deadlock.
*/
- if (i2c_omap->iestate)
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_IE_REG, i2c_omap->iestate);
+ if (dev->iestate)
+ omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
}
-static void omap_i2c_idle(struct omap_i2c_struct *i2c_omap)
+static int omap_i2c_reset(struct omap_i2c_struct *dev)
{
- u16 iv;
+ uint64_t start;
+ u16 sysc;
- i2c_omap->iestate = omap_i2c_read_reg(i2c_omap, OMAP_I2C_IE_REG);
+ if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
+ sysc = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG);
- /* Barebox driver don't need to clear interrupts here */
+ /* Disable I2C controller before soft reset */
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+ omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
+ ~(OMAP_I2C_CON_EN));
- /* omap_i2c_write_reg(i2c_omap, OMAP_I2C_IE_REG, 0); */
- if (i2c_omap->rev < OMAP_I2C_REV_2) {
- iv = omap_i2c_read_reg(i2c_omap, OMAP_I2C_IV_REG); /* Read clears */
- } else {
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_STAT_REG, i2c_omap->iestate);
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
+ /* For some reason we need to set the EN bit before the
+ * reset done bit gets set. */
+ omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+ start = get_time_ns();
+ while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
+ SYSS_RESETDONE_MASK)) {
+ if (is_timeout(start, OMAP_I2C_TIMEOUT)) {
+ dev_warn(&dev->adapter.dev, "timeout waiting "
+ "for controller reset\n");
+ return -ETIMEDOUT;
+ }
+ mdelay(1000);
+ }
+
+ /* SYSC register is cleared by the reset; rewrite it */
+ omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, sysc);
- /* Flush posted write before the i2c_omap->idle store occurs */
- omap_i2c_read_reg(i2c_omap, OMAP_I2C_STAT_REG);
}
+ return 0;
}
static int omap_i2c_init(struct omap_i2c_struct *i2c_omap)
@@ -326,7 +352,7 @@ static int omap_i2c_init(struct omap_i2c_struct *i2c_omap)
unsigned long internal_clk = 0;
struct omap_i2c_driver_data *i2c_data = i2c_omap->data;
- if (i2c_omap->rev >= OMAP_I2C_REV_2) {
+ if (i2c_omap->rev >= OMAP_I2C_OMAP1_REV_2) {
/* Disable I2C controller before soft reset */
omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG,
omap_i2c_read_reg(i2c_omap, OMAP_I2C_CON_REG) &
@@ -354,7 +380,7 @@ static int omap_i2c_init(struct omap_i2c_struct *i2c_omap)
omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSC_REG,
SYSC_AUTOIDLE_MASK);
- } else if (i2c_omap->rev >= OMAP_I2C_REV_ON_3430) {
+ } else if (i2c_omap->rev >= OMAP_I2C_REV_ON_3430_3530) {
i2c_omap->syscstate = SYSC_AUTOIDLE_MASK;
i2c_omap->syscstate |= SYSC_ENAWAKEUP_MASK;
i2c_omap->syscstate |= (SYSC_IDLEMODE_SMART <<
@@ -443,12 +469,14 @@ static int omap_i2c_init(struct omap_i2c_struct *i2c_omap)
OMAP_I2C_IE_AL) | ((i2c_omap->fifo_size) ?
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
omap_i2c_write_reg(i2c_omap, OMAP_I2C_IE_REG, i2c_omap->iestate);
- if (i2c_data->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) {
- i2c_omap->pscstate = psc;
- i2c_omap->scllstate = scll;
- i2c_omap->sclhstate = sclh;
- i2c_omap->bufstate = buf;
- }
+
+ i2c_omap->pscstate = psc;
+ i2c_omap->scllstate = scll;
+ i2c_omap->sclhstate = sclh;
+ i2c_omap->bufstate = buf;
+
+ __omap_i2c_init(i2c_omap);
+
return 0;
}
@@ -472,151 +500,301 @@ static int omap_i2c_wait_for_bb(struct i2c_adapter *adapter)
}
static inline void
+omap_i2c_complete_cmd(struct omap_i2c_struct *dev, u16 err)
+{
+ dev->cmd_err |= err;
+}
+
+static inline void
omap_i2c_ack_stat(struct omap_i2c_struct *i2c_omap, u16 stat)
{
omap_i2c_write_reg(i2c_omap, OMAP_I2C_STAT_REG, stat);
}
+static int errata_omap3_i462(struct omap_i2c_struct *dev)
+{
+ unsigned long timeout = 10000;
+ u16 stat;
+
+ do {
+ stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+ if (stat & OMAP_I2C_STAT_XUDF)
+ break;
+
+ if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
+ omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_XRDY |
+ OMAP_I2C_STAT_XDR));
+ if (stat & OMAP_I2C_STAT_NACK) {
+ dev->cmd_err |= OMAP_I2C_STAT_NACK;
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+ }
+
+ if (stat & OMAP_I2C_STAT_AL) {
+ dev_err(&dev->adapter.dev, "Arbitration lost\n");
+ dev->cmd_err |= OMAP_I2C_STAT_AL;
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
+ }
+
+ return -EIO;
+ }
+ } while (--timeout);
+
+ if (!timeout) {
+ dev_err(&dev->adapter.dev, "timeout waiting on XUDF bit\n");
+ return 0;
+ }
+
+ return 0;
+}
+
+static void omap_i2c_receive_data(struct omap_i2c_struct *dev, u8 num_bytes,
+ bool is_rdr)
+{
+ u16 w;
+
+ while (num_bytes--) {
+ w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+ *dev->buf++ = w;
+ dev->buf_len--;
+
+ /*
+ * Data reg in 2430, omap3 and
+ * omap4 is 8 bit wide
+ */
+ if (dev->data->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
+ *dev->buf++ = w >> 8;
+ dev->buf_len--;
+ }
+ }
+}
+
+static inline void i2c_omap_errata_i207(struct omap_i2c_struct *dev, u16 stat)
+{
+ /*
+ * I2C Errata(Errata Nos. OMAP2: 1.67, OMAP3: 1.8)
+ * Not applicable for OMAP4.
+ * Under certain rare conditions, RDR could be set again
+ * when the bus is busy, then ignore the interrupt and
+ * clear the interrupt.
+ */
+ if (stat & OMAP_I2C_STAT_RDR) {
+ /* Step 1: If RDR is set, clear it */
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
+
+ /* Step 2: */
+ if (!(omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG)
+ & OMAP_I2C_STAT_BB)) {
+
+ /* Step 3: */
+ if (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG)
+ & OMAP_I2C_STAT_RDR) {
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
+ dev_dbg(&dev->adapter.dev, "RDR when bus is busy.\n");
+ }
+
+ }
+ }
+}
+
+static int omap_i2c_transmit_data(struct omap_i2c_struct *dev, u8 num_bytes,
+ bool is_xdr)
+{
+ u16 w;
+
+ while (num_bytes--) {
+ w = *dev->buf++;
+ dev->buf_len--;
+
+ /*
+ * Data reg in 2430, omap3 and
+ * omap4 is 8 bit wide
+ */
+ if (dev->data->flags & OMAP_I2C_FLAG_16BIT_DATA_REG) {
+ w |= *dev->buf++ << 8;
+ dev->buf_len--;
+ }
+
+ if (dev->errata & I2C_OMAP_ERRATA_I462) {
+ int ret;
+
+ ret = errata_omap3_i462(dev);
+ if (ret < 0)
+ return ret;
+ }
+
+ omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+ }
+
+ return 0;
+}
+
static int
omap_i2c_isr(struct omap_i2c_struct *dev)
{
u16 bits;
- u16 stat, w;
- int err, count = 0;
+ u16 stat;
+ int err = 0, count = 0;
+
+ do {
+ bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+ stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
+ stat &= bits;
+
+ /* If we're in receiver mode, ignore XDR/XRDY */
+ if (dev->receiver)
+ stat &= ~(OMAP_I2C_STAT_XDR | OMAP_I2C_STAT_XRDY);
+ else
+ stat &= ~(OMAP_I2C_STAT_RDR | OMAP_I2C_STAT_RRDY);
+
+ if (!stat) {
+ /* my work here is done */
+ goto out;
+ }
- bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
- while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
dev_dbg(&dev->adapter.dev, "IRQ (ISR = 0x%04x)\n", stat);
if (count++ == 100) {
dev_warn(&dev->adapter.dev, "Too much work in one IRQ\n");
break;
}
- err = 0;
-complete:
- /*
- * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be
- * acked after the data operation is complete.
- * Ref: TRM SWPU114Q Figure 18-31
- */
- omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat &
- ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
- OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
-
if (stat & OMAP_I2C_STAT_NACK) {
err |= OMAP_I2C_STAT_NACK;
- omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
- OMAP_I2C_CON_STP);
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+ break;
}
+
if (stat & OMAP_I2C_STAT_AL) {
dev_err(&dev->adapter.dev, "Arbitration lost\n");
err |= OMAP_I2C_STAT_AL;
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
+ break;
}
+
+ /*
+ * ProDB0017052: Clear ARDY bit twice
+ */
if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK |
OMAP_I2C_STAT_AL)) {
- omap_i2c_ack_stat(dev, stat &
- (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR |
- OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
- return 0;
+ omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY |
+ OMAP_I2C_STAT_RDR |
+ OMAP_I2C_STAT_XRDY |
+ OMAP_I2C_STAT_XDR |
+ OMAP_I2C_STAT_ARDY));
+ break;
}
- if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) {
+
+ if (stat & OMAP_I2C_STAT_RDR) {
u8 num_bytes = 1;
- if (dev->fifo_size) {
- if (stat & OMAP_I2C_STAT_RRDY)
- num_bytes = dev->fifo_size;
- else /* read RXSTAT on RDR interrupt */
- num_bytes = (omap_i2c_read_reg(dev,
- OMAP_I2C_BUFSTAT_REG)
- >> 8) & 0x3F;
- }
- while (num_bytes) {
- num_bytes--;
- w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
- if (dev->buf_len) {
- *dev->buf++ = w;
- dev->buf_len--;
- } else {
- if (stat & OMAP_I2C_STAT_RRDY)
- dev_err(&dev->adapter.dev,
- "RRDY IRQ while no data"
- " requested\n");
- if (stat & OMAP_I2C_STAT_RDR)
- dev_err(&dev->adapter.dev,
- "RDR IRQ while no data"
- " requested\n");
- break;
- }
- }
- omap_i2c_ack_stat(dev,
- stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR));
+
+ if (dev->fifo_size)
+ num_bytes = dev->buf_len;
+
+ omap_i2c_receive_data(dev, num_bytes, true);
+
+ if (dev->errata & I2C_OMAP_ERRATA_I207)
+ i2c_omap_errata_i207(dev, stat);
+
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
continue;
}
- if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) {
+
+ if (stat & OMAP_I2C_STAT_RRDY) {
u8 num_bytes = 1;
- if (dev->fifo_size) {
- if (stat & OMAP_I2C_STAT_XRDY)
- num_bytes = dev->fifo_size;
- else /* read TXSTAT on XDR interrupt */
- num_bytes = omap_i2c_read_reg(dev,
- OMAP_I2C_BUFSTAT_REG)
- & 0x3F;
- }
- while (num_bytes) {
- num_bytes--;
- w = 0;
- if (dev->buf_len) {
- w = *dev->buf++;
- dev->buf_len--;
- } else {
- if (stat & OMAP_I2C_STAT_XRDY)
- dev_err(&dev->adapter.dev,
- "XRDY IRQ while no "
- "data to send\n");
- if (stat & OMAP_I2C_STAT_XDR)
- dev_err(&dev->adapter.dev,
- "XDR IRQ while no "
- "data to send\n");
- break;
- }
-
- /*
- * OMAP3430 Errata 1.153: When an XRDY/XDR
- * is hit, wait for XUDF before writing data
- * to DATA_REG. Otherwise some data bytes can
- * be lost while transferring them from the
- * memory to the I2C interface.
- */
-
- if (dev->rev <= OMAP_I2C_REV_ON_3430) {
- while (!(stat & OMAP_I2C_STAT_XUDF)) {
- if (stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
- omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
- err |= OMAP_I2C_STAT_XUDF;
- goto complete;
- }
- stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
- }
- }
-
- omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
- }
- omap_i2c_ack_stat(dev,
- stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR));
+
+ if (dev->threshold)
+ num_bytes = dev->threshold;
+
+ omap_i2c_receive_data(dev, num_bytes, false);
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+ continue;
+ }
+
+ if (stat & OMAP_I2C_STAT_XDR) {
+ u8 num_bytes = 1;
+ int ret;
+
+ if (dev->fifo_size)
+ num_bytes = dev->buf_len;
+
+ ret = omap_i2c_transmit_data(dev, num_bytes, true);
+ if (ret < 0)
+ break;
+
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR);
continue;
}
+
+ if (stat & OMAP_I2C_STAT_XRDY) {
+ u8 num_bytes = 1;
+ int ret;
+
+ if (dev->threshold)
+ num_bytes = dev->threshold;
+
+ ret = omap_i2c_transmit_data(dev, num_bytes, false);
+ if (ret < 0)
+ break;
+
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+ continue;
+ }
+
if (stat & OMAP_I2C_STAT_ROVR) {
dev_err(&dev->adapter.dev, "Receive overrun\n");
- dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+ err |= OMAP_I2C_STAT_ROVR;
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ROVR);
+ break;
}
+
if (stat & OMAP_I2C_STAT_XUDF) {
dev_err(&dev->adapter.dev, "Transmit underflow\n");
- dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+ err |= OMAP_I2C_STAT_XUDF;
+ omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XUDF);
+ break;
}
- }
+ } while (stat);
+ omap_i2c_complete_cmd(dev, err);
+ return 0;
+
+out:
return -EBUSY;
}
+static void omap_i2c_resize_fifo(struct omap_i2c_struct *dev, u8 size,
+ bool is_rx)
+{
+ u16 buf;
+
+ if (dev->data->flags & OMAP_I2C_FLAG_NO_FIFO)
+ return;
+
+ /*
+ * Set up notification threshold based on message size. We're doing
+ * this to try and avoid draining feature as much as possible. Whenever
+ * we have big messages to transfer (bigger than our total fifo size)
+ * then we might use draining feature to transfer the remaining bytes.
+ */
+
+ dev->threshold = clamp(size, (u8) 1, dev->fifo_size);
+
+ buf = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG);
+
+ if (is_rx) {
+ /* Clear RX Threshold */
+ buf &= ~(0x3f << 8);
+ buf |= ((dev->threshold - 1) << 8) | OMAP_I2C_BUF_RXFIF_CLR;
+ } else {
+ /* Clear TX Threshold */
+ buf &= ~0x3f;
+ buf |= (dev->threshold - 1) | OMAP_I2C_BUF_TXFIF_CLR;
+ }
+
+ omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
+
+ if (dev->rev < OMAP_I2C_REV_ON_3630)
+ dev->b_hw = 1; /* Enable hardware fixes */
+}
/*
* Low level master read/write transaction.
@@ -637,12 +815,18 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adapter,
if (msg->len == 0)
return -EINVAL;
+ i2c_omap->receiver = !!(msg->flags & I2C_M_RD);
+ omap_i2c_resize_fifo(i2c_omap, msg->len, i2c_omap->receiver);
+
omap_i2c_write_reg(i2c_omap, OMAP_I2C_SA_REG, msg->addr);
/* REVISIT: Could the STB bit of I2C_CON be used with probing? */
i2c_omap->buf = msg->buf;
i2c_omap->buf_len = msg->len;
+ /* make sure writes to dev->buf_len are ordered */
+ barrier();
+
omap_i2c_write_reg(i2c_omap, OMAP_I2C_CNT_REG, i2c_omap->buf_len);
/* Clear the FIFO Buffers */
@@ -658,6 +842,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adapter,
if (i2c_omap->speed > 400)
w |= OMAP_I2C_CON_OPMODE_HS;
+ if (msg->flags & I2C_M_STOP)
+ stop = 1;
if (msg->flags & I2C_M_TEN)
w |= OMAP_I2C_CON_XA;
if (!(msg->flags & I2C_M_RD))
@@ -698,38 +884,64 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adapter,
ret = omap_i2c_isr(i2c_omap);
while (ret){
ret = omap_i2c_isr(i2c_omap);
- if (is_timeout(start, 50 * MSECOND)) {
+ if (is_timeout(start, OMAP_I2C_TIMEOUT)) {
dev_err(&adapter->dev,
"timed out on polling for "
"open i2c message handling\n");
+ omap_i2c_reset(i2c_omap);
+ __omap_i2c_init(i2c_omap);
return -ETIMEDOUT;
}
}
- i2c_omap->buf_len = 0;
if (likely(!i2c_omap->cmd_err))
return 0;
/* We have an error */
if (i2c_omap->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
OMAP_I2C_STAT_XUDF)) {
- omap_i2c_init(i2c_omap);
+ omap_i2c_reset(i2c_omap);
+ __omap_i2c_init(i2c_omap);
return -EIO;
}
if (i2c_omap->cmd_err & OMAP_I2C_STAT_NACK) {
if (msg->flags & I2C_M_IGNORE_NAK)
return 0;
- if (stop) {
- w = omap_i2c_read_reg(i2c_omap, OMAP_I2C_CON_REG);
- w |= OMAP_I2C_CON_STP;
- omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG, w);
- }
+
+ w = omap_i2c_read_reg(i2c_omap, OMAP_I2C_CON_REG);
+ w |= OMAP_I2C_CON_STP;
+ omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG, w);
return -EREMOTEIO;
}
return -EIO;
}
+static void omap_i2c_unidle(struct omap_i2c_struct *i2c_omap)
+{
+ __omap_i2c_init(i2c_omap);
+}
+
+static void omap_i2c_idle(struct omap_i2c_struct *i2c_omap)
+{
+ u16 iv;
+
+ i2c_omap->iestate = omap_i2c_read_reg(i2c_omap, OMAP_I2C_IE_REG);
+
+ /* Barebox driver don't need to clear interrupts here */
+
+ /* omap_i2c_write_reg(i2c_omap, OMAP_I2C_IE_REG, 0); */
+ if (i2c_omap->rev < OMAP_I2C_OMAP1_REV_2) {
+ /* Read clears */
+ iv = omap_i2c_read_reg(i2c_omap, OMAP_I2C_IV_REG);
+ } else {
+ omap_i2c_write_reg(i2c_omap, OMAP_I2C_STAT_REG,
+ i2c_omap->iestate);
+
+ /* Flush posted write before the i2c_omap->idle store occurs */
+ omap_i2c_read_reg(i2c_omap, OMAP_I2C_STAT_REG);
+ }
+}
/*
* Prepare controller for a transaction and call omap_i2c_xfer_msg
@@ -756,11 +968,24 @@ omap_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num)
if (r == 0)
r = num;
+
+ omap_i2c_wait_for_bb(adapter);
+
out:
omap_i2c_idle(i2c_omap);
return r;
}
+#define OMAP_I2C_SCHEME(rev) ((rev & 0xc000) >> 14)
+
+#define OMAP_I2C_REV_SCHEME_0_MAJOR(rev) (rev >> 4)
+#define OMAP_I2C_REV_SCHEME_0_MINOR(rev) (rev & 0xf)
+
+#define OMAP_I2C_REV_SCHEME_1_MAJOR(rev) ((rev & 0x0700) >> 7)
+#define OMAP_I2C_REV_SCHEME_1_MINOR(rev) (rev & 0x1f)
+#define OMAP_I2C_SCHEME_0 0
+#define OMAP_I2C_SCHEME_1 1
+
static int __init
i2c_omap_probe(struct device_d *pdev)
{
@@ -768,7 +993,8 @@ i2c_omap_probe(struct device_d *pdev)
struct omap_i2c_driver_data *i2c_data;
int r;
u32 speed = 0;
- u16 s;
+ u32 rev;
+ u16 minor, major;
i2c_omap = kzalloc(sizeof(struct omap_i2c_struct), GFP_KERNEL);
if (!i2c_omap) {
@@ -787,31 +1013,66 @@ i2c_omap_probe(struct device_d *pdev)
if (pdev->platform_data != NULL)
speed = *(u32 *)pdev->platform_data;
else
- speed = 100; /* Defualt speed */
+ speed = 100; /* Default speed */
i2c_omap->speed = speed;
i2c_omap->base = dev_request_mem_region(pdev, 0);
- printf ("I2C probe\n");
- omap_i2c_unidle(i2c_omap);
-
- i2c_omap->rev = omap_i2c_read_reg(i2c_omap, OMAP_I2C_REV_REG) & 0xff;
-
- /* Set up the fifo size - Get total size */
- s = (omap_i2c_read_reg(i2c_omap, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3;
- i2c_omap->fifo_size = 0x8 << s;
/*
- * Set up notification threshold as half the total available
- * size. This is to ensure that we can handle the status on int
- * call back latencies.
+ * Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2.
+ * On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset.
+ * Also since the omap_i2c_read_reg uses reg_map_ip_* a
+ * raw_readw is done.
*/
+ rev = __raw_readw(i2c_omap->base + 0x04);
+
+ i2c_omap->scheme = OMAP_I2C_SCHEME(rev);
+ switch (i2c_omap->scheme) {
+ case OMAP_I2C_SCHEME_0:
+ i2c_omap->regs = (u8 *)reg_map_ip_v1;
+ i2c_omap->rev = omap_i2c_read_reg(i2c_omap, OMAP_I2C_REV_REG);
+ minor = OMAP_I2C_REV_SCHEME_0_MAJOR(i2c_omap->rev);
+ major = OMAP_I2C_REV_SCHEME_0_MAJOR(i2c_omap->rev);
+ break;
+ case OMAP_I2C_SCHEME_1:
+ /* FALLTHROUGH */
+ default:
+ i2c_omap->regs = (u8 *)reg_map_ip_v2;
+ rev = (rev << 16) |
+ omap_i2c_read_reg(i2c_omap, OMAP_I2C_IP_V2_REVNB_LO);
+ minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev);
+ major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev);
+ i2c_omap->rev = rev;
+ }
- i2c_omap->fifo_size = (i2c_omap->fifo_size / 2);
+ i2c_omap->errata = 0;
- if (i2c_omap->rev >= OMAP_I2C_REV_ON_4430)
- i2c_omap->b_hw = 0; /* Disable hardware fixes */
- else
- i2c_omap->b_hw = 1; /* Enable hardware fixes */
+ if (i2c_omap->rev >= OMAP_I2C_REV_ON_2430 &&
+ i2c_omap->rev < OMAP_I2C_REV_ON_4430_PLUS)
+ i2c_omap->errata |= I2C_OMAP_ERRATA_I207;
+
+ if (i2c_omap->rev <= OMAP_I2C_REV_ON_3430_3530)
+ i2c_omap->errata |= I2C_OMAP_ERRATA_I462;
+
+ if (!(i2c_data->flags & OMAP_I2C_FLAG_NO_FIFO)) {
+ u16 s;
+
+ /* Set up the fifo size - Get total size */
+ s = (omap_i2c_read_reg(i2c_omap, OMAP_I2C_BUFSTAT_REG) >> 14)
+ & 0x3;
+ i2c_omap->fifo_size = 0x8 << s;
+
+ /*
+ * Set up notification threshold as half the total available
+ * size. This is to ensure that we can handle the status on int
+ * call back latencies.
+ */
+
+ i2c_omap->fifo_size = (i2c_omap->fifo_size / 2);
+
+ if (i2c_omap->rev < OMAP_I2C_REV_ON_3630)
+ i2c_omap->b_hw = 1; /* Enable hardware fixes */
+ }
/* reset ASAP, clearing any IRQs */
omap_i2c_init(i2c_omap);
@@ -821,7 +1082,7 @@ i2c_omap_probe(struct device_d *pdev)
omap_i2c_idle(i2c_omap);
- i2c_omap->adapter.master_xfer = omap_i2c_xfer,
+ i2c_omap->adapter.master_xfer = omap_i2c_xfer,
i2c_omap->adapter.nr = pdev->id;
i2c_omap->adapter.dev.parent = pdev;
@@ -837,7 +1098,6 @@ i2c_omap_probe(struct device_d *pdev)
err_unuse_clocks:
omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG, 0);
omap_i2c_idle(i2c_omap);
-
err_free_mem:
kfree(i2c_omap);
diff --git a/drivers/input/gpio_keys.c b/drivers/input/gpio_keys.c
index b43911149e..18a29f0e94 100644
--- a/drivers/input/gpio_keys.c
+++ b/drivers/input/gpio_keys.c
@@ -95,7 +95,6 @@ static int __init gpio_keys_probe(struct device_d *dev)
cdev = &pdata->cdev;
dev->type_data = cdev;
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN;
cdev->tstc = gpio_keys_tstc;
cdev->getc = gpio_keys_getc;
diff --git a/drivers/input/imx_keypad.c b/drivers/input/imx_keypad.c
index 2ee3d0fa00..e6870dfcc2 100644
--- a/drivers/input/imx_keypad.c
+++ b/drivers/input/imx_keypad.c
@@ -441,7 +441,6 @@ static int __init imx_keypad_probe(struct device_d *dev)
cdev->dev = dev;
cdev->tstc = imx_keypad_tstc;
cdev->getc = imx_keypad_getc;
- cdev->f_caps = CONSOLE_STDIN;
cdev->f_active = CONSOLE_STDIN;
console_register(&keypad->cdev);
diff --git a/drivers/input/qt1070.c b/drivers/input/qt1070.c
index ada330a6d2..7b72965df7 100644
--- a/drivers/input/qt1070.c
+++ b/drivers/input/qt1070.c
@@ -265,7 +265,6 @@ static int qt1070_probe(struct device_d *dev)
cdev = &data->cdev;
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN;
cdev->tstc = qt1070_tstc;
cdev->getc = qt1070_getc;
diff --git a/drivers/input/twl6030_pwrbtn.c b/drivers/input/twl6030_pwrbtn.c
index ca51dee605..fc4c728778 100644
--- a/drivers/input/twl6030_pwrbtn.c
+++ b/drivers/input/twl6030_pwrbtn.c
@@ -93,7 +93,6 @@ static int __init twl6030_pwrbtn_probe(struct device_d *dev)
dev->type_data = &idata->cdev;
idata->cdev.dev = dev;
- idata->cdev.f_caps = CONSOLE_STDIN;
idata->cdev.tstc = twl6030_pwrbtn_tstc;
idata->cdev.getc = twl6030_pwrbtn_getc;
console_register(&idata->cdev);
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 7aff7df838..f34c119a21 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -34,6 +34,14 @@ config MCI_MMC_BOOT_PARTITIONS
comment "--- MCI host drivers ---"
+config MCI_DW
+ bool "Synopsys DesignWare Memory Card Interface"
+ depends on ARM
+ help
+ This selects support for the Synopsys DesignWare Mobile Storage IP
+ block, this provides host support for SD and MMC interfaces, in both
+ PIO and external DMA modes.
+
config MCI_MXS
bool "i.MX23/i.MX28"
depends on ARCH_MXS
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index df06a08f61..c13dad3129 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o
obj-$(CONFIG_MCI_PXA) += pxamci.o
obj-$(CONFIG_MCI_S3C) += s3c.o
obj-$(CONFIG_MCI_SPI) += mci_spi.o
+obj-$(CONFIG_MCI_DW) += dw_mmc.o
diff --git a/drivers/mci/atmel_mci.c b/drivers/mci/atmel_mci.c
index dca3813c6d..36107a6ef8 100644
--- a/drivers/mci/atmel_mci.c
+++ b/drivers/mci/atmel_mci.c
@@ -563,6 +563,7 @@ static int atmci_probe(struct device_d *hw_dev)
host->mci.init = atmci_reset;
host->mci.card_present = atmci_card_present;
host->mci.hw_dev = hw_dev;
+ host->mci.devname = pd->devname;
if (pd->bus_width >= 4)
host->mci.host_caps |= MMC_CAP_4_BIT_DATA;
diff --git a/drivers/mci/dw_mmc.c b/drivers/mci/dw_mmc.c
new file mode 100644
index 0000000000..cd2fbb5e9f
--- /dev/null
+++ b/drivers/mci/dw_mmc.c
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2013 Altera Corporation <www.altera.com>
+ *
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ * Rajeshawari Shinde <rajeshwari.s@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <clock.h>
+#include <init.h>
+#include <mci.h>
+#include <io.h>
+#include <platform_data/dw_mmc.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm-generic/errno.h>
+#include <asm/mmu.h>
+
+#define DWMCI_CTRL 0x000
+#define DWMCI_PWREN 0x004
+#define DWMCI_CLKDIV 0x008
+#define DWMCI_CLKSRC 0x00C
+#define DWMCI_CLKENA 0x010
+#define DWMCI_TMOUT 0x014
+#define DWMCI_CTYPE 0x018
+#define DWMCI_BLKSIZ 0x01C
+#define DWMCI_BYTCNT 0x020
+#define DWMCI_INTMASK 0x024
+#define DWMCI_CMDARG 0x028
+#define DWMCI_CMD 0x02C
+#define DWMCI_RESP0 0x030
+#define DWMCI_RESP1 0x034
+#define DWMCI_RESP2 0x038
+#define DWMCI_RESP3 0x03C
+#define DWMCI_MINTSTS 0x040
+#define DWMCI_RINTSTS 0x044
+#define DWMCI_STATUS 0x048
+#define DWMCI_FIFOTH 0x04C
+#define DWMCI_CDETECT 0x050
+#define DWMCI_WRTPRT 0x054
+#define DWMCI_GPIO 0x058
+#define DWMCI_TCMCNT 0x05C
+#define DWMCI_TBBCNT 0x060
+#define DWMCI_DEBNCE 0x064
+#define DWMCI_USRID 0x068
+#define DWMCI_VERID 0x06C
+#define DWMCI_HCON 0x070
+#define DWMCI_UHS_REG 0x074
+#define DWMCI_BMOD 0x080
+#define DWMCI_PLDMND 0x084
+#define DWMCI_DBADDR 0x088
+#define DWMCI_IDSTS 0x08C
+#define DWMCI_IDINTEN 0x090
+#define DWMCI_DSCADDR 0x094
+#define DWMCI_BUFADDR 0x098
+#define DWMCI_DATA 0x200
+
+/* Interrupt Mask register */
+#define DWMCI_INTMSK_ALL 0xffffffff
+#define DWMCI_INTMSK_RE (1 << 1)
+#define DWMCI_INTMSK_CDONE (1 << 2)
+#define DWMCI_INTMSK_DTO (1 << 3)
+#define DWMCI_INTMSK_TXDR (1 << 4)
+#define DWMCI_INTMSK_RXDR (1 << 5)
+#define DWMCI_INTMSK_RCRC (1 << 6)
+#define DWMCI_INTMSK_DCRC (1 << 7)
+#define DWMCI_INTMSK_RTO (1 << 8)
+#define DWMCI_INTMSK_DRTO (1 << 9)
+#define DWMCI_INTMSK_HTO (1 << 10)
+#define DWMCI_INTMSK_FRUN (1 << 11)
+#define DWMCI_INTMSK_HLE (1 << 12)
+#define DWMCI_INTMSK_SBE (1 << 13)
+#define DWMCI_INTMSK_ACD (1 << 14)
+#define DWMCI_INTMSK_EBE (1 << 15)
+
+/* Raw interrupt Register */
+#define DWMCI_DATA_ERR (DWMCI_INTMSK_EBE | DWMCI_INTMSK_SBE | DWMCI_INTMSK_HLE |\
+ DWMCI_INTMSK_FRUN | DWMCI_INTMSK_DCRC)
+#define DWMCI_DATA_TOUT (DWMCI_INTMSK_HTO | DWMCI_INTMSK_DRTO)
+
+/* CTRL register */
+#define DWMCI_CTRL_RESET (1 << 0)
+#define DWMCI_CTRL_FIFO_RESET (1 << 1)
+#define DWMCI_CTRL_DMA_RESET (1 << 2)
+#define DWMCI_DMA_EN (1 << 5)
+#define DWMCI_CTRL_SEND_AS_CCSD (1 << 10)
+#define DWMCI_IDMAC_EN (1 << 25)
+#define DWMCI_RESET_ALL (DWMCI_CTRL_RESET | DWMCI_CTRL_FIFO_RESET |\
+ DWMCI_CTRL_DMA_RESET)
+
+/* CMD register */
+#define DWMCI_CMD_RESP_EXP (1 << 6)
+#define DWMCI_CMD_RESP_LENGTH (1 << 7)
+#define DWMCI_CMD_CHECK_CRC (1 << 8)
+#define DWMCI_CMD_DATA_EXP (1 << 9)
+#define DWMCI_CMD_RW (1 << 10)
+#define DWMCI_CMD_SEND_STOP (1 << 12)
+#define DWMCI_CMD_ABORT_STOP (1 << 14)
+#define DWMCI_CMD_PRV_DAT_WAIT (1 << 13)
+#define DWMCI_CMD_UPD_CLK (1 << 21)
+#define DWMCI_CMD_USE_HOLD_REG (1 << 29)
+#define DWMCI_CMD_START (1 << 31)
+
+/* CLKENA register */
+#define DWMCI_CLKEN_ENABLE (1 << 0)
+#define DWMCI_CLKEN_LOW_PWR (1 << 16)
+
+/* Card-type register */
+#define DWMCI_CTYPE_1BIT 0
+#define DWMCI_CTYPE_4BIT (1 << 0)
+#define DWMCI_CTYPE_8BIT (1 << 16)
+
+/* Status Register */
+#define DWMCI_STATUS_BUSY (1 << 9)
+
+/* FIFOTH Register */
+#define DWMCI_FIFOTH_MSIZE(x) ((x) << 28)
+#define DWMCI_FIFOTH_RX_WMARK(x) ((x) << 16)
+#define DWMCI_FIFOTH_TX_WMARK(x) (x)
+#define DWMCI_FIFOTH_FIFO_DEPTH(x) ((((x) >> 16) & 0x3ff) + 1)
+
+#define DWMCI_IDMAC_OWN (1 << 31)
+#define DWMCI_IDMAC_CH (1 << 4)
+#define DWMCI_IDMAC_FS (1 << 3)
+#define DWMCI_IDMAC_LD (1 << 2)
+
+/* Bus Mode Register */
+#define DWMCI_BMOD_IDMAC_RESET (1 << 0)
+#define DWMCI_BMOD_IDMAC_FB (1 << 1)
+#define DWMCI_BMOD_IDMAC_EN (1 << 7)
+
+struct dwmci_host {
+ struct mci_host mci;
+ struct device_d *dev;
+ struct clk *clk_biu, *clk_ciu;
+ void *ioaddr;
+ unsigned int fifo_size_bytes;
+
+ struct dwmci_idmac *idmac;
+ unsigned long clkrate;
+ int ciu_div;
+};
+
+struct dwmci_idmac {
+ uint32_t flags;
+ uint32_t cnt;
+ uint32_t addr;
+ uint32_t next_addr;
+};
+
+static inline void dwmci_writel(struct dwmci_host *host, int reg, uint32_t val)
+{
+ writel(val, host->ioaddr + reg);
+}
+
+static inline uint32_t dwmci_readl(struct dwmci_host *host, int reg)
+{
+ return readl(host->ioaddr + reg);
+}
+
+#define DW_MMC_NUM_IDMACS (PAGE_SIZE / sizeof(struct dwmci_idmac))
+
+static inline struct dwmci_host *to_dwmci_host(struct mci_host *mci)
+{
+ return container_of(mci, struct dwmci_host, mci);
+}
+
+static int dwmci_wait_reset(struct dwmci_host *host, uint32_t value)
+{
+ uint64_t start;
+ uint32_t ctrl;
+
+ start = get_time_ns();
+
+ dwmci_writel(host, DWMCI_CTRL, value);
+
+ while (!is_timeout(start, SECOND)) {
+ ctrl = dwmci_readl(host, DWMCI_CTRL);
+ if (!(ctrl & DWMCI_RESET_ALL))
+ return 0;
+ }
+
+ return -EIO;
+}
+
+static int dwmci_prepare_data(struct dwmci_host *host,
+ struct mci_data *data)
+{
+ unsigned long ctrl;
+ unsigned int i = 0, flags, cnt, blk_cnt;
+ unsigned long data_start, start_addr;
+ struct dwmci_idmac *desc = host->idmac;
+
+ blk_cnt = data->blocks;
+
+ if (blk_cnt > DW_MMC_NUM_IDMACS)
+ return -EINVAL;
+
+ dwmci_wait_reset(host, DWMCI_CTRL_FIFO_RESET);
+
+ data_start = (uint32_t)desc;
+ dwmci_writel(host, DWMCI_DBADDR, (uint32_t)desc);
+
+ if (data->flags & MMC_DATA_READ)
+ start_addr = (uint32_t)data->dest;
+ else
+ start_addr = (uint32_t)data->src;
+
+ do {
+ flags = DWMCI_IDMAC_OWN | DWMCI_IDMAC_CH;
+ flags |= (i == 0) ? DWMCI_IDMAC_FS : 0;
+
+ if (blk_cnt <= 8) {
+ flags |= DWMCI_IDMAC_LD;
+ cnt = data->blocksize * blk_cnt;
+ } else {
+ cnt = data->blocksize * 8;
+ }
+
+ desc->flags = flags;
+ desc->cnt = cnt;
+ desc->addr = start_addr + (i * PAGE_SIZE);
+ desc->next_addr = (uint32_t)(desc + 1);
+
+ dev_dbg(host->dev, "desc@ 0x%p 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ desc, flags, cnt, desc->addr, desc->next_addr);
+ if (blk_cnt < 8)
+ break;
+
+ blk_cnt -= 8;
+ desc++;
+ i++;
+ } while (1);
+
+ ctrl = dwmci_readl(host, DWMCI_CTRL);
+ ctrl |= DWMCI_IDMAC_EN | DWMCI_DMA_EN;
+ dwmci_writel(host, DWMCI_CTRL, ctrl);
+
+ ctrl = dwmci_readl(host, DWMCI_BMOD);
+ ctrl |= DWMCI_BMOD_IDMAC_FB | DWMCI_BMOD_IDMAC_EN;
+ dwmci_writel(host, DWMCI_BMOD, ctrl);
+
+ dwmci_writel(host, DWMCI_BLKSIZ, data->blocksize);
+ dwmci_writel(host, DWMCI_BYTCNT, data->blocksize * data->blocks);
+
+ return 0;
+}
+
+static int dwmci_set_transfer_mode(struct dwmci_host *host,
+ struct mci_data *data)
+{
+ unsigned long mode;
+
+ mode = DWMCI_CMD_DATA_EXP;
+ if (data->flags & MMC_DATA_WRITE)
+ mode |= DWMCI_CMD_RW;
+
+ return mode;
+}
+
+static int
+dwmci_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
+{
+ struct dwmci_host *host = to_dwmci_host(mci);
+ int flags = 0;
+ uint32_t mask, ctrl;
+ uint64_t start;
+ int ret;
+ unsigned int num_bytes = 0;
+ const void *writebuf = NULL;
+
+ start = get_time_ns();
+ while (1) {
+ if (!(dwmci_readl(host, DWMCI_STATUS) & DWMCI_STATUS_BUSY))
+ break;
+
+ if (is_timeout(start, 100 * MSECOND)) {
+ dev_dbg(host->dev, "Timeout on data busy\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
+
+ if (data) {
+ num_bytes = data->blocks * data->blocksize;
+
+ if (data->flags & MMC_DATA_WRITE) {
+ dma_flush_range((unsigned long)data->src,
+ (unsigned long)(data->src + data->blocks * 512));
+
+ writebuf = data->src;
+ }
+
+ ret = dwmci_prepare_data(host, data);
+ if (ret)
+ return ret;
+ }
+
+ dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
+
+ if (data)
+ flags = dwmci_set_transfer_mode(host, data);
+
+ if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY))
+ return -EINVAL;
+
+ if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
+ flags |= DWMCI_CMD_ABORT_STOP;
+ else
+ flags |= DWMCI_CMD_PRV_DAT_WAIT;
+
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ flags |= DWMCI_CMD_RESP_EXP;
+ if (cmd->resp_type & MMC_RSP_136)
+ flags |= DWMCI_CMD_RESP_LENGTH;
+ }
+
+ if (cmd->resp_type & MMC_RSP_CRC)
+ flags |= DWMCI_CMD_CHECK_CRC;
+
+ flags |= (cmd->cmdidx | DWMCI_CMD_START | DWMCI_CMD_USE_HOLD_REG);
+
+ dev_dbg(host->dev, "Sending CMD%d\n", cmd->cmdidx);
+
+ dwmci_writel(host, DWMCI_CMD, flags);
+
+ start = get_time_ns();
+ while (1) {
+ mask = dwmci_readl(host, DWMCI_RINTSTS);
+ if (mask & DWMCI_INTMSK_CDONE) {
+ if (!data)
+ dwmci_writel(host, DWMCI_RINTSTS, mask);
+ break;
+ }
+ if (is_timeout(start, 100 * MSECOND))
+ return -ETIMEDOUT;
+ }
+
+ if (mask & DWMCI_INTMSK_RTO) {
+ dev_dbg(host->dev, "Response Timeout..\n");
+ return -ETIMEDOUT;
+ } else if (mask & DWMCI_INTMSK_RE) {
+ dev_dbg(host->dev, "Response Error..\n");
+ return -EIO;
+ }
+
+ if (cmd->resp_type & MMC_RSP_PRESENT) {
+ if (cmd->resp_type & MMC_RSP_136) {
+ cmd->response[0] = dwmci_readl(host, DWMCI_RESP3);
+ cmd->response[1] = dwmci_readl(host, DWMCI_RESP2);
+ cmd->response[2] = dwmci_readl(host, DWMCI_RESP1);
+ cmd->response[3] = dwmci_readl(host, DWMCI_RESP0);
+ } else {
+ cmd->response[0] = dwmci_readl(host, DWMCI_RESP0);
+ }
+ }
+
+ if (data) {
+ start = get_time_ns();
+ do {
+ mask = dwmci_readl(host, DWMCI_RINTSTS);
+ if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
+ dev_dbg(host->dev, "DATA ERROR!\n");
+ return -EIO;
+ }
+ if (is_timeout(start, SECOND))
+ return -ETIMEDOUT;
+ } while (!(mask & DWMCI_INTMSK_DTO));
+
+ dwmci_writel(host, DWMCI_RINTSTS, mask);
+
+ ctrl = dwmci_readl(host, DWMCI_CTRL);
+ ctrl &= ~(DWMCI_DMA_EN);
+ dwmci_writel(host, DWMCI_CTRL, ctrl);
+
+ if (data->flags & MMC_DATA_READ) {
+ dma_inv_range((unsigned long)data->dest,
+ (unsigned long)(data->dest + data->blocks * 512));
+ }
+ }
+
+ udelay(100);
+
+ return 0;
+}
+
+static int dwmci_send_cmd(struct dwmci_host *host, u32 cmd, u32 arg)
+{
+ uint64_t start = get_time_ns();
+ uint32_t status;
+
+ dwmci_writel(host, DWMCI_CMDARG, arg);
+
+ dwmci_writel(host, DWMCI_CMD, cmd | DWMCI_CMD_START);
+
+ while (1) {
+ status = dwmci_readl(host, DWMCI_CMD);
+ if (!(status & DWMCI_CMD_START))
+ return 0;
+
+ if (is_timeout(start, 100 * MSECOND)) {
+ dev_err(host->dev, "TIMEOUT error!!\n");
+ return -ETIMEDOUT;
+ }
+ }
+}
+
+static int dwmci_setup_bus(struct dwmci_host *host, uint32_t freq)
+{
+ uint32_t div;
+ unsigned long sclk;
+
+ sclk = host->clkrate / host->ciu_div;
+
+ div = DIV_ROUND_UP(sclk, freq);
+ if (div > 510)
+ div = 510;
+
+ div >>= 1;
+
+ dwmci_writel(host, DWMCI_CLKENA, 0);
+ dwmci_writel(host, DWMCI_CLKSRC, 0);
+
+ dwmci_writel(host, DWMCI_CLKDIV, div);
+
+ dwmci_send_cmd(host, DWMCI_CMD_PRV_DAT_WAIT | DWMCI_CMD_UPD_CLK, 0);
+
+ dwmci_writel(host, DWMCI_CLKENA, DWMCI_CLKEN_ENABLE);
+
+ dwmci_send_cmd(host, DWMCI_CMD_PRV_DAT_WAIT | DWMCI_CMD_UPD_CLK, 0);
+
+ return 0;
+}
+
+static void dwmci_set_ios(struct mci_host *mci, struct mci_ios *ios)
+{
+ struct dwmci_host *host = to_dwmci_host(mci);
+ uint32_t ctype;
+
+ dev_dbg(host->dev, "Buswidth = %d, clock: %d\n", ios->bus_width, ios->clock);
+
+ if (ios->clock)
+ dwmci_setup_bus(host, ios->clock);
+
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_8:
+ ctype = DWMCI_CTYPE_8BIT;
+ break;
+ case MMC_BUS_WIDTH_4:
+ ctype = DWMCI_CTYPE_4BIT;
+ break;
+ default:
+ ctype = DWMCI_CTYPE_1BIT;
+ break;
+ }
+
+ dwmci_writel(host, DWMCI_CTYPE, ctype);
+}
+
+static int dwmci_card_present(struct mci_host *mci)
+{
+ return 1;
+}
+
+static int dwmci_init(struct mci_host *mci, struct device_d *dev)
+{
+ struct dwmci_host *host = to_dwmci_host(mci);
+ uint32_t fifo_size, fifoth_val;
+
+ dwmci_writel(host, DWMCI_PWREN, 1);
+
+ if (dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
+ dev_err(host->dev, "reset failed\n");
+ return -EIO;
+ }
+
+ dwmci_writel(host, DWMCI_RINTSTS, 0xffffffff);
+ dwmci_writel(host, DWMCI_INTMASK, 0);
+
+ dwmci_writel(host, DWMCI_TMOUT, 0xffffffff);
+
+ dwmci_writel(host, DWMCI_IDINTEN, 0);
+ dwmci_writel(host, DWMCI_BMOD, 1);
+
+ fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+
+ /*
+ * Use reset default of the rx_wmark field to determine the
+ * fifo depth.
+ */
+ fifo_size = DWMCI_FIFOTH_FIFO_DEPTH(fifo_size);
+ host->fifo_size_bytes = fifo_size * 4;
+
+ fifoth_val = DWMCI_FIFOTH_MSIZE(0x2) |
+ DWMCI_FIFOTH_RX_WMARK(fifo_size / 2 - 1) |
+ DWMCI_FIFOTH_TX_WMARK(fifo_size / 2);
+
+ dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
+
+ dwmci_writel(host, DWMCI_CLKENA, 0);
+ dwmci_writel(host, DWMCI_CLKSRC, 0);
+
+ return 0;
+}
+
+static int dw_mmc_detect(struct device_d *dev)
+{
+ struct dwmci_host *host = dev->priv;
+
+ return mci_detect_card(&host->mci);
+}
+
+static int dw_mmc_probe(struct device_d *dev)
+{
+ struct dwmci_host *host;
+ struct mci_host *mci;
+ struct dw_mmc_platform_data *pdata = dev->platform_data;
+
+ host = xzalloc(sizeof(*host));
+ mci = &host->mci;
+
+ host->clk_biu = clk_get(dev, "biu");
+ if (IS_ERR(host->clk_biu))
+ return PTR_ERR(host->clk_biu);
+
+ host->clk_ciu = clk_get(dev, "ciu");
+ if (IS_ERR(host->clk_ciu))
+ return PTR_ERR(host->clk_ciu);
+
+ clk_enable(host->clk_biu);
+ clk_enable(host->clk_ciu);
+
+ host->dev = dev;
+ host->ioaddr = dev_request_mem_region(dev, 0);
+ if (!host->ioaddr)
+ return -EBUSY;
+
+ if (pdata) {
+ mci->devname = pdata->devname;
+ host->ciu_div = pdata->ciu_div;
+ } else if (dev->device_node) {
+ const char *alias = of_alias_get(dev->device_node);
+ if (alias)
+ mci->devname = xstrdup(alias);
+ of_property_read_u32(dev->device_node, "dw-mshc-ciu-div",
+ &host->ciu_div);
+ }
+
+ /* divider is 0 based in pdata and 1 based in our private struct */
+ host->ciu_div++;
+
+ host->idmac = dma_alloc_coherent(sizeof(*host->idmac) * DW_MMC_NUM_IDMACS);
+
+ host->mci.send_cmd = dwmci_cmd;
+ host->mci.set_ios = dwmci_set_ios;
+ host->mci.init = dwmci_init;
+ host->mci.card_present = dwmci_card_present;
+ host->mci.hw_dev = dev;
+ host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+ host->mci.host_caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+
+ dev->detect = dw_mmc_detect;
+
+ host->clkrate = clk_get_rate(host->clk_ciu);
+ host->mci.f_min = host->clkrate / 510 / host->ciu_div;
+ if (host->mci.f_min < 200000)
+ host->mci.f_min = 200000;
+ host->mci.f_max = host->clkrate / host->ciu_div;
+
+ mci_of_parse(&host->mci);
+
+ dev->priv = host;
+
+ return mci_register(&host->mci);
+}
+
+static __maybe_unused struct of_device_id dw_mmc_compatible[] = {
+ {
+ .compatible = "altr,socfpga-dw-mshc",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d dw_mmc_driver = {
+ .name = "dw_mmc",
+ .probe = dw_mmc_probe,
+ .of_compatible = DRV_OF_COMPAT(dw_mmc_compatible),
+};
+device_platform_driver(dw_mmc_driver);
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 8cf3e641c1..8da7097c43 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -266,6 +266,21 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
if (irqstat & IRQSTAT_CTOE)
return -ETIMEDOUT;
+ /* Workaround for ESDHC errata ENGcm03648 / ENGcm12360 */
+ if (!data && (cmd->resp_type & MMC_RSP_BUSY)) {
+ /*
+ * Poll on DATA0 line for cmd with busy signal for
+ * timout / 10 usec since DLA polling can be insecure.
+ */
+ ret = wait_on_timeout(2500 * MSECOND,
+ (esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_DAT0));
+
+ if (ret) {
+ dev_err(host->dev, "timeout PRSSTAT_DAT0\n");
+ return -ETIMEDOUT;
+ }
+ }
+
/* Copy the response to the response buffer */
if (cmd->resp_type & MMC_RSP_136) {
u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;
diff --git a/drivers/mci/omap_hsmmc.c b/drivers/mci/omap_hsmmc.c
index a2cd3fec59..19db461e0d 100644
--- a/drivers/mci/omap_hsmmc.c
+++ b/drivers/mci/omap_hsmmc.c
@@ -609,19 +609,17 @@ static int omap_mmc_probe(struct device_d *dev)
hsmmc->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
hsmmc->mci.f_min = 400000;
+ hsmmc->mci.f_max = 52000000;
pdata = (struct omap_hsmmc_platform_data *)dev->platform_data;
if (pdata) {
if (pdata->f_max)
hsmmc->mci.f_max = pdata->f_max;
- else
- hsmmc->mci.f_max = 52000000;
if (pdata->devname)
hsmmc->mci.devname = pdata->devname;
}
-
dev->priv = hsmmc;
dev->detect = omap_mmc_detect,
diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h
index 2c8b6f5212..b67818485b 100644
--- a/drivers/mci/sdhci.h
+++ b/drivers/mci/sdhci.h
@@ -77,6 +77,7 @@
#define IRQSTATEN_TC 0x00000002
#define IRQSTATEN_CC 0x00000001
+#define PRSSTAT_DAT0 0x01000000
#define PRSSTAT_CLSL 0x00800000
#define PRSSTAT_WPSPL 0x00080000
#define PRSSTAT_CDPL 0x00040000
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 5ad3e4d46e..5d7d20f08d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -130,16 +130,10 @@ config DRIVER_NET_KS8851_MLL
config DRIVER_NET_DESIGNWARE
bool "Designware Universal MAC ethernet driver"
select PHYLIB
- depends on HAS_DESIGNWARE_ETH
help
This option enables support for the Synopsys
Designware Core Univesal MAC 10M/100M/1G ethernet IP.
-config DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR
- bool
- depends on DRIVER_NET_DESIGNWARE
- default n
-
config DRIVER_NET_GIANFAR
bool "Gianfar Ethernet"
depends on ARCH_MPC85XX
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index a6b32b9b2e..ecb4656e9d 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -29,12 +29,12 @@
#include <init.h>
#include <io.h>
#include <net.h>
+#include <of_net.h>
#include <asm/mmu.h>
#include <net/designware.h>
#include <linux/phy.h>
#include "designware.h"
-
struct dw_eth_dev {
struct eth_device netdev;
struct mii_bus miibus;
@@ -54,6 +54,15 @@ struct dw_eth_dev {
struct eth_dma_regs *dma_regs_p;
int phy_addr;
phy_interface_t interface;
+ int enh_desc;
+};
+
+struct dw_eth_drvdata {
+ bool enh_desc;
+};
+
+static struct dw_eth_drvdata dwmac_370a_drvdata = {
+ .enh_desc = 1,
};
/* Speed specific definitions */
@@ -73,7 +82,7 @@ static int dwc_ether_mii_read(struct mii_bus *dev, int addr, int reg)
u64 start;
u32 miiaddr;
- miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
+ miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
((reg << MIIREGSHIFT) & MII_REGMSK);
writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
@@ -96,7 +105,7 @@ static int dwc_ether_mii_write(struct mii_bus *dev, int addr, int reg, u16 val)
u32 miiaddr;
writel(val, &mac_p->miidata);
- miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \
+ miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) |
((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE;
writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr);
@@ -149,19 +158,19 @@ static void tx_descs_init(struct eth_device *dev)
desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE];
desc_p->dmamac_next = &desc_table_p[idx + 1];
-#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR)
- desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST |
- DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \
- DESC_TXSTS_TXCHECKINSCTRL | \
- DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS);
-
- desc_p->txrx_status |= DESC_TXSTS_TXCHAIN;
- desc_p->dmamac_cntl = 0;
- desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA);
-#else
- desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
- desc_p->txrx_status = 0;
-#endif
+ if (priv->enh_desc) {
+ desc_p->txrx_status &= ~(DESC_ENH_TXSTS_TXINT | DESC_ENH_TXSTS_TXLAST |
+ DESC_ENH_TXSTS_TXFIRST | DESC_ENH_TXSTS_TXCRCDIS |
+ DESC_ENH_TXSTS_TXCHECKINSCTRL |
+ DESC_ENH_TXSTS_TXRINGEND | DESC_ENH_TXSTS_TXPADDIS);
+
+ desc_p->txrx_status |= DESC_ENH_TXSTS_TXCHAIN;
+ desc_p->dmamac_cntl = 0;
+ desc_p->txrx_status &= ~(DESC_ENH_TXSTS_MSK | DESC_ENH_TXSTS_OWNBYDMA);
+ } else {
+ desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN;
+ desc_p->txrx_status = 0;
+ }
}
/* Correcting the last pointer of the chain */
@@ -184,9 +193,11 @@ static void rx_descs_init(struct eth_device *dev)
desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE];
desc_p->dmamac_next = &desc_table_p[idx + 1];
- desc_p->dmamac_cntl =
- (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \
- DESC_RXCTRL_RXCHAIN;
+ desc_p->dmamac_cntl = MAC_MAX_FRAME_SZ;
+ if (priv->enh_desc)
+ desc_p->dmamac_cntl |= DESC_ENH_RXCTRL_RXCHAIN;
+ else
+ desc_p->dmamac_cntl |= DESC_RXCTRL_RXCHAIN;
dma_inv_range((unsigned long)desc_p->dmamac_addr,
(unsigned long)desc_p->dmamac_addr + CONFIG_ETH_BUFSIZE);
@@ -282,11 +293,12 @@ static int dwc_ether_send(struct eth_device *dev, void *packet, int length)
{
struct dw_eth_dev *priv = dev->priv;
struct eth_dma_regs *dma_p = priv->dma_regs_p;
- u32 desc_num = priv->tx_currdescnum;
+ u32 owndma, desc_num = priv->tx_currdescnum;
struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num];
+ owndma = priv->enh_desc ? DESC_ENH_TXSTS_OWNBYDMA : DESC_TXSTS_OWNBYDMA;
/* Check if the descriptor is owned by CPU */
- if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) {
+ if (desc_p->txrx_status & owndma) {
dev_err(&dev->dev, "CPU not owner of tx frame\n");
return -1;
}
@@ -295,20 +307,20 @@ static int dwc_ether_send(struct eth_device *dev, void *packet, int length)
dma_flush_range((unsigned long)desc_p->dmamac_addr,
(unsigned long)desc_p->dmamac_addr + length);
-#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR)
- desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST;
- desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \
- DESC_TXCTRL_SIZE1MASK;
+ if (priv->enh_desc) {
+ desc_p->txrx_status |= DESC_ENH_TXSTS_TXFIRST | DESC_ENH_TXSTS_TXLAST;
+ desc_p->dmamac_cntl |= (length << DESC_ENH_TXCTRL_SIZE1SHFT) &
+ DESC_ENH_TXCTRL_SIZE1MASK;
- desc_p->txrx_status &= ~(DESC_TXSTS_MSK);
- desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA;
-#else
- desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \
- DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \
- DESC_TXCTRL_TXFIRST;
+ desc_p->txrx_status &= ~(DESC_ENH_TXSTS_MSK);
+ desc_p->txrx_status |= DESC_ENH_TXSTS_OWNBYDMA;
+ } else {
+ desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) &
+ DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST |
+ DESC_TXCTRL_TXFIRST;
- desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
-#endif
+ desc_p->txrx_status = DESC_TXSTS_OWNBYDMA;
+ }
/* Test the wrap-around condition. */
if (++desc_num >= CONFIG_TX_DESCR_NUM)
@@ -334,17 +346,18 @@ static int dwc_ether_rx(struct eth_device *dev)
if (status & DESC_RXSTS_OWNBYDMA)
return 0;
- length = (status & DESC_RXSTS_FRMLENMSK) >> \
+ length = (status & DESC_RXSTS_FRMLENMSK) >>
DESC_RXSTS_FRMLENSHFT;
- net_receive(desc_p->dmamac_addr, length);
-
/*
* Make the current descriptor valid again and go to
* the next one
*/
dma_inv_range((unsigned long)desc_p->dmamac_addr,
(unsigned long)desc_p->dmamac_addr + length);
+
+ net_receive(desc_p->dmamac_addr, length);
+
desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA;
/* Test the wrap-around condition. */
@@ -376,7 +389,7 @@ static int dwc_ether_set_ethaddr(struct eth_device *dev, u8 adr[6])
struct eth_mac_regs *mac_p = priv->mac_regs_p;
u32 macid_lo, macid_hi;
- macid_lo = adr[0] + (adr[1] << 8) + \
+ macid_lo = adr[0] + (adr[1] << 8) +
(adr[2] << 16) + (adr[3] << 24);
macid_hi = adr[4] + (adr[5] << 8);
writel(macid_hi, &mac_p->macaddr0hi);
@@ -394,6 +407,14 @@ static void dwc_version(struct device_d *dev, u32 hwid)
uid, synid);
}
+static int dwc_probe_dt(struct device_d *dev, struct dw_eth_dev *priv)
+{
+ priv->phy_addr = -1;
+ priv->interface = of_get_phy_mode(dev->device_node);
+
+ return 0;
+}
+
static int dwc_ether_probe(struct device_d *dev)
{
struct dw_eth_dev *priv;
@@ -401,14 +422,27 @@ static int dwc_ether_probe(struct device_d *dev)
struct mii_bus *miibus;
void __iomem *base;
struct dwc_ether_platform_data *pdata = dev->platform_data;
-
- if (!pdata) {
- printf("dwc_ether: no platform_data\n");
- return -ENODEV;
- }
+ int ret;
+ struct dw_eth_drvdata *drvdata;
priv = xzalloc(sizeof(struct dw_eth_dev));
+ ret = dev_get_drvdata(dev, (unsigned long *)&drvdata);
+ if (ret)
+ return ret;
+
+ priv->enh_desc = drvdata->enh_desc;
+
+ if (pdata) {
+ priv->phy_addr = pdata->phy_addr;
+ priv->interface = pdata->interface;
+ priv->fix_mac_speed = pdata->fix_mac_speed;
+ } else {
+ ret = dwc_probe_dt(dev, priv);
+ if (ret)
+ return ret;
+ }
+
base = dev_request_mem_region(dev, 0);
priv->mac_regs_p = base;
dwc_version(dev, readl(&priv->mac_regs_p->version));
@@ -417,9 +451,8 @@ static int dwc_ether_probe(struct device_d *dev)
CONFIG_TX_DESCR_NUM * sizeof(struct dmamacdescr));
priv->rx_mac_descrtable = dma_alloc_coherent(
CONFIG_RX_DESCR_NUM * sizeof(struct dmamacdescr));
- priv->txbuffs = malloc(TX_TOTAL_BUFSIZE);
- priv->rxbuffs = malloc(RX_TOTAL_BUFSIZE);
- priv->fix_mac_speed = pdata->fix_mac_speed;
+ priv->txbuffs = dma_alloc(TX_TOTAL_BUFSIZE);
+ priv->rxbuffs = dma_alloc(RX_TOTAL_BUFSIZE);
edev = &priv->netdev;
miibus = &priv->miibus;
@@ -434,8 +467,6 @@ static int dwc_ether_probe(struct device_d *dev)
edev->get_ethaddr = dwc_ether_get_ethaddr;
edev->set_ethaddr = dwc_ether_set_ethaddr;
- priv->phy_addr = pdata->phy_addr;
- priv->interface = pdata->interface;
miibus->parent = dev;
miibus->read = dwc_ether_mii_read;
miibus->write = dwc_ether_mii_write;
@@ -450,9 +481,19 @@ static void dwc_ether_remove(struct device_d *dev)
{
}
+static __maybe_unused struct of_device_id dwc_ether_compatible[] = {
+ {
+ .compatible = "snps,dwmac-3.70a",
+ .data = (unsigned long)&dwmac_370a_drvdata,
+ }, {
+ /* sentinel */
+ }
+};
+
static struct driver_d dwc_ether_driver = {
.name = "designware_eth",
.probe = dwc_ether_probe,
.remove = dwc_ether_remove,
+ .of_compatible = DRV_OF_COMPAT(dwc_ether_compatible),
};
device_platform_driver(dwc_ether_driver);
diff --git a/drivers/net/designware.h b/drivers/net/designware.h
index db2ead48aa..f7b14be6cc 100644
--- a/drivers/net/designware.h
+++ b/drivers/net/designware.h
@@ -130,27 +130,21 @@ struct dmamacdescr {
*/
/* tx status bits definitions */
-#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR)
+#define DESC_ENH_TXSTS_OWNBYDMA (1 << 31)
+#define DESC_ENH_TXSTS_TXINT (1 << 30)
+#define DESC_ENH_TXSTS_TXLAST (1 << 29)
+#define DESC_ENH_TXSTS_TXFIRST (1 << 28)
+#define DESC_ENH_TXSTS_TXCRCDIS (1 << 27)
+
+#define DESC_ENH_TXSTS_TXPADDIS (1 << 26)
+#define DESC_ENH_TXSTS_TXCHECKINSCTRL (3 << 22)
+#define DESC_ENH_TXSTS_TXRINGEND (1 << 21)
+#define DESC_ENH_TXSTS_TXCHAIN (1 << 20)
+#define DESC_ENH_TXSTS_MSK (0x1FFFF << 0)
#define DESC_TXSTS_OWNBYDMA (1 << 31)
-#define DESC_TXSTS_TXINT (1 << 30)
-#define DESC_TXSTS_TXLAST (1 << 29)
-#define DESC_TXSTS_TXFIRST (1 << 28)
-#define DESC_TXSTS_TXCRCDIS (1 << 27)
-
-#define DESC_TXSTS_TXPADDIS (1 << 26)
-#define DESC_TXSTS_TXCHECKINSCTRL (3 << 22)
-#define DESC_TXSTS_TXRINGEND (1 << 21)
-#define DESC_TXSTS_TXCHAIN (1 << 20)
#define DESC_TXSTS_MSK (0x1FFFF << 0)
-#else
-
-#define DESC_TXSTS_OWNBYDMA (1 << 31)
-#define DESC_TXSTS_MSK (0x1FFFF << 0)
-
-#endif
-
/* rx status bits definitions */
#define DESC_RXSTS_OWNBYDMA (1 << 31)
#define DESC_RXSTS_DAFILTERFAIL (1 << 30)
@@ -178,14 +172,10 @@ struct dmamacdescr {
*/
/* tx control bits definitions */
-#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR)
-
-#define DESC_TXCTRL_SIZE1MASK (0x1FFF << 0)
-#define DESC_TXCTRL_SIZE1SHFT (0)
-#define DESC_TXCTRL_SIZE2MASK (0x1FFF << 16)
-#define DESC_TXCTRL_SIZE2SHFT (16)
-
-#else
+#define DESC_ENH_TXCTRL_SIZE1MASK (0x1FFF << 0)
+#define DESC_ENH_TXCTRL_SIZE1SHFT (0)
+#define DESC_ENH_TXCTRL_SIZE2MASK (0x1FFF << 16)
+#define DESC_ENH_TXCTRL_SIZE2SHFT (16)
#define DESC_TXCTRL_TXINT (1 << 31)
#define DESC_TXCTRL_TXLAST (1 << 30)
@@ -200,21 +190,15 @@ struct dmamacdescr {
#define DESC_TXCTRL_SIZE2MASK (0x7FF << 11)
#define DESC_TXCTRL_SIZE2SHFT (11)
-#endif
-
/* rx control bits definitions */
-#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR)
-
-#define DESC_RXCTRL_RXINTDIS (1 << 31)
-#define DESC_RXCTRL_RXRINGEND (1 << 15)
-#define DESC_RXCTRL_RXCHAIN (1 << 14)
+#define DESC_ENH_RXCTRL_RXINTDIS (1 << 31)
+#define DESC_ENH_RXCTRL_RXRINGEND (1 << 15)
+#define DESC_ENH_RXCTRL_RXCHAIN (1 << 14)
-#define DESC_RXCTRL_SIZE1MASK (0x1FFF << 0)
-#define DESC_RXCTRL_SIZE1SHFT (0)
-#define DESC_RXCTRL_SIZE2MASK (0x1FFF << 16)
-#define DESC_RXCTRL_SIZE2SHFT (16)
-
-#else
+#define DESC_ENH_RXCTRL_SIZE1MASK (0x1FFF << 0)
+#define DESC_ENH_RXCTRL_SIZE1SHFT (0)
+#define DESC_ENH_RXCTRL_SIZE2MASK (0x1FFF << 16)
+#define DESC_ENH_RXCTRL_SIZE2SHFT (16)
#define DESC_RXCTRL_RXINTDIS (1 << 31)
#define DESC_RXCTRL_RXRINGEND (1 << 25)
@@ -226,5 +210,3 @@ struct dmamacdescr {
#define DESC_RXCTRL_SIZE2SHFT (11)
#endif
-
-#endif
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index b1f544b5ab..d8523cee3a 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -458,9 +458,31 @@ static int macb_phy_write(struct mii_bus *bus, int addr, int reg, u16 value)
static int macb_get_ethaddr(struct eth_device *edev, unsigned char *adr)
{
struct macb_device *macb = edev->priv;
+ u32 bottom;
+ u16 top;
+ u8 addr[6];
+ int i;
dev_dbg(macb->dev, "%s\n", __func__);
+ /* Check all 4 address register for vaild address */
+ for (i = 0; i < 4; i++) {
+ bottom = macb_or_gem_readl(macb, SA1B + i * 8);
+ top = macb_or_gem_readl(macb, SA1T + i * 8);
+
+ addr[0] = bottom & 0xff;
+ addr[1] = (bottom >> 8) & 0xff;
+ addr[2] = (bottom >> 16) & 0xff;
+ addr[3] = (bottom >> 24) & 0xff;
+ addr[4] = top & 0xff;
+ addr[5] = (top >> 8) & 0xff;
+
+ if (is_valid_ether_addr(addr)) {
+ memcpy(adr, addr, sizeof(addr));
+ return 0;
+ }
+ }
+
return -1;
}
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index b868cbf194..ba81e24992 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -66,6 +66,7 @@
#include <clock.h>
#include <io.h>
#include <linux/phy.h>
+#include <net/smc91111.h>
/*---------------------------------------------------------------
.
@@ -446,6 +447,7 @@ struct smc91c111_priv {
struct mii_bus miibus;
struct accessors a;
void __iomem *base;
+ int qemu_fixup;
};
#if (SMC_DEBUG > 2 )
@@ -882,6 +884,7 @@ static void smc91c111_enable(struct eth_device *edev)
static int smc91c111_eth_open(struct eth_device *edev)
{
struct smc91c111_priv *priv = (struct smc91c111_priv *)edev->priv;
+ int ret;
/* Configure the Receive/Phy Control register */
SMC_SELECT_BANK(priv, 0);
@@ -889,8 +892,27 @@ static int smc91c111_eth_open(struct eth_device *edev)
smc91c111_enable(edev);
- return phy_device_connect(edev, &priv->miibus, 0, NULL,
+ ret = phy_device_connect(edev, &priv->miibus, 0, NULL,
0, PHY_INTERFACE_MODE_NA);
+
+ if (ret)
+ return ret;
+
+ if (priv->qemu_fixup && edev->phydev->phy_id == 0x00000000) {
+ struct phy_device *dev = edev->phydev;
+
+ dev->speed = SPEED_100;
+ dev->duplex = DUPLEX_FULL;
+ dev->autoneg = !AUTONEG_ENABLE;
+ dev->force = 1;
+ dev->link = 1;
+
+ dev_info(edev->parent, "phy with id 0x%08x detected this might be qemu\n",
+ dev->phy_id);
+ dev_info(edev->parent, "force link at 100Mpbs\n");
+ }
+
+ return 0;
}
static int smc91c111_eth_send(struct eth_device *edev, void *packet,
@@ -1286,6 +1308,12 @@ static int smc91c111_probe(struct device_d *dev)
priv = edev->priv;
+ if (dev->platform_data) {
+ struct smc91c111_pdata *pdata = dev->platform_data;
+
+ priv->qemu_fixup = pdata->qemu_fixup;
+ }
+
priv->a = access_via_32bit;
edev->init = smc91c111_init_dev;
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index db7d260c00..f769cfe9bb 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -177,6 +177,13 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
{
pwm->chip->duty_ns = duty_ns;
pwm->chip->period_ns = period_ns;
+
+ if (period_ns == 0)
+ return -EINVAL;
+
+ if (duty_ns > period_ns)
+ return -EINVAL;
+
return pwm->chip->ops->config(pwm->chip, duty_ns, period_ns);
}
EXPORT_SYMBOL_GPL(pwm_config);
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index 0e075880e0..fc7723ea8a 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -164,10 +164,6 @@ int pl011_init_port (struct console_device *cdev)
uart->uartclk = clk_get_rate(uart->clk);
/*
- * set baud rate
- */
- pl011_setbaudrate(cdev, 115200);
- /*
** Set the UART to be 8 bits, 1 stop bit, no parity, fifo enabled.
*/
pl011_rlcr(uart, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN);
@@ -196,7 +192,6 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
cdev = &uart->uart;
cdev->dev = &dev->dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = pl011_tstc;
cdev->putc = pl011_putc;
cdev->getc = pl011_getc;
diff --git a/drivers/serial/arm_dcc.c b/drivers/serial/arm_dcc.c
index bab72990df..e5f2bbe5e2 100644
--- a/drivers/serial/arm_dcc.c
+++ b/drivers/serial/arm_dcc.c
@@ -133,7 +133,6 @@ static int arm_dcc_probe(struct device_d *dev)
cdev = &arm_dcc_dev;
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = arm_dcc_tstc;
cdev->putc = arm_dcc_putc;
cdev->getc = arm_dcc_getc;
diff --git a/drivers/serial/atmel.c b/drivers/serial/atmel.c
index 40945c9282..c2a5d33b1b 100644
--- a/drivers/serial/atmel.c
+++ b/drivers/serial/atmel.c
@@ -405,8 +405,6 @@ static int atmel_serial_init_port(struct console_device *cdev)
writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), uart->base + USART3_CR);
- atmel_serial_setbaudrate(cdev, 115200);
-
writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), uart->base + USART3_CR);
writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
| USART3_BF(USCLKS, USART3_USCLKS_MCK)
@@ -425,7 +423,6 @@ static int atmel_serial_probe(struct device_d *dev)
uart = xzalloc(sizeof(struct atmel_uart_port));
cdev = &uart->uart;
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = atmel_serial_tstc;
cdev->putc = atmel_serial_putc;
cdev->getc = atmel_serial_getc;
diff --git a/drivers/serial/linux_console.c b/drivers/serial/linux_console.c
index 7ded091790..760b3b81fe 100644
--- a/drivers/serial/linux_console.c
+++ b/drivers/serial/linux_console.c
@@ -64,10 +64,12 @@ static int linux_console_probe(struct device_d *dev)
cdev = xzalloc(sizeof(struct console_device));
cdev->dev = dev;
- cdev->f_caps = data->flags;
- cdev->tstc = linux_console_tstc;
- cdev->putc = linux_console_putc;
- cdev->getc = linux_console_getc;
+ if (data->stdinfd >= 0) {
+ cdev->tstc = linux_console_tstc;
+ cdev->getc = linux_console_getc;
+ }
+ if (data->stdoutfd >= 0)
+ cdev->putc = linux_console_putc;
console_register(cdev);
diff --git a/drivers/serial/serial_altera.c b/drivers/serial/serial_altera.c
index 7ff38d7f1d..d519a87928 100644
--- a/drivers/serial/serial_altera.c
+++ b/drivers/serial/serial_altera.c
@@ -86,7 +86,6 @@ static int altera_serial_probe(struct device_d *dev)
priv->regs = dev_request_mem_region(dev, 0);
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = altera_serial_tstc;
cdev->putc = altera_serial_putc;
cdev->getc = altera_serial_getc;
diff --git a/drivers/serial/serial_altera_jtag.c b/drivers/serial/serial_altera_jtag.c
index edc3c768dd..4219a4bbb9 100644
--- a/drivers/serial/serial_altera_jtag.c
+++ b/drivers/serial/serial_altera_jtag.c
@@ -91,7 +91,6 @@ static int altera_serial_jtag_probe(struct device_d *dev) {
priv->regs = dev_request_mem_region(dev, 0);
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = altera_serial_jtag_tstc;
cdev->putc = altera_serial_jtag_putc;
cdev->getc = altera_serial_jtag_getc;
diff --git a/drivers/serial/serial_auart.c b/drivers/serial/serial_auart.c
index 0e1ab83f21..19805166bb 100644
--- a/drivers/serial/serial_auart.c
+++ b/drivers/serial/serial_auart.c
@@ -187,7 +187,6 @@ static int auart_serial_probe(struct device_d *dev)
priv = xzalloc(sizeof *priv);
cdev = &priv->cdev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = auart_serial_tstc;
cdev->putc = auart_serial_putc;
cdev->getc = auart_serial_getc;
@@ -202,7 +201,6 @@ static int auart_serial_probe(struct device_d *dev)
return PTR_ERR(priv->clk);
auart_serial_init_port(priv);
- auart_serial_setbaudrate(cdev, CONFIG_BAUDRATE);
/* Disable RTS/CTS, enable Rx, Tx, UART */
writel(BM_UARTAPP_CTRL2_RTSEN | BM_UARTAPP_CTRL2_CTSEN |
diff --git a/drivers/serial/serial_blackfin.c b/drivers/serial/serial_blackfin.c
index 7373a03775..2122226734 100644
--- a/drivers/serial/serial_blackfin.c
+++ b/drivers/serial/serial_blackfin.c
@@ -113,7 +113,6 @@ static int blackfin_serial_probe(struct device_d *dev)
cdev = xzalloc(sizeof(struct console_device));
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = blackfin_serial_tstc;
cdev->putc = blackfin_serial_putc;
cdev->getc = blackfin_serial_getc;
diff --git a/drivers/serial/serial_cadence.c b/drivers/serial/serial_cadence.c
index c29c391023..a1b76d07dc 100644
--- a/drivers/serial/serial_cadence.c
+++ b/drivers/serial/serial_cadence.c
@@ -246,7 +246,6 @@ static int cadence_serial_probe(struct device_d *dev)
}
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = cadence_serial_tstc;
cdev->putc = cadence_serial_putc;
cdev->getc = cadence_serial_getc;
diff --git a/drivers/serial/serial_clps711x.c b/drivers/serial/serial_clps711x.c
index ffbb6f80b3..e43d141703 100644
--- a/drivers/serial/serial_clps711x.c
+++ b/drivers/serial/serial_clps711x.c
@@ -58,9 +58,6 @@ static void clps711x_init_port(struct console_device *cdev)
tmp |= UBRLCR_FIFOEN | UBRLCR_WRDLEN8; /* FIFO on, 8N1 mode */
writel(tmp, s->UBRLCR);
- /* Set default baudrate on initialization */
- clps711x_setbaudrate(cdev, CONFIG_BAUDRATE);
-
/* Enable the UART */
writel(readl(SYSCON(s)) | SYSCON_UARTEN, SYSCON(s));
}
@@ -131,7 +128,6 @@ static int clps711x_probe(struct device_d *dev)
dev->priv = s;
s->cdev.dev = dev;
- s->cdev.f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
s->cdev.tstc = clps711x_tstc;
s->cdev.putc = clps711x_putc;
s->cdev.getc = clps711x_getc;
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index 8553c2e6af..01c7cc7fea 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -330,7 +330,6 @@ static int imx_serial_probe(struct device_d *dev)
priv->regs = dev_request_mem_region(dev, 0);
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = imx_serial_tstc;
cdev->putc = imx_serial_putc;
cdev->getc = imx_serial_getc;
@@ -338,7 +337,6 @@ static int imx_serial_probe(struct device_d *dev)
cdev->setbrg = imx_serial_setbaudrate;
imx_serial_init_port(cdev);
- imx_serial_setbaudrate(cdev, 115200);
/* Enable UART */
val = readl(priv->regs + UCR1);
diff --git a/drivers/serial/serial_mpc5xxx.c b/drivers/serial/serial_mpc5xxx.c
index 532eea3e5f..18aca8736d 100644
--- a/drivers/serial/serial_mpc5xxx.c
+++ b/drivers/serial/serial_mpc5xxx.c
@@ -149,7 +149,6 @@ static int mpc5xxx_serial_probe(struct device_d *dev)
cdev = xzalloc(sizeof(struct console_device));
dev->priv = dev_request_mem_region(dev, 0);
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = mpc5xxx_serial_tstc;
cdev->putc = mpc5xxx_serial_putc;
cdev->getc = mpc5xxx_serial_getc;
diff --git a/drivers/serial/serial_netx.c b/drivers/serial/serial_netx.c
index 037b9980ba..c659cfaaf3 100644
--- a/drivers/serial/serial_netx.c
+++ b/drivers/serial/serial_netx.c
@@ -138,7 +138,6 @@ static int netx_serial_probe(struct device_d *dev)
cdev = xzalloc(sizeof(struct console_device));
dev->priv = dev_request_mem_region(dev, 0);
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = netx_serial_tstc;
cdev->putc = netx_serial_putc;
cdev->getc = netx_serial_getc;
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 5899d57110..59b509c280 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -183,8 +183,6 @@ static void ns16550_serial_init_port(struct console_device *cdev)
ns16550_write(cdev, 0x07, mdr1); /* Disable */
#endif
- ns16550_setbaudrate(cdev, CONFIG_BAUDRATE);
-
#ifdef CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS
ns16550_write(cdev, 0x00, mdr1);
#endif
@@ -291,7 +289,6 @@ static int ns16550_probe(struct device_d *dev)
cdev = &priv->cdev;
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = ns16550_tstc;
cdev->putc = ns16550_putc;
cdev->getc = ns16550_getc;
diff --git a/drivers/serial/serial_omap4_usbboot.c b/drivers/serial/serial_omap4_usbboot.c
index 51b2d13003..2ef026c24d 100644
--- a/drivers/serial/serial_omap4_usbboot.c
+++ b/drivers/serial/serial_omap4_usbboot.c
@@ -62,7 +62,6 @@ static int serial_omap4_usbboot_probe(struct device_d *dev)
priv = xzalloc(sizeof(*priv));
priv->cdev.dev = dev;
- priv->cdev.f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
priv->cdev.tstc = serial_omap4_usbboot_tstc;
priv->cdev.putc = serial_omap4_usbboot_putc;
priv->cdev.getc = serial_omap4_usbboot_getc;
diff --git a/drivers/serial/serial_pl010.c b/drivers/serial/serial_pl010.c
index 9158774de9..81cea776a6 100644
--- a/drivers/serial/serial_pl010.c
+++ b/drivers/serial/serial_pl010.c
@@ -140,7 +140,6 @@ static int pl010_probe(struct device_d *dev)
cdev = xzalloc(sizeof(struct console_device));
dev->priv = dev_request_mem_region(dev, 0);
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = pl010_tstc;
cdev->putc = pl010_putc;
cdev->getc = pl010_getc;
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
index 42355cedf2..20ac4beb96 100644
--- a/drivers/serial/serial_pxa.c
+++ b/drivers/serial/serial_pxa.c
@@ -170,7 +170,6 @@ static int pxa_serial_probe(struct device_d *dev)
dev->priv = priv;
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = pxa_serial_tstc;
cdev->putc = pxa_serial_putc;
cdev->getc = pxa_serial_getc;
diff --git a/drivers/serial/serial_s3c.c b/drivers/serial/serial_s3c.c
index cc7b33e101..038193dcf4 100644
--- a/drivers/serial/serial_s3c.c
+++ b/drivers/serial/serial_s3c.c
@@ -184,7 +184,6 @@ static int s3c_serial_probe(struct device_d *dev)
priv->regs = dev_request_mem_region(dev, 0);
dev->priv = priv;
cdev->dev = dev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = s3c_serial_tstc;
cdev->putc = s3c_serial_putc;
cdev->getc = s3c_serial_getc;
diff --git a/drivers/serial/stm-serial.c b/drivers/serial/stm-serial.c
index 0d7484f4bd..3fec1ceeff 100644
--- a/drivers/serial/stm-serial.c
+++ b/drivers/serial/stm-serial.c
@@ -153,7 +153,6 @@ static int stm_serial_probe(struct device_d *dev)
cdev = &priv->cdev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = stm_serial_tstc;
cdev->putc = stm_serial_putc;
cdev->getc = stm_serial_getc;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 36fc736fd0..68a51d1e1e 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -74,7 +74,7 @@ static LIST_HEAD(usb_device_list);
static void print_usb_device(struct usb_device *dev)
{
- printf("Bus %03d Device %03d: ID %04x:%04x %s\n",
+ pr_info("Bus %03d Device %03d: ID %04x:%04x %s\n",
dev->host->busnum, dev->devnum,
dev->descriptor->idVendor,
dev->descriptor->idProduct,
@@ -440,6 +440,8 @@ static int usb_new_device(struct usb_device *dev)
dev->dev.id = DEVICE_ID_SINGLE;
+ if (dev->host->hw_dev)
+ dev->dev.parent = dev->host->hw_dev;
register_device(&dev->dev);
/* now prode if the device is a hub */
@@ -527,7 +529,7 @@ void usb_rescan(int force)
struct usb_host *host;
int ret;
- printf("USB: scanning bus for devices...\n");
+ pr_info("USB: scanning bus for devices...\n");
dev_index = 0;
list_for_each_entry(host, &host_list, list) {
@@ -536,7 +538,7 @@ void usb_rescan(int force)
continue;
}
- printf("%d USB Device(s) found\n", dev_index);
+ pr_info("%d USB Device(s) found\n", dev_index);
}
/*
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 9717c3b202..dbadbe4603 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -478,7 +478,6 @@ int gserial_connect(struct gserial *gser, u8 port_num)
gser->connect(gser);
cdev = &port->cdev;
- cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
cdev->tstc = serial_tstc;
cdev->putc = serial_putc;
cdev->getc = serial_getc;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index f44f836357..cb6a592466 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -883,6 +883,7 @@ int ehci_register(struct device_d *dev, struct ehci_data *data)
ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_TD);
ehci->td = dma_alloc_coherent(sizeof(struct qTD) * NUM_TD);
+ host->hw_dev = dev;
host->init = ehci_init;
host->submit_int_msg = submit_int_msg;
host->submit_control_msg = submit_control_msg;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index ad39bcf6ad..8bf20d0d61 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1794,6 +1794,7 @@ static int ohci_probe(struct device_d *dev)
ohci = xzalloc(sizeof(struct ohci));
host = &ohci->host;
+ host->hw_dev = dev;
host->init = ohci_init;
host->submit_int_msg = submit_int_msg;
host->submit_control_msg = submit_control_msg;
diff --git a/fs/Kconfig b/fs/Kconfig
index be4797f0e6..50a15c6bee 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -44,6 +44,25 @@ config FS_NFS
source fs/fat/Kconfig
source fs/ubifs/Kconfig
+config FS_BPKFS
+ bool
+ prompt "BPKFS support"
+ help
+ Simple update file format developed for Somfy, tools and library are
+ available under LGPLv2 (https://www.gitorious.org/libbpk).
+ This format in the v1.0 allow you to store 6 types a binary stream for
+ a unique hardware id:
+ - bootloader
+ - bootloader_version
+ - description.gz
+ - kernel
+ - rootfs
+ - firmware_version
+
+config FS_UIMAGEFS
+ bool
+ prompt "uImage FS support"
+
config PARTITION_NEED_MTD
bool
diff --git a/fs/Makefile b/fs/Makefile
index bd02d94267..e8347bd670 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -9,3 +9,5 @@ obj-$(CONFIG_FS_UBIFS) += ubifs/
obj-$(CONFIG_FS_TFTP) += tftp.o
obj-$(CONFIG_FS_OMAP4_USBBOOT) += omap4_usbbootfs.o
obj-$(CONFIG_FS_NFS) += nfs.o
+obj-$(CONFIG_FS_BPKFS) += bpkfs.o
+obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o
diff --git a/fs/bpkfs.c b/fs/bpkfs.c
new file mode 100644
index 0000000000..b3b45be76d
--- /dev/null
+++ b/fs/bpkfs.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Simple update file format developed for Somfy, tools and library are
+ * available under LGPLv2 (https://www.gitorious.org/libbpk).
+ *
+ * under GPLv2 ONLY
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <fs.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <malloc.h>
+#include <init.h>
+#include <linux/stat.h>
+#include <linux/err.h>
+#include <bpkfs.h>
+#include <libgen.h>
+
+static bool bpkfs_is_crc_file(struct bpkfs_handle_data *d)
+{
+ return d->type & (1 << 31);
+}
+
+const char* bpkfs_type_to_str(uint32_t type)
+{
+ switch (type) {
+ case BPKFS_TYPE_BL:
+ return "bootloader";
+ case BPKFS_TYPE_BLV:
+ return "bootloader_version";
+ case BPKFS_TYPE_DSC:
+ return "description.gz";
+ case BPKFS_TYPE_KER:
+ return "kernel";
+ case BPKFS_TYPE_RFS:
+ return "rootfs";
+ case BPKFS_TYPE_FMV:
+ return "firmware_version";
+ }
+
+ return NULL;
+}
+
+static struct bpkfs_handle_hw *bpkfs_get_by_hw_id(
+ struct bpkfs_handle *handle, uint32_t hw_id)
+{
+ struct bpkfs_handle_hw *h;
+
+ list_for_each_entry(h, &handle->list, list_hw_id) {
+ if (h->hw_id == hw_id)
+ return h;
+ }
+
+ return NULL;
+}
+
+static struct bpkfs_handle_hw *bpkfs_hw_id_get_by_name(
+ struct bpkfs_handle *handle, const char *name)
+{
+ struct bpkfs_handle_hw *h;
+
+ if (!name)
+ return NULL;
+
+ list_for_each_entry(h, &handle->list, list_hw_id) {
+ if (strcmp(h->name, name) == 0)
+ return h;
+ }
+
+ return NULL;
+}
+
+static struct bpkfs_handle_data *bpkfs_data_get_by_name(
+ struct bpkfs_handle_hw *h, const char *name)
+{
+ struct bpkfs_handle_data *d;
+
+ if (!name)
+ return NULL;
+
+ list_for_each_entry(d, &h->list_data, list) {
+ if (strcmp(d->name, name) == 0)
+ return d;
+ }
+
+ return NULL;
+}
+
+static struct bpkfs_handle_hw *bpkfs_get_or_add_hw_id(
+ struct bpkfs_handle *handle, uint32_t hw_id)
+{
+ struct bpkfs_handle_hw *h;
+
+ h = bpkfs_get_by_hw_id(handle, hw_id);
+ if (h)
+ return h;
+
+ h = xzalloc(sizeof(*h));
+
+ INIT_LIST_HEAD(&h->list_data);
+ h->hw_id = hw_id;
+ h->name = asprintf("hw_id_%x", hw_id);
+ list_add_tail(&h->list_hw_id, &handle->list);
+
+ return h;
+}
+
+static struct bpkfs_handle_data *bpkfs_get_by_type(
+ struct bpkfs_handle *handle, uint32_t hw_id, uint32_t type)
+{
+ struct bpkfs_handle_data *d;
+ struct bpkfs_handle_hw *h;
+
+ h = bpkfs_get_by_hw_id(handle, hw_id);
+ if (!h)
+ return NULL;
+
+ list_for_each_entry(d, &h->list_data, list) {
+ if (d->type == type)
+ return d;
+ }
+
+ return NULL;
+}
+
+static int bpkfs_open(struct device_d *dev, FILE *f, const char *filename)
+{
+ struct bpkfs_handle *priv = dev->priv;
+ struct bpkfs_handle_data *d;
+ struct bpkfs_handle_hw *h;
+ char *dir, *file;
+ int ret = -EINVAL;
+ char *tmp = xstrdup(filename);
+ char *tmp2 = xstrdup(filename);
+
+ dir = dirname(tmp);
+
+ if (dir[0] == '/')
+ dir++;
+
+ h = bpkfs_hw_id_get_by_name(priv, dir);
+ if (!h)
+ goto out;
+
+ file = basename(tmp2);
+ d = bpkfs_data_get_by_name(h, file);
+ if (!d)
+ goto out;
+
+ if (!bpkfs_is_crc_file(d)) {
+ d->fd = open(priv->filename, O_RDONLY);
+ if (d->fd < 0) {
+ ret = d->fd;
+ goto out;
+ }
+
+ lseek(d->fd, d->offset, SEEK_SET);
+ }
+
+ f->size = d->size;
+ f->inode = d;
+ ret = 0;
+
+out:
+ free(tmp);
+ free(tmp2);
+ return ret;
+}
+
+static int bpkfs_close(struct device_d *dev, FILE *file)
+{
+ struct bpkfs_handle_data *d = file->inode;
+
+ close(d->fd);
+
+ return 0;
+}
+
+static int bpkfs_read(struct device_d *dev, FILE *file, void *buf, size_t insize)
+{
+ struct bpkfs_handle_data *d = file->inode;
+
+ if (bpkfs_is_crc_file(d)) {
+ memcpy(buf, &d->data[d->pos], insize);
+ return insize;
+ } else {
+ return read(d->fd, buf, insize);
+ }
+}
+
+static loff_t bpkfs_lseek(struct device_d *dev, FILE *file, loff_t pos)
+{
+ struct bpkfs_handle_data *d = file->inode;
+
+ if (!bpkfs_is_crc_file(d))
+ lseek(d->fd, d->offset + pos, SEEK_SET);
+
+ d->pos = pos;
+
+ return pos;
+}
+
+struct somfy_readdir {
+ struct bpkfs_handle_hw *h;
+ struct bpkfs_handle_data *d;
+
+ DIR dir;
+};
+
+static DIR *bpkfs_opendir(struct device_d *dev, const char *pathname)
+{
+ struct bpkfs_handle *priv = dev->priv;
+ struct somfy_readdir *sdir;
+ DIR *dir;
+
+ sdir = xzalloc(sizeof(*sdir));
+ dir = &sdir->dir;
+ dir->priv = sdir;
+
+ if (pathname[0] == '/')
+ pathname++;
+
+ if (!strlen(pathname)) {
+ if (list_empty(&priv->list))
+ return dir;
+
+ sdir->h = list_first_entry(&priv->list,
+ struct bpkfs_handle_hw, list_hw_id);
+ } else {
+ sdir->h = bpkfs_hw_id_get_by_name(priv, pathname);
+ if (!sdir->h || list_empty(&sdir->h->list_data))
+ return dir;
+
+ sdir->d = list_first_entry(&sdir->h->list_data,
+ struct bpkfs_handle_data, list);
+ }
+
+ return dir;
+}
+
+static struct dirent *bpkfs_readdir(struct device_d *dev, DIR *dir)
+{
+ struct bpkfs_handle *priv = dev->priv;
+ struct somfy_readdir *sdir = dir->priv;
+ struct bpkfs_handle_hw *h = sdir->h;
+ struct bpkfs_handle_data *d = sdir->d;
+
+ if (!h)
+ return NULL;
+
+ if (!d) {
+ if (&h->list_hw_id == &priv->list)
+ return NULL;
+
+ strcpy(dir->d.d_name, h->name);
+ sdir->h = list_entry(h->list_hw_id.next, struct bpkfs_handle_hw, list_hw_id);
+ } else {
+ if (&d->list == &h->list_data)
+ return NULL;
+
+ strcpy(dir->d.d_name, d->name);
+ sdir->d = list_entry(d->list.next, struct bpkfs_handle_data, list);
+ }
+
+ return &dir->d;
+}
+
+static int bpkfs_closedir(struct device_d *dev, DIR *dir)
+{
+ struct somfy_readdir *sdir = dir->priv;
+
+ free(sdir);
+ return 0;
+}
+
+static int bpkfs_stat(struct device_d *dev, const char *filename, struct stat *s)
+{
+ struct bpkfs_handle *priv = dev->priv;
+ struct bpkfs_handle_data *d;
+ struct bpkfs_handle_hw *h;
+ char *dir, *file;
+ int ret = -EINVAL;
+ char *tmp = xstrdup(filename);
+ char *tmp2 = xstrdup(filename);
+
+ dir = dirname(tmp);
+
+ if (filename[0] == '/')
+ filename++;
+
+ if (dir[0] == '/')
+ dir++;
+
+ if (!strlen(dir)) {
+ h = bpkfs_hw_id_get_by_name(priv, filename);
+ if (!h)
+ goto out;
+
+ s->st_size = strlen(filename);
+ s->st_mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO;
+ ret = 0;
+ goto out;
+ }
+ h = bpkfs_hw_id_get_by_name(priv, dir);
+ if (!h)
+ goto out;
+
+ file = basename(tmp2);
+ d = bpkfs_data_get_by_name(h, file);
+ if (!d)
+ goto out;
+
+ s->st_size = d->size;
+ s->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
+
+ ret = 0;
+
+out:
+ free(tmp);
+ free(tmp2);
+ return ret;
+}
+
+static void bpkfs_remove_data(struct bpkfs_handle_hw *h)
+{
+ struct bpkfs_handle_data *d, *tmp;
+
+ list_for_each_entry_safe(d, tmp, &h->list_data, list) {
+ free(d->name);
+ free(d);
+ }
+}
+
+static void bpkfs_remove(struct device_d *dev)
+{
+ struct bpkfs_handle *priv = dev->priv;
+ struct bpkfs_handle_hw *h, *tmp;
+
+ list_for_each_entry_safe(h, tmp, &priv->list, list_hw_id) {
+ bpkfs_remove_data(h);
+ free(h->name);
+ free(h);
+ }
+
+ free(priv);
+}
+
+static int bpkfs_probe(struct device_d *dev)
+{
+ struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct bpkfs_handle *priv;
+ struct bpkfs_header *header;
+ struct bpkfs_data_header data_header;
+ int ret = 0;
+ uint32_t checksum, crc;
+ uint64_t size;
+ int i;
+ size_t offset = 0;
+ char *buf;
+ int fd;
+
+ priv = xzalloc(sizeof(struct bpkfs_handle));
+ INIT_LIST_HEAD(&priv->list);
+ buf = xmalloc(2048);
+ dev->priv = priv;
+
+ priv->filename = fsdev->backingstore;
+ dev_dbg(dev, "mount: %s\n", fsdev->backingstore);
+
+ fd = open(fsdev->backingstore, O_RDONLY);
+ if (fd < 0) {
+ ret = fd;
+ goto err;
+ }
+
+ header = &priv->header;
+
+ ret = read(fd, header, sizeof(*header));
+ if (ret < 0) {
+ dev_err(dev, "could not read: %s (ret = %d)\n", errno_str(), ret);
+ goto err;
+ }
+
+ dev_dbg(dev, "header.magic = 0x%x\n", be32_to_cpu(header->magic));
+ dev_dbg(dev, "header.version = 0x%x\n", be32_to_cpu(header->version));
+ dev_dbg(dev, "header.crc = 0x%x\n", be32_to_cpu(header->crc));
+ dev_dbg(dev, "header.size = %llu\n", be64_to_cpu(header->size));
+ dev_dbg(dev, "header.spare = %llu\n", be64_to_cpu(header->spare));
+
+ size = be64_to_cpu(header->size);
+ offset += sizeof(*header);
+ size -= sizeof(*header);
+
+ checksum = be32_to_cpu(header->crc);
+ header->crc = 0;
+
+ crc = crc32(0, header, sizeof(*header));
+
+ for (i = 0; size; i++) {
+ struct bpkfs_handle_data *d;
+ struct bpkfs_handle_hw *h;
+ const char *type;
+
+ ret = read(fd, &data_header, sizeof(data_header));
+ if (ret < 0) {
+ dev_err(dev, "could not read: %s\n", errno_str());
+ goto err;
+ } else if (ret == 0) {
+ dev_err(dev, "EOF: to_read %llu\n", size);
+ goto err;
+ }
+
+ d = xzalloc(sizeof(*d));
+
+ crc = crc32(crc, &data_header, sizeof(data_header));
+ offset += sizeof(data_header);
+ size -= sizeof(data_header);
+
+ d->type = be32_to_cpu(data_header.type);
+ d->hw_id = be32_to_cpu(data_header.hw_id);
+ d->size = be64_to_cpu(data_header.size);
+ d->offset = offset;
+ d->crc = be32_to_cpu(data_header.crc);
+ type = bpkfs_type_to_str(d->type);
+
+ h = bpkfs_get_or_add_hw_id(priv, d->hw_id);
+
+ if (!type) {
+ type = "unknown";
+ d->name = asprintf("%s_%08x", type, d->type);
+ } else {
+ d->name = xstrdup(type);
+ }
+
+ dev_dbg(dev, "%d: type = 0x%x => %s\n", i, d->type, d->name);
+ dev_dbg(dev, "%d: size = %llu\n", i, d->size);
+ dev_dbg(dev, "%d: offset = %d\n", i, d->offset);
+
+ dev_dbg(dev, "%d: hw_id = 0x%x => %s\n", i, h->hw_id, h->name);
+
+ offset += d->size;
+ size -= d->size;
+
+ if (bpkfs_get_by_type(priv, d->hw_id, d->type)) {
+ dev_info(dev, "ignore data %d type %s already present, ignored\n",
+ i, type);
+ free(d);
+ continue;
+ }
+
+ list_add_tail(&d->list, &h->list_data);
+ priv->nb_data_entries++;
+
+ ret = lseek(fd, d->size, SEEK_CUR);
+ if (ret < 0) {
+ dev_err(dev, "could not seek: %s\n", errno_str());
+ goto err;
+ }
+
+ type = d->name;
+ d = xzalloc(sizeof(*d));
+ d->type = be32_to_cpu(data_header.type);
+ d->name = asprintf("%s.crc", type);
+ d->type |= (1 << 31);
+ d->size = 8;
+ sprintf(d->data, "%08x", be32_to_cpu(data_header.crc));
+ list_add_tail(&d->list, &h->list_data);
+ }
+
+ if (crc != checksum) {
+ dev_err(dev, "invalid crc (0x%x != 0x%x)\n", checksum, crc);
+ goto err;
+ }
+
+ close(fd);
+ free(buf);
+
+ return 0;
+
+err:
+ close(fd);
+ free(buf);
+ bpkfs_remove(dev);
+
+ return ret;
+}
+
+static struct fs_driver_d bpkfs_driver = {
+ .open = bpkfs_open,
+ .close = bpkfs_close,
+ .read = bpkfs_read,
+ .lseek = bpkfs_lseek,
+ .opendir = bpkfs_opendir,
+ .readdir = bpkfs_readdir,
+ .closedir = bpkfs_closedir,
+ .stat = bpkfs_stat,
+ .flags = 0,
+ .type = filetype_bpk,
+ .drv = {
+ .probe = bpkfs_probe,
+ .remove = bpkfs_remove,
+ .name = "bpkfs",
+ }
+};
+
+static int bpkfs_init(void)
+{
+ return register_fs_driver(&bpkfs_driver);
+}
+coredevice_initcall(bpkfs_init);
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c
index 99f6d49c2c..8218fcf2af 100644
--- a/fs/cramfs/cramfs.c
+++ b/fs/cramfs/cramfs.c
@@ -422,29 +422,33 @@ static int cramfs_probe(struct device_d *dev)
{
struct fs_device_d *fsdev;
struct cramfs_priv *priv;
+ int ret;
fsdev = dev_to_fs_device(dev);
priv = xmalloc(sizeof(struct cramfs_priv));
dev->priv = priv;
- if (strncmp(fsdev->backingstore, "/dev/", 5))
- return -ENODEV;
+ ret = fsdev_open_cdev(fsdev);
+ if (ret)
+ goto err_out;
- priv->cdev = cdev_by_name(fsdev->backingstore + 5);
- if (!priv->cdev)
- return -ENODEV;
+ priv->cdev = fsdev->cdev;
if (cramfs_read_super(priv)) {
dev_info(dev, "no valid cramfs found\n");
- free(priv);
- return -EINVAL;
+ ret = -EINVAL;
}
priv->curr_base = -1;
cramfs_uncompress_init ();
return 0;
+
+err_out:
+ free(priv);
+
+ return ret;
}
static void cramfs_remove(struct device_d *dev)
diff --git a/fs/ext4/ext_barebox.c b/fs/ext4/ext_barebox.c
index adc8f758e0..69a7723b5c 100644
--- a/fs/ext4/ext_barebox.c
+++ b/fs/ext4/ext_barebox.c
@@ -225,7 +225,6 @@ static int ext_readlink(struct device_d *dev, const char *pathname,
static int ext_probe(struct device_d *dev)
{
struct fs_device_d *fsdev = dev_to_fs_device(dev);
- char *backingstore = fsdev->backingstore;
int ret;
struct ext_filesystem *fs;
@@ -234,14 +233,11 @@ static int ext_probe(struct device_d *dev)
dev->priv = fs;
fs->dev = dev;
- if (!strncmp(backingstore , "/dev/", 5))
- backingstore += 5;
-
- fs->cdev = cdev_open(backingstore, O_RDWR);
- if (!fs->cdev) {
- ret = -ENOENT;
+ ret = fsdev_open_cdev(fsdev);
+ if (ret)
goto err_open;
- }
+
+ fs->cdev = fsdev->cdev;
ret = ext4fs_mount(fs);
if (ret)
@@ -250,7 +246,6 @@ static int ext_probe(struct device_d *dev)
return 0;
err_mount:
- cdev_close(fs->cdev);
err_open:
free(fs);
@@ -262,7 +257,6 @@ static void ext_remove(struct device_d *dev)
struct ext_filesystem *fs = dev->priv;
ext4fs_umount(fs);
- cdev_close(fs->cdev);
free(fs);
}
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 15879c4160..e65ef585a2 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -373,19 +373,15 @@ static int fat_probe(struct device_d *dev)
{
struct fs_device_d *fsdev = dev_to_fs_device(dev);
struct fat_priv *priv = xzalloc(sizeof(struct fat_priv));
- char *backingstore = fsdev->backingstore;
int ret;
dev->priv = priv;
- if (!strncmp(backingstore , "/dev/", 5))
- backingstore += 5;
-
- priv->cdev = cdev_open(backingstore, O_RDWR);
- if (!priv->cdev) {
- ret = -ENOENT;
+ ret = fsdev_open_cdev(fsdev);
+ if (ret)
goto err_open;
- }
+
+ priv->cdev = fsdev->cdev;
priv->fat.userdata = priv;
ret = f_mount(&priv->fat);
@@ -395,7 +391,6 @@ static int fat_probe(struct device_d *dev)
return 0;
err_mount:
- cdev_close(priv->cdev);
err_open:
free(priv);
@@ -404,10 +399,6 @@ err_open:
static void fat_remove(struct device_d *dev)
{
- struct fat_priv *priv = dev->priv;
-
- cdev_close(priv->cdev);
-
free(dev->priv);
}
diff --git a/fs/fs.c b/fs/fs.c
index d913a503f2..ce7b425546 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -32,6 +32,7 @@
#include <magicvar.h>
#include <environment.h>
#include <libgen.h>
+#include <block.h>
void *read_file(const char *filename, size_t *size)
{
@@ -1231,6 +1232,9 @@ static void fs_remove(struct device_d *dev)
if (fsdev == fs_dev_root)
fs_dev_root = NULL;
+ if (fsdev->cdev)
+ cdev_close(fsdev->cdev);
+
free(fsdev->backingstore);
free(fsdev);
}
@@ -1266,10 +1270,7 @@ static const char *detect_fs(const char *filename)
if (type == filetype_unknown)
return NULL;
- for_each_driver(drv) {
- if (drv->bus != &fs_bus)
- continue;
-
+ bus_for_each_driver(&fs_bus, drv) {
fdrv = drv_to_fs_driver(drv);
if (type == fdrv->type)
@@ -1279,6 +1280,23 @@ static const char *detect_fs(const char *filename)
return NULL;
}
+int fsdev_open_cdev(struct fs_device_d *fsdev)
+{
+ const char *backingstore = fsdev->backingstore;
+
+ if (!strncmp(backingstore , "/dev/", 5))
+ backingstore += 5;
+
+ fsdev->cdev = cdev_open(backingstore, O_RDWR);
+ if (!fsdev->cdev)
+ return -EINVAL;
+
+ fsdev->dev.parent = fsdev->cdev->dev;
+ fsdev->parent_device = fsdev->cdev->dev;
+
+ return 0;
+}
+
/*
* Mount a device to a directory.
* We do this by registering a new device on which the filesystem
@@ -1323,14 +1341,6 @@ int mount(const char *device, const char *fsname, const char *_path)
fsdev->path = xstrdup(path);
fsdev->dev.bus = &fs_bus;
- if (!strncmp(device, "/dev/", 5))
- fsdev->cdev = cdev_by_name(device + 5);
-
- if (fsdev->cdev) {
- fsdev->dev.parent = fsdev->cdev->dev;
- fsdev->parent_device = fsdev->cdev->dev;
- }
-
ret = register_device(&fsdev->dev);
if (ret)
goto err_register;
@@ -1661,3 +1671,82 @@ ssize_t mem_write(struct cdev *cdev, const void *buf, size_t count, loff_t offse
return size;
}
EXPORT_SYMBOL(mem_write);
+
+/*
+ * cdev_get_mount_path - return the path a cdev is mounted on
+ *
+ * If a cdev is mounted return the path it's mounted on, NULL
+ * otherwise.
+ */
+const char *cdev_get_mount_path(struct cdev *cdev)
+{
+ struct fs_device_d *fsdev;
+
+ for_each_fs_device(fsdev) {
+ if (fsdev->cdev && fsdev->cdev == cdev)
+ return fsdev->path;
+ }
+
+ return NULL;
+}
+
+/*
+ * cdev_mount_default - mount a cdev to the default path
+ *
+ * If a cdev is already mounted return the path it's mounted on, otherwise
+ * mount it to /mnt/<cdevname> and return the path. Returns an error pointer
+ * on failure.
+ */
+const char *cdev_mount_default(struct cdev *cdev)
+{
+ const char *path;
+ char *newpath, *devpath;
+ int ret;
+
+ /*
+ * If this cdev is already mounted somewhere use this path
+ * instead of mounting it again to avoid corruption on the
+ * filesystem.
+ */
+ path = cdev_get_mount_path(cdev);
+ if (path)
+ return path;
+
+ newpath = asprintf("/mnt/%s", cdev->name);
+ make_directory(newpath);
+
+ devpath = asprintf("/dev/%s", cdev->name);
+
+ ret = mount(devpath, NULL, newpath);
+
+ free(devpath);
+
+ if (ret) {
+ free(newpath);
+ return ERR_PTR(ret);
+ }
+
+ return cdev_get_mount_path(cdev);
+}
+
+/*
+ * mount_all - iterate over block devices and mount all devices we are able to
+ */
+void mount_all(void)
+{
+ struct device_d *dev;
+ struct block_device *bdev;
+
+ if (!IS_ENABLED(CONFIG_BLOCK))
+ return;
+
+ for_each_device(dev)
+ device_detect(dev);
+
+ for_each_block_device(bdev) {
+ struct cdev *cdev = &bdev->cdev;
+
+ list_for_each_entry(cdev, &bdev->dev->cdevs, devices_list)
+ cdev_mount_default(cdev);
+ }
+}
diff --git a/fs/ubifs/ubifs.c b/fs/ubifs/ubifs.c
index 9df8dc5cbd..dfa6107458 100644
--- a/fs/ubifs/ubifs.c
+++ b/fs/ubifs/ubifs.c
@@ -553,25 +553,22 @@ static int ubifs_probe(struct device_d *dev)
{
struct fs_device_d *fsdev = dev_to_fs_device(dev);
struct ubifs_priv *priv = xzalloc(sizeof(struct ubifs_priv));
- char *backingstore = fsdev->backingstore;
int ret;
dev->priv = priv;
- if (!strncmp(backingstore , "/dev/", 5))
- backingstore += 5;
-
- priv->cdev = cdev_open(backingstore, O_RDONLY);
- if (!priv->cdev) {
- ret = -ENOENT;
+ ret = fsdev_open_cdev(fsdev);
+ if (ret)
goto err_free;
- }
+
+ priv->cdev = fsdev->cdev;
priv->ubi = ubi_open_volume_cdev(priv->cdev, UBI_READONLY);
if (IS_ERR(priv->ubi)) {
dev_err(dev, "failed to open ubi volume: %s\n",
strerror(-PTR_ERR(priv->ubi)));
- return PTR_ERR(priv->ubi);
+ ret = PTR_ERR(priv->ubi);
+ goto err_free;
}
priv->sb = ubifs_get_super(priv->ubi, 0);
@@ -596,7 +593,6 @@ static void ubifs_remove(struct device_d *dev)
ubifs_umount(c);
ubi_close_volume(priv->ubi);
- cdev_close(priv->cdev);
free(c);
free(sb);
diff --git a/fs/uimagefs.c b/fs/uimagefs.c
new file mode 100644
index 0000000000..6547b7cb77
--- /dev/null
+++ b/fs/uimagefs.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * under GPLv2 ONLY
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <fs.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <malloc.h>
+#include <init.h>
+#include <linux/stat.h>
+#include <linux/err.h>
+#include <uimagefs.h>
+#include <libbb.h>
+#include <rtc.h>
+
+static bool uimagefs_is_data_file(struct uimagefs_handle_data *d)
+{
+ return d->type == UIMAGEFS_DATA;
+}
+
+const char* uimagefs_type_to_str(enum uimagefs_type type)
+{
+ switch (type) {
+ case UIMAGEFS_DATA:
+ return "data";
+ case UIMAGEFS_DATA_CRC:
+ return "data.crc";
+ case UIMAGEFS_NAME:
+ return "name";
+ case UIMAGEFS_TIME:
+ return "time";
+ case UIMAGEFS_LOAD:
+ return "load_addr";
+ case UIMAGEFS_EP:
+ return "entry_point";
+ case UIMAGEFS_OS:
+ return "os";
+ case UIMAGEFS_ARCH:
+ return "arch";
+ case UIMAGEFS_TYPE:
+ return "type";
+ case UIMAGEFS_COMP:
+ return "compression";
+ }
+
+ return "unknown";
+}
+
+static struct uimagefs_handle_data *uimagefs_get_by_name(
+ struct uimagefs_handle *handle, const char *name)
+{
+ struct uimagefs_handle_data *d;
+
+ if (!name)
+ return NULL;
+
+ list_for_each_entry(d, &handle->list, list) {
+ if (strcmp(d->name, name) == 0)
+ return d;
+ }
+
+ return NULL;
+}
+
+static int uimagefs_open(struct device_d *dev, FILE *file, const char *filename)
+{
+ struct uimagefs_handle *priv = dev->priv;
+ struct uimagefs_handle_data *d;
+
+ if (filename[0] == '/')
+ filename++;
+
+ d = uimagefs_get_by_name(priv, filename);
+ if (!d)
+ return -EINVAL;
+
+ if (uimagefs_is_data_file(d)) {
+ d->fd = open(priv->filename, O_RDONLY);
+ if (d->fd < 0)
+ return d->fd;
+
+ lseek(d->fd, d->offset, SEEK_SET);
+ }
+
+ file->size = d->size;
+ file->inode = d;
+
+ return 0;
+}
+
+static int uimagefs_close(struct device_d *dev, FILE *file)
+{
+ struct uimagefs_handle_data *d = file->inode;
+
+ close(d->fd);
+
+ return 0;
+}
+
+static int uimagefs_read(struct device_d *dev, FILE *file, void *buf, size_t insize)
+{
+ struct uimagefs_handle_data *d = file->inode;
+
+ if (!uimagefs_is_data_file(d)) {
+ memcpy(buf, &d->data[d->pos], insize);
+ return insize;
+ } else {
+ return read(d->fd, buf, insize);
+ }
+}
+
+static loff_t uimagefs_lseek(struct device_d *dev, FILE *file, loff_t pos)
+{
+ struct uimagefs_handle_data *d = file->inode;
+
+ if (uimagefs_is_data_file(d))
+ lseek(d->fd, d->offset + pos, SEEK_SET);
+
+ d->pos = pos;
+
+ return pos;
+}
+
+static DIR *uimagefs_opendir(struct device_d *dev, const char *pathname)
+{
+ struct uimagefs_handle *priv = dev->priv;
+ DIR *dir;
+
+ dir = xzalloc(sizeof(DIR));
+
+ if (list_empty(&priv->list))
+ return dir;
+
+ dir->priv = list_first_entry(&priv->list,
+ struct uimagefs_handle_data, list);
+ return dir;
+}
+
+static struct dirent *uimagefs_readdir(struct device_d *dev, DIR *dir)
+{
+ struct uimagefs_handle *priv = dev->priv;
+ struct uimagefs_handle_data *d = dir->priv;
+
+ if (!d || &d->list == &priv->list)
+ return NULL;
+
+ strcpy(dir->d.d_name, d->name);
+ dir->priv = list_entry(d->list.next, struct uimagefs_handle_data, list);
+ return &dir->d;
+}
+
+static int uimagefs_closedir(struct device_d *dev, DIR *dir)
+{
+ free(dir);
+ return 0;
+}
+
+static int uimagefs_stat(struct device_d *dev, const char *filename, struct stat *s)
+{
+ struct uimagefs_handle *priv = dev->priv;
+ struct uimagefs_handle_data *d;
+
+ if (filename[0] == '/')
+ filename++;
+
+ d = uimagefs_get_by_name(priv, filename);
+ if (!d)
+ return -EINVAL;
+
+ s->st_size = d->size;
+ s->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO;
+
+ return 0;
+}
+
+static int uimagefs_ioctl(struct device_d *dev, FILE *f, int request, void *buf)
+{
+ struct uimagefs_handle *priv = dev->priv;
+
+ if (request != UIMAGEFS_METADATA)
+ return -EINVAL;
+
+ memcpy(buf, &priv->header, sizeof(struct image_header));
+
+ return 0;
+}
+
+static void uimagefs_remove(struct device_d *dev)
+{
+ struct uimagefs_handle *priv = dev->priv;
+ struct uimagefs_handle_data *d, *tmp;
+ struct stat s;
+
+ list_for_each_entry_safe(d, tmp, &priv->list, list) {
+ free(d->name);
+ free(d->data);
+ free(d);
+ }
+
+ if (IS_BUILTIN(CONFIG_FS_TFTP) && !stat(priv->tmp, &s))
+ unlink(priv->tmp);
+
+ free(priv->tmp);
+ free(priv);
+}
+
+static inline int uimage_is_multi_image(struct uimagefs_handle *priv)
+{
+ return (priv->header.ih_type == IH_TYPE_MULTI) ? 1 : 0;
+}
+
+static int uimagefs_add_str(struct uimagefs_handle *priv, enum uimagefs_type type,
+ char *s)
+{
+ struct uimagefs_handle_data *d;
+
+ d = xzalloc(sizeof(*d));
+ d->type = type;
+ d->name = xstrdup(uimagefs_type_to_str(type));
+ d->data = s;
+ d->size = strlen(s);
+
+ list_add_tail(&d->list, &priv->list);
+
+ return 0;
+}
+
+static int uimagefs_add_name(struct uimagefs_handle *priv)
+{
+ char *name;
+ struct image_header *header = &priv->header;
+
+ if (header->ih_name[0]) {
+ name = xzalloc(IH_NMLEN + 1);
+ strncpy(name, header->ih_name, IH_NMLEN);
+ } else {
+ name = xstrdup(priv->filename);
+ }
+
+ return uimagefs_add_str(priv, UIMAGEFS_NAME, name);
+}
+
+static int uimagefs_add_hex(struct uimagefs_handle *priv, enum uimagefs_type type,
+ uint32_t data)
+{
+ char *val = asprintf("0x%x", data);
+
+ return uimagefs_add_str(priv, type, val);
+}
+
+static int __uimagefs_add_data(struct uimagefs_handle *priv, size_t offset,
+ uint64_t size, int i)
+{
+ struct uimagefs_handle_data *d;
+ const char *name = uimagefs_type_to_str(UIMAGEFS_DATA);
+
+ d = xzalloc(sizeof(*d));
+ d->type = UIMAGEFS_DATA;
+ if (i < 0)
+ d->name = xstrdup(name);
+ else
+ d->name = asprintf("%s%d", name, i);
+
+ d->offset = offset;
+ d->size = size;
+
+ list_add_tail(&d->list, &priv->list);
+
+ return 0;
+}
+
+static int uimagefs_add_data(struct uimagefs_handle *priv, size_t offset,
+ uint64_t size)
+{
+ return __uimagefs_add_data(priv, offset, size, -1);
+}
+
+static int uimagefs_add_data_entry(struct uimagefs_handle *priv, size_t offset,
+ uint64_t size)
+{
+ int ret;
+
+ ret = __uimagefs_add_data(priv, offset, size, priv->nb_data_entries);
+ if (ret)
+ return ret;
+
+ priv->nb_data_entries++;
+
+ return 0;
+}
+
+#if defined(CONFIG_TIMESTAMP)
+static int uimagefs_add_time(struct uimagefs_handle *priv)
+{
+ struct image_header *header = &priv->header;
+ struct rtc_time tm;
+ char *val;
+
+ to_tm(header->ih_time, &tm);
+ val = asprintf("%4d-%02d-%02d %2d:%02d:%02d UTC",
+ tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ return uimagefs_add_str(priv, UIMAGEFS_TIME, val);
+}
+#else
+static int uimagefs_add_time(struct uimagefs_handle *priv)
+{
+ struct image_header *header = &priv->header;
+
+ return uimagefs_add_hex(priv, UIMAGEFS_TIME, header->ih_time);
+}
+#endif
+
+static int uimagefs_add_os(struct uimagefs_handle *priv)
+{
+ struct image_header *header = &priv->header;
+ char *val = xstrdup(image_get_os_name(header->ih_os));
+
+ return uimagefs_add_str(priv, UIMAGEFS_OS, val);
+}
+
+static int uimagefs_add_arch(struct uimagefs_handle *priv)
+{
+ struct image_header *header = &priv->header;
+ char *val = xstrdup(image_get_arch_name(header->ih_arch));
+
+ return uimagefs_add_str(priv, UIMAGEFS_ARCH, val);
+}
+
+static int uimagefs_add_type(struct uimagefs_handle *priv)
+{
+ struct image_header *header = &priv->header;
+ char *val = xstrdup(image_get_type_name(header->ih_type));
+
+ return uimagefs_add_str(priv, UIMAGEFS_TYPE, val);
+}
+
+static int uimagefs_add_comp(struct uimagefs_handle *priv)
+{
+ struct image_header *header = &priv->header;
+ char *val = xstrdup(image_get_comp_name(header->ih_comp));
+
+ return uimagefs_add_str(priv, UIMAGEFS_COMP, val);
+}
+
+/*
+ * open a uimage. This will check the header contents and
+ * return a handle to the uImage
+ */
+static int __uimage_open(struct uimagefs_handle *priv)
+{
+ int fd;
+ uint32_t checksum;
+ struct image_header *header;
+ int ret;
+ size_t offset = 0;
+ size_t data_offset = 0;
+
+again:
+ fd = open(priv->filename, O_RDONLY);
+ if (fd < 0) {
+ printf("could not open: %s\n", errno_str());
+ return fd;
+ }
+
+ /*
+ * Hack around tftp fs. We need lseek for uImage support, but
+ * this cannot be implemented in tftp fs, so we detect this
+ * by doing a test lseek and copy the file to ram if it fails
+ */
+ if (IS_BUILTIN(CONFIG_FS_TFTP) && lseek(fd, 0, SEEK_SET)) {
+ close(fd);
+ ret = copy_file(priv->filename, priv->tmp, 0);
+ if (ret)
+ return ret;
+ priv->filename = priv->tmp;
+ goto again;
+ }
+
+ header = &priv->header;
+
+ ret = read(fd, header, sizeof(*header));
+ if (ret < 0) {
+ printf("could not read: %s\n", errno_str());
+ goto err_out;
+ }
+ offset += sizeof(*header);
+
+ if (uimage_to_cpu(header->ih_magic) != IH_MAGIC) {
+ printf("Bad Magic Number\n");
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ checksum = uimage_to_cpu(header->ih_hcrc);
+ header->ih_hcrc = 0;
+
+ if (crc32(0, header, sizeof(*header)) != checksum) {
+ printf("Bad Header Checksum\n");
+ ret = -EIO;
+ goto err_out;
+ }
+
+ /* convert header to cpu native endianess */
+ header->ih_magic = uimage_to_cpu(header->ih_magic);
+ header->ih_hcrc = checksum;
+ header->ih_time = uimage_to_cpu(header->ih_time);
+ header->ih_size = uimage_to_cpu(header->ih_size);
+ header->ih_load = uimage_to_cpu(header->ih_load);
+ header->ih_ep = uimage_to_cpu(header->ih_ep);
+ header->ih_dcrc = uimage_to_cpu(header->ih_dcrc);
+
+ ret = uimagefs_add_arch(priv);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_comp(priv);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_name(priv);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_os(priv);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_time(priv);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_type(priv);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_hex(priv, UIMAGEFS_LOAD, header->ih_load);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_hex(priv, UIMAGEFS_EP, header->ih_ep);
+ if (ret)
+ goto err_out;
+
+ data_offset = offset;
+
+ if (uimage_is_multi_image(priv)) {
+ struct uimagefs_handle_data *d;
+
+ do {
+ u32 size;
+
+ ret = read(fd, &size, sizeof(size));
+ if (ret < 0)
+ goto err_out;
+
+ offset += sizeof(size);
+
+ if (!size)
+ break;
+
+ ret = uimagefs_add_data_entry(priv, 0, uimage_to_cpu(size));
+ if (ret)
+ goto err_out;
+ } while(1);
+
+ /* offset of the first image in a multifile image */
+ list_for_each_entry(d, &priv->list, list) {
+ if (!uimagefs_is_data_file(d))
+ continue;
+ d->offset = offset;
+ offset += (d->size + 3) & ~3;
+ }
+ } else {
+ ret = uimagefs_add_data_entry(priv, offset, header->ih_size);
+ if (ret)
+ goto err_out;
+ }
+
+ ret = uimagefs_add_data(priv, data_offset, header->ih_size);
+ if (ret)
+ goto err_out;
+
+ ret = uimagefs_add_hex(priv, UIMAGEFS_DATA_CRC, header->ih_dcrc);
+ if (ret)
+ goto err_out;
+
+ ret = 0;
+err_out:
+
+ close(fd);
+
+ return ret;
+}
+
+static int uimagefs_probe(struct device_d *dev)
+{
+ struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct uimagefs_handle *priv;
+ int ret = 0;
+
+ priv = xzalloc(sizeof(struct uimagefs_handle));
+ INIT_LIST_HEAD(&priv->list);
+ dev->priv = priv;
+
+ priv->filename = fsdev->backingstore;
+ dev_dbg(dev, "mount: %s\n", fsdev->backingstore);
+
+ if (IS_BUILTIN(CONFIG_FS_TFTP))
+ priv->tmp = asprintf("/.uImage_tmp_%08x",
+ crc32(0, fsdev->path, strlen(fsdev->path)));
+
+ ret = __uimage_open(priv);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ uimagefs_remove(dev);
+
+ return ret;
+}
+
+static struct fs_driver_d uimagefs_driver = {
+ .open = uimagefs_open,
+ .close = uimagefs_close,
+ .read = uimagefs_read,
+ .lseek = uimagefs_lseek,
+ .opendir = uimagefs_opendir,
+ .readdir = uimagefs_readdir,
+ .closedir = uimagefs_closedir,
+ .stat = uimagefs_stat,
+ .ioctl = uimagefs_ioctl,
+ .flags = 0,
+ .type = filetype_uimage,
+ .drv = {
+ .probe = uimagefs_probe,
+ .remove = uimagefs_remove,
+ .name = "uimagefs",
+ }
+};
+
+static int uimagefs_init(void)
+{
+ return register_fs_driver(&uimagefs_driver);
+}
+coredevice_initcall(uimagefs_init);
diff --git a/images/Makefile b/images/Makefile
index 0926615e01..b87f522c15 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -119,7 +119,8 @@ targets += $(foreach m, $(image-y), $(FILE_$(m)))
SECONDARY: $(addprefix $(obj)/,$(targets))
images: $(addprefix $(obj)/, $(image-y)) FORCE
- @echo "images built:\n" $(patsubst %,%\\n,$(image-y))
+ @echo "images built:"
+ @for i in $(image-y); do echo $$i; done
clean-files := *.pbl *.pblb *.pblx *.map start_*.imximg *.img barebox.z start_*.kwbimg \
start_*.kwbuartimg
diff --git a/include/block.h b/include/block.h
index eb31aca4db..872a4c1bba 100644
--- a/include/block.h
+++ b/include/block.h
@@ -2,6 +2,7 @@
#define __BLOCK_H
#include <driver.h>
+#include <linux/list.h>
struct block_device;
@@ -14,6 +15,7 @@ struct chunk;
struct block_device {
struct device_d *dev;
+ struct list_head list;
struct block_device_ops *ops;
int blockbits;
int num_blocks;
@@ -26,6 +28,10 @@ struct block_device {
struct cdev cdev;
};
+extern struct list_head block_device_list;
+
+#define for_each_block_device(bdev) list_for_each_entry(bdev, &block_device_list, list)
+
int blockdevice_register(struct block_device *blk);
int blockdevice_unregister(struct block_device *blk);
diff --git a/include/boot.h b/include/boot.h
index ccce8e1a42..56f6c359b9 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -7,6 +7,21 @@
#include <linux/list.h>
#include <environment.h>
+struct bootm_data {
+ const char *os_file;
+ const char *initrd_file;
+ const char *oftree_file;
+ int verbose;
+ bool verify;
+ bool force;
+ bool dryrun;
+ unsigned long initrd_address;
+ unsigned long os_address;
+ unsigned long os_entry;
+};
+
+int bootm_boot(struct bootm_data *data);
+
struct image_data {
/* simplest case. barebox has already loaded the os here */
struct resource *os_res;
@@ -50,6 +65,7 @@ struct image_data {
int verify;
int verbose;
int force;
+ int dryrun;
};
struct image_handler {
@@ -94,6 +110,4 @@ static inline int linux_bootargs_overwrite(const char *bootargs)
#define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
-int bootm_boot(struct image_data *);
-
#endif /* __BOOT_H */
diff --git a/include/console.h b/include/console.h
index ef6e193a20..550b440376 100644
--- a/include/console.h
+++ b/include/console.h
@@ -46,7 +46,6 @@ struct console_device {
struct list_head list;
- unsigned char f_caps;
unsigned char f_active;
unsigned int baudrate;
@@ -62,4 +61,11 @@ extern struct list_head console_list;
#define CFG_PBSIZE (CONFIG_CBSIZE+sizeof(CONFIG_PROMPT)+16)
+bool console_is_input_allow(void);
+void console_allow_input(bool val);
+
+extern int barebox_loglevel;
+
+struct console_device *console_get_first_active(void);
+
#endif
diff --git a/include/environment.h b/include/environment.h
index ae1ecf5bd6..a08f597000 100644
--- a/include/environment.h
+++ b/include/environment.h
@@ -45,7 +45,11 @@ char *var_name(struct variable_d *);
const char *getenv(const char *);
int setenv(const char *, const char *);
void export_env_ull(const char *name, unsigned long long val);
-unsigned long long getenv_ull(const char *name);
+int getenv_ull(const char *name, unsigned long long *val);
+int getenv_ul(const char *name, unsigned long *val);
+int getenv_uint(const char *name, unsigned int *val);
+int getenv_bool(const char *var, int *val);
+const char *getenv_nonempty(const char *var);
#else
static inline char *getenv(const char *var)
{
@@ -56,10 +60,22 @@ static inline int setenv(const char *var, const char *val)
{
return 0;
}
+
static inline void export_env_ull(const char *name, unsigned long long val) {}
-static inline unsigned long long getenv_ull(const char *name)
+
+static inline int getenv_ull(const char *name, unsigned long long *val)
{
- return 0;
+ return -EINVAL;
+}
+
+static inline int getenv_ul(const char *name, unsigned long *val)
+{
+ return -EINVAL;
+}
+
+static inline int getenv_uint(const char *name, unsigned int *val)
+{
+ return -EINVAL;
}
static inline int export(const char *var)
@@ -67,6 +83,15 @@ static inline int export(const char *var)
return -EINVAL;
}
+static inline int getenv_bool(const char *var, int *val)
+{
+ return -EINVAL;
+}
+
+static inline const char *getenv_nonempty(const char *var)
+{
+ return NULL;
+}
#endif
int env_pop_context(void);
diff --git a/include/filetype.h b/include/filetype.h
index 9a864daddb..ffefe1c905 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -28,6 +28,7 @@ enum filetype {
filetype_ext,
filetype_gpt,
filetype_ubifs,
+ filetype_bpk,
filetype_max,
};
diff --git a/include/fs.h b/include/fs.h
index 22c07467da..99f1689835 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -39,7 +39,6 @@ typedef struct filep {
#define FS_DRIVER_NO_DEV 1
struct fs_driver_d {
- char *name;
int (*probe) (struct device_d *dev);
int (*mkdir)(struct device_d *dev, const char *pathname);
int (*rmdir)(struct device_d *dev, const char *pathname);
@@ -88,6 +87,7 @@ struct fs_driver_d {
extern struct list_head fs_device_list;
#define for_each_fs_device(f) list_for_each_entry(f, &fs_device_list, list)
+extern struct bus_type fs_bus;
struct fs_device_d {
char *backingstore; /* the device we are associated with */
@@ -193,4 +193,9 @@ void automount_print(void);
int unlink_recursive(const char *path, char **failedpath);
+int fsdev_open_cdev(struct fs_device_d *fsdev);
+const char *cdev_get_mount_path(struct cdev *cdev);
+const char *cdev_mount_default(struct cdev *cdev);
+void mount_all(void);
+
#endif /* __FS_H */
diff --git a/include/globalvar.h b/include/globalvar.h
index c2a13b3657..456e8cd1f8 100644
--- a/include/globalvar.h
+++ b/include/globalvar.h
@@ -2,6 +2,10 @@
#define __GLOBALVAR_H
#include <param.h>
+#include <driver.h>
+#include <linux/err.h>
+
+extern struct device_d global_device;
#ifdef CONFIG_GLOBALVAR
int globalvar_add_simple(const char *name, const char *value);
@@ -12,12 +16,92 @@ int globalvar_add(const char *name,
unsigned long flags);
char *globalvar_get_match(const char *match, const char *separator);
void globalvar_set_match(const char *match, const char *val);
+
+static inline int globalvar_add_simple_int(const char *name,
+ int *value, const char *format)
+{
+ struct param_d *p;
+
+ p = dev_add_param_int(&global_device, name, NULL, NULL,
+ value, format, NULL);
+
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ return 0;
+}
+
+static inline int globalvar_add_simple_bool(const char *name,
+ int *value)
+{
+ struct param_d *p;
+
+ p = dev_add_param_bool(&global_device, name, NULL, NULL,
+ value, NULL);
+
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ return 0;
+}
+
+static inline int globalvar_add_simple_enum(const char *name,
+ int *value, const char **names, int max)
+{
+ struct param_d *p;
+
+ p = dev_add_param_enum(&global_device, name, NULL, NULL,
+ value, names, max, NULL);
+
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ return 0;
+}
+
+static inline int globalvar_add_simple_ip(const char *name,
+ IPaddr_t *ip)
+{
+ struct param_d *p;
+
+ p = dev_add_param_ip(&global_device, name, NULL, NULL,
+ ip, NULL);
+
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ return 0;
+}
#else
static inline int globalvar_add_simple(const char *name, const char *value)
{
return 0;
}
+static inline int globalvar_add_simple_int(const char *name,
+ int *value, const char *format)
+{
+ return 0;
+}
+
+static inline int globalvar_add_simple_bool(const char *name,
+ int *value)
+{
+ return 0;
+}
+
+static inline int globalvar_add_simple_enum(const char *name,
+ int *value, const char **names, int max)
+{
+ return 0;
+}
+
+static inline int globalvar_add_simple_ip(const char *name,
+ IPaddr_t *ip)
+{
+ return 0;
+}
+
static inline int globalvar_add(const char *name,
int (*set)(struct device_d *dev, struct param_d *p, const char *val),
const char *(*get)(struct device_d *, struct param_d *p),
diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index 46185ac921..81e5daa200 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -36,6 +36,7 @@ struct i2c_platform_data {
#define I2C_M_DATA_ONLY 0x0002 /* transfer data bytes only */
#define I2C_M_TEN 0x0010 /* this is a ten bit chip address */
#define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */
/**
* struct i2c_msg - an I2C transaction segment beginning with START
diff --git a/include/local_mac_address.h b/include/local_mac_address.h
new file mode 100644
index 0000000000..3d1ec66b1f
--- /dev/null
+++ b/include/local_mac_address.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#ifndef __LOCAL_MAC_ADDRESS_H__
+#define __LOCAL_MAC_ADDRESS_H__
+
+#include <net.h>
+
+/**
+ * local_mac_address_register - use random number with fix
+ * OUI provided device to provide an Ethernet address
+ * @ethid: ethernet device id
+ * @oui: Ethernet OUI (3 bytes)
+ *
+ * Generate a local Ethernet address (MAC) that is not multicast using a 1-wire id.
+ */
+static inline int local_mac_address_register(int ethid, char * oui)
+{
+ char addr[6];
+ int nb_oui = 3;
+ int i;
+
+ if (!oui)
+ return -EINVAL;
+
+ random_ether_addr(addr);
+
+ for (i = 0; i < nb_oui; i++)
+ addr[i] = oui[i];
+
+ addr[0] &= 0xfe; /* clear multicast bit */
+ addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
+
+ eth_register_ethaddr(ethid, addr);
+
+ return 0;
+}
+
+#endif /* __LOCAL_MAC_ADDRESS_H__ */
diff --git a/include/lzo.h b/include/lzo.h
index ceacfba692..6c34be13ef 100644
--- a/include/lzo.h
+++ b/include/lzo.h
@@ -4,18 +4,18 @@
* LZO Public Kernel Interface
* A mini subset of the LZO real-time data compression library
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
-#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *))
-#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS
+#define LZO1X_1_MEM_COMPRESS (8192 * sizeof(unsigned short))
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
@@ -44,6 +44,7 @@ STATIC int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
#define LZO_E_EOF_NOT_FOUND (-7)
#define LZO_E_INPUT_NOT_CONSUMED (-8)
#define LZO_E_NOT_YET_IMPLEMENTED (-9)
+#define LZO_E_INVALID_ARGUMENT (-10)
STATIC int decompress_unlzo(u8 *input, int in_len,
int (*fill) (void *, unsigned int),
diff --git a/include/net/designware.h b/include/net/designware.h
index 3f31c97610..7a7a26abfd 100644
--- a/include/net/designware.h
+++ b/include/net/designware.h
@@ -7,6 +7,7 @@ struct dwc_ether_platform_data {
int phy_addr;
phy_interface_t interface;
void (*fix_mac_speed)(int speed);
+ bool enh_desc; /* use Alternate/Enhanced Descriptor configurations */
};
#endif
diff --git a/include/net/smc91111.h b/include/net/smc91111.h
new file mode 100644
index 0000000000..0b2d49bb19
--- /dev/null
+++ b/include/net/smc91111.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnio@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#ifndef __SMC91111_H__
+#define __SMC91111_H__
+
+struct smc91c111_pdata {
+ int qemu_fixup;
+};
+
+#endif /* __SMC91111_H__ */
diff --git a/include/password.h b/include/password.h
index df03cd7561..0dd1054054 100644
--- a/include/password.h
+++ b/include/password.h
@@ -28,11 +28,23 @@
int password(unsigned char *passwd, size_t length, int flags, int timeout);
int read_passwd(unsigned char *sum, size_t length);
-int write_passwd(unsigned char *sum, size_t length);
-
-int is_passwd_enable(void);
-int passwd_disable(void);
int check_passwd(unsigned char* passwd, size_t length);
-int set_passwd(unsigned char* passwd, size_t length);
+
+int read_env_passwd(unsigned char *sum, size_t length);
+int write_env_passwd(unsigned char *sum, size_t length);
+
+int read_default_passwd(unsigned char *sum, size_t length);
+int is_passwd_default_enable(void);
+int check_default_passwd(unsigned char* passwd, size_t length);
+
+int is_passwd_env_enable(void);
+int passwd_env_disable(void);
+int check_env_passwd(unsigned char* passwd, size_t length);
+int set_env_passwd(unsigned char* passwd, size_t length);
+
+static inline int is_passwd_enable(void)
+{
+ return is_passwd_default_enable() || is_passwd_env_enable();
+}
#endif /* __PASSWORD_H__ */
diff --git a/include/platform_data/dw_mmc.h b/include/platform_data/dw_mmc.h
new file mode 100644
index 0000000000..48faa76c63
--- /dev/null
+++ b/include/platform_data/dw_mmc.h
@@ -0,0 +1,9 @@
+#ifndef __INCLUDE_PLATFORM_DATA_DW_MMC_H
+#define __INCLUDE_PLATFORM_DATA_DW_MMC_H
+
+struct dw_mmc_platform_data {
+ char *devname;
+ int ciu_div;
+};
+
+#endif /* __INCLUDE_PLATFORM_DATA_DW_MMC_H */
diff --git a/include/printk.h b/include/printk.h
index 86bf208425..f550f07bb8 100644
--- a/include/printk.h
+++ b/include/printk.h
@@ -18,12 +18,15 @@
/* debugging and troubleshooting/diagnostic helpers. */
-int dev_printf(const struct device_d *dev, const char *format, ...)
+int pr_print(int level, const char *format, ...)
__attribute__ ((format(__printf__, 2, 3)));
+int dev_printf(int level, const struct device_d *dev, const char *format, ...)
+ __attribute__ ((format(__printf__, 3, 4)));
+
#define __dev_printf(level, dev, format, args...) \
({ \
- (level) <= LOGLEVEL ? dev_printf((dev), (format), ##args) : 0; \
+ (level) <= LOGLEVEL ? dev_printf((level), (dev), (format), ##args) : 0; \
})
@@ -46,7 +49,7 @@ int dev_printf(const struct device_d *dev, const char *format, ...)
#define __pr_printk(level, format, args...) \
({ \
- (level) <= LOGLEVEL ? printk((format), ##args) : 0; \
+ (level) <= LOGLEVEL ? pr_print((level), (format), ##args) : 0; \
})
#ifndef pr_fmt
diff --git a/include/shell.h b/include/shell.h
new file mode 100644
index 0000000000..b98cac3dc5
--- /dev/null
+++ b/include/shell.h
@@ -0,0 +1,12 @@
+/*
+ * (C) Copyright 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#ifndef __SHELL_H__
+#define __SHELL_H__
+
+int shell_get_last_return_code(void);
+
+#endif /* __SHELL_H__ */
diff --git a/include/uimagefs.h b/include/uimagefs.h
new file mode 100644
index 0000000000..81b32310ad
--- /dev/null
+++ b/include/uimagefs.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * under GPLv2 only
+ */
+
+#ifndef __UIMAGEFS_H__
+#define __UIMAGEFS_H__
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <image.h>
+#include <ioctl.h>
+
+#define UIMAGEFS_METADATA _IOR('U', 100, struct image_header)
+
+enum uimagefs_type {
+ UIMAGEFS_DATA,
+ UIMAGEFS_DATA_CRC,
+ UIMAGEFS_NAME,
+ UIMAGEFS_TIME,
+ UIMAGEFS_LOAD,
+ UIMAGEFS_EP,
+ UIMAGEFS_OS,
+ UIMAGEFS_ARCH,
+ UIMAGEFS_TYPE,
+ UIMAGEFS_COMP,
+};
+
+struct uimagefs_handle_data {
+ char *name;
+ enum uimagefs_type type;
+ uint64_t size;
+
+ int fd;
+ size_t offset; /* offset in the image */
+ size_t pos; /* pos in the data */
+
+ char *data;
+
+ struct list_head list;
+};
+
+struct uimagefs_handle {
+ struct image_header header;
+ int nb_data_entries;
+ char *filename;
+ char *tmp;
+
+ struct list_head list;
+};
+
+#endif /* __UIMAGEFS_H__ */
diff --git a/include/usb/usb.h b/include/usb/usb.h
index 95fb6f3a3b..821724e544 100644
--- a/include/usb/usb.h
+++ b/include/usb/usb.h
@@ -210,6 +210,7 @@ struct usb_host {
struct list_head list;
+ struct device_d *hw_dev;
int busnum;
int scanned;
};
diff --git a/lib/copy_file.c b/lib/copy_file.c
index ab3d845a5b..778cc00901 100644
--- a/lib/copy_file.c
+++ b/lib/copy_file.c
@@ -29,7 +29,7 @@ int copy_file(const char *src, const char *dst, int verbose)
goto out;
}
- dstfd = open(dst, O_WRONLY | O_CREAT);
+ dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC);
if (dstfd < 0) {
printf("could not open %s: %s\n", dst, errno_str());
goto out;
@@ -63,8 +63,12 @@ int copy_file(const char *src, const char *dst, int verbose)
total += w;
}
- if (verbose)
- show_progress(statbuf.st_size ? total : total / 16384);
+ if (verbose) {
+ if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX)
+ show_progress(total);
+ else
+ show_progress(total / 16384);
+ }
}
ret = 0;
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c
index 1b2dc9d179..5ee36670fc 100644
--- a/lib/decompress_unlzo.c
+++ b/lib/decompress_unlzo.c
@@ -33,7 +33,7 @@
#ifdef STATIC
#include <linux/decompress/mm.h>
-#include "lzo/lzo1x_decompress.c"
+#include "lzo/lzo1x_decompress_safe.c"
#else
#include <malloc.h>
#endif
@@ -108,7 +108,7 @@ static inline int parse_header(u8 *input, int *skip, int in_len)
return 1;
}
-STATIC int decompress_unlzo(u8 *input, int in_len,
+int decompress_unlzo(u8 *input, int in_len,
int (*fill) (void *, unsigned int),
int (*flush) (void *, unsigned int),
u8 *output, int *posp,
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
index e1a97aebc3..f2191f4a3d 100644
--- a/lib/lzo/Makefile
+++ b/lib/lzo/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_LZO_COMPRESS) += lzo1x_compress.o
-obj-$(CONFIG_LZO_DECOMPRESS) += lzo1x_decompress.o
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo1x_decompress_safe.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
index a6040990a6..236eb21167 100644
--- a/lib/lzo/lzo1x_compress.c
+++ b/lib/lzo/lzo1x_compress.c
@@ -1,194 +1,243 @@
/*
- * LZO1X Compressor from MiniLZO
+ * LZO1X Compressor from LZO
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
#include <linux/module.h>
#include <linux/kernel.h>
-#include <linux/lzo.h>
#include <asm/unaligned.h>
+#include <linux/lzo.h>
#include "lzodefs.h"
static noinline size_t
-_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len, void *wrkmem)
+lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ size_t ti, void *wrkmem)
{
+ const unsigned char *ip;
+ unsigned char *op;
const unsigned char * const in_end = in + in_len;
- const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
- const unsigned char ** const dict = wrkmem;
- const unsigned char *ip = in, *ii = ip;
- const unsigned char *end, *m, *m_pos;
- size_t m_off, m_len, dindex;
- unsigned char *op = out;
+ const unsigned char * const ip_end = in + in_len - 20;
+ const unsigned char *ii;
+ lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
- ip += 4;
+ op = out;
+ ip = in;
+ ii = ip;
+ ip += ti < 4 ? 4 - ti : 0;
for (;;) {
- dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
- m_pos = dict[dindex];
-
- if (m_pos < in)
- goto literal;
-
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
- goto literal;
-
- m_off = ip - m_pos;
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
- goto try_match;
-
- dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
- m_pos = dict[dindex];
-
- if (m_pos < in)
- goto literal;
-
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
- goto literal;
-
- m_off = ip - m_pos;
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
- goto try_match;
-
- goto literal;
-
-try_match:
- if (get_unaligned((const unsigned short *)m_pos)
- == get_unaligned((const unsigned short *)ip)) {
- if (likely(m_pos[2] == ip[2]))
- goto match;
- }
-
+ const unsigned char *m_pos;
+ size_t t, m_len, m_off;
+ u32 dv;
literal:
- dict[dindex] = ip;
- ++ip;
+ ip += 1 + ((ip - ii) >> 5);
+next:
if (unlikely(ip >= ip_end))
break;
- continue;
-
-match:
- dict[dindex] = ip;
- if (ip != ii) {
- size_t t = ip - ii;
+ dv = get_unaligned_le32(ip);
+ t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
+ m_pos = in + dict[t];
+ dict[t] = (lzo_dict_t) (ip - in);
+ if (unlikely(dv != get_unaligned_le32(m_pos)))
+ goto literal;
+ ii -= ti;
+ ti = 0;
+ t = ip - ii;
+ if (t != 0) {
if (t <= 3) {
op[-2] |= t;
- } else if (t <= 18) {
+ COPY4(op, ii);
+ op += t;
+ } else if (t <= 16) {
*op++ = (t - 3);
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += t;
} else {
- size_t tt = t - 18;
-
- *op++ = 0;
- while (tt > 255) {
- tt -= 255;
+ if (t <= 18) {
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
*op++ = 0;
+ while (unlikely(tt > 255)) {
+ tt -= 255;
+ *op++ = 0;
+ }
+ *op++ = tt;
}
- *op++ = tt;
+ do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
+ *op++ = *ii++;
+ } while (--t > 0);
}
- do {
- *op++ = *ii++;
- } while (--t > 0);
}
- ip += 3;
- if (m_pos[3] != *ip++ || m_pos[4] != *ip++
- || m_pos[5] != *ip++ || m_pos[6] != *ip++
- || m_pos[7] != *ip++ || m_pos[8] != *ip++) {
- --ip;
- m_len = ip - ii;
+ m_len = 4;
+ {
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
+ u64 v;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
+ do {
+ m_len += 8;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
+ }
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctzll(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clzll(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
+ u32 v;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
+ do {
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (v != 0)
+ break;
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
+ }
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctz(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clz(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#else
+ if (unlikely(ip[m_len] == m_pos[m_len])) {
+ do {
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (ip[m_len] == m_pos[m_len]);
+ }
+#endif
+ }
+m_len_done:
- if (m_off <= M2_MAX_OFFSET) {
- m_off -= 1;
- *op++ = (((m_len - 1) << 5)
- | ((m_off & 7) << 2));
- *op++ = (m_off >> 3);
- } else if (m_off <= M3_MAX_OFFSET) {
- m_off -= 1;
+ m_off = ip - m_pos;
+ ip += m_len;
+ ii = ip;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
+ m_off -= 1;
+ *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = (m_off >> 3);
+ } else if (m_off <= M3_MAX_OFFSET) {
+ m_off -= 1;
+ if (m_len <= M3_MAX_LEN)
*op++ = (M3_MARKER | (m_len - 2));
- goto m3_m4_offset;
- } else {
- m_off -= 0x4000;
-
- *op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
- | (m_len - 2));
- goto m3_m4_offset;
+ else {
+ m_len -= M3_MAX_LEN;
+ *op++ = M3_MARKER | 0;
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ *op++ = (m_len);
}
+ *op++ = (m_off << 2);
+ *op++ = (m_off >> 6);
} else {
- end = in_end;
- m = m_pos + M2_MAX_LEN + 1;
-
- while (ip < end && *m == *ip) {
- m++;
- ip++;
- }
- m_len = ip - ii;
-
- if (m_off <= M3_MAX_OFFSET) {
- m_off -= 1;
- if (m_len <= 33) {
- *op++ = (M3_MARKER | (m_len - 2));
- } else {
- m_len -= 33;
- *op++ = M3_MARKER | 0;
- goto m3_m4_len;
- }
- } else {
- m_off -= 0x4000;
- if (m_len <= M4_MAX_LEN) {
- *op++ = (M4_MARKER
- | ((m_off & 0x4000) >> 11)
+ m_off -= 0x4000;
+ if (m_len <= M4_MAX_LEN)
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8)
| (m_len - 2));
- } else {
- m_len -= M4_MAX_LEN;
- *op++ = (M4_MARKER
- | ((m_off & 0x4000) >> 11));
-m3_m4_len:
- while (m_len > 255) {
- m_len -= 255;
- *op++ = 0;
- }
-
- *op++ = (m_len);
+ else {
+ m_len -= M4_MAX_LEN;
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8));
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
}
+ *op++ = (m_len);
}
-m3_m4_offset:
- *op++ = ((m_off & 63) << 2);
+ *op++ = (m_off << 2);
*op++ = (m_off >> 6);
}
-
- ii = ip;
- if (unlikely(ip >= ip_end))
- break;
+ goto next;
}
-
*out_len = op - out;
- return in_end - ii;
+ return in_end - (ii - ti);
}
-int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
- size_t *out_len, void *wrkmem)
+int lzo1x_1_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ void *wrkmem)
{
- const unsigned char *ii;
+ const unsigned char *ip = in;
unsigned char *op = out;
- size_t t;
+ size_t l = in_len;
+ size_t t = 0;
- if (unlikely(in_len <= M2_MAX_LEN + 5)) {
- t = in_len;
- } else {
- t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
+ while (l > 20) {
+ size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
+ uintptr_t ll_end = (uintptr_t) ip + ll;
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end)
+ break;
+ BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
+ memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
+ t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem);
+ ip += ll;
op += *out_len;
+ l -= ll;
}
+ t += l;
if (t > 0) {
- ii = in + in_len - t;
+ const unsigned char *ii = in + in_len - t;
if (op == out && t <= 238) {
*op++ = (17 + t);
@@ -198,16 +247,21 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
*op++ = (t - 3);
} else {
size_t tt = t - 18;
-
*op++ = 0;
while (tt > 255) {
tt -= 255;
*op++ = 0;
}
-
*op++ = tt;
}
- do {
+ if (t >= 16) do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
*op++ = *ii++;
} while (--t > 0);
}
@@ -223,4 +277,3 @@ EXPORT_SYMBOL_GPL(lzo1x_1_compress);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LZO1X-1 Compressor");
-
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
deleted file mode 100644
index 7f1451f085..0000000000
--- a/lib/lzo/lzo1x_decompress.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * LZO1X Decompressor from MiniLZO
- *
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
- *
- * The full LZO package can be found at:
- * http://www.oberhumer.com/opensource/lzo/
- *
- * Changed for kernel use by:
- * Nitin Gupta <nitingupta910@gmail.com>
- * Richard Purdie <rpurdie@openedhand.com>
- */
-
-#include <asm/unaligned.h>
-#include <common.h>
-#include <lzo.h>
-#include "lzodefs.h"
-
-#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
-#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
-#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
-
-#define COPY4(dst, src) \
- put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
-
-STATIC int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
- unsigned char *out, size_t *out_len)
-{
- const unsigned char * const ip_end = in + in_len;
- unsigned char * const op_end = out + *out_len;
- const unsigned char *ip = in, *m_pos;
- unsigned char *op = out;
- size_t t;
-
- *out_len = 0;
-
- if (*ip > 17) {
- t = *ip++ - 17;
- if (t < 4)
- goto match_next;
- if (HAVE_OP(t, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 1, ip_end, ip))
- goto input_overrun;
- do {
- *op++ = *ip++;
- } while (--t > 0);
- goto first_literal_run;
- }
-
- while ((ip < ip_end)) {
- t = *ip++;
- if (t >= 16)
- goto match;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 15 + *ip++;
- }
- if (HAVE_OP(t + 3, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 4, ip_end, ip))
- goto input_overrun;
-
- COPY4(op, ip);
- op += 4;
- ip += 4;
- if (--t > 0) {
- if (t >= 4) {
- do {
- COPY4(op, ip);
- op += 4;
- ip += 4;
- t -= 4;
- } while (t >= 4);
- if (t > 0) {
- do {
- *op++ = *ip++;
- } while (--t > 0);
- }
- } else {
- do {
- *op++ = *ip++;
- } while (--t > 0);
- }
- }
-
-first_literal_run:
- t = *ip++;
- if (t >= 16)
- goto match;
- m_pos = op - (1 + M2_MAX_OFFSET);
- m_pos -= t >> 2;
- m_pos -= *ip++ << 2;
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
-
- if (HAVE_OP(3, op_end, op))
- goto output_overrun;
- *op++ = *m_pos++;
- *op++ = *m_pos++;
- *op++ = *m_pos;
-
- goto match_done;
-
- do {
-match:
- if (t >= 64) {
- m_pos = op - 1;
- m_pos -= (t >> 2) & 7;
- m_pos -= *ip++ << 3;
- t = (t >> 5) - 1;
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(t + 3 - 1, op_end, op))
- goto output_overrun;
- goto copy_match;
- } else if (t >= 32) {
- t &= 31;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 31 + *ip++;
- }
- m_pos = op - 1;
- m_pos -= get_unaligned_le16(ip) >> 2;
- ip += 2;
- } else if (t >= 16) {
- m_pos = op;
- m_pos -= (t & 8) << 11;
-
- t &= 7;
- if (t == 0) {
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- while (*ip == 0) {
- t += 255;
- ip++;
- if (HAVE_IP(1, ip_end, ip))
- goto input_overrun;
- }
- t += 7 + *ip++;
- }
- m_pos -= get_unaligned_le16(ip) >> 2;
- ip += 2;
- if (m_pos == op)
- goto eof_found;
- m_pos -= 0x4000;
- } else {
- m_pos = op - 1;
- m_pos -= t >> 2;
- m_pos -= *ip++ << 2;
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(2, op_end, op))
- goto output_overrun;
-
- *op++ = *m_pos++;
- *op++ = *m_pos;
- goto match_done;
- }
-
- if (HAVE_LB(m_pos, out, op))
- goto lookbehind_overrun;
- if (HAVE_OP(t + 3 - 1, op_end, op))
- goto output_overrun;
-
- if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
- COPY4(op, m_pos);
- op += 4;
- m_pos += 4;
- t -= 4 - (3 - 1);
- do {
- COPY4(op, m_pos);
- op += 4;
- m_pos += 4;
- t -= 4;
- } while (t >= 4);
- if (t > 0)
- do {
- *op++ = *m_pos++;
- } while (--t > 0);
- } else {
-copy_match:
- *op++ = *m_pos++;
- *op++ = *m_pos++;
- do {
- *op++ = *m_pos++;
- } while (--t > 0);
- }
-match_done:
- t = ip[-2] & 3;
- if (t == 0)
- break;
-match_next:
- if (HAVE_OP(t, op_end, op))
- goto output_overrun;
- if (HAVE_IP(t + 1, ip_end, ip))
- goto input_overrun;
-
- *op++ = *ip++;
- if (t > 1) {
- *op++ = *ip++;
- if (t > 2)
- *op++ = *ip++;
- }
-
- t = *ip++;
- } while (ip < ip_end);
- }
-
- *out_len = op - out;
- return LZO_E_EOF_NOT_FOUND;
-
-eof_found:
- *out_len = op - out;
- return (ip == ip_end ? LZO_E_OK :
- (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
-input_overrun:
- *out_len = op - out;
- return LZO_E_INPUT_OVERRUN;
-
-output_overrun:
- *out_len = op - out;
- return LZO_E_OUTPUT_OVERRUN;
-
-lookbehind_overrun:
- *out_len = op - out;
- return LZO_E_LOOKBEHIND_OVERRUN;
-}
-
-EXPORT_SYMBOL(lzo1x_decompress_safe);
-
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
new file mode 100644
index 0000000000..de795a3cff
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -0,0 +1,230 @@
+/*
+ * LZO1X Decompressor from LZO
+ *
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for Linux kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <asm/unaligned.h>
+#include <common.h>
+#include <lzo.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x))
+#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
+#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun
+#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
+#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len)
+{
+ unsigned char *op;
+ const unsigned char *ip;
+ size_t t, next;
+ size_t state = 0;
+ const unsigned char *m_pos;
+ const unsigned char * const ip_end = in + in_len;
+ unsigned char * const op_end = out + *out_len;
+
+ op = out;
+ ip = in;
+
+ if (unlikely(in_len < 3))
+ goto input_overrun;
+ if (*ip > 17) {
+ t = *ip++ - 17;
+ if (t < 4) {
+ next = t;
+ goto match_next;
+ }
+ goto copy_literal_run;
+ }
+
+ for (;;) {
+ t = *ip++;
+ if (t < 16) {
+ if (likely(state == 0)) {
+ if (unlikely(t == 0)) {
+ while (unlikely(*ip == 0)) {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 15 + *ip++;
+ }
+ t += 3;
+copy_literal_run:
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
+ const unsigned char *ie = ip + t;
+ unsigned char *oe = op + t;
+ do {
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+ } while (ip < ie);
+ ip = ie;
+ op = oe;
+ } else
+#endif
+ {
+ NEED_OP(t);
+ NEED_IP(t + 3);
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ state = 4;
+ continue;
+ } else if (state != 4) {
+ next = t & 3;
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ TEST_LB(m_pos);
+ NEED_OP(2);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ goto match_next;
+ } else {
+ next = t & 3;
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ t = 3;
+ }
+ } else if (t >= 64) {
+ next = t & 3;
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1 + (3 - 1);
+ } else if (t >= 32) {
+ t = (t & 31) + (3 - 1);
+ if (unlikely(t == 2)) {
+ while (unlikely(*ip == 0)) {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 31 + *ip++;
+ NEED_IP(2);
+ }
+ m_pos = op - 1;
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ } else {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+ t = (t & 7) + (3 - 1);
+ if (unlikely(t == 2)) {
+ while (unlikely(*ip == 0)) {
+ t += 255;
+ ip++;
+ NEED_IP(1);
+ }
+ t += 7 + *ip++;
+ NEED_IP(2);
+ }
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ }
+ TEST_LB(m_pos);
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (op - m_pos >= 8) {
+ unsigned char *oe = op + t;
+ if (likely(HAVE_OP(t + 15))) {
+ do {
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+ } while (op < oe);
+ op = oe;
+ if (HAVE_IP(6)) {
+ state = next;
+ COPY4(op, ip);
+ op += next;
+ ip += next;
+ continue;
+ }
+ } else {
+ NEED_OP(t);
+ do {
+ *op++ = *m_pos++;
+ } while (op < oe);
+ }
+ } else
+#endif
+ {
+ unsigned char *oe = op + t;
+ NEED_OP(t);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ m_pos += 2;
+ do {
+ *op++ = *m_pos++;
+ } while (op < oe);
+ }
+match_next:
+ state = next;
+ t = next;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(6) && HAVE_OP(4))) {
+ COPY4(op, ip);
+ op += t;
+ ip += t;
+ } else
+#endif
+ {
+ NEED_IP(t + 3);
+ NEED_OP(t);
+ while (t > 0) {
+ *op++ = *ip++;
+ t--;
+ }
+ }
+ }
+
+eof_found:
+ *out_len = op - out;
+ return (t != 3 ? LZO_E_ERROR :
+ ip == ip_end ? LZO_E_OK :
+ ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
+
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+}
+
+EXPORT_SYMBOL(lzo1x_decompress_safe);
+
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
index b6d482c492..6710b83ce7 100644
--- a/lib/lzo/lzodefs.h
+++ b/lib/lzo/lzodefs.h
@@ -1,19 +1,37 @@
/*
* lzodefs.h -- architecture, OS and compiler specific defines
*
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
*
* The full LZO package can be found at:
* http://www.oberhumer.com/opensource/lzo/
*
- * Changed for kernel use by:
+ * Changed for Linux kernel use by:
* Nitin Gupta <nitingupta910@gmail.com>
* Richard Purdie <rpurdie@openedhand.com>
*/
-#define LZO_VERSION 0x2020
-#define LZO_VERSION_STRING "2.02"
-#define LZO_VERSION_DATE "Oct 17 2005"
+
+#define COPY4(dst, src) \
+ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#if defined(__x86_64__)
+#define COPY8(dst, src) \
+ put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
+#else
+#define COPY8(dst, src) \
+ COPY4(dst, src); COPY4((dst) + 4, (src) + 4)
+#endif
+
+#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+#error "conflicting endian definitions"
+#elif defined(__x86_64__)
+#define LZO_USE_CTZ64 1
+#define LZO_USE_CTZ32 1
+#elif defined(__i386__) || defined(__powerpc__)
+#define LZO_USE_CTZ32 1
+#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5)
+#define LZO_USE_CTZ32 1
+#endif
#define M1_MAX_OFFSET 0x0400
#define M2_MAX_OFFSET 0x0800
@@ -34,10 +52,8 @@
#define M3_MARKER 32
#define M4_MARKER 16
-#define D_BITS 14
-#define D_MASK ((1u << D_BITS) - 1)
+#define lzo_dict_t unsigned short
+#define D_BITS 13
+#define D_SIZE (1u << D_BITS)
+#define D_MASK (D_SIZE - 1)
#define D_HIGH ((D_MASK >> 1) + 1)
-
-#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
- << (s1)) ^ (p)[0])
-#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
diff --git a/lib/process_escape_sequence.c b/lib/process_escape_sequence.c
index be77792787..47a7e5cd92 100644
--- a/lib/process_escape_sequence.c
+++ b/lib/process_escape_sequence.c
@@ -19,6 +19,7 @@
#include <common.h>
#include <fs.h>
#include <libbb.h>
+#include <shell.h>
int process_escape_sequence(const char *source, char *dest, int destlen)
{
@@ -59,6 +60,12 @@ int process_escape_sequence(const char *source, char *dest, int destlen)
case 'w':
i += snprintf(dest + i, destlen - i, "%s", getcwd());
break;
+ case '$':
+ if (*(source + 2) == '?') {
+ i += snprintf(dest + i, destlen - i, "%d", shell_get_last_return_code());
+ source++;
+ break;
+ }
default:
dest[i++] = '\\';
dest[i++] = *(source + 1);
diff --git a/lib/show_progress.c b/lib/show_progress.c
index bc067eac57..98dc8495b4 100644
--- a/lib/show_progress.c
+++ b/lib/show_progress.c
@@ -18,6 +18,7 @@
*/
#include <common.h>
+#include <fs.h>
#include <progress.h>
#include <asm-generic/div64.h>
#include <linux/stringify.h>
@@ -37,7 +38,7 @@ void show_progress(int now)
return;
}
- if (progress_max) {
+ if (progress_max && progress_max != FILESIZE_MAX) {
uint64_t tmp = (int64_t)now * HASHES_PER_LINE;
do_div(tmp, progress_max);
now = tmp;
@@ -56,7 +57,7 @@ void init_progression_bar(int max)
printed = 0;
progress_max = max;
spin = 0;
- if (progress_max)
+ if (progress_max && progress_max != FILESIZE_MAX)
printf("\t[%"__stringify(HASHES_PER_LINE)"s]\r\t[", "");
else
printf("\t");
diff --git a/net/dhcp.c b/net/dhcp.c
index ff54924762..e0c231fb42 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -699,16 +699,6 @@ static int dhcp_global_init(void)
}
late_initcall(dhcp_global_init);
-static void dhcp_getenv_int(const char *name, int *i)
-{
- const char* str = getenv(name);
-
- if (!str)
- return;
-
- *i = simple_strtoul(str, NULL, 10);
-}
-
static int do_dhcp(int argc, char *argv[])
{
int ret, opt;
@@ -716,7 +706,7 @@ static int do_dhcp(int argc, char *argv[])
dhcp_reset_env();
- dhcp_getenv_int("global.dhcp.retries", &retries);
+ getenv_uint("global.dhcp.retries", &retries);
while((opt = getopt(argc, argv, "H:v:c:u:U:r:")) > 0) {
switch(opt) {
diff --git a/net/netconsole.c b/net/netconsole.c
index 99891941b7..2ab19de4d5 100644
--- a/net/netconsole.c
+++ b/net/netconsole.c
@@ -72,7 +72,6 @@ static int nc_init(void)
}
net_udp_bind(priv->con, priv->port);
- priv->cdev.f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
return 0;
}
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 6518c0f076..53f46d913f 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -8,5 +8,4 @@ mk-am35xx-spi-image
mkimage
mkublheader
omap_signGP
-omap4_usbboot
zynq_mkimage
diff --git a/scripts/Makefile b/scripts/Makefile
index 307dc3d1a4..71d30be20a 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -1,30 +1,28 @@
###
# scripts contains sources for various helper programs used throughout
-# the kernel for the build process.
+# barebox for the build process.
# ---------------------------------------------------------------------------
# kallsyms: Find all symbols in barebox
-hostprogs-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-y += bin2c
hostprogs-y += mkimage
+hostprogs-y += fix_size
hostprogs-y += bareboxenv
+hostprogs-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-$(CONFIG_ARCH_MVEBU) += kwbimage kwboot
hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image
hostprogs-$(CONFIG_ARCH_OMAP) += omap_signGP mk-am35xx-spi-image
hostprogs-$(CONFIG_ARCH_S5PCxx) += s5p_cksum
hostprogs-$(CONFIG_ARCH_DAVINCI) += mkublheader
hostprogs-$(CONFIG_ARCH_ZYNQ) += zynq_mkimage
-subdir-$(CONFIG_ARCH_IMX) += imx
-
-HOSTLOADLIBES_omap4_usbboot = -lpthread
-omap4_usbboot-objs := usb_linux.o omap4_usbboot.o
-hostprogs-$(CONFIG_OMAP4_USBBOOT)+= omap4_usbboot
-always := $(hostprogs-y) $(hostprogs-m)
+subdir-y += mod
+subdir-$(CONFIG_OMAP4_USBBOOT) += omap4_usbboot
+subdir-$(CONFIG_ARCH_IMX) += imx
+subdir-$(CONFIG_X86) += setupmbr
+subdir-$(CONFIG_DTC) += dtc
-subdir-y += mod
-
-subdir-$(CONFIG_X86) += setupmbr
+targetprogs-$(CONFIG_BAREBOXENV_TARGET) += bareboxenv-target
# Let clean descend into subdirs
subdir- += basic kconfig setupmbr
@@ -32,9 +30,12 @@ subdir- += basic kconfig setupmbr
quiet_cmd_csingle = CC $@
cmd_csingle = $(CC) -Wp,-MD,$(depfile) $(CFLAGS) -o $@ $<
-obj-$(CONFIG_BAREBOXENV_TARGET) += bareboxenv-target
+__targetprogs := $(sort $(targetprogs-y) $(targetprogs-m))
+target-csingle := $(foreach m,$(__targetprogs),$(if $($(m)-objs),,$(m)))
+__targetprogs := $(addprefix $(obj)/,$(__targetprogs))
+target-csingle := $(addprefix $(obj)/,$(target-csingle))
-scripts/bareboxenv-target: scripts/bareboxenv.c FORCE
- $(call if_changed_dep,csingle)
+always := $(hostprogs-y) $(hostprogs-m) $(targetprogs-y)
-subdir-$(CONFIG_DTC) += dtc
+$(target-csingle): %-target: %.c FORCE
+ $(call if_changed_dep,csingle)
diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
index 6d6d55b1db..f372685ae7 100644
--- a/scripts/bareboxenv.c
+++ b/scripts/bareboxenv.c
@@ -35,7 +35,7 @@
#define debug(...)
-void *xmalloc(size_t size)
+static void *xmalloc(size_t size)
{
void *p = NULL;
@@ -47,7 +47,7 @@ void *xmalloc(size_t size)
return p;
}
-void *xzalloc(size_t size)
+static void *xzalloc(size_t size)
{
void *p = xmalloc(size);
memset(p, 0, size);
@@ -57,7 +57,7 @@ void *xzalloc(size_t size)
/* Find out if the last character of a string matches the one given.
* Don't underrun the buffer if the string length is 0.
*/
-char* last_char_is(const char *s, int c)
+static char *last_char_is(const char *s, int c)
{
if (s && *s) {
size_t sz = strlen(s) - 1;
@@ -85,7 +85,7 @@ int recursive_action(const char *fileName, unsigned flags,
/* concatenate path and file name to new allocation buffer,
* not adding '/' if path name already has '/'
*/
-char *concat_path_file(const char *path, const char *filename)
+static char *concat_path_file(const char *path, const char *filename)
{
char *lc, *str;
@@ -107,7 +107,7 @@ char *concat_path_file(const char *path, const char *filename)
* and skipping "." and ".." directory entries
*/
-char *concat_subpath_file(const char *path, const char *f)
+static char *concat_subpath_file(const char *path, const char *f)
{
if (f && DOT_OR_DOTDOT(f))
return NULL;
@@ -120,7 +120,7 @@ char *concat_subpath_file(const char *path, const char *f)
#include "../lib/make_directory.c"
#include "../common/environment.c"
-void usage(char *prgname)
+static void usage(char *prgname)
{
printf( "Usage : %s [OPTION] DIRECTORY FILE\n"
"Load a barebox environment sector into a directory or\n"
diff --git a/scripts/fix_size.c b/scripts/fix_size.c
new file mode 100644
index 0000000000..869ae7e32b
--- /dev/null
+++ b/scripts/fix_size.c
@@ -0,0 +1,81 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE /* See feature_test_macros(7) */
+#endif
+#include <endian.h>
+
+int main(int argc, char**argv)
+{
+ struct stat s;
+ int c;
+ int fd;
+ uint64_t offset = 0;
+ uint32_t size = 0;
+ char *file = NULL;
+ int ret = 1;
+ int is_bigendian = 0;
+
+ while ((c = getopt (argc, argv, "hf:o:b")) != -1) {
+ switch (c) {
+ case 'f':
+ file = optarg;
+ break;
+ case 'o':
+ offset = strtoul(optarg, NULL, 16);
+ break;
+ case 'b':
+ is_bigendian = 1;
+ break;
+ }
+ }
+
+ if (!file) {
+ fprintf(stderr, "missing file\n");
+ return 1;
+ }
+
+ if (stat(file, &s)) {
+ perror("stat");
+ return 1;
+ }
+
+ fd = open(file, O_WRONLY);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret < 0) {
+ perror("lseek");
+ ret = 1;
+ goto err;
+ }
+
+ size = s.st_size;
+
+ if (is_bigendian)
+ size = htobe32(size);
+ else
+ size = htole32(size);
+
+ ret = write(fd, &size, 4);
+ if (ret != 4) {
+ perror("write");
+ ret = 1;
+ goto err;
+ }
+
+ ret = 0;
+err:
+
+ close(fd);
+
+ return ret;
+}
diff --git a/scripts/omap4_usbboot/.gitignore b/scripts/omap4_usbboot/.gitignore
new file mode 100644
index 0000000000..1975a2172f
--- /dev/null
+++ b/scripts/omap4_usbboot/.gitignore
@@ -0,0 +1 @@
+omap4_usbboot
diff --git a/scripts/omap4_usbboot/Makefile b/scripts/omap4_usbboot/Makefile
new file mode 100644
index 0000000000..af6444b0e2
--- /dev/null
+++ b/scripts/omap4_usbboot/Makefile
@@ -0,0 +1,5 @@
+HOSTLOADLIBES_omap4_usbboot = -lpthread
+omap4_usbboot-objs := usb_linux.o omap4_usbboot.o
+hostprogs-$(CONFIG_OMAP4_USBBOOT) += omap4_usbboot
+
+always := $(hostprogs-y)
diff --git a/scripts/omap4_usbboot.c b/scripts/omap4_usbboot/omap4_usbboot.c
index e52108614b..e52108614b 100644
--- a/scripts/omap4_usbboot.c
+++ b/scripts/omap4_usbboot/omap4_usbboot.c
diff --git a/scripts/usb.h b/scripts/omap4_usbboot/usb.h
index d50aa6aa6f..d50aa6aa6f 100644
--- a/scripts/usb.h
+++ b/scripts/omap4_usbboot/usb.h
diff --git a/scripts/usb_linux.c b/scripts/omap4_usbboot/usb_linux.c
index 9a6e0b84d0..9a6e0b84d0 100644
--- a/scripts/usb_linux.c
+++ b/scripts/omap4_usbboot/usb_linux.c
diff --git a/scripts/omap_signGP.c b/scripts/omap_signGP.c
index 633bcf5f85..482cfac925 100644
--- a/scripts/omap_signGP.c
+++ b/scripts/omap_signGP.c
@@ -25,6 +25,7 @@
#include <sys/stat.h>
#include <string.h>
#include <malloc.h>
+#include <getopt.h>
#include <linux/types.h>
#undef CH_WITH_CHRAM
@@ -233,6 +234,18 @@ static struct ch_chsettings_nochram config_header
};
#endif
+static void usage(const char *prgname)
+{
+ fprintf(stderr,
+"usage: %s [OPTIONS] <infile>\n"
+"\n"
+"Options:\n"
+"-o <outfile> output to <outfile>\n"
+"-l <loadaddr> specify load address\n"
+"-c Add config header\n"
+"-h This help\n"
+ , prgname);
+}
#define err(...) do { int save_errno = errno; \
fprintf(stderr, __VA_ARGS__); \
@@ -243,29 +256,43 @@ static struct ch_chsettings_nochram config_header
int main(int argc, char *argv[])
{
int i;
- char ifname[FILENAME_MAX], ofname[FILENAME_MAX], ch;
+ char *ifname, *ofname = NULL, ch;
FILE *ifile, *ofile;
- unsigned long loadaddr, len;
+ unsigned long loadaddr = ~0, len;
struct stat sinfo;
int ch_add = 0;
+ int opt;
+ while ((opt = getopt(argc, argv, "o:hl:c")) != -1) {
+ switch (opt) {
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ case 'o':
+ ofname = optarg;
+ break;
+ case 'l':
+ loadaddr = strtoul(optarg, NULL, 0);
+ break;
+ case 'c':
+ ch_add = 1;
+ break;
+ default:
+ exit(1);
+ }
+ }
- /* Default to x-load.bin and 0x40200800. */
- strcpy(ifname, "x-load.bin");
- loadaddr = 0x40200800;
-
- if ((argc == 2) || (argc == 3) || (argc == 4))
- strcpy(ifname, argv[1]);
-
- if ((argc == 3) || (argc == 4))
- loadaddr = strtoul(argv[2], NULL, 16);
+ if (loadaddr == ~0) {
+ fprintf(stderr, "no loadaddr given\n");
+ exit(1);
+ }
- if (argc == 4)
- ch_add = strtoul(argv[3], NULL, 16);
+ if (optind == argc || !ofname) {
+ usage(argv[0]);
+ exit(1);
+ }
- /* Form the output file name. */
- strcpy(ofname, ifname);
- strcat(ofname, ".ift");
+ ifname = argv[optind];
/* Open the input file. */
ifile = fopen(ifname, "rb");