mirror of
https://github.com/armbian/build.git
synced 2025-09-19 20:51:12 +02:00
404 lines
11 KiB
Diff
404 lines
11 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Paolo Sabatino <paolo.sabatino@gmail.com>
|
|
Date: Thu, 4 Jul 2024 21:49:20 +0200
|
|
Subject: UMS mode for Asus Tinkerboard
|
|
|
|
---
|
|
arch/arm/include/asm/arch-rockchip/gpio.h | 22 ++
|
|
arch/arm/mach-rockchip/board.c | 114 ++++++++++
|
|
arch/arm/mach-rockchip/spl.c | 22 ++
|
|
cmd/usb_mass_storage.c | 9 +-
|
|
common/autoboot.c | 22 ++
|
|
common/board_r.c | 1 +
|
|
drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c | 1 +
|
|
drivers/usb/gadget/f_mass_storage.c | 10 +-
|
|
include/init.h | 1 +
|
|
include/linux/usb/gadget.h | 3 +
|
|
10 files changed, 202 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/arch/arm/include/asm/arch-rockchip/gpio.h b/arch/arm/include/asm/arch-rockchip/gpio.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/arch/arm/include/asm/arch-rockchip/gpio.h
|
|
+++ b/arch/arm/include/asm/arch-rockchip/gpio.h
|
|
@@ -24,6 +24,28 @@ struct rockchip_gpio_regs {
|
|
};
|
|
check_member(rockchip_gpio_regs, ls_sync, 0x60);
|
|
|
|
+/*
|
|
+ * RK3288 IO memory map:
|
|
+ *
|
|
+ */
|
|
+#define RKIO_GPIO0_PHYS 0xFF750000
|
|
+#define RKIO_GRF_PHYS 0xFF770000
|
|
+#define RKIO_GPIO1_PHYS 0xFF780000
|
|
+#define RKIO_GPIO2_PHYS 0xFF790000
|
|
+#define RKIO_GPIO3_PHYS 0xFF7A0000
|
|
+#define RKIO_GPIO4_PHYS 0xFF7B0000
|
|
+#define RKIO_GPIO5_PHYS 0xFF7C0000
|
|
+#define RKIO_GPIO6_PHYS 0xFF7D0000
|
|
+
|
|
+/* gpio power down/up control */
|
|
+#define GRF_GPIO2A_P 0x150
|
|
+#define GRF_GPIO6A_P 0x190
|
|
+
|
|
+/* gpio input/output control */
|
|
+#define GPIO_SWPORT_DR 0x00
|
|
+#define GPIO_SWPORT_DDR 0x04
|
|
+#define GPIO_EXT_PORT 0x50
|
|
+
|
|
enum gpio_pu_pd {
|
|
GPIO_PULL_NORMAL = 0,
|
|
GPIO_PULL_UP,
|
|
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/arch/arm/mach-rockchip/board.c
|
|
+++ b/arch/arm/mach-rockchip/board.c
|
|
@@ -19,6 +19,7 @@
|
|
#include <hash.h>
|
|
#include <init.h>
|
|
#include <log.h>
|
|
+#include <linux/delay.h>
|
|
#include <mmc.h>
|
|
#include <dm/uclass-internal.h>
|
|
#include <misc.h>
|
|
@@ -30,6 +31,7 @@
|
|
#include <u-boot/sha256.h>
|
|
#include <asm/cache.h>
|
|
#include <asm/io.h>
|
|
+#include <asm/arch-rockchip/gpio.h>
|
|
#include <asm/arch-rockchip/boot_mode.h>
|
|
#include <asm/arch-rockchip/clock.h>
|
|
#include <asm/arch-rockchip/periph.h>
|
|
@@ -184,6 +186,19 @@ static void gpt_capsule_update_setup(void)
|
|
}
|
|
#endif /* CONFIG_EFI_HAVE_CAPSULE_SUPPORT && CONFIG_EFI_PARTITION */
|
|
|
|
+enum project_id {
|
|
+ TinkerBoardS = 0,
|
|
+ TinkerBoard = 7,
|
|
+};
|
|
+
|
|
+enum pcb_id {
|
|
+ SR,
|
|
+ ER,
|
|
+ PR,
|
|
+};
|
|
+
|
|
+extern bool force_ums;
|
|
+
|
|
__weak int rk_board_late_init(void)
|
|
{
|
|
return 0;
|
|
@@ -200,6 +215,105 @@ int board_late_init(void)
|
|
return rk_board_late_init();
|
|
}
|
|
|
|
+/*
|
|
+*
|
|
+* usb current limit : GPIO6_A6 (H:unlock, L:lock)
|
|
+*
|
|
+*/
|
|
+void usb_current_limit_ctrl(bool unlock_current)
|
|
+{
|
|
+ int tmp;
|
|
+
|
|
+ printf("%s: unlock_current = %d\n", __func__, unlock_current);
|
|
+ tmp = readl(RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+ if(unlock_current == true)
|
|
+ writel(tmp | 0x40, RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+ else
|
|
+ writel(tmp & ~0x40, RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+
|
|
+ tmp = readl(RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+ writel(tmp | 0x40, RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+}
|
|
+
|
|
+/*
|
|
+*
|
|
+* eMMC maskrom mode : GPIO6_A7 (H:disable maskrom, L:enable maskrom)
|
|
+*
|
|
+*/
|
|
+void rk3288_maskrom_ctrl(bool enable_emmc)
|
|
+{
|
|
+ int tmp;
|
|
+
|
|
+ printf("%s: enable_emmc = %d\n", __func__, enable_emmc);
|
|
+ tmp = readl(RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+ if(enable_emmc == true)
|
|
+ writel(tmp | 0x80, RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+ else
|
|
+ writel(tmp & ~0x80, RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+
|
|
+ tmp = readl(RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+ writel(tmp | 0x80, RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+ mdelay(10);
|
|
+}
|
|
+
|
|
+/*
|
|
+*
|
|
+* project id : GPIO2_A3 GPIO2_A2 GPIO2_A1
|
|
+* pcb id : GPIO2_B2 GPIO2_B1 GPIO2_B0
|
|
+* SDP/CDP : GPIO6_A5 (H:SDP, L:CDP)
|
|
+* usb current limit : GPIO6_A6 (H:unlock, L:lock)
|
|
+* eMMC maskrom mode : GPIO6_A7 (H:disable maskrom, L:enable maskrom)
|
|
+*
|
|
+* Please check TRM V1.2 part1 page 152 for the following register settings
|
|
+*
|
|
+*/
|
|
+int check_force_enter_ums_mode(void)
|
|
+{
|
|
+ int tmp;
|
|
+ enum pcb_id pcbid;
|
|
+ enum project_id projectid;
|
|
+
|
|
+ // GPIO2_A3/GPIO2_A2/GPIO2_A1 pull up enable
|
|
+ tmp = readl(RKIO_GRF_PHYS + GRF_GPIO2A_P);
|
|
+ writel((tmp&~(0x03F<<2)) | 0x3F<<(16 + 2) | 0x15<<2, RKIO_GRF_PHYS + GRF_GPIO2A_P);
|
|
+
|
|
+ // GPIO2_A3/GPIO2_A2/GPIO2_A1/GPIO2_B2/GPIO2_B1/GPIO2_B0 set to input
|
|
+ tmp = readl(RKIO_GPIO2_PHYS + GPIO_SWPORT_DDR);
|
|
+ writel(tmp & ~(0x70E), RKIO_GPIO2_PHYS + GPIO_SWPORT_DDR);
|
|
+
|
|
+ // GPIO6_A5 pull up/down disable
|
|
+ tmp = readl(RKIO_GRF_PHYS + GRF_GPIO6A_P);
|
|
+ writel((tmp&~(0x03<<10)) | 0x03<<(16 + 10), RKIO_GRF_PHYS + GRF_GPIO6A_P);
|
|
+
|
|
+ // GPIO6_A5 set to input
|
|
+ tmp = readl(RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+ writel(tmp & ~(0x20), RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+
|
|
+ mdelay(10);
|
|
+
|
|
+ // read GPIO2_A3/GPIO2_A2/GPIO2_A1 value
|
|
+ projectid = (readl(RKIO_GPIO2_PHYS + GPIO_EXT_PORT) & 0x0E) >>1;
|
|
+
|
|
+ // read GPIO2_B2/GPIO2_B1/GPIO2_B0 value
|
|
+ pcbid = (readl(RKIO_GPIO2_PHYS + GPIO_EXT_PORT) & 0x700) >> 8;
|
|
+
|
|
+ // only Tinker Board S and the PR stage PCB has this function
|
|
+ if(projectid!=TinkerBoard && pcbid >= ER){
|
|
+ printf("PC event = 0x%x\n", readl(RKIO_GPIO6_PHYS + GPIO_EXT_PORT)&0x20);
|
|
+ if((readl(RKIO_GPIO6_PHYS + GPIO_EXT_PORT)&0x20)==0x20) {
|
|
+ // SDP detected, enable EMMC and unlock usb current limit
|
|
+ printf("usb connected to SDP, force enter ums mode\n");
|
|
+ force_ums = true;
|
|
+ rk3288_maskrom_ctrl(true);
|
|
+ usb_current_limit_ctrl(true);
|
|
+ } else {
|
|
+ usb_current_limit_ctrl(false);
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
int board_init(void)
|
|
{
|
|
int ret;
|
|
diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/arch/arm/mach-rockchip/spl.c
|
|
+++ b/arch/arm/mach-rockchip/spl.c
|
|
@@ -116,10 +116,32 @@ __weak int arch_cpu_init(void)
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+*
|
|
+* usb current limit : GPIO6_A6 (H:unlock, L:lock)
|
|
+*
|
|
+*/
|
|
+void usb_current_limit_ctrl(bool unlock_current)
|
|
+{
|
|
+ int tmp;
|
|
+
|
|
+#include <asm/arch/gpio.h>
|
|
+
|
|
+ tmp = readl(RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+ if(unlock_current == true)
|
|
+ writel(tmp | 0x40, RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+ else
|
|
+ writel(tmp & ~0x40, RKIO_GPIO6_PHYS + GPIO_SWPORT_DR);
|
|
+
|
|
+ tmp = readl(RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+ writel(tmp | 0x40, RKIO_GPIO6_PHYS + GPIO_SWPORT_DDR);
|
|
+}
|
|
+
|
|
void board_init_f(ulong dummy)
|
|
{
|
|
int ret;
|
|
|
|
+ usb_current_limit_ctrl(true);
|
|
board_early_init_f();
|
|
|
|
ret = spl_early_init();
|
|
diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/cmd/usb_mass_storage.c
|
|
+++ b/cmd/usb_mass_storage.c
|
|
@@ -108,7 +108,7 @@ static int ums_init(const char *devtype, const char *devnums_part_str)
|
|
name = malloc(UMS_NAME_LEN);
|
|
if (!name)
|
|
goto cleanup;
|
|
- snprintf(name, UMS_NAME_LEN, "UMS disk %d", ums_count);
|
|
+ snprintf(name, UMS_NAME_LEN, "Armbian UMS disk %d", ums_count);
|
|
ums[ums_count].name = name;
|
|
ums[ums_count].block_dev = *block_dev;
|
|
|
|
@@ -133,7 +133,7 @@ cleanup:
|
|
return ret;
|
|
}
|
|
|
|
-static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
|
|
+int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
|
|
int argc, char *const argv[])
|
|
{
|
|
const char *usb_controller;
|
|
@@ -217,6 +217,11 @@ static int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag,
|
|
dm_usb_gadget_handle_interrupts(udc);
|
|
|
|
rc = fsg_main_thread(NULL);
|
|
+
|
|
+ if (rc == -ETIMEDOUT) {
|
|
+ goto cleanup_register;
|
|
+ }
|
|
+
|
|
if (rc) {
|
|
/* Check I/O error */
|
|
if (rc == -EIO)
|
|
diff --git a/common/autoboot.c b/common/autoboot.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/common/autoboot.c
|
|
+++ b/common/autoboot.c
|
|
@@ -40,6 +40,9 @@ DECLARE_GLOBAL_DATA_PTR;
|
|
static int stored_bootdelay;
|
|
static int menukey;
|
|
|
|
+bool force_ums = false;
|
|
+bool getdescriptor = false;
|
|
+
|
|
#if defined(CONFIG_AUTOBOOT_STOP_STR_CRYPT)
|
|
#define AUTOBOOT_STOP_STR_CRYPT CONFIG_AUTOBOOT_STOP_STR_CRYPT
|
|
#else
|
|
@@ -125,6 +128,10 @@ static int passwd_abort_crypt(uint64_t etime)
|
|
return abort;
|
|
}
|
|
|
|
+extern int do_usb_mass_storage(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
|
|
+void usb_current_limit_ctrl(bool unlock_current);
|
|
+void rk3288_maskrom_ctrl(bool enable_emmc);
|
|
+
|
|
/*
|
|
* Use a "constant-length" time compare function for this
|
|
* hash compare:
|
|
@@ -491,6 +498,21 @@ void autoboot_command(const char *s)
|
|
{
|
|
debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
|
|
|
|
+ if (force_ums) {
|
|
+ // force to enter ums mode
|
|
+ char *local_args[4];
|
|
+ char str1[]="ums", str2[]="1", str3[]="mmc", str4[]="0";
|
|
+
|
|
+ local_args[0]=str1;
|
|
+ local_args[1]=str2;
|
|
+ local_args[2]=str3;
|
|
+ local_args[3]=str4;
|
|
+ if (do_usb_mass_storage(NULL, 0, 4, local_args) == -ETIMEDOUT) {
|
|
+ rk3288_maskrom_ctrl(false);
|
|
+ usb_current_limit_ctrl(false);
|
|
+ }
|
|
+ }
|
|
+
|
|
if (s && (stored_bootdelay == -2 ||
|
|
(stored_bootdelay != -1 && !abortboot(stored_bootdelay)))) {
|
|
bool lock;
|
|
diff --git a/common/board_r.c b/common/board_r.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/common/board_r.c
|
|
+++ b/common/board_r.c
|
|
@@ -667,6 +667,7 @@ static init_fnc_t init_sequence_r[] = {
|
|
#ifdef CONFIG_MMC
|
|
initr_mmc,
|
|
#endif
|
|
+ check_force_enter_ums_mode,
|
|
#ifdef CONFIG_XEN
|
|
xen_init,
|
|
#endif
|
|
diff --git a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
|
|
+++ b/drivers/usb/gadget/dwc2_udc_otg_xfer_dma.c
|
|
@@ -1393,6 +1393,7 @@ static void dwc2_ep0_setup(struct dwc2_udc *dev)
|
|
debug_cond(DEBUG_SETUP != 0,
|
|
"%s: *** USB_REQ_GET_DESCRIPTOR\n",
|
|
__func__);
|
|
+ getdescriptor = true;
|
|
break;
|
|
|
|
case USB_REQ_SET_INTERFACE:
|
|
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
|
|
index 111111111111..222222222222 100644
|
|
--- a/drivers/usb/gadget/f_mass_storage.c
|
|
+++ b/drivers/usb/gadget/f_mass_storage.c
|
|
@@ -657,7 +657,7 @@ static void busy_indicator(void)
|
|
static int sleep_thread(struct fsg_common *common)
|
|
{
|
|
int rc = 0;
|
|
- int i = 0, k = 0;
|
|
+ int i = 0, k = 0, j = 0;
|
|
|
|
/* Wait until a signal arrives or we are woken up */
|
|
for (;;) {
|
|
@@ -668,6 +668,7 @@ static int sleep_thread(struct fsg_common *common)
|
|
busy_indicator();
|
|
i = 0;
|
|
k++;
|
|
+ j++;
|
|
}
|
|
|
|
if (k == 10) {
|
|
@@ -686,6 +687,13 @@ static int sleep_thread(struct fsg_common *common)
|
|
k = 0;
|
|
}
|
|
|
|
+ if (j == 300) { //about 3 seconds
|
|
+ if(force_ums && !getdescriptor) {
|
|
+ printf("wait for usb get descriptor cmd timeout\n");
|
|
+ return -ETIMEDOUT;
|
|
+ }
|
|
+ }
|
|
+
|
|
dm_usb_gadget_handle_interrupts(udcdev);
|
|
}
|
|
common->thread_wakeup_needed = 0;
|
|
diff --git a/include/init.h b/include/init.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/init.h
|
|
+++ b/include/init.h
|
|
@@ -337,6 +337,7 @@ int board_early_init_f(void);
|
|
/* manipulate the U-Boot fdt before its relocation */
|
|
int board_fix_fdt(void *rw_fdt_blob);
|
|
int board_late_init(void);
|
|
+int check_force_enter_ums_mode (void);
|
|
int board_postclk_init(void); /* after clocks/timebase, before env/serial */
|
|
int board_early_init_r(void);
|
|
|
|
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
|
|
index 111111111111..222222222222 100644
|
|
--- a/include/linux/usb/gadget.h
|
|
+++ b/include/linux/usb/gadget.h
|
|
@@ -25,6 +25,9 @@
|
|
|
|
struct usb_ep;
|
|
|
|
+extern bool force_ums;
|
|
+extern bool getdescriptor;
|
|
+
|
|
/**
|
|
* struct usb_request - describes one i/o request
|
|
* @buf: Buffer used for data. Always provide this; some controllers
|
|
--
|
|
Armbian
|
|
|