[PATCH v1 00/17] Add rk3066 ADC and USB support

Add rk3066 ADC and USB support.
The Rockchip SoC rk3066 has no support for MMC and USB in the BootROM. The TPL/SPL parts are mostly stored on NAND. With U-boot stored on an external media the moment a user wants to start a recovery action it has to be done in SPL. Some boards only have one ADC switch for the user and no serial console. The U-boot USB drivers only works in combination with OF_REAL enabled.
For current ARM SoCs the FDT stored in BBS is erased after SPL relocation in the crt0.S main function. So for drivers to work in SPL, FDT is move to the end of DRAM. The global_data must update there pointers. The common Rockchip functions must also become available in SPL.
Most work has to be done on the ADC driver that has recently had a "upgrade" for a vref regulator. For Rockchip this regulator are mostly fixed. As we are in SPL that would introduce 2 extra U-boot classes UCLASS_REGULATOR and UCLASS_GPIO. In SPL there's no pin control yet, so reduce code and read these ADC properties from the DT in SPL. While testing some improvement had to be made for reliability. Fixup SPL compile and the way the ADC section is shown in U-boot's main menu.
Add a __weak recovery button function as condition to enter the recovery mode in spl. It then looks for a boot_device to select a storage function method. And finally run the rockusb gadget while connected to a USB host.
Enable all new futures by adding them to the mk808_defconfig.
Johan Jonker (16): rockchip: spl: fix reloc gd and FDT blob pointer rockchip: spl: allow more boot devices rockchip: spl-boot-order: add usb boot option rockchip: board: allow spl compile for usb init functions rockchip: usb: gadget: rockusb: enable spl compile rockchip: configs: mk808: add spl usb configs arm: dts: rockchip: mk808: add adc usb required properties for spl rockchip: adc: enable spl compile class driver rockchip: adc: reduce error notifications from class driver rockchip: adc: enable spl compile rockchip-saradc driver rockchip: adc: fix adc timer rockchip: adc: fix the hangups rockchip: adc: make adc branch compile in SPL rockchip: adc: move config items in a sub menu rockchip: rk3066: add recovery mode in spl rockchip: configs: mk808: enable usb support
Paweł Jarosz (1): rockchip: rk3066: config nand data pins in spl
arch/arm/dts/rk3066a-mk808-u-boot.dtsi | 29 ++++++ .../arm/include/asm/arch-rockchip/f_rockusb.h | 1 + arch/arm/mach-rockchip/Makefile | 3 +- arch/arm/mach-rockchip/rk3066/rk3066.c | 93 ++++++++++++++++++- arch/arm/mach-rockchip/sdram.c | 1 + arch/arm/mach-rockchip/spl-boot-order.c | 3 + arch/arm/mach-rockchip/spl.c | 21 ++++- configs/mk808_defconfig | 21 ++++- drivers/Makefile | 3 +- drivers/adc/Kconfig | 33 +++++++ drivers/adc/Makefile | 4 +- drivers/adc/adc-uclass.c | 47 +++++++--- drivers/adc/rockchip-saradc.c | 71 ++++++++++---- drivers/usb/gadget/Kconfig | 10 ++ drivers/usb/gadget/Makefile | 2 +- include/configs/mk808.h | 3 + 16 files changed, 308 insertions(+), 37 deletions(-)

When the Rockchip function dram_init() is called in the spl.c board_init_f() the variable gd->ram_base returns 0. This is problematic for functions after the gd relocation. Fix by adding ram.base to gd->ram_base in sdram.c.
After the function spl_relocate_stack_gd is called in crt0.S the pointer gd might be relocated and BSS with the FDT blob is erased. The pointer gd->fdt_blob is no longer valid when enabled SPL_OF_REAL and SPL_MMC, SPL_USB_HOST or SPL_USB_GADGET. This patch makes that FDT properties can be parsed in the board_init_r() function.
Fix by setting this pointers simulair to board_f.c and copy the FDT to it's new location at the end of DRAM.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- arch/arm/mach-rockchip/sdram.c | 1 + arch/arm/mach-rockchip/spl.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+)
diff --git a/arch/arm/mach-rockchip/sdram.c b/arch/arm/mach-rockchip/sdram.c index 705ec7ba..b5972269 100644 --- a/arch/arm/mach-rockchip/sdram.c +++ b/arch/arm/mach-rockchip/sdram.c @@ -198,6 +198,7 @@ int dram_init(void) debug("Cannot get DRAM size: %d\n", ret); return ret; } + gd->ram_base = ram.base; gd->ram_size = ram.size; debug("SDRAM base=%lx, size=%lx\n", (unsigned long)ram.base, (unsigned long)ram.size); diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c index 30be6404..ceef9d91 100644 --- a/arch/arm/mach-rockchip/spl.c +++ b/arch/arm/mach-rockchip/spl.c @@ -10,6 +10,7 @@ #include <image.h> #include <init.h> #include <log.h> +#include <mapmem.h> #include <ram.h> #include <spl.h> #include <asm/arch-rockchip/bootrom.h> @@ -149,6 +150,21 @@ void board_init_f(ulong dummy) } gd->ram_top = gd->ram_base + get_effective_memsize(); gd->ram_top = board_get_usable_ram_top(gd->ram_size); + + /* Copy FDT blob from BSS to the end of DRAM */ + if (gd->fdt_blob) { + gd->fdt_size = ALIGN(fdt_totalsize(gd->fdt_blob), 32); + unsigned long fdt_addr = ALIGN_DOWN(gd->ram_top - gd->fdt_size, 16); + + gd->new_fdt = map_sysmem(fdt_addr, gd->fdt_size); + + debug("Reserved %lu bytes for FDT at: %08lx\n", gd->fdt_size, fdt_addr); + + if (gd->new_fdt) { + memcpy(gd->new_fdt, gd->fdt_blob, fdt_totalsize(gd->fdt_blob)); + gd->fdt_blob = gd->new_fdt; + } + } #endif preloader_console_init(); }

