diff options
166 files changed, 5459 insertions, 1429 deletions
@@ -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); } @@ -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"); |