[PATCH 0/6] Add fastboot support for MediaTek mt8518

This patch series adds basic fastboot support for MediaTek MT8518 EMMC boards, including musb-new structure for gadget driver and fastboot related configs.
mingming lee (6): usb: musb-new: mt85xx: add musb-new gadget driver. ARM: Mediatek: Add board_late_init to init usb gadget driver configs: mt8518: set global variables for fastboot configs: mt8518: enable usb gadget driver configs: mt8518: Enable fastboot related configs fastboot: mt85xx: add command to flash/erase emmc hwpart
arch/arm/dts/mt8518.dtsi | 13 + board/mediatek/mt8518/mt8518_ap1.c | 18 ++ configs/mt8518_ap1_emmc_defconfig | 22 ++ drivers/fastboot/Kconfig | 30 +++ drivers/fastboot/fb_mmc.c | 98 ++++++- drivers/usb/musb-new/Kconfig | 11 +- drivers/usb/musb-new/Makefile | 1 + drivers/usb/musb-new/mt85xx.c | 417 +++++++++++++++++++++++++++++ include/configs/mt8518.h | 10 +- 9 files changed, 614 insertions(+), 6 deletions(-) create mode 100644 drivers/usb/musb-new/mt85xx.c

Using musb-new structure for mt85xx gadget driver. Add gadget driver dts for mt8518 SoCs.
Signed-off-by: mingming lee mingming.lee@mediatek.com --- arch/arm/dts/mt8518.dtsi | 13 ++ drivers/usb/musb-new/Kconfig | 11 +- drivers/usb/musb-new/Makefile | 1 + drivers/usb/musb-new/mt85xx.c | 417 ++++++++++++++++++++++++++++++++++ 4 files changed, 441 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/musb-new/mt85xx.c
diff --git a/arch/arm/dts/mt8518.dtsi b/arch/arm/dts/mt8518.dtsi index c2d17fda4a..56da91a9fe 100644 --- a/arch/arm/dts/mt8518.dtsi +++ b/arch/arm/dts/mt8518.dtsi @@ -74,6 +74,19 @@ }; };
+ usb0: usb@11100000 { + compatible = "mediatek,mt8518-musb"; + reg = <0x11100000 0x1000>; + reg-names = "control"; + clocks = <&topckgen CLK_TOP_USB20_48M>, + <&topckgen CLK_TOP_USBIF>, + <&topckgen CLK_TOP_USB>; + clock-names = "usbpll", "usbmcu", "usb"; + interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_LOW>; + interrupt-names = "mc"; + status = "okay"; + }; + mmc0: mmc@11120000 { compatible = "mediatek,mt8516-mmc"; reg = <0x11120000 0x1000>; diff --git a/drivers/usb/musb-new/Kconfig b/drivers/usb/musb-new/Kconfig index 79ad14ef66..6cf8a2b60b 100644 --- a/drivers/usb/musb-new/Kconfig +++ b/drivers/usb/musb-new/Kconfig @@ -47,6 +47,15 @@ config USB_MUSB_DSPS bool "TI DSPS platforms"
if USB_MUSB_HOST || USB_MUSB_GADGET +config USB_MUSB_MT85XX + bool "Enable Mediatek MT85XX DRC USB controller" + depends on DM_USB && ARCH_MEDIATEK + default n + help + Say y to enable Mediatek MT85XX USB DRC controller support + if it is available on your Mediatek MUSB IP based platform. + DMA controllers are ignored. This driver follow musb-new + driver and usb gadget framework.
config USB_MUSB_PIC32 bool "Enable Microchip PIC32 DRC USB controller" @@ -76,7 +85,7 @@ endif
config USB_MUSB_PIO_ONLY bool "Disable DMA (always use PIO)" - default y if USB_MUSB_AM35X || USB_MUSB_PIC32 || USB_MUSB_OMAP2PLUS || USB_MUSB_DSPS || USB_MUSB_SUNXI + default y if USB_MUSB_AM35X || USB_MUSB_PIC32 || USB_MUSB_OMAP2PLUS || USB_MUSB_DSPS || USB_MUSB_SUNXI || USB_MUSB_MT85XX help All data is copied between memory and FIFO by the CPU. DMA controllers are ignored. diff --git a/drivers/usb/musb-new/Makefile b/drivers/usb/musb-new/Makefile index ec7852ce94..6355eb12dd 100644 --- a/drivers/usb/musb-new/Makefile +++ b/drivers/usb/musb-new/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_USB_MUSB_HOST) += musb_host.o musb_core.o musb_uboot.o obj-$(CONFIG_USB_MUSB_DSPS) += musb_dsps.o obj-$(CONFIG_USB_MUSB_DA8XX) += da8xx.o obj-$(CONFIG_USB_MUSB_AM35X) += am35x.o +obj-$(CONFIG_USB_MUSB_MT85XX) += mt85xx.o obj-$(CONFIG_USB_MUSB_OMAP2PLUS) += omap2430.o obj-$(CONFIG_USB_MUSB_PIC32) += pic32.o obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o diff --git a/drivers/usb/musb-new/mt85xx.c b/drivers/usb/musb-new/mt85xx.c new file mode 100644 index 0000000000..131fd7dd79 --- /dev/null +++ b/drivers/usb/musb-new/mt85xx.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek "glue layer" + * + * Copyright (C) 2019-2021 by Mediatek + * Based on the AllWinner SUNXI "glue layer" code. + * Copyright (C) 2015 Hans de Goede hdegoede@redhat.com + * Copyright (C) 2013 Jussi Kivilinna jussi.kivilinna@iki.fi + * + * This file is part of the Inventra Controller Driver for Linux. + */ +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <dm/lists.h> +#include <dm/root.h> +#include <linux/usb/musb.h> +#include <usb.h> +#include "linux-compat.h" +#include "musb_core.h" +#include "musb_uboot.h" + +#define DBG_I(fmt, ...) \ + pr_info(fmt, ##__VA_ARGS__) + +struct mtk_musb_config { + struct musb_hdrc_config *config; +}; + +struct mtk_musb_glue { + struct musb_host_data mdata; + struct clk usbpllclk; + struct clk usbmcuclk; + struct clk usbclk; + struct mtk_musb_config *cfg; + struct device dev; +}; + +#define to_mtk_musb_glue(d) container_of(d, struct mtk_musb_glue, dev) + +/****************************************************************************** + * phy settings + ******************************************************************************/ +#define USB20_PHY_BASE 0x11110800 +#define USBPHY_READ8(offset) \ + readb((void *)(USB20_PHY_BASE + (offset))) +#define USBPHY_WRITE8(offset, value) \ + writeb(value, (void *)(USB20_PHY_BASE + (offset))) +#define USBPHY_SET8(offset, mask) \ + USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask)) +#define USBPHY_CLR8(offset, mask) \ + USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~(mask))) + +static void mt_usb_phy_poweron(void) +{ + /* + * switch to USB function. + * (system register, force ip into usb mode). + */ + USBPHY_CLR8(0x6b, 0x04); + USBPHY_CLR8(0x6e, 0x01); + USBPHY_CLR8(0x21, 0x03); + + /* RG_USB20_BC11_SW_EN = 1'b0 */ + USBPHY_SET8(0x22, 0x04); + USBPHY_CLR8(0x1a, 0x80); + + /* RG_USB20_DP_100K_EN = 1'b0 */ + /* RG_USB20_DP_100K_EN = 1'b0 */ + USBPHY_CLR8(0x22, 0x03); + + /*OTG enable*/ + USBPHY_SET8(0x20, 0x10); + /* release force suspendm */ + USBPHY_CLR8(0x6a, 0x04); + + mdelay(800); + + /* force enter device mode */ + USBPHY_CLR8(0x6c, 0x10); + USBPHY_SET8(0x6c, 0x2E); + USBPHY_SET8(0x6d, 0x3E); +} + +static void mt_usb_phy_savecurrent(void) +{ + /* + * switch to USB function. + * (system register, force ip into usb mode). + */ + USBPHY_CLR8(0x6b, 0x04); + USBPHY_CLR8(0x6e, 0x01); + USBPHY_CLR8(0x21, 0x03); + + /* release force suspendm */ + USBPHY_CLR8(0x6a, 0x04); + USBPHY_SET8(0x68, 0x04); + /* RG_DPPULLDOWN./RG_DMPULLDOWN. */ + USBPHY_SET8(0x68, 0xc0); + /* RG_XCVRSEL[1:0] = 2'b01 */ + USBPHY_CLR8(0x68, 0x30); + USBPHY_SET8(0x68, 0x10); + /* RG_TERMSEL = 1'b1 */ + USBPHY_SET8(0x68, 0x04); + /* RG_DATAIN[3:0] = 4'b0000 */ + USBPHY_CLR8(0x69, 0x3c); + + /* + * force_dp_pulldown, force_dm_pulldown, + * force_xcversel, force_termsel. + */ + USBPHY_SET8(0x6a, 0xba); + + /* RG_USB20_BC11_SW_EN = 1'b0 */ + USBPHY_CLR8(0x1a, 0x80); + /* RG_USB20_OTG_VBUSSCMP_EN = 1'b0 */ + USBPHY_CLR8(0x1a, 0x10); + + mdelay(800); + + USBPHY_CLR8(0x6a, 0x04); + /* rg_usb20_pll_stable = 1 */ + //USBPHY_SET8(0x63, 0x02); + + mdelay(1); + + /* force suspendm = 1 */ + //USBPHY_SET8(0x6a, 0x04); +} + +static void mt_usb_phy_recover(void) +{ + /* clean PUPD_BIST_EN */ + /* PUPD_BIST_EN = 1'b0 */ + /* PMIC will use it to detect charger type */ + USBPHY_CLR8(0x1d, 0x10); + + /* force_uart_en = 1'b0 */ + USBPHY_CLR8(0x6b, 0x04); + /* RG_UART_EN = 1'b0 */ + USBPHY_CLR8(0x6e, 0x01); + /* force_uart_en = 1'b0 */ + USBPHY_CLR8(0x6a, 0x04); + + USBPHY_CLR8(0x21, 0x03); + USBPHY_CLR8(0x68, 0xf4); + + /* RG_DATAIN[3:0] = 4'b0000 */ + USBPHY_CLR8(0x69, 0x3c); + + USBPHY_CLR8(0x6a, 0xba); + + /* RG_USB20_BC11_SW_EN = 1'b0 */ + USBPHY_CLR8(0x1a, 0x80); + /* RG_USB20_OTG_VBUSSCMP_EN = 1'b1 */ + USBPHY_SET8(0x1a, 0x10); + + //HQA adjustment + USBPHY_CLR8(0x18, 0x08); + USBPHY_SET8(0x18, 0x06); + mdelay(800); + + /* force enter device mode */ + //USBPHY_CLR8(0x6c, 0x10); + //USBPHY_SET8(0x6c, 0x2E); + //USBPHY_SET8(0x6d, 0x3E); + + /* enable VRT internal R architecture */ + /* RG_USB20_INTR_EN = 1'b1 */ + USBPHY_SET8(0x00, 0x20); +} + +/****************************************************************************** + * MUSB Glue code + ******************************************************************************/ + +static irqreturn_t mtk_musb_interrupt(int irq, void *__hci) +{ + struct musb *musb = __hci; + irqreturn_t retval = IRQ_NONE; + + /* read and flush interrupts */ + musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB); +// last_int_usb = musb->int_usb; + if (musb->int_usb) + musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb); + musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX); + if (musb->int_tx) + musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx); + musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX); + if (musb->int_rx) + musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx); + + if (musb->int_usb || musb->int_tx || musb->int_rx) + retval |= musb_interrupt(musb); + + return retval; +} + +/* musb_core does not call enable / disable in a balanced manner <sigh> */ +static bool enabled; + +static int mtk_musb_enable(struct musb *musb) +{ + struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller); + + DBG_I("%s():\n", __func__); + + musb_ep_select(musb->mregs, 0); + musb_writeb(musb->mregs, MUSB_FADDR, 0); + + if (enabled) + return 0; + + mt_usb_phy_recover(); + + enabled = true; + + return 0; +} + +static void mtk_musb_disable(struct musb *musb) +{ + struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller); + int ret; + + DBG_I("%s():\n", __func__); + + if (!enabled) + return; + + mt_usb_phy_savecurrent(); + + enabled = false; +} + +static int mtk_musb_init(struct musb *musb) +{ + struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller); + int ret; + + DBG_I("%s():\n", __func__); + + ret = clk_enable(&glue->usbpllclk); + if (ret) { + dev_err(dev, "failed to enable usbpll clock\n"); + return ret; + } + ret = clk_enable(&glue->usbmcuclk); + if (ret) { + dev_err(dev, "failed to enable usbmcu clock\n"); + return ret; + } + ret = clk_enable(&glue->usbclk); + if (ret) { + dev_err(dev, "failed to enable usb clock\n"); + return ret; + } + + musb->isr = mtk_musb_interrupt; + + return 0; +} + +static int mtk_musb_exit(struct musb *musb) +{ + struct mtk_musb_glue *glue = to_mtk_musb_glue(musb->controller); + + clk_disable(&glue->usbclk); + clk_disable(&glue->usbmcuclk); + clk_disable(&glue->usbpllclk); + + return 0; +} + +static const struct musb_platform_ops mtk_musb_ops = { + .init = mtk_musb_init, + .exit = mtk_musb_exit, + .enable = mtk_musb_enable, + .disable = mtk_musb_disable, +}; + +/* MTK OTG supports up to 7 endpoints */ +#define MTK_MUSB_MAX_EP_NUM 8 +#define MTK_MUSB_RAM_BITS 16 + +static struct musb_fifo_cfg mtk_musb_mode_cfg[] = { + MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(6, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(6, FIFO_RX, 512), + MUSB_EP_FIFO_SINGLE(7, FIFO_TX, 512), + MUSB_EP_FIFO_SINGLE(7, FIFO_RX, 512), +}; + +static struct musb_hdrc_config musb_config = { + .fifo_cfg = mtk_musb_mode_cfg, + .fifo_cfg_size = ARRAY_SIZE(mtk_musb_mode_cfg), + .multipoint = true, + .dyn_fifo = true, + .num_eps = MTK_MUSB_MAX_EP_NUM, + .ram_bits = MTK_MUSB_RAM_BITS, +}; + +static int musb_usb_probe(struct udevice *dev) +{ + struct mtk_musb_glue *glue = dev_get_priv(dev); + struct musb_host_data *host = &glue->mdata; + struct musb_hdrc_platform_data pdata; + void *base = dev_read_addr_ptr(dev); + int ret; + + DBG_I("%s():\n", __func__); + +#ifdef CONFIG_USB_MUSB_HOST + struct usb_bus_priv *priv = dev_get_uclass_priv(dev); +#endif + + if (!base) + return -EINVAL; + + glue->cfg = (struct mtk_musb_config *)dev_get_driver_data(dev); + if (!glue->cfg) + return -EINVAL; + + ret = clk_get_by_name(dev, "usbpll", &glue->usbpllclk); + if (ret) { + dev_err(dev, "failed to get usbpll clock\n"); + return ret; + } + ret = clk_get_by_name(dev, "usbmcu", &glue->usbmcuclk); + if (ret) { + dev_err(dev, "failed to get usbmcu clock\n"); + return ret; + } + ret = clk_get_by_name(dev, "usb", &glue->usbclk); + if (ret) { + dev_err(dev, "failed to get usb clock\n"); + return ret; + } + + memset(&pdata, 0, sizeof(pdata)); + pdata.power = (u8)400; + pdata.platform_ops = &mtk_musb_ops; + pdata.config = glue->cfg->config; + +#ifdef CONFIG_USB_MUSB_HOST + priv->desc_before_addr = true; + + pdata.mode = MUSB_HOST; + host->host = musb_init_controller(&pdata, &glue->dev, base); + if (!host->host) + return -EIO; + + ret = musb_lowlevel_init(host); + if (!ret) + printf("MTK MUSB OTG (Host)\n"); +#else + pdata.mode = MUSB_PERIPHERAL; + host->host = musb_register(&pdata, &glue->dev, base); + if (!host->host) + return -EIO; + + printf("MTK MUSB OTG (Peripheral)\n"); +#endif + + mt_usb_phy_poweron(); + + return ret; +} + +static int musb_usb_remove(struct udevice *dev) +{ + struct mtk_musb_glue *glue = dev_get_priv(dev); + struct musb_host_data *host = &glue->mdata; + + musb_stop(host->host); + free(host->host); + host->host = NULL; + + return 0; +} + +static const struct mtk_musb_config mt8518_cfg = { + .config = &musb_config, +}; + +static const struct udevice_id mtk_musb_ids[] = { + { .compatible = "mediatek,mt8518-musb", + .data = (ulong)&mt8518_cfg }, + { } +}; + +U_BOOT_DRIVER(mtk_musb) = { + .name = "mtk_musb", +#ifdef CONFIG_USB_MUSB_HOST + .id = UCLASS_USB, +#else + .id = UCLASS_USB_GADGET_GENERIC, +#endif + .of_match = mtk_musb_ids, + .probe = musb_usb_probe, + .remove = musb_usb_remove, +#ifdef CONFIG_USB_MUSB_HOST + .ops = &musb_usb_ops, +#endif + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct mtk_musb_glue), +};