Rockchip SoCs have more boot device options then currently included in the function spl_boot_device(). Make this function generic for SPI and NAND.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- arch/arm/mach-rockchip/spl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c index ceef9d91..968f896a 100644 --- a/arch/arm/mach-rockchip/spl.c +++ b/arch/arm/mach-rockchip/spl.c @@ -53,13 +53,16 @@ u32 spl_boot_device(void) { u32 boot_device = BOOT_DEVICE_MMC1;
-#if defined(CONFIG_TARGET_CHROMEBOOK_JERRY) || \ +#if defined(CONFIG_SPI_BOOT) || \ + defined(CONFIG_TARGET_CHROMEBOOK_JERRY) || \ defined(CONFIG_TARGET_CHROMEBIT_MICKEY) || \ defined(CONFIG_TARGET_CHROMEBOOK_MINNIE) || \ defined(CONFIG_TARGET_CHROMEBOOK_SPEEDY) || \ defined(CONFIG_TARGET_CHROMEBOOK_BOB) || \ defined(CONFIG_TARGET_CHROMEBOOK_KEVIN) return BOOT_DEVICE_SPI; +#elseif defined(CONFIG_NAND_BOOT) + return BOOT_DEVICE_NAND; #endif if (CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)) return BOOT_DEVICE_BOOTROM;

Add usb boot option to spl-boot-order.c
Signed-off-by: Johan Jonker jbx6244@gmail.com --- arch/arm/mach-rockchip/spl-boot-order.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c index 93b8e7de..c4ba369b 100644 --- a/arch/arm/mach-rockchip/spl-boot-order.c +++ b/arch/arm/mach-rockchip/spl-boot-order.c @@ -77,6 +77,9 @@ static int spl_node_to_boot_device(int node) if (!uclass_get_device_by_of_offset(UCLASS_SPI_FLASH, node, &parent)) return BOOT_DEVICE_SPI;
+ if (!uclass_get_device_by_of_offset(UCLASS_USB, node, &parent)) + return BOOT_DEVICE_USB; + return -1; }

The usb init functions in board.c are needed in SPL during boot, so allow SPL compile for board.c
Signed-off-by: Johan Jonker jbx6244@gmail.com --- arch/arm/mach-rockchip/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 6c1c7b8a..ebe0afa2 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -22,10 +22,11 @@ ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),) # we can have the preprocessor correctly recognise both 0x0 and 0 # meaning "turn it off". obj-y += boot_mode.o -obj-$(CONFIG_ROCKCHIP_COMMON_BOARD) += board.o obj-$(CONFIG_MISC_INIT_R) += misc.o endif
+obj-$(CONFIG_ROCKCHIP_COMMON_BOARD) += board.o + ifeq ($(CONFIG_TPL_BUILD),) obj-$(CONFIG_DISPLAY_CPUINFO) += cpu-info.o endif

Enable spl compile for rockusb.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/usb/gadget/Kconfig | 10 ++++++++++ drivers/usb/gadget/Makefile | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 8c6cf474..b10f1956 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -164,6 +164,16 @@ config USB_FUNCTION_MASS_STORAGE
config USB_FUNCTION_ROCKUSB bool "Enable USB rockusb gadget" + depends on BLK + help + Rockusb protocol is widely used by Rockchip SoC based devices. It can + read/write info, image to/from devices. This enables the USB part of + the rockusb gadget.for more detail about Rockusb protocol, please see + doc/README.rockusb + +config SPL_USB_FUNCTION_ROCKUSB + bool "Enable USB rockusb gadget in SPL" + depends on SPL_BLK help Rockusb protocol is widely used by Rockchip SoC based devices. It can read/write info, image to/from devices. This enables the USB part of diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index d5d891b2..095d1faa 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_USB_GADGET_DWC2_OTG) += dwc2_udc_otg.o obj-$(CONFIG_USB_GADGET_DWC2_OTG_PHY) += dwc2_udc_otg_phy.o obj-$(CONFIG_USB_GADGET_FOTG210) += fotg210.o obj-$(CONFIG_USB_GADGET_MAX3420) += max3420_udc.o +obj-$(CONFIG_$(SPL_)USB_FUNCTION_ROCKUSB) += f_rockusb.o obj-$(CONFIG_CI_UDC) += ci_udc.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_GADGET_DOWNLOAD) += g_dnl.o @@ -29,7 +30,6 @@ obj-$(CONFIG_DFU_OVER_USB) += f_dfu.o obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o -obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o obj-$(CONFIG_USB_FUNCTION_ACM) += f_acm.o endif endif

