diff options
106 files changed, 1363 insertions, 863 deletions
diff --git a/Documentation/devicetree/bindings/barebox/barebox,environment.rst b/Documentation/devicetree/bindings/barebox/barebox,environment.rst index d472f66398..d5e52ead04 100644 --- a/Documentation/devicetree/bindings/barebox/barebox,environment.rst +++ b/Documentation/devicetree/bindings/barebox/barebox,environment.rst @@ -8,8 +8,9 @@ Required properties: * ``compatible``: should be ``barebox,environment`` * ``device-path``: path to the environment -The device-path is a multistring property. The first string should be a -nodepath to the node containing the physical device of the environment. +The device-path is a multistring property. The first string should contain +a nodepath to the node containing the physical device of the environment or +a nodepath to a partition described by the OF partition binding. The subsequent strings are of the form <type>:<options> to further describe the path to the environment. Supported values for <type>: diff --git a/Documentation/devicetree/bindings/mtd/m25p80.rst b/Documentation/devicetree/bindings/mtd/m25p80.rst new file mode 100644 index 0000000000..d7c8914ec5 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/m25p80.rst @@ -0,0 +1,10 @@ +MTD SPI driver for ST M25Pxx (and similar) serial flash chips +============================================================= + +Additionally to the Linux bindings in ``dts/Bindings/mtd/m25p80.txt`` +the barebox driver has the following optional properties: + +- use-large-blocks : Use large blocks rather than the 4K blocks some devices + support. 4K erase blocks do not work with UBIFS which needs + a minimum erase block size of 15360 bytes. Also bigger sectors + are faster to erase. @@ -1,5 +1,5 @@ VERSION = 2015 -PATCHLEVEL = 08 +PATCHLEVEL = 09 SUBLEVEL = 0 EXTRAVERSION = NAME = None diff --git a/arch/arm/boards/guf-vincell/board.c b/arch/arm/boards/guf-vincell/board.c index d27d9e4ddf..ad47ee2558 100644 --- a/arch/arm/boards/guf-vincell/board.c +++ b/arch/arm/boards/guf-vincell/board.c @@ -40,6 +40,9 @@ static void vincell_fec_reset(void) static int vincell_devices_init(void) { + if (!of_machine_is_compatible("guf,imx53-vincell")) + return 0; + writel(0, MX53_M4IF_BASE_ADDR + 0xc); clk_set_rate(clk_lookup("emi_slow_podf"), 133333334); diff --git a/arch/arm/boards/phytec-phycore-pxa270/board.c b/arch/arm/boards/phytec-phycore-pxa270/board.c index 833c4c81e4..1424c9c937 100644 --- a/arch/arm/boards/phytec-phycore-pxa270/board.c +++ b/arch/arm/boards/phytec-phycore-pxa270/board.c @@ -26,7 +26,7 @@ #include <partition.h> #include <linux/sizes.h> -#include <plat/gpio.h> +#include <gpio.h> #include <mach/mfp-pxa27x.h> #include <mach/pxa-regs.h> #include <mach/pxafb.h> diff --git a/arch/arm/boards/phytec-phyflex-imx6/board.c b/arch/arm/boards/phytec-phyflex-imx6/board.c index 5f65261a9f..d3100c88b3 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/board.c +++ b/arch/arm/boards/phytec-phyflex-imx6/board.c @@ -16,6 +16,7 @@ * Foundation. * */ +#define pr_fmt(fmt) "phyFLEX-i.MX6: " fmt #include <malloc.h> #include <envfs.h> @@ -27,12 +28,16 @@ #include <of.h> #include <mach/bbu.h> #include <fec.h> +#include <globalvar.h> #include <linux/micrel_phy.h> #include <mach/iomux-mx6.h> #include <mach/imx6.h> +#define PHYFLEX_MODULE_REV_1 0x1 +#define PHYFLEX_MODULE_REV_2 0x2 + #define GPIO_2_11_PD_CTL MX6_PAD_CTL_PUS_100K_DOWN | MX6_PAD_CTL_PUE | MX6_PAD_CTL_PKE | \ MX6_PAD_CTL_SPEED_MED | MX6_PAD_CTL_DSE_40ohm | MX6_PAD_CTL_HYS @@ -64,10 +69,24 @@ static void phyflex_err006282_workaround(void) gpio_direction_input(MX6_PHYFLEX_ERR006282); } +static unsigned int pfla02_module_revision; + +static unsigned int get_module_rev(void) +{ + unsigned int val = 0; + + val = gpio_get_value(IMX_GPIO_NR(2, 12)); + val |= (gpio_get_value(IMX_GPIO_NR(2, 13)) << 1); + val |= (gpio_get_value(IMX_GPIO_NR(2, 14)) << 2); + val |= (gpio_get_value(IMX_GPIO_NR(2, 15)) << 3); + + return 16 - val; +} + static int phytec_pfla02_init(void) { int ret; - char *environment_path; + char *environment_path, *envdev; if (!of_machine_is_compatible("phytec,imx6q-pfla02") && !of_machine_is_compatible("phytec,imx6dl-pfla02") && @@ -78,17 +97,25 @@ static int phytec_pfla02_init(void) imx6_bbu_nand_register_handler("nand", BBU_HANDLER_FLAG_DEFAULT); + pfla02_module_revision = get_module_rev(); + globalvar_add_simple_int("board.revision", &pfla02_module_revision, "%u"); + + pr_info("Module Revision: %u\n", pfla02_module_revision); + switch (bootsource_get()) { case BOOTSOURCE_MMC: environment_path = asprintf("/chosen/environment-sd%d", bootsource_get_instance() + 1); + envdev = "MMC"; break; case BOOTSOURCE_NAND: environment_path = asprintf("/chosen/environment-nand"); + envdev = "NAND flash"; break; default: case BOOTSOURCE_SPI: environment_path = asprintf("/chosen/environment-spinor"); + envdev = "SPI NOR flash"; break; } @@ -99,6 +126,8 @@ static int phytec_pfla02_init(void) free(environment_path); + pr_notice("Using environment in %s\n", envdev); + return 0; } device_initcall(phytec_pfla02_init); diff --git a/arch/arm/boards/zylonite/board.c b/arch/arm/boards/zylonite/board.c index dabc6ffb0b..2caadbcecc 100644 --- a/arch/arm/boards/zylonite/board.c +++ b/arch/arm/boards/zylonite/board.c @@ -28,6 +28,7 @@ #include <net/smc91111.h> #include <platform_data/mtd-nand-mrvl.h> #include <pwm.h> +#include <linux/sizes.h> #include <mach/devices.h> #include <mach/mfp-pxa3xx.h> @@ -66,6 +67,8 @@ static int zylonite_devices_init(void) &smsc91x_pdata); add_generic_device("mrvl_nand", DEVICE_ID_DYNAMIC, NULL, 0x43100000, 0x1000, IORESOURCE_MEM, &nand_pdata); + devfs_add_partition("nand0", SZ_1M, SZ_256K, DEVFS_PARTITION_FIXED, + "env0"); return 0; } device_initcall(zylonite_devices_init); diff --git a/arch/arm/boards/zylonite/env/bin/init b/arch/arm/boards/zylonite/env/bin/init deleted file mode 100644 index a6bc087b22..0000000000 --- a/arch/arm/boards/zylonite/env/bin/init +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -PATH=/env/bin -export PATH - -. /env/config -addpart /dev/nand0 $mtdparts -usbserial -s "Zylonite usb gadget" - -# Phase1: check for MTD override -mtd_env_override -if [ $? = 0 ]; then - echo "Switching to custom environment" - /env/init - exit -fi - -# Phase2: initiate network -dhcp -H zylonite - -# Phase3: activate netconsole, broadcast everywhere -netconsole.ip=255.255.255.255 -netconsole.active=ioe -netconsole.port=6666 - diff --git a/arch/arm/boards/zylonite/env/bin/mtd_env_override b/arch/arm/boards/zylonite/env/bin/mtd_env_override deleted file mode 100644 index 6ea253a4f0..0000000000 --- a/arch/arm/boards/zylonite/env/bin/mtd_env_override +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh - -loadenv /dev/nand0.barebox-env -exit $? diff --git a/arch/arm/boards/zylonite/env/boot/nand-ubi b/arch/arm/boards/zylonite/env/boot/nand-ubi new file mode 100644 index 0000000000..2231738224 --- /dev/null +++ b/arch/arm/boards/zylonite/env/boot/nand-ubi @@ -0,0 +1,5 @@ +#!/bin/sh + +global.bootm.image="/dev/nand0.kernel" +#global.bootm.oftree="/env/oftree" +global.linux.bootargs.dyn.root="root=ubi0:linux_root ubi.mtd=nand.root rootfstype=ubifs" diff --git a/arch/arm/boards/zylonite/env/config b/arch/arm/boards/zylonite/env/config deleted file mode 100644 index ee66e37cc3..0000000000 --- a/arch/arm/boards/zylonite/env/config +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -autoboot_timeout=3 - -mtdparts="128k@0(TIMH)ro,128k@128k(OBMI)ro,768k@256k(barebox),256k@1024k(barebox-env),12M@1280k(kernel),38016k@13568k(root)" -bootargs="$bootargs mtdparts=pxa3xx_nand-0:$mtdparts ubi.mtd=5 rootfstype=ubifs root=ubi0:root ro ram=64M console=ttyS0,115200" diff --git a/arch/arm/boards/zylonite/env/init/mtdparts-nand b/arch/arm/boards/zylonite/env/init/mtdparts-nand new file mode 100644 index 0000000000..9db4652c40 --- /dev/null +++ b/arch/arm/boards/zylonite/env/init/mtdparts-nand @@ -0,0 +1,11 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + init-menu-add-entry "$0" "NAND partitions" + exit +fi + +mtdparts="128k@0(TIMH)ro,128k@128k(OBMI)ro,768k@256k(barebox),256k@1024k(barebox-env),12M@1280k(kernel),38016k@13568k(root)" +kernelname="pxa3xx_nand-0" + +mtdparts-add -d nand0 -k ${kernelname} -p ${mtdparts} diff --git a/arch/arm/boards/zylonite/env/nv/hostname b/arch/arm/boards/zylonite/env/nv/hostname new file mode 100644 index 0000000000..6e6d865eda --- /dev/null +++ b/arch/arm/boards/zylonite/env/nv/hostname @@ -0,0 +1 @@ +zylonite diff --git a/arch/arm/boards/zylonite/env/nv/linux.bootargs.base b/arch/arm/boards/zylonite/env/nv/linux.bootargs.base new file mode 100644 index 0000000000..317f8b16a1 --- /dev/null +++ b/arch/arm/boards/zylonite/env/nv/linux.bootargs.base @@ -0,0 +1 @@ +ram=64M diff --git a/arch/arm/boards/zylonite/env/nv/linux.bootargs.console b/arch/arm/boards/zylonite/env/nv/linux.bootargs.console new file mode 100644 index 0000000000..476b1fbe49 --- /dev/null +++ b/arch/arm/boards/zylonite/env/nv/linux.bootargs.console @@ -0,0 +1 @@ +console=ttyS0,115200 diff --git a/arch/arm/configs/zylonite310_defconfig b/arch/arm/configs/zylonite310_defconfig index fa6587c0ee..ffe3215354 100644 --- a/arch/arm/configs/zylonite310_defconfig +++ b/arch/arm/configs/zylonite310_defconfig @@ -8,17 +8,17 @@ CONFIG_ARM_UNWIND=y # CONFIG_BANNER is not set CONFIG_MMU=y CONFIG_BAREBOX_MAX_BARE_INIT_SIZE=0x80000 -CONFIG_MALLOC_SIZE=0x1000000 +CONFIG_MALLOC_SIZE=0x800000 CONFIG_EXPERIMENTAL=y CONFIG_MODULES=y CONFIG_KALLSYMS=y CONFIG_PROMPT="zylonite-barebox:" -CONFIG_GLOB=y CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y CONFIG_CONSOLE_ACTIVATE_ALL=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/zylonite/env" CONFIG_RESET_SOURCE=y CONFIG_DEFAULT_LOGLEVEL=8 @@ -27,8 +27,6 @@ CONFIG_CMD_DMESG=y CONFIG_LONGHELP=y CONFIG_CMD_IOMEM=y CONFIG_CMD_MEMINFO=y -CONFIG_FLEXIBLE_BOOTARGS=y -CONFIG_CMD_BOOT=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y CONFIG_CMD_BOOTM_INITRD=y @@ -40,26 +38,20 @@ CONFIG_CMD_LOADY=y CONFIG_CMD_RESET=y CONFIG_CMD_SAVES=y CONFIG_CMD_PARTITION=y -CONFIG_CMD_AUTOMOUNT=y CONFIG_CMD_UBIFORMAT=y CONFIG_CMD_EXPORT=y -CONFIG_CMD_GLOBAL=y CONFIG_CMD_LOADENV=y CONFIG_CMD_PRINTENV=y CONFIG_CMD_SAVEENV=y -CONFIG_CMD_BASENAME=y CONFIG_CMD_CMP=y -CONFIG_CMD_DIRNAME=y CONFIG_CMD_FILETYPE=y CONFIG_CMD_LN=y -CONFIG_CMD_READLINK=y CONFIG_CMD_UNCOMPRESS=y CONFIG_CMD_LET=y CONFIG_CMD_MSLEEP=y CONFIG_CMD_SLEEP=y CONFIG_CMD_DHCP=y CONFIG_CMD_HOST=y -CONFIG_NET_CMD_IFUP=y CONFIG_CMD_MIITOOL=y CONFIG_CMD_PING=y CONFIG_CMD_TFTP=y diff --git a/arch/arm/cpu/cache-l2x0.c b/arch/arm/cpu/cache-l2x0.c index 2be562d7de..428dd93249 100644 --- a/arch/arm/cpu/cache-l2x0.c +++ b/arch/arm/cpu/cache-l2x0.c @@ -1,3 +1,5 @@ +#define pr_fmt(fmt) "l2x0: " fmt + #include <common.h> #include <init.h> #include <io.h> @@ -7,6 +9,7 @@ #define CACHE_LINE_SIZE 32 static void __iomem *l2x0_base; +static uint32_t l2x0_way_mask; /* Bitmask of active ways */ static inline void cache_wait(void __iomem *reg, unsigned long mask) { @@ -50,8 +53,8 @@ static inline void l2x0_flush_line(unsigned long addr) static inline void l2x0_inv_all(void) { /* invalidate all ways */ - writel(0xff, l2x0_base + L2X0_INV_WAY); - cache_wait(l2x0_base + L2X0_INV_WAY, 0xff); + writel(l2x0_way_mask, l2x0_base + L2X0_INV_WAY); + cache_wait(l2x0_base + L2X0_INV_WAY, l2x0_way_mask); cache_sync(); } @@ -112,6 +115,13 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) cache_sync(); } +static void l2x0_flush_all(void) +{ + writel(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY); + cache_wait(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask); + cache_sync(); +} + static void l2x0_disable(void) { writel(0xff, l2x0_base + L2X0_CLEAN_INV_WAY); @@ -122,9 +132,37 @@ static void l2x0_disable(void) void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) { __u32 aux; + __u32 cache_id; + int ways; + const char *type; l2x0_base = base; + cache_id = readl(l2x0_base + L2X0_CACHE_ID); + aux = readl(l2x0_base + L2X0_AUX_CTRL); + + /* Determine the number of ways */ + switch (cache_id & L2X0_CACHE_ID_PART_MASK) { + case L2X0_CACHE_ID_PART_L310: + if (aux & (1 << 16)) + ways = 16; + else + ways = 8; + type = "L310"; + break; + case L2X0_CACHE_ID_PART_L210: + ways = (aux >> 13) & 0xf; + type = "L210"; + break; + default: + /* Assume unknown chips have 8 ways */ + ways = 8; + type = "L2x0 series"; + break; + } + + l2x0_way_mask = (1 << ways) - 1; + /* * Check if l2x0 controller is already enabled. * If you are booting from non-secure mode @@ -149,5 +187,9 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) outer_cache.clean_range = l2x0_clean_range; outer_cache.flush_range = l2x0_flush_range; outer_cache.disable = l2x0_disable; -} + outer_cache.flush_all = l2x0_flush_all; + pr_debug("%s cache controller enabled\n", type); + pr_debug("l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n", + ways, cache_id, aux); +} diff --git a/arch/arm/cpu/cache.c b/arch/arm/cpu/cache.c index 7b161d59d6..27ead1c177 100644 --- a/arch/arm/cpu/cache.c +++ b/arch/arm/cpu/cache.c @@ -71,6 +71,8 @@ void __mmu_cache_flush(void) { if (cache_fns) cache_fns->mmu_cache_flush(); + if (outer_cache.flush_all) + outer_cache.flush_all(); } int arm_set_cache_functions(void) diff --git a/arch/arm/cpu/cpu.c b/arch/arm/cpu/cpu.c index 5e708023e4..ff8f43d175 100644 --- a/arch/arm/cpu/cpu.c +++ b/arch/arm/cpu/cpu.c @@ -79,10 +79,9 @@ struct outer_cache_fns outer_cache; */ void mmu_disable(void) { + __mmu_cache_flush(); if (outer_cache.disable) outer_cache.disable(); - - __mmu_cache_flush(); __mmu_cache_off(); } diff --git a/arch/arm/cpu/exceptions.S b/arch/arm/cpu/exceptions.S index f17f1e11e4..eda0d6ab8d 100644 --- a/arch/arm/cpu/exceptions.S +++ b/arch/arm/cpu/exceptions.S @@ -220,9 +220,9 @@ _fiq: .word fiq .align 4 .global arm_ignore_data_abort arm_ignore_data_abort: -.word arm_ignore_data_abort /* When != 0 data aborts are ignored */ +.word 0 /* When != 0 data aborts are ignored */ .global arm_data_abort_occurred arm_data_abort_occurred: -.word arm_data_abort_occurred /* set != 0 by the data abort handler */ +.word 0 /* set != 0 by the data abort handler */ abort_stack: .space 8 diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index 37bfa058a5..7b185d713b 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -66,6 +66,7 @@ static inline void tlb_invalidate(void) } #define PTE_FLAGS_CACHED_V7 (PTE_EXT_TEX(1) | PTE_BUFFERABLE | PTE_CACHEABLE) +#define PTE_FLAGS_WC_V7 PTE_EXT_TEX(1) #define PTE_FLAGS_UNCACHED_V7 (0) #define PTE_FLAGS_CACHED_V4 (PTE_SMALL_AP_UNO_SRW | PTE_BUFFERABLE | PTE_CACHEABLE) #define PTE_FLAGS_UNCACHED_V4 PTE_SMALL_AP_UNO_SRW @@ -75,6 +76,7 @@ static inline void tlb_invalidate(void) * This will be determined at runtime. */ static uint32_t pte_flags_cached; +static uint32_t pte_flags_wc; static uint32_t pte_flags_uncached; #define PTE_MASK ((1 << 12) - 1) @@ -159,9 +161,9 @@ static u32 *find_pte(unsigned long adr) static void dma_flush_range(unsigned long start, unsigned long end) { + __dma_flush_range(start, end); if (outer_cache.flush_range) outer_cache.flush_range(start, end); - __dma_flush_range(start, end); } static void dma_inv_range(unsigned long start, unsigned long end) @@ -325,9 +327,11 @@ static int mmu_init(void) if (cpu_architecture() >= CPU_ARCH_ARMv7) { pte_flags_cached = PTE_FLAGS_CACHED_V7; + pte_flags_wc = PTE_FLAGS_WC_V7; pte_flags_uncached = PTE_FLAGS_UNCACHED_V7; } else { pte_flags_cached = PTE_FLAGS_CACHED_V4; + pte_flags_wc = PTE_FLAGS_UNCACHED_V4; pte_flags_uncached = PTE_FLAGS_UNCACHED_V4; } @@ -408,6 +412,22 @@ void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle) return ret; } +void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle) +{ + void *ret; + + size = PAGE_ALIGN(size); + ret = xmemalign(PAGE_SIZE, size); + if (dma_handle) + *dma_handle = (dma_addr_t)ret; + + dma_inv_range((unsigned long)ret, (unsigned long)ret + size); + + remap_range(ret, size, pte_flags_wc); + + return ret; +} + unsigned long virt_to_phys(volatile void *virt) { return (unsigned long)virt; diff --git a/arch/arm/dts/imx27-phytec-phycore-rdk.dts b/arch/arm/dts/imx27-phytec-phycore-rdk.dts index 9d216afa3a..f602045c7e 100644 --- a/arch/arm/dts/imx27-phytec-phycore-rdk.dts +++ b/arch/arm/dts/imx27-phytec-phycore-rdk.dts @@ -10,13 +10,13 @@ environment-nor { compatible = "barebox,environment"; - device-path = &nor, "partname:env"; + device-path = &environment_nor; status = "disabled"; }; environment-nand { compatible = "barebox,environment"; - device-path = &nfc, "partname:env"; + device-path = &environment_nand; status = "disabled"; }; }; @@ -32,7 +32,7 @@ reg = <0x00000000 0x00080000>; }; - partition@1 { + environment_nand: partition@1 { label = "env"; reg = <0x00080000 0x00020000>; }; @@ -54,7 +54,7 @@ reg = <0x00000000 0x00080000>; }; - partition@1 { + environment_nor: partition@1 { label = "env"; reg = <0x00080000 0x00020000>; }; diff --git a/arch/arm/dts/imx51-babbage.dts b/arch/arm/dts/imx51-babbage.dts index 909774bd52..f8402ca8fa 100644 --- a/arch/arm/dts/imx51-babbage.dts +++ b/arch/arm/dts/imx51-babbage.dts @@ -18,7 +18,7 @@ environment@0 { compatible = "barebox,environment"; - device-path = &esdhc1, "partname:barebox-environment"; + device-path = &environment_esdhc1; }; }; }; @@ -27,7 +27,7 @@ #address-cells = <1>; #size-cells = <1>; - partition@0 { + environment_esdhc1: partition@0 { label = "barebox-environment"; reg = <0x80000 0x20000>; }; diff --git a/arch/arm/dts/imx53-qsb-common.dtsi b/arch/arm/dts/imx53-qsb-common.dtsi index 4007a092a8..bf634e49d4 100644 --- a/arch/arm/dts/imx53-qsb-common.dtsi +++ b/arch/arm/dts/imx53-qsb-common.dtsi @@ -16,7 +16,7 @@ environment@0 { compatible = "barebox,environment"; - device-path = &esdhc1, "partname:barebox-environment"; + device-path = &bareboxenv; }; }; }; @@ -25,7 +25,7 @@ #address-cells = <1>; #size-cells = <1>; - partition@0 { + bareboxenv: partition@0 { label = "barebox-environment"; reg = <0x80000 0x20000>; }; diff --git a/arch/arm/dts/imx6dl-eltec-hipercam.dts b/arch/arm/dts/imx6dl-eltec-hipercam.dts index 737752f0b1..166f8f1244 100644 --- a/arch/arm/dts/imx6dl-eltec-hipercam.dts +++ b/arch/arm/dts/imx6dl-eltec-hipercam.dts @@ -15,7 +15,7 @@ environment@0 { compatible = "barebox,environment"; - device-path = &norflash0, "partname:bareboxenv"; + device-path = &environment_nor0; }; }; }; @@ -39,7 +39,7 @@ reg = <0x0 0xc0000>; }; - partition@1 { + environment_nor0: partition@1 { label = "bareboxenv"; reg = <0xc0000 0x8000>; }; diff --git a/arch/arm/dts/imx6dl-phytec-pfla02.dtsi b/arch/arm/dts/imx6dl-phytec-pfla02.dtsi index 0f801aebc9..47154d5d9f 100644 --- a/arch/arm/dts/imx6dl-phytec-pfla02.dtsi +++ b/arch/arm/dts/imx6dl-phytec-pfla02.dtsi @@ -16,7 +16,3 @@ model = "Phytec phyFLEX-i.MX6 Dual Lite"; compatible = "phytec,imx6dl-pfla02", "fsl,imx6dl"; }; - -&ecspi3 { - status = "okay"; -}; diff --git a/arch/arm/dts/imx6q-phytec-pbab01.dts b/arch/arm/dts/imx6q-phytec-pbab01.dts index 580338dff8..2f816dd1ac 100644 --- a/arch/arm/dts/imx6q-phytec-pbab01.dts +++ b/arch/arm/dts/imx6q-phytec-pbab01.dts @@ -16,8 +16,4 @@ / { model = "Phytec phyFLEX-i.MX6 Quad Carrier-Board"; compatible = "phytec,imx6x-pbab01", "phytec,imx6q-pfla02", "fsl,imx6q"; - - chosen { - linux,stdout-path = &uart4; - }; }; diff --git a/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi b/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi index 6435ab791d..97cf78a73c 100644 --- a/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi +++ b/arch/arm/dts/imx6q-phytec-pcaaxl3.dtsi @@ -19,13 +19,13 @@ chosen { environment-sd { compatible = "barebox,environment"; - device-path = &usdhc3, "partname:barebox-environment"; + device-path = &environment_usdhc3; status = "disabled"; }; environment-nand { compatible = "barebox,environment"; - device-path = &gpmi, "partname:barebox-environment"; + device-path = &environment_nand; status = "disabled"; }; }; @@ -139,7 +139,7 @@ reg = <0x0 0x400000>; }; - partition@1 { + environment_nand: partition@1 { label = "barebox-environment"; reg = <0x400000 0x20000>; }; @@ -183,7 +183,7 @@ label = "barebox"; reg = <0x0 0x80000>; }; - partition@1 { + environment_usdhc3: partition@1 { label = "barebox-environment"; reg = <0x80000 0x80000>; }; diff --git a/arch/arm/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/dts/imx6q-phytec-pfla02.dtsi index b1172dc095..48f1da3cad 100644 --- a/arch/arm/dts/imx6q-phytec-pfla02.dtsi +++ b/arch/arm/dts/imx6q-phytec-pfla02.dtsi @@ -17,7 +17,3 @@ model = "Phytec phyFLEX-i.MX6 Quad"; compatible = "phytec,imx6q-pfla02", "fsl,imx6q"; }; - -&ecspi3 { - status = "okay"; -}; diff --git a/arch/arm/dts/imx6q-sabresd.dts b/arch/arm/dts/imx6q-sabresd.dts index 71ca855251..1f92c15242 100644 --- a/arch/arm/dts/imx6q-sabresd.dts +++ b/arch/arm/dts/imx6q-sabresd.dts @@ -25,7 +25,7 @@ environment@0 { compatible = "barebox,environment"; - device-path = &usdhc3, "partname:barebox-environment"; + device-path = &environment_usdhc3; }; }; }; diff --git a/arch/arm/dts/imx6q-var-custom.dts b/arch/arm/dts/imx6q-var-custom.dts index 795114d841..ef6981e3bc 100644 --- a/arch/arm/dts/imx6q-var-custom.dts +++ b/arch/arm/dts/imx6q-var-custom.dts @@ -30,7 +30,7 @@ environment@0 { compatible = "barebox,environment"; - device-path = &gpmi, "partname:barebox-environment"; + device-path = &environment_nand; }; }; diff --git a/arch/arm/dts/imx6q-var-som.dtsi b/arch/arm/dts/imx6q-var-som.dtsi index 792691191e..d005f319d6 100644 --- a/arch/arm/dts/imx6q-var-som.dtsi +++ b/arch/arm/dts/imx6q-var-som.dtsi @@ -42,7 +42,7 @@ reg = <0x0 0x200000>; }; - partition@1 { + environment_nand: partition@1 { label = "barebox-environment"; reg = <0x200000 0x20000>; }; diff --git a/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi index 157e130ff1..86ab991c91 100644 --- a/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi +++ b/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi @@ -9,22 +9,8 @@ * http://www.gnu.org/copyleft/gpl.html */ -&fec { - status = "okay"; -}; +#include <arm/imx6qdl-phytec-pbab01.dtsi> &uart1 { status = "okay"; }; - -&uart4 { - status = "okay"; -}; - -&usdhc2 { - status = "okay"; -}; - -&usdhc3 { - status = "okay"; -}; diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi index 5ac0ef9431..b79ce2c0f9 100644 --- a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi +++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi @@ -9,7 +9,14 @@ * http://www.gnu.org/copyleft/gpl.html */ +#include <arm/imx6qdl-phytec-pfla02.dtsi> + / { + memory { + /* let barebox fill the memory node */ + reg = <0 0>; + }; + chosen { environment-nand { compatible = "barebox,environment"; @@ -50,17 +57,7 @@ }; &ecspi3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ecspi3>; - status = "disabled"; - fsl,spi-num-chipselects = <1>; - cs-gpios = <&gpio4 24 0>; - - flash: m25p80@0 { - compatible = "m25p80"; - spi-max-frequency = <20000000>; - reg = <0>; - + flash: flash@0 { #address-cells = <1>; #size-cells = <1>; @@ -87,12 +84,7 @@ }; &fec { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_enet>; phy-handle = <ðphy>; - phy-mode = "rgmii"; - phy-reset-gpios = <&gpio3 23 0>; - status = "disabled"; mdio { #address-cells = <1>; @@ -108,10 +100,6 @@ }; &gpmi { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gpmi_nand>; - nand-on-flash-bbt; - status = "okay"; #address-cells = <1>; #size-cells = <1>; @@ -143,44 +131,20 @@ &iomuxc { pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_hog>; - - ecspi3 { - pinctrl_ecspi3: ecspi3grp { - fsl,pins = < - MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1 - MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1 - MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1 - MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */ - >; - }; - }; + pinctrl-0 = <&pinctrl_hog>, <&pinctrl_rev>; - enet { - pinctrl_enet: enetgrp { + imx6q-phytec-pfla02 { + pinctrl_rev: revgrp { fsl,pins = < - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 - MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 + MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x80000000 + MX6QDL_PAD_SD4_DAT4__GPIO2_IO12 0x80000000 + MX6QDL_PAD_SD4_DAT5__GPIO2_IO13 0x80000000 + MX6QDL_PAD_SD4_DAT6__GPIO2_IO14 0x80000000 + MX6QDL_PAD_SD4_DAT7__GPIO2_IO15 0x80000000 >; }; - }; - gpmi-nand { - pinctrl_gpmi_nand: gpmi-nand { + pinctrl_gpmi_nand: gpminandgrp { fsl,pins = < MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 @@ -204,79 +168,13 @@ >; }; }; - - hog { - pinctrl_hog: hoggrp { - fsl,pins = < - MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000 - MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x80000000 - >; - }; - }; - - uart4 { - pinctrl_uart4: uart4grp { - fsl,pins = < - MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 - MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 - >; - }; - }; - - usdhc2 { - pinctrl_usdhc2: usdhc2grp { - fsl,pins = < - MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 - MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 - MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 - MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 - MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 - MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 - >; - }; - }; - - usdhc3 { - pinctrl_usdhc3: usdhc3grp { - fsl,pins = < - MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 - MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 - MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 - MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 - MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 - MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 - MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000 - MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 - >; - }; - }; }; &ocotp { barebox,provide-mac-address = <&fec 0x620>; }; -&uart4 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart4>; - status = "disabled"; -}; - -&usdhc2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc2>; - cd-gpios = <&gpio1 4 0>; - wp-gpios = <&gpio1 2 0>; - status = "disabled"; -}; - &usdhc3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc3>; - cd-gpios = <&gpio1 27 0>; - wp-gpios = <&gpio1 29 0>; - status = "disabled"; - #address-cells = <1>; #size-cells = <1>; @@ -284,6 +182,7 @@ label = "barebox"; reg = <0x0 0x80000>; }; + partition@1 { label = "barebox-environment"; reg = <0x80000 0x80000>; diff --git a/arch/arm/dts/imx6qdl-sabresd.dtsi b/arch/arm/dts/imx6qdl-sabresd.dtsi index 54201bdb7e..32318cf389 100644 --- a/arch/arm/dts/imx6qdl-sabresd.dtsi +++ b/arch/arm/dts/imx6qdl-sabresd.dtsi @@ -34,7 +34,7 @@ reg = <0x0 0x80000>; }; - partition@1 { + environment_usdhc3: partition@1 { label = "barebox-environment"; reg = <0x80000 0x80000>; }; diff --git a/arch/arm/dts/imx6s-riotboard.dts b/arch/arm/dts/imx6s-riotboard.dts index 117c00a575..a522dd9934 100644 --- a/arch/arm/dts/imx6s-riotboard.dts +++ b/arch/arm/dts/imx6s-riotboard.dts @@ -17,7 +17,7 @@ environment@0 { compatible = "barebox,environment"; - device-path = &usdhc4, "partname:barebox-environment"; + device-path = &environment_usdhc4; }; }; @@ -232,7 +232,7 @@ reg = <0x0 0x80000>; }; - partition@1 { + environment_usdhc4: partition@1 { label = "barebox-environment"; reg = <0x80000 0x80000>; }; diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h deleted file mode 100644 index b3c1efe739..0000000000 --- a/arch/arm/include/asm/gpio.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _ARCH_ARM_GPIO_H -#define _ARCH_ARM_GPIO_H - -#ifndef CONFIG_GPIOLIB -#include <mach/gpio.h> -#else -#include <asm-generic/gpio.h> -#endif - -#endif /* _ARCH_ARM_GPIO_H */ diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h index 97bb0dbeb6..3b19e9ef3c 100644 --- a/arch/arm/include/asm/mmu.h +++ b/arch/arm/include/asm/mmu.h @@ -67,6 +67,7 @@ struct outer_cache_fns { void (*inv_range)(unsigned long, unsigned long); void (*clean_range)(unsigned long, unsigned long); void (*flush_range)(unsigned long, unsigned long); + void (*flush_all)(void); void (*disable)(void); }; diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index 4e9d6865ab..bdc0cb6879 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -7,8 +7,6 @@ #ifndef __AT91_GPIO_H__ #define __AT91_GPIO_H__ -#include <asm-generic/gpio.h> - #define MAX_NB_GPIO_PER_BANK 32 static inline unsigned pin_to_bank(unsigned pin) diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h deleted file mode 100644 index 306ab4c9f2..0000000000 --- a/arch/arm/mach-ep93xx/include/mach/gpio.h +++ /dev/null @@ -1 +0,0 @@ -#include <asm-generic/gpio.h> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 0de2d3e153..f2dc52d518 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -175,15 +175,18 @@ config ARCH_IMX53 config ARCH_IMX6 bool + select ARCH_HAS_L2X0 select ARCH_HAS_FEC_IMX select CPU_V7 select PINCTRL_IMX_IOMUX_V3 + select OFTREE select COMMON_CLK_OF_PROVIDER select HW_HAS_PCI config ARCH_IMX6SX bool select ARCH_IMX6 + select OFTREE select COMMON_CLK_OF_PROVIDER config IMX_MULTI_BOARDS diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index 7508964bf5..ceabe19dc2 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -22,6 +22,7 @@ #include <mach/imx6-anadig.h> #include <mach/imx6-regs.h> #include <mach/generic.h> +#include <asm/mmu.h> #define SI_REV 0x260 @@ -193,3 +194,37 @@ int imx6_devices_init(void) return 0; } + +#define L310_PREFETCH_CTRL 0xF60 + +static int imx6_mmu_init(void) +{ + void __iomem *l2x0_base = IOMEM(0x00a02000); + u32 val; + + if (!cpu_is_mx6()) + return 0; + + /* Configure the L2 PREFETCH and POWER registers */ + val = readl(l2x0_base + L310_PREFETCH_CTRL); + val |= 0x70800000; + + /* + * The L2 cache controller(PL310) version on the i.MX6D/Q is r3p1-50rel0 + * The L2 cache controller(PL310) version on the i.MX6DL/SOLO/SL is r3p2 + * But according to ARM PL310 errata: 752271 + * ID: 752271: Double linefill feature can cause data corruption + * Fault Status: Present in: r3p0, r3p1, r3p1-50rel0. Fixed in r3p2 + * Workaround: The only workaround to this erratum is to disable the + * double linefill feature. This is the default behavior. + */ + if (cpu_is_mx6q()) + val &= ~(1 << 30 | 1 << 23); + + writel(val, l2x0_base + L310_PREFETCH_CTRL); + + l2x0_init(l2x0_base, 0x0, ~0UL); + + return 0; +} +postmmu_initcall(imx6_mmu_init); diff --git a/arch/arm/mach-mxs/include/mach/gpio.h b/arch/arm/mach-mxs/include/mach/gpio.h deleted file mode 100644 index 8643c98d5a..0000000000 --- a/arch/arm/mach-mxs/include/mach/gpio.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * (C) Copyright 2010 Juergen Beisert - 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. - * - */ - -#ifndef __ASM_MACH_GPIO_H -#define __ASM_MACH_GPIO_H - -#include <asm-generic/gpio.h> - -#endif /* __ASM_MACH_GPIO_H */ diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c index 4e98493e73..7dd6ac0648 100644 --- a/arch/arm/mach-pxa/gpio.c +++ b/arch/arm/mach-pxa/gpio.c @@ -66,3 +66,35 @@ int __init pxa_init_gpio(int start, int end) return 0; } + +int gpio_get_value(unsigned gpio) +{ + return GPLR(gpio) & GPIO_bit(gpio); +} + +void gpio_set_value(unsigned gpio, int value) +{ + if (value) + GPSR(gpio) = GPIO_bit(gpio); + else + GPCR(gpio) = GPIO_bit(gpio); +} + +int gpio_direction_input(unsigned gpio) +{ + if (__gpio_is_inverted(gpio)) + GPDR(gpio) |= GPIO_bit(gpio); + else + GPDR(gpio) &= ~GPIO_bit(gpio); + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + gpio_set_value(gpio, value); + if (__gpio_is_inverted(gpio)) + GPDR(gpio) &= ~GPIO_bit(gpio); + else + GPDR(gpio) |= GPIO_bit(gpio); + return 0; +} diff --git a/arch/arm/mach-pxa/include/plat/gpio.h b/arch/arm/mach-pxa/include/plat/gpio.h index 4c7b5266fb..35f90715e0 100644 --- a/arch/arm/mach-pxa/include/plat/gpio.h +++ b/arch/arm/mach-pxa/include/plat/gpio.h @@ -31,38 +31,6 @@ #define GFER_OFFSET 0x3C #define GEDR_OFFSET 0x48 -static inline int gpio_get_value(unsigned gpio) -{ - return GPLR(gpio) & GPIO_bit(gpio); -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - if (value) - GPSR(gpio) = GPIO_bit(gpio); - else - GPCR(gpio) = GPIO_bit(gpio); -} - -static inline int gpio_direction_input(unsigned gpio) -{ - if (__gpio_is_inverted(gpio)) - GPDR(gpio) |= GPIO_bit(gpio); - else - GPDR(gpio) &= ~GPIO_bit(gpio); - return 0; -} - -static inline int gpio_direction_output(unsigned gpio, int value) -{ - gpio_set_value(gpio, value); - if (__gpio_is_inverted(gpio)) - GPDR(gpio) &= ~GPIO_bit(gpio); - else - GPDR(gpio) |= GPIO_bit(gpio); - return 0; -} - /* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85). * Those cases currently cause holes in the GPIO number space, the * actual number of the last GPIO is recorded by 'pxa_last_gpio'. diff --git a/arch/arm/mach-samsung/gpio-s3c24x0.c b/arch/arm/mach-samsung/gpio-s3c24x0.c index f62588f0e7..58ca284eab 100644 --- a/arch/arm/mach-samsung/gpio-s3c24x0.c +++ b/arch/arm/mach-samsung/gpio-s3c24x0.c @@ -15,7 +15,7 @@ #include <errno.h> #include <io.h> #include <mach/s3c-iomap.h> -#include <mach/gpio.h> +#include <gpio.h> #include <mach/s3c24xx-gpio.h> #include <mach/iomux.h> diff --git a/arch/arm/mach-samsung/include/mach/gpio.h b/arch/arm/mach-samsung/include/mach/gpio.h deleted file mode 100644 index 39206676f8..0000000000 --- a/arch/arm/mach-samsung/include/mach/gpio.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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. - */ - -#ifndef __ASM_MACH_GPIO_H -#define __ASM_MACH_GPIO_H - -#include <asm-generic/gpio.h> - -#endif /* __ASM_MACH_GPIO_H */ diff --git a/arch/mips/include/asm/gpio.h b/arch/mips/include/asm/gpio.h deleted file mode 100644 index 41a9589f84..0000000000 --- a/arch/mips/include/asm/gpio.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ARCH_MIPS_GPIO_H -#define _ARCH_MIPS_GPIO_H - -#include <asm-generic/gpio.h> - -#endif /* _ARCH_MIPS_GPIO_H */ diff --git a/arch/ppc/boards/freescale-p1010rdb/p1010rdb.c b/arch/ppc/boards/freescale-p1010rdb/p1010rdb.c index 5bae5849ca..60cae46d25 100644 --- a/arch/ppc/boards/freescale-p1010rdb/p1010rdb.c +++ b/arch/ppc/boards/freescale-p1010rdb/p1010rdb.c @@ -21,6 +21,7 @@ #include <net.h> #include <types.h> #include <i2c/i2c.h> +#include <gpio.h> #include <partition.h> #include <memory.h> #include <asm/cache.h> @@ -32,7 +33,6 @@ #include <mach/immap_85xx.h> #include <mach/gianfar.h> #include <mach/clock.h> -#include <mach/gpio.h> #include <mach/early_udelay.h> #include <of.h> diff --git a/arch/ppc/boards/geip-da923rc/da923rc.c b/arch/ppc/boards/geip-da923rc/da923rc.c index 3d77349e0d..b6b5d56acd 100644 --- a/arch/ppc/boards/geip-da923rc/da923rc.c +++ b/arch/ppc/boards/geip-da923rc/da923rc.c @@ -21,6 +21,7 @@ #include <driver.h> #include <asm/io.h> #include <net.h> +#include <gpio.h> #include <ns16550.h> #include <partition.h> #include <environment.h> diff --git a/arch/ppc/mach-mpc85xx/include/mach/gpio.h b/arch/ppc/mach-mpc85xx/include/mach/gpio.h index 61f634922e..b41ecc5214 100644 --- a/arch/ppc/mach-mpc85xx/include/mach/gpio.h +++ b/arch/ppc/mach-mpc85xx/include/mach/gpio.h @@ -10,8 +10,6 @@ #ifndef _MACH_PPC_GPIO_H #define _MACH_PPC_GPIO_H -#include <asm-generic/gpio.h> - extern void fsl_enable_gpiout(void); #endif /* _MACH_PPC_GPIO_H */ diff --git a/commands/Kconfig b/commands/Kconfig index 133dcbf22c..630cb12169 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -928,7 +928,7 @@ config CMD_LS config CMD_MD5SUM tristate select COMPILE_HASH - select MD5 + select DIGEST_MD5_GENERIC prompt "md5sum" help Usage: md5sum FILE|AREA... @@ -993,7 +993,7 @@ config CMD_RMDIR config CMD_SHA1SUM tristate select COMPILE_HASH - select SHA1 + select DIGEST_SHA1_GENERIC prompt "sha1sum" help Calculate SHA1 digest @@ -1005,7 +1005,7 @@ config CMD_SHA1SUM config CMD_SHA224SUM tristate select COMPILE_HASH - select SHA224 + select DIGEST_SHA224_GENERIC prompt "sha224sum" help Calculate SHA224 digest @@ -1017,7 +1017,7 @@ config CMD_SHA224SUM config CMD_SHA256SUM tristate select COMPILE_HASH - select SHA256 + select DIGEST_SHA256_GENERIC prompt "sha256sum" help sha256sum - calculate SHA256 digest @@ -1029,7 +1029,7 @@ config CMD_SHA256SUM config CMD_SHA384SUM tristate select COMPILE_HASH - select SHA384 + select DIGEST_SHA384_GENERIC prompt "sha384sum" help Calculate SHA384 digest @@ -1041,7 +1041,7 @@ config CMD_SHA384SUM config CMD_SHA512SUM tristate select COMPILE_HASH - select SHA512 + select DIGEST_SHA512_GENERIC prompt "sha512sum" help sha512sum - calculate SHA512 digest @@ -1458,6 +1458,7 @@ endif config CMD_SPLASH bool select IMAGE_RENDERER + depends on VIDEO prompt "splash" help Display a BMP image on a framebuffer device diff --git a/commands/boot.c b/commands/boot.c index 3341a05ebd..fd58824d98 100644 --- a/commands/boot.c +++ b/commands/boot.c @@ -14,6 +14,7 @@ #include <environment.h> #include <globalvar.h> #include <magicvar.h> +#include <watchdog.h> #include <command.h> #include <readkey.h> #include <common.h> @@ -24,6 +25,7 @@ #include <clock.h> #include <boot.h> #include <glob.h> +#include <init.h> #include <menu.h> #include <fs.h> #include <complete.h> @@ -71,10 +73,28 @@ out: return ret; } +static unsigned int boot_watchdog_timeout; + +static int init_boot_watchdog_timeout(void) +{ + return globalvar_add_simple_int("boot.watchdog_timeout", + &boot_watchdog_timeout, "%u"); +} +late_initcall(init_boot_watchdog_timeout); + +BAREBOX_MAGICVAR_NAMED(global_watchdog_timeout, global.boot.watchdog_timeout, + "Watchdog enable timeout in seconds before booting"); + static int boot_entry(struct blspec_entry *be) { int ret; + if (IS_ENABLED(CONFIG_WATCHDOG) && boot_watchdog_timeout) { + ret = watchdog_set_timeout(boot_watchdog_timeout); + if (ret) + pr_warn("Failed to enable watchdog: %s\n", strerror(-ret)); + } + if (be->scriptpath) { ret = boot_script(be->scriptpath); } else { @@ -375,7 +395,7 @@ static int do_boot(int argc, char *argv[]) dryrun = 0; timeout = -1; - while ((opt = getopt(argc, argv, "vldmt:")) > 0) { + while ((opt = getopt(argc, argv, "vldmt:w:")) > 0) { switch (opt) { case 'v': verbose++; @@ -392,6 +412,9 @@ static int do_boot(int argc, char *argv[]) case 't': timeout = simple_strtoul(optarg, NULL, 0); break; + case 'w': + boot_watchdog_timeout = simple_strtoul(optarg, NULL, 0); + break; } } @@ -477,6 +500,7 @@ BAREBOX_CMD_HELP_OPT ("-v","Increase verbosity") BAREBOX_CMD_HELP_OPT ("-d","Dryrun. See what happens but do no actually boot") BAREBOX_CMD_HELP_OPT ("-l","List available boot sources") BAREBOX_CMD_HELP_OPT ("-m","Show a menu with boot options") +BAREBOX_CMD_HELP_OPT ("-w SECS","Start watchdog with timeout SECS before booting") BAREBOX_CMD_HELP_OPT ("-t SECS","specify timeout in SECS") BAREBOX_CMD_HELP_END diff --git a/commands/login.c b/commands/login.c index bf5085c854..58bb592900 100644 --- a/commands/login.c +++ b/commands/login.c @@ -19,89 +19,23 @@ #include <command.h> #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) - -#if defined(CONFIG_PASSWD_MODE_STAR) -#define LOGIN_MODE STAR -#elif defined(CONFIG_PASSWD_MODE_CLEAR) -#define LOGIN_MODE CLEAR -#else -#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 = login_timeout; - char *timeout_cmd = "boot"; - - console_allow_input(true); - if (!is_passwd_enable()) { - puts("login: password not set\n"); - return 0; - } - - while((opt = getopt(argc, argv, "t:")) > 0) { - switch(opt) { - case 't': - timeout = simple_strtoul(optarg, NULL, 10); - break; - } - } - - if (optind != argc) - timeout_cmd = argv[optind]; - - do { - puts("Password: "); - passwd_len = password(passwd, PASSWD_MAX_LENGTH, LOGIN_MODE, timeout); - - if (passwd_len < 0) { - console_allow_input(false); - run_command(timeout_cmd); - } - - if (check_passwd(passwd, passwd_len) == 1) - return 0; - } while(1); + login(); return 0; } BAREBOX_CMD_HELP_START(login) BAREBOX_CMD_HELP_TEXT("Asks for a password from the console before script execution continues.") -BAREBOX_CMD_HELP_TEXT("The password can be set with the 'passwd' command. Instead of specifying") -BAREBOX_CMD_HELP_TEXT("a TIMEOUT the magic variable 'global.login.timeout' could be set.") -BAREBOX_CMD_HELP_TEXT("") -BAREBOX_CMD_HELP_TEXT("Options:") -BAREBOX_CMD_HELP_OPT("-t TIMEOUT", "Execute COMMAND if no login withing TIMEOUT seconds") +BAREBOX_CMD_HELP_TEXT("The password can be set with the 'passwd' command.") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(login) .cmd = do_login, BAREBOX_CMD_DESC("ask for a password") - BAREBOX_CMD_OPTS("[-t TIMEOUT] COMMAND") BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE) 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/menutree.c b/commands/menutree.c index 5d30b67ee5..ea5f65f3a1 100644 --- a/commands/menutree.c +++ b/commands/menutree.c @@ -12,12 +12,15 @@ #include <common.h> #include <getopt.h> #include <menu.h> +#include <password.h> static int do_menutree(int argc, char *argv[]) { int opt, ret; char *path = "/env/menu"; + login(); + while ((opt = getopt(argc, argv, "m:")) > 0) { switch (opt) { case 'm': diff --git a/commands/splash.c b/commands/splash.c index 90f0a0cdf2..15b296b680 100644 --- a/commands/splash.c +++ b/commands/splash.c @@ -15,9 +15,9 @@ static int do_splash(int argc, char *argv[]) int opt; char *fbdev = "/dev/fb0"; char *image_file; - int offscreen = 0; u32 bg_color = 0x00000000; bool do_bg = false; + void *buf; memset(&s, 0, sizeof(s)); @@ -41,8 +41,6 @@ static int do_splash(int argc, char *argv[]) case 'y': s.y = simple_strtoul(optarg, NULL, 0); break; - case 'o': - offscreen = 1; } } @@ -52,21 +50,17 @@ static int do_splash(int argc, char *argv[]) } image_file = argv[optind]; - sc = fb_open(fbdev, offscreen); + sc = fb_open(fbdev); if (IS_ERR(sc)) { perror("fd_open"); return PTR_ERR(sc); } - if (sc->offscreenbuf) { - if (do_bg) - gu_memset_pixel(sc->info, sc->offscreenbuf, bg_color, - sc->s.width * sc->s.height); - else - memcpy(sc->offscreenbuf, sc->fb, sc->fbsize); - } else if (do_bg) { - gu_memset_pixel(sc->info, sc->fb, bg_color, sc->s.width * sc->s.height); - } + buf = gui_screen_render_buffer(sc); + + if (do_bg) + gu_memset_pixel(sc->info, buf, bg_color, + sc->s.width * sc->s.height); ret = image_renderer_file(sc, &s, image_file); if (ret > 0) @@ -89,7 +83,6 @@ BAREBOX_CMD_HELP_OPT ("-f FB\t", "framebuffer device (default /dev/fb0)") BAREBOX_CMD_HELP_OPT ("-x XOFFS", "x offset (default center)") BAREBOX_CMD_HELP_OPT ("-y YOFFS", "y offset (default center)") BAREBOX_CMD_HELP_OPT ("-b COLOR", "background color in 0xttrrggbb") -BAREBOX_CMD_HELP_OPT ("-o\t", "render offscreen") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(splash) diff --git a/commands/ubiformat.c b/commands/ubiformat.c index e63f16e351..f9d952cff0 100644 --- a/commands/ubiformat.c +++ b/commands/ubiformat.c @@ -779,6 +779,7 @@ BAREBOX_CMD_HELP_OPT("-f FILE\t", "flash image file") BAREBOX_CMD_HELP_OPT("-e VALUE", "use VALUE as erase counter value for all eraseblocks") BAREBOX_CMD_HELP_OPT("-x NUM\t", "UBI version number to put to EC headers (default 1)") BAREBOX_CMD_HELP_OPT("-Q NUM\t", "32-bit UBI image sequence number to use") +BAREBOX_CMD_HELP_OPT("-y\t", "Assume yes for all questions") BAREBOX_CMD_HELP_OPT("-q\t", "suppress progress percentage information") BAREBOX_CMD_HELP_OPT("-v\t", "be verbose") BAREBOX_CMD_HELP_TEXT("") diff --git a/common/Kconfig b/common/Kconfig index 8c6ba7fd42..877d3855a2 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -450,8 +450,14 @@ config PASSWORD config PASSWORD_DEFAULT string - prompt "Password default" + prompt "Password default file" depends on PASSWORD + help + Set this to a file which is used as default password file. This file + has to contain the passwd encoded with the selected password digest. + i.e.: + echo -ne "MyPassword" | md5sum | while read a b; do echo $a > passwdfile; done + if PASSWORD @@ -460,19 +466,19 @@ choice config PASSWD_SUM_MD5 bool "MD5" - select MD5 + select DIGEST_MD5_GENERIC config PASSWD_SUM_SHA1 bool "SHA1" - select SHA1 + select DIGEST_SHA1_GENERIC config PASSWD_SUM_SHA256 bool "SHA256" - select SHA256 + select DIGEST_SHA256_GENERIC config PASSWD_SUM_SHA512 bool "SHA512" - select SHA512 + select DIGEST_SHA512_GENERIC config PASSWD_CRYPTO_PBKDF2 bool "PBKDF2" diff --git a/common/console.c b/common/console.c index bf64c08b7c..84d4ea714d 100644 --- a/common/console.c +++ b/common/console.c @@ -344,9 +344,6 @@ 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 @@ -381,9 +378,6 @@ 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 2c82c6fd46..fcf89e8568 100644 --- a/common/console_common.c +++ b/common/console_common.c @@ -33,33 +33,6 @@ #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; LIST_HEAD(barebox_logbuf); diff --git a/common/console_simple.c b/common/console_simple.c index 6cb72bb46a..69e76593ad 100644 --- a/common/console_simple.c +++ b/common/console_simple.c @@ -41,9 +41,6 @@ EXPORT_SYMBOL(console_putc); int tstc(void) { - if (unlikely(!console_is_input_allow())) - return 0; - if (!console) return 0; @@ -53,9 +50,6 @@ EXPORT_SYMBOL(tstc); int getc(void) { - if (unlikely(!console_is_input_allow())) - return -EPERM; - if (!console) return -EINVAL; return console->getc(console); diff --git a/common/hush.c b/common/hush.c index ffd251339e..abe87137b5 100644 --- a/common/hush.c +++ b/common/hush.c @@ -116,6 +116,7 @@ #include <errno.h> #include <fs.h> #include <libbb.h> +#include <password.h> #include <glob.h> #include <getopt.h> #include <libfile.h> @@ -1914,6 +1915,8 @@ int run_shell(void) struct p_context ctx; int exit = 0; + login(); + do { setup_file_in_str(&input); rcode = parse_stream_outer(&ctx, &input, FLAG_PARSE_SEMICOLON); diff --git a/common/parser.c b/common/parser.c index 207599f429..ed414d04ea 100644 --- a/common/parser.c +++ b/common/parser.c @@ -1,5 +1,6 @@ #include <common.h> #include <command.h> +#include <password.h> #include <environment.h> #include <shell.h> @@ -266,6 +267,8 @@ int run_shell(void) int len; int rc = 1; + login(); + for (;;) { len = readline (CONFIG_PROMPT, console_buffer, CONFIG_CBSIZE); diff --git a/common/password.c b/common/password.c index c8454228d0..43c5e0cc0e 100644 --- a/common/password.c +++ b/common/password.c @@ -24,8 +24,11 @@ #include <digest.h> #include <malloc.h> #include <xfuncs.h> +#include <magicvar.h> #include <clock.h> +#include <init.h> #include <stdlib.h> +#include <globalvar.h> #include <generated/passwd.h> #include <crypto/pbkdf2.h> @@ -73,7 +76,7 @@ int password(unsigned char *passwd, size_t length, int flags, int timeout) case CTL_CH('c'): passwd[0] = '\0'; puts("\r\n"); - return 0; + return -EINTR; case CTL_CH('h'): case BB_KEY_DEL7: case BB_KEY_DEL: @@ -104,7 +107,7 @@ int password(unsigned char *passwd, size_t length, int flags, int timeout) } } while (!is_timeout(start, timeout * SECOND) || timeout == 0); - return -1; + return -ETIMEDOUT; } EXPORT_SYMBOL(password); @@ -155,17 +158,7 @@ static unsigned char to_hexa(unsigned char c) return 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) +static int read_default_passwd(unsigned char *sum, size_t length) { int i = 0; int len = strlen(default_passwd); @@ -192,7 +185,7 @@ int read_default_passwd(unsigned char *sum, size_t length) } EXPORT_SYMBOL(read_default_passwd); -int read_env_passwd(unsigned char *sum, size_t length) +static int read_env_passwd(unsigned char *sum, size_t length) { int fd; int ret = 0; @@ -283,7 +276,7 @@ exit: } EXPORT_SYMBOL(write_env_passwd); -static int __check_passwd(unsigned char* passwd, size_t length, int std) +static int check_passwd(unsigned char *passwd, size_t length) { struct digest *d = NULL; unsigned char *passwd1_sum; @@ -295,6 +288,10 @@ static int __check_passwd(unsigned char* passwd, size_t length, int std) hash_len = PBKDF2_LENGTH; } else { d = digest_alloc(PASSWD_SUM); + if (!d) { + pr_err("No such digest: %s\n", PASSWD_SUM); + return -ENOENT; + } hash_len = digest_length(d); } @@ -305,10 +302,12 @@ static int __check_passwd(unsigned char* passwd, size_t length, int std) passwd2_sum = passwd1_sum + hash_len; - if (std) + if (is_passwd_env_enable()) ret = read_env_passwd(passwd2_sum, hash_len); - else + else if (is_passwd_default_enable()) ret = read_default_passwd(passwd2_sum, hash_len); + else + ret = -EINVAL; if (ret < 0) goto err; @@ -342,28 +341,6 @@ err: return ret; } -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 = NULL; @@ -374,6 +351,8 @@ int set_env_passwd(unsigned char* passwd, size_t length) hash_len = PBKDF2_LENGTH; } else { d = digest_alloc(PASSWD_SUM); + if (!d) + return -EINVAL; hash_len = digest_length(d); } @@ -406,3 +385,69 @@ err: return ret; } EXPORT_SYMBOL(set_env_passwd); + +#define PASSWD_MAX_LENGTH (128 + 1) + +#if defined(CONFIG_PASSWD_MODE_STAR) +#define LOGIN_MODE STAR +#elif defined(CONFIG_PASSWD_MODE_CLEAR) +#define LOGIN_MODE CLEAR +#else +#define LOGIN_MODE HIDE +#endif + +static int logged_in; +static int login_timeout = 60; +static char *login_fail_command; + +/** + * login() - Prompt for password + * + * This function only returns when the correct password has been entered or + * no password is necessary because either no password is configured or the + * correct password has been entered in a previous call to this function. + */ +void login(void) +{ + unsigned char passwd[PASSWD_MAX_LENGTH]; + int ret; + + if (!is_passwd_default_enable() && !is_passwd_env_enable()) + return; + + if (logged_in) + return; + + while (1) { + printf("Password: "); + + ret = password(passwd, PASSWD_MAX_LENGTH, LOGIN_MODE, login_timeout); + if (ret < 0) + run_command(login_fail_command); + + if (ret < 0) + continue; + + if (check_passwd(passwd, ret) != 1) + continue; + + logged_in = 1; + return; + } +} + +static int login_global_init(void) +{ + login_fail_command = xstrdup("boot"); + + globalvar_add_simple_int("login.timeout", &login_timeout, "%d"); + globalvar_add_simple_string("login.fail_command", &login_fail_command); + + return 0; +} +late_initcall(login_global_init); + +BAREBOX_MAGICVAR_NAMED(global_login_fail_command, global.login.fail_command, + "command to run when password entry failed"); +BAREBOX_MAGICVAR_NAMED(global_login_timeout, global.login.timeout, + "timeout to type the password"); diff --git a/common/startup.c b/common/startup.c index 802b90e0e8..4a303b297a 100644 --- a/common/startup.c +++ b/common/startup.c @@ -108,13 +108,10 @@ void __noreturn start_barebox(void) if (IS_ENABLED(CONFIG_COMMAND_SUPPORT)) { pr_info("running /env/bin/init...\n"); - if (!stat("/env/bin/init", &s)) { + if (!stat("/env/bin/init", &s)) run_command("source /env/bin/init"); - } else { + else pr_err("/env/bin/init not found\n"); - if (IS_ENABLED(CONFIG_CMD_LOGIN)) - while(run_command("login -t 0")); - } } if (!barebox_main) { diff --git a/crypto/Kconfig b/crypto/Kconfig index 24f8b410ed..ef807dec68 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -82,5 +82,5 @@ endif config CRYPTO_PBKDF2 select DIGEST - select SHA1 + select DIGEST_SHA1_GENERIC bool diff --git a/defaultenv/defaultenv-2-base/bin/init b/defaultenv/defaultenv-2-base/bin/init index 30651e55d2..37ee3651ba 100644 --- a/defaultenv/defaultenv-2-base/bin/init +++ b/defaultenv/defaultenv-2-base/bin/init @@ -27,25 +27,15 @@ magicvar -a global.allow_color "Allow color on the console (boolean)" [ -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 autoboot="$?" if [ "${key}" = "q" ]; then - ${login_cmd} exit fi -[ -n ${login_cmd} ] && global.console.input_allow=0 - for i in /env/init/*; do . $i done @@ -56,17 +46,12 @@ else echo -e -n "\nHit any key to stop autoboot: " fi -[ -n ${login_cmd} ] && global.console.input_allow=1 - if [ "$autoboot" = 0 ]; then timeout -a $global.autoboot_timeout -v key autoboot="$?" fi -[ -n ${login_cmd} ] && global.console.input_allow=0 - if [ "${key}" = "q" ]; then - ${login_cmd} exit fi @@ -75,12 +60,9 @@ 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/eeprom/at24.c b/drivers/eeprom/at24.c index bb2dd533b6..76f30e7e22 100644 --- a/drivers/eeprom/at24.c +++ b/drivers/eeprom/at24.c @@ -21,6 +21,8 @@ #include <linux/log2.h> #include <i2c/i2c.h> #include <i2c/at24.h> +#include <gpio.h> +#include <of_gpio.h> /* * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. @@ -55,6 +57,8 @@ struct at24_data { u8 *writebuf; unsigned write_max; unsigned num_addresses; + int wp_gpio; + int wp_active_low; /* * Some chips tie up multiple I2C addresses; dummy devices reserve @@ -345,6 +349,25 @@ static ssize_t at24_cdev_write(struct cdev *cdev, const void *buf, size_t count, return at24_write(at24, buf, off, count); } +static ssize_t at24_cdev_protect(struct cdev *cdev, size_t count, loff_t offset, + int prot) +{ + struct at24_data *at24 = cdev->priv; + + if (!gpio_is_valid(at24->wp_gpio)) + return -EOPNOTSUPP; + + prot = !!prot; + if (at24->wp_active_low) + prot = !prot; + + gpio_set_value(at24->wp_gpio, prot); + + udelay(50); + + return 0; +} + static int at24_probe(struct device_d *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -403,6 +426,7 @@ static int at24_probe(struct device_d *dev) at24->cdev.ops = &at24->fops; at24->fops.lseek = dev_lseek_default; at24->fops.read = at24_cdev_read, + at24->fops.protect = at24_cdev_protect, at24->cdev.size = chip.byte_len; writable = !(chip.flags & AT24_FLAG_READONLY); @@ -419,6 +443,19 @@ static int at24_probe(struct device_d *dev) at24->writebuf = xmalloc(write_max + 2); } + at24->wp_gpio = -1; + if (dev->device_node) { + enum of_gpio_flags flags; + at24->wp_gpio = of_get_named_gpio_flags(dev->device_node, + "wp-gpios", 0, &flags); + if (gpio_is_valid(at24->wp_gpio)) { + at24->wp_active_low = flags & OF_GPIO_ACTIVE_LOW; + gpio_request(at24->wp_gpio, "eeprom-wp"); + gpio_direction_output(at24->wp_gpio, + !at24->wp_active_low); + } + } + at24->client[0] = client; /* use dummy devices for multiple-address chips */ @@ -440,6 +477,7 @@ static int at24_probe(struct device_d *dev) return 0; err_clients: + gpio_free(at24->wp_gpio); kfree(at24->writebuf); kfree(at24); err_out: diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index dc43eb83a4..2563c0d25a 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -106,9 +106,10 @@ static int sclhi(struct i2c_algo_bit_data *adap) } } #ifdef DEBUG - if (jiffies != start && i2c_debug >= 3) - pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go " - "high\n", jiffies - start); + if ((get_time_ns() - start) < 10000) + pr_debug("i2c-algo-bit: needed %u usecs for SCL to go " + "high\n", (unsigned int)(get_time_ns() - start) / + 1000); #endif done: @@ -116,6 +117,31 @@ done: return 0; } +static int wait_busy(struct i2c_algo_bit_data *adap) +{ + uint64_t start; + + if (sclhi(adap) < 0) + return -ETIMEDOUT; + + start = get_time_ns(); + while (!getsda(adap)) { + if (is_timeout(start, adap->timeout_ms * MSECOND)) { + if (getsda(adap)) + break; + return -ETIMEDOUT; + } + } +#ifdef DEBUG + if ((get_time_ns() - start) < 10000) + pr_debug("i2c-algo-bit: needed %u usecs for SDA to go " + "high\n", (unsigned int)(get_time_ns() - start) / + 1000); +#endif + + udelay(adap->udelay); + return 0; +} /* --- other auxiliary functions -------------------------------------- */ static void i2c_start(struct i2c_algo_bit_data *adap) @@ -426,10 +452,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) count--; bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n", - inval, - (flags & I2C_M_NO_RD_ACK) - ? "(no ack/nak)" - : (count ? "A" : "NA")); + inval, count ? "A" : "NA"); inval = acknak(i2c_adap, count); if (inval < 0) @@ -514,6 +537,13 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, return ret; } + if (wait_busy(adap) < 0) { /* timeout */ + dev_warn(&i2c_adap->dev, "timeout waiting for bus ready\n"); + ret = i2c_recover_bus(i2c_adap); + if (ret < 0) + return ret; + } + bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); i2c_start(adap); for (i = 0; i < num; i++) { diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index b4a0ecdb20..9362ed181f 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -10,6 +10,7 @@ #include <common.h> #include <driver.h> +#include <malloc.h> #include <i2c/i2c.h> #include <i2c/i2c-algo-bit.h> #include <i2c/i2c-gpio.h> @@ -187,6 +188,13 @@ static int i2c_gpio_probe(struct device_d *dev) adap->algo_data = bit_data; adap->dev.parent = dev; adap->dev.device_node = dev->device_node; + adap->bus_recovery_info = xzalloc(sizeof(*adap->bus_recovery_info)); + adap->bus_recovery_info->scl_gpio = pdata->scl_pin; + adap->bus_recovery_info->sda_gpio = pdata->sda_pin; + adap->bus_recovery_info->get_sda = i2c_get_sda_gpio_value; + adap->bus_recovery_info->get_scl = i2c_get_scl_gpio_value; + adap->bus_recovery_info->set_scl = i2c_set_scl_gpio_value; + adap->bus_recovery_info->recover_bus = i2c_generic_scl_recovery; adap->nr = dev->id; ret = i2c_bit_add_numbered_bus(adap); @@ -201,10 +209,12 @@ static int i2c_gpio_probe(struct device_d *dev) return 0; err_add_bus: + free(adap->bus_recovery_info); gpio_free(pdata->scl_pin); err_request_scl: gpio_free(pdata->sda_pin); err_request_sda: + free(priv); return ret; } diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 714e83c4b9..4cd03e18a8 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -539,8 +539,10 @@ static int __init i2c_fsl_probe(struct device_d *pdev) #ifdef CONFIG_COMMON_CLK i2c_fsl->clk = clk_get(pdev, NULL); - if (IS_ERR(i2c_fsl->clk)) - return PTR_ERR(i2c_fsl->clk); + if (IS_ERR(i2c_fsl->clk)) { + ret = PTR_ERR(i2c_fsl->clk); + goto fail; + } #endif /* Setup i2c_fsl driver structure */ i2c_fsl->adapter.master_xfer = i2c_fsl_xfer; @@ -548,8 +550,10 @@ static int __init i2c_fsl_probe(struct device_d *pdev) i2c_fsl->adapter.dev.parent = pdev; i2c_fsl->adapter.dev.device_node = pdev->device_node; i2c_fsl->base = dev_request_mem_region(pdev, 0); - if (IS_ERR(i2c_fsl->base)) - return PTR_ERR(i2c_fsl->base); + if (IS_ERR(i2c_fsl->base)) { + ret = PTR_ERR(i2c_fsl->base); + goto fail; + } i2c_fsl->dfsrr = -1; diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 330db98982..48c55daeda 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -107,16 +107,20 @@ #define OMAP_I2C_SCLH_HSSCLH 8 /* I2C System Test Register (OMAP_I2C_SYSTEST): */ -#ifdef DEBUG #define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */ #define OMAP_I2C_SYSTEST_FREE (1 << 14) /* Free running mode */ #define OMAP_I2C_SYSTEST_TMODE_MASK (3 << 12) /* Test mode select */ #define OMAP_I2C_SYSTEST_TMODE_SHIFT (12) /* Test mode select */ +/* Functional mode */ +#define OMAP_I2C_SYSTEST_SCL_I_FUNC (1 << 8) /* SCL line input value */ +#define OMAP_I2C_SYSTEST_SCL_O_FUNC (1 << 7) /* SCL line output value */ +#define OMAP_I2C_SYSTEST_SDA_I_FUNC (1 << 6) /* SDA line input value */ +#define OMAP_I2C_SYSTEST_SDA_O_FUNC (1 << 5) /* SDA line output value */ +/* SDA/SCL IO mode */ #define OMAP_I2C_SYSTEST_SCL_I (1 << 3) /* SCL line sense in */ #define OMAP_I2C_SYSTEST_SCL_O (1 << 2) /* SCL line drive out */ #define OMAP_I2C_SYSTEST_SDA_I (1 << 1) /* SDA line sense in */ #define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */ -#endif /* OCP_SYSSTATUS bit definitions */ #define SYSS_RESETDONE_MASK (1 << 0) @@ -492,7 +496,7 @@ static int omap_i2c_wait_for_bb(struct i2c_adapter *adapter) while (omap_i2c_read_reg(i2c_omap, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) { if (is_timeout(start, MSECOND)) { dev_warn(&adapter->dev, "timeout waiting for bus ready\n"); - return -ETIMEDOUT; + return i2c_recover_bus(adapter); } } @@ -673,6 +677,10 @@ omap_i2c_isr(struct omap_i2c_struct *dev) /* * ProDB0017052: Clear ARDY bit twice */ + if (stat & OMAP_I2C_STAT_ARDY) + omap_i2c_ack_stat(dev, OMAP_I2C_STAT_ARDY); + + if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { omap_i2c_ack_stat(dev, (OMAP_I2C_STAT_RRDY | @@ -986,6 +994,79 @@ out: #define OMAP_I2C_SCHEME_0 0 #define OMAP_I2C_SCHEME_1 1 +static int omap_i2c_get_scl(struct i2c_adapter *adapter) +{ + struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter); + u32 reg; + + reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG); + + return reg & OMAP_I2C_SYSTEST_SCL_I_FUNC; +} + +static int omap_i2c_get_sda(struct i2c_adapter *adapter) +{ + struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter); + u32 reg; + + reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG); + + return reg & OMAP_I2C_SYSTEST_SDA_I_FUNC; +} + +static void omap_i2c_set_scl(struct i2c_adapter *adapter, int val) +{ + struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter); + u32 reg; + + reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG); + if (val) + reg |= OMAP_I2C_SYSTEST_SCL_O; + else + reg &= ~OMAP_I2C_SYSTEST_SCL_O; + omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSTEST_REG, reg); +} + +static void omap_i2c_prepare_recovery(struct i2c_adapter *adapter) +{ + struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter); + u32 reg; + + reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG); + /* enable test mode */ + reg |= OMAP_I2C_SYSTEST_ST_EN; + /* select SDA/SCL IO mode */ + reg |= 3 << OMAP_I2C_SYSTEST_TMODE_SHIFT; + /* set SCL to high-impedance state (reset value is 0) */ + reg |= OMAP_I2C_SYSTEST_SCL_O; + /* set SDA to high-impedance state (reset value is 0) */ + reg |= OMAP_I2C_SYSTEST_SDA_O; + omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSTEST_REG, reg); +} + +static void omap_i2c_unprepare_recovery(struct i2c_adapter *adapter) +{ + struct omap_i2c_struct *i2c_omap = to_omap_i2c_struct(adapter); + u32 reg; + + reg = omap_i2c_read_reg(i2c_omap, OMAP_I2C_SYSTEST_REG); + /* restore reset values */ + reg &= ~OMAP_I2C_SYSTEST_ST_EN; + reg &= ~OMAP_I2C_SYSTEST_TMODE_MASK; + reg &= ~OMAP_I2C_SYSTEST_SCL_O; + reg &= ~OMAP_I2C_SYSTEST_SDA_O; + omap_i2c_write_reg(i2c_omap, OMAP_I2C_SYSTEST_REG, reg); +} + +static struct i2c_bus_recovery_info omap_i2c_bus_recovery_info = { + .get_scl = omap_i2c_get_scl, + .get_sda = omap_i2c_get_sda, + .set_scl = omap_i2c_set_scl, + .prepare_recovery = omap_i2c_prepare_recovery, + .unprepare_recovery = omap_i2c_unprepare_recovery, + .recover_bus = i2c_generic_scl_recovery, +}; + static int __init i2c_omap_probe(struct device_d *pdev) { @@ -1097,6 +1178,7 @@ i2c_omap_probe(struct device_d *pdev) i2c_omap->adapter.nr = pdev->id; i2c_omap->adapter.dev.parent = pdev; i2c_omap->adapter.dev.device_node = pdev->device_node; + i2c_omap->adapter.bus_recovery_info = &omap_i2c_bus_recovery_info; /* i2c device drivers may be active on return from add_adapter() */ r = i2c_add_numbered_adapter(&i2c_omap->adapter); diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c index f0df666b97..52aaea8170 100644 --- a/drivers/i2c/i2c.c +++ b/drivers/i2c/i2c.c @@ -23,6 +23,7 @@ #include <xfuncs.h> #include <init.h> #include <of.h> +#include <gpio.h> #include <i2c/i2c.h> @@ -228,6 +229,135 @@ int i2c_write_reg(struct i2c_client *client, u32 addr, const u8 *buf, u16 count) } EXPORT_SYMBOL(i2c_write_reg); +/* i2c bus recovery routines */ +int i2c_get_scl_gpio_value(struct i2c_adapter *adap) +{ + gpio_direction_input(adap->bus_recovery_info->scl_gpio); + return gpio_get_value(adap->bus_recovery_info->scl_gpio); +} + +void i2c_set_scl_gpio_value(struct i2c_adapter *adap, int val) +{ + if (val) + gpio_direction_input(adap->bus_recovery_info->scl_gpio); + else + gpio_direction_output(adap->bus_recovery_info->scl_gpio, 0); +} + +int i2c_get_sda_gpio_value(struct i2c_adapter *adap) +{ + return gpio_get_value(adap->bus_recovery_info->sda_gpio); +} + +static int i2c_get_gpios_for_recovery(struct i2c_adapter *adap) +{ + struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; + struct device_d *dev = &adap->dev; + int ret = 0; + + ret = gpio_request_one(bri->scl_gpio, GPIOF_IN, "i2c-scl"); + if (ret) { + dev_warn(dev, "Can't get SCL gpio: %d\n", bri->scl_gpio); + return ret; + } + + if (bri->get_sda) { + if (gpio_request_one(bri->sda_gpio, GPIOF_IN, "i2c-sda")) { + /* work without SDA polling */ + dev_warn(dev, "Can't get SDA gpio: %d. Not using SDA polling\n", + bri->sda_gpio); + bri->get_sda = NULL; + } + } + + return ret; +} + +static void i2c_put_gpios_for_recovery(struct i2c_adapter *adap) +{ + struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; + + if (bri->get_sda) + gpio_free(bri->sda_gpio); + + gpio_free(bri->scl_gpio); +} + +/* + * We are generating clock pulses. ndelay() determines durating of clk pulses. + * We will generate clock with rate 100 KHz and so duration of both clock levels + * is: delay in ns = (10^6 / 100) / 2 + */ +#define RECOVERY_NDELAY 5000 +#define RECOVERY_CLK_CNT 9 + +static int i2c_generic_recovery(struct i2c_adapter *adap) +{ + struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; + int i = 0, val = 1, ret = 0; + + if (bri->prepare_recovery) + bri->prepare_recovery(adap); + + bri->set_scl(adap, val); + ndelay(RECOVERY_NDELAY); + + /* + * By this time SCL is high, as we need to give 9 falling-rising edges + */ + while (i++ < RECOVERY_CLK_CNT * 2) { + if (val) { + /* Break if SDA is high */ + if (bri->get_sda && bri->get_sda(adap)) + break; + /* SCL shouldn't be low here */ + if (!bri->get_scl(adap)) { + dev_err(&adap->dev, + "SCL is stuck low, exit recovery\n"); + ret = -EBUSY; + break; + } + } + + val = !val; + bri->set_scl(adap, val); + ndelay(RECOVERY_NDELAY); + } + + if (bri->unprepare_recovery) + bri->unprepare_recovery(adap); + + return ret; +} + +int i2c_generic_scl_recovery(struct i2c_adapter *adap) +{ + return i2c_generic_recovery(adap); +} + +int i2c_generic_gpio_recovery(struct i2c_adapter *adap) +{ + int ret; + + ret = i2c_get_gpios_for_recovery(adap); + if (ret) + return ret; + + ret = i2c_generic_recovery(adap); + i2c_put_gpios_for_recovery(adap); + + return ret; +} + +int i2c_recover_bus(struct i2c_adapter *adap) +{ + if (!adap->bus_recovery_info) + return -EOPNOTSUPP; + + dev_dbg(&adap->dev, "Trying i2c bus recovery\n"); + return adap->bus_recovery_info->recover_bus(adap); +} + /** * i2c_new_device - instantiate one new I2C device * diff --git a/drivers/mci/mmci.c b/drivers/mci/mmci.c index 608cac1932..9d1e858917 100644 --- a/drivers/mci/mmci.c +++ b/drivers/mci/mmci.c @@ -269,18 +269,18 @@ static int read_bytes(struct mci_host *mci, char *dest, unsigned int blkcount, u xfercount -= len; dest += len; status = mmci_readl(host, MMCISTATUS); - status_err = status & (MCI_CMDCRCFAIL | MCI_DATATIMEOUT | - MCI_RXOVERRUN); + status_err = status & (MCI_DATACRCFAIL | MCI_DATATIMEOUT | + MCI_RXOVERRUN); } while(xfercount && !status_err); status_err = status & - (MCI_CMDCRCFAIL | MCI_DATATIMEOUT | MCI_DATABLOCKEND | + (MCI_DATACRCFAIL | MCI_DATATIMEOUT | MCI_DATABLOCKEND | MCI_RXOVERRUN); while (!status_err) { status = mmci_readl(host, MMCISTATUS); status_err = status & - (MCI_CMDCRCFAIL | MCI_DATATIMEOUT | MCI_DATABLOCKEND | + (MCI_DATACRCFAIL | MCI_DATATIMEOUT | MCI_DATABLOCKEND | MCI_RXOVERRUN); } @@ -288,7 +288,7 @@ static int read_bytes(struct mci_host *mci, char *dest, unsigned int blkcount, u dev_err(host->hw_dev, "Read data timed out, xfercount: %u, status: 0x%08X\n", xfercount, status); return -ETIMEDOUT; - } else if (status & MCI_CMDCRCFAIL) { + } else if (status & MCI_DATACRCFAIL) { dev_err(host->hw_dev, "Read data bytes CRC error: 0x%x\n", status); return -EILSEQ; } else if (status & MCI_RXOVERRUN) { @@ -351,7 +351,7 @@ static int write_bytes(struct mci_host *mci, char *dest, unsigned int blkcount, dev_dbg(host->hw_dev, "write_bytes: blkcount=%u blksize=%u\n", blkcount, blksize); status = mmci_readl(host, MMCISTATUS); - status_err = status & (MCI_CMDCRCFAIL | MCI_DATATIMEOUT); + status_err = status & (MCI_DATACRCFAIL | MCI_DATATIMEOUT); do { len = mmci_pio_write(host, dest, xfercount, status); @@ -359,11 +359,11 @@ static int write_bytes(struct mci_host *mci, char *dest, unsigned int blkcount, dest += len; status = mmci_readl(host, MMCISTATUS); - status_err = status & (MCI_CMDCRCFAIL | MCI_DATATIMEOUT); + status_err = status & (MCI_DATACRCFAIL | MCI_DATATIMEOUT); } while (!status_err && xfercount); status_err = status & - (MCI_CMDCRCFAIL | MCI_DATATIMEOUT | MCI_DATABLOCKEND); + (MCI_DATACRCFAIL | MCI_DATATIMEOUT | MCI_DATABLOCKEND); while (!status_err) { status = mmci_readl(host, MMCISTATUS); status_err = status & @@ -374,7 +374,7 @@ static int write_bytes(struct mci_host *mci, char *dest, unsigned int blkcount, dev_err(host->hw_dev, "Write data timed out, xfercount:%u,status:0x%08X\n", xfercount, status); return -ETIMEDOUT; - } else if (status & MCI_CMDCRCFAIL) { + } else if (status & MCI_DATACRCFAIL) { dev_err(host->hw_dev, "Write data CRC error\n"); return -EILSEQ; } diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 794c9dbd82..d627690080 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c @@ -235,6 +235,7 @@ static int m25p_probe(struct device_d *dev) enum read_mode mode = SPI_NOR_NORMAL; const char *flash_name = NULL; int device_id; + bool use_large_blocks; int ret; data = dev->platform_data; @@ -272,7 +273,10 @@ static int m25p_probe(struct device_d *dev) else flash_name = NULL; /* auto-detect */ - ret = spi_nor_scan(nor, flash_name, mode); + use_large_blocks = of_property_read_bool(dev->device_node, + "use-large-blocks"); + + ret = spi_nor_scan(nor, flash_name, mode, use_large_blocks); if (ret) return ret; diff --git a/drivers/mtd/nand/nand_mrvl_nfc.c b/drivers/mtd/nand/nand_mrvl_nfc.c index 258ff75953..1ec48cc09e 100644 --- a/drivers/mtd/nand/nand_mrvl_nfc.c +++ b/drivers/mtd/nand/nand_mrvl_nfc.c @@ -881,8 +881,9 @@ static int mrvl_nand_scan(struct mtd_info *mtd) * We'll use a bad block table stored in-flash and don't * allow writing the bad block marker to the flash. */ - chip->bbt_options |= NAND_BBT_USE_FLASH | - NAND_BBT_NO_OOB_BBM; + chip->bbt_options |= + NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB_BBM | + NAND_BBT_CREATE_EMPTY; chip->bbt_td = &bbt_main_descr; chip->bbt_md = &bbt_mirror_descr; } diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index dce29ca0ea..ff7bb7a5d8 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -1078,7 +1078,7 @@ static int cqspi_setup_flash(struct device_d *dev, nor->write = cqspi_write; nor->erase = cqspi_erase; - ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD); + ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD, false); if (ret) goto probe_failed; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index c85ed34e06..b357e5adb4 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -370,85 +370,27 @@ erase_err: static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, size_t len) { - struct spi_nor *nor = mtd_to_spi_nor(mtd); - uint32_t offset = ofs; - uint8_t status_old, status_new; - int ret = 0; - - ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); - if (ret) - return ret; - - status_old = read_sr(nor); - - if (offset < mtd->size - (mtd->size / 2)) - status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0; - else if (offset < mtd->size - (mtd->size / 4)) - status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; - else if (offset < mtd->size - (mtd->size / 8)) - status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; - else if (offset < mtd->size - (mtd->size / 16)) - status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; - else if (offset < mtd->size - (mtd->size / 32)) - status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; - else if (offset < mtd->size - (mtd->size / 64)) - status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; - else - status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; - - /* Only modify protection if it will not unlock other areas */ - if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) > - (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { - write_enable(nor); - ret = write_sr(nor, status_new); - if (ret) - goto err; - } - -err: - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); - return ret; + return 0; } static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); - uint32_t offset = ofs; - uint8_t status_old, status_new; - int ret = 0; + uint8_t status; + int ret; ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); if (ret) return ret; - status_old = read_sr(nor); - - if (offset+len > mtd->size - (mtd->size / 64)) - status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0); - else if (offset+len > mtd->size - (mtd->size / 32)) - status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; - else if (offset+len > mtd->size - (mtd->size / 16)) - status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; - else if (offset+len > mtd->size - (mtd->size / 8)) - status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; - else if (offset+len > mtd->size - (mtd->size / 4)) - status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; - else if (offset+len > mtd->size - (mtd->size / 2)) - status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; - else - status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; + status = read_sr(nor); + status &= ~(SR_BP2 | SR_BP1 | SR_BP0); + write_enable(nor); - /* Only modify protection if it will not lock other areas */ - if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) < - (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { - write_enable(nor); - ret = write_sr(nor, status_new); - if (ret) - goto err; - } + ret = write_sr(nor, status); -err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); + return ret; } @@ -523,6 +465,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, + { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, 0) }, /* ESMT */ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, @@ -537,6 +480,7 @@ static const struct spi_device_id spi_nor_ids[] = { /* GigaDevice */ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, + { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, /* Intel/Numonyx -- xxxs33b */ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, @@ -551,6 +495,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, + { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, @@ -559,14 +504,14 @@ static const struct spi_device_id spi_nor_ids[] = { { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, /* Micron */ - { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, - { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, - { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, - { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, + { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, + { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ) }, + { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, + { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, - { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, - { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, - { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR | SPI_NOR_QUAD_READ) }, + { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, + { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, + { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, /* PMC */ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, @@ -646,6 +591,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ + { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) }, { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, @@ -656,6 +602,7 @@ static const struct spi_device_id spi_nor_ids[] = { { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) }, { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, + { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K) }, { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, @@ -923,7 +870,8 @@ static int spi_nor_check(struct spi_nor *nor) return 0; } -int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) +int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode, + bool use_large_blocks) { const struct spi_device_id *id = NULL; struct flash_info *info; @@ -1012,10 +960,10 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS /* prefer "small sector" erase if possible */ - if (info->flags & SECT_4K) { + if (info->flags & SECT_4K && !use_large_blocks) { nor->erase_opcode = SPINOR_OP_BE_4K; mtd->erasesize = 4096; - } else if (info->flags & SECT_4K_PMC) { + } else if (info->flags & SECT_4K_PMC && !use_large_blocks) { nor->erase_opcode = SPINOR_OP_BE_4K_PMC; mtd->erasesize = 4096; } else diff --git a/drivers/of/of_path.c b/drivers/of/of_path.c index 2dc784851d..992972c9b5 100644 --- a/drivers/of/of_path.c +++ b/drivers/of/of_path.c @@ -117,7 +117,8 @@ out: * @flags: use OF_FIND_PATH_FLAGS_BB to return the .bb device if available * * paths in the devicetree have the form of a multistring property. The first - * string contains the full path to the physical device containing the path. + * string contains the full path to the physical device containing the path or + * a full path to a partition described by the OF partition binding. * The remaining strings have the form "<type>:<options>". Currently supported * for <type> are: * @@ -129,6 +130,7 @@ out: * * device-path = &mmc0, "partname:0"; * device-path = &norflash, "partname:barebox-environment"; + * device-path = &environment_nor; */ int of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags) { @@ -147,13 +149,15 @@ int of_find_path(struct device_node *node, const char *propname, char **outpath, return -ENODEV; op.dev = of_find_device_by_node_path(rnode->full_name); - if (!op.dev) - return -ENODEV; + if (!op.dev) { + op.dev = of_find_device_by_node_path(rnode->parent->full_name); + if (!op.dev) + return -ENODEV; + } device_detect(op.dev); - if (list_is_singular(&op.dev->cdevs)) - op.cdev = list_first_entry(&op.dev->cdevs, struct cdev, devices_list); + op.cdev = cdev_by_device_node(rnode); i = 1; diff --git a/drivers/of/partition.c b/drivers/of/partition.c index 3dce84404f..6017897b02 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -64,8 +64,8 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node) if (IS_ERR(new)) new = NULL; - if (new && new->dev) - new->dev->device_node = node; + if (new) + new->device_node = node;; free(filename); diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c index 6805d22a75..80dfc7819a 100644 --- a/drivers/spi/imx_spi.c +++ b/drivers/spi/imx_spi.c @@ -39,11 +39,18 @@ struct imx_spi { struct clk *clk; unsigned int (*xchg_single)(struct imx_spi *imx, u32 data); + void (*do_transfer)(struct spi_device *spi); void (*chipselect)(struct spi_device *spi, int active); + + const void *tx_buf; + void *rx_buf; + int xfer_len; + int bits_per_word; }; struct spi_imx_devtype_data { unsigned int (*xchg_single)(struct imx_spi *imx, u32 data); + void (*do_transfer)(struct spi_device *spi); void (*chipselect)(struct spi_device *spi, int active); void (*init)(struct imx_spi *imx); }; @@ -230,14 +237,8 @@ static unsigned int cspi_2_3_xchg_single(struct imx_spi *imx, unsigned int data) { void __iomem *base = imx->regs; - unsigned int cfg_reg = readl(base + CSPI_2_3_CTRL); - writel(data, base + CSPI_2_3_TXDATA); - cfg_reg |= CSPI_2_3_CTRL_XCH; - - writel(cfg_reg, base + CSPI_2_3_CTRL); - while (!(readl(base + CSPI_2_3_STAT) & CSPI_2_3_STAT_RR)); return readl(base + CSPI_2_3_RXDATA); @@ -306,6 +307,8 @@ static void cspi_2_3_chipselect(struct spi_device *spi, int is_active) ctrl |= (spi->bits_per_word - 1) << CSPI_2_3_CTRL_BL_OFFSET; + ctrl |= CSPI_2_3_CTRL_SMC; + cfg |= CSPI_2_3_CONFIG_SBBCTRL(cs); if (spi->mode & SPI_CPHA) @@ -336,38 +339,39 @@ static u32 imx_xchg_single(struct spi_device *spi, u32 tx_val) return imx_spi_maybe_reverse_bits(spi, rx_val); } -static void imx_spi_do_transfer(struct spi_device *spi, struct spi_transfer *t) +static void imx_spi_do_transfer(struct spi_device *spi) { + struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); unsigned i; - if (spi->bits_per_word <= 8) { - const u8 *tx_buf = t->tx_buf; - u8 *rx_buf = t->rx_buf; + if (imx->bits_per_word <= 8) { + const u8 *tx_buf = imx->tx_buf; + u8 *rx_buf = imx->rx_buf; u8 rx_val; - for (i = 0; i < t->len; i++) { + for (i = 0; i < imx->xfer_len; i++) { rx_val = imx_xchg_single(spi, tx_buf ? tx_buf[i] : 0); if (rx_buf) rx_buf[i] = rx_val; } - } else if (spi->bits_per_word <= 16) { - const u16 *tx_buf = t->tx_buf; - u16 *rx_buf = t->rx_buf; + } else if (imx->bits_per_word <= 16) { + const u16 *tx_buf = imx->tx_buf; + u16 *rx_buf = imx->rx_buf; u16 rx_val; - for (i = 0; i < t->len >> 1; i++) { + for (i = 0; i < imx->xfer_len >> 1; i++) { rx_val = imx_xchg_single(spi, tx_buf ? tx_buf[i] : 0); if (rx_buf) rx_buf[i] = rx_val; } - } else if (spi->bits_per_word <= 32) { - const u32 *tx_buf = t->tx_buf; - u32 *rx_buf = t->rx_buf; + } else if (imx->bits_per_word <= 32) { + const u32 *tx_buf = imx->tx_buf; + u32 *rx_buf = imx->rx_buf; u32 rx_val; - for (i = 0; i < t->len >> 2; i++) { + for (i = 0; i < imx->xfer_len >> 2; i++) { rx_val = imx_xchg_single(spi, tx_buf ? tx_buf[i] : 0); if (rx_buf) @@ -376,6 +380,77 @@ static void imx_spi_do_transfer(struct spi_device *spi, struct spi_transfer *t) } } +static int cspi_2_3_xchg_burst(struct spi_device *spi) +{ + struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); + int now, txlen, rxlen; + u32 ctrl; + void __iomem *base = imx->regs; + + now = min(imx->xfer_len, 512); + now >>= 2; + + if (!now) + return 0; + + txlen = rxlen = now; + + ctrl = readl(base + CSPI_2_3_CTRL); + ctrl &= ~(0xfff << CSPI_2_3_CTRL_BL_OFFSET); + ctrl |= ((txlen * 32) - 1) << CSPI_2_3_CTRL_BL_OFFSET; + ctrl |= 1 << 3; + writel(ctrl, base + CSPI_2_3_CTRL); + + while (txlen || rxlen) { + u32 status = readl(base + CSPI_2_3_STAT); + + if (txlen && !(status & CSPI_2_3_STAT_TF)) { + if (imx->tx_buf) { + u32 data = swab32(*(u32 *)imx->tx_buf); + writel(data, base + CSPI_2_3_TXDATA); + imx->tx_buf += sizeof(u32); + } else { + writel(0, base + CSPI_2_3_TXDATA); + } + txlen--; + } + + if (rxlen && (status & CSPI_2_3_STAT_RR)) { + u32 data = readl(base + CSPI_2_3_RXDATA); + + if (imx->rx_buf) { + *(u32 *)imx->rx_buf = swab32(data); + imx->rx_buf += sizeof(u32); + } + + rxlen--; + } + } + + imx->xfer_len -= now * 4; + + return now; +} + +static void cspi_2_3_do_transfer(struct spi_device *spi) +{ + struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); + u32 ctrl; + + if (imx->bits_per_word == 8 || imx->bits_per_word == 16 || imx->bits_per_word == 32) + while (cspi_2_3_xchg_burst(spi) > 0); + + if (!imx->xfer_len) + return; + + ctrl = readl(imx->regs + CSPI_2_3_CTRL); + ctrl &= ~(0xfff << CSPI_2_3_CTRL_BL_OFFSET); + ctrl |= (spi->bits_per_word - 1) << CSPI_2_3_CTRL_BL_OFFSET; + writel(ctrl, imx->regs + CSPI_2_3_CTRL); + + imx_spi_do_transfer(spi); +} + static int imx_spi_transfer(struct spi_device *spi, struct spi_message *mesg) { struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); @@ -399,7 +474,12 @@ static int imx_spi_transfer(struct spi_device *spi, struct spi_message *mesg) cs_change = t->cs_change; - imx_spi_do_transfer(spi, t); + imx->tx_buf = t->tx_buf; + imx->rx_buf = t->rx_buf; + imx->xfer_len = t->len; + imx->bits_per_word = spi->bits_per_word; + imx->do_transfer(spi); + mesg->actual_length += t->len; if (cs_change) @@ -415,17 +495,20 @@ static int imx_spi_transfer(struct spi_device *spi, struct spi_message *mesg) static __maybe_unused struct spi_imx_devtype_data spi_imx_devtype_data_0_0 = { .chipselect = cspi_0_0_chipselect, .xchg_single = cspi_0_0_xchg_single, + .do_transfer = imx_spi_do_transfer, .init = cspi_0_0_init, }; static __maybe_unused struct spi_imx_devtype_data spi_imx_devtype_data_0_7 = { .chipselect = cspi_0_7_chipselect, .xchg_single = cspi_0_7_xchg_single, + .do_transfer = imx_spi_do_transfer, .init = cspi_0_7_init, }; static __maybe_unused struct spi_imx_devtype_data spi_imx_devtype_data_2_3 = { .chipselect = cspi_2_3_chipselect, + .do_transfer = cspi_2_3_do_transfer, .xchg_single = cspi_2_3_xchg_single, }; @@ -490,6 +573,7 @@ static int imx_spi_probe(struct device_d *dev) imx->chipselect = devdata->chipselect; imx->xchg_single = devdata->xchg_single; + imx->do_transfer = devdata->do_transfer; imx->regs = dev_request_mem_region(dev, 0); if (devdata->init) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index d7f5b07637..501e9fa7d3 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -7,6 +7,7 @@ if VIDEO config FRAMEBUFFER_CONSOLE bool + depends on !CONSOLE_NONE select IMAGE_RENDERER select FONTS prompt "framebuffer console support" @@ -119,6 +120,7 @@ comment "Video encoder chips" config DRIVER_VIDEO_MTL017 bool "MTL017 LVDS encoder" select VIDEO_VPL + depends on I2C help The MTL017 is a parallel to lvds video encoder chip found on the Efika MX Smartbook. diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 29b4c71014..3672c44202 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -11,10 +11,12 @@ static int fb_ioctl(struct cdev* cdev, int req, void *data) { struct fb_info *info = cdev->priv; + struct fb_info **fb; switch (req) { case FBIOGET_SCREENINFO: - memcpy(data, info, sizeof(*info)); + fb = data; + *fb = info; break; case FBIO_ENABLE: info->fbops->fb_enable(info); @@ -29,11 +31,40 @@ static int fb_ioctl(struct cdev* cdev, int req, void *data) return 0; } +static int fb_alloc_shadowfb(struct fb_info *info) +{ + if (info->screen_base_shadow && info->shadowfb) + return 0; + + if (!info->screen_base_shadow && !info->shadowfb) + return 0; + + if (info->shadowfb) { + info->screen_base_shadow = memalign(PAGE_SIZE, + info->line_length * info->yres); + if (!info->screen_base_shadow) + return -ENOMEM; + memcpy(info->screen_base_shadow, info->screen_base, + info->line_length * info->yres); + } else { + free(info->screen_base_shadow); + info->screen_base_shadow = NULL; + } + + return 0; +} + int fb_enable(struct fb_info *info) { + int ret; + if (info->enabled) return 0; + ret = fb_alloc_shadowfb(info); + if (ret) + return ret; + info->fbops->fb_enable(info); info->enabled = true; @@ -186,6 +217,22 @@ static void fb_info(struct device_d *dev) fb_print_modes(&info->edid_modes); } +void *fb_get_screen_base(struct fb_info *info) +{ + return info->screen_base_shadow ? + info->screen_base_shadow : info->screen_base; +} + +int fb_set_shadowfb(struct param_d *p, void *priv) +{ + struct fb_info *info = priv; + + if (!info->enabled) + return 0; + + return fb_alloc_shadowfb(info); +} + int register_framebuffer(struct fb_info *info) { int id = get_free_deviceid("fb"); @@ -243,6 +290,8 @@ int register_framebuffer(struct fb_info *info) for (i = 0; i < info->edid_modes.num_modes; i++) names[i + info->modes.num_modes] = info->edid_modes.modes[i].name; dev_add_param_enum(dev, "mode_name", fb_set_modename, NULL, &info->current_mode, names, num_modes, info); + info->shadowfb = 1; + dev_add_param_bool(dev, "shadowfb", fb_set_shadowfb, NULL, &info->shadowfb, info); info->mode = fb_num_to_mode(info, 0); diff --git a/drivers/video/fbconsole.c b/drivers/video/fbconsole.c index b368079992..b10503eb84 100644 --- a/drivers/video/fbconsole.c +++ b/drivers/video/fbconsole.c @@ -40,6 +40,7 @@ struct fbc_priv { u8 csi[256]; int active; + int in_console; }; static int fbc_getc(struct console_device *cdev) @@ -57,6 +58,7 @@ static void cls(struct fbc_priv *priv) void *buf = gui_screen_render_buffer(priv->sc); memset(buf, 0, priv->fb->line_length * priv->fb->yres); + gu_screen_blit(priv->sc); } struct rgb { @@ -137,6 +139,8 @@ static void video_invertchar(struct fbc_priv *priv, int x, int y) gu_invert_area(priv->fb, buf, x * priv->font_width, y * priv->font_height, priv->font_width, priv->font_height); + gu_screen_blit_area(priv->sc, x * priv->font_width, y * priv->font_height, + priv->font_width, priv->font_height); } static void printchar(struct fbc_priv *priv, int c) @@ -169,7 +173,10 @@ static void printchar(struct fbc_priv *priv, int c) default: drawchar(priv, priv->x, priv->y, c); - gu_screen_blit(priv->sc); + + gu_screen_blit_area(priv->sc, priv->x * priv->font_width, + priv->y * priv->font_height, + priv->font_width, priv->font_height); priv->x++; if (priv->x > priv->cols) { @@ -187,6 +194,7 @@ static void printchar(struct fbc_priv *priv, int c) memcpy(buf, buf + line_height, line_height * (priv->rows + 1)); memset(buf + line_height * priv->rows, 0, line_height); + gu_screen_blit(priv->sc); priv->y = priv->rows; } @@ -250,6 +258,7 @@ static void fbc_parse_csi(struct fbc_priv *priv) return; case 'J': cls(priv); + video_invertchar(priv, priv->x, priv->y); return; case 'H': video_invertchar(priv, priv->x, priv->y); @@ -282,6 +291,10 @@ static void fbc_putc(struct console_device *cdev, char c) struct fbc_priv *priv = container_of(cdev, struct fbc_priv, cdev); + if (priv->in_console) + return; + priv->in_console = 1; + switch (priv->state) { case LIT: switch (c) { @@ -329,6 +342,7 @@ static void fbc_putc(struct console_device *cdev, char c) } break; } + priv->in_console = 0; } static int setup_font(struct fbc_priv *priv) @@ -370,7 +384,7 @@ static int fbc_set_active(struct console_device *cdev, unsigned flags) if (ret) return ret; - priv->sc = fb_create_screen(fb, 0); + priv->sc = fb_create_screen(fb); if (IS_ERR(priv->sc)) return PTR_ERR(priv->sc); diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c index b56658202c..a87e720d96 100644 --- a/drivers/video/imx-ipu-fb.c +++ b/drivers/video/imx-ipu-fb.c @@ -355,7 +355,8 @@ struct ipu_ch_param { struct ipu_cpmem_word word[2]; }; -void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v) +static void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, + u32 wbs, u32 v) { u32 bit = (wbs >> 8) % 160; u32 size = wbs & 0xff; @@ -500,7 +501,8 @@ static int sdc_init_panel(struct fb_info *info, enum disp_data_mapping fmt) return 0; } -int ipu_cpmem_set_format_rgb(struct ipu_ch_param *p, struct imx_ipu_fb_rgb *rgb) +static int ipu_cpmem_set_format_rgb(struct ipu_ch_param *p, + struct imx_ipu_fb_rgb *rgb) { int bpp = 0, npb = 0, ro, go, bo, to; diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.c b/drivers/video/imx-ipu-v3/imx-hdmi.c index f5a2e3c601..fa55b19c94 100644 --- a/drivers/video/imx-ipu-v3/imx-hdmi.c +++ b/drivers/video/imx-ipu-v3/imx-hdmi.c @@ -6,8 +6,7 @@ * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * - * SH-Mobile High-Definition Multimedia Interface (HDMI) driver - * for SLISHDMI13T and SLIPHDMIT IP cores + * Designware High-Definition Multimedia Interface (HDMI) driver * * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de> */ @@ -60,7 +59,7 @@ enum hdmi_datamap { YCbCr422_12B = 0x12, }; -enum imx_hdmi_devtype { +enum dw_hdmi_devtype { IMX6Q_HDMI, IMX6DL_HDMI, }; @@ -117,8 +116,8 @@ struct hdmi_data_info { struct hdmi_vmode video_mode; }; -struct imx_hdmi { - enum imx_hdmi_devtype dev_type; +struct dw_hdmi { + enum dw_hdmi_devtype dev_type; struct device_d *dev; struct clk *isfr_clk; struct clk *iahb_clk; @@ -140,10 +139,12 @@ struct imx_hdmi { unsigned int sample_rate; int ratio; + struct fb_videomode *mode; + struct vpl vpl; }; -static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di) +static void dw_hdmi_set_ipu_di_mux(struct dw_hdmi *hdmi, int ipu_di) { void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc; uint32_t val; @@ -156,49 +157,47 @@ static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di) writel(val, gpr3); } -static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset) +static inline void hdmi_writeb(struct dw_hdmi *hdmi, u8 val, int offset) { writeb(val, hdmi->regs + offset); } -static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset) +static inline u8 hdmi_readb(struct dw_hdmi *hdmi, int offset) { return readb(hdmi->regs + offset); } -static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg) +static void hdmi_modb(struct dw_hdmi *hdmi, u8 data, u8 mask, unsigned reg) { u8 val = hdmi_readb(hdmi, reg) & ~mask; + val |= data & mask; hdmi_writeb(hdmi, val, reg); } -static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg, - u8 shift, u8 mask) +static void hdmi_mask_writeb(struct dw_hdmi *hdmi, u8 data, unsigned int reg, + u8 shift, u8 mask) { hdmi_modb(hdmi, data << shift, mask, reg); } -static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi, - unsigned int value) +static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, + unsigned int n) { - hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1); - hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2); - hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3); + /* Must be set/cleared first */ + hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); /* nshift factor = 0 */ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); -} - -static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts) -{ - /* Must be set/cleared first */ - hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); - hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); - hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); + hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); + hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); + + hdmi_writeb(hdmi, (n >> 16) & 0x0f, HDMI_AUD_N3); + hdmi_writeb(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2); + hdmi_writeb(hdmi, n & 0xff, HDMI_AUD_N1); } static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk, @@ -334,12 +333,11 @@ static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk, } if (ratio == 100) return cts; - else - return (cts * ratio) / 100; + return (cts * ratio) / 100; } -static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi, - unsigned long pixel_clk) +static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, + unsigned long pixel_clk) { unsigned int clk_n, clk_cts; @@ -350,7 +348,7 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi, if (!clk_cts) { dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n", - __func__, pixel_clk); + __func__, pixel_clk); return; } @@ -358,11 +356,10 @@ static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi, __func__, hdmi->sample_rate, hdmi->ratio, pixel_clk, clk_n, clk_cts); - hdmi_set_clock_regenerator_n(hdmi, clk_n); - hdmi_regenerate_cts(hdmi, clk_cts); + hdmi_set_cts_n(hdmi, clk_cts, clk_n); } -static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi) +static void hdmi_init_clk_regenerator(struct dw_hdmi *hdmi) { hdmi_set_clk_regenerator(hdmi, 74250000); } @@ -374,7 +371,7 @@ static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi) * pin{31~24} <==> G[7:0] * pin{15~8} <==> B[7:0] */ -static void hdmi_video_sample(struct imx_hdmi *hdmi) +static void hdmi_video_sample(struct dw_hdmi *hdmi) { int color_format = 0; u8 val; @@ -430,27 +427,32 @@ static void hdmi_video_sample(struct imx_hdmi *hdmi) hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1); } -static int is_color_space_conversion(struct imx_hdmi *hdmi) +static int is_color_space_conversion(struct dw_hdmi *hdmi) { - return (hdmi->hdmi_data.enc_in_format != - hdmi->hdmi_data.enc_out_format); + return hdmi->hdmi_data.enc_in_format != hdmi->hdmi_data.enc_out_format; } -static int is_color_space_decimation(struct imx_hdmi *hdmi) +static int is_color_space_decimation(struct dw_hdmi *hdmi) { - return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) && - (hdmi->hdmi_data.enc_in_format == RGB || - hdmi->hdmi_data.enc_in_format == YCBCR444)); + if (hdmi->hdmi_data.enc_out_format != YCBCR422_8BITS) + return 0; + if (hdmi->hdmi_data.enc_in_format == RGB || + hdmi->hdmi_data.enc_in_format == YCBCR444) + return 1; + return 0; } -static int is_color_space_interpolation(struct imx_hdmi *hdmi) +static int is_color_space_interpolation(struct dw_hdmi *hdmi) { - return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) && - (hdmi->hdmi_data.enc_out_format == RGB || - hdmi->hdmi_data.enc_out_format == YCBCR444)); + if (hdmi->hdmi_data.enc_in_format != YCBCR422_8BITS) + return 0; + if (hdmi->hdmi_data.enc_out_format == RGB || + hdmi->hdmi_data.enc_out_format == YCBCR444) + return 1; + return 0; } -static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) +static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi) { const u16 (*csc_coeff)[3][4] = &csc_coeff_default; unsigned i; @@ -458,12 +460,14 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) if (is_color_space_conversion(hdmi)) { if (hdmi->hdmi_data.enc_out_format == RGB) { - if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) + if (hdmi->hdmi_data.colorimetry == + HDMI_COLORIMETRY_ITU_601) csc_coeff = &csc_coeff_rgb_out_eitu601; else csc_coeff = &csc_coeff_rgb_out_eitu709; } else if (hdmi->hdmi_data.enc_in_format == RGB) { - if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601) + if (hdmi->hdmi_data.colorimetry == + HDMI_COLORIMETRY_ITU_601) csc_coeff = &csc_coeff_rgb_in_eitu601; else csc_coeff = &csc_coeff_rgb_in_eitu709; @@ -489,7 +493,7 @@ static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi) HDMI_CSC_SCALE); } -static void hdmi_video_csc(struct imx_hdmi *hdmi) +static void hdmi_video_csc(struct dw_hdmi *hdmi) { int color_depth = 0; int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE; @@ -517,7 +521,7 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi) hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK, HDMI_CSC_SCALE); - imx_hdmi_update_csc_coeffs(hdmi); + dw_hdmi_update_csc_coeffs(hdmi); } /* @@ -525,7 +529,7 @@ static void hdmi_video_csc(struct imx_hdmi *hdmi) * for example, if input is YCC422 mode or repeater is used, * data should be repacked this module can be bypassed. */ -static void hdmi_video_packetize(struct imx_hdmi *hdmi) +static void hdmi_video_packetize(struct dw_hdmi *hdmi) { unsigned int color_depth = 0; unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit; @@ -533,21 +537,22 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi) struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data; u8 val, vp_conf; - if (hdmi_data->enc_out_format == RGB - || hdmi_data->enc_out_format == YCBCR444) { - if (!hdmi_data->enc_color_depth) + if (hdmi_data->enc_out_format == RGB || + hdmi_data->enc_out_format == YCBCR444) { + if (!hdmi_data->enc_color_depth) { output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; - else if (hdmi_data->enc_color_depth == 8) { + } else if (hdmi_data->enc_color_depth == 8) { color_depth = 4; output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS; - } else if (hdmi_data->enc_color_depth == 10) + } else if (hdmi_data->enc_color_depth == 10) { color_depth = 5; - else if (hdmi_data->enc_color_depth == 12) + } else if (hdmi_data->enc_color_depth == 12) { color_depth = 6; - else if (hdmi_data->enc_color_depth == 16) + } else if (hdmi_data->enc_color_depth == 16) { color_depth = 7; - else + } else { return; + } } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) { if (!hdmi_data->enc_color_depth || hdmi_data->enc_color_depth == 8) @@ -559,8 +564,9 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi) else return; output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422; - } else + } else { return; + } /* set the packetizer registers */ val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) & @@ -620,109 +626,110 @@ static void hdmi_video_packetize(struct imx_hdmi *hdmi) HDMI_VP_CONF); } -static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi, - unsigned char bit) +static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, + unsigned char bit) { hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET, HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0); } -static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi, - unsigned char bit) +static inline void hdmi_phy_test_enable(struct dw_hdmi *hdmi, + unsigned char bit) { hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET, HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0); } -static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi, - unsigned char bit) +static inline void hdmi_phy_test_clock(struct dw_hdmi *hdmi, + unsigned char bit) { hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET, HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0); } -static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi, - unsigned char bit) +static inline void hdmi_phy_test_din(struct dw_hdmi *hdmi, + unsigned char bit) { hdmi_writeb(hdmi, bit, HDMI_PHY_TST1); } -static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi, - unsigned char bit) +static inline void hdmi_phy_test_dout(struct dw_hdmi *hdmi, + unsigned char bit) { hdmi_writeb(hdmi, bit, HDMI_PHY_TST2); } -static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec) +static bool hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, int msec) { - unsigned char val = 0; - val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3; - while (!val) { - udelay(1000); + u32 val; + + while ((val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3) == 0) { if (msec-- == 0) return false; - val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3; + udelay(1000); } + hdmi_writeb(hdmi, val, HDMI_IH_I2CMPHY_STAT0); + return true; } -static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, - unsigned char addr) +static void __hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, + unsigned char addr) { hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0); hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR); hdmi_writeb(hdmi, (unsigned char)(data >> 8), - HDMI_PHY_I2CM_DATAO_1_ADDR); + HDMI_PHY_I2CM_DATAO_1_ADDR); hdmi_writeb(hdmi, (unsigned char)(data >> 0), - HDMI_PHY_I2CM_DATAO_0_ADDR); + HDMI_PHY_I2CM_DATAO_0_ADDR); hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE, - HDMI_PHY_I2CM_OPERATION_ADDR); + HDMI_PHY_I2CM_OPERATION_ADDR); hdmi_phy_wait_i2c_done(hdmi, 1000); } -static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data, - unsigned char addr) +static int hdmi_phy_i2c_write(struct dw_hdmi *hdmi, unsigned short data, + unsigned char addr) { __hdmi_phy_i2c_write(hdmi, data, addr); return 0; } -static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable) +static void dw_hdmi_phy_enable_power(struct dw_hdmi *hdmi, u8 enable) { hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_OFFSET, HDMI_PHY_CONF0_PDZ_MASK); } -static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable) +static void dw_hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, u8 enable) { hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_OFFSET, HDMI_PHY_CONF0_ENTMDS_MASK); } -static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable) +static void dw_hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, u8 enable) { hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET, HDMI_PHY_CONF0_GEN2_PDDQ_MASK); } -static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable) +static void dw_hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, u8 enable) { hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET, HDMI_PHY_CONF0_GEN2_TXPWRON_MASK); } -static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable) +static void dw_hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, u8 enable) { hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDATAENPOL_OFFSET, HDMI_PHY_CONF0_SELDATAENPOL_MASK); } -static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable) +static void dw_hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi, u8 enable) { hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_OFFSET, @@ -730,10 +737,10 @@ static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable) } enum { - RES_8, - RES_10, - RES_12, - RES_MAX, + DW_HDMI_RES_8, + DW_HDMI_RES_10, + DW_HDMI_RES_12, + DW_HDMI_RES_MAX, }; struct mpll_config { @@ -741,7 +748,7 @@ struct mpll_config { struct { u16 cpce; u16 gmp; - } res[RES_MAX]; + } res[DW_HDMI_RES_MAX]; }; static const struct mpll_config mpll_config[] = { @@ -774,7 +781,7 @@ static const struct mpll_config mpll_config[] = { struct curr_ctrl { unsigned long mpixelclock; - u16 curr[RES_MAX]; + u16 curr[DW_HDMI_RES_MAX]; }; static const struct curr_ctrl curr_ctrl[] = { @@ -794,7 +801,7 @@ static const struct curr_ctrl curr_ctrl[] = { } }; -static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, +static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep, unsigned char res, int cscon) { unsigned res_idx, i; @@ -806,13 +813,13 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, switch (res) { case 0: /* color resolution 0 is 8 bit colour depth */ case 8: - res_idx = RES_8; + res_idx = DW_HDMI_RES_8; break; case 10: - res_idx = RES_10; + res_idx = DW_HDMI_RES_10; break; case 12: - res_idx = RES_12; + res_idx = DW_HDMI_RES_12; break; default: return -EINVAL; @@ -827,10 +834,10 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL); /* gen2 tx power off */ - imx_hdmi_phy_gen2_txpwron(hdmi, 0); + dw_hdmi_phy_gen2_txpwron(hdmi, 0); /* gen2 pddq */ - imx_hdmi_phy_gen2_pddq(hdmi, 1); + dw_hdmi_phy_gen2_pddq(hdmi, 1); /* PHY reset */ hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ); @@ -840,7 +847,7 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, hdmi_phy_test_clear(hdmi, 1); hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2, - HDMI_PHY_I2CM_SLAVE_ADDR); + HDMI_PHY_I2CM_SLAVE_ADDR); hdmi_phy_test_clear(hdmi, 0); /* PLL/MPLL Cfg - always match on final entry */ @@ -878,15 +885,15 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, /* REMOVE CLK TERM */ hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */ - imx_hdmi_phy_enable_power(hdmi, 1); + dw_hdmi_phy_enable_power(hdmi, 1); /* toggle TMDS enable */ - imx_hdmi_phy_enable_tmds(hdmi, 0); - imx_hdmi_phy_enable_tmds(hdmi, 1); + dw_hdmi_phy_enable_tmds(hdmi, 0); + dw_hdmi_phy_enable_tmds(hdmi, 1); /* gen2 tx power on */ - imx_hdmi_phy_gen2_txpwron(hdmi, 1); - imx_hdmi_phy_gen2_pddq(hdmi, 0); + dw_hdmi_phy_gen2_txpwron(hdmi, 1); + dw_hdmi_phy_gen2_pddq(hdmi, 0); /*Wait for PHY PLL lock */ msec = 5; @@ -907,7 +914,7 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep, return 0; } -static int imx_hdmi_phy_init(struct imx_hdmi *hdmi) +static int dw_hdmi_phy_init(struct dw_hdmi *hdmi) { int i, ret; bool cscon = false; @@ -918,10 +925,10 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi) /* HDMI Phy spec says to do the phy initialization sequence twice */ for (i = 0; i < 2; i++) { - imx_hdmi_phy_sel_data_en_pol(hdmi, 1); - imx_hdmi_phy_sel_interface_control(hdmi, 0); - imx_hdmi_phy_enable_tmds(hdmi, 0); - imx_hdmi_phy_enable_power(hdmi, 0); + dw_hdmi_phy_sel_data_en_pol(hdmi, 1); + dw_hdmi_phy_sel_interface_control(hdmi, 0); + dw_hdmi_phy_enable_tmds(hdmi, 0); + dw_hdmi_phy_enable_power(hdmi, 0); /* Enable CSC */ ret = hdmi_phy_configure(hdmi, 0, 8, cscon); @@ -933,7 +940,7 @@ static int imx_hdmi_phy_init(struct imx_hdmi *hdmi) return 0; } -static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi) +static void hdmi_tx_hdcp_config(struct dw_hdmi *hdmi) { u8 de; @@ -952,19 +959,99 @@ static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi) HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1); } -static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi) +static void hdmi_av_composer(struct dw_hdmi *hdmi) +{ + u8 inv_val; + struct hdmi_vmode *vmode = &hdmi->hdmi_data.video_mode; + int hblank, vblank; + struct fb_videomode *mode = hdmi->mode; + + vmode->mhsyncpolarity = !!(mode->sync & FB_SYNC_HOR_HIGH_ACT); + vmode->mvsyncpolarity = !!(mode->sync & FB_SYNC_VERT_HIGH_ACT); + vmode->minterlaced = !!(mode->vmode & FB_VMODE_INTERLACED); + vmode->mpixelclock = PICOS2KHZ(mode->pixclock) * 1000; + + dev_dbg(hdmi->dev, "final pixclk = %d\n", vmode->mpixelclock); + + /* Set up HDMI_FC_INVIDCONF */ + inv_val = (hdmi->hdmi_data.hdcp_enable ? + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE : + HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE); + + inv_val |= (vmode->mvsyncpolarity ? + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW); + + inv_val |= (vmode->mhsyncpolarity ? + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW); + + inv_val |= (vmode->mdataenablepolarity ? + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW); + + if (hdmi->vic == 39) + inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH; + else + inv_val |= (vmode->minterlaced ? + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH : + HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW); + + inv_val |= (vmode->minterlaced ? + HDMI_FC_INVIDCONF_IN_I_P_INTERLACED : + HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE); + + inv_val |= (vmode->mdvi ? + HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE : + HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE); + + hdmi_writeb(hdmi, inv_val, HDMI_FC_INVIDCONF); + + /* Set up horizontal active pixel width */ + hdmi_writeb(hdmi, mode->xres >> 8, HDMI_FC_INHACTV1); + hdmi_writeb(hdmi, mode->xres, HDMI_FC_INHACTV0); + + /* Set up vertical active lines */ + hdmi_writeb(hdmi, mode->yres >> 8, HDMI_FC_INVACTV1); + hdmi_writeb(hdmi, mode->yres, HDMI_FC_INVACTV0); + + /* Set up horizontal blanking pixel region width */ + hblank = mode->left_margin + mode->right_margin + mode->hsync_len; + hdmi_writeb(hdmi, hblank >> 8, HDMI_FC_INHBLANK1); + hdmi_writeb(hdmi, hblank, HDMI_FC_INHBLANK0); + + /* Set up vertical blanking pixel region width */ + vblank = mode->upper_margin + mode->lower_margin + mode->vsync_len; + hdmi_writeb(hdmi, vblank, HDMI_FC_INVBLANK); + + /* Set up HSYNC active edge delay width (in pixel clks) */ + hdmi_writeb(hdmi, mode->right_margin >> 8, HDMI_FC_HSYNCINDELAY1); + hdmi_writeb(hdmi, mode->right_margin, HDMI_FC_HSYNCINDELAY0); + + /* Set up VSYNC active edge delay (in lines) */ + hdmi_writeb(hdmi, mode->lower_margin, HDMI_FC_VSYNCINDELAY); + + /* Set up HSYNC active pulse width (in pixel clks) */ + hdmi_writeb(hdmi, mode->hsync_len >> 8, HDMI_FC_HSYNCINWIDTH1); + hdmi_writeb(hdmi, mode->hsync_len, HDMI_FC_HSYNCINWIDTH0); + + /* Set up VSYNC active edge delay (in lines) */ + hdmi_writeb(hdmi, mode->vsync_len, HDMI_FC_VSYNCINWIDTH); +} + +static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi) { if (!hdmi->phy_enabled) return; - imx_hdmi_phy_enable_tmds(hdmi, 0); - imx_hdmi_phy_enable_power(hdmi, 0); + dw_hdmi_phy_enable_tmds(hdmi, 0); + dw_hdmi_phy_enable_power(hdmi, 0); hdmi->phy_enabled = false; } /* HDMI Initialization Step B.4 */ -static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi) +static void dw_hdmi_enable_video_path(struct dw_hdmi *hdmi) { u8 clkdis; @@ -994,7 +1081,7 @@ static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi) } /* Workaround to clear the overflow condition */ -static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi) +static void dw_hdmi_clear_overflow(struct dw_hdmi *hdmi) { int count; u8 val; @@ -1012,12 +1099,10 @@ static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi) hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF); } -static int imx_hdmi_setup(struct imx_hdmi *hdmi) +static int dw_hdmi_setup(struct dw_hdmi *hdmi) { int ret; - hdmi->vic = 0; - dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n"); hdmi->hdmi_data.video_mode.mdvi = true; @@ -1035,28 +1120,28 @@ static int imx_hdmi_setup(struct imx_hdmi *hdmi) hdmi->hdmi_data.hdcp_enable = 0; hdmi->hdmi_data.video_mode.mdataenablepolarity = true; + /* HDMI Initialization Step B.1 */ + hdmi_av_composer(hdmi); + /* HDMI Initializateion Step B.2 */ - ret = imx_hdmi_phy_init(hdmi); + ret = dw_hdmi_phy_init(hdmi); if (ret) return ret; /* HDMI Initialization Step B.3 */ - imx_hdmi_enable_video_path(hdmi); - - /* not for DVI mode */ - dev_dbg(hdmi->dev, "%s DVI mode\n", __func__); + dw_hdmi_enable_video_path(hdmi); hdmi_video_packetize(hdmi); hdmi_video_csc(hdmi); hdmi_video_sample(hdmi); hdmi_tx_hdcp_config(hdmi); - imx_hdmi_clear_overflow(hdmi); + dw_hdmi_clear_overflow(hdmi); return 0; } -static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi) +static void initialize_hdmi_ih_mutes(struct dw_hdmi *hdmi) { u8 ih_mute; @@ -1108,22 +1193,22 @@ static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi) hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE); } -struct imx_hdmi_data { +struct dw_hdmi_data { unsigned ipu_mask; - enum imx_hdmi_devtype devtype; + enum dw_hdmi_devtype devtype; }; -static struct imx_hdmi_data imx6q_hdmi_data = { +static struct dw_hdmi_data imx6q_hdmi_data = { .ipu_mask = 0xf, .devtype = IMX6Q_HDMI, }; -static struct imx_hdmi_data imx6dl_hdmi_data = { +static struct dw_hdmi_data imx6dl_hdmi_data = { .ipu_mask = 0x3, .devtype = IMX6DL_HDMI, }; -static struct of_device_id imx_hdmi_dt_ids[] = { +static struct of_device_id dw_hdmi_dt_ids[] = { { .compatible = "fsl,imx6q-hdmi", .data = &imx6q_hdmi_data, @@ -1135,7 +1220,7 @@ static struct of_device_id imx_hdmi_dt_ids[] = { } }; -static int imx_hdmi_get_modes(struct imx_hdmi *hdmi, struct display_timings *timings) +static int dw_hdmi_get_modes(struct dw_hdmi *hdmi, struct display_timings *timings) { int ret = -ENOENT; @@ -1155,23 +1240,24 @@ static int imx_hdmi_get_modes(struct imx_hdmi *hdmi, struct display_timings *tim return ret; } -static int imx_hdmi_ioctl(struct vpl *vpl, unsigned int port, +static int dw_hdmi_ioctl(struct vpl *vpl, unsigned int port, unsigned int cmd, void *data) { - struct imx_hdmi *hdmi = container_of(vpl, struct imx_hdmi, vpl); + struct dw_hdmi *hdmi = container_of(vpl, struct dw_hdmi, vpl); struct ipu_di_mode *mode; switch (cmd) { case VPL_ENABLE: - return imx_hdmi_setup(hdmi); + return dw_hdmi_setup(hdmi); case VPL_DISABLE: - imx_hdmi_phy_disable(hdmi); + dw_hdmi_phy_disable(hdmi); return 0; case VPL_PREPARE: - imx_hdmi_set_ipu_di_mux(hdmi, port); + hdmi->mode = data; + dw_hdmi_set_ipu_di_mux(hdmi, port); return 0; case VPL_GET_VIDEOMODES: - return imx_hdmi_get_modes(hdmi, data); + return dw_hdmi_get_modes(hdmi, data); case IMX_IPU_VPL_DI_MODE: mode = data; @@ -1184,12 +1270,12 @@ static int imx_hdmi_ioctl(struct vpl *vpl, unsigned int port, return 0; } -static int imx_hdmi_probe(struct device_d *dev) +static int dw_hdmi_probe(struct device_d *dev) { struct device_node *np = dev->device_node; - struct imx_hdmi *hdmi; + struct dw_hdmi *hdmi; int ret; - const struct imx_hdmi_data *devtype; + const struct dw_hdmi_data *devtype; ret = dev_get_drvdata(dev, (const void **)&devtype); if (ret) @@ -1275,7 +1361,7 @@ static int imx_hdmi_probe(struct device_d *dev) hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0); hdmi->vpl.node = np; - hdmi->vpl.ioctl = imx_hdmi_ioctl; + hdmi->vpl.ioctl = dw_hdmi_ioctl; ret = vpl_register(&hdmi->vpl); if (ret) return ret; @@ -1288,12 +1374,12 @@ err_isfr: return ret; } -static struct driver_d imx_hdmi_driver = { - .probe = imx_hdmi_probe, - .of_compatible = imx_hdmi_dt_ids, +static struct driver_d dw_hdmi_driver = { + .probe = dw_hdmi_probe, + .of_compatible = dw_hdmi_dt_ids, .name = "imx-hdmi", }; -device_platform_driver(imx_hdmi_driver); +device_platform_driver(dw_hdmi_driver); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver"); diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.h b/drivers/video/imx-ipu-v3/imx-hdmi.h index 39b677689d..b3e144227f 100644 --- a/drivers/video/imx-ipu-v3/imx-hdmi.h +++ b/drivers/video/imx-ipu-v3/imx-hdmi.h @@ -837,7 +837,8 @@ enum { HDMI_PHY_CONF0_PDZ_OFFSET = 7, HDMI_PHY_CONF0_ENTMDS_MASK = 0x40, HDMI_PHY_CONF0_ENTMDS_OFFSET = 6, - HDMI_PHY_CONF0_SPARECTRL = 0x20, + HDMI_PHY_CONF0_SPARECTRL_MASK = 0x20, + HDMI_PHY_CONF0_SPARECTRL_OFFSET = 5, HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10, HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4, HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8, diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c index e804c31b29..ea2e83b7f0 100644 --- a/drivers/video/imx-ipu-v3/ipufb.c +++ b/drivers/video/imx-ipu-v3/ipufb.c @@ -75,6 +75,31 @@ static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) return chan << bf->offset; } +static int ipu_crtc_adjust_videomode(struct ipufb_info *fbi, struct fb_videomode *mode) +{ + u32 diff; + + if (mode->lower_margin >= 2) + return 0; + + diff = 2 - mode->lower_margin; + + if (mode->upper_margin >= diff) { + mode->upper_margin -= diff; + } else if (mode->vsync_len > diff) { + mode->vsync_len = mode->vsync_len - diff; + } else { + dev_warn(fbi->dev, "failed to adjust videomode\n"); + return -EINVAL; + } + + mode->lower_margin = 2; + + dev_warn(fbi->dev, "videomode adapted for IPU restrictions\n"); + + return 0; +} + int ipu_crtc_mode_set(struct ipufb_info *fbi, struct fb_videomode *mode, int x, int y) @@ -109,6 +134,11 @@ int ipu_crtc_mode_set(struct ipufb_info *fbi, sig_cfg.v_start_width = mode->upper_margin; sig_cfg.v_sync_width = mode->vsync_len; + + ret = ipu_crtc_adjust_videomode(fbi, mode); + if (ret) + return ret; + sig_cfg.v_end_width = mode->lower_margin; sig_cfg.pixelclock = PICOS2KHZ(mode->pixclock) * 1000UL; sig_cfg.clkflags = di_mode.di_clkflags; @@ -184,7 +214,7 @@ static int ipufb_activate_var(struct fb_info *info) struct ipufb_info *fbi = container_of(info, struct ipufb_info, info); info->line_length = info->xres * (info->bits_per_pixel >> 3); - fbi->info.screen_base = dma_alloc_coherent(info->line_length * info->yres, + fbi->info.screen_base = dma_alloc_writecombine(info->line_length * info->yres, DMA_ADDRESS_BROKEN); if (!fbi->info.screen_base) return -ENOMEM; diff --git a/drivers/video/simple-panel.c b/drivers/video/simple-panel.c index dceedc60c3..3dd760b385 100644 --- a/drivers/video/simple-panel.c +++ b/drivers/video/simple-panel.c @@ -82,7 +82,8 @@ static int simple_panel_get_modes(struct simple_panel *panel, struct display_tim { int ret = -ENOENT; - if (panel->ddc_node) { + if (panel->ddc_node && IS_ENABLED(CONFIG_DRIVER_VIDEO_EDID) && + IS_ENABLED(CONFIG_I2C)) { struct i2c_adapter *i2c; i2c = of_find_i2c_adapter_by_node(panel->ddc_node); diff --git a/fs/devfs-core.c b/fs/devfs-core.c index f45f8cadf1..62571fb8a3 100644 --- a/fs/devfs-core.c +++ b/fs/devfs-core.c @@ -57,6 +57,19 @@ struct cdev *cdev_by_name(const char *filename) return NULL; } +struct cdev *cdev_by_device_node(struct device_node *node) +{ + struct cdev *cdev; + + list_for_each_entry(cdev, &cdev_list, list) { + if (!cdev->device_node) + continue; + if (cdev->device_node == node) + return cdev; + } + return NULL; +} + /** * device_find_partition - find a partition belonging to a physical device * diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h deleted file mode 100644 index 767497096a..0000000000 --- a/include/asm-generic/gpio.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ASM_GENERIC_GPIO_H -#define __ASM_GENERIC_GPIO_H - -void gpio_set_value(unsigned gpio, int value); -int gpio_get_value(unsigned gpio); -int gpio_direction_output(unsigned gpio, int value); -int gpio_direction_input(unsigned gpio); - -#endif /* __ASM_GENERIC_GPIO_H */ diff --git a/include/console.h b/include/console.h index a6737c8581..4b2f134a4c 100644 --- a/include/console.h +++ b/include/console.h @@ -71,9 +71,6 @@ 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); diff --git a/include/dma.h b/include/dma.h index 800d8b155f..4d31797968 100644 --- a/include/dma.h +++ b/include/dma.h @@ -39,5 +39,6 @@ void dma_sync_single_for_device(unsigned long address, size_t size, void *dma_alloc_coherent(size_t size, dma_addr_t *dma_handle); void dma_free_coherent(void *mem, dma_addr_t dma_handle, size_t size); +void *dma_alloc_writecombine(size_t size, dma_addr_t *dma_handle); #endif /* __DMA_H */ diff --git a/include/driver.h b/include/driver.h index 728f8abb49..046dd9079d 100644 --- a/include/driver.h +++ b/include/driver.h @@ -436,6 +436,7 @@ struct cdev { struct file_operations *ops; void *priv; struct device_d *dev; + struct device_node *device_node; struct list_head list; struct list_head devices_list; char *name; /* filename under /dev/ */ @@ -456,6 +457,7 @@ int devfs_remove(struct cdev *); int cdev_find_free_index(const char *); struct cdev *device_find_partition(struct device_d *dev, const char *name); struct cdev *cdev_by_name(const char *filename); +struct cdev *cdev_by_device_node(struct device_node *node); struct cdev *cdev_open(const char *name, unsigned long flags); int cdev_do_open(struct cdev *, unsigned long flags); void cdev_close(struct cdev *cdev); diff --git a/include/fb.h b/include/fb.h index 311d5db192..cf113c4300 100644 --- a/include/fb.h +++ b/include/fb.h @@ -118,6 +118,7 @@ struct fb_info { struct device_d dev; /* This is this fb device */ void *screen_base; + void *screen_base_shadow; unsigned long screen_size; void *priv; @@ -141,6 +142,7 @@ struct fb_info { int register_simplefb; /* If true a simplefb device node will * be created. */ + int shadowfb; }; struct display_timings *of_get_display_timings(struct device_node *np); @@ -167,5 +169,6 @@ void fb_edid_add_modes(struct fb_info *info); void fb_of_reserve_add_fixup(struct fb_info *info); int register_fbconsole(struct fb_info *fb); +void *fb_get_screen_base(struct fb_info *info); #endif /* __FB_H */ diff --git a/include/gpio.h b/include/gpio.h index f116ea6af7..7b3f512b19 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -1,7 +1,28 @@ #ifndef __GPIO_H #define __GPIO_H -#include <asm/gpio.h> +#ifdef CONFIG_GENERIC_GPIO +void gpio_set_value(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); +int gpio_direction_input(unsigned gpio); +#else +static inline void gpio_set_value(unsigned gpio, int value) +{ +} +static inline int gpio_get_value(unsigned gpio) +{ + return 0; +} +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return -EINVAL; +} +static inline int gpio_direction_input(unsigned gpio) +{ + return -EINVAL; +} +#endif #define ARCH_NR_GPIOS 256 diff --git a/include/gui/graphic_utils.h b/include/gui/graphic_utils.h index ab8c3fcff3..231b3a9414 100644 --- a/include/gui/graphic_utils.h +++ b/include/gui/graphic_utils.h @@ -19,11 +19,13 @@ void gu_set_pixel(struct fb_info *info, void *adr, u32 px); void gu_set_rgb_pixel(struct fb_info *info, void *adr, u8 r, u8 g, u8 b); void gu_set_rgba_pixel(struct fb_info *info, void *adr, u8 r, u8 g, u8 b, u8 a); void gu_memset_pixel(struct fb_info *info, void* buf, u32 color, size_t size); -struct screen *fb_create_screen(struct fb_info *info, bool offscreen); -struct screen *fb_open(const char *fbdev, bool offscreen); +struct screen *fb_create_screen(struct fb_info *info); +struct screen *fb_open(const char *fbdev); void fb_close(struct screen *sc); void gu_screen_blit(struct screen *sc); void gu_invert_area(struct fb_info *info, void *buf, int startx, int starty, int width, int height); +void gu_screen_blit_area(struct screen *sc, int startx, int starty, int width, + int height); #endif /* __GRAPHIC_UTILS_H__ */ diff --git a/include/gui/gui.h b/include/gui/gui.h index 03e60aa0de..133149beef 100644 --- a/include/gui/gui.h +++ b/include/gui/gui.h @@ -23,16 +23,12 @@ struct screen { struct surface s; void *fb; - void *offscreenbuf; int fbsize; }; static inline void *gui_screen_render_buffer(struct screen *sc) { - if (sc->offscreenbuf) - return sc->offscreenbuf; - return sc->fb; + return fb_get_screen_base(sc->info); } - #endif /* __GUI_H__ */ diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h index 4696f43e31..12e4827755 100644 --- a/include/i2c/i2c.h +++ b/include/i2c/i2c.h @@ -19,6 +19,8 @@ #include <driver.h> #include <linux/types.h> +struct i2c_adapter; + /* * struct i2c_platform_data - structure of platform data for MXC I2C driver * @param bitrate Bus speed measured in Hz @@ -61,6 +63,47 @@ struct i2c_msg { __u16 len; /**< Number of data bytes in @buf being read from or written to the I2C slave address. */ }; +/** + * struct i2c_bus_recovery_info - I2C bus recovery information + * @recover_bus: Recover routine. Either pass driver's recover_bus() routine, or + * i2c_generic_scl_recovery() or i2c_generic_gpio_recovery(). + * @get_scl: This gets current value of SCL line. Mandatory for generic SCL + * recovery. Used internally for generic GPIO recovery. + * @set_scl: This sets/clears SCL line. Mandatory for generic SCL recovery. Used + * internally for generic GPIO recovery. + * @get_sda: This gets current value of SDA line. Optional for generic SCL + * recovery. Used internally, if sda_gpio is a valid GPIO, for generic GPIO + * recovery. + * @prepare_recovery: This will be called before starting recovery. Platform may + * configure padmux here for SDA/SCL line or something else they want. + * @unprepare_recovery: This will be called after completing recovery. Platform + * may configure padmux here for SDA/SCL line or something else they want. + * @scl_gpio: gpio number of the SCL line. Only required for GPIO recovery. + * @sda_gpio: gpio number of the SDA line. Only required for GPIO recovery. + */ +struct i2c_bus_recovery_info { + int (*recover_bus)(struct i2c_adapter *); + + int (*get_scl)(struct i2c_adapter *); + void (*set_scl)(struct i2c_adapter *, int val); + int (*get_sda)(struct i2c_adapter *); + + void (*prepare_recovery)(struct i2c_adapter *); + void (*unprepare_recovery)(struct i2c_adapter *); + + /* gpio recovery */ + int scl_gpio; + int sda_gpio; +}; + +int i2c_recover_bus(struct i2c_adapter *adap); + +/* Generic recovery routines */ +int i2c_get_scl_gpio_value(struct i2c_adapter *adap); +void i2c_set_scl_gpio_value(struct i2c_adapter *adap, int val); +int i2c_get_sda_gpio_value(struct i2c_adapter *adap); +int i2c_generic_gpio_recovery(struct i2c_adapter *adap); +int i2c_generic_scl_recovery(struct i2c_adapter *adap); /** * i2c_adapter is the structure used to identify a physical i2c bus @@ -74,6 +117,8 @@ struct i2c_adapter { struct list_head list; int retries; void *algo_data; + + struct i2c_bus_recovery_info *bus_recovery_info; }; diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index f099406c53..bd2b16dd2a 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -190,6 +190,7 @@ struct spi_nor { * @nor: the spi_nor structure * @name: the chip type name * @mode: the read mode supported by the driver + * @use_large_blocks: prefer large blocks even if 4k blocks are supported * * The drivers can use this fuction to scan the SPI NOR. * In the scanning, it will try to get all the necessary information to @@ -199,6 +200,7 @@ struct spi_nor { * * Return: 0 for success, others for failure. */ -int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode); +int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode, + bool use_large_blocks); #endif diff --git a/include/password.h b/include/password.h index 0dd1054054..8b9961815f 100644 --- a/include/password.h +++ b/include/password.h @@ -26,25 +26,15 @@ #define CLEAR (1 << 2) int password(unsigned char *passwd, size_t length, int flags, int timeout); - -int read_passwd(unsigned char *sum, size_t length); -int check_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); +int set_env_passwd(unsigned char *passwd, size_t length); -static inline int is_passwd_enable(void) +#ifdef CONFIG_PASSWORD +void login(void); +#else +static inline void login(void) { - return is_passwd_default_enable() || is_passwd_env_enable(); } +#endif #endif /* __PASSWORD_H__ */ diff --git a/include/spi/imx-spi.h b/include/spi/imx-spi.h index 560b092bd2..221c66502f 100644 --- a/include/spi/imx-spi.h +++ b/include/spi/imx-spi.h @@ -61,6 +61,7 @@ #define CSPI_2_3_CTRL 0x08 #define CSPI_2_3_CTRL_ENABLE (1 << 0) #define CSPI_2_3_CTRL_XCH (1 << 2) +#define CSPI_2_3_CTRL_SMC (1 << 3) #define CSPI_2_3_CTRL_MODE(cs) (1 << ((cs) + 4)) #define CSPI_2_3_CTRL_POSTDIV_OFFSET 8 #define CSPI_2_3_CTRL_PREDIV_OFFSET 12 @@ -78,6 +79,7 @@ #define CSPI_2_3_INT_RREN (1 << 3) #define CSPI_2_3_STAT 0x18 -#define CSPI_2_3_STAT_RR (1 << 3) +#define CSPI_2_3_STAT_TF (1 << 2) +#define CSPI_2_3_STAT_RR (1 << 3) #endif /* __SPI_IMX_SPI_H */ diff --git a/include/video/backlight.h b/include/video/backlight.h index 56e0341ea4..8dc49dc113 100644 --- a/include/video/backlight.h +++ b/include/video/backlight.h @@ -1,6 +1,7 @@ #ifndef __VIDEO_BACKLIGHT_H #define __VIDEO_BACKLIGHT_H +#ifdef CONFIG_DRIVER_VIDEO_BACKLIGHT struct backlight_device { int brightness; int brightness_cur; @@ -16,5 +17,21 @@ int backlight_set_brightness(struct backlight_device *, int brightness); int backlight_set_brightness_default(struct backlight_device *); int backlight_register(struct backlight_device *); struct backlight_device *of_backlight_find(struct device_node *node); +#else +struct backlight_device ; + +static inline int +backlight_set_brightness(struct backlight_device *dev, int brightness) +{ + return 0; +} +static inline int +backlight_set_brightness_default(struct backlight_device *dev) +{ + return 0; +} +static inline struct backlight_device * +of_backlight_find(struct device_node *node) { return NULL; } +#endif #endif /* __VIDEO_BACKLIGHT_H */ diff --git a/include/watchdog.h b/include/watchdog.h index fd24b5b79e..6fd896734b 100644 --- a/include/watchdog.h +++ b/include/watchdog.h @@ -31,12 +31,12 @@ static inline int watchdog_register(struct watchdog *w) return 0; } -int watchdog_deregister(struct watchdog *w) +static inline int watchdog_deregister(struct watchdog *w) { return 0; } -int watchdog_set_timeout(unsigned t) +static inline int watchdog_set_timeout(unsigned t) { return 0; } diff --git a/lib/gui/graphic_utils.c b/lib/gui/graphic_utils.c index 47003a0837..4c1885d55b 100644 --- a/lib/gui/graphic_utils.c +++ b/lib/gui/graphic_utils.c @@ -245,7 +245,7 @@ void gu_rgba_blend(struct fb_info *info, struct image *img, void* buf, int heigh } } -struct screen *fb_create_screen(struct fb_info *info, bool offscreen) +struct screen *fb_create_screen(struct fb_info *info) { struct screen *sc; @@ -257,19 +257,12 @@ struct screen *fb_create_screen(struct fb_info *info, bool offscreen) sc->s.height = info->yres; sc->fbsize = info->line_length * sc->s.height; sc->fb = info->screen_base; - - if (offscreen) { - /* - * Don't fail if malloc fails, just continue rendering directly - * on the framebuffer - */ - sc->offscreenbuf = malloc(sc->fbsize); - } + sc->info = info; return sc; } -struct screen *fb_open(const char * fbdev, bool offscreen) +struct screen *fb_open(const char * fbdev) { int fd, ret; struct fb_info *info; @@ -281,12 +274,12 @@ struct screen *fb_open(const char * fbdev, bool offscreen) info = xzalloc(sizeof(*info)); - ret = ioctl(fd, FBIOGET_SCREENINFO, info); + ret = ioctl(fd, FBIOGET_SCREENINFO, &info); if (ret) { goto failed_screeninfo; } - sc = fb_create_screen(info, offscreen); + sc = fb_create_screen(info); if (IS_ERR(sc)) { ret = PTR_ERR(sc); goto failed_create; @@ -298,7 +291,6 @@ struct screen *fb_open(const char * fbdev, bool offscreen) return sc; failed_create: - free(sc->offscreenbuf); free(sc); failed_screeninfo: close(fd); @@ -308,20 +300,35 @@ failed_screeninfo: void fb_close(struct screen *sc) { - free(sc->offscreenbuf); - - if (sc->fd > 0) { + if (sc->fd > 0) close(sc->fd); - free(sc->info); - } free(sc); } +void gu_screen_blit_area(struct screen *sc, int startx, int starty, int width, + int height) +{ + struct fb_info *info = sc->info; + int bpp = info->bits_per_pixel >> 3; + + if (info->screen_base_shadow) { + int y; + void *fb = info->screen_base + starty * sc->info->line_length + startx * bpp; + void *fboff = info->screen_base_shadow + starty * sc->info->line_length + startx * bpp; + + for (y = starty; y < starty + height; y++) { + memcpy(fb, fboff, width * bpp); + fb += sc->info->line_length; + fboff += sc->info->line_length; + } + } +} + void gu_screen_blit(struct screen *sc) { - if (!sc->offscreenbuf) - return; + struct fb_info *info = sc->info; - memcpy(sc->fb, sc->offscreenbuf, sc->fbsize); + if (info->screen_base_shadow) + memcpy(info->screen_base, info->screen_base_shadow, sc->fbsize); } diff --git a/lib/libfile.c b/lib/libfile.c index ba03700aba..a27460c10d 100644 --- a/lib/libfile.c +++ b/lib/libfile.c @@ -262,7 +262,7 @@ int copy_file(const char *src, const char *dst, int verbose) char *rw_buf = NULL; int srcfd = 0, dstfd = 0; int r, w; - int ret = 1; + int ret = 1, err1 = 0; void *buf; int total = 0; struct stat statbuf; @@ -326,9 +326,9 @@ out: if (srcfd > 0) close(srcfd); if (dstfd > 0) - close(dstfd); + err1 = close(dstfd); - return ret; + return ret ?: err1; } EXPORT_SYMBOL(copy_file); |