From: Lothar Waßmann Date: Wed, 15 Mar 2017 08:10:30 +0000 (+0100) Subject: arm64: add support for Ka-Ro TXSD-410E X-Git-Tag: KARO-TXSD-2017-03-15 X-Git-Url: https://git.kernelconcepts.de/?p=karo-tx-uboot.git;a=commitdiff_plain;h=30f98c375bbaec314c2ff41dd83e67bff0a4ec4e arm64: add support for Ka-Ro TXSD-410E The TXSD-410E is a SoM compatible to the Qualcomm Dragonboard410c but in a form factor compatible with the TX module family manufactured by Ka-Ro electronics GmbH. --- diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 032c5aebc1..8e6b064bfe 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -152,7 +152,8 @@ dtb-$(CONFIG_FSL_LSCH2) += fsl-ls1043a-qds-duart.dtb \ fsl-ls1012a-rdb.dtb \ fsl-ls1012a-frdm.dtb -dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb +dtb-$(CONFIG_ARCH_SNAPDRAGON) += dragonboard410c.dtb \ + txsd-410e.dtb dtb-$(CONFIG_MACH_SUN4I) += \ sun4i-a10-a1000.dtb \ diff --git a/arch/arm/dts/txsd-410e.dts b/arch/arm/dts/txsd-410e.dts new file mode 100644 index 0000000000..a3738825de --- /dev/null +++ b/arch/arm/dts/txsd-410e.dts @@ -0,0 +1,255 @@ +/* + * Qualcomm APQ8016 based Ka-Ro TXSD-410E board device tree source + * + * (C) Copyright 2016 Lothar Waßmann + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; + +#include "skeleton64.dtsi" +#include +#include + +/ { + model = "Ka-Ro electronics GmbH TXSD-410E"; + compatible = "qcom,dragonboard", "qcom,apq8016-sbc"; + qcom,msm-id = <0xce 0x0 0xf8 0x0 0xf9 0x0 0xfa 0x0 0xf7 0x0>; + qcom,board-id = <0x10018 0x0>; + #address-cells = <0x2>; + #size-cells = <0x2>; + + aliases { + serial0 = &uart1; + soc_gpios = &soc_gpios; + i2c0 = &i2c_gpio1; + i2c1 = &i2c_gpio2; + i2c2 = &i2c_gpio3; + }; + + memory { + device_type = "memory"; + reg = <0 0x90000000 0 0x2da00000>; + }; + + chosen { + stdout-path = "serial0"; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + soc { + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges = <0x0 0x0 0x0 0xffffffff>; + compatible = "simple-bus"; + + clkc: qcom,gcc@1800000 { + compatible = "qcom,gcc-apq8016"; + reg = <0x1800000 0x80000>; + #address-cells = <0x1>; + #size-cells = <0x0>; + }; + + uart1: serial@78b0000 { + compatible = "qcom,msm-uartdm-v1.4"; + reg = <0x78b0000 0x200>; + u-boot,dm-pre-reloc; + clock = <&clkc 4>; + }; + + restart@4ab000 { + compatible = "qcom,pshold"; + reg = <0x4ab000 0x4>; + }; + + soc_gpios: pinctrl@1000000 { + compatible = "qcom,apq8016-pinctrl"; + reg = <0x1000000 0x300000>; + gpio-controller; + gpio-count = <122>; + gpio-bank-name = "soc"; + #gpio-cells = <2>; + }; + + ehci@78d9000 { + compatible = "qcom,ehci-host"; + reg = <0x78d9000 0x400>; + }; + + sdhci@07824000 { + compatible = "qcom,sdhci-msm-v4"; + reg = <0x7824900 0x11c 0x7824000 0x800>; + bus-width = <0x8>; + index = <0x0>; + non-removable; + clock = <&clkc 0>; + clock-frequency = <100000000>; + }; + + sdhci@07864000 { + compatible = "qcom,sdhci-msm-v4"; + reg = <0x7864900 0x11c 0x7864000 0x800>; + index = <0x1>; + bus-width = <0x4>; + clock = <&clkc 1>; + clock-frequency = <200000000>; + }; + + spmi@200f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x200f000 0x1000 + 0x2400000 0x400000 + 0x2c00000 0x400000 + >; + #address-cells = <0x1>; + #size-cells = <0x1>; + + pmic0: pm8916@0 { + compatible = "qcom,spmi-pmic"; + reg = <0x0 0x1>; + #address-cells = <0x1>; + #size-cells = <0x1>; + + rtc@6000 { + compatible = "qcom,pm8941-rtc"; + reg = <0x6000 0x4c>, <0x6100 0x49>; + reg-names = "rtc", "alarm"; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>; + }; + + pm8916_gpios: pm8916_gpios@c000 { + compatible = "qcom,pm8916-gpio"; + reg = <0xc000 0x400>; + gpio-controller; + gpio-count = <4>; + #gpio-cells = <2>; + gpio-bank-name = "pmic"; + }; + }; + + pmic1: pm8916@1 { + compatible = "qcom,spmi-pmic"; + reg = <0x1 0x1>; + }; + }; + }; + + i2c_gpio1: i2c-gpio@0 { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pinmux>; + gpios = <&soc_gpios 18 GPIO_ACTIVE_HIGH>, /* SDA */ + <&soc_gpios 19 GPIO_ACTIVE_HIGH>; /* CLK */ + + tsc2007@48 { + compatible = "ti,tsc2007"; + reg = <0x48>; + }; + }; + + i2c_gpio2: i2c-gpio@1 { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pinmux>; + gpios = <&soc_gpios 53 GPIO_ACTIVE_HIGH>, /* SDA */ + <&soc_gpios 54 GPIO_ACTIVE_HIGH>; /* CLK */ + + dsi83@2c { + compatible = "ti,sn65dsi83"; + reg = <0x2c>; + }; + }; + + i2c_gpio3: i2c-gpio@2 { + compatible = "i2c-gpio"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pinmux>; + gpios = <&soc_gpios 29 GPIO_ACTIVE_HIGH>, /* SDA */ + <&soc_gpios 30 GPIO_ACTIVE_HIGH>; /* CLK */ + }; + + leds { + compatible = "gpio-leds"; + + user { + label = "user"; + gpios = <&soc_gpios 71 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&soc_gpios { + i2c0_pinmux: i2c0-pins { + pinmux { + function = "gpio"; + pins = "gpio18", "gpio19"; + }; + + pinconf { + pins = "gpio18", "gpio19"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + i2c1_pinmux: i2c1-pins { + pinmux { + function = "gpio"; + pins = "gpio53", "gpio54"; + }; + + pinconf { + pins = "gpio53", "gpio54"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + i2c2_pinmux: i2c2-pins { + pinmux { + function = "gpio"; + pins = "gpio29", "gpio30"; + }; + + pinconf { + pins = "gpio29", "gpio30"; + drive-strength = <16>; + bias-pull-up; + }; + }; + + led_pinmux: led-pins { + pinmux { + function = "gpio"; + pins = "gpio71"; + }; + + pinconf { + pins = "gpio71"; + drive-strength = <16>; + }; +}; + + usb_vbus_pinmux: usb-vbus { + pinmux { + function = "gpio"; + pins = "gpio56"; + }; + + pinconf { + pins = "gpio56"; + drive-strength = <16>; + }; + }; +}; diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index dc7ba21c18..e2affb41bf 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -19,8 +19,17 @@ config TARGET_DRAGONBOARD410C - HDMI - 20-pin low speed and 40-pin high speed expanders, 4 LED, 3 buttons +config TARGET_TXSD_410E + bool "Ka-Ro electronics TXSD-410E" + help + Support for Ka-Ro electronics TXSD-410E module. This board + is compatible with the Qualcomm Snapdragon 410C board and + has a form factor like the TX-Series modules produced by + Ka-Ro electronics GmbH. + endchoice source "board/qualcomm/dragonboard410c/Kconfig" +source "board/karo/txsd/Kconfig" endif diff --git a/board/karo/common/Makefile b/board/karo/common/Makefile new file mode 100644 index 0000000000..d8869d277f --- /dev/null +++ b/board/karo/common/Makefile @@ -0,0 +1,14 @@ +# +# (C) Copyright 2012-2015 Lothar Waßmann +# +# SPDX-License-Identifier: GPL-2.0+ +# + +ifeq ($(CONFIG_SPL_BUILD),) + obj-$(CONFIG_OF_LIBFDT) += fdt.o + obj-$(CONFIG_SPLASH_SCREEN) += splashimage.o +endif +obj-$(CONFIG_CMD_NAND) += nand.o +obj-$(CONFIG_ENV_IS_IN_MMC) += mmc.o +obj-$(CONFIG_LCD) += lcd.o +obj-y += env.o diff --git a/board/karo/common/env.c b/board/karo/common/env.c new file mode 100644 index 0000000000..2b347cde3e --- /dev/null +++ b/board/karo/common/env.c @@ -0,0 +1,50 @@ +/* + * (C) Copyright 2014 Lothar Waßmann + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include + +#include "karo.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_UBOOT_IGNORE_ENV +void env_cleanup(void) +{ + set_default_env(NULL); +} +#else +static const char const *cleanup_vars[] = { + "bootargs", + "fileaddr", + "filesize", + "safeboot", + "wdreset", +}; + +void env_cleanup(void) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(cleanup_vars); i++) { + setenv(cleanup_vars[i], NULL); + } +} +#endif diff --git a/board/karo/common/fdt.c b/board/karo/common/fdt.c new file mode 100644 index 0000000000..d8ff1b8b08 --- /dev/null +++ b/board/karo/common/fdt.c @@ -0,0 +1,929 @@ +/* + * (C) Copyright 2012-2016 Lothar Waßmann + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * +*/ +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_VIDEO_IPUV3 +#include +#endif +#include +#include +#include +#include +#include + +#include "karo.h" + +#ifdef CONFIG_MAX_DTB_SIZE +#define MAX_DTB_SIZE CONFIG_MAX_DTB_SIZE +#else +#define MAX_DTB_SIZE SZ_64K +#endif + +DECLARE_GLOBAL_DATA_PTR; + +static void karo_set_fdtsize(void *fdt) +{ + size_t fdtsize = getenv_hex("fdtsize", 0); + + if (fdtsize == fdt_totalsize(fdt)) { + return; + } + debug("FDT size changed from %zu to %u\n", + fdtsize, fdt_totalsize(fdt)); + setenv_hex("fdtsize", fdt_totalsize(fdt)); +} + +static void *karo_fdt_load_dtb(void) +{ + int ret; + void *fdt; + + if (getenv("fdtaddr") == NULL) + setenv_hex("fdtaddr", CONFIG_SYS_FDT_ADDR); + fdt = (void *)getenv_ulong("fdtaddr", 16, CONFIG_SYS_FDT_ADDR); + + if (had_ctrlc()) { + printf("aborting DTB load\n"); + return NULL; + } + + ret = karo_load_part("dtb", fdt, MAX_DTB_SIZE); + if (ret) { + printf("Failed to load dtb from flash: %d\n", ret); + memset(fdt, 0, MAX_DTB_SIZE); + return NULL; + } + + if (fdt_check_header(fdt)) { + debug("No valid DTB in flash\n"); + return NULL; + } + debug("Using DTB from flash\n"); + karo_set_fdtsize(fdt); + return fdt; +} + +static inline void karo_create_default_dtb(void *fdt) +{ + int offs; + + fdt_create_empty_tree(fdt, 256); + offs = fdt_add_subnode(fdt, 0, "display"); + offs = fdt_add_subnode(fdt, offs, "display-timings"); + offs = fdt_add_subnode(fdt, 0, "aliases"); + fdt_setprop(fdt, offs, "display", "/display", strlen("/display")); +} + +void karo_fdt_move_fdt(void) +{ + void *fdt; + unsigned long fdt_addr = getenv_hex("fdtaddr", 0); + + if (working_fdt) { + debug("DTB already loaded\n"); + return; + } + + setenv("fdtsize", NULL); + + if (!fdt_addr) { + fdt_addr = CONFIG_SYS_FDT_ADDR; + printf("fdtaddr is not set; using default: %08lx\n", + fdt_addr); + } + + fdt = karo_fdt_load_dtb(); + if (fdt == NULL) { + fdt = (void *)gd->fdt_blob; + if (fdt == NULL) { +#ifdef CONFIG_OF_EMBED + printf("Compiled in FDT not found"); +#else + printf("No FDT found"); +#endif + printf("; creating empty DTB\n"); + fdt = (void *)fdt_addr; + karo_create_default_dtb(fdt); + } else { + printf("No DTB in flash; using default DTB\n"); + } + debug("Checking FDT header @ %p\n", fdt); + if (fdt_check_header(fdt)) { + printf("ERROR: No valid DTB found at %p\n", fdt); + return; + } + debug("Copying FDT from %p..%p to %08lx..%08lx\n", + fdt, fdt + fdt_totalsize(fdt) - 1, + fdt_addr, fdt_addr + fdt_totalsize(fdt) - 1); + memmove((void *)fdt_addr, fdt, fdt_totalsize(fdt)); + } + set_working_fdt_addr(fdt_addr); + karo_set_fdtsize(fdt); +} + +void karo_fdt_remove_node(void *blob, const char *node) +{ + int off = fdt_path_offset(blob, node); + int ret; + + debug("Removing node '%s' from DT\n", node); + + if (off < 0) { + printf("Could not find node '%s': %s\n", node, + fdt_strerror(off)); + } else { + ret = fdt_del_node(blob, off); + if (ret) + printf("Failed to remove node '%s': %s\n", + node, fdt_strerror(ret)); + } + karo_set_fdtsize(blob); +} + +void karo_fdt_enable_node(void *blob, const char *node, int enable) +{ + int off = fdt_path_offset(blob, node); + + debug("%sabling node '%s'\n", enable ? "En" : "Dis", node); + if (off < 0) { + printf("Could not find node '%s': %s\n", node, + fdt_strerror(off)); + return; + } + fdt_set_node_status(blob, off, + enable ? FDT_STATUS_OKAY : FDT_STATUS_DISABLED, 0); + + karo_set_fdtsize(blob); +} + +static void fdt_disable_tp_node(void *blob, const char *name) +{ + int offs = fdt_node_offset_by_compatible(blob, -1, name); + + while (offs >= 0) { + debug("Disabling node '%s'\n", name); + fdt_set_node_status(blob, offs, FDT_STATUS_DISABLED, 0); + offs = fdt_node_offset_by_compatible(blob, offs, name); + } +} + +void karo_fdt_fixup_touchpanel(void *blob, const char *panels[], + size_t num_panels) +{ + int i; + const char *model = getenv("touchpanel"); + + for (i = 0; i < num_panels; i++) { + const char *tp = panels[i]; + + if (model != NULL) { + if (strcmp(model, tp) == 0) + continue; + while (tp != NULL) { + if (*tp != '\0' && strcmp(model, tp + 1) == 0) + break; + tp = strpbrk(tp + 1, ",-"); + } + if (tp != NULL) + continue; + } + fdt_disable_tp_node(blob, panels[i]); + } + karo_set_fdtsize(blob); +} + +static int karo_fdt_disable_node_phandle(void *blob, const char *parent, + const char *name) +{ + const uint32_t *ph; + int off; + + off = fdt_path_offset(blob, parent); + if (off < 0) { + printf("Failed to find node '%s'\n", parent); + return off; + } + + ph = fdt_getprop(blob, off, name, NULL); + if (ph == NULL) { + debug("Failed to find '%s' phandle in node '%s'\n", name, + fdt_get_name(blob, off, NULL)); + return -FDT_ERR_NOTFOUND; + } + + off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*ph)); + if (off <= 0) { + printf("Failed to find '%s' node via phandle %04x\n", + name, fdt32_to_cpu(*ph)); + return -FDT_ERR_NOTFOUND; + } + return fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); +} + +void karo_fdt_fixup_usb_otg(void *blob, const char *node, const char *phy, + const char *phy_supply) +{ + const char *otg_mode = getenv("otg_mode"); + int off; + int ret; + int disable_otg = 0; + int disable_phy_pins = 0; + + debug("OTG mode is '%s'\n", otg_mode ? otg_mode : ""); + + off = fdt_path_offset(blob, node); + if (off < 0) { + debug("Failed to find node %s\n", node); + return; + } + + if (otg_mode && (strcasecmp(otg_mode, "device") == 0 || + strcasecmp(otg_mode, "gadget") == 0)) { + debug("Setting dr_mode to 'peripheral'\n"); + ret = fdt_setprop_string(blob, off, "dr_mode", "peripheral"); + disable_phy_pins = 1; + } else if (otg_mode && strcasecmp(otg_mode, "host") == 0) { + debug("Setting dr_mode to 'host'\n"); + ret = fdt_setprop_string(blob, off, "dr_mode", "host"); + } else if (otg_mode && strcasecmp(otg_mode, "otg") == 0) { + debug("Setting dr_mode to 'otg'\n"); + ret = fdt_setprop_string(blob, off, "dr_mode", "otg"); + } else { + if (otg_mode && strcasecmp(otg_mode, "none") != 0) + printf("Invalid 'otg_mode' setting '%s'; disabling usbotg port\n", + otg_mode); + disable_otg = 1; + ret = 0; + } + + if ((!disable_phy_pins && !disable_otg) || ret) + goto out; + + ret = karo_fdt_disable_node_phandle(blob, node, phy_supply); + if (ret && ret == -FDT_ERR_NOTFOUND) { + const uint32_t *ph; + + ph = fdt_getprop(blob, off, phy, NULL); + if (ph == NULL) { + printf("Failed to find '%s' phandle in node '%s'\n", + phy, node); + ret = -FDT_ERR_NOTFOUND; + goto out; + } + off = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*ph)); + if (off < 0) { + printf("Failed to find '%s' node via phandle %04x\n", + phy, fdt32_to_cpu(*ph)); + ret = off; + goto out; + } + ph = fdt_getprop(blob, off, phy_supply, NULL); + if (ph == NULL) { + debug("Failed to find '%s' phandle in node '%s'\n", + phy_supply, fdt_get_name(blob, off, NULL)); + ret = -FDT_ERR_NOTFOUND; + goto disable_otg; + } + ret = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*ph)); + if (ret > 0) { + debug("Disabling node %s via phandle %s:%s\n", + fdt_get_name(blob, ret, NULL), + fdt_get_name(blob, off, NULL), phy_supply); + ret = fdt_set_node_status(blob, ret, + FDT_STATUS_DISABLED, 0); + } + } + if (ret && ret != -FDT_ERR_NOTFOUND) + goto out; + +disable_otg: + if (disable_otg) { + debug("Disabling '%s'\n", fdt_get_name(blob, off, NULL)); + ret = fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + if (ret > 0) + ret = karo_fdt_disable_node_phandle(blob, node, phy); + } else if (disable_phy_pins) { + debug("Removing '%s' from node '%s'\n", phy_supply, + fdt_get_name(blob, off, NULL)); + ret = fdt_delprop(blob, off, phy_supply); + } + +out: + if (ret && ret != -FDT_ERR_NOTFOUND) + printf("Failed to update usbotg: %s\n", fdt_strerror(ret)); + else + debug("node '%s' updated\n", node); + karo_set_fdtsize(blob); +} + +static inline int karo_fdt_flexcan_enabled(void *blob) +{ + static const char *can_ifs[] = { + "can0", + "can1", + }; + size_t i; + + for (i = 0; i < ARRAY_SIZE(can_ifs); i++) { + const char *status; + int off = fdt_path_offset(blob, can_ifs[i]); + + if (off < 0) { + debug("node '%s' not found\n", can_ifs[i]); + continue; + } + status = fdt_getprop(blob, off, "status", NULL); + if (status && strcmp(status, "okay") == 0) { + debug("%s is enabled\n", can_ifs[i]); + return 1; + } + } + debug("can driver is disabled\n"); + return 0; +} + +static inline void karo_fdt_set_lcd_pins(void *blob, const char *name) +{ + int off = fdt_path_offset(blob, name); + u32 ph; + const struct fdt_property *pc; + int len; + + if (off < 0) + return; + + ph = fdt_create_phandle(blob, off); + if (!ph) + return; + + off = fdt_path_offset(blob, "display"); + if (off < 0) + return; + + pc = fdt_get_property(blob, off, "pinctrl-0", &len); + if (!pc || len < sizeof(ph)) + return; + + memcpy((void *)pc->data, &ph, sizeof(ph)); + fdt_setprop_cell(blob, off, "pinctrl-0", ph); +} + +void karo_fdt_fixup_flexcan(void *blob, int xcvr_present) +{ + int ret; + const char *xcvr_status = "disabled"; + const char *otg_mode = getenv("otg_mode"); + + if (xcvr_present) { + if (karo_fdt_flexcan_enabled(blob)) { + if (!is_lvds()) { + debug("Changing LCD to use 23bits only\n"); + karo_fdt_set_lcd_pins(blob, "lcdif_23bit_pins_a"); + xcvr_status = NULL; + } + } else if (!is_lvds()) { + debug("Changing LCD to use 24bits\n"); + karo_fdt_set_lcd_pins(blob, "lcdif_24bit_pins_a"); + } + } else { + int off = fdt_path_offset(blob, "can0"); + + if (off >= 0) + fdt_delprop(blob, off, "xceiver-supply"); + off = fdt_path_offset(blob, "can1"); + if (off >= 0) + fdt_delprop(blob, off, "xceiver-supply"); + if (!is_lvds()) + karo_fdt_set_lcd_pins(blob, "lcdif_24bit_pins_a"); + } + + if (otg_mode && strcasecmp(otg_mode, "host") == 0) + karo_fdt_enable_node(blob, "can1", 0); + + if (xcvr_status) { + debug("Disabling CAN XCVR\n"); + ret = fdt_find_and_setprop(blob, "reg_can_xcvr", "status", + xcvr_status, strlen(xcvr_status) + 1, 1); + if (ret) + printf("Failed to disable CAN transceiver switch: %s\n", + fdt_strerror(ret)); + } +} + +void karo_fdt_del_prop(void *blob, const char *compat, u32 offs, + const char *propname) +{ + int offset = -1; + const fdt32_t *reg = NULL; + + while (1) { + offset = fdt_node_offset_by_compatible(blob, offset, compat); + if (offset <= 0) + return; + + reg = fdt_getprop(blob, offset, "reg", NULL); + if (reg == NULL) + return; + + if (fdt32_to_cpu(*reg) == offs) + break; + } + debug("Removing property '%s' from node %s@%x\n", + propname, compat, offs); + fdt_delprop(blob, offset, propname); + + karo_set_fdtsize(blob); +} + +#ifdef CONFIG_LCD +static int fdt_init_fb_mode(const void *blob, int off, struct fb_videomode *fb_mode) +{ + const uint32_t *prop; + + memset(fb_mode, 0, sizeof(*fb_mode)); + + prop = fdt_getprop(blob, off, "clock-frequency", NULL); + if (prop) + fb_mode->pixclock = KHZ2PICOS(fdt32_to_cpu(*prop) / 1000); + + prop = fdt_getprop(blob, off, "hactive", NULL); + if (prop) + fb_mode->xres = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "vactive", NULL); + if (prop) + fb_mode->yres = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "hback-porch", NULL); + if (prop) + fb_mode->left_margin = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "hsync-len", NULL); + if (prop) + fb_mode->hsync_len = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "hfront-porch", NULL); + if (prop) + fb_mode->right_margin = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "vback-porch", NULL); + if (prop) + fb_mode->upper_margin = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "vsync-len", NULL); + if (prop) + fb_mode->vsync_len = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "vfront-porch", NULL); + if (prop) + fb_mode->lower_margin = fdt32_to_cpu(*prop); + + prop = fdt_getprop(blob, off, "hsync-active", NULL); + if (prop) + fb_mode->sync |= *prop ? FB_SYNC_VERT_HIGH_ACT : 0; + + prop = fdt_getprop(blob, off, "vsync-active", NULL); + if (prop) + fb_mode->sync |= *prop ? FB_SYNC_VERT_HIGH_ACT : 0; + + prop = fdt_getprop(blob, off, "de-active", NULL); + if (prop) + fb_mode->sync |= *prop ? 0 : FB_SYNC_OE_LOW_ACT; + + prop = fdt_getprop(blob, off, "pixelclk-active", NULL); + if (prop) + fb_mode->sync |= *prop ? 0 : FB_SYNC_CLK_LAT_FALL; + + return 0; +} + +static int fdt_update_native_fb_mode(void *blob, int off) +{ + int ret; + uint32_t ph; + + ret = fdt_increase_size(blob, 64); + if (ret) { + printf("Warning: Failed to increase FDT size: %s\n", + fdt_strerror(ret)); + } + debug("Creating phandle at offset %d\n", off); + ph = fdt_create_phandle(blob, off); + if (!ph) { + printf("Failed to create phandle for video timing\n"); + return -ENOMEM; + } + + debug("phandle of %s @ %06x=%04x\n", fdt_get_name(blob, off, NULL), + off, ph); + off = fdt_parent_offset(blob, off); + if (off < 0) + return off; + debug("parent offset=%06x\n", off); + ret = fdt_setprop_cell(blob, off, "native-mode", ph); + if (ret) + printf("Failed to set property 'native-mode': %s\n", + fdt_strerror(ret)); + karo_set_fdtsize(blob); + return ret; +} + +static int karo_fdt_find_video_timings(const void *blob) +{ + int off = fdt_path_offset(blob, "display"); + const char *subnode = "display-timings"; + + if (off < 0) { + debug("Could not find node 'display' in FDT: %s\n", + fdt_strerror(off)); + return off; + } + + off = fdt_subnode_offset(blob, off, subnode); + if (off < 0) { + debug("Could not find node '%s' in FDT: %s\n", subnode, + fdt_strerror(off)); + } + return off; +} + +int karo_fdt_get_fb_mode(const void *blob, const char *name, + struct fb_videomode *fb_mode) +{ + int off = karo_fdt_find_video_timings(blob); + + if (off < 0) + return off; + while (off > 0) { + const char *n, *endp; + int len, d = 1; + + off = fdt_next_node(blob, off, &d); + if (off < 0) + return off; + if (d < 1) + return -EINVAL; + if (d > 2) { + debug("Skipping node @ %04x %s depth %d\n", off, + fdt_get_name(blob, off, NULL), d); + continue; + } + + n = fdt_getprop(blob, off, "panel-name", &len); + if (!n) { + n = fdt_get_name(blob, off, NULL); + if (strcasecmp(n, name) == 0) { + break; + } + } else { + int found = 0; + + for (endp = n + len; n < endp; n += strlen(n) + 1) { + debug("Checking panel-name '%s'\n", n); + if (strcasecmp(n, name) == 0) { + debug("Using node %s @ %04x\n", + fdt_get_name(blob, off, NULL), off); + found = 1; + break; + } + } + if (found) + break; + } + } + if (off > 0) + return fdt_init_fb_mode(blob, off, fb_mode); + + return -EINVAL; +} + +#define SET_FB_PROP(n, v) ({ \ + int ret; \ + ret = fdt_setprop_u32(blob, off, n, v); \ + if (ret) { \ + printf("Failed to set property %s: %s\n", name, \ + fdt_strerror(ret)); \ + } \ + ret; \ +}) + +int karo_fdt_create_fb_mode(void *blob, const char *name, + struct fb_videomode *fb_mode) +{ + int off = fdt_path_offset(blob, "display"); + int ret; + const char *subnode = "display-timings"; + + if (off < 0) { + printf("'display' node not found in FDT\n"); + return off; + } + + ret = fdt_increase_size(blob, 512); + if (ret) { + printf("Failed to increase FDT size: %s\n", fdt_strerror(ret)); + return ret; + } + + ret = fdt_subnode_offset(blob, off, subnode); + if (ret < 0) { + debug("Could not find node '%s' in FDT: %s\n", subnode, + fdt_strerror(ret)); + ret = fdt_add_subnode(blob, off, subnode); + if (ret < 0) { + printf("Failed to add %s subnode: %s\n", subnode, + fdt_strerror(ret)); + return ret; + } + } + + ret = fdt_add_subnode(blob, ret, name); + if (ret < 0) { + printf("Failed to add %s subnode: %s\n", name, + fdt_strerror(ret)); + return ret; + } + off = ret; + + ret = SET_FB_PROP("clock-frequency", + PICOS2KHZ(fb_mode->pixclock) * 1000); + if (ret) + goto out; + ret = SET_FB_PROP("hactive", fb_mode->xres); + if (ret) + goto out; + ret = SET_FB_PROP("vactive", fb_mode->yres); + if (ret) + goto out; + ret = SET_FB_PROP("hback-porch", fb_mode->left_margin); + if (ret) + goto out; + ret = SET_FB_PROP("hsync-len", fb_mode->hsync_len); + if (ret) + goto out; + ret = SET_FB_PROP("hfront-porch", fb_mode->right_margin); + if (ret) + goto out; + ret = SET_FB_PROP("vback-porch", fb_mode->upper_margin); + if (ret) + goto out; + ret = SET_FB_PROP("vsync-len", fb_mode->vsync_len); + if (ret) + goto out; + ret = SET_FB_PROP("vfront-porch", fb_mode->lower_margin); + if (ret) + goto out; + ret = SET_FB_PROP("hsync-active", + fb_mode->sync & FB_SYNC_VERT_HIGH_ACT ? 1 : 0); + if (ret) + goto out; + ret = SET_FB_PROP("vsync-active", + fb_mode->sync & FB_SYNC_VERT_HIGH_ACT ? 1 : 0); + if (ret) + goto out; + ret = SET_FB_PROP("de-active", + !(fb_mode->sync & FB_SYNC_OE_LOW_ACT)); + if (ret) + goto out; + ret = SET_FB_PROP("pixelclk-active", + !(fb_mode->sync & FB_SYNC_CLK_LAT_FALL)); +out: + karo_set_fdtsize(blob); + return ret; +} + +int karo_fdt_update_fb_mode(void *blob, const char *name) +{ + int off = fdt_path_offset(blob, "display"); + const char *subnode = "display-timings"; + + if (off < 0) + return off; + + if (name == NULL) { + int ret; + + debug("Disabling node '%s' at %03x\n", + fdt_get_name(blob, off, NULL), off); + ret = fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); + return ret; + } + + off = fdt_subnode_offset(blob, off, subnode); + if (off < 0) { + debug("Could not find node '%s' in FDT: %s\n", subnode, + fdt_strerror(off)); + return off; + } + while (off > 0) { + const char *n, *endp; + int len, d = 1; + + off = fdt_next_node(blob, off, &d); + if (off < 0) + return off; + if (d < 1) + return -EINVAL; + if (d > 2) { + debug("Skipping node @ %04x %s depth %d\n", off, + fdt_get_name(blob, off, NULL), d); + continue; + } + + n = fdt_getprop(blob, off, "panel-name", &len); + if (!n) { + n = fdt_get_name(blob, off, NULL); + if (strcasecmp(n, name) == 0) { + break; + } + } else { + int found = 0; + + for (endp = n + len; n < endp; n += strlen(n) + 1) { + debug("Checking panel-name '%s'\n", n); + if (strcasecmp(n, name) == 0) { + debug("Using node %s @ %04x\n", + fdt_get_name(blob, off, NULL), off); + found = 1; + break; + } + } + if (found) + break; + } + } + if (off > 0) + return fdt_update_native_fb_mode(blob, off); + return off; +} + +#ifdef CONFIG_SYS_LVDS_IF +#ifdef CONFIG_SOC_MXC +#define LVDS_DATA_WIDTH_NAME "fsl,data-width" +#define LVDS_DATA_MAPPING_NAME "fsl,data-mapping" +#else +#define LVDS_DATA_WIDTH_NAME "lvds-data-width" +#define LVDS_DATA_MAPPING_NAME "lvds-data-mapping" +#endif + +int karo_fdt_get_lcd_bus_width(const void *blob, int default_width) +{ + int off = fdt_path_offset(blob, "display"); + + if (off >= 0) { + const uint32_t *prop; + + prop = fdt_getprop(blob, off, LVDS_DATA_WIDTH_NAME, NULL); + if (prop) + return fdt32_to_cpu(*prop); + } + return default_width; +} + +int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping) +{ + int off = fdt_path_offset(blob, "display"); + + if (off >= 0) { + const char *prop; + + prop = fdt_getprop(blob, off, LVDS_DATA_MAPPING_NAME, NULL); + if (prop) + return strcmp(prop, "jeida") == 0; + } + return default_mapping; +} + +u8 karo_fdt_get_lvds_channels(const void *blob) +{ + static const char *lvds_chans[] = { + "lvds0", + "lvds1", + }; + u8 lvds_chan_mask = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(lvds_chans); i++) { + const char *status; + int off = fdt_path_offset(blob, lvds_chans[i]); + + if (off < 0) + continue; + + status = fdt_getprop(blob, off, "status", NULL); + if (status && strcmp(status, "okay") == 0) { + debug("%s is enabled\n", lvds_chans[i]); + lvds_chan_mask |= 1 << i; + } + } + return lvds_chan_mask; +} +#endif + +int karo_fdt_find_backlight_node(const void *blob) +{ + int off = fdt_path_offset(blob, "backlight"); /* first try alias */ +#ifdef CONFIG_SYS_LVDS_IF + const char *backlight_node = "/backlight0"; +#else + const char *backlight_node = "/backlight"; +#endif + if (off < 0) { + /* + * if no 'backlight' alias exists try finding '/backlight0' + * or '/backlight' depending on LVDS or not + */ + off = fdt_path_offset(blob, backlight_node); + if (off < 0) { + printf("%s node not found in DT\n", backlight_node); + return off; + } + } + return off; +} + +int karo_fdt_get_backlight_gpio(const void *blob, struct gpio_desc *desc) +{ + int off = karo_fdt_find_backlight_node(blob); + const char *prop_name = "gpios"; + const struct fdt_property *prop; + int ret; + + if (off < 0) { + printf("Could not find 'backlight' node in FDT: %s\n", + fdt_strerror(off)); + return off; + } + + prop = fdt_get_property(blob, off, prop_name, NULL); + if (!prop) { + prop_name = "gpio"; + prop = fdt_get_property(blob, off, prop_name, NULL); + if (!prop) { + debug("'gpios' or 'gpio' property not found in backlight node\n"); + return -ENOENT; + } + } + ret = gpio_request_by_name_nodev(blob, off, prop_name, 0, desc, 0); + if (ret < 0) + printf("Failed to request backlight gpio %s/%s: %d\n", + fdt_get_name(blob, off, NULL), prop_name, ret); + + return ret; +} + +int karo_fdt_get_backlight_polarity(const void *blob) +{ + int off = karo_fdt_find_backlight_node(blob); + const struct fdt_property *prop; + int len; + const char *prop_name = "pwms"; + + if (off < 0) { + printf("Could not find 'backlight' node in FDT: %s\n", + fdt_strerror(off)); + return off; + } + + prop = fdt_get_property(blob, off, prop_name, &len); + if (!prop) { + prop_name = "gpios"; + prop = fdt_get_property(blob, off, prop_name, &len); + if (!prop) { + prop_name = "gpios"; + prop = fdt_get_property(blob, off, prop_name, &len); + } + if (!prop) { + printf("'pwms' or 'gpios' property not found in backlight node\n"); + return 0; + } + } + if (prop) + debug("'%s' property has len %d\n", prop_name, len); + + len /= sizeof(u32); + if (prop && len > 3) { + const u32 *data = (const u32 *)prop->data; + return fdt32_to_cpu(data[3]) != 0; + } + return 0; +} +#endif /* CONFIG_LCD */ diff --git a/board/karo/common/karo.h b/board/karo/common/karo.h new file mode 100644 index 0000000000..2841c8c159 --- /dev/null +++ b/board/karo/common/karo.h @@ -0,0 +1,188 @@ +/* + * (C) Copyright 2012 Lothar Waßmann + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * +*/ + +#include + +struct fb_videomode; +struct gpio_desc; + +#ifdef CONFIG_SYS_LVDS_IF +#define is_lvds() 1 +#else +#define is_lvds() 0 +#endif + +void env_cleanup(void); + +#ifdef CONFIG_OF_LIBFDT +void karo_fdt_remove_node(void *blob, const char *node); +void karo_fdt_move_fdt(void); +void karo_fdt_fixup_touchpanel(void *blob, const char *panels[], + size_t num_panels); +void karo_fdt_fixup_usb_otg(void *blob, const char *node, const char *phy, + const char *phy_supply); +void karo_fdt_fixup_flexcan(void *blob, int xcvr_present); +void karo_fdt_del_prop(void *blob, const char *compat, u32 offs, + const char *prop); +void karo_fdt_enable_node(void *blob, const char *node, int enable); +int karo_fdt_get_fb_mode(const void *blob, const char *name, + struct fb_videomode *fb_mode); +int karo_fdt_update_fb_mode(void *blob, const char *name); +int karo_fdt_create_fb_mode(void *blob, const char *name, + struct fb_videomode *mode); +int karo_fdt_get_backlight_polarity(const void *blob); +int karo_fdt_get_backlight_gpio(const void *blob, struct gpio_desc *desc); +#else +static inline void karo_fdt_remove_node(void *blob, const char *node) +{ +} +static inline void karo_fdt_move_fdt(void) +{ +} +static inline void karo_fdt_fixup_touchpanel(void *blob, const char *panels[], + size_t num_panels) +{ +} +static inline void karo_fdt_fixup_usb_otg(void *blob, const char *node, + const char *phy, + const char *phy_supply) +{ +} +static inline void karo_fdt_fixup_flexcan(void *blob, int xcvr_present) +{ +} +static inline void karo_fdt_del_prop(void *blob, const char *compat, + u32 offs, const char *prop) +{ +} +static inline void karo_fdt_enable_node(void *blob, const char *node, + int enable) +{ +} +static inline int karo_fdt_get_fb_mode(void *blob, const char *name, + struct fb_videomode *fb_mode) +{ + return 0; +} +static inline int karo_fdt_update_fb_mode(void *blob, const char *name) +{ + return 0; +} +static inline int karo_fdt_create_fb_mode(void *blob, + const char *name, + struct fb_videomode *mode) +{ + return 0; +} +static inline int karo_fdt_get_backlight_polarity(const void *blob) +{ + return getenv_yesno("backlight_polarity"); +} +static inline int karo_fdt_get_backlight_gpio(const void *blob, + struct gpio_desc *desc) +{ + return -ENOENT; +} +#endif + +#if defined(CONFIG_SYS_LVDS_IF) && defined(CONFIG_OF_LIBFDT) +int karo_fdt_get_lcd_bus_width(const void *blob, int default_width); +int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping); +u8 karo_fdt_get_lvds_channels(const void *blob); +#else +static inline int karo_fdt_get_lcd_bus_width(const void *blob, int default_width) +{ + return default_width; +} +static inline int karo_fdt_get_lvds_mapping(const void *blob, int default_mapping) +{ + return default_mapping; +} +static inline u8 karo_fdt_get_lvds_channels(const void *blob) +{ + return 0; +} +#endif + +static inline const char *karo_get_vmode(const char *video_mode) +{ + const char *vmode = NULL; + + if (video_mode == NULL || strlen(video_mode) == 0) + return NULL; + + vmode = strchr(video_mode, ':'); + return vmode ? vmode + 1 : video_mode; +} + +#ifdef CONFIG_LCD +#ifdef CONFIG_VIDEO_IPUV3 +#include +#endif + +#ifndef FB_SYNC_CLK_LAT_FALL +#define FB_SYNC_CLK_LAT_FALL 0 +#define FB_SYNC_OE_LOW_ACT 0 +#endif + +int karo_get_fb_mode(const char *name, struct fb_videomode **mode); +#else +static inline int karo_get_fb_mode(const char *name, + struct fb_videomode **mode) +{ + return -EOPNOTSUPP; +} +#endif /* CONFIG_LCD */ + +#ifdef CONFIG_SPLASH_SCREEN +int karo_load_splashimage(int mode); +#else +static inline int karo_load_splashimage(int mode) +{ + return 0; +} +#endif /* CONFIG_SPLASH_SCREEN */ + +#ifdef CONFIG_CMD_NAND +int karo_nand_load_part(const char *part, void *addr, size_t len); +#else +static inline int karo_nand_load_part(const char *part, void *addr, size_t len) +{ + return -EOPNOTSUPP; +} +#endif + +#ifdef CONFIG_ENV_IS_IN_MMC +int karo_mmc_load_part(const char *part, void *addr, size_t len); +#else +static inline int karo_mmc_load_part(const char *part, void *addr, size_t len) +{ + return -EOPNOTSUPP; +} +#endif + +static inline int karo_load_part(const char *part, void *addr, size_t len) +{ + int ret; + + ret = karo_nand_load_part(part, addr, len); + if (ret == -EOPNOTSUPP) + return karo_mmc_load_part(part, addr, len); + return ret; +} + +#define DIV_ROUND(n, d) (((n) + (d) / 2) / (d)) diff --git a/board/karo/common/lcd.c b/board/karo/common/lcd.c new file mode 100644 index 0000000000..b914c1887a --- /dev/null +++ b/board/karo/common/lcd.c @@ -0,0 +1,198 @@ +#include +#include +#ifdef CONFIG_VIDEO_IPUV3 +#include +#endif + +#include "karo.h" + +static struct fb_videomode karo_tx_fb_modes[] = { +#ifndef CONFIG_SYS_LVDS_IF + { + /* Standard VGA timing */ + .name = "VGA", + .refresh = 60, + .xres = 640, + .yres = 480, + .pixclock = KHZ2PICOS(25175), + .left_margin = 48, + .hsync_len = 96, + .right_margin = 16, + .upper_margin = 31, + .vsync_len = 2, + .lower_margin = 12, + .sync = FB_SYNC_CLK_LAT_FALL, + }, + { + /* Emerging ETV570 640 x 480 display. Syncs low active, + * DE high active, 115.2 mm x 86.4 mm display area + * VGA compatible timing + */ + .name = "ETV570", + .refresh = 60, + .xres = 640, + .yres = 480, + .pixclock = KHZ2PICOS(25175), + .left_margin = 114, + .hsync_len = 30, + .right_margin = 16, + .upper_margin = 32, + .vsync_len = 3, + .lower_margin = 10, + .sync = FB_SYNC_CLK_LAT_FALL, + }, + { + /* Emerging ET0350G0DH6 320 x 240 display. + * 70.08 mm x 52.56 mm display area. + */ + .name = "ET0350", + .refresh = 60, + .xres = 320, + .yres = 240, + .pixclock = KHZ2PICOS(6500), + .left_margin = 68 - 34, + .hsync_len = 34, + .right_margin = 20, + .upper_margin = 18 - 3, + .vsync_len = 3, + .lower_margin = 4, + .sync = FB_SYNC_CLK_LAT_FALL, + }, + { + /* Emerging ET0430G0DH6 480 x 272 display. + * 95.04 mm x 53.856 mm display area. + */ + .name = "ET0430", + .refresh = 60, + .xres = 480, + .yres = 272, + .pixclock = KHZ2PICOS(9000), + .left_margin = 2, + .hsync_len = 41, + .right_margin = 2, + .upper_margin = 2, + .vsync_len = 10, + .lower_margin = 2, + }, + { + /* Emerging ET0500G0DH6 800 x 480 display. + * 109.6 mm x 66.4 mm display area. + */ + .name = "ET0500", + .refresh = 60, + .xres = 800, + .yres = 480, + .pixclock = KHZ2PICOS(33260), + .left_margin = 216 - 128, + .hsync_len = 128, + .right_margin = 1056 - 800 - 216, + .upper_margin = 35 - 2, + .vsync_len = 2, + .lower_margin = 525 - 480 - 35, + .sync = FB_SYNC_CLK_LAT_FALL, + }, + { + /* Emerging ETQ570G0DH6 320 x 240 display. + * 115.2 mm x 86.4 mm display area. + */ + .name = "ETQ570", + .refresh = 60, + .xres = 320, + .yres = 240, + .pixclock = KHZ2PICOS(6400), + .left_margin = 38, + .hsync_len = 30, + .right_margin = 30, + .upper_margin = 16, /* 15 according to datasheet */ + .vsync_len = 3, /* TVP -> 1>x>5 */ + .lower_margin = 4, /* 4.5 according to datasheet */ + .sync = FB_SYNC_CLK_LAT_FALL, + }, + { + /* Emerging ET0700G0DH6 800 x 480 display. + * 152.4 mm x 91.44 mm display area. + */ + .name = "ET0700", + .refresh = 60, + .xres = 800, + .yres = 480, + .pixclock = KHZ2PICOS(33260), + .left_margin = 216 - 128, + .hsync_len = 128, + .right_margin = 1056 - 800 - 216, + .upper_margin = 35 - 2, + .vsync_len = 2, + .lower_margin = 525 - 480 - 35, + .sync = FB_SYNC_CLK_LAT_FALL, + }, + { + /* Emerging ET070001DM6 800 x 480 display. + * 152.4 mm x 91.44 mm display area. + */ + .name = "ET070001DM6", + .refresh = 60, + .xres = 800, + .yres = 480, + .pixclock = KHZ2PICOS(33260), + .left_margin = 216 - 128, + .hsync_len = 128, + .right_margin = 1056 - 800 - 216, + .upper_margin = 35 - 2, + .vsync_len = 2, + .lower_margin = 525 - 480 - 35, + .sync = 0, + }, +#else + { + /* HannStar HSD100PXN1 + * 202.7m mm x 152.06 mm display area. + */ + .name = "HSD100PXN1", + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = KHZ2PICOS(65000), + .left_margin = 0, + .hsync_len = 0, + .right_margin = 320, + .upper_margin = 0, + .vsync_len = 0, + .lower_margin = 38, + .sync = FB_SYNC_CLK_LAT_FALL, + }, +#endif + { + /* unnamed entry for assigning parameters parsed from 'video_mode' string */ + .refresh = 60, + .left_margin = 48, + .hsync_len = 96, + .right_margin = 16, + .upper_margin = 31, + .vsync_len = 2, + .lower_margin = 12, + .sync = FB_SYNC_CLK_LAT_FALL, + }, +}; + +int karo_get_fb_mode(const char *name, struct fb_videomode **mode) +{ + size_t i; + + if (name == NULL) { + if (mode) + *mode = karo_tx_fb_modes; + return ARRAY_SIZE(karo_tx_fb_modes); + } + for (i = 0; i < ARRAY_SIZE(karo_tx_fb_modes); i++) { + struct fb_videomode *m = &karo_tx_fb_modes[i]; + + if (m->name && strcmp(m->name, name) == 0) { + if (mode) + *mode = m; + return i; + } + } + if (mode) + *mode = NULL; + return -ENOENT; +} diff --git a/board/karo/common/mmc.c b/board/karo/common/mmc.c new file mode 100644 index 0000000000..53dc00dba9 --- /dev/null +++ b/board/karo/common/mmc.c @@ -0,0 +1,210 @@ +/* + * (C) Copyright 2014 Lothar Waßmann + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "karo.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define MAX_SEARCH_PARTITIONS 16 + +static int find_partitions(const char *ifname, int devno, const char *partname, + struct blk_desc **dev_desc, disk_partition_t *info) +{ + struct blk_desc *dd; + char dev_part_str[16]; + int p; + + dd = blk_get_devnum_by_typename(ifname, devno); + if (!dd || dd->type == DEV_TYPE_UNKNOWN) { + printf("** Bad device %s %d **\n", ifname, devno); + return -1; + } + part_init(dd); + + /* + * No partition table on device, + * or user requested partition 0 (entire device). + */ + if (dd->part_type == PART_TYPE_UNKNOWN) { + printf("** No partition table on device %s %d **\n", + ifname, devno); + return -ENODEV; + } + + printf("part type: %08x\n", dd->part_type); + for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) { + int ret; + + if (partname) { + ret = part_get_info(dd, p, info); + if (ret == 0) + ret = strncmp((char *)info->name, partname, + sizeof(info->name)); + } else { + ret = fat_register_device(dd, p); + + } + if (ret) + continue; + + snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d", + devno, p); + ret = fs_set_blk_dev(ifname, dev_part_str, FS_TYPE_ANY); + if (ret == 0) { + dd->log2blksz = LOG2(dd->blksz); + *dev_desc = dd; + return 0; + } + } + printf("** No valid partition on device %s %d **\n", + ifname, devno); + return -ENODEV; +} + +static int karo_mmc_find_part(struct mmc *mmc, const char *part, + const char *filename, int devno, + disk_partition_t *part_info) +{ + int ret; + struct blk_desc *mmc_dev; + +#if defined(CONFIG_SYS_DTB_OFFSET) && defined(CONFIG_SYS_MMC_ENV_PART) + if (strcmp(part, "dtb") == 0) { + const int partnum = CONFIG_SYS_MMC_ENV_PART; + + part_info->blksz = mmc->read_bl_len; + part_info->start = CONFIG_SYS_DTB_OFFSET / part_info->blksz; + part_info->size = CONFIG_SYS_DTB_PART_SIZE / part_info->blksz; + printf("Using virtual partition %s(%d) ["LBAF".."LBAF"]\n", + part, partnum, part_info->start, + part_info->start + part_info->size - 1); + return partnum; + } +#endif + ret = find_partitions("mmc", devno, part, &mmc_dev, part_info); + if (ret < 0) { + printf("No (e)MMC partition found: %d\n", ret); + return ret; + } + return 0; +} + +int karo_mmc_load_part(const char *part_file, void *addr, size_t len) +{ + int ret; + struct mmc *mmc; + char *partname = strdup(part_file); + char *filename; + disk_partition_t part_info; + int devno = mmc_get_env_dev(); + lbaint_t blk_cnt; + + if (!partname) + return -ENOMEM; + + mmc = find_mmc_device(devno); + if (!mmc) { + printf("Failed to find mmc%u\n", devno); + return -ENODEV; + } + + if (mmc_init(mmc)) { + printf("Failed to init MMC device %d\n", devno); + return -EIO; + } + + filename = strchr(partname, ':'); + if (filename) { + *filename = '\0'; + filename++; + } else { + filename = partname; + } + + blk_cnt = DIV_ROUND_UP(len, mmc->read_bl_len); + + ret = karo_mmc_find_part(mmc, partname, filename, devno, &part_info); + if (ret < 0) + goto out; + + if (partname == filename) { + int partnum = ret; + struct blk_desc *desc = mmc_get_blk_desc(mmc); + int hwpart = desc->hwpart; + ulong retval; + + if (part_info.start + blk_cnt < part_info.start) { + printf("%s: given length 0x%08zx exceeds size of partition\n", + __func__, len); + ret = -EINVAL; + goto out; + } + if (partnum != hwpart) { + ret = blk_select_hwpart_devnum(IF_TYPE_MMC, devno, + partnum); + if (ret) + goto out; + + desc = mmc_get_blk_desc(mmc); + } + if (part_info.start + blk_cnt > desc->lba) + blk_cnt = desc->lba - part_info.start; + + debug("Reading 0x"LBAF" blks from MMC partition %d offset 0x"LBAF" to %p\n", + blk_cnt, partnum, part_info.start, addr); + + retval = blk_dread(desc, part_info.start, blk_cnt, addr); + if (partnum != hwpart) + blk_select_hwpart_devnum(IF_TYPE_MMC, devno, hwpart); + if (IS_ERR_VALUE(retval) || retval == 0) { + printf("Failed to read file %s from MMC partition %s\n", + filename, partname); + ret = retval ?: -EIO; + goto out; + } + debug("Read %lu (%zu) byte from partition '%s' @ offset 0x"LBAF"\n", + retval * mmc->read_bl_len, len, filename, part_info.start); + } else { + loff_t len_read; + + debug("Trying to read (%zu) byte from file '%s' in mmc partition '%s'\n", + len, filename, partname); + ret = fs_read(filename, (ulong)addr, 0, len, &len_read); + if (ret < 0) { + printf("Failed to read %zu byte from '%s' in mmc partition '%s'; err: %d\n", + len, filename, partname, ret); + goto out; + } + debug("Read %llu bytes from %s\n", len_read, filename); + } +out: + free(partname); + return ret; +} diff --git a/board/karo/common/splashimage.c b/board/karo/common/splashimage.c new file mode 100644 index 0000000000..e3072e873f --- /dev/null +++ b/board/karo/common/splashimage.c @@ -0,0 +1,72 @@ +/* + * (C) Copyright 2012 Lothar Waßmann + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "karo.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_DM_VIDEO +static ulong calc_fbsize(void) +{ + return panel_info.vl_row * panel_info.vl_col * + NBITS(panel_info.vl_bpix) / 8; +} +#else +static ulong calc_fbsize(void) +{ + return 1; +} +#endif + +int karo_load_splashimage(int mode) +{ + int ret; + unsigned long la = gd->fb_base; + char *splashimage = getenv("splashimage"); + ulong fbsize = calc_fbsize(); + char *end; + + if (!la || !splashimage) + return 0; + + if ((simple_strtoul(splashimage, &end, 16) != 0) && + *end == '\0') { + if (mode) + return 0; + la = simple_strtoul(splashimage, NULL, 16); + splashimage = "logo.bmp"; + } else if (!mode) { + return 0; + } + + if (had_ctrlc()) + return -ENODEV; + + ret = karo_load_part(splashimage, (void *)la, fbsize); + if (ret) { + printf("Failed to load logo from '%s': %d\n", splashimage, ret); + return ret; + } + return 0; +} diff --git a/board/karo/txsd/Kconfig b/board/karo/txsd/Kconfig new file mode 100644 index 0000000000..faa26683e9 --- /dev/null +++ b/board/karo/txsd/Kconfig @@ -0,0 +1,15 @@ +if TARGET_TXSD_410E + +config SYS_BOARD + default "txsd" + +config SYS_VENDOR + default "karo" + +config SYS_SOC + default "apq8016" + +config SYS_CONFIG_NAME + default "txsd" + +endif diff --git a/board/karo/txsd/MAINTAINERS b/board/karo/txsd/MAINTAINERS new file mode 100644 index 0000000000..8d098a3360 --- /dev/null +++ b/board/karo/txsd/MAINTAINERS @@ -0,0 +1,6 @@ +TXSD410E BOARD +M: Lothar Waßmann +S: Maintained +F: board/karo/txsd/ +F: include/configs/txsd.h +F: configs/txsd-410e_defconfig diff --git a/board/karo/txsd/Makefile b/board/karo/txsd/Makefile new file mode 100644 index 0000000000..06b9f799c8 --- /dev/null +++ b/board/karo/txsd/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2017 Lothar Waßmann +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := txsd.o +extra-y += head.o diff --git a/board/karo/txsd/README b/board/karo/txsd/README new file mode 100644 index 0000000000..07f15d5b72 --- /dev/null +++ b/board/karo/txsd/README @@ -0,0 +1,71 @@ +# +# (C) Copyright 2016 Lothar Waßmann +# +# SPDX-License-Identifier: GPL-2.0+ +# + +Build & Run instructions: + +1) Install mkbootimg and dtbTool from + git://codeaurora.org/quic/kernel/skales (15ece94f09 worked for me) +2) Setup CROSS_COMPILE to aarch64 compiler +3) make dragonboard410c_config +4) make +5) generate fake, empty ramdisk (can have 0 bytes) +$ touch rd + +6) Generate qualcomm device tree table with dtbTool [1] +$ dtbTool -o dt.img arch/arm/dts + +7) Generate Android boot image with mkbootimg [2]: +$ mkbootimg --kernel=u-boot-dtb.bin --output=u-boot.img --dt=dt.img \ + --pagesize 2048 --base 0x80000000 --ramdisk=rd --cmdline="" + +8) Enter fastboot (reboot board with vol- button pressed) + +9) Boot it: +$ fastboot boot u-boot.img +or flash as kernel: +$ fastboot flash boot u-boot.img +$ fastboot reboot + + +What is working: +- UART +- GPIO (SoC) +- SD +- eMMC +- Reset +- USB in EHCI mode (usb starts does switch device->host, usb stop does the opposite) +- PMIC GPIOS (but not in generic subsystem) +- PMIC "special" buttons (power, vol-) + +What is not working / known bugs: +- SDHCI is slow (~2.5MiB/s for SD and eMMC) + +[1] To boot any kernel image, Little Kernel requires valid device tree for the +platform it runs on. dtbTool creates device tree table that Little Kernel scans. +Later on proper device tree is passed to next boot stage. +Full device tree is not required to boot u-boot. Enough would be: +/dts-v1/; + +/ { + model = "Qualcomm Technologies, Inc. Dragonboard 410c"; + compatible = "qcom,dragonboard", "qcom,apq8016-sbc"; + qcom,msm-id = <0xce 0x0 0xf8 0x0 0xf9 0x0 0xfa 0x0 0xf7 0x0>; + qcom,board-id = <0x10018 0x0>; + #address-cells = <0x2>; + #size-cells = <0x2>; + chosen { }; + aliases { }; + + memory { + device_type = "memory"; + reg = <0 0x80000000 0 0x3da00000>; + }; +}; + +but for simplicity (and because size of image is not that critical) we use +existing Qualcomm device trees. + +[2] Note that ramdisk is required, even if it is unused. diff --git a/board/karo/txsd/config.mk b/board/karo/txsd/config.mk new file mode 100644 index 0000000000..a070fc64c2 --- /dev/null +++ b/board/karo/txsd/config.mk @@ -0,0 +1,25 @@ +LOGO_BMP = logos/karo.bmp +PLATFORM_CPPFLAGS += -Werror + +CONFIG_ENV_SIZE := $(shell expr 128 \* 1024) +CONFIG_U_BOOT_PART_SIZE := $(shell expr 4130 \* 512) +CONFIG_U_BOOT_IMG_SIZE := $(shell expr 1 \* 1048576) + +CONFIG_ENV_OFFSET := $(CONFIG_U_BOOT_PART_SIZE) +CONFIG_SYS_DTB_OFFSET := $(shell expr 3106 \* 512) +CONFIG_MAX_DTB_SIZE := $(shell expr $(CONFIG_U_BOOT_PART_SIZE) - $(CONFIG_SYS_DTB_OFFSET)) + +CONFIG_LOADADDR := $(shell expr `printf %u $(CONFIG_SYS_SDRAM_BASE)` + `printf %u 0x01000000`) +CONFIG_FDTADDR := $(shell expr `printf %u $(CONFIG_SYS_SDRAM_BASE)` + `printf %u 0x03000000`) +CONFIG_RDADDR := $(shell expr `printf %u $(CONFIG_SYS_SDRAM_BASE)` + `printf %u 0x03500000`) + +PLATFORM_CPPFLAGS += -DCONFIG_LOADADDR=$(shell printf "%08x" $(CONFIG_LOADADDR)) +PLATFORM_CPPFLAGS += -DCONFIG_FDTADDR=$(shell printf "%08x" $(CONFIG_FDTADDR)) +PLATFORM_CPPFLAGS += -DCONFIG_RDADDR=$(shell printf "%08x" $(CONFIG_RDADDR)) + +PLATFORM_CPPFLAGS += -DCONFIG_ENV_OFFSET=$(shell printf "0x%x" $(CONFIG_ENV_OFFSET)) +PLATFORM_CPPFLAGS += -DCONFIG_ENV_SIZE=$(CONFIG_ENV_SIZE) +PLATFORM_CPPFLAGS += -DCONFIG_MAX_DTB_SIZE=$(CONFIG_MAX_DTB_SIZE) +PLATFORM_CPPFLAGS += -DCONFIG_SYS_DTB_PART_SIZE=$(CONFIG_MAX_DTB_SIZE) +PLATFORM_CPPFLAGS += -DCONFIG_SYS_DTB_OFFSET=$(shell printf "0x%x" $(CONFIG_SYS_DTB_OFFSET)) +PLATFORM_CPPFLAGS += -DCONFIG_U_BOOT_IMG_SIZE=$(CONFIG_U_BOOT_IMG_SIZE) diff --git a/board/karo/txsd/head.S b/board/karo/txsd/head.S new file mode 100644 index 0000000000..16dafac027 --- /dev/null +++ b/board/karo/txsd/head.S @@ -0,0 +1,33 @@ +/* + * ARM64 header for proper chain-loading with Little Kernel. + * + * (C) 2017 Lothar Waßmann + * based on board/qualcomm/dragonboard410c/head.S + * (C) Copyright 2015 Mateusz Kulikowski + * + * Little Kernel shipped with Dragonboard410C boots standard Linux images for + * ARM64. This file adds header that is required to boot U-Boot properly. + * + * For details see: + * https://www.kernel.org/doc/Documentation/arm64/booting.txt + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +.global _arm64_header +_arm64_header: + b _start + .word 0 + /* Image load offset from start of RAM, little-endian */ + .quad CONFIG_SYS_TEXT_BASE - PHYS_SDRAM_1 + /* Effective size of kernel image, little-endian */ + .quad 0 /* 0x60000 - ignored */ + /* Informative flags, little-endian */ + .quad 0 + .quad 0 /* reserved */ + .quad 0 /* reserved */ + .quad 0 /* reserved */ + .byte 'A','R','M','d' /* Magic number, "ARM\x64" */ + .word 0 /* reserved */ diff --git a/board/karo/txsd/txsd.c b/board/karo/txsd/txsd.c new file mode 100644 index 0000000000..0669bcacaa --- /dev/null +++ b/board/karo/txsd/txsd.c @@ -0,0 +1,614 @@ +/* + * Board init file for TXSD-410E + * + * (C) Copyright 2017 Lothar Waßmann + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef DEBUG +#include +#endif +#include +#include +#include +#include + +#include "../common/karo.h" + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_SHOW_ACTIVITY + +enum { + LED_STATE_INIT, + LED_STATE_ACTIVE, + LED_STATE_DISABLED, +}; + +static int led_state = LED_STATE_INIT; + +#define FDT_USER_LED_LABEL "txsd-410e:green:user1" + +void show_activity(int arg) +{ + static struct udevice *led_dev; + static ulong last; + int ret; + + if (led_state == LED_STATE_ACTIVE) { + static int led_on; + + if (get_timer(last) > CONFIG_SYS_HZ) { + last = get_timer(0); + led_on = !led_on; + ret = led_set_on(led_dev, led_on); + if (ret != 0) + goto disable; + } + } else if (led_state == LED_STATE_DISABLED) { + return; + } else if (led_state == LED_STATE_INIT) { + ret = led_get_by_label(FDT_USER_LED_LABEL, &led_dev); + if (ret) { + printf("No '%s' LED found in DTB\n", + FDT_USER_LED_LABEL); + goto disable; + } + last = get_timer(0); + led_state = LED_STATE_ACTIVE; + } else { + printf("Invalid LED state: %d @ %p\n", led_state, &led_state); + goto disable; + } + return; + +disable: + led_state = LED_STATE_DISABLED; +} +#endif + +#ifdef CONFIG_LCD +vidinfo_t panel_info = { + /* set to max. size supported by SoC */ + .vl_col = 1920, + .vl_row = 1080, + + .vl_bpix = LCD_COLOR32, /* Bits per pixel, 0: 1bpp, 1: 2bpp, 2: 4bpp, 3: 8bpp ... */ +}; + +static int lcd_enabled = 1; +static int lcd_bl_polarity; +static struct gpio_desc lcd_bl_gpio; + +void lcd_enable(void) +{ + if (lcd_bl_gpio.dev) { + dm_gpio_set_dir_flags(&lcd_bl_gpio, GPIOD_IS_OUT | + (lcd_bl_polarity ? GPIOD_ACTIVE_LOW : 0)); + } +} + +void lcd_ctrl_init(void *lcdbase) +{ + int color_depth = 24; + const char *video_mode = karo_get_vmode(getenv("video_mode")); + const char *vm; + unsigned long val; + int refresh = 60; + struct fb_videomode *p; + struct fb_videomode fb_mode; + int xres_set = 0, yres_set = 0, bpp_set = 0, refresh_set = 0; + + if (karo_get_fb_mode(NULL, &p) <= 0) + goto disable; + + if (!lcd_enabled) { + debug("LCD disabled\n"); + goto disable; + } + + if (had_ctrlc() || video_mode == NULL) { + debug("Disabling LCD\n"); + lcd_enabled = 0; + if (had_ctrlc()) + setenv("splashimage", NULL); + goto disable; + } + + karo_fdt_move_fdt(); + karo_fdt_get_backlight_gpio(gd->fdt_blob, &lcd_bl_gpio); + lcd_bl_polarity = karo_fdt_get_backlight_polarity(gd->fdt_blob); + + vm = video_mode; + if (karo_fdt_get_fb_mode(gd->fdt_blob, video_mode, &fb_mode) == 0) { + p = &fb_mode; + debug("Using video mode from FDT\n"); + vm += strlen(vm); + if (fb_mode.xres > panel_info.vl_col || + fb_mode.yres > panel_info.vl_row) { + printf("video resolution from DT: %dx%d exceeds hardware limits: %dx%d\n", + fb_mode.xres, fb_mode.yres, + panel_info.vl_col, panel_info.vl_row); + lcd_enabled = 0; + goto disable; + } + } + if (p->name != NULL) + debug("Trying compiled-in video modes\n"); + while (p->name != NULL) { + if (strcmp(p->name, vm) == 0) { + debug("Using video mode: '%s'\n", p->name); + vm += strlen(vm); + break; + } + p++; + } + if (*vm != '\0') + debug("Trying to decode video_mode: '%s'\n", vm); + while (*vm != '\0') { + if (*vm >= '0' && *vm <= '9') { + char *end; + + val = simple_strtoul(vm, &end, 0); + if (end > vm) { + if (!xres_set) { + if (val > panel_info.vl_col) + val = panel_info.vl_col; + p->xres = val; + panel_info.vl_col = val; + xres_set = 1; + } else if (!yres_set) { + if (val > panel_info.vl_row) + val = panel_info.vl_row; + p->yres = val; + panel_info.vl_row = val; + yres_set = 1; + } else if (!bpp_set) { + switch (val) { + case 24: + case 18: + color_depth = val; + break; + + default: + printf("Invalid color depth: '%.*s' in video_mode; using default: '%u'\n", + (int)(end - vm), vm, color_depth); + } + bpp_set = 1; + } else if (!refresh_set) { + refresh = val; + refresh_set = 1; + } + } + vm = end; + } + switch (*vm) { + case '@': + bpp_set = 1; + /* fallthru */ + case '-': + yres_set = 1; + /* fallthru */ + case 'x': + xres_set = 1; + /* fallthru */ + case 'M': + case 'R': + vm++; + break; + + default: + if (*vm != '\0') + vm++; + } + } + if (p->xres == 0 || p->yres == 0) { + int num_modes = karo_get_fb_mode(NULL, &p); + int i; + + printf("Invalid video mode: %s\n", getenv("video_mode")); + lcd_enabled = 0; + printf("Supported video modes are:"); + for (i = 0; i < num_modes; i++, p++) { + if (p->name) + printf(" %s", p->name); + } + printf("\n"); + goto disable; + } + if (p->xres > panel_info.vl_col || p->yres > panel_info.vl_row) { + printf("video resolution: %dx%d exceeds hardware limits: %dx%d\n", + p->xres, p->yres, panel_info.vl_col, panel_info.vl_row); + lcd_enabled = 0; + goto disable; + } + panel_info.vl_col = p->xres; + panel_info.vl_row = p->yres; + + switch (color_depth) { + case 8: + panel_info.vl_bpix = LCD_COLOR8; + break; + case 16: + panel_info.vl_bpix = LCD_COLOR16; + break; + default: + panel_info.vl_bpix = LCD_COLOR32; + } + + p->pixclock = KHZ2PICOS(refresh * + (p->xres + p->left_margin + p->right_margin + p->hsync_len) * + (p->yres + p->upper_margin + p->lower_margin + p->vsync_len) / + 1000); + debug("Pixel clock set to %lu.%03lu MHz\n", + PICOS2KHZ(p->pixclock) / 1000, PICOS2KHZ(p->pixclock) % 1000); + + if (p != &fb_mode) { + int ret; + + debug("Creating new display-timing node from '%s'\n", + video_mode); + ret = karo_fdt_create_fb_mode(working_fdt, video_mode, p); + if (ret) + printf("Failed to create new display-timing node from '%s': %d\n", + video_mode, ret); + } + +#if 0 + gpio_request_array(stk5_lcd_gpios, ARRAY_SIZE(stk5_lcd_gpios)); + imx_iomux_v3_setup_multiple_pads(stk5_lcd_pads, + ARRAY_SIZE(stk5_lcd_pads)); +#endif + if (karo_load_splashimage(0) == 0) { + debug("Initializing LCD controller\n"); + } else { + debug("Skipping initialization of LCD controller\n"); + } + return; + +disable: + lcd_enabled = 0; + panel_info.vl_col = 0; + panel_info.vl_row = 0; +} +#endif /* CONFIG_LCD */ + +void txsd_mmc_preinit(void) +{ + struct udevice *mmcdev; + + for (uclass_first_device(UCLASS_MMC, &mmcdev); mmcdev; + uclass_next_device(&mmcdev)) { + struct mmc *m = mmc_get_mmc_dev(mmcdev); + if (m) + mmc_set_preinit(m, 1); + } +} + +int dram_init(void) +{ +#ifdef DEBUG + const struct mm_region *mm = mem_map; + int i; + + for (i = 0; mm->size; i++, mm++) { + printf("MMU region[%d]=%08llx..%08llx -> %08llx..%08llx size: %08llx Attrs: %08llx\n", + i, mm->phys, mm->phys + mm->size - 1, + mm->virt, mm->virt + mm->size - 1, mm->size, mm->attrs); + } +#endif +#if CONFIG_NR_DRAM_BANKS == 1 + gd->ram_size = PHYS_SDRAM_1_SIZE; +#else + gd->ram_size = PHYS_SDRAM_1_SIZE + PHYS_SDRAM_2_SIZE; +#endif + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + printf("RAM bank 0 size set to %lluMiB\n", gd->bd->bi_dram[0].size / SZ_1M); +#if CONFIG_NR_DRAM_BANKS > 1 + gd->bd->bi_dram[1].start = PHYS_SDRAM_2; + gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; + printf("RAM bank 1 size set to %lluMiB\n", gd->bd->bi_dram[1].size / SZ_1M); +#endif + printf("Total RAM size: %lluMiB\n", gd->ram_size / SZ_1M); +} + +/* run with default environment */ +int board_init(void) +{ + if (ctrlc()) { + printf(" detected; safeboot enabled\n"); + return 0; + } + txsd_mmc_preinit(); + return 0; +} + +/* run with env from mass storage device */ +static inline int fdt_err_to_errno(int fdterr) +{ + switch (-fdterr) { + case FDT_ERR_NOTFOUND: + return -ENOENT; + case FDT_ERR_EXISTS: + return -EEXIST; + case FDT_ERR_NOSPACE: + return -ENOMEM; + case FDT_ERR_BADOFFSET: + case FDT_ERR_BADPATH: + case FDT_ERR_BADPHANDLE: + case FDT_ERR_BADSTATE: + return -EINVAL; + case FDT_ERR_TRUNCATED: + return -EILSEQ; + case FDT_ERR_BADMAGIC: + case FDT_ERR_BADVERSION: + case FDT_ERR_BADSTRUCTURE: + case FDT_ERR_BADLAYOUT: + case FDT_ERR_INTERNAL: + case FDT_ERR_BADNCELLS: + case FDT_ERR_TOODEEP: + return -EINVAL; + } + return -EBADFD; +} + +int board_prepare_usb(enum usb_init_type type) +{ + static struct gpio_desc vbusen; + static int inited; + int ret; + + printf("Setting up USB port as %s\n", + type == USB_INIT_HOST ? "host" : + USB_INIT_DEVICE ? "device" : "invalid"); + if (type != USB_INIT_HOST && type != USB_INIT_DEVICE) + printf("Invalid USB type: %08x\n", type); + + if (!inited) { + int off = fdt_path_offset(gd->fdt_blob, "usbhost"); + + if (off < 0) { + printf("Could not find 'usbost' node: %s\n", + fdt_strerror(off)); + return -ENODEV; + } + ret = gpio_request_by_name_nodev(gd->fdt_blob, off, + "switch-gpio", 0, &vbusen, 0); + if (ret) { + printf("Failed to request VBUSEN GPIO: %d\n", ret); + return ret; + } + inited = 1; + } + + ret = dm_gpio_set_value(&vbusen, type == USB_INIT_HOST); + if (ret == 0) + ret = dm_gpio_set_dir_flags(&vbusen, GPIOD_IS_OUT); + if (ret == 0) + ret = dm_gpio_set_value(&vbusen, type == USB_INIT_HOST); + + return ret; +} + +static int karo_spmi_init(void) +{ + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev); + if (ret) + return ret; + + /* Configure PON_PS_HOLD_RESET_CTL for HARD reset */ + ret = spmi_reg_write(dev, 0, 8, 0x5a, 7); + return ret; +} + +/* Check for - if pressed - stop autoboot */ +int misc_init_r(void) +{ + unsigned long fdt_addr __maybe_unused = getenv_ulong("fdtaddr", 16, 0); + int ret; + + env_cleanup(); + + if (had_ctrlc()) { + setenv_ulong("safeboot", 1); + return 0; + } + setenv("safeboot", NULL); + + ret = karo_spmi_init(); + if (ret) + printf("Failed to initialize SPMI interface: %d\n", ret); + + karo_fdt_move_fdt(); + + if (getenv("usbethaddr") && !had_ctrlc()) { + uchar mac_addr[ETH_ALEN]; + + ret = usb_init(); + if (ret < 0) { + printf("USB init failed: %d\n", ret); + return 0; + } + if (eth_getenv_enetaddr("usbethaddr", mac_addr)) + printf("MAC address: %pM\n", mac_addr); + + } else { + printf("'usbethaddr' not set; skipping USB initialization\n"); + } + return 0; +} + +#ifdef CONFIG_QCOM_SMD_RPM +#define LDO(n, uV, en) uint32_t ldo##n[] = { \ + LDOA_RES_TYPE, n, KEY_SOFTWARE_ENABLE, 4, GENERIC_##en, \ + KEY_MICRO_VOLT, 4, uV, } + +static LDO(2, 1200000, ENABLE); // LPDDR +static LDO(3, 1150000, ENABLE); // VDD_MEM, PLL, USB +static LDO(5, 1800000, ENABLE); // LPDDR I/O +static LDO(7, 1800000, ENABLE); // WLAN OSC, PLL2, VDDA2, USBPHY +static LDO(8, 2900000, ENABLE); // eMMC +static LDO(15, 1800000, ENABLE); // Basisboard VDDIO + L16 +static LDO(16, 1800000, ENABLE); // Basisboard VDDIO + L15 (55mA) +static LDO(17, 3300000, ENABLE); // Basisboard VDD33 (450mA) + +static LDO(1, 1225000, DISABLE); // ext. Conn. +static LDO(6, 1800000, DISABLE); // MIPI + Temp Sens. +static LDO(9, 3300000, DISABLE); // WLAN +static LDO(11, 1900000, ENABLE); // JTAG, ext. Conn. OWIRE +static LDO(12, 2900000, ENABLE); // SD-Card +static LDO(13, 3075000, ENABLE); // USBPHY + +static LDO(4, 1800000, DISABLE); // NC +static LDO(10, 1000000, DISABLE); // NC +static LDO(14, 1000000, DISABLE); // NC +static LDO(18, 1000000, DISABLE); // NC + +#define _debug(fmt...) do {} while (0) + +static inline void __smd_regulator_control(uint32_t *data, size_t len, + const char *name) +{ + int ret; + + _debug("%s@%d: %sabling %s: %u.%03uV\n", __func__, __LINE__, + data[4] == GENERIC_ENABLE ? "En" : "Dis", name, + data[7] / 1000000, data[7] / 1000 % 1000); + ret = rpm_send_data(data, len, RPM_REQUEST_TYPE); + if (ret) + printf("Failed to configure regulator %s\n", name); + udelay(10000); +} + +#define smd_regulator_control(n) __smd_regulator_control(n, sizeof(n), #n) + +static void smd_pmic_setup(void) +{ + smd_rpm_init(); + + smd_regulator_control(ldo1); + smd_regulator_control(ldo2); + smd_regulator_control(ldo3); + smd_regulator_control(ldo4); + smd_regulator_control(ldo5); + smd_regulator_control(ldo6); + smd_regulator_control(ldo7); + smd_regulator_control(ldo8); + smd_regulator_control(ldo9); + smd_regulator_control(ldo10); + smd_regulator_control(ldo11); + smd_regulator_control(ldo12); + smd_regulator_control(ldo13); + smd_regulator_control(ldo14); + smd_regulator_control(ldo15); + smd_regulator_control(ldo16); + smd_regulator_control(ldo17); + smd_regulator_control(ldo18); + + /* turn off unused regulators */ + smd_regulator_control(ldo4); + smd_regulator_control(ldo10); + smd_regulator_control(ldo14); + smd_regulator_control(ldo18); + + /* enable all essential regulators */ + smd_regulator_control(ldo2); + smd_regulator_control(ldo3); + smd_regulator_control(ldo5); + smd_regulator_control(ldo7); + smd_regulator_control(ldo8); + smd_regulator_control(ldo15); + smd_regulator_control(ldo16); + smd_regulator_control(ldo17); + + /* setup optional regulators */ + smd_regulator_control(ldo1); + smd_regulator_control(ldo6); + smd_regulator_control(ldo9); + smd_regulator_control(ldo11); + smd_regulator_control(ldo12); + smd_regulator_control(ldo13); + + smd_rpm_uninit(); +} +#else +static inline void smd_pmic_setup(void) +{ +} +#endif + +int board_late_init(void) +{ + if (!getenv("safeboot") && !ctrlc()) + smd_pmic_setup(); + + clear_ctrlc(); + return 0; +} + +static const char *txsd_touchpanels[] = { + "edt,edt-ft5x06", + "eeti,egalax_ts", +}; + +int ft_board_setup(void *blob, bd_t *bd) +{ + int ret; + const char *video_mode = karo_get_vmode(getenv("video_mode")); + + ret = fdt_increase_size(blob, 4096); + if (ret) { + printf("Failed to increase FDT size: %s\n", fdt_strerror(ret)); + return ret; + } + karo_fdt_fixup_touchpanel(blob, txsd_touchpanels, + ARRAY_SIZE(txsd_touchpanels)); + karo_fdt_update_fb_mode(blob, video_mode); + smd_rpm_uninit(); + return 0; +} + +static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int ret; + struct udevice *dev; + + ret = uclass_get_device_by_name(UCLASS_SPMI, "spmi", &dev); + if (ret) { + printf("Failed to get SPMI bus: %d\n", ret); + return CMD_RET_FAILURE; + } + + ret = spmi_reg_write(dev, 0, 8, 0x8f, 8); + if (ret) + return CMD_RET_FAILURE; + + do_reset(NULL, 0, 0, NULL); + return CMD_RET_FAILURE; +} + +U_BOOT_CMD( + fastboot, 2, 1, do_fastboot, + "reboot into Fastboot protocol\n", + " - run as a fastboot usb device" +); diff --git a/board/karo/txsd/u-boot.lds b/board/karo/txsd/u-boot.lds new file mode 100644 index 0000000000..885e9731cb --- /dev/null +++ b/board/karo/txsd/u-boot.lds @@ -0,0 +1,90 @@ +/* + * Override linker script for fastboot-readable images + * + * (C) Copyright 2015 Mateusz Kulikowski + * + * Based on arch/arm/cpu/armv8/u-boot.lds (Just add header) + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(_arm64_header) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(8); + .text : + { + *(.__image_copy_start) + board/karo/txsd/head.o (.text*) + CPUDIR/start.o (.text*) + *(.text*) + } + + . = ALIGN(8); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(8); + .data : { + *(.data*) + } + + . = ALIGN(8); + + . = .; + + . = ALIGN(8); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(8); + + .image_copy_end : + { + *(.__image_copy_end) + } + + . = ALIGN(8); + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rela.dyn : { + *(.rela*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + _end = .; + + . = ALIGN(8); + + .bss_start : { + KEEP(*(.__bss_start)); + } + + .bss : { + *(.bss*) + . = ALIGN(8); + } + + .bss_end : { + KEEP(*(.__bss_end)); + } + + /DISCARD/ : { *(.dynsym) } + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } +} diff --git a/configs/txsd-410e_defconfig b/configs/txsd-410e_defconfig new file mode 100644 index 0000000000..5c8f74a597 --- /dev/null +++ b/configs/txsd-410e_defconfig @@ -0,0 +1,76 @@ +CONFIG_ARM=y +CONFIG_ARCH_SNAPDRAGON=y +CONFIG_TARGET_TXSD_410E=y +CONFIG_IDENT_STRING="\nKa-Ro electronics TXSD-410E" +CONFIG_DEFAULT_DEVICE_TREE="txsd-410e" +CONFIG_SD_BOOT=y +CONFIG_BOOTDELAY=3 +CONFIG_SYS_NO_FLASH=y +CONFIG_VERSION_VARIABLE=y +CONFIG_SYS_PROMPT="TXSD U-Boot > " +CONFIG_BLK=y +CONFIG_CLK=y +CONFIG_CMD_CPU=y # overridden by CONFIG_MP +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MMC=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_SMD=y +CONFIG_CMD_SPMI=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIMER=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +CONFIG_CPU=y +CONFIG_DEBUG_TIMER_WRAP=y +CONFIG_DEBUG_TIMER_WRAP_SECONDS=60 +# CONFIG_EFI_LOADER is not set +CONFIG_MSM_GPIO=y +CONFIG_PM8916_GPIO=y +CONFIG_DM_ETH=y +CONFIG_DM_I2C=y +CONFIG_DM_I2C_GPIO=y +CONFIG_DM_MMC=y +CONFIG_DM_MMC_OPS=y +CONFIG_DM_PMIC=y +CONFIG_DM_RTC=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_MSM_SDHCI=y +CONFIG_OF_BOARD_SETUP=y +CONFIG_OF_CONTROL=y +CONFIG_OF_SEPARATE=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +# CONFIG_REQUIRE_SERIAL_CONSOLE is not set +CONFIG_PMIC_PM8916=y +CONFIG_MSM_SERIAL=y +CONFIG_QCOM_SMD=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_SPMI_MSM=y +CONFIG_SYSRESET=y +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ULPI_VIEWPORT=y +CONFIG_USB_ULPI=y +CONFIG_USB_STORAGE=y +CONFIG_CONSOLE_ROTATION=y +CONFIG_VIDEO_BRIDGE=y +# CONFIG_REGEX is not set diff --git a/include/configs/txsd.h b/include/configs/txsd.h new file mode 100644 index 0000000000..81cdd9e5ef --- /dev/null +++ b/include/configs/txsd.h @@ -0,0 +1,182 @@ +/* + * Board configuration file for TXSD-410E + * + * (C) Copyright 2016 Lothar Waßmann + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIGS_TXSD_H +#define __CONFIGS_TXSD_H + +#include +#include + +#define CONFIG_ARMV8_PSCI +#define CONFIG_MISC_INIT_R +#define CONFIG_BOARD_LATE_INIT + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_TEXT_BASE 0x90080000 +#define CONFIG_SYS_SDRAM_BASE 0x90000000 +#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE +#define PHYS_SDRAM_1_SIZE (3 * SZ_256M) + +/* 986 MiB (the last 38MiB are secured for TrustZone by ATF */ +#define CONFIG_SYS_MEM_RESERVE_SECURE (38 * SZ_1M) +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_SDRAM_BASE + 0x7fff0) + +#define CONFIG_SYS_LOAD_ADDR _pfx(0x, CONFIG_LOADADDR) +#define CONFIG_SYS_FDT_ADDR _pfx(0x, CONFIG_FDTADDR) +#define CONFIG_SYS_RD_ADDR _pfx(0x, CONFIG_RDADDR) + +#define CONFIG_SYS_MEMTEST_START PHYS_SDRAM_1 +#define CONFIG_SYS_MEMTEST_END (PHYS_SDRAM_1 + SZ_512M) + +#define CONFIG_SYS_CACHELINE_SIZE 64 + +/* UART */ +#define CONFIG_BAUDRATE 115200 + +/* Generic Timer Definitions */ +#define COUNTER_FREQUENCY 19000000 + +/* This are needed to have proper mmc support */ +#define CONFIG_MMC +#define CONFIG_GENERIC_MMC +#define CONFIG_SDHCI + +#define CONFIG_SYS_LDSCRIPT "board/$(BOARDDIR)/u-boot.lds" + +/* + * Fixup - in init code we switch from device to host mode, + * it has to be done after each HCD reset + */ +#define CONFIG_EHCI_HCD_INIT_AFTER_RESET + +#define CONFIG_USB_HOST_ETHER /* Enable USB Networking */ + +/* Support all relevant USB ethernet dongles */ +#define CONFIG_USB_ETHER_DM9601 +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_ASIX88179 +#define CONFIG_USB_ETHER_MCS7830 +#define CONFIG_USB_ETHER_RTL8152 +#define CONFIG_USB_ETHER_SMSC95XX + +/* LCD Logo and Splash screen support */ +#define CONFIG_LCD + +#ifdef CONFIG_LCD +#define CONFIG_SYS_LVDS_IF +#define CONFIG_SPLASH_SCREEN +#define CONFIG_SPLASH_SCREEN_ALIGN + +#define CONFIG_LCD_LOGO +#define LCD_BPP LCD_COLOR32 +#define CONFIG_CMD_BMP +#define CONFIG_BMP_16BPP +#define CONFIG_BMP_24BPP +#define CONFIG_BMP_32BPP +#define CONFIG_VIDEO_BMP_RLE8 +#endif /* CONFIG_LCD */ + +/* Extra Commands */ +#define CONFIG_CMD_ENV +#define CONFIG_CMD_GPT +#define CONFIG_CMD_PART +#define CONFIG_CMD_TFTP +#define CONFIG_FAT_WRITE + +/* Enable that for switching of boot partitions */ +#define CONFIG_SUPPORT_EMMC_BOOT + +/* Partition table support */ +#define HAVE_BLOCK_DEVICE /* Needed for partition commands */ +#define CONFIG_PARTITION_UUIDS + +#define CONFIG_BOOTP_DNS +#define CONFIG_BOOTP_GATEWAY +#define CONFIG_BOOTP_SUBNETMASK + +#define CONFIG_CMDLINE_EDITING +#define CONFIG_AUTO_COMPLETE +#define CONFIG_SYS_LONGHELP +#define CONFIG_DOS_PARTITION +#define CONFIG_EFI_PARTITION +#define CONFIG_SUPPORT_RAW_INITRD +#define CONFIG_SHOW_ACTIVITY + +#define xstr(s) str(s) +#define str(s) #s +#define __pfx(x, s) (x##s) +#define _pfx(x, s) __pfx(x, s) + +/* BOOTP options */ +#define CONFIG_BOOTP_BOOTFILESIZE + +/* Environment - Boot*/ + +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 +#define EMMC_BOOT_ACK_STR "emmc_boot_ack=1\0" +#define EMMC_BOOT_PART_STR "emmc_boot_part=" \ + xstr(CONFIG_SYS_MMCSD_FS_BOOT_PARTITION) "\0" + +#define CONFIG_BOOTCOMMAND "run bootcmd_${boot_mode} bootm_cmd" +#define CONFIG_SYS_AUTOLOAD "no" + +/* Environment */ +#define CONFIG_EXTRA_ENV_SETTINGS \ + "autostart=no\0" \ + "baseboard=mb7\0" \ + "bootargs_mmc=run default_bootargs;setenv bootargs ${bootargs}" \ + " root=PARTUUID=${rootpart_uuid} rootwait\0" \ + "bootargs_nfs=run default_bootargs;setenv bootargs ${bootargs}" \ + " root=/dev/nfs nfsroot=${nfs_server}:${nfsroot},nolock" \ + " ip=dhcp\0" \ + "bootcmd_mmc=setenv autostart no;run bootargs_mmc" \ + ";load mmc ${bootpart} ${loadaddr} Image.gz\0" \ + "bootcmd_net=setenv autoload y;setenv autostart n" \ + ";run bootargs_nfs;dhcp\0" \ + "bootcmd_nfs=setenv autoload y;setenv autostart n" \ + ";run bootargs_nfs;load mmc ${bootpart} ${loadaddr} Image.gz\0" \ + "bootdelay=1\0" \ + "bootm_cmd=booti ${loadaddr} - ${fdtaddr}\0" \ + "boot_mode=mmc\0" \ + "bootpart=0:4\0" \ + "default_bootargs=setenv bootargs init=/linuxrc" \ + " console=ttyMSM0,115200n8 panic=1 ${append_bootargs}\0" \ + EMMC_BOOT_PART_STR \ + EMMC_BOOT_ACK_STR \ + "fdtaddr=" xstr(CONFIG_FDTADDR) "\0" \ + "fdtcontroladdr=" xstr(CONFIG_FDTADDR) "\0" \ + "fdtsave=fdt resize;setexpr fs ${fs} / 200" \ + ";mmc write ${fdtaddr} c22 ${fs}\0" \ + "fdt_high=0xffffffffffffffff\0" \ + "initrd_high=0xffffffffffffffff\0" \ + "nfsroot=/tftpboot/rootfs\0" \ + "otg_mode=device\0" \ + "rdaddr=" xstr(CONFIG_RDADDR) "\0" \ + "rootpart_uuid=7f63ea01-808e-ad2c-6a4b-8f386a2bd218\0" \ + "touchpanel=edt-ft5x06\0" \ + "video_mode=VGA\0" + +#define CONFIG_ENV_IS_IN_MMC +#define CONFIG_SYS_MMC_ENV_DEV 0 +#define CONFIG_SYS_MMC_ENV_PART 0x0 +#define CONFIG_ENV_VARS_UBOOT_CONFIG +#define CONFIG_ENV_OVERWRITE + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + SZ_64M) + +/* Monitor Command Prompt */ +#define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */ +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE +#define CONFIG_SYS_MAXARGS 64 /* max command args */ +#define CONFIG_CMDLINE_EDITING + +#endif /* __CONFIGS_TXSD_H */ diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index efa95f07ae..cec8783d67 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -3044,6 +3044,7 @@ CONFIG_MARVELL_GPIO CONFIG_MARVELL_MFP CONFIG_MASK_AER_AO CONFIG_MAX_DSP_CPUS +CONFIG_MAX_DTB_SIZE CONFIG_MAX_FPGA_DEVICES CONFIG_MAX_I2C_NUM CONFIG_MAX_MEM_MAPPED @@ -3806,6 +3807,7 @@ CONFIG_RANDOM_UUID CONFIG_RAPIDIO CONFIG_RBTREE CONFIG_RCAR_BOARD_STRING +CONFIG_RDADDR CONFIG_RD_LVL CONFIG_REALMODE_DEBUG CONFIG_RED_LED @@ -5090,6 +5092,8 @@ CONFIG_SYS_DSPI_CTAR4 CONFIG_SYS_DSPI_CTAR5 CONFIG_SYS_DSPI_CTAR6 CONFIG_SYS_DSPI_CTAR7 +CONFIG_SYS_DTB_OFFSET +CONFIG_SYS_DTB_PART_SIZE CONFIG_SYS_DTT_ADM1021 CONFIG_SYS_DTT_BUS_NUM CONFIG_SYS_DTT_HYSTERESIS @@ -6373,6 +6377,7 @@ CONFIG_SYS_LS_MC_FW_IN_NOR CONFIG_SYS_LS_PPA_FW_ADDR CONFIG_SYS_LS_PPA_FW_IN_XIP CONFIG_SYS_LS_PPA_FW_IN_xxx +CONFIG_SYS_LVDS_IF CONFIG_SYS_M41T11_BASE_YEAR CONFIG_SYS_M41T11_EXT_CENTURY_DATA CONFIG_SYS_MACB0_BASE @@ -7395,6 +7400,7 @@ CONFIG_SYS_RCAR_I2C3_BASE CONFIG_SYS_RCAR_I2C3_SPEED CONFIG_SYS_RCCR CONFIG_SYS_RCWH_PCIHOST +CONFIG_SYS_RD_ADDR CONFIG_SYS_READ_SPD CONFIG_SYS_REDUNDAND_ENVIRONMENT CONFIG_SYS_RELOC_MONITOR_BASE @@ -8268,6 +8274,7 @@ CONFIG_USE_TTY CONFIG_UTBIPAR_INIT_TBIPA CONFIG_U_BOOT_HDR_ADDR CONFIG_U_BOOT_HDR_SIZE +CONFIG_U_BOOT_IMG_SIZE CONFIG_U_QE CONFIG_V38B CONFIG_VAL