Add usb spl configs for mk808.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- include/configs/mk808.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/configs/mk808.h b/include/configs/mk808.h index e2ab2b51..5a0c7fbc 100644 --- a/include/configs/mk808.h +++ b/include/configs/mk808.h @@ -6,4 +6,7 @@ #define ROCKCHIP_DEVICE_SETTINGS #include <configs/rk3066_common.h>
+#define CONFIG_SYS_USB_FAT_BOOT_PARTITION 1 +#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" + #endif

Add adc and usb required properties for spl to rk3066a-mk808-u-boot.dtsi
Signed-off-by: Johan Jonker jbx6244@gmail.com --- arch/arm/dts/rk3066a-mk808-u-boot.dtsi | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/arch/arm/dts/rk3066a-mk808-u-boot.dtsi b/arch/arm/dts/rk3066a-mk808-u-boot.dtsi index e0aa929f..60b39026 100644 --- a/arch/arm/dts/rk3066a-mk808-u-boot.dtsi +++ b/arch/arm/dts/rk3066a-mk808-u-boot.dtsi @@ -6,6 +6,10 @@ config { u-boot,boot-led = "mk808:blue:power"; }; + + chosen { + u-boot,spl-boot-order = &mmc0, &usb_host; + }; };
&cru { @@ -39,6 +43,11 @@ compatible = "rockchip,rk3066-noc", "syscon"; };
+&saradc { + vdd-microvolts = <2500000>; + u-boot,dm-spl; +}; + &timer2 { clock-frequency = <24000000>; u-boot,dm-pre-reloc; @@ -47,3 +56,23 @@ &uart2 { u-boot,dm-pre-reloc; }; + +&usb_host { + u-boot,dm-spl; +}; + +&usb_otg { + u-boot,dm-spl; +}; + +&usbphy { + u-boot,dm-spl; +}; + +&usbphy0 { + u-boot,dm-spl; +}; + +&usbphy1 { + u-boot,dm-spl; +};

Enable spl compile of the class driver for other compile modes then OF_REAL, so that at least it doesn't break the process. Use #if because code review shows that IS_ENABLED() and device_get_supply_regulator() results in probe failure.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/adc/adc-uclass.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c index 67137ffb..e8ce638d 100644 --- a/drivers/adc/adc-uclass.c +++ b/drivers/adc/adc-uclass.c @@ -199,7 +199,11 @@ int adc_channel_single_shot(const char *name, int channel, unsigned int *data) struct udevice *dev; int ret;
+#if IS_ENABLED(CONFIG_SPL_BUILD) + ret = uclass_get_device(UCLASS_ADC, 0, &dev); +#else ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev); +#endif if (ret) return ret;
@@ -248,7 +252,11 @@ int adc_channels_single_shot(const char *name, unsigned int channel_mask, struct udevice *dev; int ret;
+#if IS_ENABLED(CONFIG_SPL_BUILD) + ret = uclass_get_device(UCLASS_ADC, 0, &dev); +#else ret = uclass_get_device_by_name(UCLASS_ADC, name, &dev); +#endif if (ret) return ret;
@@ -372,20 +380,26 @@ int adc_raw_to_uV(struct udevice *dev, unsigned int raw, int *uV) static int adc_vdd_plat_set(struct udevice *dev) { struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); - int ret; char *prop;
+ uc_pdata->vdd_microvolts = -ENODATA; + + if (CONFIG_IS_ENABLED(OF_PLATDATA)) + return 0; + prop = "vdd-polarity-negative"; uc_pdata->vdd_polarity_negative = dev_read_bool(dev, prop);
/* Optionally get regulators */ - ret = device_get_supply_regulator(dev, "vdd-supply", - &uc_pdata->vdd_supply); +#if !IS_ENABLED(CONFIG_SPL_BUILD) + int ret = device_get_supply_regulator(dev, "vdd-supply", + &uc_pdata->vdd_supply); if (!ret) return adc_vdd_plat_update(dev);
if (ret != -ENOENT) return ret; +#endif
/* No vdd-supply phandle. */ prop = "vdd-microvolts"; @@ -397,19 +411,26 @@ static int adc_vdd_plat_set(struct udevice *dev) static int adc_vss_plat_set(struct udevice *dev) { struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); - int ret; char *prop;
+ uc_pdata->vss_microvolts = -ENODATA; + + if (CONFIG_IS_ENABLED(OF_PLATDATA)) + return 0; + prop = "vss-polarity-negative"; uc_pdata->vss_polarity_negative = dev_read_bool(dev, prop);
- ret = device_get_supply_regulator(dev, "vss-supply", - &uc_pdata->vss_supply); + /* Optionally get regulators */ +#if !IS_ENABLED(CONFIG_SPL_BUILD) + int ret = device_get_supply_regulator(dev, "vss-supply", + &uc_pdata->vss_supply); if (!ret) return adc_vss_plat_update(dev);
if (ret != -ENOENT) return ret; +#endif
/* No vss-supply phandle. */ prop = "vss-microvolts";

The adc class driver reads optional "vss-supply" and "vdd-supply" properties. The SoC adc driver can parse for vref, so reduce error notifications when not found.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/adc/adc-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c index e8ce638d..3dbdfa6f 100644 --- a/drivers/adc/adc-uclass.c +++ b/drivers/adc/adc-uclass.c @@ -446,12 +446,12 @@ static int adc_pre_probe(struct udevice *dev) /* Set ADC VDD plat: polarity, uV, regulator (phandle). */ ret = adc_vdd_plat_set(dev); if (ret) - pr_err("%s: Can't update Vdd. Error: %d", dev->name, ret); + pr_debug("%s: Can't update Vdd: %d", dev->name, ret);
/* Set ADC VSS plat: polarity, uV, regulator (phandle). */ ret = adc_vss_plat_set(dev); if (ret) - pr_err("%s: Can't update Vss. Error: %d", dev->name, ret); + pr_debug("%s: Can't update Vss: %d", dev->name, ret);
return 0; }

Enable spl compile rockchip-saradc driver. When OF_PLATDATA is selected the "vdd-microvolts" property is used instead of vref from regulator to reduze size from the regulator and the gpio class.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/adc/rockchip-saradc.c | 64 +++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 15 deletions(-)
diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c index 760f8fe6..f61cfe4b 100644 --- a/drivers/adc/rockchip-saradc.c +++ b/drivers/adc/rockchip-saradc.c @@ -9,6 +9,7 @@ #include <adc.h> #include <clk.h> #include <dm.h> +#include <dt-structs.h> #include <errno.h> #include <asm/io.h> #include <linux/bitops.h> @@ -41,6 +42,12 @@ struct rockchip_saradc_priv { const struct rockchip_saradc_data *data; };
+struct rockchip_adc_plat { +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct dtd_rockchip_adc dtplat; +#endif +}; + int rockchip_saradc_channel_data(struct udevice *dev, int channel, unsigned int *data) { @@ -101,30 +108,48 @@ int rockchip_saradc_stop(struct udevice *dev)
int rockchip_saradc_probe(struct udevice *dev) { +#if CONFIG_IS_ENABLED(OF_PLATDATA) || !IS_ENABLED(CONFIG_SPL_BUILD) struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); +#endif struct rockchip_saradc_priv *priv = dev_get_priv(dev); - struct udevice *vref; struct clk clk; - int vref_uv; int ret;
- ret = clk_get_by_index(dev, 0, &clk); - if (ret) +#if CONFIG_IS_ENABLED(OF_PLATDATA) + struct rockchip_adc_plat *plat = dev_get_plat(dev); + struct dtd_rockchip_adc *dtplat = &plat->dtplat; + + priv->regs = (struct rockchip_saradc_regs *)dtplat->reg[0]; + + ret = clk_get_by_phandle(dev, &dtplat->clocks[0], &clk); + if (ret < 0) return ret;
+ uc_pdata->vdd_microvolts = dtplat->vdd_microvolts; + uc_pdata->vss_microvolts = 0; +#endif + if (CONFIG_IS_ENABLED(OF_REAL)) { + ret = clk_get_by_index(dev, 0, &clk); + if (ret) + return ret; + } + ret = clk_set_rate(&clk, priv->data->clk_rate); if (IS_ERR_VALUE(ret)) return ret;
priv->active_channel = -1;
+#if !IS_ENABLED(CONFIG_SPL_BUILD) + struct udevice *vref; + ret = device_get_supply_regulator(dev, "vref-supply", &vref); if (ret) { printf("can't get vref-supply: %d\n", ret); return ret; }
- vref_uv = regulator_get_value(vref); + int vref_uv = regulator_get_value(vref); if (vref_uv < 0) { printf("can't get vref-supply value: %d\n", vref_uv); return vref_uv; @@ -134,6 +159,7 @@ int rockchip_saradc_probe(struct udevice *dev) uc_pdata->vdd_supply = vref; uc_pdata->vdd_microvolts = vref_uv; uc_pdata->vss_microvolts = 0; +#endif
return 0; } @@ -142,16 +168,19 @@ int rockchip_saradc_of_to_plat(struct udevice *dev) { struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct rockchip_saradc_priv *priv = dev_get_priv(dev); - struct rockchip_saradc_data *data;
- data = (struct rockchip_saradc_data *)dev_get_driver_data(dev); - priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev); - if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) { - pr_err("Dev: %s - can't get address!", dev->name); - return -ENODATA; + if (CONFIG_IS_ENABLED(OF_REAL)) { + priv->regs = (struct rockchip_saradc_regs *)dev_read_addr(dev); + if (priv->regs == (struct rockchip_saradc_regs *)FDT_ADDR_T_NONE) { + pr_err("Dev: %s - can't get address!", dev->name); + return -ENODATA; + } + } else { + dev->driver_data = dev->driver->of_match->data; }
- priv->data = data; + priv->data = (struct rockchip_saradc_data *)dev_get_driver_data(dev); + uc_pdata->data_mask = (1 << priv->data->num_bits) - 1; uc_pdata->data_format = ADC_DATA_FORMAT_BIN; uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5; @@ -194,12 +223,17 @@ static const struct udevice_id rockchip_saradc_ids[] = { { } };
-U_BOOT_DRIVER(rockchip_saradc) = { - .name = "rockchip_saradc", +U_BOOT_DRIVER(rockchip_adc) = { + .name = "rockchip_adc", .id = UCLASS_ADC, .of_match = rockchip_saradc_ids, .ops = &rockchip_saradc_ops, .probe = rockchip_saradc_probe, - .of_to_plat = rockchip_saradc_of_to_plat, + .of_to_plat = rockchip_saradc_of_to_plat, .priv_auto = sizeof(struct rockchip_saradc_priv), + .plat_auto = sizeof(struct rockchip_adc_plat), + }; +DM_DRIVER_ALIAS(rockchip_adc, rockchip_saradc) +DM_DRIVER_ALIAS(rockchip_adc, rockchip_rk3066_tsadc) +DM_DRIVER_ALIAS(rockchip_adc, rockchip_rk3399_saradc)

Replace adc timer counter by SoC timer to prevent EBUSY notifications.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/adc/adc-uclass.c | 10 ++++++---- drivers/adc/rockchip-saradc.c | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/drivers/adc/adc-uclass.c b/drivers/adc/adc-uclass.c index 3dbdfa6f..a539f999 100644 --- a/drivers/adc/adc-uclass.c +++ b/drivers/adc/adc-uclass.c @@ -146,6 +146,7 @@ int adc_channel_data(struct udevice *dev, int channel, unsigned int *data) struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); const struct adc_ops *ops = dev_get_driver_ops(dev); unsigned int timeout_us = uc_pdata->data_timeout_us; + unsigned long start_time; int ret;
if (!ops->channel_data) @@ -155,14 +156,14 @@ int adc_channel_data(struct udevice *dev, int channel, unsigned int *data) if (ret) return ret;
+ start_time = get_timer(0); do { ret = ops->channel_data(dev, channel, data); if (!ret || ret != -EBUSY) break;
- /* TODO: use timer uclass (for early calls). */ sdelay(5); - } while (timeout_us--); + } while (get_timer(start_time) < timeout_us);
return ret; } @@ -173,6 +174,7 @@ int adc_channels_data(struct udevice *dev, unsigned int channel_mask, struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); unsigned int timeout_us = uc_pdata->multidata_timeout_us; const struct adc_ops *ops = dev_get_driver_ops(dev); + unsigned long start_time; int ret;
if (!ops->channels_data) @@ -182,14 +184,14 @@ int adc_channels_data(struct udevice *dev, unsigned int channel_mask, if (ret) return ret;
+ start_time = get_timer(0); do { ret = ops->channels_data(dev, channel_mask, channels); if (!ret || ret != -EBUSY) break;
- /* TODO: use timer uclass (for early calls). */ sdelay(5); - } while (timeout_us--); + } while (get_timer(start_time) < timeout_us);
return ret; } diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c index f61cfe4b..e6a0341d 100644 --- a/drivers/adc/rockchip-saradc.c +++ b/drivers/adc/rockchip-saradc.c @@ -183,7 +183,7 @@ int rockchip_saradc_of_to_plat(struct udevice *dev)
uc_pdata->data_mask = (1 << priv->data->num_bits) - 1; uc_pdata->data_format = ADC_DATA_FORMAT_BIN; - uc_pdata->data_timeout_us = SARADC_TIMEOUT / 5; + uc_pdata->data_timeout_us = SARADC_TIMEOUT; uc_pdata->channel_mask = (1 << priv->data->num_channels) - 1;
return 0;