Add board_late_init function to init usb gadget driver for mt8518
Signed-off-by: mingming lee mingming.lee@mediatek.com --- board/mediatek/mt8518/mt8518_ap1.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/board/mediatek/mt8518/mt8518_ap1.c b/board/mediatek/mt8518/mt8518_ap1.c index 9710907fe2..2ac7c6cd18 100644 --- a/board/mediatek/mt8518/mt8518_ap1.c +++ b/board/mediatek/mt8518/mt8518_ap1.c @@ -16,3 +16,21 @@ int board_init(void) debug("gd->fdt_blob is %p\n", gd->fdt_blob); return 0; } + +int board_late_init(void) +{ +#ifdef CONFIG_USB_GADGET + struct udevice *dev; + int ret; +#endif + +#ifdef CONFIG_USB_GADGET + ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev); + if (ret) { + pr_err("%s: Cannot find USB device\n", __func__); + return ret; + } +#endif + + return 0; +}

set common fastboot variables for mt8518
Signed-off-by: mingming lee mingming.lee@mediatek.com --- include/configs/mt8518.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/include/configs/mt8518.h b/include/configs/mt8518.h index 8906245a62..9bc9c04e66 100644 --- a/include/configs/mt8518.h +++ b/include/configs/mt8518.h @@ -11,9 +11,6 @@
#include <linux/sizes.h>
-#define CONFIG_ENV_SIZE SZ_4K - -/* Machine ID */ #define CONFIG_SYS_NONCACHED_MEMORY SZ_1M
#define CONFIG_CPU_ARMV8 @@ -39,7 +36,7 @@ /* ENV Setting */ #if defined(CONFIG_MMC_MTK) #define CONFIG_SYS_MMC_ENV_DEV 0 -#define CONFIG_ENV_OFFSET 0x4E60000 + #define CONFIG_ENV_OVERWRITE
/* MMC offset in block unit,and block size is 0x200 */ @@ -58,10 +55,15 @@ #define ENV_BOOT_CMD \ "mtk_boot=run boot_rd_img;bootm;\0"
+#define ENV_FASTBOOT \ + "serial#=1234567890ABCDEF\0" \ + "board=mt8518\0" + #define CONFIG_EXTRA_ENV_SETTINGS \ "fdt_high=0x6c000000\0" \ ENV_DEVICE_SETTINGS \ ENV_BOOT_READ_IMAGE \ + ENV_FASTBOOT \ ENV_BOOT_CMD \ "bootcmd=run mtk_boot;\0" \

Enable board_late_init and usb gadget for mt8518
Signed-off-by: mingming lee mingming.lee@mediatek.com --- configs/mt8518_ap1_emmc_defconfig | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/configs/mt8518_ap1_emmc_defconfig b/configs/mt8518_ap1_emmc_defconfig index dd42076f4d..9857b7b776 100644 --- a/configs/mt8518_ap1_emmc_defconfig +++ b/configs/mt8518_ap1_emmc_defconfig @@ -39,3 +39,13 @@ CONFIG_DM_MMC=y CONFIG_MMC_MTK=y CONFIG_MMC_HS200_SUPPORT=y # CONFIG_ENV_IS_IN_MMC is not set +CONFIG_BOARD_LATE_INIT=y +CONFIG_USB=y +CONFIG_USB_GADGET=y +CONFIG_DM_USB=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_MUSB_MT85XX=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_USB_GADGET_VENDOR_NUM=0x0bb4 +CONFIG_USB_GADGET_PRODUCT_NUM=0x0c01 +CONFIG_USB_GADGET_MANUFACTURER="Mediatek." \ No newline at end of file

Enable EFI module. Enable fastboot.
Signed-off-by: mingming lee mingming.lee@mediatek.com --- configs/mt8518_ap1_emmc_defconfig | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/configs/mt8518_ap1_emmc_defconfig b/configs/mt8518_ap1_emmc_defconfig index 9857b7b776..714fd8e087 100644 --- a/configs/mt8518_ap1_emmc_defconfig +++ b/configs/mt8518_ap1_emmc_defconfig @@ -34,6 +34,7 @@ CONFIG_WDT_MTK=y CONFIG_CLK=y CONFIG_TIMER=y CONFIG_MTK_TIMER=y +CONFIG_MMC=y CONFIG_CMD_MMC=y CONFIG_DM_MMC=y CONFIG_MMC_MTK=y @@ -48,4 +49,14 @@ CONFIG_USB_MUSB_MT85XX=y CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_GADGET_VENDOR_NUM=0x0bb4 CONFIG_USB_GADGET_PRODUCT_NUM=0x0c01 -CONFIG_USB_GADGET_MANUFACTURER="Mediatek." \ No newline at end of file +CONFIG_USB_GADGET_MANUFACTURER="Mediatek." +CONFIG_EFI_PARTITION=y +CONFIG_FASTBOOT_GPT_NAME=GPT +CONFIG_USB_FUNCTION_FASTBOOT=y +CONFIG_FASTBOOT=y +CONFIG_CMD_FASTBOOT=y +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_BUF_ADDR=0x56000000 +CONFIG_FASTBOOT_BUF_SIZE=0x1E00000

This patch includes the following: 1. Add fastboot command to erase the whole EMMC_USER 2. Add fastboot command to flash image at EMMC_BOOT1 3. Add fastboot command to erase the whole EMMC_BOOT1 4. Enale CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT for mt8518
Signed-off-by: mingming lee mingming.lee@mediatek.com --- configs/mt8518_ap1_emmc_defconfig | 1 + drivers/fastboot/Kconfig | 30 ++++++++++ drivers/fastboot/fb_mmc.c | 98 ++++++++++++++++++++++++++++++- 3 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/configs/mt8518_ap1_emmc_defconfig b/configs/mt8518_ap1_emmc_defconfig index 714fd8e087..e929d40d75 100644 --- a/configs/mt8518_ap1_emmc_defconfig +++ b/configs/mt8518_ap1_emmc_defconfig @@ -60,3 +60,4 @@ CONFIG_FASTBOOT_FLASH_MMC=y CONFIG_FASTBOOT_FLASH_MMC_DEV=0 CONFIG_FASTBOOT_BUF_ADDR=0x56000000 CONFIG_FASTBOOT_BUF_SIZE=0x1E00000 +CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT=y \ No newline at end of file diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 433ea0dc3b..a4cf52dc9a 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -104,6 +104,36 @@ config FASTBOOT_FLASH_NAND_TRIMFFS When flashing NAND enable the DROP_FFS flag to drop trailing all-0xff pages.
+config FASTBOOT_MMC_BOOT1_SUPPORT + bool "Enable EMMC_BOOT1 flash/erase" + depends on FASTBOOT_FLASH_MMC && EFI_PARTITION + help + The fastboot "flash" and "erase" commands normally does operations + on EMMC userdata. Define this to enable the special commands to + flash/erase EMMC_BOOT1. + The default target name for updating EMMC_BOOT1 is "mmc0boot0". + +config FASTBOOT_MMC_BOOT1_NAME + string "Target name for updating EMMC_BOOT1" + depends on FASTBOOT_MMC_BOOT1_SUPPORT + default "mmc0boot0" + help + The fastboot "flash" and "erase" commands support operations on + EMMC_BOOT1. This occurs when the specified "EMMC_BOOT1 name" on + the "fastboot flash" and "fastboot erase" commands match the value + defined here. + The default target name for updating EMMC_BOOT1 is "mmc0boot0". + +config FASTBOOT_MMC_USER_NAME + string "Target name for erasing EMMC_USER" + depends on FASTBOOT_FLASH_MMC && EFI_PARTITION + default "mmc0" + help + The fastboot "erase" command supports erasing EMMC_USER. This occurs + when the specified "EMMC_USER name" on the "fastboot erase" commands + match the value defined here. + The default target name for erasing EMMC_USER is "mmc0". + config FASTBOOT_GPT_NAME string "Target name for updating GPT" depends on FASTBOOT_FLASH_MMC && EFI_PARTITION diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index b0b19c5762..4eabbfdf3d 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -129,6 +129,76 @@ static void write_raw_image(struct blk_desc *dev_desc, disk_partition_t *info, fastboot_okay(NULL, response); }
+#ifdef CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT +static int fb_mmc_erase_mmc_hwpart(struct blk_desc *dev_desc) +{ + lbaint_t blks; + + debug("Start Erasing mmc hwpart[%u]...\n", dev_desc->hwpart); + + blks = fb_mmc_blk_write(dev_desc, 0, dev_desc->lba, NULL); + + if (blks != dev_desc->lba) { + pr_err("Failed to erase mmc hwpart[%u]\n", dev_desc->hwpart); + return 1; + } + + printf("........ erased %lu bytes from mmc hwpart[%u]\n", + dev_desc->lba * dev_desc->blksz, dev_desc->hwpart); + + return 0; +} + +static void fb_mmc_boot1_ops(struct blk_desc *dev_desc, void *buffer, + u32 buff_sz, char *response) +{ + lbaint_t blkcnt; + lbaint_t blks; + unsigned long blksz; + + // To operate on EMMC_BOOT1 (mmc0boot0), we first change the hwpart + if (blk_dselect_hwpart(dev_desc, 1)) { + pr_err("Failed to select hwpart\n"); + fastboot_fail("Failed to select hwpart", response); + return; + } + + if (buffer) { /* flash */ + + /* determine number of blocks to write */ + blksz = dev_desc->blksz; + blkcnt = ((buff_sz + (blksz - 1)) & ~(blksz - 1)); + blkcnt = lldiv(blkcnt, blksz); + + if (blkcnt > dev_desc->lba) { + pr_err("Image size too large\n"); + fastboot_fail("Image size too large", response); + return; + } + + debug("Start Flashing Image to EMMC_BOOT1...\n"); + + blks = fb_mmc_blk_write(dev_desc, 0, blkcnt, buffer); + + if (blks != blkcnt) { + pr_err("Failed to write EMMC_BOOT1\n"); + fastboot_fail("Failed to write EMMC_BOOT1", response); + return; + } + + printf("........ wrote %lu bytes to EMMC_BOOT1\n", + blkcnt * blksz); + } else { /* erase */ + if (fb_mmc_erase_mmc_hwpart(dev_desc)) { + fastboot_fail("Failed to erase EMMC_BOOT1", response); + return; + } + } + + fastboot_okay(NULL, response); +} +#endif + #ifdef CONFIG_ANDROID_BOOT_IMAGE /** * Read Android boot image header from boot partition. @@ -345,8 +415,17 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer, return; }
+#ifdef CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT + if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) { + fb_mmc_boot1_ops(dev_desc, download_buffer, + download_bytes, response); + return; + } +#endif + #if CONFIG_IS_ENABLED(EFI_PARTITION) - if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0) { + if (strcmp(cmd, CONFIG_FASTBOOT_GPT_NAME) == 0 || + strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) { printf("%s: updating MBR, Primary and Backup GPT(s)\n", __func__); if (is_valid_gpt_buf(dev_desc, download_buffer)) { @@ -457,6 +536,23 @@ void fastboot_mmc_erase(const char *cmd, char *response) return; }
+#ifdef CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT + if (strcmp(cmd, CONFIG_FASTBOOT_MMC_BOOT1_NAME) == 0) { + /* erase EMMC boot1 */ + fb_mmc_boot1_ops(dev_desc, NULL, 0, response); + return; + } +#endif + + if (strcmp(cmd, CONFIG_FASTBOOT_MMC_USER_NAME) == 0) { + /* erase EMMC userdata */ + if (fb_mmc_erase_mmc_hwpart(dev_desc)) + fastboot_fail("Failed to erase EMMC_USER", response); + else + fastboot_okay(NULL, response); + return; + } + ret = part_get_info_by_name_or_alias(dev_desc, cmd, &info); if (ret < 0) { pr_err("cannot find partition: '%s'\n", cmd);

On Mon, Jan 06, 2020 at 02:26:49PM +0800, mingming lee wrote:
This patch includes the following:
- Add fastboot command to erase the whole EMMC_USER
- Add fastboot command to flash image at EMMC_BOOT1
- Add fastboot command to erase the whole EMMC_BOOT1
- Enale CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT for mt8518
Signed-off-by: mingming lee mingming.lee@mediatek.com
This breaks building of dra7xx_evm and possibly others, thanks.

On Wed, 2020-01-15 at 15:48 -0500, Tom Rini wrote:
On Mon, Jan 06, 2020 at 02:26:49PM +0800, mingming lee wrote:
This patch includes the following:
- Add fastboot command to erase the whole EMMC_USER
- Add fastboot command to flash image at EMMC_BOOT1
- Add fastboot command to erase the whole EMMC_BOOT1
- Enale CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT for mt8518
Signed-off-by: mingming lee mingming.lee@mediatek.com
This breaks building of dra7xx_evm and possibly others, thanks.
hi Tom,
Thank you very much for the review, I would fixed it in the next version.
By The way, I wonder could U pls share your way for check? Then in the futher I could check it all on my local before submit.

On Thu, Jan 16, 2020 at 09:52:16AM +0800, Mingming Lee wrote:
On Wed, 2020-01-15 at 15:48 -0500, Tom Rini wrote:
On Mon, Jan 06, 2020 at 02:26:49PM +0800, mingming lee wrote:
This patch includes the following:
- Add fastboot command to erase the whole EMMC_USER
- Add fastboot command to flash image at EMMC_BOOT1
- Add fastboot command to erase the whole EMMC_BOOT1
- Enale CONFIG_FASTBOOT_MMC_BOOT1_SUPPORT for mt8518
Signed-off-by: mingming lee mingming.lee@mediatek.com
This breaks building of dra7xx_evm and possibly others, thanks.
hi Tom,
Thank you very much for the review, I would fixed it in the next version.
By The way, I wonder could U pls share your way for check? Then in the futher I could check it all on my local before submit.
The easiest way would be to use Travis CI or Azure or GitLab to build the world, as that's one of my tests.
participants (3)
-
Mingming Lee
-
mingming lee
-
Tom Rini