From 6f2d59cb7f16bf5bc169c87fe87de402d9fb8bf8 Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Fri, 14 Dec 2018 21:14:29 +0100 Subject: [PATCH 01/58] test: bootcount: add bootcount-uclass test Add a test for the bootcount uclass, which uses the RTC bootcount backend (i.e. drivers/bootcount/rtc.c is implictly also tested). Signed-off-by: Philipp Tomsich Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 6 ++++++ configs/sandbox_defconfig | 5 +++++ test/dm/Makefile | 1 + test/dm/bootcount.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 test/dm/bootcount.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 3790b4c5208..1d011ded7cc 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -315,6 +315,12 @@ }; }; + bootcount@0 { + compatible = "u-boot,bootcount-rtc"; + rtc = <&rtc_1>; + offset = <0x13>; + }; + adc@0 { compatible = "sandbox,adc"; vdd-supply = <&buck2>; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 90146f64cd1..78a684b5ec4 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -57,6 +57,7 @@ CONFIG_CMD_DNS=y CONFIG_CMD_LINK_LOCAL=y CONFIG_CMD_ETHSW=y CONFIG_CMD_BMP=y +CONFIG_CMD_BOOTCOUNT=y CONFIG_CMD_TIME=y CONFIG_CMD_TIMER=y CONFIG_CMD_SOUND=y @@ -86,6 +87,9 @@ CONFIG_ADC=y CONFIG_ADC_SANDBOX=y CONFIG_AXI=y CONFIG_AXI_SANDBOX=y +CONFIG_BOOTCOUNT_LIMIT=y +CONFIG_DM_BOOTCOUNT=y +CONFIG_DM_BOOTCOUNT_RTC=y CONFIG_CLK=y CONFIG_CPU=y CONFIG_DM_DEMO=y @@ -217,3 +221,4 @@ CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_UT_ENV=y +CONFIG_UT_OVERLAY=y diff --git a/test/dm/Makefile b/test/dm/Makefile index 7dc80be25e3..1b089960cbb 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -15,6 +15,7 @@ ifneq ($(CONFIG_SANDBOX),) obj-$(CONFIG_SOUND) += audio.o obj-$(CONFIG_BLK) += blk.o obj-$(CONFIG_BOARD) += board.o +obj-$(CONFIG_DM_BOOTCOUNT) += bootcount.o obj-$(CONFIG_CLK) += clk.o obj-$(CONFIG_DM_ETH) += eth.o obj-$(CONFIG_FIRMWARE) += firmware.o diff --git a/test/dm/bootcount.c b/test/dm/bootcount.c new file mode 100644 index 00000000000..0817b7d3ec1 --- /dev/null +++ b/test/dm/bootcount.c @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) 2018 Theobroma Systems Design und Consulting GmbH + */ + +#include +#include +#include +#include +#include +#include + +static int dm_test_bootcount(struct unit_test_state *uts) +{ + struct udevice *dev; + u32 val; + + ut_assertok(uclass_get_device(UCLASS_BOOTCOUNT, 0, &dev)); + ut_assertok(dm_bootcount_set(dev, 0)); + ut_assertok(dm_bootcount_get(dev, &val)); + ut_assert(val == 0); + ut_assertok(dm_bootcount_set(dev, 0xab)); + ut_assertok(dm_bootcount_get(dev, &val)); + ut_assert(val == 0xab); + + return 0; +} + +DM_TEST(dm_test_bootcount, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + From eddb7278d790ceaa4a0e8c578240f999f11737b7 Mon Sep 17 00:00:00 2001 From: Yan Liu Date: Mon, 17 Dec 2018 09:27:59 -0500 Subject: [PATCH 02/58] am57xx_evm_defconfig: Enable YMODEM support Enable CONFIG_SPL_YMODEM_SUPPORT to support UART boot Signed-off-by: Yan Liu Reviewed-by: Lokesh Vutla --- configs/am57xx_evm_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/am57xx_evm_defconfig b/configs/am57xx_evm_defconfig index 91293daee7e..51dedc6111c 100644 --- a/configs/am57xx_evm_defconfig +++ b/configs/am57xx_evm_defconfig @@ -25,6 +25,7 @@ CONFIG_SPL_DMA_SUPPORT=y # CONFIG_SPL_NAND_SUPPORT is not set CONFIG_SPL_OS_BOOT=y CONFIG_SPL_SPI_LOAD=y +CONFIG_SPL_YMODEM_SUPPORT=y CONFIG_CMD_SPL=y # CONFIG_CMD_FLASH is not set # CONFIG_CMD_SETEXPR is not set From 596be5f3274ff674f526b77f75064f0495aff693 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Mon, 17 Dec 2018 20:14:42 +0100 Subject: [PATCH 03/58] image: fix compiling without CMD_FDT Booting an image currently sets the environment variable "fdtaddr" by calling into 'cmd/fdt.c'. As a result, linking U-Boot fails if CMD_FDT is not enabled. Fix this by adding 'if (CONFIG_IS_ENABLED(CMD_FDT))' to the two places where 'set_working_fdt_addr()' is called. Signed-off-by: Simon Goldschmidt --- common/bootm.c | 3 ++- common/image-fdt.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/common/bootm.c b/common/bootm.c index 8bf84ebcb7e..80f304ce9f1 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -262,7 +262,8 @@ int bootm_find_images(int flag, int argc, char * const argv[]) puts("Could not find a valid device tree\n"); return 1; } - set_working_fdt_addr(map_to_sysmem(images.ft_addr)); + if (CONFIG_IS_ENABLED(CMD_FDT)) + set_working_fdt_addr(map_to_sysmem(images.ft_addr)); #endif #if IMAGE_ENABLE_FIT diff --git a/common/image-fdt.c b/common/image-fdt.c index 95748f0ae10..8ee5a13352c 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -193,7 +193,8 @@ int boot_relocate_fdt(struct lmb *lmb, char **of_flat_tree, ulong *of_size) *of_flat_tree = of_start; *of_size = of_len; - set_working_fdt_addr(map_to_sysmem(*of_flat_tree)); + if (CONFIG_IS_ENABLED(CMD_FDT)) + set_working_fdt_addr(map_to_sysmem(*of_flat_tree)); return 0; error: From e7ab6dfc65f3656bf0df9e818dc12ad33be26d44 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 18 Dec 2018 17:52:06 +0800 Subject: [PATCH 04/58] poplar: add DWC2 OTG gadget support It enables DWC2 OTG gadget driver support for Poplar board. As usb2_phy_init() is being always called from board_init(), we can save the call from board_usb_init(). Signed-off-by: Shawn Guo --- .../asm/arch-hi3798cv200/hi3798cv200.h | 5 ++++ board/hisilicon/poplar/poplar.c | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h index f97b1eb29f8..bb221e17e0e 100644 --- a/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h +++ b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h @@ -13,11 +13,16 @@ /* DEVICES */ #define REG_BASE_MCI 0xF9830000 #define REG_BASE_UART0 0xF8B00000 +#define HIOTG_BASE_ADDR 0xF98C0000 /* PERI control registers (4KB) */ /* USB2 PHY01 configuration register */ #define PERI_CTRL_USB0 (REG_BASE_PERI_CTRL + 0x120) + /* USB2 controller configuration register */ +#define PERI_CTRL_USB3 (REG_BASE_PERI_CTRL + 0x12c) +#define USB2_2P_CHIPID (1 << 28) + /* PERI CRG registers (4KB) */ /* USB2 CTRL0 clock and soft reset */ #define PERI_CRG46 (REG_BASE_CRG + 0xb8) diff --git a/board/hisilicon/poplar/poplar.c b/board/hisilicon/poplar/poplar.c index 8adc750962a..155dfbb401f 100644 --- a/board/hisilicon/poplar/poplar.c +++ b/board/hisilicon/poplar/poplar.c @@ -166,6 +166,34 @@ int board_mmc_init(bd_t *bis) return ret; } +#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG) +#include +#include +#include + +static struct dwc2_plat_otg_data poplar_otg_data = { + .regs_otg = HIOTG_BASE_ADDR +}; + +static void set_usb_to_device(void) +{ + setbits_le32(PERI_CTRL_USB3, USB2_2P_CHIPID); +} + +int board_usb_init(int index, enum usb_init_type init) +{ + set_usb_to_device(); + return dwc2_udc_probe(&poplar_otg_data); +} + +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name) +{ + if (!env_get("serial#")) + g_dnl_set_serialnumber("0123456789POPLAR"); + return 0; +} +#endif + int board_init(void) { usb2_phy_init(); From 37cbd8918c83c9b160e79c3b79f3521cd8f73537 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Tue, 18 Dec 2018 17:52:07 +0800 Subject: [PATCH 05/58] poplar_defconfig: enable fastboot support It enables fastboot support on Poplar board by using DWC2 OTG gadget driver. Signed-off-by: Shawn Guo --- configs/poplar_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/configs/poplar_defconfig b/configs/poplar_defconfig index 239783a5926..ea0ea892207 100644 --- a/configs/poplar_defconfig +++ b/configs/poplar_defconfig @@ -11,11 +11,22 @@ CONFIG_CMD_USB=y # CONFIG_ISO_PARTITION is not set CONFIG_DEFAULT_DEVICE_TREE="hi3798cv200-poplar" CONFIG_ENV_IS_IN_MMC=y +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT_BUF_ADDR=0x20000000 +CONFIG_FASTBOOT_BUF_SIZE=0x10000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 CONFIG_MMC_DW=y CONFIG_MMC_DW_K3=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="HiSilicon" +CONFIG_USB_GADGET_VENDOR_NUM=0x18d1 +CONFIG_USB_GADGET_PRODUCT_NUM=0xd00d +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_GADGET_DWC2_OTG_PHY_BUS_WIDTH_8=y CONFIG_USB_HOST_ETHER=y CONFIG_USB_ETHER_ASIX=y CONFIG_FAT_WRITE=y From 3e066bcaefb51adcf5c0594d42abe145f701dbeb Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:51 +0800 Subject: [PATCH 06/58] reset: MedaiTek: add reset controller driver for MediaTek SoCs This patch adds reset controller driver for MediaTek SoCs. Signed-off-by: Ryder Lee Signed-off-by: Weijie Gao --- arch/arm/include/asm/arch-mediatek/reset.h | 13 +++ drivers/reset/Kconfig | 7 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-mediatek.c | 102 +++++++++++++++++++++ include/dt-bindings/reset/mtk-reset.h | 18 ++++ 5 files changed, 141 insertions(+) create mode 100644 arch/arm/include/asm/arch-mediatek/reset.h create mode 100644 drivers/reset/reset-mediatek.c create mode 100644 include/dt-bindings/reset/mtk-reset.h diff --git a/arch/arm/include/asm/arch-mediatek/reset.h b/arch/arm/include/asm/arch-mediatek/reset.h new file mode 100644 index 00000000000..9704666d24e --- /dev/null +++ b/arch/arm/include/asm/arch-mediatek/reset.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 MediaTek Inc. + */ + +#ifndef __MEDIATEK_RESET_H +#define __MEDIATEK_RESET_H + +#include + +int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs); + +#endif /* __MEDIATEK_RESET_H */ diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 9c5208b7da5..3a6d61f440c 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -106,4 +106,11 @@ config RESET_SOCFPGA help Support for reset controller on SoCFPGA platform. +config RESET_MEDIATEK + bool "Reset controller driver for MediaTek SoCs" + depends on DM_RESET && ARCH_MEDIATEK && CLK + default y + help + Support for reset controller on MediaTek SoCs. + endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index f4520878b7c..8a4dcab8f64 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o obj-$(CONFIG_RESET_MESON) += reset-meson.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o +obj-$(CONFIG_RESET_MEDIATEK) += reset-mediatek.o diff --git a/drivers/reset/reset-mediatek.c b/drivers/reset/reset-mediatek.c new file mode 100644 index 00000000000..e3614e6e2ae --- /dev/null +++ b/drivers/reset/reset-mediatek.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 MediaTek Inc. + * + * Author: Ryder Lee + * Weijie Gao + */ + +#include +#include +#include +#include +#include +#include + +struct mediatek_reset_priv { + struct regmap *regmap; + u32 regofs; + u32 nr_resets; +}; + +static int mediatek_reset_request(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int mediatek_reset_free(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int mediatek_reset_assert(struct reset_ctl *reset_ctl) +{ + struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev); + int id = reset_ctl->id; + + if (id >= priv->nr_resets) + return -EINVAL; + + return regmap_update_bits(priv->regmap, + priv->regofs + ((id / 32) << 2), BIT(id % 32), BIT(id % 32)); +} + +static int mediatek_reset_deassert(struct reset_ctl *reset_ctl) +{ + struct mediatek_reset_priv *priv = dev_get_priv(reset_ctl->dev); + int id = reset_ctl->id; + + if (id >= priv->nr_resets) + return -EINVAL; + + return regmap_update_bits(priv->regmap, + priv->regofs + ((id / 32) << 2), BIT(id % 32), 0); +} + +struct reset_ops mediatek_reset_ops = { + .request = mediatek_reset_request, + .free = mediatek_reset_free, + .rst_assert = mediatek_reset_assert, + .rst_deassert = mediatek_reset_deassert, +}; + +static int mediatek_reset_probe(struct udevice *dev) +{ + struct mediatek_reset_priv *priv = dev_get_priv(dev); + + if (!priv->regofs && !priv->nr_resets) + return -EINVAL; + + priv->regmap = syscon_node_to_regmap(dev_ofnode(dev)); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + + return 0; +} + +int mediatek_reset_bind(struct udevice *pdev, u32 regofs, u32 num_regs) +{ + struct udevice *rst_dev; + struct mediatek_reset_priv *priv; + int ret; + + ret = device_bind_driver_to_node(pdev, "mediatek_reset", "reset", + dev_ofnode(pdev), &rst_dev); + if (ret) + return ret; + + priv = malloc(sizeof(struct mediatek_reset_priv)); + priv->regofs = regofs; + priv->nr_resets = num_regs * 32; + rst_dev->priv = priv; + + return 0; +} + +U_BOOT_DRIVER(mediatek_reset) = { + .name = "mediatek_reset", + .id = UCLASS_RESET, + .probe = mediatek_reset_probe, + .ops = &mediatek_reset_ops, + .priv_auto_alloc_size = sizeof(struct mediatek_reset_priv), +}; diff --git a/include/dt-bindings/reset/mtk-reset.h b/include/dt-bindings/reset/mtk-reset.h new file mode 100644 index 00000000000..5f0a74f280c --- /dev/null +++ b/include/dt-bindings/reset/mtk-reset.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 MediaTek Inc. + */ + +#ifndef _DT_BINDINGS_MTK_RESET_H_ +#define _DT_BINDINGS_MTK_RESET_H_ + +/* ETHSYS */ +#define ETHSYS_PPE_RST 31 +#define ETHSYS_EPHY_RST 24 +#define ETHSYS_GMAC_RST 23 +#define ETHSYS_ESW_RST 16 +#define ETHSYS_FE_RST 6 +#define ETHSYS_MCM_RST 2 +#define ETHSYS_SYS_RST 0 + +#endif /* _DT_BINDINGS_MTK_RESET_H_ */ From 2dca3cc2a9f3cd41e29076ba93f6e2684377e7d9 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:52 +0800 Subject: [PATCH 07/58] clk: MediaTek: bind ethsys reset controller The ethsys contains not only the clock gating controller, but also the reset controller for the whole ethernet subsystem and its components. This patch adds binding of the reset controller so that the ethernet node can have references on it. Signed-off-by: Weijie Gao --- drivers/clk/mediatek/clk-mt7623.c | 15 +++++++++++++++ drivers/clk/mediatek/clk-mt7629.c | 15 +++++++++++++++ drivers/clk/mediatek/clk-mtk.h | 2 ++ 3 files changed, 32 insertions(+) diff --git a/drivers/clk/mediatek/clk-mt7623.c b/drivers/clk/mediatek/clk-mt7623.c index c6b09d8e18d..87ad4f79ced 100644 --- a/drivers/clk/mediatek/clk-mt7623.c +++ b/drivers/clk/mediatek/clk-mt7623.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -782,6 +783,19 @@ static int mt7623_ethsys_probe(struct udevice *dev) return mtk_common_clk_gate_init(dev, &mt7623_clk_tree, eth_cgs); } +static int mt7623_ethsys_bind(struct udevice *dev) +{ + int ret = 0; + +#if CONFIG_IS_ENABLED(RESET_MEDIATEK) + ret = mediatek_reset_bind(dev, ETHSYS_RST_CTRL_OFS, 1); + if (ret) + debug("Warning: failed to bind ethsys reset controller\n"); +#endif + + return ret; +} + static const struct udevice_id mt7623_apmixed_compat[] = { { .compatible = "mediatek,mt7623-apmixedsys" }, { } @@ -865,6 +879,7 @@ U_BOOT_DRIVER(mtk_clk_ethsys) = { .id = UCLASS_CLK, .of_match = mt7623_ethsys_compat, .probe = mt7623_ethsys_probe, + .bind = mt7623_ethsys_bind, .priv_auto_alloc_size = sizeof(struct mtk_cg_priv), .ops = &mtk_clk_gate_ops, }; diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index 2601b6cf30d..6a9f60139c0 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -602,6 +603,19 @@ static int mt7629_ethsys_probe(struct udevice *dev) return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, eth_cgs); } +static int mt7629_ethsys_bind(struct udevice *dev) +{ + int ret = 0; + +#if CONFIG_IS_ENABLED(RESET_MEDIATEK) + ret = mediatek_reset_bind(dev, ETHSYS_RST_CTRL_OFS, 1); + if (ret) + debug("Warning: failed to bind ethsys reset controller\n"); +#endif + + return ret; +} + static int mt7629_sgmiisys_probe(struct udevice *dev) { return mtk_common_clk_gate_init(dev, &mt7629_clk_tree, sgmii_cgs); @@ -695,6 +709,7 @@ U_BOOT_DRIVER(mtk_clk_ethsys) = { .id = UCLASS_CLK, .of_match = mt7629_ethsys_compat, .probe = mt7629_ethsys_probe, + .bind = mt7629_ethsys_bind, .priv_auto_alloc_size = sizeof(struct mtk_cg_priv), .ops = &mtk_clk_gate_ops, }; diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 74152ed9c6e..7847388b2a1 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -23,6 +23,8 @@ #define CLK_PARENT_TOPCKGEN BIT(5) #define CLK_PARENT_MASK GENMASK(5, 4) +#define ETHSYS_RST_CTRL_OFS 0x34 + /* struct mtk_pll_data - hardware-specific PLLs data */ struct mtk_pll_data { const int id; From 23f17164d9ed6b92f7cd2064aa80f15da5489056 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:53 +0800 Subject: [PATCH 08/58] ethernet: MediaTek: add ethernet driver for MediaTek ARM-based SoCs This patch adds ethernet support for Mediatek ARM-based SoCs, including a minimum setup of the integrated switch. Cc: Joe Hershberger Signed-off-by: Mark Lee Signed-off-by: Weijie Gao Tested-By: "Frank Wunderlich" --- drivers/net/Kconfig | 10 + drivers/net/Makefile | 1 + drivers/net/mtk_eth.c | 1175 +++++++++++++++++++++++++++++++++++++++++ drivers/net/mtk_eth.h | 286 ++++++++++ 4 files changed, 1472 insertions(+) create mode 100644 drivers/net/mtk_eth.c create mode 100644 drivers/net/mtk_eth.h diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7044c6adf32..ff55e03d3fd 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -513,4 +513,14 @@ config TSEC_ENET This driver implements support for the (Enhanced) Three-Speed Ethernet Controller found on Freescale SoCs. +config MEDIATEK_ETH + bool "MediaTek Ethernet GMAC Driver" + depends on DM_ETH + select PHYLIB + select DM_GPIO + select DM_RESET + help + This Driver support MediaTek Ethernet GMAC + Say Y to enable support for the MediaTek Ethernet GMAC. + endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 0dbfa033068..ee7f3e71a8d 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -74,3 +74,4 @@ obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o obj-$(CONFIG_FSL_PFE) += pfe_eth/ obj-$(CONFIG_SNI_AVE) += sni_ave.o obj-y += ti/ +obj-$(CONFIG_MEDIATEK_ETH) += mtk_eth.o diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c new file mode 100644 index 00000000000..cc09404830a --- /dev/null +++ b/drivers/net/mtk_eth.c @@ -0,0 +1,1175 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 MediaTek Inc. + * + * Author: Weijie Gao + * Author: Mark Lee + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtk_eth.h" + +#define NUM_TX_DESC 24 +#define NUM_RX_DESC 24 +#define TX_TOTAL_BUF_SIZE (NUM_TX_DESC * PKTSIZE_ALIGN) +#define RX_TOTAL_BUF_SIZE (NUM_RX_DESC * PKTSIZE_ALIGN) +#define TOTAL_PKT_BUF_SIZE (TX_TOTAL_BUF_SIZE + RX_TOTAL_BUF_SIZE) + +#define MT7530_NUM_PHYS 5 +#define MT7530_DFL_SMI_ADDR 31 + +#define MT7530_PHY_ADDR(base, addr) \ + (((base) + (addr)) & 0x1f) + +#define GDMA_FWD_TO_CPU \ + (0x20000000 | \ + GDM_ICS_EN | \ + GDM_TCS_EN | \ + GDM_UCS_EN | \ + STRP_CRC | \ + (DP_PDMA << MYMAC_DP_S) | \ + (DP_PDMA << BC_DP_S) | \ + (DP_PDMA << MC_DP_S) | \ + (DP_PDMA << UN_DP_S)) + +#define GDMA_FWD_DISCARD \ + (0x20000000 | \ + GDM_ICS_EN | \ + GDM_TCS_EN | \ + GDM_UCS_EN | \ + STRP_CRC | \ + (DP_DISCARD << MYMAC_DP_S) | \ + (DP_DISCARD << BC_DP_S) | \ + (DP_DISCARD << MC_DP_S) | \ + (DP_DISCARD << UN_DP_S)) + +struct pdma_rxd_info1 { + u32 PDP0; +}; + +struct pdma_rxd_info2 { + u32 PLEN1 : 14; + u32 LS1 : 1; + u32 UN_USED : 1; + u32 PLEN0 : 14; + u32 LS0 : 1; + u32 DDONE : 1; +}; + +struct pdma_rxd_info3 { + u32 PDP1; +}; + +struct pdma_rxd_info4 { + u32 FOE_ENTRY : 14; + u32 CRSN : 5; + u32 SP : 3; + u32 L4F : 1; + u32 L4VLD : 1; + u32 TACK : 1; + u32 IP4F : 1; + u32 IP4 : 1; + u32 IP6 : 1; + u32 UN_USED : 4; +}; + +struct pdma_rxdesc { + struct pdma_rxd_info1 rxd_info1; + struct pdma_rxd_info2 rxd_info2; + struct pdma_rxd_info3 rxd_info3; + struct pdma_rxd_info4 rxd_info4; +}; + +struct pdma_txd_info1 { + u32 SDP0; +}; + +struct pdma_txd_info2 { + u32 SDL1 : 14; + u32 LS1 : 1; + u32 BURST : 1; + u32 SDL0 : 14; + u32 LS0 : 1; + u32 DDONE : 1; +}; + +struct pdma_txd_info3 { + u32 SDP1; +}; + +struct pdma_txd_info4 { + u32 VLAN_TAG : 16; + u32 INS : 1; + u32 RESV : 2; + u32 UDF : 6; + u32 FPORT : 3; + u32 TSO : 1; + u32 TUI_CO : 3; +}; + +struct pdma_txdesc { + struct pdma_txd_info1 txd_info1; + struct pdma_txd_info2 txd_info2; + struct pdma_txd_info3 txd_info3; + struct pdma_txd_info4 txd_info4; +}; + +enum mtk_switch { + SW_NONE, + SW_MT7530 +}; + +enum mtk_soc { + SOC_MT7623, + SOC_MT7629 +}; + +struct mtk_eth_priv { + char pkt_pool[TOTAL_PKT_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN); + + struct pdma_txdesc *tx_ring_noc; + struct pdma_rxdesc *rx_ring_noc; + + int rx_dma_owner_idx0; + int tx_cpu_owner_idx0; + + void __iomem *fe_base; + void __iomem *gmac_base; + void __iomem *ethsys_base; + + struct mii_dev *mdio_bus; + int (*mii_read)(struct mtk_eth_priv *priv, u8 phy, u8 reg); + int (*mii_write)(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 val); + int (*mmd_read)(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg); + int (*mmd_write)(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg, + u16 val); + + enum mtk_soc soc; + int gmac_id; + int force_mode; + int speed; + int duplex; + + struct phy_device *phydev; + int phy_interface; + int phy_addr; + + enum mtk_switch sw; + int (*switch_init)(struct mtk_eth_priv *priv); + u32 mt7530_smi_addr; + u32 mt7530_phy_base; + + struct gpio_desc rst_gpio; + int mcm; + + struct reset_ctl rst_fe; + struct reset_ctl rst_mcm; +}; + +static void mtk_pdma_write(struct mtk_eth_priv *priv, u32 reg, u32 val) +{ + writel(val, priv->fe_base + PDMA_BASE + reg); +} + +static void mtk_pdma_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, + u32 set) +{ + clrsetbits_le32(priv->fe_base + PDMA_BASE + reg, clr, set); +} + +static void mtk_gdma_write(struct mtk_eth_priv *priv, int no, u32 reg, + u32 val) +{ + u32 gdma_base; + + if (no == 1) + gdma_base = GDMA2_BASE; + else + gdma_base = GDMA1_BASE; + + writel(val, priv->fe_base + gdma_base + reg); +} + +static u32 mtk_gmac_read(struct mtk_eth_priv *priv, u32 reg) +{ + return readl(priv->gmac_base + reg); +} + +static void mtk_gmac_write(struct mtk_eth_priv *priv, u32 reg, u32 val) +{ + writel(val, priv->gmac_base + reg); +} + +static void mtk_gmac_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, u32 set) +{ + clrsetbits_le32(priv->gmac_base + reg, clr, set); +} + +static void mtk_ethsys_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, + u32 set) +{ + clrsetbits_le32(priv->ethsys_base + reg, clr, set); +} + +/* Direct MDIO clause 22/45 access via SoC */ +static int mtk_mii_rw(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data, + u32 cmd, u32 st) +{ + int ret; + u32 val; + + val = (st << MDIO_ST_S) | + ((cmd << MDIO_CMD_S) & MDIO_CMD_M) | + (((u32)phy << MDIO_PHY_ADDR_S) & MDIO_PHY_ADDR_M) | + (((u32)reg << MDIO_REG_ADDR_S) & MDIO_REG_ADDR_M); + + if (cmd == MDIO_CMD_WRITE) + val |= data & MDIO_RW_DATA_M; + + mtk_gmac_write(priv, GMAC_PIAC_REG, val | PHY_ACS_ST); + + ret = wait_for_bit_le32(priv->gmac_base + GMAC_PIAC_REG, + PHY_ACS_ST, 0, 5000, 0); + if (ret) { + pr_warn("MDIO access timeout\n"); + return ret; + } + + if (cmd == MDIO_CMD_READ) { + val = mtk_gmac_read(priv, GMAC_PIAC_REG); + return val & MDIO_RW_DATA_M; + } + + return 0; +} + +/* Direct MDIO clause 22 read via SoC */ +static int mtk_mii_read(struct mtk_eth_priv *priv, u8 phy, u8 reg) +{ + return mtk_mii_rw(priv, phy, reg, 0, MDIO_CMD_READ, MDIO_ST_C22); +} + +/* Direct MDIO clause 22 write via SoC */ +static int mtk_mii_write(struct mtk_eth_priv *priv, u8 phy, u8 reg, u16 data) +{ + return mtk_mii_rw(priv, phy, reg, data, MDIO_CMD_WRITE, MDIO_ST_C22); +} + +/* Direct MDIO clause 45 read via SoC */ +static int mtk_mmd_read(struct mtk_eth_priv *priv, u8 addr, u8 devad, u16 reg) +{ + int ret; + + ret = mtk_mii_rw(priv, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45); + if (ret) + return ret; + + return mtk_mii_rw(priv, addr, devad, 0, MDIO_CMD_READ_C45, + MDIO_ST_C45); +} + +/* Direct MDIO clause 45 write via SoC */ +static int mtk_mmd_write(struct mtk_eth_priv *priv, u8 addr, u8 devad, + u16 reg, u16 val) +{ + int ret; + + ret = mtk_mii_rw(priv, addr, devad, reg, MDIO_CMD_ADDR, MDIO_ST_C45); + if (ret) + return ret; + + return mtk_mii_rw(priv, addr, devad, val, MDIO_CMD_WRITE, + MDIO_ST_C45); +} + +/* Indirect MDIO clause 45 read via MII registers */ +static int mtk_mmd_ind_read(struct mtk_eth_priv *priv, u8 addr, u8 devad, + u16 reg) +{ + int ret; + + ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG, + (MMD_ADDR << MMD_CMD_S) | + ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); + if (ret) + return ret; + + ret = priv->mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, reg); + if (ret) + return ret; + + ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG, + (MMD_DATA << MMD_CMD_S) | + ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); + if (ret) + return ret; + + return priv->mii_read(priv, addr, MII_MMD_ADDR_DATA_REG); +} + +/* Indirect MDIO clause 45 write via MII registers */ +static int mtk_mmd_ind_write(struct mtk_eth_priv *priv, u8 addr, u8 devad, + u16 reg, u16 val) +{ + int ret; + + ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG, + (MMD_ADDR << MMD_CMD_S) | + ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); + if (ret) + return ret; + + ret = priv->mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, reg); + if (ret) + return ret; + + ret = priv->mii_write(priv, addr, MII_MMD_ACC_CTL_REG, + (MMD_DATA << MMD_CMD_S) | + ((devad << MMD_DEVAD_S) & MMD_DEVAD_M)); + if (ret) + return ret; + + return priv->mii_write(priv, addr, MII_MMD_ADDR_DATA_REG, val); +} + +static int mtk_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + struct mtk_eth_priv *priv = bus->priv; + + if (devad < 0) + return priv->mii_read(priv, addr, reg); + else + return priv->mmd_read(priv, addr, devad, reg); +} + +static int mtk_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + struct mtk_eth_priv *priv = bus->priv; + + if (devad < 0) + return priv->mii_write(priv, addr, reg, val); + else + return priv->mmd_write(priv, addr, devad, reg, val); +} + +static int mtk_mdio_register(struct udevice *dev) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + struct mii_dev *mdio_bus = mdio_alloc(); + int ret; + + if (!mdio_bus) + return -ENOMEM; + + /* Assign MDIO access APIs according to the switch/phy */ + switch (priv->sw) { + case SW_MT7530: + priv->mii_read = mtk_mii_read; + priv->mii_write = mtk_mii_write; + priv->mmd_read = mtk_mmd_ind_read; + priv->mmd_write = mtk_mmd_ind_write; + break; + default: + priv->mii_read = mtk_mii_read; + priv->mii_write = mtk_mii_write; + priv->mmd_read = mtk_mmd_read; + priv->mmd_write = mtk_mmd_write; + } + + mdio_bus->read = mtk_mdio_read; + mdio_bus->write = mtk_mdio_write; + snprintf(mdio_bus->name, sizeof(mdio_bus->name), dev->name); + + mdio_bus->priv = (void *)priv; + + ret = mdio_register(mdio_bus); + + if (ret) + return ret; + + priv->mdio_bus = mdio_bus; + + return 0; +} + +/* + * MT7530 Internal Register Address Bits + * ------------------------------------------------------------------- + * | 15 14 13 12 11 10 9 8 7 6 | 5 4 3 2 | 1 0 | + * |----------------------------------------|---------------|--------| + * | Page Address | Reg Address | Unused | + * ------------------------------------------------------------------- + */ + +static int mt7530_reg_read(struct mtk_eth_priv *priv, u32 reg, u32 *data) +{ + int ret, low_word, high_word; + + /* Write page address */ + ret = mtk_mii_write(priv, priv->mt7530_smi_addr, 0x1f, reg >> 6); + if (ret) + return ret; + + /* Read low word */ + low_word = mtk_mii_read(priv, priv->mt7530_smi_addr, (reg >> 2) & 0xf); + if (low_word < 0) + return low_word; + + /* Read high word */ + high_word = mtk_mii_read(priv, priv->mt7530_smi_addr, 0x10); + if (high_word < 0) + return high_word; + + if (data) + *data = ((u32)high_word << 16) | (low_word & 0xffff); + + return 0; +} + +static int mt7530_reg_write(struct mtk_eth_priv *priv, u32 reg, u32 data) +{ + int ret; + + /* Write page address */ + ret = mtk_mii_write(priv, priv->mt7530_smi_addr, 0x1f, reg >> 6); + if (ret) + return ret; + + /* Write low word */ + ret = mtk_mii_write(priv, priv->mt7530_smi_addr, (reg >> 2) & 0xf, + data & 0xffff); + if (ret) + return ret; + + /* Write high word */ + return mtk_mii_write(priv, priv->mt7530_smi_addr, 0x10, data >> 16); +} + +static void mt7530_reg_rmw(struct mtk_eth_priv *priv, u32 reg, u32 clr, + u32 set) +{ + u32 val; + + mt7530_reg_read(priv, reg, &val); + val &= ~clr; + val |= set; + mt7530_reg_write(priv, reg, val); +} + +static void mt7530_core_reg_write(struct mtk_eth_priv *priv, u32 reg, u32 val) +{ + u8 phy_addr = MT7530_PHY_ADDR(priv->mt7530_phy_base, 0); + + mtk_mmd_ind_write(priv, phy_addr, 0x1f, reg, val); +} + +static int mt7530_pad_clk_setup(struct mtk_eth_priv *priv, int mode) +{ + u32 ncpo1, ssc_delta; + + switch (mode) { + case PHY_INTERFACE_MODE_RGMII: + ncpo1 = 0x0c80; + ssc_delta = 0x87; + break; + default: + printf("error: xMII mode %d not supported\n", mode); + return -EINVAL; + } + + /* Disable MT7530 core clock */ + mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG, 0); + + /* Disable MT7530 PLL */ + mt7530_core_reg_write(priv, CORE_GSWPLL_GRP1, + (2 << RG_GSWPLL_POSDIV_200M_S) | + (32 << RG_GSWPLL_FBKDIV_200M_S)); + + /* For MT7530 core clock = 500Mhz */ + mt7530_core_reg_write(priv, CORE_GSWPLL_GRP2, + (1 << RG_GSWPLL_POSDIV_500M_S) | + (25 << RG_GSWPLL_FBKDIV_500M_S)); + + /* Enable MT7530 PLL */ + mt7530_core_reg_write(priv, CORE_GSWPLL_GRP1, + (2 << RG_GSWPLL_POSDIV_200M_S) | + (32 << RG_GSWPLL_FBKDIV_200M_S) | + RG_GSWPLL_EN_PRE); + + udelay(20); + + mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG, REG_GSWCK_EN); + + /* Setup the MT7530 TRGMII Tx Clock */ + mt7530_core_reg_write(priv, CORE_PLL_GROUP5, ncpo1); + mt7530_core_reg_write(priv, CORE_PLL_GROUP6, 0); + mt7530_core_reg_write(priv, CORE_PLL_GROUP10, ssc_delta); + mt7530_core_reg_write(priv, CORE_PLL_GROUP11, ssc_delta); + mt7530_core_reg_write(priv, CORE_PLL_GROUP4, RG_SYSPLL_DDSFBK_EN | + RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN); + + mt7530_core_reg_write(priv, CORE_PLL_GROUP2, + RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN | + (1 << RG_SYSPLL_POSDIV_S)); + + mt7530_core_reg_write(priv, CORE_PLL_GROUP7, + RG_LCDDS_PCW_NCPO_CHG | (3 << RG_LCCDS_C_S) | + RG_LCDDS_PWDB | RG_LCDDS_ISO_EN); + + /* Enable MT7530 core clock */ + mt7530_core_reg_write(priv, CORE_TRGMII_GSW_CLK_CG, + REG_GSWCK_EN | REG_TRGMIICK_EN); + + return 0; +} + +static int mt7530_setup(struct mtk_eth_priv *priv) +{ + u16 phy_addr, phy_val; + u32 val; + int i; + + /* Select 250MHz clk for RGMII mode */ + mtk_ethsys_rmw(priv, ETHSYS_CLKCFG0_REG, + ETHSYS_TRGMII_CLK_SEL362_5, 0); + + /* Global reset switch */ + if (priv->mcm) { + reset_assert(&priv->rst_mcm); + udelay(1000); + reset_deassert(&priv->rst_mcm); + mdelay(1000); + } else if (dm_gpio_is_valid(&priv->rst_gpio)) { + dm_gpio_set_value(&priv->rst_gpio, 0); + udelay(1000); + dm_gpio_set_value(&priv->rst_gpio, 1); + mdelay(1000); + } + + /* Modify HWTRAP first to allow direct access to internal PHYs */ + mt7530_reg_read(priv, HWTRAP_REG, &val); + val |= CHG_TRAP; + val &= ~C_MDIO_BPS; + mt7530_reg_write(priv, MHWTRAP_REG, val); + + /* Calculate the phy base address */ + val = ((val & SMI_ADDR_M) >> SMI_ADDR_S) << 3; + priv->mt7530_phy_base = (val | 0x7) + 1; + + /* Turn off PHYs */ + for (i = 0; i < MT7530_NUM_PHYS; i++) { + phy_addr = MT7530_PHY_ADDR(priv->mt7530_phy_base, i); + phy_val = priv->mii_read(priv, phy_addr, MII_BMCR); + phy_val |= BMCR_PDOWN; + priv->mii_write(priv, phy_addr, MII_BMCR, phy_val); + } + + /* Force MAC link down before reset */ + mt7530_reg_write(priv, PCMR_REG(5), FORCE_MODE); + mt7530_reg_write(priv, PCMR_REG(6), FORCE_MODE); + + /* MT7530 reset */ + mt7530_reg_write(priv, SYS_CTRL_REG, SW_SYS_RST | SW_REG_RST); + udelay(100); + + val = (1 << IPG_CFG_S) | + MAC_MODE | FORCE_MODE | + MAC_TX_EN | MAC_RX_EN | + BKOFF_EN | BACKPR_EN | + (SPEED_1000M << FORCE_SPD_S) | + FORCE_DPX | FORCE_LINK; + + /* MT7530 Port6: Forced 1000M/FD, FC disabled */ + mt7530_reg_write(priv, PCMR_REG(6), val); + + /* MT7530 Port5: Forced link down */ + mt7530_reg_write(priv, PCMR_REG(5), FORCE_MODE); + + /* MT7530 Port6: Set to RGMII */ + mt7530_reg_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_M, P6_INTF_MODE_RGMII); + + /* Hardware Trap: Enable Port6, Disable Port5 */ + mt7530_reg_read(priv, HWTRAP_REG, &val); + val |= CHG_TRAP | LOOPDET_DIS | P5_INTF_DIS | + (P5_INTF_SEL_GMAC5 << P5_INTF_SEL_S) | + (P5_INTF_MODE_RGMII << P5_INTF_MODE_S); + val &= ~(C_MDIO_BPS | P6_INTF_DIS); + mt7530_reg_write(priv, MHWTRAP_REG, val); + + /* Setup switch core pll */ + mt7530_pad_clk_setup(priv, priv->phy_interface); + + /* Lower Tx Driving for TRGMII path */ + for (i = 0 ; i < NUM_TRGMII_CTRL ; i++) + mt7530_reg_write(priv, MT7530_TRGMII_TD_ODT(i), + (8 << TD_DM_DRVP_S) | (8 << TD_DM_DRVN_S)); + + for (i = 0 ; i < NUM_TRGMII_CTRL; i++) + mt7530_reg_rmw(priv, MT7530_TRGMII_RD(i), RD_TAP_M, 16); + + /* Turn on PHYs */ + for (i = 0; i < MT7530_NUM_PHYS; i++) { + phy_addr = MT7530_PHY_ADDR(priv->mt7530_phy_base, i); + phy_val = priv->mii_read(priv, phy_addr, MII_BMCR); + phy_val &= ~BMCR_PDOWN; + priv->mii_write(priv, phy_addr, MII_BMCR, phy_val); + } + + /* Set port isolation */ + for (i = 0; i < 8; i++) { + /* Set port matrix mode */ + if (i != 6) + mt7530_reg_write(priv, PCR_REG(i), + (0x40 << PORT_MATRIX_S)); + else + mt7530_reg_write(priv, PCR_REG(i), + (0x3f << PORT_MATRIX_S)); + + /* Set port mode to user port */ + mt7530_reg_write(priv, PVC_REG(i), + (0x8100 << STAG_VPID_S) | + (VLAN_ATTR_USER << VLAN_ATTR_S)); + } + + return 0; +} + +static void mtk_phy_link_adjust(struct mtk_eth_priv *priv) +{ + u16 lcl_adv = 0, rmt_adv = 0; + u8 flowctrl; + u32 mcr; + + mcr = (1 << IPG_CFG_S) | + (MAC_RX_PKT_LEN_1536 << MAC_RX_PKT_LEN_S) | + MAC_MODE | FORCE_MODE | + MAC_TX_EN | MAC_RX_EN | + BKOFF_EN | BACKPR_EN; + + switch (priv->phydev->speed) { + case SPEED_10: + mcr |= (SPEED_10M << FORCE_SPD_S); + break; + case SPEED_100: + mcr |= (SPEED_100M << FORCE_SPD_S); + break; + case SPEED_1000: + mcr |= (SPEED_1000M << FORCE_SPD_S); + break; + }; + + if (priv->phydev->link) + mcr |= FORCE_LINK; + + if (priv->phydev->duplex) { + mcr |= FORCE_DPX; + + if (priv->phydev->pause) + rmt_adv = LPA_PAUSE_CAP; + if (priv->phydev->asym_pause) + rmt_adv |= LPA_PAUSE_ASYM; + + if (priv->phydev->advertising & ADVERTISED_Pause) + lcl_adv |= ADVERTISE_PAUSE_CAP; + if (priv->phydev->advertising & ADVERTISED_Asym_Pause) + lcl_adv |= ADVERTISE_PAUSE_ASYM; + + flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv); + + if (flowctrl & FLOW_CTRL_TX) + mcr |= FORCE_TX_FC; + if (flowctrl & FLOW_CTRL_RX) + mcr |= FORCE_RX_FC; + + debug("rx pause %s, tx pause %s\n", + flowctrl & FLOW_CTRL_RX ? "enabled" : "disabled", + flowctrl & FLOW_CTRL_TX ? "enabled" : "disabled"); + } + + mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr); +} + +static int mtk_phy_start(struct mtk_eth_priv *priv) +{ + struct phy_device *phydev = priv->phydev; + int ret; + + ret = phy_startup(phydev); + + if (ret) { + debug("Could not initialize PHY %s\n", phydev->dev->name); + return ret; + } + + if (!phydev->link) { + debug("%s: link down.\n", phydev->dev->name); + return 0; + } + + mtk_phy_link_adjust(priv); + + debug("Speed: %d, %s duplex%s\n", phydev->speed, + (phydev->duplex) ? "full" : "half", + (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); + + return 0; +} + +static int mtk_phy_probe(struct udevice *dev) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + struct phy_device *phydev; + + phydev = phy_connect(priv->mdio_bus, priv->phy_addr, dev, + priv->phy_interface); + if (!phydev) + return -ENODEV; + + phydev->supported &= PHY_GBIT_FEATURES; + phydev->advertising = phydev->supported; + + priv->phydev = phydev; + phy_config(phydev); + + return 0; +} + +static void mtk_mac_init(struct mtk_eth_priv *priv) +{ + int i, ge_mode = 0; + u32 mcr; + + switch (priv->phy_interface) { + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_SGMII: + ge_mode = GE_MODE_RGMII; + break; + case PHY_INTERFACE_MODE_MII: + case PHY_INTERFACE_MODE_GMII: + ge_mode = GE_MODE_MII; + break; + case PHY_INTERFACE_MODE_RMII: + ge_mode = GE_MODE_RMII; + break; + default: + break; + } + + /* set the gmac to the right mode */ + mtk_ethsys_rmw(priv, ETHSYS_SYSCFG0_REG, + SYSCFG0_GE_MODE_M << SYSCFG0_GE_MODE_S(priv->gmac_id), + ge_mode << SYSCFG0_GE_MODE_S(priv->gmac_id)); + + if (priv->force_mode) { + mcr = (1 << IPG_CFG_S) | + (MAC_RX_PKT_LEN_1536 << MAC_RX_PKT_LEN_S) | + MAC_MODE | FORCE_MODE | + MAC_TX_EN | MAC_RX_EN | + BKOFF_EN | BACKPR_EN | + FORCE_LINK; + + switch (priv->speed) { + case SPEED_10: + mcr |= SPEED_10M << FORCE_SPD_S; + break; + case SPEED_100: + mcr |= SPEED_100M << FORCE_SPD_S; + break; + case SPEED_1000: + mcr |= SPEED_1000M << FORCE_SPD_S; + break; + } + + if (priv->duplex) + mcr |= FORCE_DPX; + + mtk_gmac_write(priv, GMAC_PORT_MCR(priv->gmac_id), mcr); + } + + if (priv->soc == SOC_MT7623) { + /* Lower Tx Driving for TRGMII path */ + for (i = 0 ; i < NUM_TRGMII_CTRL; i++) + mtk_gmac_write(priv, GMAC_TRGMII_TD_ODT(i), + (8 << TD_DM_DRVP_S) | + (8 << TD_DM_DRVN_S)); + + mtk_gmac_rmw(priv, GMAC_TRGMII_RCK_CTRL, 0, + RX_RST | RXC_DQSISEL); + mtk_gmac_rmw(priv, GMAC_TRGMII_RCK_CTRL, RX_RST, 0); + } +} + +static void mtk_eth_fifo_init(struct mtk_eth_priv *priv) +{ + char *pkt_base = priv->pkt_pool; + int i; + + mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0xffff0000, 0); + udelay(500); + + memset(priv->tx_ring_noc, 0, NUM_TX_DESC * sizeof(struct pdma_txdesc)); + memset(priv->rx_ring_noc, 0, NUM_RX_DESC * sizeof(struct pdma_rxdesc)); + memset(priv->pkt_pool, 0, TOTAL_PKT_BUF_SIZE); + + flush_dcache_range((u32)pkt_base, (u32)(pkt_base + TOTAL_PKT_BUF_SIZE)); + + priv->rx_dma_owner_idx0 = 0; + priv->tx_cpu_owner_idx0 = 0; + + for (i = 0; i < NUM_TX_DESC; i++) { + priv->tx_ring_noc[i].txd_info2.LS0 = 1; + priv->tx_ring_noc[i].txd_info2.DDONE = 1; + priv->tx_ring_noc[i].txd_info4.FPORT = priv->gmac_id + 1; + + priv->tx_ring_noc[i].txd_info1.SDP0 = virt_to_phys(pkt_base); + pkt_base += PKTSIZE_ALIGN; + } + + for (i = 0; i < NUM_RX_DESC; i++) { + priv->rx_ring_noc[i].rxd_info2.PLEN0 = PKTSIZE_ALIGN; + priv->rx_ring_noc[i].rxd_info1.PDP0 = virt_to_phys(pkt_base); + pkt_base += PKTSIZE_ALIGN; + } + + mtk_pdma_write(priv, TX_BASE_PTR_REG(0), + virt_to_phys(priv->tx_ring_noc)); + mtk_pdma_write(priv, TX_MAX_CNT_REG(0), NUM_TX_DESC); + mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0); + + mtk_pdma_write(priv, RX_BASE_PTR_REG(0), + virt_to_phys(priv->rx_ring_noc)); + mtk_pdma_write(priv, RX_MAX_CNT_REG(0), NUM_RX_DESC); + mtk_pdma_write(priv, RX_CRX_IDX_REG(0), NUM_RX_DESC - 1); + + mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0); +} + +static int mtk_eth_start(struct udevice *dev) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + int ret; + + /* Reset FE */ + reset_assert(&priv->rst_fe); + udelay(1000); + reset_deassert(&priv->rst_fe); + mdelay(10); + + /* Packets forward to PDMA */ + mtk_gdma_write(priv, priv->gmac_id, GDMA_IG_CTRL_REG, GDMA_FWD_TO_CPU); + + if (priv->gmac_id == 0) + mtk_gdma_write(priv, 1, GDMA_IG_CTRL_REG, GDMA_FWD_DISCARD); + else + mtk_gdma_write(priv, 0, GDMA_IG_CTRL_REG, GDMA_FWD_DISCARD); + + udelay(500); + + mtk_eth_fifo_init(priv); + + /* Start PHY */ + if (priv->sw == SW_NONE) { + ret = mtk_phy_start(priv); + if (ret) + return ret; + } + + mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, 0, + TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN); + udelay(500); + + return 0; +} + +static void mtk_eth_stop(struct udevice *dev) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + + mtk_pdma_rmw(priv, PDMA_GLO_CFG_REG, + TX_WB_DDONE | RX_DMA_EN | TX_DMA_EN, 0); + udelay(500); + + wait_for_bit_le32(priv->fe_base + PDMA_BASE + PDMA_GLO_CFG_REG, + RX_DMA_BUSY | TX_DMA_BUSY, 0, 5000, 0); +} + +static int mtk_eth_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mtk_eth_priv *priv = dev_get_priv(dev); + unsigned char *mac = pdata->enetaddr; + u32 macaddr_lsb, macaddr_msb; + + macaddr_msb = ((u32)mac[0] << 8) | (u32)mac[1]; + macaddr_lsb = ((u32)mac[2] << 24) | ((u32)mac[3] << 16) | + ((u32)mac[4] << 8) | (u32)mac[5]; + + mtk_gdma_write(priv, priv->gmac_id, GDMA_MAC_MSB_REG, macaddr_msb); + mtk_gdma_write(priv, priv->gmac_id, GDMA_MAC_LSB_REG, macaddr_lsb); + + return 0; +} + +static int mtk_eth_send(struct udevice *dev, void *packet, int length) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->tx_cpu_owner_idx0; + void *pkt_base; + + if (!priv->tx_ring_noc[idx].txd_info2.DDONE) { + debug("mtk-eth: TX DMA descriptor ring is full\n"); + return -EPERM; + } + + pkt_base = (void *)phys_to_virt(priv->tx_ring_noc[idx].txd_info1.SDP0); + memcpy(pkt_base, packet, length); + flush_dcache_range((u32)pkt_base, (u32)pkt_base + + roundup(length, ARCH_DMA_MINALIGN)); + + priv->tx_ring_noc[idx].txd_info2.SDL0 = length; + priv->tx_ring_noc[idx].txd_info2.DDONE = 0; + + priv->tx_cpu_owner_idx0 = (priv->tx_cpu_owner_idx0 + 1) % NUM_TX_DESC; + mtk_pdma_write(priv, TX_CTX_IDX_REG(0), priv->tx_cpu_owner_idx0); + + return 0; +} + +static int mtk_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->rx_dma_owner_idx0; + uchar *pkt_base; + u32 length; + + if (!priv->rx_ring_noc[idx].rxd_info2.DDONE) { + debug("mtk-eth: RX DMA descriptor ring is empty\n"); + return -EAGAIN; + } + + length = priv->rx_ring_noc[idx].rxd_info2.PLEN0; + pkt_base = (void *)phys_to_virt(priv->rx_ring_noc[idx].rxd_info1.PDP0); + invalidate_dcache_range((u32)pkt_base, (u32)pkt_base + + roundup(length, ARCH_DMA_MINALIGN)); + + if (packetp) + *packetp = pkt_base; + + return length; +} + +static int mtk_eth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 idx = priv->rx_dma_owner_idx0; + + priv->rx_ring_noc[idx].rxd_info2.DDONE = 0; + priv->rx_ring_noc[idx].rxd_info2.LS0 = 0; + priv->rx_ring_noc[idx].rxd_info2.PLEN0 = PKTSIZE_ALIGN; + + mtk_pdma_write(priv, RX_CRX_IDX_REG(0), idx); + priv->rx_dma_owner_idx0 = (priv->rx_dma_owner_idx0 + 1) % NUM_RX_DESC; + + return 0; +} + +static int mtk_eth_probe(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mtk_eth_priv *priv = dev_get_priv(dev); + u32 iobase = pdata->iobase; + int ret; + + /* Frame Engine Register Base */ + priv->fe_base = (void *)iobase; + + /* GMAC Register Base */ + priv->gmac_base = (void *)(iobase + GMAC_BASE); + + /* MDIO register */ + ret = mtk_mdio_register(dev); + if (ret) + return ret; + + /* Prepare for tx/rx rings */ + priv->tx_ring_noc = (struct pdma_txdesc *) + noncached_alloc(sizeof(struct pdma_txdesc) * NUM_TX_DESC, + ARCH_DMA_MINALIGN); + priv->rx_ring_noc = (struct pdma_rxdesc *) + noncached_alloc(sizeof(struct pdma_rxdesc) * NUM_RX_DESC, + ARCH_DMA_MINALIGN); + + /* Set MAC mode */ + mtk_mac_init(priv); + + /* Probe phy if switch is not specified */ + if (priv->sw == SW_NONE) + return mtk_phy_probe(dev); + + /* Initialize switch */ + return priv->switch_init(priv); +} + +static int mtk_eth_remove(struct udevice *dev) +{ + struct mtk_eth_priv *priv = dev_get_priv(dev); + + /* MDIO unregister */ + mdio_unregister(priv->mdio_bus); + mdio_free(priv->mdio_bus); + + /* Stop possibly started DMA */ + mtk_eth_stop(dev); + + return 0; +} + +static int mtk_eth_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct mtk_eth_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + struct regmap *regmap; + const char *str; + ofnode subnode; + int ret; + + priv->soc = dev_get_driver_data(dev); + + pdata->iobase = devfdt_get_addr(dev); + + /* get corresponding ethsys phandle */ + ret = dev_read_phandle_with_args(dev, "mediatek,ethsys", NULL, 0, 0, + &args); + if (ret) + return ret; + + regmap = syscon_node_to_regmap(args.node); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + priv->ethsys_base = regmap_get_range(regmap, 0); + if (!priv->ethsys_base) { + dev_err(dev, "Unable to find ethsys\n"); + return -ENODEV; + } + + /* Reset controllers */ + ret = reset_get_by_name(dev, "fe", &priv->rst_fe); + if (ret) { + printf("error: Unable to get reset ctrl for frame engine\n"); + return ret; + } + + priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0); + + /* Interface mode is required */ + str = dev_read_string(dev, "phy-mode"); + if (str) { + pdata->phy_interface = phy_get_interface_by_name(str); + priv->phy_interface = pdata->phy_interface; + } else { + printf("error: phy-mode is not set\n"); + return -EINVAL; + } + + /* Force mode or autoneg */ + subnode = ofnode_find_subnode(dev_ofnode(dev), "fixed-link"); + if (ofnode_valid(subnode)) { + priv->force_mode = 1; + priv->speed = ofnode_read_u32_default(subnode, "speed", 0); + priv->duplex = ofnode_read_bool(subnode, "full-duplex"); + + if (priv->speed != SPEED_10 && priv->speed != SPEED_100 && + priv->speed != SPEED_1000) { + printf("error: no valid speed set in fixed-link\n"); + return -EINVAL; + } + } + + /* check for switch first, otherwise phy will be used */ + priv->sw = SW_NONE; + priv->switch_init = NULL; + str = dev_read_string(dev, "mediatek,switch"); + + if (str) { + if (!strcmp(str, "mt7530")) { + priv->sw = SW_MT7530; + priv->switch_init = mt7530_setup; + priv->mt7530_smi_addr = MT7530_DFL_SMI_ADDR; + } else { + printf("error: unsupported switch\n"); + return -EINVAL; + } + + priv->mcm = dev_read_bool(dev, "mediatek,mcm"); + if (priv->mcm) { + ret = reset_get_by_name(dev, "mcm", &priv->rst_mcm); + if (ret) { + printf("error: no reset ctrl for mcm\n"); + return ret; + } + } else { + gpio_request_by_name(dev, "reset-gpios", 0, + &priv->rst_gpio, GPIOD_IS_OUT); + } + } else { + subnode = ofnode_find_subnode(dev_ofnode(dev), "phy-handle"); + if (!ofnode_valid(subnode)) { + printf("error: phy-handle is not specified\n"); + return ret; + } + + priv->phy_addr = ofnode_read_s32_default(subnode, "reg", -1); + if (priv->phy_addr < 0) { + printf("error: phy address is not specified\n"); + return ret; + } + } + + return 0; +} + +static const struct udevice_id mtk_eth_ids[] = { + { .compatible = "mediatek,mt7629-eth", .data = SOC_MT7629 }, + { .compatible = "mediatek,mt7623-eth", .data = SOC_MT7623 }, + {} +}; + +static const struct eth_ops mtk_eth_ops = { + .start = mtk_eth_start, + .stop = mtk_eth_stop, + .send = mtk_eth_send, + .recv = mtk_eth_recv, + .free_pkt = mtk_eth_free_pkt, + .write_hwaddr = mtk_eth_write_hwaddr, +}; + +U_BOOT_DRIVER(mtk_eth) = { + .name = "mtk-eth", + .id = UCLASS_ETH, + .of_match = mtk_eth_ids, + .ofdata_to_platdata = mtk_eth_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .probe = mtk_eth_probe, + .remove = mtk_eth_remove, + .ops = &mtk_eth_ops, + .priv_auto_alloc_size = sizeof(struct mtk_eth_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h new file mode 100644 index 00000000000..fe89a03739f --- /dev/null +++ b/drivers/net/mtk_eth.h @@ -0,0 +1,286 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018 MediaTek Inc. + * + * Author: Weijie Gao + * Author: Mark Lee + */ + +#ifndef _MTK_ETH_H_ +#define _MTK_ETH_H_ + +/* Frame Engine Register Bases */ +#define PDMA_BASE 0x0800 +#define GDMA1_BASE 0x0500 +#define GDMA2_BASE 0x1500 +#define GMAC_BASE 0x10000 + +/* Ethernet subsystem registers */ + +#define ETHSYS_SYSCFG0_REG 0x14 +#define SYSCFG0_GE_MODE_S(n) (12 + ((n) * 2)) +#define SYSCFG0_GE_MODE_M 0x3 + +#define ETHSYS_CLKCFG0_REG 0x2c +#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11) + +/* SYSCFG0_GE_MODE: GE Modes */ +#define GE_MODE_RGMII 0 +#define GE_MODE_MII 1 +#define GE_MODE_MII_PHY 2 +#define GE_MODE_RMII 3 + +/* Frame Engine Registers */ + +/* PDMA */ +#define TX_BASE_PTR_REG(n) (0x000 + (n) * 0x10) +#define TX_MAX_CNT_REG(n) (0x004 + (n) * 0x10) +#define TX_CTX_IDX_REG(n) (0x008 + (n) * 0x10) +#define TX_DTX_IDX_REG(n) (0x00c + (n) * 0x10) + +#define RX_BASE_PTR_REG(n) (0x100 + (n) * 0x10) +#define RX_MAX_CNT_REG(n) (0x104 + (n) * 0x10) +#define RX_CRX_IDX_REG(n) (0x108 + (n) * 0x10) +#define RX_DRX_IDX_REG(n) (0x10c + (n) * 0x10) + +#define PDMA_GLO_CFG_REG 0x204 +#define TX_WB_DDONE BIT(6) +#define RX_DMA_BUSY BIT(3) +#define RX_DMA_EN BIT(2) +#define TX_DMA_BUSY BIT(1) +#define TX_DMA_EN BIT(0) + +#define PDMA_RST_IDX_REG 0x208 +#define RST_DRX_IDX0 BIT(16) +#define RST_DTX_IDX0 BIT(0) + +/* GDMA */ +#define GDMA_IG_CTRL_REG 0x000 +#define GDM_ICS_EN BIT(22) +#define GDM_TCS_EN BIT(21) +#define GDM_UCS_EN BIT(20) +#define STRP_CRC BIT(16) +#define MYMAC_DP_S 12 +#define MYMAC_DP_M 0xf000 +#define BC_DP_S 8 +#define BC_DP_M 0xf00 +#define MC_DP_S 4 +#define MC_DP_M 0xf0 +#define UN_DP_S 0 +#define UN_DP_M 0x0f + +#define GDMA_MAC_LSB_REG 0x008 + +#define GDMA_MAC_MSB_REG 0x00c + +/* MYMAC_DP/BC_DP/MC_DP/UN_DP: Destination ports */ +#define DP_PDMA 0 +#define DP_GDMA1 1 +#define DP_GDMA2 2 +#define DP_PPE 4 +#define DP_QDMA 5 +#define DP_DISCARD 7 + +/* GMAC Registers */ + +#define GMAC_PIAC_REG 0x0004 +#define PHY_ACS_ST BIT(31) +#define MDIO_REG_ADDR_S 25 +#define MDIO_REG_ADDR_M 0x3e000000 +#define MDIO_PHY_ADDR_S 20 +#define MDIO_PHY_ADDR_M 0x1f00000 +#define MDIO_CMD_S 18 +#define MDIO_CMD_M 0xc0000 +#define MDIO_ST_S 16 +#define MDIO_ST_M 0x30000 +#define MDIO_RW_DATA_S 0 +#define MDIO_RW_DATA_M 0xffff + +/* MDIO_CMD: MDIO commands */ +#define MDIO_CMD_ADDR 0 +#define MDIO_CMD_WRITE 1 +#define MDIO_CMD_READ 2 +#define MDIO_CMD_READ_C45 3 + +/* MDIO_ST: MDIO start field */ +#define MDIO_ST_C45 0 +#define MDIO_ST_C22 1 + +#define GMAC_PORT_MCR(p) (0x0100 + (p) * 0x100) +#define MAC_RX_PKT_LEN_S 24 +#define MAC_RX_PKT_LEN_M 0x3000000 +#define IPG_CFG_S 18 +#define IPG_CFG_M 0xc0000 +#define MAC_MODE BIT(16) +#define FORCE_MODE BIT(15) +#define MAC_TX_EN BIT(14) +#define MAC_RX_EN BIT(13) +#define BKOFF_EN BIT(9) +#define BACKPR_EN BIT(8) +#define FORCE_RX_FC BIT(5) +#define FORCE_TX_FC BIT(4) +#define FORCE_SPD_S 2 +#define FORCE_SPD_M 0x0c +#define FORCE_DPX BIT(1) +#define FORCE_LINK BIT(0) + +/* MAC_RX_PKT_LEN: Max RX packet length */ +#define MAC_RX_PKT_LEN_1518 0 +#define MAC_RX_PKT_LEN_1536 1 +#define MAC_RX_PKT_LEN_1552 2 +#define MAC_RX_PKT_LEN_JUMBO 3 + +/* FORCE_SPD: Forced link speed */ +#define SPEED_10M 0 +#define SPEED_100M 1 +#define SPEED_1000M 2 + +#define GMAC_TRGMII_RCK_CTRL 0x300 +#define RX_RST BIT(31) +#define RXC_DQSISEL BIT(30) + +#define GMAC_TRGMII_TD_ODT(n) (0x354 + (n) * 8) +#define TD_DM_DRVN_S 4 +#define TD_DM_DRVN_M 0xf0 +#define TD_DM_DRVP_S 0 +#define TD_DM_DRVP_M 0x0f + +/* MT7530 Registers */ + +#define PCR_REG(p) (0x2004 + (p) * 0x100) +#define PORT_MATRIX_S 16 +#define PORT_MATRIX_M 0xff0000 + +#define PVC_REG(p) (0x2010 + (p) * 0x100) +#define STAG_VPID_S 16 +#define STAG_VPID_M 0xffff0000 +#define VLAN_ATTR_S 6 +#define VLAN_ATTR_M 0xc0 + +/* VLAN_ATTR: VLAN attributes */ +#define VLAN_ATTR_USER 0 +#define VLAN_ATTR_STACK 1 +#define VLAN_ATTR_TRANSLATION 2 +#define VLAN_ATTR_TRANSPARENT 3 + +#define PCMR_REG(p) (0x3000 + (p) * 0x100) +/* XXX: all fields are defined under GMAC_PORT_MCR */ + +#define SYS_CTRL_REG 0x7000 +#define SW_PHY_RST BIT(2) +#define SW_SYS_RST BIT(1) +#define SW_REG_RST BIT(0) + +#define NUM_TRGMII_CTRL 5 + +#define HWTRAP_REG 0x7800 +#define MHWTRAP_REG 0x7804 +#define CHG_TRAP BIT(16) +#define LOOPDET_DIS BIT(14) +#define P5_INTF_SEL_S 13 +#define P5_INTF_SEL_M 0x2000 +#define SMI_ADDR_S 11 +#define SMI_ADDR_M 0x1800 +#define XTAL_FSEL_S 9 +#define XTAL_FSEL_M 0x600 +#define P6_INTF_DIS BIT(8) +#define P5_INTF_MODE_S 7 +#define P5_INTF_MODE_M 0x80 +#define P5_INTF_DIS BIT(6) +#define C_MDIO_BPS BIT(5) +#define CHIP_MODE_S 0 +#define CHIP_MODE_M 0x0f + +/* P5_INTF_SEL: Interface type of Port5 */ +#define P5_INTF_SEL_GPHY 0 +#define P5_INTF_SEL_GMAC5 1 + +/* P5_INTF_MODE: Interface mode of Port5 */ +#define P5_INTF_MODE_GMII_MII 0 +#define P5_INTF_MODE_RGMII 1 + +#define MT7530_P6ECR 0x7830 +#define P6_INTF_MODE_M 0x3 +#define P6_INTF_MODE_S 0 + +/* P6_INTF_MODE: Interface mode of Port6 */ +#define P6_INTF_MODE_RGMII 0 +#define P6_INTF_MODE_TRGMII 1 + +#define MT7530_TRGMII_RD(n) (0x7a10 + (n) * 8) +#define RD_TAP_S 0 +#define RD_TAP_M 0x7f + +#define MT7530_TRGMII_TD_ODT(n) (0x7a54 + (n) * 8) +/* XXX: all fields are defined under GMAC_TRGMII_TD_ODT */ + +/* MT7530 GPHY MDIO Indirect Access Registers */ + +#define MII_MMD_ACC_CTL_REG 0x0d +#define MMD_CMD_S 14 +#define MMD_CMD_M 0xc000 +#define MMD_DEVAD_S 0 +#define MMD_DEVAD_M 0x1f + +/* MMD_CMD: MMD commands */ +#define MMD_ADDR 0 +#define MMD_DATA 1 +#define MMD_DATA_RW_POST_INC 2 +#define MMD_DATA_W_POST_INC 3 + +#define MII_MMD_ADDR_DATA_REG 0x0e + +/* MT7530 GPHY MDIO MMD Registers */ + +#define CORE_PLL_GROUP2 0x401 +#define RG_SYSPLL_EN_NORMAL BIT(15) +#define RG_SYSPLL_VODEN BIT(14) +#define RG_SYSPLL_POSDIV_S 5 +#define RG_SYSPLL_POSDIV_M 0x60 + +#define CORE_PLL_GROUP4 0x403 +#define RG_SYSPLL_DDSFBK_EN BIT(12) +#define RG_SYSPLL_BIAS_EN BIT(11) +#define RG_SYSPLL_BIAS_LPF_EN BIT(10) + +#define CORE_PLL_GROUP5 0x404 +#define RG_LCDDS_PCW_NCPO1_S 0 +#define RG_LCDDS_PCW_NCPO1_M 0xffff + +#define CORE_PLL_GROUP6 0x405 +#define RG_LCDDS_PCW_NCPO0_S 0 +#define RG_LCDDS_PCW_NCPO0_M 0xffff + +#define CORE_PLL_GROUP7 0x406 +#define RG_LCDDS_PWDB BIT(15) +#define RG_LCDDS_ISO_EN BIT(13) +#define RG_LCCDS_C_S 4 +#define RG_LCCDS_C_M 0x70 +#define RG_LCDDS_PCW_NCPO_CHG BIT(3) + +#define CORE_PLL_GROUP10 0x409 +#define RG_LCDDS_SSC_DELTA_S 0 +#define RG_LCDDS_SSC_DELTA_M 0xfff + +#define CORE_PLL_GROUP11 0x40a +#define RG_LCDDS_SSC_DELTA1_S 0 +#define RG_LCDDS_SSC_DELTA1_M 0xfff + +#define CORE_GSWPLL_GRP1 0x40d +#define RG_GSWPLL_POSDIV_200M_S 12 +#define RG_GSWPLL_POSDIV_200M_M 0x3000 +#define RG_GSWPLL_EN_PRE BIT(11) +#define RG_GSWPLL_FBKDIV_200M_S 0 +#define RG_GSWPLL_FBKDIV_200M_M 0xff + +#define CORE_GSWPLL_GRP2 0x40e +#define RG_GSWPLL_POSDIV_500M_S 8 +#define RG_GSWPLL_POSDIV_500M_M 0x300 +#define RG_GSWPLL_FBKDIV_500M_S 0 +#define RG_GSWPLL_FBKDIV_500M_M 0xff + +#define CORE_TRGMII_GSW_CLK_CG 0x410 +#define REG_GSWCK_EN BIT(0) +#define REG_TRGMIICK_EN BIT(1) + +#endif /* _MTK_ETH_H_ */ From d9506a6fdd0269f86c7a1fe5bbee7191acc3d1c8 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:54 +0800 Subject: [PATCH 09/58] arm: dts: add ethernet related node for MT7623 SoC This patch adds ethernet gmac node for MT7623 with MT7530 gigabit switch. Signed-off-by: Mark Lee --- arch/arm/dts/mt7623.dtsi | 21 ++++++++++++++++++++- arch/arm/dts/mt7623n-bananapi-bpi-r2.dts | 13 +++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/arch/arm/dts/mt7623.dtsi b/arch/arm/dts/mt7623.dtsi index f50f4ef1b92..448d1d73810 100644 --- a/arch/arm/dts/mt7623.dtsi +++ b/arch/arm/dts/mt7623.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include "skeleton.dtsi" / { @@ -248,8 +249,26 @@ }; ethsys: syscon@1b000000 { - compatible = "mediatek,mt7623-ethsys"; + compatible = "mediatek,mt7623-ethsys", "syscon"; reg = <0x1b000000 0x1000>; #clock-cells = <1>; + #reset-cells = <1>; + }; + + eth: ethernet@1b100000 { + compatible = "mediatek,mt7623-eth", "syscon"; + reg = <0x1b100000 0x20000>; + clocks = <&topckgen CLK_TOP_ETHIF_SEL>, + <ðsys CLK_ETHSYS_ESW>, + <ðsys CLK_ETHSYS_GP1>, + <ðsys CLK_ETHSYS_GP2>, + <&apmixedsys CLK_APMIXED_TRGPLL>; + clock-names = "ethif", "esw", "gp1", "gp2", "trgpll"; + power-domains = <&scpsys MT7623_POWER_DOMAIN_ETH>; + resets = <ðsys ETHSYS_FE_RST>, + <ðsys ETHSYS_MCM_RST>; + reset-names = "fe", "mcm"; + mediatek,ethsys = <ðsys>; + status = "disabled"; }; }; diff --git a/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts index 84a77fde443..51628bb6399 100644 --- a/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/dts/mt7623n-bananapi-bpi-r2.dts @@ -67,6 +67,19 @@ }; }; +ð { + status = "okay"; + mediatek,gmac-id = <0>; + phy-mode = "rgmii"; + mediatek,switch = "mt7530"; + reset-gpios = <&gpio 33 GPIO_ACTIVE_HIGH>; + + fixed-link { + speed = <1000>; + full-duplex; + }; +}; + &mmc0 { pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins_default>; From 9d42b613a8f45fb8fc91c43a40b6e4723b56eb63 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:55 +0800 Subject: [PATCH 10/58] arm: dts: add ethernet related node for MT7629 SoC This patch adds ethernet gmac node for MT7629 with internal gigabit phy. Signed-off-by: Mark Lee --- arch/arm/dts/mt7629-rfb.dts | 11 ++++++++++ arch/arm/dts/mt7629.dtsi | 43 +++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/arch/arm/dts/mt7629-rfb.dts b/arch/arm/dts/mt7629-rfb.dts index a6d28a060f3..95d10aa6d32 100644 --- a/arch/arm/dts/mt7629-rfb.dts +++ b/arch/arm/dts/mt7629-rfb.dts @@ -22,6 +22,17 @@ }; }; +ð { + status = "okay"; + mediatek,gmac-id = <1>; + phy-mode = "gmii"; + phy-handle = <&phy0>; + + phy0: ethernet-phy@0 { + reg = <0>; + }; +}; + &pinctrl { qspi_pins: qspi-pins { mux { diff --git a/arch/arm/dts/mt7629.dtsi b/arch/arm/dts/mt7629.dtsi index e6052bbdcf3..c87115e0fe4 100644 --- a/arch/arm/dts/mt7629.dtsi +++ b/arch/arm/dts/mt7629.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include "skeleton.dtsi" / { @@ -228,6 +229,48 @@ compatible = "mediatek,mt7629-ethsys", "syscon"; reg = <0x1b000000 0x1000>; #clock-cells = <1>; + #reset-cells = <1>; + }; + + eth: ethernet@1b100000 { + compatible = "mediatek,mt7629-eth", "syscon"; + reg = <0x1b100000 0x20000>; + clocks = <&topckgen CLK_TOP_ETH_SEL>, + <&topckgen CLK_TOP_F10M_REF_SEL>, + <ðsys CLK_ETH_ESW_EN>, + <ðsys CLK_ETH_GP0_EN>, + <ðsys CLK_ETH_GP1_EN>, + <ðsys CLK_ETH_GP2_EN>, + <ðsys CLK_ETH_FE_EN>, + <&sgmiisys0 CLK_SGMII_TX_EN>, + <&sgmiisys0 CLK_SGMII_RX_EN>, + <&sgmiisys0 CLK_SGMII_CDR_REF>, + <&sgmiisys0 CLK_SGMII_CDR_FB>, + <&sgmiisys1 CLK_SGMII_TX_EN>, + <&sgmiisys1 CLK_SGMII_RX_EN>, + <&sgmiisys1 CLK_SGMII_CDR_REF>, + <&sgmiisys1 CLK_SGMII_CDR_FB>, + <&apmixedsys CLK_APMIXED_SGMIPLL>, + <&apmixedsys CLK_APMIXED_ETH2PLL>; + clock-names = "ethif", "sgmiitop", "esw", "gp0", "gp1", "gp2", + "fe", "sgmii_tx250m", "sgmii_rx250m", + "sgmii_cdr_ref", "sgmii_cdr_fb", + "sgmii2_tx250m", "sgmii2_rx250m", + "sgmii2_cdr_ref", "sgmii2_cdr_fb", + "sgmii_ck", "eth2pll"; + assigned-clocks = <&topckgen CLK_TOP_ETH_SEL>, + <&topckgen CLK_TOP_F10M_REF_SEL>; + assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL1_D2>, + <&topckgen CLK_TOP_SGMIIPLL_D2>; + power-domains = <&scpsys MT7629_POWER_DOMAIN_ETHSYS>; + resets = <ðsys ETHSYS_FE_RST>; + reset-names = "fe"; + mediatek,ethsys = <ðsys>; + mediatek,sgmiisys = <&sgmiisys0>; + mediatek,infracfg = <&infracfg>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; }; sgmiisys0: syscon@1b128000 { From 8505cdde8eb3afa8254e864f48574bc1d52c01f2 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:56 +0800 Subject: [PATCH 11/58] arm: MediaTek: add ethernet support for MT7623 boards Enable ethernet related configs to mt7623n_bpir2_defconfig. Add default IP addresses. Enable noncached memory region required by ethernet driver. Signed-off-by: Mark Lee --- configs/mt7623n_bpir2_defconfig | 6 ++++++ include/configs/mt7623.h | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig index ae4fb280dc4..53ac63e19c9 100644 --- a/configs/mt7623n_bpir2_defconfig +++ b/configs/mt7623n_bpir2_defconfig @@ -28,6 +28,7 @@ CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="mt7623n-bananapi-bpi-r2" +CONFIG_NET_RANDOM_ETHADDR=y CONFIG_REGMAP=y CONFIG_SYSCON=y # CONFIG_BLOCK_CACHE is not set @@ -37,6 +38,11 @@ CONFIG_DM_MMC=y # CONFIG_MMC_QUIRKS is not set CONFIG_MMC_HS400_SUPPORT=y CONFIG_MMC_MTK=y +CONFIG_DM_RESET=y +CONFIG_RESET_MEDIATEK=y +CONFIG_PHY_FIXED=y +CONFIG_DM_ETH=y +CONFIG_MEDIATEK_ETH=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_PINCTRL_MT7623=y diff --git a/include/configs/mt7623.h b/include/configs/mt7623.h index ba763501cf2..5129c83da8f 100644 --- a/include/configs/mt7623.h +++ b/include/configs/mt7623.h @@ -24,6 +24,7 @@ /* Size of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN SZ_4M +#define CONFIG_SYS_NONCACHED_MEMORY SZ_1M /* Environment */ #define CONFIG_ENV_SIZE SZ_4K @@ -53,4 +54,8 @@ #define CONFIG_EXTRA_ENV_SETTINGS \ FDT_HIGH +/* Ethernet */ +#define CONFIG_IPADDR 192.168.1.1 +#define CONFIG_SERVERIP 192.168.1.2 + #endif From d7fe0ad2850a1bdba6d5582d8a6b871cd4ace8de Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:57 +0800 Subject: [PATCH 12/58] arm: MediaTek: add ethernet support for MT7629 boards Enable ethernet related configs to mt7629_rfb_defconfig. Add default IP addresses. Enable noncached memory region required by ethernet driver. Signed-off-by: Mark Lee --- configs/mt7629_rfb_defconfig | 5 +++++ include/configs/mt7629.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig index 1729d13c3d3..fdd5f575774 100644 --- a/configs/mt7629_rfb_defconfig +++ b/configs/mt7629_rfb_defconfig @@ -32,6 +32,7 @@ CONFIG_CMD_PING=y CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb" CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-parents" +CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_REGMAP=y CONFIG_SPL_REGMAP=y @@ -51,6 +52,10 @@ CONFIG_SPI_FLASH_MACRONIX=y CONFIG_SPI_FLASH_SPANSION=y CONFIG_SPI_FLASH_STMICRO=y CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_RESET=y +CONFIG_RESET_MEDIATEK=y +CONFIG_DM_ETH=y +CONFIG_MEDIATEK_ETH=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_PINCTRL_MT7629=y diff --git a/include/configs/mt7629.h b/include/configs/mt7629.h index a665a5eb7f2..9910d8c89a6 100644 --- a/include/configs/mt7629.h +++ b/include/configs/mt7629.h @@ -24,6 +24,7 @@ /* Size of malloc() pool */ #define CONFIG_SYS_MALLOC_LEN SZ_4M +#define CONFIG_SYS_NONCACHED_MEMORY SZ_1M /* Environment */ #define CONFIG_ENV_SIZE SZ_4K @@ -54,4 +55,8 @@ /* DRAM */ #define CONFIG_SYS_SDRAM_BASE 0x40000000 +/* Ethernet */ +#define CONFIG_IPADDR 192.168.1.1 +#define CONFIG_SERVERIP 192.168.1.2 + #endif From d049ff9ca5e1f7891e68eb89d495f16fa7d8948a Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:58 +0800 Subject: [PATCH 13/58] MAINTAINERS: ARM MEDIATEK: update file entries This patch adds new file entries for MediaTek SoCs Signed-off-by: Weijie Gao --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index f86fdf9c338..e192db07548 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -176,6 +176,8 @@ F: drivers/ram/mediatek/ F: drivers/spi/mtk_qspi.c F: drivers/timer/mtk_timer.c F: drivers/watchdog/mtk_wdt.c +F: drivers/net/mtk_eth.c +F: drivers/reset/reset-mediatek.c F: tools/mtk_image.c F: tools/mtk_image.h N: mediatek From b5d29e439053ea42ccae84104f90440612274ee9 Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Thu, 20 Dec 2018 16:12:59 +0800 Subject: [PATCH 14/58] configs: MediaTek: use OF_SEPARATE instead of OF_EMBED This patch replace OF_EMBED with OF_SEPARATE of defconfig files of MediaTek boards because now OF_EMBED is only used for debugging purpose. Signed-off-by: Weijie Gao Reviewed-by: Simon Glass --- configs/mt7623n_bpir2_defconfig | 2 +- configs/mt7629_rfb_defconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/mt7623n_bpir2_defconfig b/configs/mt7623n_bpir2_defconfig index 53ac63e19c9..8cb49073269 100644 --- a/configs/mt7623n_bpir2_defconfig +++ b/configs/mt7623n_bpir2_defconfig @@ -26,7 +26,7 @@ CONFIG_CMD_READ=y CONFIG_CMD_PING=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y -CONFIG_OF_EMBED=y +CONFIG_OF_SEPARATE=y CONFIG_DEFAULT_DEVICE_TREE="mt7623n-bananapi-bpi-r2" CONFIG_NET_RANDOM_ETHADDR=y CONFIG_REGMAP=y diff --git a/configs/mt7629_rfb_defconfig b/configs/mt7629_rfb_defconfig index fdd5f575774..1da9932dcd9 100644 --- a/configs/mt7629_rfb_defconfig +++ b/configs/mt7629_rfb_defconfig @@ -29,7 +29,7 @@ CONFIG_CMD_SF_TEST=y # CONFIG_CMD_NFS is not set CONFIG_CMD_PING=y # CONFIG_PARTITIONS is not set -CONFIG_OF_EMBED=y +CONFIG_OF_SEPARATE=y CONFIG_DEFAULT_DEVICE_TREE="mt7629-rfb" CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-parents" CONFIG_NET_RANDOM_ETHADDR=y From 5bb409c1ba4aea00b5dbd834f0e217a759c1041c Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 27 Dec 2018 19:04:03 +0530 Subject: [PATCH 15/58] include: configs: Add gunzip size for HiKey board Default 8MB gunzip size is not enough to load the release kernel, hence fix 64MB size for uncompressing the kernel. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Simon Glass Reviewed-by: Simon Glass --- include/configs/hikey.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/configs/hikey.h b/include/configs/hikey.h index 1376d6155de..572a52fad59 100644 --- a/include/configs/hikey.h +++ b/include/configs/hikey.h @@ -18,6 +18,8 @@ #define CONFIG_REMAKE_ELF +#define CONFIG_SYS_BOOTM_LEN SZ_64M + /* Physical Memory Map */ /* CONFIG_SYS_TEXT_BASE needs to align with where ATF loads bl33.bin */ From 6240e64f92085f6e8950d938a0103281ad4f5ab2 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 27 Dec 2018 19:04:04 +0530 Subject: [PATCH 16/58] mmc: Convert HI6220 MMC driver to driver model Convert HiSilicon HI6220 MMC driver based on DWMMC IP to driver model. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Simon Glass [trini: Enable this on poplar] Signed-off-by: Tom Rini --- configs/hikey_defconfig | 1 + configs/poplar_defconfig | 1 + drivers/mmc/hi6220_dw_mmc.c | 100 +++++++++++++++++++++++++----------- 3 files changed, 71 insertions(+), 31 deletions(-) diff --git a/configs/hikey_defconfig b/configs/hikey_defconfig index 3bc5ceb5d8c..e9a9857322b 100644 --- a/configs/hikey_defconfig +++ b/configs/hikey_defconfig @@ -18,6 +18,7 @@ CONFIG_DEFAULT_DEVICE_TREE="hi6220-hikey" CONFIG_ENV_IS_IN_FAT=y CONFIG_ENV_FAT_INTERFACE="mmc" CONFIG_ENV_FAT_DEVICE_AND_PART="1:1" +CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_MMC_DW_K3=y CONFIG_CONS_INDEX=4 diff --git a/configs/poplar_defconfig b/configs/poplar_defconfig index ea0ea892207..81bd3702e42 100644 --- a/configs/poplar_defconfig +++ b/configs/poplar_defconfig @@ -16,6 +16,7 @@ CONFIG_FASTBOOT_BUF_ADDR=0x20000000 CONFIG_FASTBOOT_BUF_SIZE=0x10000000 CONFIG_FASTBOOT_FLASH=y CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_DM_MMC=y CONFIG_MMC_DW=y CONFIG_MMC_DW_K3=y CONFIG_USB=y diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c index ce395d53c94..cc58aff38cc 100644 --- a/drivers/mmc/hi6220_dw_mmc.c +++ b/drivers/mmc/hi6220_dw_mmc.c @@ -5,51 +5,89 @@ */ #include +#include #include +#include +#include #include -#include -#define DWMMC_MAX_CH_NUM 4 +DECLARE_GLOBAL_DATA_PTR; -#define DWMMC_MAX_FREQ 50000000 -#define DWMMC_MIN_FREQ 400000 +struct hi6220_dwmmc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; -/* Source clock is configured to 100MHz by ATF bl1*/ -#define MMC0_DEFAULT_FREQ 100000000 +struct hi6220_dwmmc_priv_data { + struct dwmci_host host; +}; -static int hi6220_dwmci_core_init(struct dwmci_host *host, int index) +static int hi6220_dwmmc_ofdata_to_platdata(struct udevice *dev) { - host->name = "Hisilicon DWMMC"; + struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); + struct dwmci_host *host = &priv->host; - host->dev_index = index; + host->name = dev->name; + host->ioaddr = (void *)devfdt_get_addr(dev); + host->buswidth = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), + "bus-width", 4); + + /* use non-removable property for differentiating SD card and eMMC */ + if (dev_read_bool(dev, "non-removable")) + host->dev_index = 0; + else + host->dev_index = 1; + + host->priv = priv; - /* Add the mmc channel to be registered with mmc core */ - if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) { - printf("DWMMC%d registration failed\n", index); - return -1; - } return 0; } -/* - * This function adds the mmc channel to be registered with mmc core. - * index - mmc channel number. - * regbase - register base address of mmc channel specified in 'index'. - * bus_width - operating bus width of mmc channel specified in 'index'. - */ -int hi6220_dwmci_add_port(int index, u32 regbase, int bus_width) +static int hi6220_dwmmc_probe(struct udevice *dev) { - struct dwmci_host *host = NULL; + struct hi6220_dwmmc_plat *plat = dev_get_platdata(dev); + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); + struct dwmci_host *host = &priv->host; - host = calloc(1, sizeof(struct dwmci_host)); - if (!host) { - pr_err("dwmci_host calloc failed!\n"); - return -ENOMEM; - } + /* Use default bus speed due to absence of clk driver */ + host->bus_hz = 50000000; - host->ioaddr = (void *)(ulong)regbase; - host->buswidth = bus_width; - host->bus_hz = MMC0_DEFAULT_FREQ; + dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000); + host->mmc = &plat->mmc; - return hi6220_dwmci_core_init(host, index); + host->mmc->priv = &priv->host; + upriv->mmc = host->mmc; + host->mmc->dev = dev; + + return dwmci_probe(dev); } + +static int hi6220_dwmmc_bind(struct udevice *dev) +{ + struct hi6220_dwmmc_plat *plat = dev_get_platdata(dev); + int ret; + + ret = dwmci_bind(dev, &plat->mmc, &plat->cfg); + if (ret) + return ret; + + return 0; +} + +static const struct udevice_id hi6220_dwmmc_ids[] = { + { .compatible = "hisilicon,hi6220-dw-mshc" }, + { } +}; + +U_BOOT_DRIVER(hi6220_dwmmc_drv) = { + .name = "hi6220_dwmmc", + .id = UCLASS_MMC, + .of_match = hi6220_dwmmc_ids, + .ofdata_to_platdata = hi6220_dwmmc_ofdata_to_platdata, + .ops = &dm_dwmci_ops, + .bind = hi6220_dwmmc_bind, + .probe = hi6220_dwmmc_probe, + .priv_auto_alloc_size = sizeof(struct hi6220_dwmmc_priv_data), + .platdata_auto_alloc_size = sizeof(struct hi6220_dwmmc_plat), +}; From a50eb64915fd2e4775684b0dee98fb5d322ee4e4 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Thu, 27 Dec 2018 19:04:05 +0530 Subject: [PATCH 17/58] arm: dts: Add MMC nodes for HiKey board Add MMC nodes for HiKey board based on HI6220 SoC. There are three MMC controllers in this SoC, first one used for eMMC, second one used for SD card and third one is not used by u-boot. Signed-off-by: Manivannan Sadhasivam Reviewed-by: Simon Glass Reviewed-by: Tom Rini --- arch/arm/dts/hi6220-hikey-u-boot.dtsi | 14 ++++++++++++++ arch/arm/dts/hi6220-hikey.dts | 11 +++++++++++ arch/arm/dts/hi6220.dtsi | 18 ++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 arch/arm/dts/hi6220-hikey-u-boot.dtsi diff --git a/arch/arm/dts/hi6220-hikey-u-boot.dtsi b/arch/arm/dts/hi6220-hikey-u-boot.dtsi new file mode 100644 index 00000000000..31139832401 --- /dev/null +++ b/arch/arm/dts/hi6220-hikey-u-boot.dtsi @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * U-Boot additions + * + * Copyright (c) 2018 Linaro Ltd. + */ + +&mmc0 { + u-boot,dm-pre-reloc; +}; + +&mmc1 { + u-boot,dm-pre-reloc; +}; diff --git a/arch/arm/dts/hi6220-hikey.dts b/arch/arm/dts/hi6220-hikey.dts index 24f09257af0..d63929348bb 100644 --- a/arch/arm/dts/hi6220-hikey.dts +++ b/arch/arm/dts/hi6220-hikey.dts @@ -40,6 +40,17 @@ }; }; +&mmc0 { + status = "okay"; + non-removable; + bus-width = <8>; +}; + +&mmc1 { + status = "okay"; + bus-width = <4>; +}; + &uart2 { label = "LS-UART0"; }; diff --git a/arch/arm/dts/hi6220.dtsi b/arch/arm/dts/hi6220.dtsi index a610ccb6346..501c8906fd6 100644 --- a/arch/arm/dts/hi6220.dtsi +++ b/arch/arm/dts/hi6220.dtsi @@ -162,6 +162,24 @@ #clock-cells = <1>; }; + mmc0: dwmmc@f723d000 { + compatible = "hisilicon,hi6220-dw-mshc"; + reg = <0x0 0xf723d000 0x0 0x1000>; + interrupts = <0x0 0x48 0x4>; + clocks = <&sys_ctrl 2>, <&sys_ctrl 1>; + clock-names = "ciu", "biu"; + status = "disabled"; + }; + + mmc1: dwmmc@f723e000 { + compatible = "hisilicon,hi6220-dw-mshc"; + reg = <0x0 0xf723e000 0x0 0x1000>; + interrupts = <0x0 0x49 0x4>; + clocks = <&sys_ctrl 4>, <&sys_ctrl 3>; + clock-names = "ciu", "biu"; + status = "disabled"; + }; + uart0: uart@f8015000 { /* console */ compatible = "arm,pl011", "arm,primecell"; reg = <0x0 0xf8015000 0x0 0x1000>; From 871bf7d9baba0ebb0485c01657399b2a339daa20 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 27 Dec 2018 08:11:13 -0700 Subject: [PATCH 18/58] test: Use single quote consistently Some tests have ended up using double quotes where single quotes could be used. Adjust this for consistency with the rest of U-Boot's Python code. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- test/py/tests/test_avb.py | 14 +-- test/py/tests/test_bind.py | 140 +++++++++++++++--------------- test/py/tests/test_dfu.py | 38 ++++---- test/py/tests/test_efi_loader.py | 12 +-- test/py/tests/test_fpga.py | 54 ++++++------ test/py/tests/test_fs/conftest.py | 8 +- test/py/tests/test_mmc_rd.py | 66 +++++++------- test/py/tests/test_net.py | 22 ++--- test/py/tests/test_ums.py | 24 ++--- 9 files changed, 189 insertions(+), 189 deletions(-) diff --git a/test/py/tests/test_avb.py b/test/py/tests/test_avb.py index 9683fd80d07..e70a010c9ac 100644 --- a/test/py/tests/test_avb.py +++ b/test/py/tests/test_avb.py @@ -51,22 +51,22 @@ def test_avb_mmc_uuid(u_boot_console): part_lines = u_boot_console.run_command('mmc part').splitlines() part_list = {} - cur_partname = "" + cur_partname = '' for line in part_lines: - if "\"" in line: - start_pt = line.find("\"") - end_pt = line.find("\"", start_pt + 1) + if '"' in line: + start_pt = line.find('"') + end_pt = line.find('"', start_pt + 1) cur_partname = line[start_pt + 1: end_pt] - if "guid:" in line: - guid_to_check = line.split("guid:\t") + if 'guid:' in line: + guid_to_check = line.split('guid:\t') part_list[cur_partname] = guid_to_check[1] # lets check all guids with avb get_guid for part, guid in part_list.iteritems(): avb_guid_resp = u_boot_console.run_command('avb get_uuid %s' % part) - assert guid == avb_guid_resp.split("UUID: ")[1] + assert guid == avb_guid_resp.split('UUID: ')[1] @pytest.mark.buildconfigspec('cmd_avb') diff --git a/test/py/tests/test_bind.py b/test/py/tests/test_bind.py index dee3fee5661..6e1feb80ae0 100644 --- a/test/py/tests/test_bind.py +++ b/test/py/tests/test_bind.py @@ -25,82 +25,82 @@ def in_tree(response, name, uclass, drv, depth, last_child): def test_bind_unbind_with_node(u_boot_console): #bind /bind-test. Device should come up as well as its children - response = u_boot_console.run_command("bind /bind-test generic_simple_bus") + response = u_boot_console.run_command('bind /bind-test generic_simple_bus') assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) - assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True) + assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False) + assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True) #Unbind child #1. No error expected and all devices should be there except for bind-test-child1 - response = u_boot_console.run_command("unbind /bind-test/bind-test-child1") + response = u_boot_console.run_command('unbind /bind-test/bind-test-child1') assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) - assert "bind-test-child1" not in tree - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True) + assert 'bind-test-child1' not in tree + assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True) #bind child #1. No error expected and all devices should be there - response = u_boot_console.run_command("bind /bind-test/bind-test-child1 phy_sandbox") + response = u_boot_console.run_command('bind /bind-test/bind-test-child1 phy_sandbox') assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) - assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, False) + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True) + assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, True) + assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, False) #Unbind child #2. No error expected and all devices should be there except for bind-test-child2 - response = u_boot_console.run_command("unbind /bind-test/bind-test-child2") + response = u_boot_console.run_command('unbind /bind-test/bind-test-child2') assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) - assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, True) - assert "bind-test-child2" not in tree + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True) + assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, True) + assert 'bind-test-child2' not in tree #Bind child #2. No error expected and all devices should be there - response = u_boot_console.run_command("bind /bind-test/bind-test-child2 generic_simple_bus") + response = u_boot_console.run_command('bind /bind-test/bind-test-child2 generic_simple_bus') assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) - assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True) + assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False) + assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True) #Unbind parent. No error expected. All devices should be removed and unbound - response = u_boot_console.run_command("unbind /bind-test") + response = u_boot_console.run_command('unbind /bind-test') assert response == '' - tree = u_boot_console.run_command("dm tree") - assert "bind-test" not in tree - assert "bind-test-child1" not in tree - assert "bind-test-child2" not in tree + tree = u_boot_console.run_command('dm tree') + assert 'bind-test' not in tree + assert 'bind-test-child1' not in tree + assert 'bind-test-child2' not in tree #try binding invalid node with valid driver - response = u_boot_console.run_command("bind /not-a-valid-node generic_simple_bus") + response = u_boot_console.run_command('bind /not-a-valid-node generic_simple_bus') assert response != '' - tree = u_boot_console.run_command("dm tree") - assert "not-a-valid-node" not in tree + tree = u_boot_console.run_command('dm tree') + assert 'not-a-valid-node' not in tree #try binding valid node with invalid driver - response = u_boot_console.run_command("bind /bind-test not_a_driver") + response = u_boot_console.run_command('bind /bind-test not_a_driver') assert response != '' - tree = u_boot_console.run_command("dm tree") - assert "bind-test" not in tree + tree = u_boot_console.run_command('dm tree') + assert 'bind-test' not in tree #bind /bind-test. Device should come up as well as its children - response = u_boot_console.run_command("bind /bind-test generic_simple_bus") + response = u_boot_console.run_command('bind /bind-test generic_simple_bus') assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test", "simple_bus", "generic_simple_bus", 0, True) - assert in_tree(tree, "bind-test-child1", "phy", "phy_sandbox", 1, False) - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test', 'simple_bus', 'generic_simple_bus', 0, True) + assert in_tree(tree, 'bind-test-child1', 'phy', 'phy_sandbox', 1, False) + assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True) - response = u_boot_console.run_command("unbind /bind-test") + response = u_boot_console.run_command('unbind /bind-test') assert response == '' def get_next_line(tree, name): treelines = [x.strip() for x in tree.splitlines() if x.strip()] - child_line = "" + child_line = '' for idx, line in enumerate(treelines): - if ("-- " + name) in line: + if ('-- ' + name) in line: try: child_line = treelines[idx+1] except: @@ -111,68 +111,68 @@ def get_next_line(tree, name): @pytest.mark.buildconfigspec('cmd_bind') def test_bind_unbind_with_uclass(u_boot_console): #bind /bind-test - response = u_boot_console.run_command("bind /bind-test generic_simple_bus") + response = u_boot_console.run_command('bind /bind-test generic_simple_bus') assert response == '' #make sure bind-test-child2 is there and get its uclass/index pair - tree = u_boot_console.run_command("dm tree") - child2_line = [x.strip() for x in tree.splitlines() if "-- bind-test-child2" in x] + tree = u_boot_console.run_command('dm tree') + child2_line = [x.strip() for x in tree.splitlines() if '-- bind-test-child2' in x] assert len(child2_line) == 1 child2_uclass = child2_line[0].split()[0] child2_index = int(child2_line[0].split()[1]) #bind generic_simple_bus as a child of bind-test-child2 - response = u_boot_console.run_command("bind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus")) + response = u_boot_console.run_command('bind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus')) #check that the child is there and its uclass/index pair is right - tree = u_boot_console.run_command("dm tree") + tree = u_boot_console.run_command('dm tree') - child_of_child2_line = get_next_line(tree, "bind-test-child2") + child_of_child2_line = get_next_line(tree, 'bind-test-child2') assert child_of_child2_line child_of_child2_index = int(child_of_child2_line.split()[1]) - assert in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True) + assert in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True) assert child_of_child2_index == child2_index + 1 #unbind the child and check it has been removed - response = u_boot_console.run_command("unbind simple_bus {}".format(child_of_child2_index)) + response = u_boot_console.run_command('unbind simple_bus {}'.format(child_of_child2_index)) assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) - assert not in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True) - child_of_child2_line = get_next_line(tree, "bind-test-child2") - assert child_of_child2_line == "" + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True) + assert not in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True) + child_of_child2_line = get_next_line(tree, 'bind-test-child2') + assert child_of_child2_line == '' #bind generic_simple_bus as a child of bind-test-child2 - response = u_boot_console.run_command("bind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus")) + response = u_boot_console.run_command('bind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus')) #check that the child is there and its uclass/index pair is right - tree = u_boot_console.run_command("dm tree") + tree = u_boot_console.run_command('dm tree') treelines = [x.strip() for x in tree.splitlines() if x.strip()] - child_of_child2_line = get_next_line(tree, "bind-test-child2") + child_of_child2_line = get_next_line(tree, 'bind-test-child2') assert child_of_child2_line child_of_child2_index = int(child_of_child2_line.split()[1]) - assert in_tree(tree, "generic_simple_bus", "simple_bus", "generic_simple_bus", 2, True) + assert in_tree(tree, 'generic_simple_bus', 'simple_bus', 'generic_simple_bus', 2, True) assert child_of_child2_index == child2_index + 1 #unbind the child and check it has been removed - response = u_boot_console.run_command("unbind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus")) + response = u_boot_console.run_command('unbind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus')) assert response == '' - tree = u_boot_console.run_command("dm tree") - assert in_tree(tree, "bind-test-child2", "simple_bus", "generic_simple_bus", 1, True) + tree = u_boot_console.run_command('dm tree') + assert in_tree(tree, 'bind-test-child2', 'simple_bus', 'generic_simple_bus', 1, True) - child_of_child2_line = get_next_line(tree, "bind-test-child2") - assert child_of_child2_line == "" + child_of_child2_line = get_next_line(tree, 'bind-test-child2') + assert child_of_child2_line == '' #unbind the child again and check it doesn't change the tree - tree_old = u_boot_console.run_command("dm tree") - response = u_boot_console.run_command("unbind {} {} generic_simple_bus".format(child2_uclass, child2_index, "generic_simple_bus")) - tree_new = u_boot_console.run_command("dm tree") + tree_old = u_boot_console.run_command('dm tree') + response = u_boot_console.run_command('unbind {} {} generic_simple_bus'.format(child2_uclass, child2_index, 'generic_simple_bus')) + tree_new = u_boot_console.run_command('dm tree') assert response == '' assert tree_old == tree_new - response = u_boot_console.run_command("unbind /bind-test") + response = u_boot_console.run_command('unbind /bind-test') assert response == '' diff --git a/test/py/tests/test_dfu.py b/test/py/tests/test_dfu.py index a24600376cb..5d87eb349bf 100644 --- a/test/py/tests/test_dfu.py +++ b/test/py/tests/test_dfu.py @@ -20,28 +20,28 @@ For example: env__usb_dev_ports = ( { - "fixture_id": "micro_b", - "tgt_usb_ctlr": "0", - "host_usb_dev_node": "/dev/usbdev-p2371-2180", + 'fixture_id': 'micro_b', + 'tgt_usb_ctlr': '0', + 'host_usb_dev_node': '/dev/usbdev-p2371-2180', # This parameter is optional /if/ you only have a single board # attached to your host at a time. - "host_usb_port_path": "3-13", + 'host_usb_port_path': '3-13', }, ) -# Optional entries (required only when "alt_id_test_file" and -# "alt_id_dummy_file" are specified). -test_file_name = "/dfu_test.bin" -dummy_file_name = "/dfu_dummy.bin" -# Above files are used to generate proper "alt_info" entry -"alt_info": "/%s ext4 0 2;/%s ext4 0 2" % (test_file_name, dummy_file_name), +# Optional entries (required only when 'alt_id_test_file' and +# 'alt_id_dummy_file' are specified). +test_file_name = '/dfu_test.bin' +dummy_file_name = '/dfu_dummy.bin' +# Above files are used to generate proper 'alt_info' entry +'alt_info': '/%s ext4 0 2;/%s ext4 0 2' % (test_file_name, dummy_file_name), env__dfu_configs = ( # eMMC, partition 1 { - "fixture_id": "emmc", - "alt_info": "/dfu_test.bin ext4 0 1;/dfu_dummy.bin ext4 0 1", - "cmd_params": "mmc 0", + 'fixture_id': 'emmc', + 'alt_info': '/dfu_test.bin ext4 0 1;/dfu_dummy.bin ext4 0 1', + 'cmd_params': 'mmc 0', # This value is optional. # If present, it specified the set of transfer sizes tested. # If missing, a default list of sizes will be used, which covers @@ -49,7 +49,7 @@ env__dfu_configs = ( # Manually specifying test sizes is useful if you wish to test 4 DFU # configurations, but don't want to test every single transfer size # on each, to avoid bloating the overall time taken by testing. - "test_sizes": (63, 64, 65), + 'test_sizes': (63, 64, 65), # This value is optional. # The name of the environment variable that the the dfu command reads # alt info from. If unspecified, this defaults to dfu_alt_info, which is @@ -57,17 +57,17 @@ env__dfu_configs = ( # One example is the Odroid XU3, which automatically generates # $dfu_alt_info, each time the dfu command is run, by concatenating # $dfu_alt_boot and $dfu_alt_system. - "alt_info_env_name": "dfu_alt_system", + 'alt_info_env_name': 'dfu_alt_system', # This value is optional. - # For boards which require the "test file" alt setting number other than + # For boards which require the 'test file' alt setting number other than # default (0) it is possible to specify exact file name to be used as # this parameter. - "alt_id_test_file": test_file_name, + 'alt_id_test_file': test_file_name, # This value is optional. - # For boards which require the "dummy file" alt setting number other + # For boards which require the 'dummy file' alt setting number other # than default (1) it is possible to specify exact file name to be used # as this parameter. - "alt_id_dummy_file": dummy_file_name, + 'alt_id_dummy_file': dummy_file_name, }, ) diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py index a66c6e6f947..d6b214f8452 100644 --- a/test/py/tests/test_efi_loader.py +++ b/test/py/tests/test_efi_loader.py @@ -35,17 +35,17 @@ env__net_dhcp_server = True # static IP. If solely relying on DHCP, this variable may be omitted or set to # an empty list. env__net_static_env_vars = [ - ("ipaddr", "10.0.0.100"), - ("netmask", "255.255.255.0"), - ("serverip", "10.0.0.1"), + ('ipaddr', '10.0.0.100'), + ('netmask', '255.255.255.0'), + ('serverip', '10.0.0.1'), ] # Details regarding a file that may be read from a TFTP server. This variable # may be omitted or set to None if TFTP testing is not possible or desired. env__efi_loader_helloworld_file = { - "fn": "lib/efi_loader/helloworld.efi", - "size": 5058624, - "crc32": "c2244b26", + 'fn': 'lib/efi_loader/helloworld.efi', + 'size': 5058624, + 'crc32': 'c2244b26', } """ diff --git a/test/py/tests/test_fpga.py b/test/py/tests/test_fpga.py index 7459ce58674..798f6eed3dc 100644 --- a/test/py/tests/test_fpga.py +++ b/test/py/tests/test_fpga.py @@ -24,40 +24,40 @@ env__net_dhcp_server = True # static IP. In this test case we atleast need serverip for performing tftpb # to get required files. env__net_static_env_vars = [ - ("ipaddr", "10.0.0.100"), - ("netmask", "255.255.255.0"), - ("serverip", "10.0.0.1"), + ('ipaddr', '10.0.0.100'), + ('netmask', '255.255.255.0'), + ('serverip', '10.0.0.1'), ] # Details regarding the files that may be read from a TFTP server. . env__fpga_secure_readable_file = { - "fn": "auth_bhdr_ppk1_bit.bin", - "enckupfn": "auth_bhdr_enc_kup_load_bit.bin", - "addr": 0x1000000, - "keyaddr": 0x100000, - "keyfn": "key.txt", + 'fn': 'auth_bhdr_ppk1_bit.bin', + 'enckupfn': 'auth_bhdr_enc_kup_load_bit.bin', + 'addr': 0x1000000, + 'keyaddr': 0x100000, + 'keyfn': 'key.txt', } env__fpga_under_test = { - "dev": 0, - "addr" : 0x1000000, - "bitstream_load": "compress.bin", - "bitstream_load_size": 1831960, - "bitstream_loadp": "compress_pr.bin", - "bitstream_loadp_size": 423352, - "bitstream_loadb": "compress.bit", - "bitstream_loadb_size": 1832086, - "bitstream_loadbp": "compress_pr.bit", - "bitstream_loadbp_size": 423491, - "mkimage_legacy": "download.ub", - "mkimage_legacy_size": 13321468, - "mkimage_legacy_gz": "download.gz.ub", - "mkimage_legacy_gz_size": 53632, - "mkimage_fit": "download-fit.ub", - "mkimage_fit_size": 13322784, - "loadfs": "mmc 0 compress.bin", - "loadfs_size": 1831960, - "loadfs_block_size": 0x10000, + 'dev': 0, + 'addr' : 0x1000000, + 'bitstream_load': 'compress.bin', + 'bitstream_load_size': 1831960, + 'bitstream_loadp': 'compress_pr.bin', + 'bitstream_loadp_size': 423352, + 'bitstream_loadb': 'compress.bit', + 'bitstream_loadb_size': 1832086, + 'bitstream_loadbp': 'compress_pr.bit', + 'bitstream_loadbp_size': 423491, + 'mkimage_legacy': 'download.ub', + 'mkimage_legacy_size': 13321468, + 'mkimage_legacy_gz': 'download.gz.ub', + 'mkimage_legacy_gz_size': 53632, + 'mkimage_fit': 'download-fit.ub', + 'mkimage_fit_size': 13322784, + 'loadfs': 'mmc 0 compress.bin', + 'loadfs_size': 1831960, + 'loadfs_block_size': 0x10000, } """ diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py index 60b4a2d737b..43eeb4be0ba 100644 --- a/test/py/tests/test_fs/conftest.py +++ b/test/py/tests/test_fs/conftest.py @@ -54,7 +54,7 @@ def pytest_configure(config): supported_fs = config.getoption('fs_type') if supported_fs: - print("*** FS TYPE modified: %s" % supported_fs) + print('*** FS TYPE modified: %s' % supported_fs) supported_fs_basic = intersect(supported_fs, supported_fs_basic) supported_fs_ext = intersect(supported_fs, supported_fs_ext) supported_fs_mkdir = intersect(supported_fs, supported_fs_mkdir) @@ -174,7 +174,7 @@ def tool_is_in_path(tool): Return: True if available, False if not. """ - for path in os.environ["PATH"].split(os.pathsep): + for path in os.environ['PATH'].split(os.pathsep): fn = os.path.join(path, tool) if os.path.isfile(fn) and os.access(fn, os.X_OK): return True @@ -202,9 +202,9 @@ def mount_fs(fs_type, device, mount_point): check_call('guestmount -a %s -m /dev/sda %s' % (device, mount_point), shell=True) else: - mount_opt = "loop,rw" + mount_opt = 'loop,rw' if re.match('fat', fs_type): - mount_opt += ",umask=0000" + mount_opt += ',umask=0000' check_call('sudo mount -o %s %s %s' % (mount_opt, device, mount_point), shell=True) diff --git a/test/py/tests/test_mmc_rd.py b/test/py/tests/test_mmc_rd.py index c5858cb0892..a13bc0a5f60 100644 --- a/test/py/tests/test_mmc_rd.py +++ b/test/py/tests/test_mmc_rd.py @@ -14,45 +14,45 @@ which MMC devices should be tested. For example: env__mmc_rd_configs = ( { - "fixture_id": "emmc-boot0", - "is_emmc": True, - "devid": 0, - "partid": 1, - "sector": 0x10, - "count": 1, + 'fixture_id': 'emmc-boot0', + 'is_emmc': True, + 'devid': 0, + 'partid': 1, + 'sector': 0x10, + 'count': 1, }, { - "fixture_id": "emmc-boot1", - "is_emmc": True, - "devid": 0, - "partid": 2, - "sector": 0x10, - "count": 1, + 'fixture_id': 'emmc-boot1', + 'is_emmc': True, + 'devid': 0, + 'partid': 2, + 'sector': 0x10, + 'count': 1, }, { - "fixture_id": "emmc-data", - "is_emmc": True, - "devid": 0, - "partid": 0, - "sector": 0x10, - "count": 0x1000, + 'fixture_id': 'emmc-data', + 'is_emmc': True, + 'devid': 0, + 'partid': 0, + 'sector': 0x10, + 'count': 0x1000, }, { - "fixture_id": "sd-mbr", - "is_emmc": False, - "devid": 1, - "partid": None, - "sector": 0, - "count": 1, - "crc32": "8f6ecf0d", + 'fixture_id': 'sd-mbr', + 'is_emmc': False, + 'devid': 1, + 'partid': None, + 'sector': 0, + 'count': 1, + 'crc32': '8f6ecf0d', }, { - "fixture_id": "sd-large", - "is_emmc": False, - "devid": 1, - "partid": None, - "sector": 0x10, - "count": 0x1000, + 'fixture_id': 'sd-large', + 'is_emmc': False, + 'devid': 1, + 'partid': None, + 'sector': 0x10, + 'count': 0x1000, }, ) """ @@ -92,9 +92,9 @@ def test_mmc_rd(u_boot_console, env__mmc_rd_config): response = u_boot_console.run_command(cmd) assert 'no card present' not in response if is_emmc: - partid_response = "(part %d)" % partid + partid_response = '(part %d)' % partid else: - partid_response = "" + partid_response = '' good_response = 'mmc%d%s is current device' % (devid, partid_response) assert good_response in response diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py index 2821ce65da8..9c395e69faf 100644 --- a/test/py/tests/test_net.py +++ b/test/py/tests/test_net.py @@ -33,27 +33,27 @@ env__net_dhcp_server = True # static IP. If solely relying on DHCP, this variable may be omitted or set to # an empty list. env__net_static_env_vars = [ - ("ipaddr", "10.0.0.100"), - ("netmask", "255.255.255.0"), - ("serverip", "10.0.0.1"), + ('ipaddr', '10.0.0.100'), + ('netmask', '255.255.255.0'), + ('serverip', '10.0.0.1'), ] # Details regarding a file that may be read from a TFTP server. This variable # may be omitted or set to None if TFTP testing is not possible or desired. env__net_tftp_readable_file = { - "fn": "ubtest-readable.bin", - "addr": 0x10000000, - "size": 5058624, - "crc32": "c2244b26", + 'fn': 'ubtest-readable.bin', + 'addr': 0x10000000, + 'size': 5058624, + 'crc32': 'c2244b26', } # Details regarding a file that may be read from a NFS server. This variable # may be omitted or set to None if NFS testing is not possible or desired. env__net_nfs_readable_file = { - "fn": "ubtest-readable.bin", - "addr": 0x10000000, - "size": 5058624, - "crc32": "c2244b26", + 'fn': 'ubtest-readable.bin', + 'addr': 0x10000000, + 'size': 5058624, + 'crc32': 'c2244b26', } """ diff --git a/test/py/tests/test_ums.py b/test/py/tests/test_ums.py index e8eb43c76b7..749b1606235 100644 --- a/test/py/tests/test_ums.py +++ b/test/py/tests/test_ums.py @@ -23,35 +23,35 @@ For example: # Leave this list empty if you have no block_devs below with writable # partitions defined. env__mount_points = ( - "/mnt/ubtest-mnt-p2371-2180-na", + '/mnt/ubtest-mnt-p2371-2180-na', ) env__usb_dev_ports = ( { - "fixture_id": "micro_b", - "tgt_usb_ctlr": "0", - "host_ums_dev_node": "/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0", + 'fixture_id': 'micro_b', + 'tgt_usb_ctlr': '0', + 'host_ums_dev_node': '/dev/disk/by-path/pci-0000:00:14.0-usb-0:13:1.0-scsi-0:0:0:0', }, ) env__block_devs = ( # eMMC; always present { - "fixture_id": "emmc", - "type": "mmc", - "id": "0", + 'fixture_id': 'emmc', + 'type': 'mmc', + 'id': '0', # The following two properties are optional. # If present, the partition will be mounted and a file written-to and # read-from it. If missing, only a simple block read test will be # performed. - "writable_fs_partition": 1, - "writable_fs_subdir": "tmp/", + 'writable_fs_partition': 1, + 'writable_fs_subdir': 'tmp/', }, # SD card; present since I plugged one in { - "fixture_id": "sd", - "type": "mmc", - "id": "1" + 'fixture_id': 'sd', + 'type': 'mmc', + 'id': '1' }, ) From f88a34defeed99dec7c4e88ef21fe40715083bb7 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 27 Dec 2018 17:03:26 +0100 Subject: [PATCH 19/58] omap3: igep00x0: Remove unmaintained IGEP0032 defconfig The IGEP0032 board was never officially pushed upstream and actually I don't have access to this hardware, unless someone with the hardware wants to start working on this doesn't makes sense have this defconfig here. So remove it. Signed-off-by: Enric Balletbo i Serra --- board/isee/igep00x0/MAINTAINERS | 1 - configs/igep0032_defconfig | 53 --------------------------------- 2 files changed, 54 deletions(-) delete mode 100644 configs/igep0032_defconfig diff --git a/board/isee/igep00x0/MAINTAINERS b/board/isee/igep00x0/MAINTAINERS index d75d400eed0..a07c9f49a85 100644 --- a/board/isee/igep00x0/MAINTAINERS +++ b/board/isee/igep00x0/MAINTAINERS @@ -4,4 +4,3 @@ S: Maintained F: board/isee/igep00x0/ F: include/configs/omap3_igep00x0.h F: configs/igep00x0_defconfig -F: configs/igep0032_defconfig diff --git a/configs/igep0032_defconfig b/configs/igep0032_defconfig deleted file mode 100644 index 20d2cf5820c..00000000000 --- a/configs/igep0032_defconfig +++ /dev/null @@ -1,53 +0,0 @@ -CONFIG_ARM=y -CONFIG_ARCH_OMAP2PLUS=y -CONFIG_TARGET_OMAP3_IGEP00X0=y -CONFIG_SPL=y -CONFIG_DISTRO_DEFAULTS=y -CONFIG_NR_DRAM_BANKS=2 -CONFIG_OF_BOARD_SETUP=y -CONFIG_BOOTDELAY=3 -CONFIG_BOOTCOMMAND="run findfdt; run distro_bootcmd" -CONFIG_SYS_CONSOLE_IS_IN_ENV=y -CONFIG_SYS_CONSOLE_INFO_QUIET=y -CONFIG_VERSION_VARIABLE=y -# CONFIG_DISPLAY_BOARDINFO is not set -# CONFIG_SPL_EXT_SUPPORT is not set -CONFIG_SPL_MTD_SUPPORT=y -CONFIG_SPL_ONENAND_SUPPORT=y -CONFIG_SPL_OS_BOOT=y -CONFIG_CMD_SPL=y -CONFIG_CMD_ASKENV=y -# CONFIG_CMD_FLASH is not set -CONFIG_CMD_GPIO=y -CONFIG_CMD_I2C=y -CONFIG_CMD_MMC=y -CONFIG_CMD_NAND=y -CONFIG_CMD_ONENAND=y -CONFIG_CMD_SPI=y -# CONFIG_CMD_SETEXPR is not set -CONFIG_CMD_CACHE=y -CONFIG_CMD_EXT4_WRITE=y -CONFIG_CMD_MTDPARTS=y -CONFIG_CMD_UBI=y -# CONFIG_CMD_UBIFS is not set -CONFIG_NET_RANDOM_ETHADDR=y -CONFIG_MMC_OMAP_HS=y -CONFIG_NAND=y -CONFIG_SYS_NAND_BUSWIDTH_16BIT=y -CONFIG_SPL_NAND_SIMPLE=y -CONFIG_SMC911X=y -CONFIG_SMC911X_BASE=0x2C000000 -CONFIG_SMC911X_32_BIT=y -CONFIG_CONS_INDEX=3 -CONFIG_SPI=y -CONFIG_OMAP3_SPI=y -CONFIG_USB=y -CONFIG_USB_MUSB_UDC=y -CONFIG_USB_OMAP3=y -CONFIG_TWL4030_USB=y -CONFIG_USB_GADGET=y -CONFIG_FAT_WRITE=y -CONFIG_UBIFS_SILENCE_MSG=y -CONFIG_BCH=y -CONFIG_OF_LIBFDT=y -CONFIG_FDT_FIXUP_PARTITIONS=y From 2432dace1199618463b6dfbd8f30dd6d14c8037d Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 27 Dec 2018 17:03:27 +0100 Subject: [PATCH 20/58] omap3: igep00x0: Remove USB support due DM_USB deadline The USB support for this board was never really tested, in fact, the presence of these options are more a copy & paste error from the Beagleboard than a feature that really was used. As doesn't work, remove for now. If someone at some point want to add this support he'll need to migrate the board to use CONFIG_DM_USB instead. Signed-off-by: Enric Balletbo i Serra --- configs/igep00x0_defconfig | 5 ----- include/configs/omap3_igep00x0.h | 10 ---------- 2 files changed, 15 deletions(-) diff --git a/configs/igep00x0_defconfig b/configs/igep00x0_defconfig index 330350c32ac..ba32609eab2 100644 --- a/configs/igep00x0_defconfig +++ b/configs/igep00x0_defconfig @@ -42,11 +42,6 @@ CONFIG_SMC911X_32_BIT=y CONFIG_CONS_INDEX=3 CONFIG_SPI=y CONFIG_OMAP3_SPI=y -CONFIG_USB=y -CONFIG_USB_MUSB_UDC=y -CONFIG_USB_OMAP3=y -CONFIG_TWL4030_USB=y -CONFIG_USB_GADGET=y CONFIG_FAT_WRITE=y CONFIG_UBIFS_SILENCE_MSG=y CONFIG_BCH=y diff --git a/include/configs/omap3_igep00x0.h b/include/configs/omap3_igep00x0.h index 775374cf288..521e1675e0e 100644 --- a/include/configs/omap3_igep00x0.h +++ b/include/configs/omap3_igep00x0.h @@ -32,16 +32,6 @@ #define GPIO_IGEP00X0_BOARD_DETECTION 28 #define GPIO_IGEP00X0_REVISION_DETECTION 129 -/* USB device configuration */ -#define CONFIG_USB_DEVICE 1 -#define CONFIG_USB_TTY 1 - -/* Change these to suit your needs */ -#define CONFIG_USBD_VENDORID 0x0451 -#define CONFIG_USBD_PRODUCTID 0x5678 -#define CONFIG_USBD_MANUFACTURER "Texas Instruments" -#define CONFIG_USBD_PRODUCT_NAME "IGEP" - #ifndef CONFIG_SPL_BUILD /* Environment */ From 829d6465b07731a8ccd0c3f71e4cfd7219491901 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 27 Dec 2018 17:03:28 +0100 Subject: [PATCH 21/58] omap3: igep00x0: Switch to using TI_COMMON_CMD_OPTION Enable TI_COMMON_CMD_OPTIONS and remove similar options from the defconfig. Signed-off-by: Enric Balletbo i Serra --- board/isee/igep00x0/Kconfig | 2 ++ configs/igep00x0_defconfig | 7 +------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/board/isee/igep00x0/Kconfig b/board/isee/igep00x0/Kconfig index aa46882b051..597d6d92cfe 100644 --- a/board/isee/igep00x0/Kconfig +++ b/board/isee/igep00x0/Kconfig @@ -9,4 +9,6 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "omap3_igep00x0" +source "board/ti/common/Kconfig" + endif diff --git a/configs/igep00x0_defconfig b/configs/igep00x0_defconfig index ba32609eab2..2c2da1e385e 100644 --- a/configs/igep00x0_defconfig +++ b/configs/igep00x0_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_OMAP2PLUS=y +CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_TARGET_OMAP3_IGEP00X0=y CONFIG_SPL=y CONFIG_DISTRO_DEFAULTS=y @@ -16,17 +17,11 @@ CONFIG_SPL_MTD_SUPPORT=y CONFIG_SPL_ONENAND_SUPPORT=y CONFIG_SPL_OS_BOOT=y CONFIG_CMD_SPL=y -CONFIG_CMD_ASKENV=y # CONFIG_CMD_FLASH is not set -CONFIG_CMD_GPIO=y -CONFIG_CMD_I2C=y -CONFIG_CMD_MMC=y CONFIG_CMD_NAND=y CONFIG_CMD_ONENAND=y -CONFIG_CMD_SPI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_CACHE=y -CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_MTDPARTS=y CONFIG_CMD_UBI=y # CONFIG_CMD_UBIFS is not set From 94b9a0cc46b68ea3a56dd8126a81dbe64091dcaa Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 27 Dec 2018 17:03:29 +0100 Subject: [PATCH 22/58] omap3: igep00x0: Switch to simple malloc in SPL To save more space, switch to simple malloc here. Signed-off-by: Enric Balletbo i Serra --- configs/igep00x0_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/igep00x0_defconfig b/configs/igep00x0_defconfig index 2c2da1e385e..b806f23fa56 100644 --- a/configs/igep00x0_defconfig +++ b/configs/igep00x0_defconfig @@ -3,6 +3,7 @@ CONFIG_ARCH_OMAP2PLUS=y CONFIG_TI_COMMON_CMD_OPTIONS=y CONFIG_TARGET_OMAP3_IGEP00X0=y CONFIG_SPL=y +CONFIG_SPL_SYS_MALLOC_SIMPLE=y CONFIG_DISTRO_DEFAULTS=y CONFIG_NR_DRAM_BANKS=2 CONFIG_OF_BOARD_SETUP=y From 8fd8f2e4fc7508df94c5a0f18a1dda047c8f6760 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 27 Dec 2018 17:03:30 +0100 Subject: [PATCH 23/58] omap3: igep00x0: Add Device Tree Support and DM_MMC driver This adds device tree for OMAP3 IGEP based boards and the DM_MMC driver. Signed-off-by: Enric Balletbo i Serra Reviewed-by: Tom Rini --- arch/arm/dts/Makefile | 3 + arch/arm/dts/omap3-igep.dtsi | 250 ++++++++++++++++++++++ arch/arm/dts/omap3-igep0020-common.dtsi | 264 ++++++++++++++++++++++++ arch/arm/dts/omap3-igep0020-u-boot.dtsi | 24 +++ arch/arm/dts/omap3-igep0020.dts | 50 +++++ configs/igep00x0_defconfig | 3 + 6 files changed, 594 insertions(+) create mode 100644 arch/arm/dts/omap3-igep.dtsi create mode 100644 arch/arm/dts/omap3-igep0020-common.dtsi create mode 100644 arch/arm/dts/omap3-igep0020-u-boot.dtsi create mode 100644 arch/arm/dts/omap3-igep0020.dts diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index dda4e594914..2f31091fddf 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -522,6 +522,9 @@ dtb-$(CONFIG_TARGET_OMAP3_BEAGLE) += \ omap3-beagle-xm.dtb \ omap3-beagle.dtb +dtb-$(CONFIG_TARGET_OMAP3_IGEP00X0) += \ + omap3-igep0020.dtb + dtb-$(CONFIG_TARGET_SAMA5D2_PTC_EK) += \ at91-sama5d2_ptc_ek.dtb diff --git a/arch/arm/dts/omap3-igep.dtsi b/arch/arm/dts/omap3-igep.dtsi new file mode 100644 index 00000000000..f33cc80c9db --- /dev/null +++ b/arch/arm/dts/omap3-igep.dtsi @@ -0,0 +1,250 @@ +/* + * Common device tree for IGEP boards based on AM/DM37x + * + * Copyright (C) 2012 Javier Martinez Canillas + * Copyright (C) 2012 Enric Balletbo i Serra + * + * 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. + */ +/dts-v1/; + +#include "omap36xx.dtsi" + +/ { + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x20000000>; /* 512 MB */ + }; + + chosen { + stdout-path = &uart3; + }; + + sound { + compatible = "ti,omap-twl4030"; + ti,model = "igep2"; + ti,mcbsp = <&mcbsp2>; + }; + + vdd33: regulator-vdd33 { + compatible = "regulator-fixed"; + regulator-name = "vdd33"; + regulator-always-on; + }; + +}; + +&omap3_pmx_core { + gpmc_pins: pinmux_gpmc_pins { + pinctrl-single,pins = < + /* OneNAND seems to require PIN_INPUT on clock. */ + OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0) /* gpmc_clk.gpmc_clk */ + >; + }; + + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */ + OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0) /* uart1_tx.uart1_tx */ + >; + }; + + uart3_pins: pinmux_uart3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx.uart3_rx */ + OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx.uart3_tx */ + >; + }; + + mcbsp2_pins: pinmux_mcbsp2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x213c, PIN_INPUT | MUX_MODE0) /* mcbsp2_fsx.mcbsp2_fsx */ + OMAP3_CORE1_IOPAD(0x213e, PIN_INPUT | MUX_MODE0) /* mcbsp2_clkx.mcbsp2_clkx */ + OMAP3_CORE1_IOPAD(0x2140, PIN_INPUT | MUX_MODE0) /* mcbsp2_dr.mcbsp2.dr */ + OMAP3_CORE1_IOPAD(0x2142, PIN_OUTPUT | MUX_MODE0) /* mcbsp2_dx.mcbsp2_dx */ + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */ + OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */ + OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat0.sdmmc1_dat0 */ + OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */ + OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */ + OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */ + >; + }; + + mmc2_pins: pinmux_mmc2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2158, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_clk.sdmmc2_clk */ + OMAP3_CORE1_IOPAD(0x215a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_cmd.sdmmc2_cmd */ + OMAP3_CORE1_IOPAD(0x215c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat0.sdmmc2_dat0 */ + OMAP3_CORE1_IOPAD(0x215e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat1.sdmmc2_dat1 */ + OMAP3_CORE1_IOPAD(0x2160, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat2.sdmmc2_dat2 */ + OMAP3_CORE1_IOPAD(0x2162, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc2_dat3.sdmmc2_dat3 */ + >; + }; + + i2c1_pins: pinmux_i2c1_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21ba, PIN_INPUT | MUX_MODE0) /* i2c1_scl.i2c1_scl */ + OMAP3_CORE1_IOPAD(0x21bc, PIN_INPUT | MUX_MODE0) /* i2c1_sda.i2c1_sda */ + >; + }; + + i2c3_pins: pinmux_i2c3_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21c2, PIN_INPUT | MUX_MODE0) /* i2c3_scl.i2c3_scl */ + OMAP3_CORE1_IOPAD(0x21c4, PIN_INPUT | MUX_MODE0) /* i2c3_sda.i2c3_sda */ + >; + }; +}; + +&gpmc { + pinctrl-names = "default"; + pinctrl-0 = <&gpmc_pins>; + + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + linux,mtd-name= "micron,mt29c4g96maz"; + nand-bus-width = <16>; + gpmc,device-width = <2>; + ti,nand-ecc-opt = "bch8"; + + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-off-ns = <40>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + + status = "okay"; + }; + + onenand@0,0 { + compatible = "ti,omap2-onenand"; + reg = <0 0 0x20000>; /* CS0, offset 0, IO size 128K */ + + gpmc,sync-read; + gpmc,sync-write; + gpmc,burst-length = <16>; + gpmc,burst-wrap; + gpmc,burst-read; + gpmc,burst-write; + gpmc,device-width = <2>; /* GPMC_DEVWIDTH_16BIT */ + gpmc,mux-add-data = <2>; /* GPMC_MUX_AD */ + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <96>; + gpmc,cs-wr-off-ns = <96>; + gpmc,adv-on-ns = <0>; + gpmc,adv-rd-off-ns = <12>; + gpmc,adv-wr-off-ns = <12>; + gpmc,oe-on-ns = <18>; + gpmc,oe-off-ns = <96>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <96>; + gpmc,rd-cycle-ns = <114>; + gpmc,wr-cycle-ns = <114>; + gpmc,access-ns = <90>; + gpmc,page-burst-access-ns = <12>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,wait-monitoring-ns = <0>; + gpmc,clk-activation-ns = <6>; + gpmc,wr-data-mux-bus-ns = <30>; + gpmc,wr-access-ns = <90>; + gpmc,sync-clk-ps = <12000>; + + #address-cells = <1>; + #size-cells = <1>; + + status = "disabled"; + }; +}; + +&i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c1_pins>; + clock-frequency = <2600000>; + + twl: twl@48 { + reg = <0x48>; + interrupts = <7>; /* SYS_NIRQ cascaded to intc */ + interrupt-parent = <&intc>; + + twl_audio: audio { + compatible = "ti,twl4030-audio"; + codec { + }; + }; + }; +}; + +#include "twl4030.dtsi" +#include "twl4030_omap3.dtsi" + +&i2c3 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c3_pins>; +}; + +&mcbsp2 { + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp2_pins>; + status = "okay"; +}; + +&mmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + vmmc-supply = <&vmmc1>; + vmmc_aux-supply = <&vsim>; + bus-width = <4>; + cd-gpios = <&twl_gpio 0 GPIO_ACTIVE_LOW>; +}; + +&mmc3 { + status = "disabled"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins>; +}; + +&twl_gpio { + ti,use-leds; +}; + +&usb_otg_hs { + interface-type = <0>; + usb-phy = <&usb2_phy>; + phys = <&usb2_phy>; + phy-names = "usb2-phy"; + mode = <3>; + power = <50>; +}; diff --git a/arch/arm/dts/omap3-igep0020-common.dtsi b/arch/arm/dts/omap3-igep0020-common.dtsi new file mode 100644 index 00000000000..ecbec23af49 --- /dev/null +++ b/arch/arm/dts/omap3-igep0020-common.dtsi @@ -0,0 +1,264 @@ +/* + * Common Device Tree Source for IGEPv2 + * + * Copyright (C) 2014 Javier Martinez Canillas + * Copyright (C) 2014 Enric Balletbo i Serra + * + * 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. + */ + +#include "omap3-igep.dtsi" +#include "omap-gpmc-smsc9221.dtsi" + +/ { + + leds { + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins>; + compatible = "gpio-leds"; + + boot { + label = "omap3:green:boot"; + gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + + user0 { + label = "omap3:red:user0"; + gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + user1 { + label = "omap3:red:user1"; + gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; + default-state = "off"; + }; + + user2 { + label = "omap3:green:user1"; + gpios = <&twl_gpio 19 GPIO_ACTIVE_LOW>; + }; + }; + + /* HS USB Port 1 Power */ + hsusb1_power: hsusb1_power_reg { + compatible = "regulator-fixed"; + regulator-name = "hsusb1_vbus"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&twl_gpio 18 GPIO_ACTIVE_LOW>; /* GPIO LEDA */ + startup-delay-us = <70000>; + }; + + /* HS USB Host PHY on PORT 1 */ + hsusb1_phy: hsusb1_phy { + compatible = "usb-nop-xceiv"; + reset-gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; /* gpio_24 */ + vcc-supply = <&hsusb1_power>; + #phy-cells = <0>; + }; + + tfp410: encoder { + compatible = "ti,tfp410"; + powerdown-gpios = <&gpio6 10 GPIO_ACTIVE_LOW>; /* gpio_170 */ + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + tfp410_in: endpoint { + remote-endpoint = <&dpi_out>; + }; + }; + + port@1 { + reg = <1>; + + tfp410_out: endpoint { + remote-endpoint = <&dvi_connector_in>; + }; + }; + }; + }; + + dvi0: connector { + compatible = "dvi-connector"; + label = "dvi"; + + digital; + + ddc-i2c-bus = <&i2c3>; + + port { + dvi_connector_in: endpoint { + remote-endpoint = <&tfp410_out>; + }; + }; + }; +}; + +&omap3_pmx_core { + pinctrl-names = "default"; + pinctrl-0 = < + &tfp410_pins + &dss_dpi_pins + >; + + tfp410_pins: pinmux_tfp410_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21c6, PIN_OUTPUT | MUX_MODE4) /* hdq_sio.gpio_170 */ + >; + }; + + dss_dpi_pins: pinmux_dss_dpi_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */ + OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */ + OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0) /* dss_vsync.dss_vsync */ + OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0) /* dss_acbias.dss_acbias */ + OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0) /* dss_data0.dss_data0 */ + OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0) /* dss_data1.dss_data1 */ + OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0) /* dss_data2.dss_data2 */ + OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0) /* dss_data3.dss_data3 */ + OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0) /* dss_data4.dss_data4 */ + OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0) /* dss_data5.dss_data5 */ + OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0) /* dss_data6.dss_data6 */ + OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0) /* dss_data7.dss_data7 */ + OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0) /* dss_data8.dss_data8 */ + OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0) /* dss_data9.dss_data9 */ + OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0) /* dss_data10.dss_data10 */ + OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0) /* dss_data11.dss_data11 */ + OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0) /* dss_data12.dss_data12 */ + OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0) /* dss_data13.dss_data13 */ + OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0) /* dss_data14.dss_data14 */ + OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0) /* dss_data15.dss_data15 */ + OMAP3_CORE1_IOPAD(0x20fc, PIN_OUTPUT | MUX_MODE0) /* dss_data16.dss_data16 */ + OMAP3_CORE1_IOPAD(0x20fe, PIN_OUTPUT | MUX_MODE0) /* dss_data17.dss_data17 */ + OMAP3_CORE1_IOPAD(0x2100, PIN_OUTPUT | MUX_MODE0) /* dss_data18.dss_data18 */ + OMAP3_CORE1_IOPAD(0x2102, PIN_OUTPUT | MUX_MODE0) /* dss_data19.dss_data19 */ + OMAP3_CORE1_IOPAD(0x2104, PIN_OUTPUT | MUX_MODE0) /* dss_data20.dss_data20 */ + OMAP3_CORE1_IOPAD(0x2106, PIN_OUTPUT | MUX_MODE0) /* dss_data21.dss_data21 */ + OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE0) /* dss_data22.dss_data22 */ + OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE0) /* dss_data23.dss_data23 */ + >; + }; + + uart2_pins: pinmux_uart2_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT | MUX_MODE0) /* uart2_cts.uart2_cts */ + OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts .uart2_rts*/ + OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0) /* uart2_tx.uart2_tx */ + OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */ + >; + }; + + smsc9221_pins: pinmux_smsc9221_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x21d2, PIN_INPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */ + >; + }; +}; + +&omap3_pmx_core2 { + pinctrl-names = "default"; + pinctrl-0 = < + &hsusbb1_pins + >; + + hsusbb1_pins: pinmux_hsusbb1_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25da, PIN_OUTPUT | MUX_MODE3) /* etk_ctl.hsusb1_clk */ + OMAP3630_CORE2_IOPAD(0x25d8, PIN_OUTPUT | MUX_MODE3) /* etk_clk.hsusb1_stp */ + OMAP3630_CORE2_IOPAD(0x25ec, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d8.hsusb1_dir */ + OMAP3630_CORE2_IOPAD(0x25ee, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d9.hsusb1_nxt */ + OMAP3630_CORE2_IOPAD(0x25dc, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d0.hsusb1_data0 */ + OMAP3630_CORE2_IOPAD(0x25de, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d1.hsusb1_data1 */ + OMAP3630_CORE2_IOPAD(0x25e0, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d2.hsusb1_data2 */ + OMAP3630_CORE2_IOPAD(0x25e2, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d3.hsusb1_data7 */ + OMAP3630_CORE2_IOPAD(0x25e4, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d4.hsusb1_data4 */ + OMAP3630_CORE2_IOPAD(0x25e6, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d5.hsusb1_data5 */ + OMAP3630_CORE2_IOPAD(0x25e8, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d6.hsusb1_data6 */ + OMAP3630_CORE2_IOPAD(0x25ea, PIN_INPUT_PULLDOWN | MUX_MODE3) /* etk_d7.hsusb1_data3 */ + >; + }; + + leds_pins: pinmux_leds_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25f4, PIN_OUTPUT | MUX_MODE4) /* etk_d12.gpio_26 */ + OMAP3630_CORE2_IOPAD(0x25f6, PIN_OUTPUT | MUX_MODE4) /* etk_d13.gpio_27 */ + OMAP3630_CORE2_IOPAD(0x25f8, PIN_OUTPUT | MUX_MODE4) /* etk_d14.gpio_28 */ + >; + }; + + mmc1_wp_pins: pinmux_mmc1_cd_pins { + pinctrl-single,pins = < + OMAP3630_CORE2_IOPAD(0x25fa, PIN_INPUT | MUX_MODE4) /* etk_d15.gpio_29 */ + >; + }; +}; + +&i2c3 { + clock-frequency = <100000>; + + /* + * Display monitor features are burnt in the EEPROM + * as EDID data. + */ + eeprom@50 { + compatible = "ti,eeprom"; + reg = <0x50>; + }; +}; + +&gpmc { + ranges = <0 0 0x30000000 0x01000000>, /* CS0: 16MB for NAND */ + <5 0 0x2c000000 0x01000000>; /* CS5: 16MB for ethernet */ + + ethernet@gpmc { + pinctrl-names = "default"; + pinctrl-0 = <&smsc9221_pins>; + reg = <5 0 0xff>; + interrupt-parent = <&gpio6>; + interrupts = <16 IRQ_TYPE_LEVEL_LOW>; + }; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; +}; + +&usbhshost { + port1-mode = "ehci-phy"; +}; + +&usbhsehci { + phys = <&hsusb1_phy>; +}; + +&vpll2 { + /* Needed for DSS */ + regulator-name = "vdds_dsi"; +}; + +&dss { + status = "ok"; + + port { + dpi_out: endpoint { + remote-endpoint = <&tfp410_in>; + data-lines = <24>; + }; + }; +}; + +&mmc1 { + pinctrl-0 = <&mmc1_pins &mmc1_wp_pins>; + wp-gpios = <&gpio1 29 GPIO_ACTIVE_LOW>; /* gpio_29 */ +}; diff --git a/arch/arm/dts/omap3-igep0020-u-boot.dtsi b/arch/arm/dts/omap3-igep0020-u-boot.dtsi new file mode 100644 index 00000000000..41beaf0900c --- /dev/null +++ b/arch/arm/dts/omap3-igep0020-u-boot.dtsi @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * U-Boot additions + * + * (C) Copyright 2017 Derald D. Woods + */ + +/ { + chosen { + stdout-path = &uart3; + }; +}; + +&uart1 { + reg-shift = <2>; +}; + +&uart2 { + reg-shift = <2>; +}; + +&uart3 { + reg-shift = <2>; +}; diff --git a/arch/arm/dts/omap3-igep0020.dts b/arch/arm/dts/omap3-igep0020.dts new file mode 100644 index 00000000000..33d6b4ead09 --- /dev/null +++ b/arch/arm/dts/omap3-igep0020.dts @@ -0,0 +1,50 @@ +/* + * Device Tree Source for IGEPv2 Rev. C (TI OMAP AM/DM37x) + * + * Copyright (C) 2012 Javier Martinez Canillas + * Copyright (C) 2012 Enric Balletbo i Serra + * + * 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. + */ + +#include "omap3-igep0020-common.dtsi" + +/ { + model = "IGEPv2 Rev. C (TI OMAP AM/DM37x)"; + compatible = "isee,omap3-igep0020", "ti,omap36xx", "ti,omap3"; + + vmmcsdio_fixed: fixedregulator-mmcsdio { + compatible = "regulator-fixed"; + regulator-name = "vmmcsdio_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + mmc2_pwrseq: mmc2_pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>, /* gpio_139 - RESET_N_W */ + <&gpio5 10 GPIO_ACTIVE_LOW>; /* gpio_138 - WIFI_PDN */ + }; +}; + +&omap3_pmx_core { + lbee1usjyc_pins: pinmux_lbee1usjyc_pins { + pinctrl-single,pins = < + OMAP3_CORE1_IOPAD(0x2166, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat5.gpio_137 - RESET_N_W */ + OMAP3_CORE1_IOPAD(0x2168, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat6.gpio_138 - WIFI_PDN */ + OMAP3_CORE1_IOPAD(0x216a, PIN_OUTPUT | MUX_MODE4) /* sdmmc2_dat7.gpio_139 - RST_N_B */ + >; + }; +}; + +/* On board Wifi module */ +&mmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&mmc2_pins &lbee1usjyc_pins>; + vmmc-supply = <&vmmcsdio_fixed>; + mmc-pwrseq = <&mmc2_pwrseq>; + bus-width = <4>; + non-removable; +}; diff --git a/configs/igep00x0_defconfig b/configs/igep00x0_defconfig index b806f23fa56..efd8519d141 100644 --- a/configs/igep00x0_defconfig +++ b/configs/igep00x0_defconfig @@ -27,6 +27,9 @@ CONFIG_CMD_MTDPARTS=y CONFIG_CMD_UBI=y # CONFIG_CMD_UBIFS is not set CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_DEFAULT_DEVICE_TREE="omap3-igep0020" +CONFIG_OF_CONTROL=y +CONFIG_DM_MMC=y CONFIG_MMC_OMAP_HS=y CONFIG_NAND=y CONFIG_SYS_NAND_BUSWIDTH_16BIT=y From e5f0878c0785535fd3646693c36ef549b42f9438 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Thu, 27 Dec 2018 17:34:11 +0100 Subject: [PATCH 24/58] am335x: sl50: Add Device Tree Support and DM_MMC driver This adds device tree and the DM_MMC driver for the SL50 board. Signed-off-by: Enric Balletbo i Serra --- arch/arm/dts/Makefile | 3 +- arch/arm/dts/am335x-sl50.dts | 549 ++++++++++++++++++++++++++++++++++ configs/am335x_sl50_defconfig | 3 + 3 files changed, 554 insertions(+), 1 deletion(-) create mode 100644 arch/arm/dts/am335x-sl50.dts diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 2f31091fddf..4b4bd806e02 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -193,7 +193,8 @@ dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb \ am335x-pxm50.dtb \ am335x-rut.dtb \ am335x-pdu001.dtb \ - am335x-chiliboard.dtb + am335x-chiliboard.dtb \ + am335x-sl50.dtb dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb \ am43x-epos-evm.dtb \ am437x-idk-evm.dtb \ diff --git a/arch/arm/dts/am335x-sl50.dts b/arch/arm/dts/am335x-sl50.dts new file mode 100644 index 00000000000..1bcc60424ec --- /dev/null +++ b/arch/arm/dts/am335x-sl50.dts @@ -0,0 +1,549 @@ +/* + * Copyright (C) 2015 Toby Churchill - http://www.toby-churchill.com/ + * + * 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. + */ +/dts-v1/; + +#include "am33xx.dtsi" + +/ { + model = "Toby Churchill SL50 Series"; + compatible = "tcl,am335x-sl50", "ti,am33xx"; + + cpus { + cpu@0 { + cpu0-supply = <&dcdc2_reg>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x20000000>; /* 512 MB */ + }; + + chosen { + stdout-path = &uart0; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&led_pins>; + + led0 { + label = "sl50:green:usr0"; + gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led1 { + label = "sl50:red:usr1"; + gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led2 { + label = "sl50:green:usr2"; + gpios = <&gpio1 23 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + + led3 { + label = "sl50:red:usr3"; + gpios = <&gpio1 24 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + backlight0: disp0 { + compatible = "pwm-backlight"; + pwms = <&ehrpwm1 0 500000 0>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>; + default-brightness-level = <6>; + }; + + backlight1: disp1 { + compatible = "pwm-backlight"; + pwms = <&ehrpwm1 1 500000 0>; + brightness-levels = <0 10 20 30 40 50 60 70 80 90 99>; + default-brightness-level = <6>; + }; + + clocks { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + /* audio external oscillator */ + tlv320aic3x_mclk: oscillator@0 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24576000>; /* 24.576MHz */ + }; + }; + + sound { + compatible = "ti,da830-evm-audio"; + ti,model = "AM335x-SL50"; + ti,audio-codec = <&audio_codec>; + ti,mcasp-controller = <&mcasp0>; + + clocks = <&tlv320aic3x_mclk>; + clock-names = "mclk"; + + ti,audio-routing = + "Headphone Jack", "HPLOUT", + "Headphone Jack", "HPROUT", + "LINE1R", "Line In", + "LINE1L", "Line In"; + }; + + emmc_pwrseq: pwrseq@0 { + compatible = "mmc-pwrseq-emmc"; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_pwrseq_pins>; + reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>; + }; + + vmmcsd_fixed: fixedregulator0 { + compatible = "regulator-fixed"; + regulator-name = "vmmcsd_fixed"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&am33xx_pinmux { + pinctrl-names = "default"; + pinctrl-0 = <&lwb_pins>; + + led_pins: pinmux_led_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7) /* gpmc_a5.gpio1_21 */ + AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7) /* gpmc_a6.gpio1_22 */ + AM33XX_IOPAD(0x85c, PIN_OUTPUT | MUX_MODE7) /* gpmc_a7.gpio1_23 */ + AM33XX_IOPAD(0x860, PIN_OUTPUT | MUX_MODE7) /* gpmc_a8.gpio1_24 */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + uart1_pins: pinmux_uart1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_rxd.uart1_rxd */ + AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */ + >; + }; + + uart4_pins: pinmux_uart4_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6) /* gpmc_wait0.uart4_rxd */ + AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* gpmc_wpn.uart4_txd */ + >; + }; + + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + i2c2_pins: pinmux_i2c2_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.i2c2_sda */ + AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.i2c2_scl */ + >; + }; + + cpsw_default: cpsw_default { + pinctrl-single,pins = < + /* Slave 1 */ + AM33XX_IOPAD(0x910, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */ + AM33XX_IOPAD(0x914, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */ + AM33XX_IOPAD(0x918, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */ + AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */ + AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */ + AM33XX_IOPAD(0x924, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */ + AM33XX_IOPAD(0x928, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */ + AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */ + AM33XX_IOPAD(0x930, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */ + AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */ + AM33XX_IOPAD(0x938, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */ + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */ + AM33XX_IOPAD(0x940, PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */ + >; + }; + + cpsw_sleep: cpsw_sleep { + pinctrl-single,pins = < + /* Slave 1 reset value */ + AM33XX_IOPAD(0x910, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x914, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x918, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x91c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x920, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x924, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x928, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x92c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x930, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x934, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x938, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x93c, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x940, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + davinci_mdio_default: davinci_mdio_default { + pinctrl-single,pins = < + /* MDIO */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ + AM33XX_IOPAD(0x94c, PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ + >; + }; + + davinci_mdio_sleep: davinci_mdio_sleep { + pinctrl-single,pins = < + /* MDIO reset value */ + AM33XX_IOPAD(0x948, PIN_INPUT_PULLDOWN | MUX_MODE7) + AM33XX_IOPAD(0x94c, PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; + + mmc1_pins: pinmux_mmc1_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x96c, PIN_INPUT | MUX_MODE7) /* uart0_rtsn.gpio1_9 */ + >; + }; + + emmc_pwrseq_pins: pinmux_emmc_pwrseq_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x850, PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a4.gpio1_20 */ + >; + }; + + emmc_pins: pinmux_emmc_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x880, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ + AM33XX_IOPAD(0x884, PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ + AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ + AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */ + AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */ + AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */ + AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */ + >; + }; + + audio_pins: pinmux_audio_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9ac, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */ + AM33XX_IOPAD(0x994, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_fsx.mcasp0_fsx */ + AM33XX_IOPAD(0x990, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_aclkx.mcasp0_aclkx */ + AM33XX_IOPAD(0x998, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mcasp0_axr0.mcasp0_axr0 */ + AM33XX_IOPAD(0x99c, PIN_OUTPUT_PULLDOWN | MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2 */ + >; + }; + + ehrpwm1_pins: pinmux_ehrpwm1a_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x848, PIN_OUTPUT | MUX_MODE6) /* gpmc_a2.ehrpwm1a */ + AM33XX_IOPAD(0x84c, PIN_OUTPUT | MUX_MODE6) /* gpmc_a3.ehrpwm1b */ + >; + }; + + spi0_pins: pinmux_spi0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* SPI0_MOSI - spi0_d0.spi0_d0 */ + AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* SPI0_MISO - spi0_d1.spi0_d1 */ + AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* SPI0_CLK - spi0_clk.spi0_clk */ + AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* SPI0_CS0 (NBATTSS) - spi0_cs0.spi0_cs0 */ + AM33XX_IOPAD(0x960, PIN_INPUT_PULLUP | MUX_MODE0) /* SPI0_CS1 (FPGA_FLASH_NCS) - spi0_cs1.spi0_cs1 */ + >; + }; + + lwb_pins: pinmux_lwb_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9a4, PIN_OUTPUT | MUX_MODE7) /* SoundPA_en - mcasp0_fsr.gpio3_19 */ + AM33XX_IOPAD(0x828, PIN_OUTPUT | MUX_MODE7) /* nKbdOnC - gpmc_ad10.gpio0_26 */ + AM33XX_IOPAD(0x830, PIN_INPUT_PULLUP | MUX_MODE7) /* nKbdInt - gpmc_ad12.gpio1_12 */ + AM33XX_IOPAD(0x834, PIN_INPUT_PULLUP | MUX_MODE7) /* nKbdReset - gpmc_ad13.gpio1_13 */ + AM33XX_IOPAD(0x838, PIN_INPUT_PULLUP | MUX_MODE7) /* nDispReset - gpmc_ad14.gpio1_14 */ + AM33XX_IOPAD(0x844, PIN_INPUT_PULLUP | MUX_MODE7) /* USB1_enPower - gpmc_a1.gpio1_17 */ + /* PDI Bus - Battery system */ + AM33XX_IOPAD(0x840, PIN_INPUT_PULLUP | MUX_MODE7) /* nBattReset gpmc_a0.gpio1_16 */ + AM33XX_IOPAD(0x83c, PIN_INPUT_PULLUP | MUX_MODE7) /* BattPDIData gpmc_ad15.gpio1_15 */ + >; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + clock-frequency = <400000>; + + tps: tps@24 { + reg = <0x24>; + }; + + bq32000: rtc@68 { + compatible = "ti,bq32000"; + trickle-resistor-ohms = <1120>; + reg = <0x68>; + }; + + eeprom: eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + }; + + gpio_exp: mcp23017@20 { + compatible = "microchip,mcp23017"; + reg = <0x20>; + }; + +}; + +&i2c2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins>; + + clock-frequency = <400000>; + + audio_codec: tlv320aic3106@1b { + status = "okay"; + compatible = "ti,tlv320aic3106"; + reg = <0x1b>; + + AVDD-supply = <&ldo4_reg>; + IOVDD-supply = <&ldo4_reg>; + DRVDD-supply = <&ldo4_reg>; + DVDD-supply = <&ldo3_reg>; + }; + + /* Ambient Light Sensor */ + als: isl29023@44 { + compatible = "isil,isl29023"; + reg = <0x44>; + }; +}; + +&rtc { + status = "disabled"; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +&mmc1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&mmc1_pins>; + bus-width = <4>; + cd-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; + vmmc-supply = <&vmmcsd_fixed>; +}; + +&mmc2 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_pins>; + bus-width = <8>; + vmmc-supply = <&vmmcsd_fixed>; + mmc-pwrseq = <&emmc_pwrseq>; +}; + +&mcasp0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&audio_pins>; + + op-mode = <0>; /* MCASP_ISS_MODE */ + tdm-slots = <2>; + serial-dir = < + 2 0 1 0 + 0 0 0 0 + 0 0 0 0 + 0 0 0 0 + >; + tx-num-evt = <1>; + rx-num-evt = <1>; +}; + +&uart0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; +}; + +&uart1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart1_pins>; +}; + +&uart4 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins>; +}; + +&spi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&spi0_pins>; + + flash: n25q032@1 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "micron,n25q032"; + reg = <1>; + spi-max-frequency = <5000000>; + }; +}; + +#include "tps65217.dtsi" + +&tps { + ti,pmic-shutdown-controller; + + interrupt-parent = <&intc>; + interrupts = <7>; /* NNMI */ + + regulators { + dcdc1_reg: regulator@0 { + /* VDDS_DDR */ + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <1500000>; + regulator-always-on; + }; + + dcdc2_reg: regulator@1 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1325000>; + regulator-boot-on; + regulator-always-on; + }; + + dcdc3_reg: regulator@2 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <925000>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + ldo1_reg: regulator@3 { + /* VRTC / VIO / VDDS*/ + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + ldo2_reg: regulator@4 { + /* VDD_3V3AUX */ + regulator-always-on; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + ldo3_reg: regulator@5 { + /* VDD_1V8 */ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + ldo4_reg: regulator@6 { + /* VDD_3V3A */ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "mii"; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "mii"; +}; + +&mac { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&cpsw_default>; + pinctrl-1 = <&cpsw_sleep>; +}; + +&davinci_mdio { + status = "okay"; + pinctrl-names = "default", "sleep"; + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; +}; + +&sham { + status = "okay"; +}; + +&aes { + status = "okay"; +}; + +&epwmss1 { + status = "okay"; +}; + +&ehrpwm1 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&ehrpwm1_pins>; +}; diff --git a/configs/am335x_sl50_defconfig b/configs/am335x_sl50_defconfig index 822f73d1142..8c622471da8 100644 --- a/configs/am335x_sl50_defconfig +++ b/configs/am335x_sl50_defconfig @@ -40,6 +40,9 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_BOOTCOUNT_LIMIT=y +CONFIG_DEFAULT_DEVICE_TREE="am335x-sl50" +CONFIG_OF_CONTROL=y +CONFIG_DM_MMC=y CONFIG_MMC_OMAP_HS=y CONFIG_MII=y CONFIG_DRIVER_TI_CPSW=y From 9a878e8f1714cade4021c997f68b7f86321c0421 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 28 Dec 2018 11:55:48 +0100 Subject: [PATCH 25/58] am335x: igep003x: Add Device Tree Support and DM_MMC driver This adds device tree and the DM_MMC driver for the AM335x IGEP based boards. Signed-off-by: Enric Balletbo i Serra --- arch/arm/dts/Makefile | 3 +- arch/arm/dts/am335x-base0033.dts | 95 +++++++++ arch/arm/dts/am335x-igep0033.dtsi | 323 ++++++++++++++++++++++++++++++ configs/am335x_igep003x_defconfig | 3 + 4 files changed, 423 insertions(+), 1 deletion(-) create mode 100644 arch/arm/dts/am335x-base0033.dts create mode 100644 arch/arm/dts/am335x-igep0033.dtsi diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 4b4bd806e02..b2ca87deefd 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -194,7 +194,8 @@ dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-bone.dtb \ am335x-rut.dtb \ am335x-pdu001.dtb \ am335x-chiliboard.dtb \ - am335x-sl50.dtb + am335x-sl50.dtb \ + am335x-base0033.dtb dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb \ am43x-epos-evm.dtb \ am437x-idk-evm.dtb \ diff --git a/arch/arm/dts/am335x-base0033.dts b/arch/arm/dts/am335x-base0033.dts new file mode 100644 index 00000000000..29782be0760 --- /dev/null +++ b/arch/arm/dts/am335x-base0033.dts @@ -0,0 +1,95 @@ +/* + * am335x-base0033.dts - Device Tree file for IGEP AQUILA EXPANSION + * + * Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz + * + * 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. + */ + +#include "am335x-igep0033.dtsi" + +/ { + model = "IGEP COM AM335x on AQUILA Expansion"; + compatible = "isee,am335x-base0033", "isee,am335x-igep0033", "ti,am33xx"; + + hdmi { + compatible = "ti,tilcdc,slave"; + i2c = <&i2c0>; + pinctrl-names = "default", "off"; + pinctrl-0 = <&nxp_hdmi_pins>; + pinctrl-1 = <&nxp_hdmi_off_pins>; + status = "okay"; + }; + + leds_base { + pinctrl-names = "default"; + pinctrl-0 = <&leds_base_pins>; + + compatible = "gpio-leds"; + + led0 { + label = "base:red:user"; + gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; /* gpio1_21 */ + default-state = "off"; + }; + + led1 { + label = "base:green:user"; + gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>; /* gpio2_0 */ + default-state = "off"; + }; + }; +}; + +&am33xx_pinmux { + nxp_hdmi_pins: pinmux_nxp_hdmi_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */ + AM33XX_IOPAD(0x8a0, PIN_OUTPUT | MUX_MODE0) /* lcd_data0 */ + AM33XX_IOPAD(0x8a4, PIN_OUTPUT | MUX_MODE0) /* lcd_data1 */ + AM33XX_IOPAD(0x8a8, PIN_OUTPUT | MUX_MODE0) /* lcd_data2 */ + AM33XX_IOPAD(0x8ac, PIN_OUTPUT | MUX_MODE0) /* lcd_data3 */ + AM33XX_IOPAD(0x8b0, PIN_OUTPUT | MUX_MODE0) /* lcd_data4 */ + AM33XX_IOPAD(0x8b4, PIN_OUTPUT | MUX_MODE0) /* lcd_data5 */ + AM33XX_IOPAD(0x8b8, PIN_OUTPUT | MUX_MODE0) /* lcd_data6 */ + AM33XX_IOPAD(0x8bc, PIN_OUTPUT | MUX_MODE0) /* lcd_data7 */ + AM33XX_IOPAD(0x8c0, PIN_OUTPUT | MUX_MODE0) /* lcd_data8 */ + AM33XX_IOPAD(0x8c4, PIN_OUTPUT | MUX_MODE0) /* lcd_data9 */ + AM33XX_IOPAD(0x8c8, PIN_OUTPUT | MUX_MODE0) /* lcd_data10 */ + AM33XX_IOPAD(0x8cc, PIN_OUTPUT | MUX_MODE0) /* lcd_data11 */ + AM33XX_IOPAD(0x8d0, PIN_OUTPUT | MUX_MODE0) /* lcd_data12 */ + AM33XX_IOPAD(0x8d4, PIN_OUTPUT | MUX_MODE0) /* lcd_data13 */ + AM33XX_IOPAD(0x8d8, PIN_OUTPUT | MUX_MODE0) /* lcd_data14 */ + AM33XX_IOPAD(0x8dc, PIN_OUTPUT | MUX_MODE0) /* lcd_data15 */ + AM33XX_IOPAD(0x8e0, PIN_OUTPUT | MUX_MODE0) /* lcd_vsync */ + AM33XX_IOPAD(0x8e4, PIN_OUTPUT | MUX_MODE0) /* lcd_hsync */ + AM33XX_IOPAD(0x8e8, PIN_OUTPUT | MUX_MODE0) /* lcd_pclk */ + AM33XX_IOPAD(0x8ec, PIN_OUTPUT | MUX_MODE0) /* lcd_ac_bias_en */ + >; + }; + nxp_hdmi_off_pins: pinmux_nxp_hdmi_off_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x9b0, PIN_OUTPUT | MUX_MODE3) /* xdma_event_intr0.clkout1 */ + >; + }; + + leds_base_pins: pinmux_leds_base_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x854, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */ + AM33XX_IOPAD(0x888, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn3.gpio2_0 */ + >; + }; +}; + +&lcdc { + status = "okay"; +}; + +&i2c0 { + eeprom: eeprom@50 { + compatible = "atmel,24c256"; + reg = <0x50>; + }; +}; diff --git a/arch/arm/dts/am335x-igep0033.dtsi b/arch/arm/dts/am335x-igep0033.dtsi new file mode 100644 index 00000000000..a5769a8f5fc --- /dev/null +++ b/arch/arm/dts/am335x-igep0033.dtsi @@ -0,0 +1,323 @@ +/* + * am335x-igep0033.dtsi - Device Tree file for IGEP COM AQUILA AM335x + * + * Copyright (C) 2013 ISEE 2007 SL - http://www.isee.biz + * + * 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. + */ + +/dts-v1/; + +#include "am33xx.dtsi" +#include + +/ { + cpus { + cpu@0 { + cpu0-supply = <&vdd1_reg>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; + + leds { + pinctrl-names = "default"; + pinctrl-0 = <&leds_pins>; + + compatible = "gpio-leds"; + + led0 { + label = "com:green:user"; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + }; + + vbat: fixedregulator0 { + compatible = "regulator-fixed"; + regulator-name = "vbat"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-boot-on; + }; + + vmmc: fixedregulator1 { + compatible = "regulator-fixed"; + regulator-name = "vmmc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; +}; + +&am33xx_pinmux { + i2c0_pins: pinmux_i2c0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ + AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ + >; + }; + + nandflash_pins: pinmux_nandflash_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x800, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad0.gpmc_ad0 */ + AM33XX_IOPAD(0x804, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad1.gpmc_ad1 */ + AM33XX_IOPAD(0x808, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad2.gpmc_ad2 */ + AM33XX_IOPAD(0x80c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad3.gpmc_ad3 */ + AM33XX_IOPAD(0x810, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad4.gpmc_ad4 */ + AM33XX_IOPAD(0x814, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad5.gpmc_ad5 */ + AM33XX_IOPAD(0x818, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad6.gpmc_ad6 */ + AM33XX_IOPAD(0x81c, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_ad7.gpmc_ad7 */ + AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE0) /* gpmc_wait0.gpmc_wait0 */ + AM33XX_IOPAD(0x874, PIN_INPUT_PULLUP | MUX_MODE7) /* gpmc_wpn.gpio0_30 */ + AM33XX_IOPAD(0x87c, PIN_OUTPUT | MUX_MODE0) /* gpmc_csn0.gpmc_csn0 */ + AM33XX_IOPAD(0x890, PIN_OUTPUT | MUX_MODE0) /* gpmc_advn_ale.gpmc_advn_ale */ + AM33XX_IOPAD(0x894, PIN_OUTPUT | MUX_MODE0) /* gpmc_oen_ren.gpmc_oen_ren */ + AM33XX_IOPAD(0x898, PIN_OUTPUT | MUX_MODE0) /* gpmc_wen.gpmc_wen */ + AM33XX_IOPAD(0x89c, PIN_OUTPUT | MUX_MODE0) /* gpmc_be0n_cle.gpmc_be0n_cle */ + >; + }; + + uart0_pins: pinmux_uart0_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ + AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ + >; + }; + + leds_pins: pinmux_leds_pins { + pinctrl-single,pins = < + AM33XX_IOPAD(0x85c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */ + >; + }; +}; + +&mac { + status = "okay"; +}; + +&davinci_mdio { + status = "okay"; +}; + +&cpsw_emac0 { + phy_id = <&davinci_mdio>, <0>; + phy-mode = "rmii"; +}; + +&cpsw_emac1 { + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rmii"; +}; + +&phy_sel { + rmii-clock-ext; +}; + +&elm { + status = "okay"; +}; + +&gpmc { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&nandflash_pins>; + + ranges = <0 0 0x08000000 0x1000000>; /* CS0: 16MB for NAND */ + + nand@0,0 { + compatible = "ti,omap2-nand"; + reg = <0 0 4>; /* CS0, offset 0, IO size 4 */ + interrupt-parent = <&gpmc>; + interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */ + <1 IRQ_TYPE_NONE>; /* termcount */ + rb-gpios = <&gpmc 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */ + nand-bus-width = <8>; + ti,nand-ecc-opt = "bch8"; + gpmc,device-width = <1>; + gpmc,sync-clk-ps = <0>; + gpmc,cs-on-ns = <0>; + gpmc,cs-rd-off-ns = <44>; + gpmc,cs-wr-off-ns = <44>; + gpmc,adv-on-ns = <6>; + gpmc,adv-rd-off-ns = <34>; + gpmc,adv-wr-off-ns = <44>; + gpmc,we-on-ns = <0>; + gpmc,we-off-ns = <40>; + gpmc,oe-on-ns = <0>; + gpmc,oe-off-ns = <54>; + gpmc,access-ns = <64>; + gpmc,rd-cycle-ns = <82>; + gpmc,wr-cycle-ns = <82>; + gpmc,bus-turnaround-ns = <0>; + gpmc,cycle2cycle-delay-ns = <0>; + gpmc,clk-activation-ns = <0>; + gpmc,wr-access-ns = <40>; + gpmc,wr-data-mux-bus-ns = <0>; + + #address-cells = <1>; + #size-cells = <1>; + ti,elm-id = <&elm>; + + /* MTD partition table */ + partition@0 { + label = "SPL"; + reg = <0x00000000 0x000080000>; + }; + + partition@1 { + label = "U-boot"; + reg = <0x00080000 0x001e0000>; + }; + + partition@2 { + label = "U-Boot Env"; + reg = <0x00260000 0x00020000>; + }; + + partition@3 { + label = "Kernel"; + reg = <0x00280000 0x00500000>; + }; + + partition@4 { + label = "File System"; + reg = <0x00780000 0x007880000>; + }; + }; +}; + +&i2c0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&i2c0_pins>; + + clock-frequency = <400000>; + + tps: tps@2d { + reg = <0x2d>; + }; +}; + +&mmc1 { + status = "okay"; + vmmc-supply = <&vmmc>; + bus-width = <4>; +}; + +&uart0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pins>; +}; + +&usb { + status = "okay"; +}; + +&usb_ctrl_mod { + status = "okay"; +}; + +&usb0_phy { + status = "okay"; +}; + +&usb1_phy { + status = "okay"; +}; + +&usb0 { + status = "okay"; +}; + +&usb1 { + status = "okay"; + dr_mode = "host"; +}; + +&cppi41dma { + status = "okay"; +}; + +#include "tps65910.dtsi" + +&tps { + vcc1-supply = <&vbat>; + vcc2-supply = <&vbat>; + vcc3-supply = <&vbat>; + vcc4-supply = <&vbat>; + vcc5-supply = <&vbat>; + vcc6-supply = <&vbat>; + vcc7-supply = <&vbat>; + vccio-supply = <&vbat>; + + regulators { + vrtc_reg: regulator@0 { + regulator-always-on; + }; + + vio_reg: regulator@1 { + regulator-always-on; + }; + + vdd1_reg: regulator@2 { + /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ + regulator-name = "vdd_mpu"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1312500>; + regulator-boot-on; + regulator-always-on; + }; + + vdd2_reg: regulator@3 { + /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ + regulator-name = "vdd_core"; + regulator-min-microvolt = <912500>; + regulator-max-microvolt = <1150000>; + regulator-boot-on; + regulator-always-on; + }; + + vdd3_reg: regulator@4 { + regulator-always-on; + }; + + vdig1_reg: regulator@5 { + regulator-always-on; + }; + + vdig2_reg: regulator@6 { + regulator-always-on; + }; + + vpll_reg: regulator@7 { + regulator-always-on; + }; + + vdac_reg: regulator@8 { + regulator-always-on; + }; + + vaux1_reg: regulator@9 { + regulator-always-on; + }; + + vaux2_reg: regulator@10 { + regulator-always-on; + }; + + vaux33_reg: regulator@11 { + regulator-always-on; + }; + + vmmc_reg: regulator@12 { + regulator-always-on; + }; + }; +}; + diff --git a/configs/am335x_igep003x_defconfig b/configs/am335x_igep003x_defconfig index 186c65f0bf6..0a8feadc753 100644 --- a/configs/am335x_igep003x_defconfig +++ b/configs/am335x_igep003x_defconfig @@ -41,6 +41,9 @@ CONFIG_CMD_UBI=y # CONFIG_CMD_UBIFS is not set CONFIG_ENV_IS_IN_UBI=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y +CONFIG_DEFAULT_DEVICE_TREE="am335x-base0033" +CONFIG_OF_CONTROL=y +CONFIG_DM_MMC=y CONFIG_MMC_OMAP_HS=y CONFIG_NAND=y CONFIG_MTD_UBI_FASTMAP=y From b9a2a0e2e9c024009010a9755d5377795f660b1a Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Jan 2019 21:19:24 +0100 Subject: [PATCH 26/58] mmc: Add support for downgrading HS200/HS400 to HS mode The mmc_select_mode_and_width() function can be called while the card is in HS200/HS400 mode and can be used to downgrade the card to lower mode, e.g. HS. This is used for example by mmc_boot_part_access_chk() which cannot access the card in HS200/HS400 mode and which is in turn called by saveenv if env is in the MMC. In such case, forcing the card clock to legacy frequency cannot work. Instead, the card must be switched to HS mode first, from which it can then be reprogrammed as needed. However, this procedure needs additional code changes, since the current implementation checks whether the card correctly switched to HS mode in mmc_set_card_speed(). The check only expects that the card will be going to HS mode from lower modes, not from higher modes, hence add a parameter which indicates that the HS200/HS400 to HS downgrade is happening. This makes the code send the switch command first, reconfigure the controller next and finally perform the EXT_CSD readback check. The last two steps cannot be done in reverse order as the card is already in HS mode when the clock are being switched on the controller side. Signed-off-by: Marek Vasut Cc: Jaehoon Chung --- drivers/mmc/mmc.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d8581271321..84d157ff403 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -754,7 +754,8 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) } #if !CONFIG_IS_ENABLED(MMC_TINY) -static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode) +static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode, + bool hsdowngrade) { int err; int speed_bits; @@ -788,6 +789,20 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode) if (err) return err; +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ + CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + /* + * In case the eMMC is in HS200/HS400 mode and we are downgrading + * to HS mode, the card clock are still running much faster than + * the supported HS mode clock, so we can not reliably read out + * Extended CSD. Reconfigure the controller to run at HS mode. + */ + if (hsdowngrade) { + mmc_select_mode(mmc, MMC_HS); + mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false); + } +#endif + if ((mode == MMC_HS) || (mode == MMC_HS_52)) { /* Now check to see that it worked */ err = mmc_send_ext_csd(mmc, test_csd); @@ -1849,7 +1864,7 @@ static int mmc_select_hs400(struct mmc *mmc) int err; /* Set timing to HS200 for tuning */ - err = mmc_set_card_speed(mmc, MMC_HS_200); + err = mmc_set_card_speed(mmc, MMC_HS_200, false); if (err) return err; @@ -1865,7 +1880,7 @@ static int mmc_select_hs400(struct mmc *mmc) } /* Set back to HS */ - mmc_set_card_speed(mmc, MMC_HS); + mmc_set_card_speed(mmc, MMC_HS, false); mmc_set_clock(mmc, mmc_mode2freq(mmc, MMC_HS), false); err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, @@ -1873,7 +1888,7 @@ static int mmc_select_hs400(struct mmc *mmc) if (err) return err; - err = mmc_set_card_speed(mmc, MMC_HS_400); + err = mmc_set_card_speed(mmc, MMC_HS_400, false); if (err) return err; @@ -1920,7 +1935,19 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) return -ENOTSUPP; } - mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE); +#if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ + CONFIG_IS_ENABLED(MMC_HS400_SUPPORT) + /* + * In case the eMMC is in HS200/HS400 mode, downgrade to HS mode + * before doing anything else, since a transition from either of + * the HS200/HS400 mode directly to legacy mode is not supported. + */ + if (mmc->selected_mode == MMC_HS_200 || + mmc->selected_mode == MMC_HS_400) + mmc_set_card_speed(mmc, MMC_HS, true); + else +#endif + mmc_set_clock(mmc, mmc->legacy_speed, MMC_CLK_ENABLE); for_each_mmc_mode_by_pref(card_caps, mwt) { for_each_supported_width(card_caps & mwt->widths, @@ -1952,7 +1979,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) } } else { /* configure the bus speed (card) */ - err = mmc_set_card_speed(mmc, mwt->mode); + err = mmc_set_card_speed(mmc, mwt->mode, false); if (err) goto error; From d2a083696e403aa34288638fcef943deedaf1492 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Jan 2019 22:09:43 +0100 Subject: [PATCH 27/58] cmd: mmc: Force mmc reinit when no card present In case the card is removed, force-init the MMC to start the internal machinery which deregisters and invalidate the MMC device. Signed-off-by: Marek Vasut Cc: Jaehoon Chung --- cmd/mmc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/mmc.c b/cmd/mmc.c index 3920a1836a5..ca8f982f53f 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -101,6 +101,9 @@ static struct mmc *init_mmc_device(int dev, bool force_init) return NULL; } + if (!mmc_getcd(mmc)) + force_init = true; + if (force_init) mmc->has_init = 0; if (mmc_init(mmc)) From 1d044d323d1eaa5731028a2d288bf53c1151e1fc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 3 Jan 2019 22:09:44 +0100 Subject: [PATCH 28/58] cmd: mmc: Invalidate MMC block cache after init Make sure the block cache is cleared for the MMC device after it was reinitialized to avoid having any stale data in the cache, like e.g. partition tables or such. Signed-off-by: Marek Vasut Cc: Jaehoon Chung --- cmd/mmc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmd/mmc.c b/cmd/mmc.c index ca8f982f53f..9951315f911 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -108,6 +108,12 @@ static struct mmc *init_mmc_device(int dev, bool force_init) mmc->has_init = 0; if (mmc_init(mmc)) return NULL; + +#ifdef CONFIG_BLOCK_CACHE + struct blk_desc *bd = mmc_get_blk_desc(mmc); + blkcache_invalidate(bd->if_type, bd->devnum); +#endif + return mmc; } static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) From 6e00104880d73f21076f443085f102d323d25b0f Mon Sep 17 00:00:00 2001 From: Patrice Chotard Date: Fri, 4 Jan 2019 11:48:55 +0100 Subject: [PATCH 29/58] configs: stm32: Remove CONFIG_OF_EMBED Building with CONFIG_OF_EMBED generates build warnings, as it should only be used for debugging purposes. Remove CONFIG_OF_EMBED from all stm32 config files which are using this flag. Signed-off-by: Patrice Chotard --- configs/stm32f429-discovery_defconfig | 1 - configs/stm32f429-evaluation_defconfig | 1 - configs/stm32f469-discovery_defconfig | 1 - configs/stm32h743-disco_defconfig | 1 - configs/stm32h743-eval_defconfig | 1 - 5 files changed, 5 deletions(-) diff --git a/configs/stm32f429-discovery_defconfig b/configs/stm32f429-discovery_defconfig index ef0f6f7373d..265b1ec0682 100644 --- a/configs/stm32f429-discovery_defconfig +++ b/configs/stm32f429-discovery_defconfig @@ -20,7 +20,6 @@ CONFIG_CMD_IMLS=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIMER=y CONFIG_OF_CONTROL=y -CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="stm32f429-disco" CONFIG_ENV_IS_IN_FLASH=y # CONFIG_MMC is not set diff --git a/configs/stm32f429-evaluation_defconfig b/configs/stm32f429-evaluation_defconfig index 6a2ed2a9b06..9f1a7680ad0 100644 --- a/configs/stm32f429-evaluation_defconfig +++ b/configs/stm32f429-evaluation_defconfig @@ -23,7 +23,6 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIMER=y # CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y -CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="stm32429i-eval" CONFIG_DM_MMC=y CONFIG_ARM_PL180_MMCI=y diff --git a/configs/stm32f469-discovery_defconfig b/configs/stm32f469-discovery_defconfig index 0b36c0fc583..801af6bb618 100644 --- a/configs/stm32f469-discovery_defconfig +++ b/configs/stm32f469-discovery_defconfig @@ -23,7 +23,6 @@ CONFIG_CMD_CACHE=y CONFIG_CMD_TIMER=y # CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y -CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="stm32f469-disco" CONFIG_DM_MMC=y CONFIG_ARM_PL180_MMCI=y diff --git a/configs/stm32h743-disco_defconfig b/configs/stm32h743-disco_defconfig index 92d21d180b6..5460ad029a3 100644 --- a/configs/stm32h743-disco_defconfig +++ b/configs/stm32h743-disco_defconfig @@ -23,7 +23,6 @@ CONFIG_CMD_TIMER=y CONFIG_CMD_EXT4_WRITE=y # CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y -CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="stm32h743i-disco" CONFIG_DM_MMC=y CONFIG_STM32_SDMMC2=y diff --git a/configs/stm32h743-eval_defconfig b/configs/stm32h743-eval_defconfig index c08363d1368..2884c96648d 100644 --- a/configs/stm32h743-eval_defconfig +++ b/configs/stm32h743-eval_defconfig @@ -23,7 +23,6 @@ CONFIG_CMD_TIMER=y CONFIG_CMD_EXT4_WRITE=y # CONFIG_ISO_PARTITION is not set CONFIG_OF_CONTROL=y -CONFIG_OF_EMBED=y CONFIG_DEFAULT_DEVICE_TREE="stm32h743i-eval" CONFIG_DM_MMC=y CONFIG_STM32_SDMMC2=y From b1970013d4da5579cf33f0da84715d49d9690d49 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 11:31:54 +0100 Subject: [PATCH 30/58] cmd: gpio: use correct printf code gpio is defined as unsigned int. So we should use %u when calling printf(). Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- cmd/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/gpio.c b/cmd/gpio.c index ecdc453918f..c60946bc069 100644 --- a/cmd/gpio.c +++ b/cmd/gpio.c @@ -213,7 +213,7 @@ static int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } gpio_direction_output(gpio, value); } - printf("gpio: pin %s (gpio %i) value is ", str_gpio, gpio); + printf("gpio: pin %s (gpio %u) value is ", str_gpio, gpio); if (IS_ERR_VALUE(value)) printf("unknown (ret=%d)\n", value); else From 82919517fbda20f616507386919791cb03581d39 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 11:52:06 +0100 Subject: [PATCH 31/58] cmd: nvedit: use correct format code len is defined as unsigned. So use %u for printf(). Signed-off-by: Heinrich Schuchardt --- cmd/nvedit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/nvedit.c b/cmd/nvedit.c index de16c72c23f..ebaa16b7545 100644 --- a/cmd/nvedit.c +++ b/cmd/nvedit.c @@ -708,8 +708,8 @@ int env_get_f(const char *name, char *buf, unsigned len) if (n) *--buf = '\0'; - printf("env_buf [%d bytes] too small for value of \"%s\"\n", - len, name); + printf("env_buf [%u bytes] too small for value of \"%s\"\n", + len, name); return n; } From c6b2ea379ce6867f18897b45beacfea138c53a31 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 12:03:37 +0100 Subject: [PATCH 32/58] cmd: sf: use correct printf code test->time_ms[] is defined as unsigned. So use %u for printf(). Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- cmd/sf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/sf.c b/cmd/sf.c index 84bb0575f23..738ef0e46dc 100644 --- a/cmd/sf.c +++ b/cmd/sf.c @@ -413,7 +413,7 @@ static void show_time(struct test_info *test, int stage) do_div(speed, test->time_ms[stage] * 1024); bps = speed * 8; - printf("%d %s: %d ticks, %d KiB/s %d.%03d Mbps\n", stage, + printf("%d %s: %u ticks, %d KiB/s %d.%03d Mbps\n", stage, stage_name[stage], test->time_ms[stage], (int)speed, bps / 1000, bps % 1000); } From 1d1af2ae5afe18d9ea7037201b241e963ac7307e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 12:09:10 +0100 Subject: [PATCH 33/58] cmd: tpm-v2: use correct format code updates is defined as unsigned int. So use %u for printf(). Signed-off-by: Heinrich Schuchardt --- cmd/tpm-v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/tpm-v2.c b/cmd/tpm-v2.c index bb51834c478..459a955d290 100644 --- a/cmd/tpm-v2.c +++ b/cmd/tpm-v2.c @@ -151,7 +151,7 @@ static int do_tpm_pcr_read(cmd_tbl_t *cmdtp, int flag, int argc, rc = tpm2_pcr_read(dev, index, priv->pcr_select_min, data, &updates); if (!rc) { - printf("PCR #%u content (%d known updates):\n", index, updates); + printf("PCR #%u content (%u known updates):\n", index, updates); print_byte_string(data, TPM2_DIGEST_LEN); } From 76428561b343daafc163e4bf1d6b5e8f5454d63a Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 12:26:28 +0100 Subject: [PATCH 34/58] cmd: ubi: remove unreachable code It does not make sense to check if argc < 2 a second time, especially after accessing argv[1]. Signed-off-by: Heinrich Schuchardt --- cmd/ubi.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cmd/ubi.c b/cmd/ubi.c index a12ac703ebe..c511a2fb760 100644 --- a/cmd/ubi.c +++ b/cmd/ubi.c @@ -472,12 +472,8 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc < 2) return CMD_RET_USAGE; - if (strcmp(argv[1], "detach") == 0) { - if (argc < 2) - return CMD_RET_USAGE; - + if (strcmp(argv[1], "detach") == 0) return ubi_detach(); - } if (strcmp(argv[1], "part") == 0) { const char *vid_header_offset = NULL; From 9ae2ddc82e80e937e5da235a4c66fc3af5c91fc7 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 12:34:16 +0100 Subject: [PATCH 35/58] cmd: unzip: use correct format code src_len is defined as unsigned long. So use %lu for printf(). Signed-off-by: Heinrich Schuchardt --- cmd/unzip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/unzip.c b/cmd/unzip.c index f7aabf72d1e..6c0f97cb4bb 100644 --- a/cmd/unzip.c +++ b/cmd/unzip.c @@ -27,7 +27,7 @@ static int do_unzip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (gunzip((void *) dst, dst_len, (void *) src, &src_len) != 0) return 1; - printf("Uncompressed size: %ld = 0x%lX\n", src_len, src_len); + printf("Uncompressed size: %lu = 0x%lX\n", src_len, src_len); env_set_hex("filesize", src_len); return 0; From d667090999236ddbf8bbbc98dc576bf301db59d0 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 6 Jan 2019 12:38:37 +0100 Subject: [PATCH 36/58] cmd: zip: use correct format code dst_len is defined as unsigned long. So use %lu for printf(). Signed-off-by: Heinrich Schuchardt --- cmd/zip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/zip.c b/cmd/zip.c index d105d84e380..9cd400a7e80 100644 --- a/cmd/zip.c +++ b/cmd/zip.c @@ -28,7 +28,7 @@ static int do_zip(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (gzip((void *) dst, &dst_len, (void *) src, src_len) != 0) return 1; - printf("Compressed size: %ld = 0x%lX\n", dst_len, dst_len); + printf("Compressed size: %lu = 0x%lX\n", dst_len, dst_len); env_set_hex("filesize", dst_len); return 0; From 7d05d3a8e35f888ec3f90f66fe53a7c381c06d10 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Mon, 7 Jan 2019 20:29:26 +0100 Subject: [PATCH 37/58] dtoc: make generated platdata structs const The platdata initialization structs are currently generated into .rwdata. Make sure the are put into .rodata by generating them as const. Signed-off-by: Simon Goldschmidt Reviewed-by: Simon Glass --- tools/dtoc/dtb_platdata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index 6cb12594466..ca580b45d4a 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -461,7 +461,7 @@ class DtbPlatdata(object): """ struct_name, _ = get_compat_name(node) var_name = conv_name_to_c(node.name) - self.buf('static struct %s%s %s%s = {\n' % + self.buf('static const struct %s%s %s%s = {\n' % (STRUCT_PREFIX, struct_name, VAL_PREFIX, var_name)) for pname, prop in node.props.items(): if pname in PROP_IGNORE_LIST or pname[0] == '#': From 92e5cb804ae69a6e58ba49f6ca2e57934e541d88 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 7 Jan 2019 21:23:22 +0100 Subject: [PATCH 38/58] spl: ymodem: Add support for loading gzip compressed uImage Add support for gunzip-ing gzip-compressed uImages in the SPL Ymodem code. Loading data over Ymodem can be gruelingly slow, gzip-ing the data can reduce that aggravating slowness at least slightly (depends on the data, u-boot.bin compresses to ~1/3 of it's original size on ARM64), hence add optional support for decompressing gzip-compressed uImages. Signed-off-by: Marek Vasut Cc: Tom Rini --- common/spl/spl_ymodem.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/common/spl/spl_ymodem.c b/common/spl/spl_ymodem.c index 3b1bd71bda0..577fdc69afe 100644 --- a/common/spl/spl_ymodem.c +++ b/common/spl/spl_ymodem.c @@ -69,12 +69,13 @@ static ulong ymodem_read_fit(struct spl_load_info *load, ulong offset, static int spl_ymodem_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - int size = 0; + ulong size = 0; int err; int res; int ret; connection_info_t info; char buf[BUF_SIZE]; + struct image_header *ih; ulong addr = 0; info.mode = xyzModem_ymodem; @@ -107,12 +108,18 @@ static int spl_ymodem_load_image(struct spl_image_info *spl_image, while ((res = xyzModem_stream_read(buf, BUF_SIZE, &err)) > 0) size += res; } else { - ret = spl_parse_image_header(spl_image, - (struct image_header *)buf); + ih = (struct image_header *)buf; + ret = spl_parse_image_header(spl_image, ih); if (ret) return ret; - addr = spl_image->load_addr; +#ifdef CONFIG_SPL_GZIP + if (ih->ih_comp == IH_COMP_GZIP) + addr = CONFIG_SYS_LOAD_ADDR; + else +#endif + addr = spl_image->load_addr; memcpy((void *)addr, buf, res); + ih = (struct image_header *)addr; size += res; addr += res; @@ -121,13 +128,25 @@ static int spl_ymodem_load_image(struct spl_image_info *spl_image, size += res; addr += res; } + +#ifdef CONFIG_SPL_GZIP + if (ih->ih_comp == IH_COMP_GZIP) { + if (gunzip((void *)(spl_image->load_addr + sizeof(*ih)), + CONFIG_SYS_BOOTM_LEN, + (void *)(CONFIG_SYS_LOAD_ADDR + sizeof(*ih)), + &size)) { + puts("Uncompressing error\n"); + return -EIO; + } + } +#endif } end_stream: xyzModem_stream_close(&err); xyzModem_stream_terminate(false, &getcymodem); - printf("Loaded %d bytes\n", size); + printf("Loaded %lu bytes\n", size); return 0; } SPL_LOAD_IMAGE_METHOD("UART", 0, BOOT_DEVICE_UART, spl_ymodem_load_image); From 05f6da3fac8abf4356f4cc7ed5904943eec82535 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Mon, 7 Jan 2019 21:23:38 +0100 Subject: [PATCH 39/58] lib: uuid: Do not enable UUID command SPL The uuid command is only really useful in U-Boot, but it's useless in SPL. Worse yet, it pulls in various environment manipulation functions as it call env_set(). Do not compile the command in in SPL. Signed-off-by: Marek Vasut Cc: Tom Rini --- lib/uuid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/uuid.c b/lib/uuid.c index 5d5adf6b2df..fa20ee39fc3 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -271,7 +271,7 @@ void gen_rand_uuid_str(char *uuid_str, int str_format) uuid_bin_to_str(uuid_bin, uuid_str, str_format); } -#ifdef CONFIG_CMD_UUID +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CMD_UUID) int do_uuid(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { char uuid[UUID_STR_LEN + 1]; From 03e6151d5bb42fd055e9c1e571440359bd5b5282 Mon Sep 17 00:00:00 2001 From: Josef Lusticky Date: Tue, 8 Jan 2019 14:19:46 +0100 Subject: [PATCH 40/58] pylibfdt: Use Python 2 in Makefile pylibfdt needs Python 2 to build. Replace $(PYTHON) with $(PYTHON2) in pylibfdt Makefile to ensure Python 2 is used to build it. This fixes build on systems where Python 3 is the default version of the "python" interpreter. Reviewed-by: Simon Glass --- scripts/dtc/pylibfdt/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/dtc/pylibfdt/Makefile b/scripts/dtc/pylibfdt/Makefile index c769d7db062..15e66ad44d7 100644 --- a/scripts/dtc/pylibfdt/Makefile +++ b/scripts/dtc/pylibfdt/Makefile @@ -21,7 +21,7 @@ quiet_cmd_pymod = PYMOD $@ CPPFLAGS="$(HOSTCFLAGS) -I$(LIBFDT_srcdir)" OBJDIR=$(obj) \ SOURCES="$(PYLIBFDT_srcs)" \ SWIG_OPTS="-I$(LIBFDT_srcdir) -I$(LIBFDT_srcdir)/.." \ - $(PYTHON) $< --quiet build_ext --inplace + $(PYTHON2) $< --quiet build_ext --inplace $(obj)/_libfdt.so: $(src)/setup.py $(PYLIBFDT_srcs) FORCE $(call if_changed,pymod) From a4773c5559867f8fc6b0c1a7eb8ab36cfd53756f Mon Sep 17 00:00:00 2001 From: Lokesh Vutla Date: Tue, 8 Jan 2019 19:28:35 +0530 Subject: [PATCH 41/58] xyz-modem: Fix timeout loop waiting with WATCHDOG Commit 2c77c0d6524eb ("xyz-modem: Change getc timeout loop waiting") fixes the loop delay when using a hw watchdog, assuming that watchdog kicking is taken care of by getc(). But the xyzmodem driver tries to do a getc only after confirming that a character is available like below: while (!tstc()) { till timeout; } if (tstc()) *c = getc(); and getc() does a watchdog reset only if it fails to see a character. In this case, getc() always sees a character and never does a watchdog reset. So to make sure that watchdog doesn't get reset while loading the file, do a watchdog reset just before starting the image loading. Signed-off-by: Lokesh Vutla Signed-off-by: Vignesh R Reviewed-by: Simon Glass --- common/xyzModem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/xyzModem.c b/common/xyzModem.c index e5c65b480a2..e85da74a698 100644 --- a/common/xyzModem.c +++ b/common/xyzModem.c @@ -25,6 +25,7 @@ #include #include #include +#include /* Assumption - run xyzModem protocol over the console port */ @@ -63,6 +64,7 @@ CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c) { ulong now = get_timer(0); + WATCHDOG_RESET(); while (!tstc ()) { if (get_timer(now) > xyzModem_CHAR_TIMEOUT) From bb5835bc018dc8d7cc4d7abf0ef0521be5093985 Mon Sep 17 00:00:00 2001 From: Vagrant Cascadian Date: Tue, 8 Jan 2019 13:10:23 -0800 Subject: [PATCH 42/58] Fix typo: missmatched -> mismatched. Signed-off-by: Vagrant Cascadian Reviewed-by: Peng Fan --- tools/imx8image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/imx8image.c b/tools/imx8image.c index 0d856b9d94f..435f308b99e 100644 --- a/tools/imx8image.c +++ b/tools/imx8image.c @@ -674,7 +674,7 @@ static int get_container_image_start_pos(image_t *image_stack, uint32_t align) fclose(fd); if (header.tag != IVT_HEADER_TAG_B0) { - fprintf(stderr, "header tag missmatched \n"); + fprintf(stderr, "header tag mismatched \n"); exit(EXIT_FAILURE); } else { file_off += From 7828e3cf70513d7bd3a2bcefd52802633c78affd Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Wed, 9 Jan 2019 20:27:09 +0100 Subject: [PATCH 43/58] drivers: serial: DEBUG_UART_SKIP_INIT depends on DEBUG_UART DEBUG_UART_SKIP_INIT is used only by debug UART and thus should depend on DEBUG_UART. Signed-off-by: Simon Goldschmidt Reviewed-by: Simon Glass --- drivers/serial/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b7ff2960abf..e67ea523388 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -442,6 +442,7 @@ config DEBUG_UART_ANNOUNCE config DEBUG_UART_SKIP_INIT bool "Skip UART initialization" + depends on DEBUG_UART help Select this if the UART you want to use for debug output is already initialized by the time U-Boot starts its execution. From c4448bdc4fb398478bc8499cfcf85fca3c36ad08 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Wed, 9 Jan 2019 20:35:31 +0100 Subject: [PATCH 44/58] serial: ns16550: fix debug uart putc called before init If _debug_uart_putc() is called before _debug_uart_init(), the ns16550 debug uart driver hangs in a tight loop waiting for the tx FIFO to get empty. As this can happen via a printf sneaking in before the port calls debug_uart_init(), introduce a config option to ignore characters before the debug uart is initialized. This is done by reading the baudrate divisor and aborting if is zero. The Kconfig option is required as reading the baudrate divisor does not seem to work for all ns16500 compatibles (which is why the last attempt on this has been reverted in 1a67969a99). Tested on socfpga_cyclone5_socrates. Signed-off-by: Simon Goldschmidt Reviewed-by: Simon Glass --- drivers/serial/Kconfig | 12 ++++++++++++ drivers/serial/ns16550.c | 20 ++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index e67ea523388..887cd687c02 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -447,6 +447,18 @@ config DEBUG_UART_SKIP_INIT Select this if the UART you want to use for debug output is already initialized by the time U-Boot starts its execution. +config DEBUG_UART_NS16550_CHECK_ENABLED + bool "Check if UART is enabled on output" + depends on DEBUG_UART + depends on DEBUG_UART_NS16550 + help + Select this if puts()/putc() might be called before the debug UART + has been initialized. If this is disabled, putc() might sit in a + tight loop if it is called before debug_uart_init() has been called. + + Note that this does not work for every ns16550-compatible UART and + so has to be enabled carefully or you might notice lost characters. + config ALTERA_JTAG_UART bool "Altera JTAG UART support" depends on DM_SERIAL diff --git a/drivers/serial/ns16550.c b/drivers/serial/ns16550.c index 560ca2ae349..6cf2be8f2b8 100644 --- a/drivers/serial/ns16550.c +++ b/drivers/serial/ns16550.c @@ -272,12 +272,28 @@ static inline void _debug_uart_init(void) serial_dout(&com_port->lcr, UART_LCRVAL); } +static inline int NS16550_read_baud_divisor(struct NS16550 *com_port) +{ + int ret; + + serial_dout(&com_port->lcr, UART_LCR_BKSE | UART_LCRVAL); + ret = serial_din(&com_port->dll) & 0xff; + ret |= (serial_din(&com_port->dlm) & 0xff) << 8; + serial_dout(&com_port->lcr, UART_LCRVAL); + + return ret; +} + static inline void _debug_uart_putc(int ch) { struct NS16550 *com_port = (struct NS16550 *)CONFIG_DEBUG_UART_BASE; - while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) - ; + while (!(serial_din(&com_port->lsr) & UART_LSR_THRE)) { +#ifdef CONFIG_DEBUG_UART_NS16550_CHECK_ENABLED + if (!NS16550_read_baud_divisor(com_port)) + return; +#endif + } serial_dout(&com_port->thr, ch); } From 0b588deffe5f925dbef96945e6c3b5ab65be6a33 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 10 Jan 2019 23:11:39 +0900 Subject: [PATCH 45/58] kbuild: fix parallel build race caused by u-boot.cfg regeneration Multiple people have reported intermittent build failure in parallel building. Kever Yang reported this issue some time ago [1], but I could not get enough clue at that time. This time, Richard Purdie provided a full build log [2], which was very helpful for me to root-cause it. The cause of the problem is commit 0d982c585330 ("Makefile: add dependencies to regenerate u-boot.cfg when lost"). That commit added the 'cfg' as the prerequisite of the 'all' target, so the parallel build tries to run it simultaneously, then regenerates a symlink while building objects. When u-boot.cfg is accidentally lost, let's rebuild it before descending into any subdirectories. Also, what is annoying is u-boot.cfg is currently regenerated every time since it depends on FORCE. We can get rid of all the prerequisites of u-boot.cfg because u-boot.cfg is rebuilt anyway as the byproduct of auto.conf when a user updates the .config file. [1] https://lists.denx.de/pipermail/u-boot/2018-June/330341.html [2] https://autobuilder.yoctoproject.org/typhoon/#/builders/65/builds/160/steps/7/logs/step1b Fixes: 0d982c585330 ("Makefile: add dependencies to regenerate u-boot.cfg when lost") Reported-by: Kever Yang Reported-by: Richard Purdie Signed-off-by: Masahiro Yamada Reviewed-by: Simon Glass --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 6aa08964fff..47bf90bccb5 100644 --- a/Makefile +++ b/Makefile @@ -534,7 +534,7 @@ include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd @# Otherwise, 'make silentoldconfig' would be invoked twice. $(Q)touch include/config/auto.conf -u-boot.cfg spl/u-boot.cfg tpl/u-boot.cfg: include/config.h FORCE +u-boot.cfg spl/u-boot.cfg tpl/u-boot.cfg: $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.autoconf $(@) -include include/autoconf.mk @@ -910,7 +910,7 @@ quiet_cmd_cfgcheck = CFGCHK $2 cmd_cfgcheck = $(srctree)/scripts/check-config.sh $2 \ $(srctree)/scripts/config_whitelist.txt $(srctree) -all: $(ALL-y) cfg +all: $(ALL-y) ifeq ($(CONFIG_DM_I2C_COMPAT)$(CONFIG_SANDBOX),y) @echo >&2 "===================== WARNING ======================" @echo >&2 "This board uses CONFIG_DM_I2C_COMPAT. Please remove" @@ -1555,7 +1555,7 @@ ifneq ($(KBUILD_SRC),) endif # prepare2 creates a makefile if using a separate output directory -prepare2: prepare3 outputmakefile +prepare2: prepare3 outputmakefile cfg prepare1: prepare2 $(version_h) $(timestamp_h) \ include/config/auto.conf From f75977303d64bc346c34a0bb8a6d9c7eaa67b00b Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Fri, 11 Jan 2019 15:30:50 +1300 Subject: [PATCH 46/58] common: Kconfig: miscellaneous spelling fixes Signed-off-by: Chris Packham Reviewed-by: Simon Glass --- common/Kconfig | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/common/Kconfig b/common/Kconfig index 57bd16d9623..2c017df4087 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -308,7 +308,7 @@ config SILENT_CONSOLE help This option allows the console to be silenced, meaning that no output will appear on the console devices. This is controlled by - setting the environment vaariable 'silent' to a non-empty value. + setting the environment variable 'silent' to a non-empty value. Note this also silences the console when booting Linux. When the console is set up, the variable is checked, and the @@ -430,7 +430,7 @@ config SYS_CONSOLE_INFO_QUIET help Normally U-Boot displays the current settings for stdout, stdin and stderr on boot when the post-relocation console is set up. - Enable this option to supress this output. It can be obtained by + Enable this option to suppress this output. It can be obtained by calling stdio_print_current_devices() from board code. config SYS_STDIO_DEREGISTER @@ -565,14 +565,14 @@ config LOG_TEST This enables a 'log test' command to test logging. It is normally executed from a pytest and simply outputs logging information in various different ways to test that the logging system works - correctly with varoius settings. + correctly with various settings. config LOG_ERROR_RETURN bool "Log all functions which return an error" depends on LOG help When an error is returned in U-Boot it is sometimes difficult to - figure out the root cause. For eaxmple, reading from SPI flash may + figure out the root cause. For example, reading from SPI flash may fail due to a problem in the SPI controller or due to the flash part not returning the expected information. This option changes log_ret() to log any errors it sees. With this option disabled, @@ -661,7 +661,7 @@ config ARCH_MISC_INIT With this option U-Boot will call arch_misc_init() after relocation to allow miscellaneous arch-dependent initialisation to be performed. This function should be defined by the board - and will be called after the console is set up, after relocaiton. + and will be called after the console is set up, after relocation. config BOARD_EARLY_INIT_F bool "Call board-specific init before relocation" From 368a0dfbf8ab283f792f5aabf436463254a8f577 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 11 Jan 2019 19:42:26 +0900 Subject: [PATCH 47/58] kbuild: add .DELETE_ON_ERROR special target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linux commit 9c2af1c7377a8a6ef86e5cabf80978f3dbbb25c0 If Make gets a fatal signal while a shell is executing, it may delete the target file that the recipe was supposed to update. This is needed to make sure that it is remade from scratch when Make is next run; if Make is interrupted after the recipe has begun to write the target file, it results in an incomplete file whose time stamp is newer than that of the prerequisites files. Make automatically deletes the incomplete file on interrupt unless the target is marked .PRECIOUS. The situation is just the same as when the shell fails for some reasons. Usually when a recipe line fails, if it has changed the target file at all, the file is corrupted, or at least it is not completely updated. Yet the file’s time stamp says that it is now up to date, so the next time Make runs, it will not try to update that file. However, Make does not cater to delete the incomplete target file in this case. We need to add .DELETE_ON_ERROR somewhere in the Makefile to request it. scripts/Kbuild.include seems a suitable place to add it because it is included from almost all sub-makes. Signed-off-by: Masahiro Yamada --- scripts/Kbuild.include | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 13ebddda65c..460acd61f9e 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -315,6 +315,9 @@ why = \ echo-why = $(call escsq, $(strip $(why))) endif +# delete partially updated (i.e. corrupted) files on error +.DELETE_ON_ERROR: + ifdef CONFIG_SPL_BUILD SPL_ := SPL_ ifeq ($(CONFIG_TPL_BUILD),y) From c16b137e490308f5578dae9e7896a8798493c475 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 11 Jan 2019 19:42:27 +0900 Subject: [PATCH 48/58] kbuild: add .SECONDARY special target to scripts/Kbuild.include Based on the following Linux commits: - 54a702f70589 ("kbuild: mark $(targets) as .SECONDARY and remove .PRECIOUS markers") - 8e9b61b293d9 ("kbuild: move .SECONDARY special target to Kbuild.include") GNU Make automatically deletes intermediate files that are updated in a chain of pattern rules. Example 1) %.dtb.o <- %.dtb.S <- %.dtb <- %.dts Example 2) %.o <- %.c <- %.c_shipped A couple of makefiles mark such targets as .PRECIOUS to prevent Make from deleting them, but the correct way is to use .SECONDARY. .SECONDARY Prerequisites of this special target are treated as intermediate files but are never automatically deleted. .PRECIOUS When make is interrupted during execution, it may delete the target file it is updating if the file was modified since make started. If you mark the file as precious, make will never delete the file if interrupted. Both can avoid deletion of intermediate files, but the difference is the behavior when Make is interrupted; .SECONDARY deletes the target, but .PRECIOUS does not. The use of .PRECIOUS is relatively rare since we do not want to keep partially constructed (possibly corrupted) targets. .SECONDARY with no prerequisites causes all targets to be treated as secondary. This agrees the policy of Kbuild. scripts/Kbuild.include seems a suitable place to add it because it is included from almost all sub-makes. Signed-off-by: Masahiro Yamada --- dts/Makefile | 3 --- examples/standalone/Makefile | 1 - post/lib_powerpc/fpu/Makefile | 3 --- scripts/Kbuild.include | 3 +++ scripts/Makefile.build | 2 -- scripts/Makefile.lib | 3 --- 6 files changed, 3 insertions(+), 12 deletions(-) diff --git a/dts/Makefile b/dts/Makefile index cd6e9a968ee..a7a604303cc 100644 --- a/dts/Makefile +++ b/dts/Makefile @@ -43,9 +43,6 @@ endif arch-dtbs: $(Q)$(MAKE) $(build)=$(ARCH_PATH) dtbs -.SECONDARY: $(obj)/dt.dtb.S $(obj)/dt-spl.dtb.S - - ifeq ($(CONFIG_SPL_BUILD),y) obj-$(CONFIG_OF_EMBED) := dt-spl.dtb.o # support "out-of-tree" build for dtb-spl diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile index f01816f24f4..0b17a91804c 100644 --- a/examples/standalone/Makefile +++ b/examples/standalone/Makefile @@ -26,7 +26,6 @@ LIB = $(obj)/libstubs.o LIBOBJS-$(CONFIG_PPC) += ppc_longjmp.o ppc_setjmp.o LIBOBJS-y += stubs.o -.SECONDARY: $(call objectify,$(COBJS)) targets += $(patsubst $(obj)/%,%,$(LIB)) $(COBJS) $(LIBOBJS-y) LIBOBJS := $(addprefix $(obj)/,$(LIBOBJS-y)) diff --git a/post/lib_powerpc/fpu/Makefile b/post/lib_powerpc/fpu/Makefile index 404eefcfd0f..9b2c1fadb65 100644 --- a/post/lib_powerpc/fpu/Makefile +++ b/post/lib_powerpc/fpu/Makefile @@ -11,9 +11,6 @@ targets += $(objs-before-objcopy) $(foreach m, $(objs-before-objcopy), $(eval CFLAGS_REMOVE_$m := -msoft-float)) ccflags-y := -mhard-float -fkeep-inline-functions -# Do not delete intermidiate files (*.o) -.SECONDARY: $(call objectify, $(objs-before-objcopy)) - obj-y := $(objs-before-objcopy:.o=_.o) OBJCOPYFLAGS := -R .gnu.attributes diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 460acd61f9e..b8969e2a75e 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -318,6 +318,9 @@ endif # delete partially updated (i.e. corrupted) files on error .DELETE_ON_ERROR: +# do not delete intermediate files automatically +.SECONDARY: + ifdef CONFIG_SPL_BUILD SPL_ := SPL_ ifeq ($(CONFIG_TPL_BUILD),y) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 482ed0c8d80..f7a041296d3 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -331,8 +331,6 @@ quiet_cmd_asn1_compiler = ASN.1 $@ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \ $(subst .h,.c,$@) $(subst .c,.h,$@) -.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h - $(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler $(call cmd,asn1_compiler) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index a4f16bb4bb5..a5b57fc6b98 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -214,7 +214,6 @@ endef quiet_cmd_flex = LEX $@ cmd_flex = $(LEX) -o$@ -L $< -.PRECIOUS: $(obj)/%.lex.c $(obj)/%.lex.c: $(src)/%.l FORCE $(call if_changed,flex) @@ -223,14 +222,12 @@ $(obj)/%.lex.c: $(src)/%.l FORCE quiet_cmd_bison = YACC $@ cmd_bison = $(YACC) -o$@ -t -l $< -.PRECIOUS: $(obj)/%.tab.c $(obj)/%.tab.c: $(src)/%.y FORCE $(call if_changed,bison) quiet_cmd_bison_h = YACC $@ cmd_bison_h = $(YACC) -o/dev/null --defines=$@ -t -l $< -.PRECIOUS: $(obj)/%.tab.h $(obj)/%.tab.h: $(src)/%.y FORCE $(call if_changed,bison_h) From 45297e2ab2172470b0b04e1ae728a31ab7321601 Mon Sep 17 00:00:00 2001 From: Simon Goldschmidt Date: Fri, 11 Jan 2019 20:56:02 +0100 Subject: [PATCH 49/58] Makefile: run CONFIG_BOARD_SIZE_LIMIT against .img With the current Makefile, CONFIG_BOARD_SIZE_LIMIT is used to check the U-Boot binary without devicetree only. This produces wrong results when OF_SEPARATE is used. To fix this, run the CONFIG_BOARD_SIZE_LIMIT check on all .img binaries as well. Signed-off-by: Simon Goldschmidt Reviewed-by: Simon Glass --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 47bf90bccb5..3be9fc5c340 100644 --- a/Makefile +++ b/Makefile @@ -1198,6 +1198,7 @@ MKIMAGEFLAGS_u-boot.pbl = -n $(srctree)/$(CONFIG_SYS_FSL_PBL_RCW:"%"=%) \ u-boot-dtb.img u-boot.img u-boot.kwb u-boot.pbl u-boot-ivt.img: \ $(if $(CONFIG_SPL_LOAD_FIT),u-boot-nodtb.bin dts/dt.dtb,u-boot.bin) FORCE $(call if_changed,mkimage) + $(BOARD_SIZE_CHECK) u-boot.itb: u-boot-nodtb.bin dts/dt.dtb $(U_BOOT_ITS) FORCE $(call if_changed,mkfitimage) From 2e89bbefdc9c1d2ec03e2a5320a56fb1129da916 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Wed, 8 Aug 2018 13:20:29 +0200 Subject: [PATCH 50/58] blk: Increase cache element size Cache up to 4 kiB entries. 4 kiB is the default block size on ext4, yet the underlying block layer devices usually report support for 512B . In most cases, the 512B support is emulated (ie. SD cards, SSDs, USB sticks etc.) and the real block size of those devices is much bigger. To avoid performance degradation with such devices and FS setup, bump the maximum cache entry size to 4 kiB. Signed-off-by: Marek Vasut Cc: Tom Rini Cc: Simon Glass Reviewed-by: Tom Rini --- drivers/block/blkcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/blkcache.c b/drivers/block/blkcache.c index 294511fcdb5..1fa64989d3f 100644 --- a/drivers/block/blkcache.c +++ b/drivers/block/blkcache.c @@ -24,7 +24,7 @@ struct block_cache_node { static LIST_HEAD(block_cache); static struct block_cache_stats _stats = { - .max_blocks_per_entry = 2, + .max_blocks_per_entry = 8, .max_entries = 32 }; From cbe07ebeafb7b67785844830c7562adc4a1f9dbf Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 3 Dec 2018 22:54:18 +0100 Subject: [PATCH 51/58] common: command: Fix command auto-completion When auto-completing command arguments, the last argument is not necessarily the one we need to auto-complete. When the last character is a space, a tab or '\0' what we want instead is list all possible values, or if there's only one possible value, place this value on the command line instead of trying to suffix the last valid argument with missing chars. Signed-off-by: Boris Brezillon Reviewed-by: Tom Rini --- common/command.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/common/command.c b/common/command.c index 2433a89e0a8..435824356b5 100644 --- a/common/command.c +++ b/common/command.c @@ -362,13 +362,21 @@ int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp) sep = NULL; seplen = 0; if (i == 1) { /* one match; perfect */ - k = strlen(argv[argc - 1]); + if (last_char != '\0' && !isblank(last_char)) + k = strlen(argv[argc - 1]); + else + k = 0; + s = cmdv[0] + k; len = strlen(s); sep = " "; seplen = 1; } else if (i > 1 && (j = find_common_prefix(cmdv)) != 0) { /* more */ - k = strlen(argv[argc - 1]); + if (last_char != '\0' && !isblank(last_char)) + k = strlen(argv[argc - 1]); + else + k = 0; + j -= k; if (j > 0) { s = cmdv[0] + k; From 6fb61445bb28a37397fdce5cb2d3f5ffd0e1a4e4 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 3 Dec 2018 22:54:19 +0100 Subject: [PATCH 52/58] common: command: Expose a generic helper to auto-complete sub commands Some commands have a table of sub-commands. With minor adjustments, complete_cmdv() is able to provide auto-completion for sub-commands (it's just about passing the table of commands instead of taking the global one). We rename this function into complete_subcmd() and implement complete_cmdv() as a wrapper around complete_subcmdv(). Signed-off-by: Boris Brezillon Reviewed-by: Tom Rini --- common/command.c | 20 ++++++++++++++++---- include/command.h | 3 +++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/common/command.c b/common/command.c index 435824356b5..e13cb47ac18 100644 --- a/common/command.c +++ b/common/command.c @@ -161,11 +161,11 @@ int var_complete(int argc, char * const argv[], char last_char, int maxv, char * /*************************************************************************************/ -static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]) +int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc, + char * const argv[], char last_char, + int maxv, char *cmdv[]) { #ifdef CONFIG_CMDLINE - cmd_tbl_t *cmdtp = ll_entry_start(cmd_tbl_t, cmd); - const int count = ll_entry_count(cmd_tbl_t, cmd); const cmd_tbl_t *cmdend = cmdtp + count; const char *p; int len, clen; @@ -193,7 +193,7 @@ static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv /* more than one arg or one but the start of the next */ if (argc > 1 || last_char == '\0' || isblank(last_char)) { - cmdtp = find_cmd(argv[0]); + cmdtp = find_cmd_tbl(argv[0], cmdtp, count); if (cmdtp == NULL || cmdtp->complete == NULL) { cmdv[0] = NULL; return 0; @@ -238,6 +238,18 @@ static int complete_cmdv(int argc, char * const argv[], char last_char, int maxv #endif } +static int complete_cmdv(int argc, char * const argv[], char last_char, + int maxv, char *cmdv[]) +{ +#ifdef CONFIG_CMDLINE + return complete_subcmdv(ll_entry_start(cmd_tbl_t, cmd), + ll_entry_count(cmd_tbl_t, cmd), argc, argv, + last_char, maxv, cmdv); +#else + return 0; +#endif +} + static int make_argv(char *s, int argvsz, char *argv[]) { int argc = 0; diff --git a/include/command.h b/include/command.h index 200c7a5e9f4..89efcecfa92 100644 --- a/include/command.h +++ b/include/command.h @@ -54,6 +54,9 @@ int _do_help (cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]); cmd_tbl_t *find_cmd(const char *cmd); cmd_tbl_t *find_cmd_tbl (const char *cmd, cmd_tbl_t *table, int table_len); +int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc, + char * const argv[], char last_char, int maxv, + char *cmdv[]); extern int cmd_usage(const cmd_tbl_t *cmdtp); From 80a48dd47e3bf3ede676fae5a630cb6c80de3e69 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 3 Dec 2018 22:54:20 +0100 Subject: [PATCH 53/58] common: command: Rework the 'cmd is repeatable' logic The repeatable property is currently attached to the main command and sub-commands have no way to change the repeatable value (the ->repeatable field in sub-command entries is ignored). Replace the ->repeatable field by an extended ->cmd() hook (called ->cmd_rep()) which takes a new int pointer to store the repeatable cap of the command being executed. With this trick, we can let sub-commands decide whether they are repeatable or not. We also patch mmc and dtimg who are testing the ->repeatable field directly (they now use cmd_is_repeatable() instead), and fix the help entry manually since it doesn't use the U_BOOT_CMD() macro. Signed-off-by: Boris Brezillon Reviewed-by: Tom Rini --- cmd/dtimg.c | 2 +- cmd/help.c | 2 +- cmd/mmc.c | 4 ++-- common/command.c | 36 ++++++++++++++++++++++++++++---- include/command.h | 52 +++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 84 insertions(+), 12 deletions(-) diff --git a/cmd/dtimg.c b/cmd/dtimg.c index 65c8d101b98..ae7d82f26dd 100644 --- a/cmd/dtimg.c +++ b/cmd/dtimg.c @@ -116,7 +116,7 @@ static int do_dtimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!cp || argc > cp->maxargs) return CMD_RET_USAGE; - if (flag == CMD_FLAG_REPEAT && !cp->repeatable) + if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) return CMD_RET_SUCCESS; return cp->cmd(cmdtp, flag, argc, argv); diff --git a/cmd/help.c b/cmd/help.c index 503fa632e74..fa2010c67eb 100644 --- a/cmd/help.c +++ b/cmd/help.c @@ -29,7 +29,7 @@ U_BOOT_CMD( /* This does not use the U_BOOT_CMD macro as ? can't be used in symbol names */ ll_entry_declare(cmd_tbl_t, question_mark, cmd) = { - "?", CONFIG_SYS_MAXARGS, 1, do_help, + "?", CONFIG_SYS_MAXARGS, cmd_always_repeatable, do_help, "alias for 'help'", #ifdef CONFIG_SYS_LONGHELP "" diff --git a/cmd/mmc.c b/cmd/mmc.c index 9951315f911..8bc3648193c 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -256,7 +256,7 @@ static int do_mmcrpmb(cmd_tbl_t *cmdtp, int flag, if (cp == NULL || argc > cp->maxargs) return CMD_RET_USAGE; - if (flag == CMD_FLAG_REPEAT && !cp->repeatable) + if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) return CMD_RET_SUCCESS; mmc = init_mmc_device(curr_device, false); @@ -916,7 +916,7 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (cp == NULL || argc > cp->maxargs) return CMD_RET_USAGE; - if (flag == CMD_FLAG_REPEAT && !cp->repeatable) + if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp)) return CMD_RET_SUCCESS; if (curr_device < 0) { diff --git a/common/command.c b/common/command.c index e13cb47ac18..19f0534a76e 100644 --- a/common/command.c +++ b/common/command.c @@ -501,6 +501,30 @@ void fixup_cmdtable(cmd_tbl_t *cmdtp, int size) } #endif +int cmd_always_repeatable(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[], int *repeatable) +{ + *repeatable = 1; + + return cmdtp->cmd(cmdtp, flag, argc, argv); +} + +int cmd_never_repeatable(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[], int *repeatable) +{ + *repeatable = 0; + + return cmdtp->cmd(cmdtp, flag, argc, argv); +} + +int cmd_discard_repeatable(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + int repeatable; + + return cmdtp->cmd_rep(cmdtp, flag, argc, argv, &repeatable); +} + /** * Call a command function. This should be the only route in U-Boot to call * a command, so that we can track whether we are waiting for input or @@ -510,13 +534,15 @@ void fixup_cmdtable(cmd_tbl_t *cmdtp, int size) * @param flag Some flags normally 0 (see CMD_FLAG_.. above) * @param argc Number of arguments (arg 0 must be the command text) * @param argv Arguments + * @param repeatable Can the command be repeated * @return 0 if command succeeded, else non-zero (CMD_RET_...) */ -static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], + int *repeatable) { int result; - result = (cmdtp->cmd)(cmdtp, flag, argc, argv); + result = cmdtp->cmd_rep(cmdtp, flag, argc, argv, repeatable); if (result) debug("Command failed, result=%d\n", result); return result; @@ -553,12 +579,14 @@ enum command_ret_t cmd_process(int flag, int argc, char * const argv[], /* If OK so far, then do the command */ if (!rc) { + int newrep; + if (ticks) *ticks = get_timer(0); - rc = cmd_call(cmdtp, flag, argc, argv); + rc = cmd_call(cmdtp, flag, argc, argv, &newrep); if (ticks) *ticks = get_timer(*ticks); - *repeatable &= cmdtp->repeatable; + *repeatable &= newrep; } if (rc == CMD_RET_USAGE) rc = cmd_usage(cmdtp); diff --git a/include/command.h b/include/command.h index 89efcecfa92..bb93f022c51 100644 --- a/include/command.h +++ b/include/command.h @@ -29,7 +29,16 @@ struct cmd_tbl_s { char *name; /* Command Name */ int maxargs; /* maximum number of arguments */ - int repeatable; /* autorepeat allowed? */ + /* + * Same as ->cmd() except the command + * tells us if it can be repeated. + * Replaces the old ->repeatable field + * which was not able to make + * repeatable property different for + * the main command and sub-commands. + */ + int (*cmd_rep)(struct cmd_tbl_s *cmd, int flags, int argc, + char * const argv[], int *repeatable); /* Implementation function */ int (*cmd)(struct cmd_tbl_s *, int, int, char * const []); char *usage; /* Usage message (short) */ @@ -60,6 +69,19 @@ int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc, extern int cmd_usage(const cmd_tbl_t *cmdtp); +/* Dummy ->cmd and ->cmd_rep wrappers. */ +int cmd_always_repeatable(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[], int *repeatable); +int cmd_never_repeatable(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[], int *repeatable); +int cmd_discard_repeatable(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]); + +static inline bool cmd_is_repeatable(cmd_tbl_t *cmdtp) +{ + return cmdtp->cmd_rep == cmd_always_repeatable; +} + #ifdef CONFIG_AUTO_COMPLETE extern int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]); extern int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp); @@ -188,16 +210,28 @@ int board_run_command(const char *cmdline); #endif #ifdef CONFIG_CMDLINE +#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \ + _usage, _help, _comp) \ + { #_name, _maxargs, _cmd_rep, cmd_discard_repeatable, \ + _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) } + #define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, _comp) \ - { #_name, _maxargs, _rep, _cmd, _usage, \ - _CMD_HELP(_help) _CMD_COMPLETE(_comp) } + { #_name, _maxargs, \ + _rep ? cmd_always_repeatable : cmd_never_repeatable, \ + _cmd, _usage, _CMD_HELP(_help) _CMD_COMPLETE(_comp) } #define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \ ll_entry_declare(cmd_tbl_t, _name, cmd) = \ U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, _comp); +#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \ + _help, _comp) \ + ll_entry_declare(cmd_tbl_t, _name, cmd) = \ + U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \ + _usage, _help, _comp) + #else #define U_BOOT_SUBCMD_START(name) static cmd_tbl_t name[] = {}; #define U_BOOT_SUBCMD_END @@ -209,15 +243,25 @@ int board_run_command(const char *cmdline); _cmd(NULL, 0, 0, NULL); \ return 0; \ } + +#define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \ + _usage, _help, _comp) \ + { #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage, \ + _CMD_HELP(_help) _CMD_COMPLETE(_comp) } + #define U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, \ _help, _comp) \ - { #_name, _maxargs, _rep, 0 ? _cmd : NULL, _usage, \ + { #_name, _maxargs, NULL, 0 ? _cmd : NULL, _usage, \ _CMD_HELP(_help) _CMD_COMPLETE(_comp) } #define U_BOOT_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, \ _comp) \ _CMD_REMOVE(sub_ ## _name, _cmd) +#define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \ + _help, _comp) \ + _CMD_REMOVE(sub_ ## _name, _cmd_rep) + #endif /* CONFIG_CMDLINE */ #define U_BOOT_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \ From c0cf06e523cbe50dbf38d5c81d0595f5b8517f4a Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 3 Dec 2018 22:54:21 +0100 Subject: [PATCH 54/58] command: commands: Add macros to declare commands with subcmds Most cmd/xxx.c source files expose several commands through a single entry point. Some of them are doing the sub-command parsing manually in their do_() function, others are declaring a table of sub-commands and then use find_cmd_tbl() to delegate the request to the sub command handler. In either case, the amount of code to do that is not negligible and repetitive, not to mention that almost no commands are implementing the auto-completion hook, which means most u-boot commands lack auto-completion. Provide several macros to easily define commands exposing sub-commands. Signed-off-by: Boris Brezillon Reviewed-by: Tom Rini --- include/command.h | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/include/command.h b/include/command.h index bb93f022c51..461b17447c0 100644 --- a/include/command.h +++ b/include/command.h @@ -209,6 +209,70 @@ int board_run_command(const char *cmdline); # define _CMD_HELP(x) #endif +#ifdef CONFIG_NEEDS_MANUAL_RELOC +#define U_BOOT_SUBCMDS_RELOC(_cmdname) \ + static void _cmdname##_subcmds_reloc(void) \ + { \ + static int relocated; \ + \ + if (relocated) \ + return; \ + \ + fixup_cmdtable(_cmdname##_subcmds, \ + ARRAY_SIZE(_cmdname##_subcmds)); \ + relocated = 1; \ + } +#else +#define U_BOOT_SUBCMDS_RELOC(_cmdname) \ + static void _cmdname##_subcmds_reloc(void) { } +#endif + +#define U_BOOT_SUBCMDS_DO_CMD(_cmdname) \ + static int do_##_cmdname(cmd_tbl_t *cmdtp, int flag, int argc, \ + char * const argv[], int *repeatable) \ + { \ + cmd_tbl_t *subcmd; \ + \ + _cmdname##_subcmds_reloc(); \ + \ + /* We need at least the cmd and subcmd names. */ \ + if (argc < 2 || argc > CONFIG_SYS_MAXARGS) \ + return CMD_RET_USAGE; \ + \ + subcmd = find_cmd_tbl(argv[1], _cmdname##_subcmds, \ + ARRAY_SIZE(_cmdname##_subcmds)); \ + if (!subcmd || argc - 1 > subcmd->maxargs) \ + return CMD_RET_USAGE; \ + \ + if (flag == CMD_FLAG_REPEAT && \ + !cmd_is_repeatable(subcmd)) \ + return CMD_RET_SUCCESS; \ + \ + return subcmd->cmd_rep(subcmd, flag, argc - 1, \ + argv + 1, repeatable); \ + } + +#ifdef CONFIG_AUTO_COMPLETE +#define U_BOOT_SUBCMDS_COMPLETE(_cmdname) \ + static int complete_##_cmdname(int argc, char * const argv[], \ + char last_char, int maxv, \ + char *cmdv[]) \ + { \ + return complete_subcmdv(_cmdname##_subcmds, \ + ARRAY_SIZE(_cmdname##_subcmds), \ + argc - 1, argv + 1, last_char, \ + maxv, cmdv); \ + } +#else +#define U_BOOT_SUBCMDS_COMPLETE(_cmdname) +#endif + +#define U_BOOT_SUBCMDS(_cmdname, ...) \ + static cmd_tbl_t _cmdname##_subcmds[] = { __VA_ARGS__ }; \ + U_BOOT_SUBCMDS_RELOC(_cmdname) \ + U_BOOT_SUBCMDS_DO_CMD(_cmdname) \ + U_BOOT_SUBCMDS_COMPLETE(_cmdname) + #ifdef CONFIG_CMDLINE #define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \ _usage, _help, _comp) \ @@ -271,4 +335,18 @@ int board_run_command(const char *cmdline); U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _cmd, \ _usage, _help, NULL) +#define U_BOOT_SUBCMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd, \ + _comp) \ + U_BOOT_CMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd, \ + "", "", _comp) + +#define U_BOOT_SUBCMD_MKENT(_name, _maxargs, _rep, _do_cmd) \ + U_BOOT_SUBCMD_MKENT_COMPLETE(_name, _maxargs, _rep, _do_cmd, \ + NULL) + +#define U_BOOT_CMD_WITH_SUBCMDS(_name, _usage, _help, ...) \ + U_BOOT_SUBCMDS(_name, __VA_ARGS__) \ + U_BOOT_CMDREP_COMPLETE(_name, CONFIG_SYS_MAXARGS, do_##_name, \ + _usage, _help, complete_##_name) + #endif /* __COMMAND_H */ From 9671243e8d10defb06f2ea24fac138c87697d7fc Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 3 Dec 2018 22:54:22 +0100 Subject: [PATCH 55/58] cmd: mtd: Use the subcmd infrastructure to declare mtd sub-commands It's way simpler this way, and we also gain auto-completion support for free (MTD name auto-completion has been added with mtd_name_complete()) Signed-off-by: Boris Brezillon Reviewed-by: Tom Rini --- cmd/mtd.c | 476 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 281 insertions(+), 195 deletions(-) diff --git a/cmd/mtd.c b/cmd/mtd.c index 61422239846..cda702d18b1 100644 --- a/cmd/mtd.c +++ b/cmd/mtd.c @@ -15,6 +15,22 @@ #include #include +#include + +static struct mtd_info *get_mtd_by_name(const char *name) +{ + struct mtd_info *mtd; + + mtd_probe_devices(); + + mtd = get_mtd_device_nm(name); + if (IS_ERR_OR_NULL(mtd)) + printf("MTD device %s not found, ret %ld\n", name, + PTR_ERR(mtd)); + + return mtd; +} + static uint mtd_len_to_pages(struct mtd_info *mtd, u64 len) { do_div(len, mtd->writesize); @@ -177,7 +193,8 @@ static bool mtd_oob_write_is_empty(struct mtd_oob_ops *op) return true; } -static int do_mtd_list(void) +static int do_mtd_list(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { struct mtd_info *mtd; int dev_nb = 0; @@ -221,229 +238,287 @@ static int mtd_special_write_oob(struct mtd_info *mtd, u64 off, return ret; } -static int do_mtd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +static int do_mtd_io(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + bool dump, read, raw, woob, write_empty_pages, has_pages = false; + u64 start_off, off, len, remaining, default_len; + struct mtd_oob_ops io_op = {}; + uint user_addr = 0, npages; + const char *cmd = argv[0]; struct mtd_info *mtd; - const char *cmd; - char *mtd_name; + u32 oob_len; + u8 *buf; + int ret; - /* All MTD commands need at least two arguments */ if (argc < 2) return CMD_RET_USAGE; - /* Parse the command name and its optional suffixes */ - cmd = argv[1]; - - /* List the MTD devices if that is what the user wants */ - if (strcmp(cmd, "list") == 0) - return do_mtd_list(); - - /* - * The remaining commands require also at least a device ID. - * Check the selected device is valid. Ensure it is probed. - */ - if (argc < 3) - return CMD_RET_USAGE; - - mtd_name = argv[2]; - mtd_probe_devices(); - mtd = get_mtd_device_nm(mtd_name); - if (IS_ERR_OR_NULL(mtd)) { - printf("MTD device %s not found, ret %ld\n", - mtd_name, PTR_ERR(mtd)); + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR_OR_NULL(mtd)) return CMD_RET_FAILURE; + + if (mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH) + has_pages = true; + + dump = !strncmp(cmd, "dump", 4); + read = dump || !strncmp(cmd, "read", 4); + raw = strstr(cmd, ".raw"); + woob = strstr(cmd, ".oob"); + write_empty_pages = !has_pages || strstr(cmd, ".dontskipff"); + + argc -= 2; + argv += 2; + + if (!dump) { + if (!argc) { + ret = CMD_RET_USAGE; + goto out_put_mtd; + } + + user_addr = simple_strtoul(argv[0], NULL, 16); + argc--; + argv++; } - put_mtd_device(mtd); - argc -= 3; - argv += 3; + start_off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0; + if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) { + printf("Offset not aligned with a page (0x%x)\n", + mtd->writesize); + ret = CMD_RET_FAILURE; + goto out_put_mtd; + } - /* Do the parsing */ - if (!strncmp(cmd, "read", 4) || !strncmp(cmd, "dump", 4) || - !strncmp(cmd, "write", 5)) { - bool has_pages = mtd->type == MTD_NANDFLASH || - mtd->type == MTD_MLCNANDFLASH; - bool dump, read, raw, woob, write_empty_pages; - struct mtd_oob_ops io_op = {}; - uint user_addr = 0, npages; - u64 start_off, off, len, remaining, default_len; - u32 oob_len; - u8 *buf; - int ret; + default_len = dump ? mtd->writesize : mtd->size; + len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : default_len; + if (!mtd_is_aligned_with_min_io_size(mtd, len)) { + len = round_up(len, mtd->writesize); + printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n", + mtd->writesize, len); + } - dump = !strncmp(cmd, "dump", 4); - read = dump || !strncmp(cmd, "read", 4); - raw = strstr(cmd, ".raw"); - woob = strstr(cmd, ".oob"); - write_empty_pages = !has_pages || strstr(cmd, ".dontskipff"); + remaining = len; + npages = mtd_len_to_pages(mtd, len); + oob_len = woob ? npages * mtd->oobsize : 0; - if (!dump) { - if (!argc) - return CMD_RET_USAGE; + if (dump) + buf = kmalloc(len + oob_len, GFP_KERNEL); + else + buf = map_sysmem(user_addr, 0); - user_addr = simple_strtoul(argv[0], NULL, 16); - argc--; - argv++; - } + if (!buf) { + printf("Could not map/allocate the user buffer\n"); + ret = CMD_RET_FAILURE; + goto out_put_mtd; + } - start_off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0; - if (!mtd_is_aligned_with_min_io_size(mtd, start_off)) { - printf("Offset not aligned with a page (0x%x)\n", - mtd->writesize); - return CMD_RET_FAILURE; - } + if (has_pages) + printf("%s %lld byte(s) (%d page(s)) at offset 0x%08llx%s%s%s\n", + read ? "Reading" : "Writing", len, npages, start_off, + raw ? " [raw]" : "", woob ? " [oob]" : "", + !read && write_empty_pages ? " [dontskipff]" : ""); + else + printf("%s %lld byte(s) at offset 0x%08llx\n", + read ? "Reading" : "Writing", len, start_off); - default_len = dump ? mtd->writesize : mtd->size; - len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : - default_len; - if (!mtd_is_aligned_with_min_io_size(mtd, len)) { - len = round_up(len, mtd->writesize); - printf("Size not on a page boundary (0x%x), rounding to 0x%llx\n", - mtd->writesize, len); - } + io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB; + io_op.len = has_pages ? mtd->writesize : len; + io_op.ooblen = woob ? mtd->oobsize : 0; + io_op.datbuf = buf; + io_op.oobbuf = woob ? &buf[len] : NULL; - remaining = len; - npages = mtd_len_to_pages(mtd, len); - oob_len = woob ? npages * mtd->oobsize : 0; + /* Search for the first good block after the given offset */ + off = start_off; + while (mtd_block_isbad(mtd, off)) + off += mtd->erasesize; - if (dump) - buf = kmalloc(len + oob_len, GFP_KERNEL); - else - buf = map_sysmem(user_addr, 0); - - if (!buf) { - printf("Could not map/allocate the user buffer\n"); - return CMD_RET_FAILURE; - } - - if (has_pages) - printf("%s %lld byte(s) (%d page(s)) at offset 0x%08llx%s%s%s\n", - read ? "Reading" : "Writing", len, npages, start_off, - raw ? " [raw]" : "", woob ? " [oob]" : "", - !read && write_empty_pages ? " [dontskipff]" : ""); - else - printf("%s %lld byte(s) at offset 0x%08llx\n", - read ? "Reading" : "Writing", len, start_off); - - io_op.mode = raw ? MTD_OPS_RAW : MTD_OPS_AUTO_OOB; - io_op.len = has_pages ? mtd->writesize : len; - io_op.ooblen = woob ? mtd->oobsize : 0; - io_op.datbuf = buf; - io_op.oobbuf = woob ? &buf[len] : NULL; - - /* Search for the first good block after the given offset */ - off = start_off; - while (mtd_block_isbad(mtd, off)) + /* Loop over the pages to do the actual read/write */ + while (remaining) { + /* Skip the block if it is bad */ + if (mtd_is_aligned_with_block_size(mtd, off) && + mtd_block_isbad(mtd, off)) { off += mtd->erasesize; - - /* Loop over the pages to do the actual read/write */ - while (remaining) { - /* Skip the block if it is bad */ - if (mtd_is_aligned_with_block_size(mtd, off) && - mtd_block_isbad(mtd, off)) { - off += mtd->erasesize; - continue; - } - - if (read) - ret = mtd_read_oob(mtd, off, &io_op); - else - ret = mtd_special_write_oob(mtd, off, &io_op, - write_empty_pages, - woob); - - if (ret) { - printf("Failure while %s at offset 0x%llx\n", - read ? "reading" : "writing", off); - return CMD_RET_FAILURE; - } - - off += io_op.retlen; - remaining -= io_op.retlen; - io_op.datbuf += io_op.retlen; - io_op.oobbuf += io_op.oobretlen; + continue; } - if (!ret && dump) - mtd_dump_device_buf(mtd, start_off, buf, len, woob); - - if (dump) - kfree(buf); + if (read) + ret = mtd_read_oob(mtd, off, &io_op); else - unmap_sysmem(buf); + ret = mtd_special_write_oob(mtd, off, &io_op, + write_empty_pages, woob); if (ret) { - printf("%s on %s failed with error %d\n", - read ? "Read" : "Write", mtd->name, ret); - return CMD_RET_FAILURE; + printf("Failure while %s at offset 0x%llx\n", + read ? "reading" : "writing", off); + break; } - } else if (!strcmp(cmd, "erase")) { - bool scrub = strstr(cmd, ".dontskipbad"); - struct erase_info erase_op = {}; - u64 off, len; - int ret; - - off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0; - len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->size; - - if (!mtd_is_aligned_with_block_size(mtd, off)) { - printf("Offset not aligned with a block (0x%x)\n", - mtd->erasesize); - return CMD_RET_FAILURE; - } - - if (!mtd_is_aligned_with_block_size(mtd, len)) { - printf("Size not a multiple of a block (0x%x)\n", - mtd->erasesize); - return CMD_RET_FAILURE; - } - - printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n", - off, off + len - 1, mtd_div_by_eb(len, mtd)); - - erase_op.mtd = mtd; - erase_op.addr = off; - erase_op.len = len; - erase_op.scrub = scrub; - - while (erase_op.len) { - ret = mtd_erase(mtd, &erase_op); - - /* Abort if its not a bad block error */ - if (ret != -EIO) - break; - - printf("Skipping bad block at 0x%08llx\n", - erase_op.fail_addr); - - /* Skip bad block and continue behind it */ - erase_op.len -= erase_op.fail_addr - erase_op.addr; - erase_op.len -= mtd->erasesize; - erase_op.addr = erase_op.fail_addr + mtd->erasesize; - } - - if (ret && ret != -EIO) - return CMD_RET_FAILURE; - } else if (!strcmp(cmd, "bad")) { - loff_t off; - - if (!mtd_can_have_bb(mtd)) { - printf("Only NAND-based devices can have bad blocks\n"); - return CMD_RET_SUCCESS; - } - - printf("MTD device %s bad blocks list:\n", mtd->name); - for (off = 0; off < mtd->size; off += mtd->erasesize) - if (mtd_block_isbad(mtd, off)) - printf("\t0x%08llx\n", off); - } else { - return CMD_RET_USAGE; + off += io_op.retlen; + remaining -= io_op.retlen; + io_op.datbuf += io_op.retlen; + io_op.oobbuf += io_op.oobretlen; } + if (!ret && dump) + mtd_dump_device_buf(mtd, start_off, buf, len, woob); + + if (dump) + kfree(buf); + else + unmap_sysmem(buf); + + if (ret) { + printf("%s on %s failed with error %d\n", + read ? "Read" : "Write", mtd->name, ret); + ret = CMD_RET_FAILURE; + } else { + ret = CMD_RET_SUCCESS; + } + +out_put_mtd: + put_mtd_device(mtd); + + return ret; +} + +static int do_mtd_erase(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct erase_info erase_op = {}; + struct mtd_info *mtd; + u64 off, len; + bool scrub; + int ret; + + if (argc < 2) + return CMD_RET_USAGE; + + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR_OR_NULL(mtd)) + return CMD_RET_FAILURE; + + scrub = strstr(argv[0], ".dontskipbad"); + + argc -= 2; + argv += 2; + + off = argc > 0 ? simple_strtoul(argv[0], NULL, 16) : 0; + len = argc > 1 ? simple_strtoul(argv[1], NULL, 16) : mtd->size; + + if (!mtd_is_aligned_with_block_size(mtd, off)) { + printf("Offset not aligned with a block (0x%x)\n", + mtd->erasesize); + ret = CMD_RET_FAILURE; + goto out_put_mtd; + } + + if (!mtd_is_aligned_with_block_size(mtd, len)) { + printf("Size not a multiple of a block (0x%x)\n", + mtd->erasesize); + ret = CMD_RET_FAILURE; + goto out_put_mtd; + } + + printf("Erasing 0x%08llx ... 0x%08llx (%d eraseblock(s))\n", + off, off + len - 1, mtd_div_by_eb(len, mtd)); + + erase_op.mtd = mtd; + erase_op.addr = off; + erase_op.len = len; + erase_op.scrub = scrub; + + while (erase_op.len) { + ret = mtd_erase(mtd, &erase_op); + + /* Abort if its not a bad block error */ + if (ret != -EIO) + break; + + printf("Skipping bad block at 0x%08llx\n", erase_op.fail_addr); + + /* Skip bad block and continue behind it */ + erase_op.len -= erase_op.fail_addr - erase_op.addr; + erase_op.len -= mtd->erasesize; + erase_op.addr = erase_op.fail_addr + mtd->erasesize; + } + + if (ret && ret != -EIO) + ret = CMD_RET_FAILURE; + else + ret = CMD_RET_SUCCESS; + +out_put_mtd: + put_mtd_device(mtd); + + return ret; +} + +static int do_mtd_bad(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + struct mtd_info *mtd; + loff_t off; + + if (argc < 2) + return CMD_RET_USAGE; + + mtd = get_mtd_by_name(argv[1]); + if (IS_ERR_OR_NULL(mtd)) + return CMD_RET_FAILURE; + + if (!mtd_can_have_bb(mtd)) { + printf("Only NAND-based devices can have bad blocks\n"); + goto out_put_mtd; + } + + printf("MTD device %s bad blocks list:\n", mtd->name); + for (off = 0; off < mtd->size; off += mtd->erasesize) { + if (mtd_block_isbad(mtd, off)) + printf("\t0x%08llx\n", off); + } + +out_put_mtd: + put_mtd_device(mtd); + return CMD_RET_SUCCESS; } +#ifdef CONFIG_AUTO_COMPLETE +static int mtd_name_complete(int argc, char * const argv[], char last_char, + int maxv, char *cmdv[]) +{ + int len = 0, n_found = 0; + struct mtd_info *mtd; + + argc--; + argv++; + + if (argc > 1 || + (argc == 1 && (last_char == '\0' || isblank(last_char)))) + return 0; + + if (argc) + len = strlen(argv[0]); + + mtd_for_each_device(mtd) { + if (argc && + (len > strlen(mtd->name) || + strncmp(argv[0], mtd->name, len))) + continue; + + if (n_found >= maxv - 2) { + cmdv[n_found++] = "..."; + break; + } + + cmdv[n_found++] = mtd->name; + } + + cmdv[n_found] = NULL; + + return n_found; +} +#endif /* CONFIG_AUTO_COMPLETE */ + static char mtd_help_text[] = #ifdef CONFIG_SYS_LONGHELP "- generic operations on memory technology devices\n\n" @@ -470,4 +545,15 @@ static char mtd_help_text[] = #endif ""; -U_BOOT_CMD(mtd, 10, 1, do_mtd, "MTD utils", mtd_help_text); +U_BOOT_CMD_WITH_SUBCMDS(mtd, "MTD utils", mtd_help_text, + U_BOOT_SUBCMD_MKENT(list, 1, 1, do_mtd_list), + U_BOOT_SUBCMD_MKENT_COMPLETE(read, 5, 0, do_mtd_io, + mtd_name_complete), + U_BOOT_SUBCMD_MKENT_COMPLETE(write, 5, 0, do_mtd_io, + mtd_name_complete), + U_BOOT_SUBCMD_MKENT_COMPLETE(dump, 4, 0, do_mtd_io, + mtd_name_complete), + U_BOOT_SUBCMD_MKENT_COMPLETE(erase, 4, 0, do_mtd_erase, + mtd_name_complete), + U_BOOT_SUBCMD_MKENT_COMPLETE(bad, 2, 1, do_mtd_bad, + mtd_name_complete)); From 9652cfd9ee5679b72f28d581d7d48916f8031937 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Mon, 3 Dec 2018 22:54:23 +0100 Subject: [PATCH 56/58] cmd: adc: Use the sub-command infrastructure And you get sub-command auto-completion for free. Signed-off-by: Boris Brezillon Reviewed-by: Tom Rini --- cmd/adc.c | 33 +++++---------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/cmd/adc.c b/cmd/adc.c index 2d635acbd95..381961cf51a 100644 --- a/cmd/adc.c +++ b/cmd/adc.c @@ -146,37 +146,14 @@ static int do_adc_scan(cmd_tbl_t *cmdtp, int flag, int argc, return CMD_RET_SUCCESS; } -static cmd_tbl_t cmd_adc_sub[] = { - U_BOOT_CMD_MKENT(list, 1, 1, do_adc_list, "", ""), - U_BOOT_CMD_MKENT(info, 2, 1, do_adc_info, "", ""), - U_BOOT_CMD_MKENT(single, 3, 1, do_adc_single, "", ""), - U_BOOT_CMD_MKENT(scan, 3, 1, do_adc_scan, "", ""), -}; - -static int do_adc(cmd_tbl_t *cmdtp, int flag, int argc, - char *const argv[]) -{ - cmd_tbl_t *c; - - if (argc < 2) - return CMD_RET_USAGE; - - /* Strip off leading 'adc' command argument */ - argc--; - argv++; - - c = find_cmd_tbl(argv[0], &cmd_adc_sub[0], ARRAY_SIZE(cmd_adc_sub)); - - if (c) - return c->cmd(cmdtp, flag, argc, argv); - else - return CMD_RET_USAGE; -} - static char adc_help_text[] = "list - list ADC devices\n" "adc info - Get ADC device info\n" "adc single - Get Single data of ADC device channel\n" "adc scan [channel mask] - Scan all [or masked] ADC channels"; -U_BOOT_CMD(adc, 4, 1, do_adc, "ADC sub-system", adc_help_text); +U_BOOT_CMD_WITH_SUBCMDS(adc, "ADC sub-system", adc_help_text, + U_BOOT_SUBCMD_MKENT(list, 1, 1, do_adc_list), + U_BOOT_SUBCMD_MKENT(info, 2, 1, do_adc_info), + U_BOOT_SUBCMD_MKENT(single, 3, 1, do_adc_single), + U_BOOT_SUBCMD_MKENT(scan, 3, 1, do_adc_scan)); From 31a2cf1ca4968dcaf78aef222b6683fea4f2c72d Mon Sep 17 00:00:00 2001 From: Tien Fong Chee Date: Mon, 10 Dec 2018 21:29:44 +0800 Subject: [PATCH 57/58] misc: fs_loader: Switching private data allocation to DM auto allocation Switching private data manual allocation to driver model auto allocation so users no longer need to deallocate themself because this would be deallocated by driver model when the device is no longer required. Signed-off-by: Tien Fong Chee Reviewed-by: Simon Glass --- doc/driver-model/fs_firmware_loader.txt | 35 ++------ drivers/misc/fs_loader.c | 108 ++++++++++-------------- include/fs_loader.h | 32 +------ 3 files changed, 56 insertions(+), 119 deletions(-) diff --git a/doc/driver-model/fs_firmware_loader.txt b/doc/driver-model/fs_firmware_loader.txt index 290915a9598..b9aee848cc5 100644 --- a/doc/driver-model/fs_firmware_loader.txt +++ b/doc/driver-model/fs_firmware_loader.txt @@ -74,17 +74,16 @@ Firmware storage device described in device tree source File system firmware Loader API ------------------------------- -int request_firmware_into_buf(struct device_platdata *plat, +int request_firmware_into_buf(struct udevice *dev, const char *name, - void *buf, size_t size, u32 offset, - struct firmware **firmwarep) + void *buf, size_t size, u32 offset) -------------------------------------------------------------------- Load firmware into a previously allocated buffer Parameters: -1. struct device_platdata *plat - Platform data such as storage and partition firmware loading from +1. struct udevice *dev + An instance of a driver 2. const char *name name of firmware file @@ -98,36 +97,16 @@ Parameters: 5. u32 offset offset of a file for start reading into buffer -6. struct firmware **firmwarep - pointer to firmware image - return: size of total read -ve when error Description: - The firmware is loaded directly into the buffer pointed to by buf and - the @firmwarep data member is pointed at buf - -Note: Memory would be allocated for firmware image, hence user should - free() *firmwarep and *firmwarep->priv structs after usage of - request_firmware_into_buf(), otherwise it will always leak memory - while subsequent calls of request_firmware_into_buf() with the same - *firmwarep argument. Those arguments can be free through calling API - below release_firmware(); + The firmware is loaded directly into the buffer pointed to by buf Example of creating firmware loader instance and calling request_firmware_into_buf API: if (uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &dev)) { - request_firmware_into_buf(dev->plat, filename, buffer_location, - buffer_size, offset_ofreading, &fw); + request_firmware_into_buf(dev, filename, buffer_location, + buffer_size, offset_ofreading); } - -void release_firmware(struct firmware *firmware) ------------------------------------------------- -Release the resource associated with a firmware image - -Parameters: - -1. struct firmware *firmware - Firmware resource to release diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index baa5f8302ae..57a14a3479a 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -16,9 +16,22 @@ DECLARE_GLOBAL_DATA_PTR; -struct firmware_priv { - const char *name; /* Filename */ - u32 offset; /* Offset of reading a file */ +/** + * struct firmware - A place for storing firmware and its attribute data. + * + * This holds information about a firmware and its content. + * + * @size: Size of a file + * @data: Buffer for file + * @priv: Firmware loader private fields + * @name: Filename + * @offset: Offset of reading a file + */ +struct firmware { + size_t size; + const u8 *data; + const char *name; + u32 offset; }; #ifdef CONFIG_CMD_UBIFS @@ -88,74 +101,42 @@ static int select_fs_dev(struct device_platdata *plat) /** * _request_firmware_prepare - Prepare firmware struct. * + * @dev: An instance of a driver. * @name: Name of firmware file. * @dbuf: Address of buffer to load firmware into. * @size: Size of buffer. * @offset: Offset of a file for start reading into buffer. - * @firmwarep: Pointer to pointer to firmware image. * * Return: Negative value if fail, 0 for successful. */ -static int _request_firmware_prepare(const char *name, void *dbuf, - size_t size, u32 offset, - struct firmware **firmwarep) +static int _request_firmware_prepare(struct udevice *dev, + const char *name, void *dbuf, + size_t size, u32 offset) { if (!name || name[0] == '\0') return -EINVAL; - /* No memory allocation is required if *firmwarep is allocated */ - if (!(*firmwarep)) { - (*firmwarep) = calloc(1, sizeof(struct firmware)); - if (!(*firmwarep)) - return -ENOMEM; + struct firmware *firmwarep = dev_get_priv(dev); - (*firmwarep)->priv = calloc(1, sizeof(struct firmware_priv)); - if (!(*firmwarep)->priv) { - free(*firmwarep); - return -ENOMEM; - } - } else if (!(*firmwarep)->priv) { - (*firmwarep)->priv = calloc(1, sizeof(struct firmware_priv)); - if (!(*firmwarep)->priv) { - free(*firmwarep); - return -ENOMEM; - } - } + if (!firmwarep) + return -ENOMEM; - ((struct firmware_priv *)((*firmwarep)->priv))->name = name; - ((struct firmware_priv *)((*firmwarep)->priv))->offset = offset; - (*firmwarep)->data = dbuf; - (*firmwarep)->size = size; + firmwarep->name = name; + firmwarep->offset = offset; + firmwarep->data = dbuf; + firmwarep->size = size; return 0; } -/** - * release_firmware - Release the resource associated with a firmware image - * @firmware: Firmware resource to release - */ -void release_firmware(struct firmware *firmware) -{ - if (firmware) { - if (firmware->priv) { - free(firmware->priv); - firmware->priv = NULL; - } - free(firmware); - } -} - /** * fw_get_filesystem_firmware - load firmware into an allocated buffer. - * @plat: Platform data such as storage and partition firmware loading from. - * @firmware: pointer to firmware image. + * @dev: An instance of a driver. * * Return: Size of total read, negative value when error. */ -static int fw_get_filesystem_firmware(struct device_platdata *plat, - struct firmware *firmware) +static int fw_get_filesystem_firmware(struct udevice *dev) { - struct firmware_priv *fw_priv = NULL; loff_t actread; char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume; int ret; @@ -178,20 +159,23 @@ static int fw_get_filesystem_firmware(struct device_platdata *plat, else ret = -ENODEV; } else { - ret = select_fs_dev(plat); + ret = select_fs_dev(dev->platdata); } if (ret) goto out; - fw_priv = firmware->priv; + struct firmware *firmwarep = dev_get_priv(dev); - ret = fs_read(fw_priv->name, (ulong)map_to_sysmem(firmware->data), - fw_priv->offset, firmware->size, &actread); + if (!firmwarep) + return -ENOMEM; + + ret = fs_read(firmwarep->name, (ulong)map_to_sysmem(firmwarep->data), + firmwarep->offset, firmwarep->size, &actread); if (ret) { debug("Error: %d Failed to read %s from flash %lld != %zu.\n", - ret, fw_priv->name, actread, firmware->size); + ret, firmwarep->name, actread, firmwarep->size); } else { ret = actread; } @@ -205,33 +189,30 @@ out: /** * request_firmware_into_buf - Load firmware into a previously allocated buffer. - * @plat: Platform data such as storage and partition firmware loading from. + * @dev: An instance of a driver. * @name: Name of firmware file. * @buf: Address of buffer to load firmware into. * @size: Size of buffer. * @offset: Offset of a file for start reading into buffer. - * @firmwarep: Pointer to firmware image. * - * The firmware is loaded directly into the buffer pointed to by @buf and - * the @firmwarep data member is pointed at @buf. + * The firmware is loaded directly into the buffer pointed to by @buf. * * Return: Size of total read, negative value when error. */ -int request_firmware_into_buf(struct device_platdata *plat, +int request_firmware_into_buf(struct udevice *dev, const char *name, - void *buf, size_t size, u32 offset, - struct firmware **firmwarep) + void *buf, size_t size, u32 offset) { int ret; - if (!plat) + if (!dev) return -EINVAL; - ret = _request_firmware_prepare(name, buf, size, offset, firmwarep); + ret = _request_firmware_prepare(dev, name, buf, size, offset); if (ret < 0) /* error */ return ret; - ret = fw_get_filesystem_firmware(plat, *firmwarep); + ret = fw_get_filesystem_firmware(dev); return ret; } @@ -286,6 +267,7 @@ U_BOOT_DRIVER(fs_loader) = { .probe = fs_loader_probe, .ofdata_to_platdata = fs_loader_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct device_platdata), + .priv_auto_alloc_size = sizeof(struct firmware), }; UCLASS_DRIVER(fs_loader) = { diff --git a/include/fs_loader.h b/include/fs_loader.h index 0be4f17e632..b728c06fcff 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -8,21 +8,6 @@ #include -/** - * struct firmware - A place for storing firmware and its attribute data. - * - * This holds information about a firmware and its content. - * - * @size: Size of a file - * @data: Buffer for file - * @priv: Firmware loader private fields - */ -struct firmware { - size_t size; - const u8 *data; - void *priv; -}; - /** * struct phandle_part - A place for storing phandle of node and its partition * @@ -52,28 +37,19 @@ struct device_platdata { char *ubivol; }; -/** - * release_firmware - Release the resource associated with a firmware image - * @firmware: Firmware resource to release - */ -void release_firmware(struct firmware *firmware); - /** * request_firmware_into_buf - Load firmware into a previously allocated buffer. - * @plat: Platform data such as storage and partition firmware loading from. + * @dev: An instance of a driver. * @name: Name of firmware file. * @buf: Address of buffer to load firmware into. * @size: Size of buffer. * @offset: Offset of a file for start reading into buffer. - * @firmwarep: Pointer to firmware image. * - * The firmware is loaded directly into the buffer pointed to by @buf and - * the @firmwarep data member is pointed at @buf. + * The firmware is loaded directly into the buffer pointed to by @buf. * * Return: Size of total read, negative value when error. */ -int request_firmware_into_buf(struct device_platdata *plat, +int request_firmware_into_buf(struct udevice *dev, const char *name, - void *buf, size_t size, u32 offset, - struct firmware **firmwarep); + void *buf, size_t size, u32 offset); #endif From 03dcf17dba3dbd6f1cfe9ecaa0665ea8c11e0ef2 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Wed, 5 Dec 2018 09:26:50 +0100 Subject: [PATCH 58/58] common: command: Add support for $ auto-completion Add the dollar_complete() function to auto-complete arguments starting with a '$' and use it in the cmd_auto_complete() path such that all args starting with a $ can be auto-completed based on the available env vars. Signed-off-by: Boris Brezillon [trini: Fix some linking problems] Signed-off-by: Tom Rini --- common/command.c | 32 +++++++++++++++++++++++------ env/common.c | 52 ++++++++++++++++++++++++++++++++++++++++++++---- include/common.h | 3 ++- lib/Makefile | 3 +-- 4 files changed, 77 insertions(+), 13 deletions(-) diff --git a/common/command.c b/common/command.c index 19f0534a76e..e14d1fa1d6b 100644 --- a/common/command.c +++ b/common/command.c @@ -142,23 +142,38 @@ int cmd_usage(const cmd_tbl_t *cmdtp) } #ifdef CONFIG_AUTO_COMPLETE +static char env_complete_buf[512]; int var_complete(int argc, char * const argv[], char last_char, int maxv, char *cmdv[]) { - static char tmp_buf[512]; int space; space = last_char == '\0' || isblank(last_char); if (space && argc == 1) - return env_complete("", maxv, cmdv, sizeof(tmp_buf), tmp_buf); + return env_complete("", maxv, cmdv, sizeof(env_complete_buf), + env_complete_buf, false); if (!space && argc == 2) - return env_complete(argv[1], maxv, cmdv, sizeof(tmp_buf), tmp_buf); + return env_complete(argv[1], maxv, cmdv, + sizeof(env_complete_buf), + env_complete_buf, false); return 0; } +static int dollar_complete(int argc, char * const argv[], char last_char, + int maxv, char *cmdv[]) +{ + /* Make sure the last argument starts with a $. */ + if (argc < 1 || argv[argc - 1][0] != '$' || + last_char == '\0' || isblank(last_char)) + return 0; + + return env_complete(argv[argc - 1], maxv, cmdv, sizeof(env_complete_buf), + env_complete_buf, true); +} + /*************************************************************************************/ int complete_subcmdv(cmd_tbl_t *cmdtp, int count, int argc, @@ -357,9 +372,14 @@ int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp) /* separate into argv */ argc = make_argv(tmp_buf, sizeof(argv)/sizeof(argv[0]), argv); - /* do the completion and return the possible completions */ - i = complete_cmdv(argc, argv, last_char, - sizeof(cmdv) / sizeof(cmdv[0]), cmdv); + /* first try a $ completion */ + i = dollar_complete(argc, argv, last_char, + sizeof(cmdv) / sizeof(cmdv[0]), cmdv); + if (!i) { + /* do the completion and return the possible completions */ + i = complete_cmdv(argc, argv, last_char, + sizeof(cmdv) / sizeof(cmdv[0]), cmdv); + } /* no match; bell and out */ if (i == 0) { diff --git a/env/common.c b/env/common.c index 3317cef3552..d1a6a528601 100644 --- a/env/common.c +++ b/env/common.c @@ -240,32 +240,76 @@ void env_relocate(void) } } -#if defined(CONFIG_AUTO_COMPLETE) && !defined(CONFIG_SPL_BUILD) -int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf) +#ifdef CONFIG_AUTO_COMPLETE +int env_complete(char *var, int maxv, char *cmdv[], int bufsz, char *buf, + bool dollar_comp) { ENTRY *match; int found, idx; + if (dollar_comp) { + /* + * When doing $ completion, the first character should + * obviously be a '$'. + */ + if (var[0] != '$') + return 0; + + var++; + + /* + * The second one, if present, should be a '{', as some + * configuration of the u-boot shell expand ${var} but not + * $var. + */ + if (var[0] == '{') + var++; + else if (var[0] != '\0') + return 0; + } + idx = 0; found = 0; cmdv[0] = NULL; + while ((idx = hmatch_r(var, idx, &match, &env_htab))) { int vallen = strlen(match->key) + 1; - if (found >= maxv - 2 || bufsz < vallen) + if (found >= maxv - 2 || + bufsz < vallen + (dollar_comp ? 3 : 0)) break; cmdv[found++] = buf; + + /* Add the '${' prefix to each var when doing $ completion. */ + if (dollar_comp) { + strcpy(buf, "${"); + buf += 2; + bufsz -= 3; + } + memcpy(buf, match->key, vallen); buf += vallen; bufsz -= vallen; + + if (dollar_comp) { + /* + * This one is a bit odd: vallen already contains the + * '\0' character but we need to add the '}' suffix, + * hence the buf - 1 here. strcpy() will add the '\0' + * character just after '}'. buf is then incremented + * to account for the extra '}' we just added. + */ + strcpy(buf - 1, "}"); + buf++; + } } qsort(cmdv, found, sizeof(cmdv[0]), strcmp_compar); if (idx) - cmdv[found++] = "..."; + cmdv[found++] = dollar_comp ? "${...}" : "..."; cmdv[found] = NULL; return found; diff --git a/include/common.h b/include/common.h index 657cc404cfa..18948b6bc2d 100644 --- a/include/common.h +++ b/include/common.h @@ -248,7 +248,8 @@ static inline int env_set_addr(const char *varname, const void *addr) } #ifdef CONFIG_AUTO_COMPLETE -int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf); +int env_complete(char *var, int maxv, char *cmdv[], int maxsz, char *buf, + bool dollar_comp); #endif int get_env_id (void); diff --git a/lib/Makefile b/lib/Makefile index a6dd928a926..f06d6316d46 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -41,7 +41,6 @@ obj-y += ldiv.o obj-$(CONFIG_MD5) += md5.o obj-y += net_utils.o obj-$(CONFIG_PHYSMEM) += physmem.o -obj-y += qsort.o obj-y += rc4.o obj-$(CONFIG_SUPPORT_EMMC_RPMB) += sha256.o obj-$(CONFIG_RBTREE) += rbtree.o @@ -67,7 +66,6 @@ obj-$(CONFIG_$(SPL_)LZ4) += lz4_wrapper.o obj-$(CONFIG_LIBAVB) += libavb/ -obj-$(CONFIG_$(SPL_TPL_)SAVEENV) += qsort.o obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += libfdt/ ifneq ($(CONFIG_$(SPL_TPL_)BUILD)$(CONFIG_$(SPL_TPL_)OF_PLATDATA),yy) obj-$(CONFIG_$(SPL_TPL_)OF_CONTROL) += fdtdec_common.o @@ -80,6 +78,7 @@ obj-$(CONFIG_$(SPL_TPL_)HASH_SUPPORT) += crc16.o obj-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o endif obj-$(CONFIG_ADDR_MAP) += addr_map.o +obj-y += qsort.o obj-y += hashtable.o obj-y += errno.o obj-y += display_options.o