The Rockchip saradc behaves strange when doing an "adc scan" with hang ups. Fix by adding an adc power down before the settings are made. Similair to what TRM recommands follow this flow below:
Power-down A/D Converter in SARADC_CTRL[3] Power-up A/D Converter in SARADC_CTRL[3] and select input channel of A/D Converter in SARADC_CTRL[2:0] bit Wait an A/D interrupt or poll the SARADC_STAS register to determine when the conversion is completed Read the conversion result in the SARADC_DATA register
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/adc/rockchip-saradc.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/adc/rockchip-saradc.c b/drivers/adc/rockchip-saradc.c index e6a0341d..fb0f2e03 100644 --- a/drivers/adc/rockchip-saradc.c +++ b/drivers/adc/rockchip-saradc.c @@ -13,6 +13,7 @@ #include <errno.h> #include <asm/io.h> #include <linux/bitops.h> +#include <linux/delay.h> #include <linux/err.h> #include <power/regulator.h>
@@ -82,6 +83,10 @@ int rockchip_saradc_start_channel(struct udevice *dev, int channel) return -EINVAL; }
+ writel(0, &priv->regs->ctrl); + + udelay(1); + /* 8 clock periods as delay between power up and start cmd */ writel(8, &priv->regs->dly_pu_soc);

Make the ADC branch compile in SPL.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/Makefile | 3 ++- drivers/adc/Kconfig | 29 +++++++++++++++++++++++++++++ drivers/adc/Makefile | 4 ++-- 3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/drivers/Makefile b/drivers/Makefile index 4e7cf284..e79bbe29 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_$(SPL_)FPGA) += fpga/ ifndef CONFIG_TPL_BUILD ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_ADC) += adc/ obj-$(CONFIG_SPL_CPU) += cpu/ obj-$(CONFIG_SPL_CRYPTO) += crypto/ obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR) += ddr/fsl/ @@ -71,7 +72,7 @@ endif
ifeq ($(CONFIG_SPL_BUILD)$(CONFIG_TPL_BUILD),)
-obj-y += adc/ +obj-$(CONFIG_ADC) += adc/ obj-y += ata/ obj-y += bus/ obj-$(CONFIG_DM_DEMO) += demo/ diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index e719c38b..68e0d2d3 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -1,5 +1,6 @@ config ADC bool "Enable ADC drivers using Driver Model" + depends on DM help This enables ADC API for drivers, which allows driving ADC features by single and multi-channel methods for: @@ -11,8 +12,23 @@ config ADC - support supply's phandle with auto-enable - supply polarity setting in fdt
+config SPL_ADC + bool "Enable ADC drivers using Driver Model in SPL" + depends on SPL_DM + help + This enables ADC API for drivers, which allows driving ADC features + by single and multi-channel methods in SPL for: + - start/stop/get data for conversion of a single-channel selected by + a number or multi-channels selected by a bitmask + - get data mask (ADC resolution) + ADC reference Voltage supply options: + - methods for get Vdd/Vss reference Voltage values with polarity + - support supply's phandle with auto-enable + - supply polarity setting in fdt + config ADC_EXYNOS bool "Enable Exynos 54xx ADC driver" + depends on ADC help This enables basic driver for Exynos ADC compatible with Exynos54xx. It provides: @@ -22,6 +38,7 @@ config ADC_EXYNOS
config ADC_SANDBOX bool "Enable Sandbox ADC test driver" + depends on ADC help This enables driver for Sandbox ADC device emulation. It provides: @@ -31,6 +48,7 @@ config ADC_SANDBOX
config SARADC_MESON bool "Enable Amlogic Meson SARADC driver" + depends on ADC imply REGMAP help This enables driver for Amlogic Meson SARADC. @@ -41,6 +59,7 @@ config SARADC_MESON
config SARADC_ROCKCHIP bool "Enable Rockchip SARADC driver" + depends on ADC help This enables driver for Rockchip SARADC. It provides: @@ -48,6 +67,16 @@ config SARADC_ROCKCHIP - 1O or 12 bits resolution - Up to 1MSPS of sample rate
+config SPL_SARADC_ROCKCHIP + bool "Enable Rockchip SARADC driver in SPL" + depends on SPL_ADC + help + This enables driver for Rockchip SARADC in SPL. + It provides: + - 2~6 analog input channels + - 1O or 12 bits resolution + - Up to 1MSPS of sample rate + config STM32_ADC bool "Enable STMicroelectronics STM32 ADC driver" depends on ADC && (STM32H7 || ARCH_STM32MP) diff --git a/drivers/adc/Makefile b/drivers/adc/Makefile index c1387f3a..43788c48 100644 --- a/drivers/adc/Makefile +++ b/drivers/adc/Makefile @@ -4,9 +4,9 @@ # Przemyslaw Marczak p.marczak@samsung.com #
-obj-$(CONFIG_ADC) += adc-uclass.o +obj-y += adc-uclass.o obj-$(CONFIG_ADC_EXYNOS) += exynos-adc.o obj-$(CONFIG_ADC_SANDBOX) += sandbox.o -obj-$(CONFIG_SARADC_ROCKCHIP) += rockchip-saradc.o +obj-$(CONFIG_$(SPL_)SARADC_ROCKCHIP) += rockchip-saradc.o obj-$(CONFIG_SARADC_MESON) += meson-saradc.o obj-$(CONFIG_STM32_ADC) += stm32-adc.o stm32-adc-core.o

There are multiple ADC config items in the main menu. Move them out of sight in a sub menu.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- drivers/adc/Kconfig | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index 68e0d2d3..ba07754a 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -1,3 +1,5 @@ +menu "ADC support" + config ADC bool "Enable ADC drivers using Driver Model" depends on DM @@ -92,3 +94,5 @@ config STM32_ADC - core driver to deal with common resources - child driver to deal with individual ADC resources (declare ADC device and associated channels, start/stop conversions) + +endmenu # menu "ADC suupport"

From: Paweł Jarosz paweljarosz3691@gmail.com
The rk3066 grf_soc_con0 allows interchangeable data pin configuration for emmc and nand.
Use rockchip_nand_board_early_init function to config nand data pins in spl as bootrom leaves it in default state.
Signed-off-by: Paweł Jarosz paweljarosz3691@gmail.com Signed-off-by: Johan Jonker jbx6244@gmail.com --- arch/arm/mach-rockchip/rk3066/rk3066.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-rockchip/rk3066/rk3066.c b/arch/arm/mach-rockchip/rk3066/rk3066.c index 78c7d894..1d1b8687 100644 --- a/arch/arm/mach-rockchip/rk3066/rk3066.c +++ b/arch/arm/mach-rockchip/rk3066/rk3066.c @@ -28,12 +28,15 @@ void board_debug_uart_init(void)
void spl_board_init(void) { + __maybe_unused struct rk3066_grf * const grf = (void *)GRF_BASE; + if (!IS_ENABLED(CONFIG_SPL_BUILD)) return;
- if (IS_ENABLED(CONFIG_SPL_DM_MMC)) { - struct rk3066_grf * const grf = (void *)GRF_BASE; + if (IS_ENABLED(CONFIG_NAND_BOOT)) + rk_clrreg(&grf->soc_con0, EMMC_FLASH_SEL_MASK);
+ if (IS_ENABLED(CONFIG_SPL_DM_MMC)) { rk_clrsetreg(&grf->gpio3b_iomux, GPIO3B0_MASK | GPIO3B1_MASK | GPIO3B2_MASK | GPIO3B3_MASK | GPIO3B4_MASK | GPIO3B5_MASK |

Add a recovery button test as condition to enter the recovery mode in spl. Run the rockusb gadget for MMC while connected to a USB host. Allow external user defined functions by labeling these functions as "__weak".
Signed-off-by: Johan Jonker jbx6244@gmail.com --- .../arm/include/asm/arch-rockchip/f_rockusb.h | 1 + arch/arm/mach-rockchip/rk3066/rk3066.c | 86 +++++++++++++++++++ 2 files changed, 87 insertions(+)
diff --git a/arch/arm/include/asm/arch-rockchip/f_rockusb.h b/arch/arm/include/asm/arch-rockchip/f_rockusb.h index e9c7f793..ab1e2c2f 100644 --- a/arch/arm/include/asm/arch-rockchip/f_rockusb.h +++ b/arch/arm/include/asm/arch-rockchip/f_rockusb.h @@ -8,6 +8,7 @@ #ifndef _F_ROCKUSB_H_ #define _F_ROCKUSB_H_ #include <blk.h> +#include <linux/usb/composite.h>
#define ROCKUSB_VERSION "0.1"
diff --git a/arch/arm/mach-rockchip/rk3066/rk3066.c b/arch/arm/mach-rockchip/rk3066/rk3066.c index 1d1b8687..be19400c 100644 --- a/arch/arm/mach-rockchip/rk3066/rk3066.c +++ b/arch/arm/mach-rockchip/rk3066/rk3066.c @@ -4,9 +4,15 @@ */
#include <common.h> +#include <adc.h> +#include <g_dnl.h> +#include <spl.h> #include <asm/io.h> #include <asm/arch-rockchip/bootrom.h> #include <asm/arch-rockchip/grf_rk3066.h> +#include <asm/arch-rockchip/f_rockusb.h> +#include <dm/device.h> +#include <dm/uclass.h>
#define GRF_BASE 0x20008000
@@ -26,6 +32,81 @@ void board_debug_uart_init(void) GPIO1B0_UART2_SIN << GPIO1B0_SHIFT); }
+__weak void do_spl(void) +{ + if (CONFIG_IS_ENABLED(OF_PLATDATA)) + return; + +#if IS_ENABLED(CONFIG_SPL_USB_FUNCTION_ROCKUSB) + char *dev_type; + int dev_index; + int ret; + + switch (spl_boot_device()) { + case BOOT_DEVICE_MMC1: + dev_type = "mmc"; + dev_index = 0; + break; + default: + return; + } + + rockusb_dev_init(dev_type, dev_index); + + ret = usb_gadget_initialize(0); + if (ret) { + printf("USB init failed: %d\n", ret); + return; + } + + g_dnl_clear_detach(); + ret = g_dnl_register("usb_dnl_rockusb"); + if (ret) + return; + + if (!g_dnl_board_usb_cable_connected()) { + printf("\rUSB cable not detected\n"); + goto exit; + } + + while (1) { + if (g_dnl_detach()) + break; + if (ctrlc()) + break; + usb_gadget_handle_interrupts(0); + } + +exit: + g_dnl_unregister(); + g_dnl_clear_detach(); + usb_gadget_release(0); +#endif + return; +} + +#define KEY_DOWN_MIN_VAL 0 +#define KEY_DOWN_MAX_VAL 30 + +__weak int rockchip_dnl_key_pressed(void) +{ +#if IS_ENABLED(CONFIG_SPL_SARADC_ROCKCHIP) + unsigned int val; + int ret; + + ret = adc_channel_single_shot("saradc@2006c000", 1, &val); + + if (ret) { + printf("Read adc key val failed\n"); + return false; + } + + if (val >= KEY_DOWN_MIN_VAL && val <= KEY_DOWN_MAX_VAL) + return true; +#endif + return false; +} + void spl_board_init(void) { __maybe_unused struct rk3066_grf * const grf = (void *)GRF_BASE; @@ -49,4 +130,9 @@ void spl_board_init(void) GPIO3B5_SDMMC0_DATA3 << GPIO3B5_SHIFT | GPIO3B6_SDMMC0_DECTN << GPIO3B6_SHIFT); } + + if (rockchip_dnl_key_pressed()) { + printf("Recovery button was pressed!\n"); + do_spl(); + } }

Enable usb support in the mk808_defconfig. Add adc button in full and spl mode to do an action on user demand.
Signed-off-by: Johan Jonker jbx6244@gmail.com --- configs/mk808_defconfig | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
diff --git a/configs/mk808_defconfig b/configs/mk808_defconfig index 20bca75a..6ae41a23 100644 --- a/configs/mk808_defconfig +++ b/configs/mk808_defconfig @@ -26,6 +26,7 @@ CONFIG_SPL_FS_FAT=y CONFIG_SYS_LOAD_ADDR=0x70800800 CONFIG_SPL_PAYLOAD="u-boot.bin" CONFIG_DEBUG_UART=y +# CONFIG_ANDROID_BOOT_IMAGE is not set CONFIG_SD_BOOT=y CONFIG_USE_PREBOOT=y CONFIG_DEFAULT_FDT_FILE="rk3066a-mk808.dtb" @@ -35,14 +36,23 @@ CONFIG_BOARD_LATE_INIT=y CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x200000 CONFIG_SPL_SEPARATE_BSS=y +CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FS_EXT4=y CONFIG_SYS_MMCSD_FS_BOOT_PARTITION=2 +CONFIG_SPL_MMC_WRITE=y +CONFIG_SPL_USB_HOST=y +CONFIG_SPL_USB_STORAGE=y +CONFIG_SPL_USB_GADGET=y CONFIG_TPL_NEEDS_SEPARATE_STACK=y # CONFIG_BOOTM_PLAN9 is not set # CONFIG_BOOTM_RTEMS is not set # CONFIG_BOOTM_VXWORKS is not set +CONFIG_CMD_ADC=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y +CONFIG_CMD_ROCKUSB=y +CONFIG_CMD_USB_MASS_STORAGE=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_CACHE=y CONFIG_CMD_TIME=y @@ -51,7 +61,6 @@ CONFIG_SPL_OF_CONTROL=y CONFIG_TPL_OF_CONTROL=y CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" CONFIG_OF_DTB_PROPS_REMOVE=y -CONFIG_SPL_OF_PLATDATA=y CONFIG_TPL_OF_PLATDATA=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y # CONFIG_NET is not set @@ -65,10 +74,13 @@ CONFIG_SPL_SYSCON=y CONFIG_TPL_SYSCON=y # CONFIG_SIMPLE_BUS is not set # CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_SPL_ADC=y +CONFIG_SPL_SARADC_ROCKCHIP=y # CONFIG_TPL_BLK is not set CONFIG_CLK=y CONFIG_SPL_CLK=y CONFIG_TPL_CLK=y +CONFIG_FASTBOOT_BUF_ADDR=0x80000000 CONFIG_ROCKCHIP_GPIO=y # CONFIG_SPL_DM_I2C is not set CONFIG_LED=y @@ -97,6 +109,13 @@ CONFIG_TIMER=y CONFIG_SPL_TIMER=y CONFIG_TPL_TIMER=y CONFIG_DESIGNWARE_APB_TIMER=y +CONFIG_USB=y +CONFIG_USB_DWC2=y +CONFIG_ROCKCHIP_USB2_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_FUNCTION_ROCKUSB=y +CONFIG_SPL_USB_FUNCTION_ROCKUSB=y CONFIG_SPL_TINY_MEMSET=y CONFIG_ERRNO_STR=y # CONFIG_TPL_OF_LIBFDT is not set
participants (1)
-
Johan Jonker