Re: [PATCH] rpi: always set fdt_addr to the correct value
Hi Matthias, On 15.02.2022 19:19, Matthias Brugger wrote: > > On 15/02/2022 15:55, Matthias Brugger wrote: >> >> On 18/02/2022 03:44, Jaehoon Chung wrote: >>> On 22. 2. 14. 20:25, Marek Szyprowski wrote: >>>> The fdt_addr env have meaning only for the current runtime and it >>>> depends >>>> on the dtb size or firmware version. If one save the environment to >>>> disk >>>> and the loads it on the latter boot, the fdt_addr might change, what >>>> result in passing incorrect dtb address to the kernel. Fix this by >>>> always >>>> setting the fdt_addr env. This fixes system operation after saving the >>>> env to disk and updating i.e. dtb files or firmware. >>>> >>>> Signed-off-by: Marek Szyprowski >>> >>> Reviewed-by: Jaehoon Chung >>> >> >> Could we keep the discussion where we left it the last time you >> submitted the patch? >> > > I forgot to add the link to the old discussion: > https://patchwork.ozlabs.org/project/uboot/patch/20210512123945.25649-1-m.salv...@koansoftware.com/ Well, I'm still not convinced that this is a good idea. I found this issue while debugging something else and I must admit that the current behavior is really counterintuitive. I was surprised that after setting some really unrelated things in u-boot's envs (like additional kernel arguments to increase debug level) and saving such config, I got completely broken system. Right, I've also updated DTB in meantime because I was bisecting some kernel related issue, but still this is something that a typical user might face during system update. If we want to keep current behavior, the 'saveenv' command should print a large banner that one has to first delete the 'fdt_addr' env if he wants to have a working system. I will check if it would be possible to use some flags for the 'fdt_addr' env to mark it as 'do-not-save-unless-changed-manually'. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
[PATCH] rpi: always set fdt_addr to the correct value
The fdt_addr env have meaning only for the current runtime and it depends on the dtb size or firmware version. If one save the environment to disk and the loads it on the latter boot, the fdt_addr might change, what result in passing incorrect dtb address to the kernel. Fix this by always setting the fdt_addr env. This fixes system operation after saving the env to disk and updating i.e. dtb files or firmware. Signed-off-by: Marek Szyprowski --- board/raspberrypi/rpi/rpi.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index bc3cc597adb..6d6d2e69234 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -347,9 +347,6 @@ static void set_fdtfile(void) */ static void set_fdt_addr(void) { - if (env_get("fdt_addr")) - return; - if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) return; -- 2.17.1
[PATCH] arm: rpi: perform XHCI firmware upload only once
XHCI firmware upload must be performed only once after initializing the PCI bridge. This fixes USB stack initialization after calling "usb stop; usb start" on Raspberry Pi 4B. Signed-off-by: Marek Szyprowski --- arch/arm/mach-bcm283x/msg.c | 6 ++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-bcm283x/msg.c b/arch/arm/mach-bcm283x/msg.c index 347aece3cd..345f7fe2b7 100644 --- a/arch/arm/mach-bcm283x/msg.c +++ b/arch/arm/mach-bcm283x/msg.c @@ -170,6 +170,12 @@ int bcm2711_notify_vl805_reset(void) ALLOC_CACHE_ALIGN_BUFFER(struct msg_notify_vl805_reset, msg_notify_vl805_reset, 1); int ret; + static int done = false; + + if (done) + return 0; + + done = true; BCM2835_MBOX_INIT_HDR(msg_notify_vl805_reset); BCM2835_MBOX_INIT_TAG(_notify_vl805_reset->dev_addr, -- 2.17.1
Re: u-boot on RPi4 32bit - issue after upgrading the firmware
Hi On 04.03.2021 02:33, Jaehoon Chung wrote: > On 2/25/21 8:11 PM, Marek Szyprowski wrote: >> On 25.02.2021 11:55, Nicolas Saenz Julienne wrote: >>> On Thu, 2021-02-25 at 11:43 +0100, Marek Szyprowski wrote: >>>> Recently I've upgraded a video core firmware on my RPi4 and I've noticed >>>> that u-boot in ARM 32bit mode stopped working properly or even randomly >>>> crashes. I've bisected the firmware releases and the issue appears for >>>> the first time in the commit 63b1922311 ("firmware: arm_loader: Update >>>> armstubs with those from PR 117 See: >>>> https://protect2.fireeye.com/v1/url?k=a201e8b0-fd9ad069-a20063ff-0cc47a3356b2-1ab72bd783ec5635=1=5f377675-c909-4cc4-a1d5-b740cbf6255e=https%3A%2F%2Fgithub.com%2Fraspberrypi%2Ftools%2Fpull%2F117;). >>> Just for confirmation, >>>> This issue can be easily observed as a failure of the xhci. See the >>>> attached log: >>>> >>>> Read start4x.elf bytes 2984808 hnd 0x06e2 sha256 d21bf9d3954fea04 >>>> Read fixup4x.dat bytes 8432 hnd 0x06dd sha256 10d3b073ab232613 >>>> 0x00a03111 0x 0x001f >>>> MEM GPU: 76 ARM: 948 TOTAL: 1024 >>>> Starting start4x.elf @ 0xfec00200 partition 0 >>>> PCI reset >>>> + >>>> >>>> MESS:00:00:04.800023:0: arasan: arasan_emmc_open >>>> MESS:00:00:04.975752:0: brfs: File read: /mfs/sd/config.txt >>>> MESS:00:00:04.979162:0: brfs: File read: 2153 bytes >>>> MESS:00:00:05.046081:0: brfs: File read: /mfs/sd/config.txt >>>> MESS:00:00:06.121174:0: gpioman: gpioman_get_pin_num: pin >>>> DISPLAY_DSI_PORT not defined >>>> MESS:00:00:06.128433:0: *** Restart logging >>>> MESS:00:00:06.129897:0: brfs: File read: 2153 bytes >>>> MESS:00:00:06.148533:0: hdmi: HDMI:hdmi_get_state is deprecated, use >>>> hdmi_get_display_state instead >>>> MESS:00:00:06.154474:0: HDMI0: hdmi_pixel_encoding: 3 >>>> MESS:00:00:06.159948:0: HDMI1: hdmi_pixel_encoding: 3 >>>> MESS:00:00:06.166901:0: dtb_file 'bcm2711-rpi-4-b.dtb' >>>> MESS:00:00:06.178359:0: brfs: File read: /mfs/sd/bcm2711-rpi-4-b.dtb >>>> MESS:00:00:06.181601:0: Loading 'bcm2711-rpi-4-b.dtb' to 0x100 size 0xc901 >>>> MESS:00:00:06.201386:0: brfs: File read: 51457 bytes >>>> MESS:00:00:06.267975:0: brfs: File read: /mfs/sd/config.txt >>>> MESS:00:00:06.270915:0: dtparam: audio=on >>>> MESS:00:00:06.283974:0: brfs: File read: 2153 bytes >>>> MESS:00:00:06.286148:0: Failed to load overlay 'vc4-fkms-v3d' >>>> MESS:00:00:06.291378:0: brfs: File read: /mfs/sd/overlays/vc4-fkms-v3d.dtbo >>>> MESS:00:00:06.304096:0: Failed to open command line file 'cmdline.txt' >>>> MESS:00:00:07.484256:0: brfs: File read: /mfs/sd/u-boot.bin >>>> MESS:00:00:07.486726:0: Loading 'u-boot.bin' to 0x8000 size 0x84cf4 >>>> MESS:00:00:07.492726:0: Device tree loaded to 0x2eff3100 (size 0xce24) >>>> MESS:00:00:07.500863:0: uart: Set PL011 baud rate to 103448.30 Hz >>>> MESS:00:00:07.508031:0: uart: Baud rate change done... >>>> MESS:00:00:07.510053:0: >>>> >>>> U-Boot 2021.04-rc2 (Feb 25 2021 - 11:21:44 +0100) >>> Can you try with today's master branch, I'm specially interested in seeing >>> if >>> 56f1bcc4b7fb helps. >> I've checked the mentioned commit, sadly nothing changes: >> >> U-Boot 2021.04-rc2-00041-g56f1bcc4b7 (Feb 25 2021 - 12:05:07 +0100) >> >> DRAM: 948 MiB >> RPI 4 Model B (0xa03111) >> MMC: mmcnr@7e30: 1, emmc2@7e34: 0 >> Loading Environment from FAT... OK >> In: serial >> Out: serial >> Err: serial >> Net: eth0: ethernet@7d58 >> Hit any key to stop autoboot: 0 >> U-Boot> pci enum >> PCIe BRCM: link up, 5.0 Gbps x1 (SSC) >> U-Boot> usb start >> starting USB... >> Bus xhci_pci: Host not halted after 16000 microseconds. >> probe failed, error -16 >> No working controllers found >> U-Boot> >> >> I've checked that on two RPi4 boards (one with 1GB RAM and one with 8GB). > It seems that couldn't get hc_length from capbase. > > us xhci_pci: XHCI-PCI init hccr ff80 and hcor ff80 hc_length 0 > xhci_register: dev='xhci_pci', ctrl=3a3679c0, hccr=ff80, hcor=ff80 > > When i have compared with working and not, hc_length is different. > hc_length should be to set 0x20 when it's working fine. > > I don't have the knowledge of USB..So it's taking too more time for debugging. > > Could you share what i do to check more? I've finally had some time to analyze it more. It looks that 0xff80 base address in ARM 32bit virtual address space chosen for XHCI PCI device conflicts with the updated ARM/VideoCore firmware. I have no idea why, but switching to 0xffc0 fixed the issue. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
[PATCH] ARM: bcm283x: change the virtual address of the XHCI PCI device base
Move the XHCI PCI device base up in the virtual address space. This fixes initialization failure observed with newer Raspberry Pi firmware, later than 63b1922311 ("firmware: arm_loader: Update armstubs with those from PR 117). It looks that chosing 0xff80 as the XHCI PCI device base conflicts with the updated ARM/VideoCore firmware. This also requires to reduce the size of the mapped PCI device region from 8MiB to 4MiB to fit into 32bit address space. This is still enough for the XHCI PCI device. Signed-off-by: Marek Szyprowski --- This fixes the issue observed on ARM 32bit after upgrading the RPi4 firmware files, described some time ago here: https://lists.denx.de/pipermail/u-boot/2021-February/442317.html --- arch/arm/mach-bcm283x/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-bcm283x/init.c b/arch/arm/mach-bcm283x/init.c index 49027ce0a2..9803499985 100644 --- a/arch/arm/mach-bcm283x/init.c +++ b/arch/arm/mach-bcm283x/init.c @@ -14,7 +14,7 @@ #include #define BCM2711_RPI4_PCIE_XHCI_MMIO_PHYS 0x6UL -#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE 0x80UL +#define BCM2711_RPI4_PCIE_XHCI_MMIO_SIZE 0x40UL #ifdef CONFIG_ARM64 #include @@ -148,7 +148,7 @@ int mach_cpu_init(void) #ifdef CONFIG_ARMV7_LPAE #ifdef CONFIG_TARGET_RPI_4_32B -#define BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT 0xff80UL +#define BCM2711_RPI4_PCIE_XHCI_MMIO_VIRT 0xffc0UL #include #include -- 2.17.1
Re: u-boot on RPi4 32bit - issue after upgrading the firmware
Hi Nicolas, On 25.02.2021 11:55, Nicolas Saenz Julienne wrote: > On Thu, 2021-02-25 at 11:43 +0100, Marek Szyprowski wrote: >> Recently I've upgraded a video core firmware on my RPi4 and I've noticed >> that u-boot in ARM 32bit mode stopped working properly or even randomly >> crashes. I've bisected the firmware releases and the issue appears for >> the first time in the commit 63b1922311 ("firmware: arm_loader: Update >> armstubs with those from PR 117 See: >> https://protect2.fireeye.com/v1/url?k=a201e8b0-fd9ad069-a20063ff-0cc47a3356b2-1ab72bd783ec5635=1=5f377675-c909-4cc4-a1d5-b740cbf6255e=https%3A%2F%2Fgithub.com%2Fraspberrypi%2Ftools%2Fpull%2F117;). > Just for confirmation, >> This issue can be easily observed as a failure of the xhci. See the >> attached log: >> >> Read start4x.elf bytes 2984808 hnd 0x06e2 sha256 d21bf9d3954fea04 >> Read fixup4x.dat bytes 8432 hnd 0x06dd sha256 10d3b073ab232613 >> 0x00a03111 0x 0x001f >> MEM GPU: 76 ARM: 948 TOTAL: 1024 >> Starting start4x.elf @ 0xfec00200 partition 0 >> PCI reset >> + >> >> MESS:00:00:04.800023:0: arasan: arasan_emmc_open >> MESS:00:00:04.975752:0: brfs: File read: /mfs/sd/config.txt >> MESS:00:00:04.979162:0: brfs: File read: 2153 bytes >> MESS:00:00:05.046081:0: brfs: File read: /mfs/sd/config.txt >> MESS:00:00:06.121174:0: gpioman: gpioman_get_pin_num: pin >> DISPLAY_DSI_PORT not defined >> MESS:00:00:06.128433:0: *** Restart logging >> MESS:00:00:06.129897:0: brfs: File read: 2153 bytes >> MESS:00:00:06.148533:0: hdmi: HDMI:hdmi_get_state is deprecated, use >> hdmi_get_display_state instead >> MESS:00:00:06.154474:0: HDMI0: hdmi_pixel_encoding: 3 >> MESS:00:00:06.159948:0: HDMI1: hdmi_pixel_encoding: 3 >> MESS:00:00:06.166901:0: dtb_file 'bcm2711-rpi-4-b.dtb' >> MESS:00:00:06.178359:0: brfs: File read: /mfs/sd/bcm2711-rpi-4-b.dtb >> MESS:00:00:06.181601:0: Loading 'bcm2711-rpi-4-b.dtb' to 0x100 size 0xc901 >> MESS:00:00:06.201386:0: brfs: File read: 51457 bytes >> MESS:00:00:06.267975:0: brfs: File read: /mfs/sd/config.txt >> MESS:00:00:06.270915:0: dtparam: audio=on >> MESS:00:00:06.283974:0: brfs: File read: 2153 bytes >> MESS:00:00:06.286148:0: Failed to load overlay 'vc4-fkms-v3d' >> MESS:00:00:06.291378:0: brfs: File read: /mfs/sd/overlays/vc4-fkms-v3d.dtbo >> MESS:00:00:06.304096:0: Failed to open command line file 'cmdline.txt' >> MESS:00:00:07.484256:0: brfs: File read: /mfs/sd/u-boot.bin >> MESS:00:00:07.486726:0: Loading 'u-boot.bin' to 0x8000 size 0x84cf4 >> MESS:00:00:07.492726:0: Device tree loaded to 0x2eff3100 (size 0xce24) >> MESS:00:00:07.500863:0: uart: Set PL011 baud rate to 103448.30 Hz >> MESS:00:00:07.508031:0: uart: Baud rate change done... >> MESS:00:00:07.510053:0: >> >> U-Boot 2021.04-rc2 (Feb 25 2021 - 11:21:44 +0100) > Can you try with today's master branch, I'm specially interested in seeing if > 56f1bcc4b7fb helps. I've checked the mentioned commit, sadly nothing changes: U-Boot 2021.04-rc2-00041-g56f1bcc4b7 (Feb 25 2021 - 12:05:07 +0100) DRAM: 948 MiB RPI 4 Model B (0xa03111) MMC: mmcnr@7e30: 1, emmc2@7e34: 0 Loading Environment from FAT... OK In: serial Out: serial Err: serial Net: eth0: ethernet@7d58 Hit any key to stop autoboot: 0 U-Boot> pci enum PCIe BRCM: link up, 5.0 Gbps x1 (SSC) U-Boot> usb start starting USB... Bus xhci_pci: Host not halted after 16000 microseconds. probe failed, error -16 No working controllers found U-Boot> I've checked that on two RPi4 boards (one with 1GB RAM and one with 8GB). Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
u-boot on RPi4 32bit - issue after upgrading the firmware
Hi! Recently I've upgraded a video core firmware on my RPi4 and I've noticed that u-boot in ARM 32bit mode stopped working properly or even randomly crashes. I've bisected the firmware releases and the issue appears for the first time in the commit 63b1922311 ("firmware: arm_loader: Update armstubs with those from PR 117 See: https://github.com/raspberrypi/tools/pull/117;). This issue can be easily observed as a failure of the xhci. See the attached log: Read start4x.elf bytes 2984808 hnd 0x06e2 sha256 d21bf9d3954fea04 Read fixup4x.dat bytes 8432 hnd 0x06dd sha256 10d3b073ab232613 0x00a03111 0x 0x001f MEM GPU: 76 ARM: 948 TOTAL: 1024 Starting start4x.elf @ 0xfec00200 partition 0 PCI reset + MESS:00:00:04.800023:0: arasan: arasan_emmc_open MESS:00:00:04.975752:0: brfs: File read: /mfs/sd/config.txt MESS:00:00:04.979162:0: brfs: File read: 2153 bytes MESS:00:00:05.046081:0: brfs: File read: /mfs/sd/config.txt MESS:00:00:06.121174:0: gpioman: gpioman_get_pin_num: pin DISPLAY_DSI_PORT not defined MESS:00:00:06.128433:0: *** Restart logging MESS:00:00:06.129897:0: brfs: File read: 2153 bytes MESS:00:00:06.148533:0: hdmi: HDMI:hdmi_get_state is deprecated, use hdmi_get_display_state instead MESS:00:00:06.154474:0: HDMI0: hdmi_pixel_encoding: 3 MESS:00:00:06.159948:0: HDMI1: hdmi_pixel_encoding: 3 MESS:00:00:06.166901:0: dtb_file 'bcm2711-rpi-4-b.dtb' MESS:00:00:06.178359:0: brfs: File read: /mfs/sd/bcm2711-rpi-4-b.dtb MESS:00:00:06.181601:0: Loading 'bcm2711-rpi-4-b.dtb' to 0x100 size 0xc901 MESS:00:00:06.201386:0: brfs: File read: 51457 bytes MESS:00:00:06.267975:0: brfs: File read: /mfs/sd/config.txt MESS:00:00:06.270915:0: dtparam: audio=on MESS:00:00:06.283974:0: brfs: File read: 2153 bytes MESS:00:00:06.286148:0: Failed to load overlay 'vc4-fkms-v3d' MESS:00:00:06.291378:0: brfs: File read: /mfs/sd/overlays/vc4-fkms-v3d.dtbo MESS:00:00:06.304096:0: Failed to open command line file 'cmdline.txt' MESS:00:00:07.484256:0: brfs: File read: /mfs/sd/u-boot.bin MESS:00:00:07.486726:0: Loading 'u-boot.bin' to 0x8000 size 0x84cf4 MESS:00:00:07.492726:0: Device tree loaded to 0x2eff3100 (size 0xce24) MESS:00:00:07.500863:0: uart: Set PL011 baud rate to 103448.30 Hz MESS:00:00:07.508031:0: uart: Baud rate change done... MESS:00:00:07.510053:0: U-Boot 2021.04-rc2 (Feb 25 2021 - 11:21:44 +0100) DRAM: 948 MiB RPI 4 Model B (0xa03111) MMC: mmcnr@7e30: 1, emmc2@7e34: 0 Loading Environment from FAT... OK In: serial Out: serial Err: serial Net: eth0: ethernet@7d58 Hit any key to stop autoboot: 0 U-Boot> pci enum PCIe BRCM: link up, 5.0 Gbps x1 (SSC) U-Boot> usb start starting USB... Bus xhci_pci: Host not halted after 16000 microseconds. probe failed, error -16 No working controllers found U-Boot> Is it a known issue? In ARM64 mode everything works fine, but this not very surprising, because the firmware change in the mentioned commit is related to the ARM 32bit mode. Does anyone have an idea how to fix this issue? I've checked also the latest version of the RPi firmware, but the issue is still there. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
Re: [PATCH] button: adc: fix treshold typo
On 23.02.2021 16:10, Neil Armstrong wrote: > Fix the treshold typo in code by threshold. > > Fixes: c0165c85c3 ("button: add a simple Analog to Digital Converter device > based button driver") > Suggested-by: Tom Rini > Signed-off-by: Neil Armstrong Acked-by: Marek Szyprowski > --- > drivers/button/button-adc.c | 14 +++--- > 1 file changed, 7 insertions(+), 7 deletions(-) > > diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c > index eed86564fb..fd896c76f9 100644 > --- a/drivers/button/button-adc.c > +++ b/drivers/button/button-adc.c > @@ -55,7 +55,7 @@ static int button_adc_of_to_plat(struct udevice *dev) > struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); > struct button_adc_priv *priv = dev_get_priv(dev); > struct ofnode_phandle_args args; > - u32 treshold, up_treshold, t; > + u32 threshold, up_threshold, t; > ofnode node; > int ret; > > @@ -73,12 +73,12 @@ static int button_adc_of_to_plat(struct udevice *dev) > return ret; > > ret = ofnode_read_u32(dev_ofnode(dev->parent), > - "keyup-threshold-microvolt", _treshold); > + "keyup-threshold-microvolt", _threshold); > if (ret) > return ret; > > ret = ofnode_read_u32(dev_ofnode(dev), "press-threshold-microvolt", > - ); > + ); > if (ret) > return ret; > > @@ -87,13 +87,13 @@ static int button_adc_of_to_plat(struct udevice *dev) > if (ret) > return ret; > > - if (t > treshold) > - up_treshold = t; > + if (t > threshold) > + up_threshold = t; > } > > priv->channel = args.args[0]; > - priv->min = treshold; > - priv->max = up_treshold; > + priv->min = threshold; > + priv->max = up_threshold; > > return ret; > } Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
[PATCH v7 1/5] dt-bindings: input: adc-keys bindings documentation
Dump adc-keys bindings documentation from Linux kernel source tree from commit 698dc0cf9447 ("dt-bindings: input: adc-keys: clarify description"). Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- doc/device-tree-bindings/input/adc-keys.txt | 67 + 1 file changed, 67 insertions(+) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt diff --git a/doc/device-tree-bindings/input/adc-keys.txt b/doc/device-tree-bindings/input/adc-keys.txt new file mode 100644 index 00..6c8be6a9ac --- /dev/null +++ b/doc/device-tree-bindings/input/adc-keys.txt @@ -0,0 +1,67 @@ +ADC attached resistor ladder buttons + + +Required properties: + - compatible: "adc-keys" + - io-channels: Phandle to an ADC channel + - io-channel-names = "buttons"; + - keyup-threshold-microvolt: Voltage above or equal to which all the keys are + considered up. + +Optional properties: + - poll-interval: Poll interval time in milliseconds + - autorepeat: Boolean, Enable auto repeat feature of Linux input + subsystem. + +Each button (key) is represented as a sub-node of "adc-keys": + +Required subnode-properties: + - label: Descriptive name of the key. + - linux,code: Keycode to emit. + - press-threshold-microvolt: voltage above or equal to which this key is +considered pressed. + +No two values of press-threshold-microvolt may be the same. +All values of press-threshold-microvolt must be less than +keyup-threshold-microvolt. + +Example: + +#include + + adc-keys { + compatible = "adc-keys"; + io-channels = < 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <200>; + + button-up { + label = "Volume Up"; + linux,code = ; + press-threshold-microvolt = <150>; + }; + + button-down { + label = "Volume Down"; + linux,code = ; + press-threshold-microvolt = <100>; + }; + + button-enter { + label = "Enter"; + linux,code = ; + press-threshold-microvolt = <50>; + }; + }; + ++++ +| 2.000.000 <= value | no key pressed | ++++ +| 1.500.000 <= value < 2.000.000 | KEY_VOLUMEUP pressed | ++++ +| 1.000.000 <= value < 1.500.000 | KEY_VOLUMEDOWN pressed | ++++ +| 500.000 <= value < 1.000.000 | KEY_ENTER pressed | ++++ +| value < 500.000 | no key pressed | ++++ -- 2.17.1
[PATCH v7 0/5] VIM3: add support for checking 'Function' button state
Hi All, This patchset adds all building blocks needed for checking the 'Function' button state in the boot script on Amlogic A311D based VIM3 board. This button is connected to the ADC line of the SoC, so it required to enable meson SARADC, the clocks needed for it and a simple button-adc drivers. Once applied, one can use following commands in the boot scripts: -->8--- echo Checking Func button state: \\c if button Function then echo Selected alternative boot ... fi --->8--- Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v7: - added linux,code properties to the test.dts v6: https://lists.denx.de/pipermail/u-boot/2021-February/441039.html - added a simple sandbox test for adc-keys - use of_to_plat and adc_raw_to_uV to simplify code in the adc button driver v5: https://lists.denx.de/pipermail/u-boot/2021-January/438751.html - rebased onto latest uboot-amlogic/u-boot-amlogic-next branch - synchronized adc-keys binding with the recent version from the Linux kernel - updated adc-keys driver to match behavior from dt-bindings - added a patch for meson-saradc driver to register vdd reference supply to the ADC framework v4: https://lists.denx.de/pipermail/u-boot/2020-December/435641.html - rebased onto uboot-amlogic/u-boot-amlogic-next and dropped merged patches - added adc-keys bindings docs (copied from Linux kernel) - minor code adjustments pointed by Simon - enabled driver also in khadas-vim3l_defconfig v3: https://lists.denx.de/pipermail/u-boot/2020-December/435072.html - removed 'button' env variable - extended kconfig and patch descriptions v2: https://lists.denx.de/pipermail/u-boot/2020-December/434991.html - removed Change-Id tags - split defconfig changes into ADC and button related v1: https://lists.denx.de/pipermail/u-boot/2020-December/434875.html - initial submission Patch summary: Marek Szyprowski (5): dt-bindings: input: adc-keys bindings documentation button: add a simple Analog to Digital Converter device based button driver adc: meson-saradc: add support for getting reference voltage value configs: khadas-vim3(l): enable Function button support test: add a simple test for the adc-keys button driver arch/sandbox/dts/test.dts | 27 +++- configs/khadas-vim3_defconfig | 2 + configs/khadas-vim3l_defconfig | 2 + configs/sandbox_defconfig | 1 + doc/device-tree-bindings/input/adc-keys.txt | 67 + drivers/adc/meson-saradc.c | 21 +++ drivers/button/Kconfig | 8 ++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 146 test/dm/button.c| 50 ++- 10 files changed, 322 insertions(+), 3 deletions(-) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt create mode 100644 drivers/button/button-adc.c -- 2.17.1
[PATCH v7 3/5] adc: meson-saradc: add support for getting reference voltage value
Add support for getting the 'vref-supply' regulator and register it as ADC's reference voltage regulator, so clients can translate sampled ADC values to the voltage. Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- drivers/adc/meson-saradc.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c index 21db55831d..1a45a3a265 100644 --- a/drivers/adc/meson-saradc.c +++ b/drivers/adc/meson-saradc.c @@ -18,6 +18,7 @@ #include #include #include +#include #define MESON_SAR_ADC_REG0 0x00 #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) @@ -656,7 +657,10 @@ static int meson_saradc_stop(struct udevice *dev) static int meson_saradc_probe(struct udevice *dev) { + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct meson_saradc_priv *priv = dev_get_priv(dev); + struct udevice *vref; + int vref_uv; int ret; ret = regmap_init_mem(dev_ofnode(dev), >regmap); @@ -675,6 +679,23 @@ static int meson_saradc_probe(struct udevice *dev) priv->active_channel = -1; + ret = device_get_supply_regulator(dev, "vref-supply", ); + if (ret) { + printf("can't get vref-supply: %d\n", ret); + return ret; + } + + vref_uv = regulator_get_value(vref); + if (vref_uv < 0) { + printf("can't get vref-supply value: %d\n", vref_uv); + return vref_uv; + } + + /* VDD supplied by common vref pin */ + uc_pdata->vdd_supply = vref; + uc_pdata->vdd_microvolts = vref_uv; + uc_pdata->vss_microvolts = 0; + return 0; } -- 2.17.1
[PATCH v7 2/5] button: add a simple Analog to Digital Converter device based button driver
Add a simple Analog to Digital Converter device based button driver. This driver binds to the 'adc-keys' device tree node. Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- drivers/button/Kconfig | 8 ++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 146 3 files changed, 155 insertions(+) create mode 100644 drivers/button/button-adc.c diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 6b3ec7e55d..6db3c5e93a 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -9,6 +9,14 @@ config BUTTON can provide access to board-specific buttons. Use of the device tree for configuration is encouraged. +config BUTTON_ADC + bool "Button adc" + depends on BUTTON + help + Enable support for buttons which are connected to Analog to Digital + Converter device. The ADC driver must use driver model. Buttons are + configured using the device tree. + config BUTTON_GPIO bool "Button gpio" depends on BUTTON diff --git a/drivers/button/Makefile b/drivers/button/Makefile index fcc10ebe8d..bbd18af149 100644 --- a/drivers/button/Makefile +++ b/drivers/button/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2020 Philippe Reynes obj-$(CONFIG_BUTTON) += button-uclass.o +obj-$(CONFIG_BUTTON_ADC) += button-adc.o obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c new file mode 100644 index 00..eed86564fb --- /dev/null +++ b/drivers/button/button-adc.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct button_adc_priv - private data for button-adc driver. + * + * @adc: Analog to Digital Converter device to which button is connected. + * @channel: channel of the ADC device to probe the button state. + * @min: minimal uV value to consider button as pressed. + * @max: maximal uV value to consider button as pressed. + */ +struct button_adc_priv { + struct udevice *adc; + int channel; + int min; + int max; +}; + +static enum button_state_t button_adc_get_state(struct udevice *dev) +{ + struct button_adc_priv *priv = dev_get_priv(dev); + unsigned int val; + int ret, uV; + + ret = adc_start_channel(priv->adc, priv->channel); + if (ret) + return ret; + + ret = adc_channel_data(priv->adc, priv->channel, ); + if (ret) + return ret; + + ret = adc_raw_to_uV(priv->adc, val, ); + if (ret) + return ret; + + return (uV >= priv->min && uV < priv->max) ? BUTTON_ON : BUTTON_OFF; +} + +static int button_adc_of_to_plat(struct udevice *dev) +{ + struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); + struct button_adc_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + u32 treshold, up_treshold, t; + ofnode node; + int ret; + + /* Ignore the top-level button node */ + if (!uc_plat->label) + return 0; + + ret = dev_read_phandle_with_args(dev->parent, "io-channels", +"#io-channel-cells", 0, 0, ); + if (ret) + return ret; + + ret = uclass_get_device_by_ofnode(UCLASS_ADC, args.node, >adc); + if (ret) + return ret; + + ret = ofnode_read_u32(dev_ofnode(dev->parent), + "keyup-threshold-microvolt", _treshold); + if (ret) + return ret; + + ret = ofnode_read_u32(dev_ofnode(dev), "press-threshold-microvolt", + ); + if (ret) + return ret; + + dev_for_each_subnode(node, dev->parent) { + ret = ofnode_read_u32(node, "press-threshold-microvolt", ); + if (ret) + return ret; + + if (t > treshold) + up_treshold = t; + } + + priv->channel = args.args[0]; + priv->min = treshold; + priv->max = up_treshold; + + return ret; +} + +static int button_adc_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + struct button_uc_plat *uc_plat; + const char *label; + + label = ofnode_read_string(node, "label"); + if (!label) { + debug("%s: node %s has no label\n", __func__, +
[PATCH v7 4/5] configs: khadas-vim3(l): enable Function button support
Add options required to check the 'Function' button state. Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- configs/khadas-vim3_defconfig | 2 ++ configs/khadas-vim3l_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 5d16652fd6..bc17430569 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y diff --git a/configs/khadas-vim3l_defconfig b/configs/khadas-vim3l_defconfig index 6b13ce045c..c1877922c7 100644 --- a/configs/khadas-vim3l_defconfig +++ b/configs/khadas-vim3l_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v7 5/5] test: add a simple test for the adc-keys button driver
Add adc-keys device to the sandbox/test.dts and connect it to the channel #3 of the sandbox_adc driver. The default values sampled by sandbox_adc driver determines that button3 and button4 are released and button5 is pressed. Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 28 +- configs/sandbox_defconfig | 1 + test/dm/button.c | 50 +-- 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e95f4631bf..202e091841 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -69,6 +70,30 @@ }; }; + buttons2 { + compatible = "adc-keys"; + io-channels = < 3>; + keyup-threshold-microvolt = <300>; + + button-up { + label = "button3"; + linux,code = ; + press-threshold-microvolt = <150>; + }; + + button-down { + label = "button4"; + linux,code = ; + press-threshold-microvolt = <100>; + }; + + button-enter { + label = "button5"; + linux,code = ; + press-threshold-microvolt = <50>; + }; + }; + cros_ec: cros-ec { reg = <0 0>; compatible = "google,cros-ec-sandbox"; @@ -587,8 +612,9 @@ i2c-eeprom = <_i2c>; }; - adc@0 { + adc: adc@0 { compatible = "sandbox,adc"; + #io-channel-cells = <1>; vdd-supply = <>; vss-microvolts = <0>; }; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 0c7674efc9..3731bf05ff 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -122,6 +122,7 @@ CONFIG_DM_BOOTCOUNT=y CONFIG_DM_BOOTCOUNT_RTC=y CONFIG_DM_BOOTCOUNT_I2C_EEPROM=y CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_BUTTON_GPIO=y CONFIG_CLK=y CONFIG_CLK_COMPOSITE_CCF=y diff --git a/test/dm/button.c b/test/dm/button.c index ecaa47cf5f..f8a7fab61d 100644 --- a/test/dm/button.c +++ b/test/dm/button.c @@ -7,7 +7,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -17,11 +20,20 @@ static int dm_test_button_base(struct unit_test_state *uts) { struct udevice *dev; - /* Get the top-level device */ + /* Get the top-level gpio buttons device */ ut_assertok(uclass_get_device(UCLASS_BUTTON, 0, )); + /* Get the 2 gpio buttons */ ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, )); ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, )); - ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 3, )); + + /* Get the top-level adc buttons device */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 3, )); + /* Get the 3 adc buttons */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 4, )); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 5, )); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 6, )); + + ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 7, )); return 0; } @@ -72,3 +84,37 @@ static int dm_test_button_label(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_button_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test adc-keys driver */ +static int dm_test_button_keys_adc(struct unit_test_state *uts) +{ + struct udevice *supply; + struct udevice *dev; + int uV; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", )); + + ut_assertok(regulator_get_by_devname(SANDBOX_BUCK2_DEVNAME, )); + ut_assertok(regulator_set_value(supply, SANDBOX_BUCK2_SET_UV)); + ut_asserteq(SANDBOX_BUCK2_SET_UV, regulator_get_value(supply)); + /* Update ADC plat and get new Vdd value */ + ut_assertok(adc_vdd_value(dev, )); + ut_asserteq(SANDBOX_BUCK2_SET_UV, uV); + + /* +* sandbox-adc returns constant value on channel 3, is used by adc-keys: +* SANDBOX_ADC_CHANNEL3_DATA * SANDBOX_BUCK2_SET_UV / SANDBOX_ADC_DATA_MASK = +* 0x3000 * 330 / 0x = 618759uV +* This means that button3 and button4 are released and button5 +* is pressed. +*/ + ut_assertok(button_get_by_label("button3", )); + ut_asserteq(BUTTON_OFF, button_get_state(dev)); + ut_assertok(button_get_by_label("button4", )); + ut_asserteq(BUTTON_OFF, button_get_state(dev)); + ut_assertok(button_get_by_la
[PATCH v6 5/5] test: add a simple test for the adc-keys button driver
Add adc-keys device to the sandbox/test.dts and connect it to the channel #3 of the sandbox_adc driver. The default values sampled by sandbox_adc driver determines that button3 and button4 are released and button5 is pressed. Signed-off-by: Marek Szyprowski --- arch/sandbox/dts/test.dts | 24 ++- configs/sandbox_defconfig | 1 + test/dm/button.c | 50 +-- 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e95f4631bf..a32b019ae7 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -69,6 +69,27 @@ }; }; + buttons2 { + compatible = "adc-keys"; + io-channels = < 3>; + keyup-threshold-microvolt = <300>; + + button-up { + label = "button3"; + press-threshold-microvolt = <150>; + }; + + button-down { + label = "button4"; + press-threshold-microvolt = <100>; + }; + + button-enter { + label = "button5"; + press-threshold-microvolt = <50>; + }; + }; + cros_ec: cros-ec { reg = <0 0>; compatible = "google,cros-ec-sandbox"; @@ -587,8 +608,9 @@ i2c-eeprom = <_i2c>; }; - adc@0 { + adc: adc@0 { compatible = "sandbox,adc"; + #io-channel-cells = <1>; vdd-supply = <>; vss-microvolts = <0>; }; diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 0c7674efc9..3731bf05ff 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -122,6 +122,7 @@ CONFIG_DM_BOOTCOUNT=y CONFIG_DM_BOOTCOUNT_RTC=y CONFIG_DM_BOOTCOUNT_I2C_EEPROM=y CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_BUTTON_GPIO=y CONFIG_CLK=y CONFIG_CLK_COMPOSITE_CCF=y diff --git a/test/dm/button.c b/test/dm/button.c index ecaa47cf5f..f8a7fab61d 100644 --- a/test/dm/button.c +++ b/test/dm/button.c @@ -7,7 +7,10 @@ #include #include +#include #include +#include +#include #include #include #include @@ -17,11 +20,20 @@ static int dm_test_button_base(struct unit_test_state *uts) { struct udevice *dev; - /* Get the top-level device */ + /* Get the top-level gpio buttons device */ ut_assertok(uclass_get_device(UCLASS_BUTTON, 0, )); + /* Get the 2 gpio buttons */ ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, )); ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, )); - ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 3, )); + + /* Get the top-level adc buttons device */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 3, )); + /* Get the 3 adc buttons */ + ut_assertok(uclass_get_device(UCLASS_BUTTON, 4, )); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 5, )); + ut_assertok(uclass_get_device(UCLASS_BUTTON, 6, )); + + ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 7, )); return 0; } @@ -72,3 +84,37 @@ static int dm_test_button_label(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_button_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Test adc-keys driver */ +static int dm_test_button_keys_adc(struct unit_test_state *uts) +{ + struct udevice *supply; + struct udevice *dev; + int uV; + + ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", )); + + ut_assertok(regulator_get_by_devname(SANDBOX_BUCK2_DEVNAME, )); + ut_assertok(regulator_set_value(supply, SANDBOX_BUCK2_SET_UV)); + ut_asserteq(SANDBOX_BUCK2_SET_UV, regulator_get_value(supply)); + /* Update ADC plat and get new Vdd value */ + ut_assertok(adc_vdd_value(dev, )); + ut_asserteq(SANDBOX_BUCK2_SET_UV, uV); + + /* +* sandbox-adc returns constant value on channel 3, is used by adc-keys: +* SANDBOX_ADC_CHANNEL3_DATA * SANDBOX_BUCK2_SET_UV / SANDBOX_ADC_DATA_MASK = +* 0x3000 * 330 / 0x = 618759uV +* This means that button3 and button4 are released and button5 +* is pressed. +*/ + ut_assertok(button_get_by_label("button3", )); + ut_asserteq(BUTTON_OFF, button_get_state(dev)); + ut_assertok(button_get_by_label("button4", )); + ut_asserteq(BUTTON_OFF, button_get_state(dev)); + ut_assertok(button_get_by_label("button5", )); + ut_asserteq(BUTTON_ON, button_get_state(dev)); + + return 0; +} +DM_TEST(dm_test_button_keys_adc, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); -- 2.17.1
[PATCH v6 2/5] button: add a simple Analog to Digital Converter device based button driver
Add a simple Analog to Digital Converter device based button driver. This driver binds to the 'adc-keys' device tree node. Signed-off-by: Marek Szyprowski --- drivers/button/Kconfig | 8 ++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 146 3 files changed, 155 insertions(+) create mode 100644 drivers/button/button-adc.c diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 6b3ec7e55d..6db3c5e93a 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -9,6 +9,14 @@ config BUTTON can provide access to board-specific buttons. Use of the device tree for configuration is encouraged. +config BUTTON_ADC + bool "Button adc" + depends on BUTTON + help + Enable support for buttons which are connected to Analog to Digital + Converter device. The ADC driver must use driver model. Buttons are + configured using the device tree. + config BUTTON_GPIO bool "Button gpio" depends on BUTTON diff --git a/drivers/button/Makefile b/drivers/button/Makefile index fcc10ebe8d..bbd18af149 100644 --- a/drivers/button/Makefile +++ b/drivers/button/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2020 Philippe Reynes obj-$(CONFIG_BUTTON) += button-uclass.o +obj-$(CONFIG_BUTTON_ADC) += button-adc.o obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c new file mode 100644 index 00..eed86564fb --- /dev/null +++ b/drivers/button/button-adc.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct button_adc_priv - private data for button-adc driver. + * + * @adc: Analog to Digital Converter device to which button is connected. + * @channel: channel of the ADC device to probe the button state. + * @min: minimal uV value to consider button as pressed. + * @max: maximal uV value to consider button as pressed. + */ +struct button_adc_priv { + struct udevice *adc; + int channel; + int min; + int max; +}; + +static enum button_state_t button_adc_get_state(struct udevice *dev) +{ + struct button_adc_priv *priv = dev_get_priv(dev); + unsigned int val; + int ret, uV; + + ret = adc_start_channel(priv->adc, priv->channel); + if (ret) + return ret; + + ret = adc_channel_data(priv->adc, priv->channel, ); + if (ret) + return ret; + + ret = adc_raw_to_uV(priv->adc, val, ); + if (ret) + return ret; + + return (uV >= priv->min && uV < priv->max) ? BUTTON_ON : BUTTON_OFF; +} + +static int button_adc_of_to_plat(struct udevice *dev) +{ + struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); + struct button_adc_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + u32 treshold, up_treshold, t; + ofnode node; + int ret; + + /* Ignore the top-level button node */ + if (!uc_plat->label) + return 0; + + ret = dev_read_phandle_with_args(dev->parent, "io-channels", +"#io-channel-cells", 0, 0, ); + if (ret) + return ret; + + ret = uclass_get_device_by_ofnode(UCLASS_ADC, args.node, >adc); + if (ret) + return ret; + + ret = ofnode_read_u32(dev_ofnode(dev->parent), + "keyup-threshold-microvolt", _treshold); + if (ret) + return ret; + + ret = ofnode_read_u32(dev_ofnode(dev), "press-threshold-microvolt", + ); + if (ret) + return ret; + + dev_for_each_subnode(node, dev->parent) { + ret = ofnode_read_u32(node, "press-threshold-microvolt", ); + if (ret) + return ret; + + if (t > treshold) + up_treshold = t; + } + + priv->channel = args.args[0]; + priv->min = treshold; + priv->max = up_treshold; + + return ret; +} + +static int button_adc_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + struct button_uc_plat *uc_plat; + const char *label; + + label = ofnode_read_string(node, "label"); + if (!label) { + debug("%s: node %s has no label\n", __func__, + ofnode_get_name(node)); + return -EINVAL; +
[PATCH v6 4/5] configs: khadas-vim3(l): enable Function button support
Add options required to check the 'Function' button state. Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- configs/khadas-vim3_defconfig | 2 ++ configs/khadas-vim3l_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 5d16652fd6..bc17430569 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y diff --git a/configs/khadas-vim3l_defconfig b/configs/khadas-vim3l_defconfig index 6b13ce045c..c1877922c7 100644 --- a/configs/khadas-vim3l_defconfig +++ b/configs/khadas-vim3l_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v6 0/5] VIM3: add support for checking 'Function' button state
Hi All, This patchset adds all building blocks needed for checking the 'Function' button state in the boot script on Amlogic A311D based VIM3 board. This button is connected to the ADC line of the SoC, so it required to enable meson SARADC, the clocks needed for it and a simple button-adc drivers. Once applied, one can use following commands in the boot scripts: -->8--- echo Checking Func button state: \\c if button Function then echo Selected alternative boot ... fi --->8--- Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v6: - added a simple sandbox test for adc-keys - use of_to_plat and adc_raw_to_uV to simplify code in the adc button driver v5: https://lists.denx.de/pipermail/u-boot/2021-January/438751.html - rebased onto latest uboot-amlogic/u-boot-amlogic-next branch - synchronized adc-keys binding with the recent version from the Linux kernel - updated adc-keys driver to match behavior from dt-bindings - added a patch for meson-saradc driver to register vdd reference supply to the ADC framework v4: https://lists.denx.de/pipermail/u-boot/2020-December/435641.html - rebased onto uboot-amlogic/u-boot-amlogic-next and dropped merged patches - added adc-keys bindings docs (copied from Linux kernel) - minor code adjustments pointed by Simon - enabled driver also in khadas-vim3l_defconfig v3: https://lists.denx.de/pipermail/u-boot/2020-December/435072.html - removed 'button' env variable - extended kconfig and patch descriptions v2: https://lists.denx.de/pipermail/u-boot/2020-December/434991.html - removed Change-Id tags - split defconfig changes into ADC and button related v1: https://lists.denx.de/pipermail/u-boot/2020-December/434875.html - initial submission Patch summary: Marek Szyprowski (5): dt-bindings: input: adc-keys bindings documentation button: add a simple Analog to Digital Converter device based button driver adc: meson-saradc: add support for getting reference voltage value configs: khadas-vim3(l): enable Function button support test: add a simple test for the adc-keys button driver arch/sandbox/dts/test.dts | 24 +++- configs/khadas-vim3_defconfig | 2 + configs/khadas-vim3l_defconfig | 2 + configs/sandbox_defconfig | 1 + doc/device-tree-bindings/input/adc-keys.txt | 67 + drivers/adc/meson-saradc.c | 21 +++ drivers/button/Kconfig | 8 ++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 146 test/dm/button.c| 50 ++- 10 files changed, 319 insertions(+), 3 deletions(-) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt create mode 100644 drivers/button/button-adc.c -- 2.17.1
[PATCH v6 1/5] dt-bindings: input: adc-keys bindings documentation
Dump adc-keys bindings documentation from Linux kernel source tree from commit 698dc0cf9447 ("dt-bindings: input: adc-keys: clarify description"). Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- doc/device-tree-bindings/input/adc-keys.txt | 67 + 1 file changed, 67 insertions(+) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt diff --git a/doc/device-tree-bindings/input/adc-keys.txt b/doc/device-tree-bindings/input/adc-keys.txt new file mode 100644 index 00..6c8be6a9ac --- /dev/null +++ b/doc/device-tree-bindings/input/adc-keys.txt @@ -0,0 +1,67 @@ +ADC attached resistor ladder buttons + + +Required properties: + - compatible: "adc-keys" + - io-channels: Phandle to an ADC channel + - io-channel-names = "buttons"; + - keyup-threshold-microvolt: Voltage above or equal to which all the keys are + considered up. + +Optional properties: + - poll-interval: Poll interval time in milliseconds + - autorepeat: Boolean, Enable auto repeat feature of Linux input + subsystem. + +Each button (key) is represented as a sub-node of "adc-keys": + +Required subnode-properties: + - label: Descriptive name of the key. + - linux,code: Keycode to emit. + - press-threshold-microvolt: voltage above or equal to which this key is +considered pressed. + +No two values of press-threshold-microvolt may be the same. +All values of press-threshold-microvolt must be less than +keyup-threshold-microvolt. + +Example: + +#include + + adc-keys { + compatible = "adc-keys"; + io-channels = < 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <200>; + + button-up { + label = "Volume Up"; + linux,code = ; + press-threshold-microvolt = <150>; + }; + + button-down { + label = "Volume Down"; + linux,code = ; + press-threshold-microvolt = <100>; + }; + + button-enter { + label = "Enter"; + linux,code = ; + press-threshold-microvolt = <50>; + }; + }; + ++++ +| 2.000.000 <= value | no key pressed | ++++ +| 1.500.000 <= value < 2.000.000 | KEY_VOLUMEUP pressed | ++++ +| 1.000.000 <= value < 1.500.000 | KEY_VOLUMEDOWN pressed | ++++ +| 500.000 <= value < 1.000.000 | KEY_ENTER pressed | ++++ +| value < 500.000 | no key pressed | ++++ -- 2.17.1
[PATCH v6 3/5] adc: meson-saradc: add support for getting reference voltage value
Add support for getting the 'vref-supply' regulator and register it as ADC's reference voltage regulator, so clients can translate sampled ADC values to the voltage. Signed-off-by: Marek Szyprowski Reviewed-by: Simon Glass --- drivers/adc/meson-saradc.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c index 21db55831d..1a45a3a265 100644 --- a/drivers/adc/meson-saradc.c +++ b/drivers/adc/meson-saradc.c @@ -18,6 +18,7 @@ #include #include #include +#include #define MESON_SAR_ADC_REG0 0x00 #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) @@ -656,7 +657,10 @@ static int meson_saradc_stop(struct udevice *dev) static int meson_saradc_probe(struct udevice *dev) { + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct meson_saradc_priv *priv = dev_get_priv(dev); + struct udevice *vref; + int vref_uv; int ret; ret = regmap_init_mem(dev_ofnode(dev), >regmap); @@ -675,6 +679,23 @@ static int meson_saradc_probe(struct udevice *dev) priv->active_channel = -1; + ret = device_get_supply_regulator(dev, "vref-supply", ); + if (ret) { + printf("can't get vref-supply: %d\n", ret); + return ret; + } + + vref_uv = regulator_get_value(vref); + if (vref_uv < 0) { + printf("can't get vref-supply value: %d\n", vref_uv); + return vref_uv; + } + + /* VDD supplied by common vref pin */ + uc_pdata->vdd_supply = vref; + uc_pdata->vdd_microvolts = vref_uv; + uc_pdata->vss_microvolts = 0; + return 0; } -- 2.17.1
Re: [PATCH v5 2/4] button: add a simple Analog to Digital Converter device based button driver
Hi Simon, On 08.02.2021 18:08, Simon Glass wrote: > On Mon, 8 Feb 2021 at 09:10, Marek Szyprowski > wrote: >> On 06.02.2021 17:21, Simon Glass wrote: >>> On Thu, 4 Feb 2021 at 03:36, Marek Szyprowski >>> wrote: >>>> ... >>>> Could you give me a bit more hints or point where to start? I've tried >>>> to build sandbox, but it fails for v2021.01 release (I've did make >>>> sandbox_defconfig && make all). I assume I would need to add adc and >>>> adc-keys devices to some sandbox dts and some code triggering and >>>> checking the key values, but that's all I know now. >>> Well you do need to be able to build sandbox or you will get >>> nowhere...what error did you get? Once we understand what went wrong >>> we can update the docs. Maybe it is missing a dependency. >> $ gcc --version >> gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 >> Copyright (C) 2017 Free Software Foundation, Inc. >> This is free software; see the source for copying conditions. There is NO >> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. >> >> $ git checkout v2021.01 >> >> $ make sandbox_defconfig >> # >> # configuration written to .config >> # >> >> $ make >> scripts/kconfig/conf --syncconfig Kconfig >> CFG u-boot.cfg >> GEN include/autoconf.mk >> GEN include/autoconf.mk.dep >> CFGCHK u-boot.cfg >> UPD include/generated/timestamp_autogenerated.h >> HOSTCC tools/mkenvimage.o >> HOSTLD tools/mkenvimage >> HOSTCC tools/fit_image.o >> HOSTCC tools/image-host.o >> HOSTCC tools/dumpimage.o >> HOSTLD tools/dumpimage >> HOSTCC tools/mkimage.o >> HOSTLD tools/mkimage >> HOSTLD tools/fit_info >> HOSTLD tools/fit_check_sign >> >> ... >> >> CC arch/sandbox/cpu/cpu.o >> In file included from include/common.h:26:0, >>from arch/sandbox/cpu/cpu.c:6: >> include/asm/global_data.h:112:58: warning: call-clobbered register used >> for global register variable >>#define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9") >> ^ >> include/dm/of.h:86:1: note: in expansion of macro ‘DECLARE_GLOBAL_DATA_PTR’ >>DECLARE_GLOBAL_DATA_PTR; > This is pretty mysterious. Are you sure you are using an x86_64 machine? I've finally found what caused the issue on my build system. It is x86_64 machine, but after some old cross-builds I had an 'asm' symlink in u-boot/include directory pointing to arch/arm directory. I'm quite surprised that it has not been removed by make clean/distclean/mrproper combo. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
Re: [PATCH v5 2/4] button: add a simple Analog to Digital Converter device based button driver
Hi Simon, On 06.02.2021 17:21, Simon Glass wrote: > On Thu, 4 Feb 2021 at 03:36, Marek Szyprowski > wrote: >> ... >> Could you give me a bit more hints or point where to start? I've tried >> to build sandbox, but it fails for v2021.01 release (I've did make >> sandbox_defconfig && make all). I assume I would need to add adc and >> adc-keys devices to some sandbox dts and some code triggering and >> checking the key values, but that's all I know now. > Well you do need to be able to build sandbox or you will get > nowhere...what error did you get? Once we understand what went wrong > we can update the docs. Maybe it is missing a dependency. $ gcc --version gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ git checkout v2021.01 $ make sandbox_defconfig # # configuration written to .config # $ make scripts/kconfig/conf --syncconfig Kconfig CFG u-boot.cfg GEN include/autoconf.mk GEN include/autoconf.mk.dep CFGCHK u-boot.cfg UPD include/generated/timestamp_autogenerated.h HOSTCC tools/mkenvimage.o HOSTLD tools/mkenvimage HOSTCC tools/fit_image.o HOSTCC tools/image-host.o HOSTCC tools/dumpimage.o HOSTLD tools/dumpimage HOSTCC tools/mkimage.o HOSTLD tools/mkimage HOSTLD tools/fit_info HOSTLD tools/fit_check_sign ... CC arch/sandbox/cpu/cpu.o In file included from include/common.h:26:0, from arch/sandbox/cpu/cpu.c:6: include/asm/global_data.h:112:58: warning: call-clobbered register used for global register variable #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r9") ^ include/dm/of.h:86:1: note: in expansion of macro ‘DECLARE_GLOBAL_DATA_PTR’ DECLARE_GLOBAL_DATA_PTR; ^~~ In file included from arch/sandbox/cpu/cpu.c:18:0: ./arch/sandbox/include/asm/state.h:98:30: error: ‘CONFIG_SANDBOX_SPI_MAX_BUS’ undeclared here (not in a function); did you mean ‘CONFIG_SANDBOX_SPI’? struct sandbox_spi_info spi[CONFIG_SANDBOX_SPI_MAX_BUS] ^~ CONFIG_SANDBOX_SPI ./arch/sandbox/include/asm/state.h:99:7: error: ‘CONFIG_SANDBOX_SPI_MAX_CS’ undeclared here (not in a function); did you mean ‘CONFIG_SANDBOX_SPI_MAX_BUS’? [CONFIG_SANDBOX_SPI_MAX_CS]; ^ CONFIG_SANDBOX_SPI_MAX_BUS arch/sandbox/cpu/cpu.c: In function ‘is_in_sandbox_mem’: arch/sandbox/cpu/cpu.c:83:41: error: ‘volatile struct arch_global_data’ has no member named ‘ram_buf’ return (const uint8_t *)ptr >= gd->arch.ram_buf && ^ arch/sandbox/cpu/cpu.c:84:34: error: ‘volatile struct arch_global_data’ has no member named ‘ram_buf’ (const uint8_t *)ptr < gd->arch.ram_buf + gd->ram_size; ^ arch/sandbox/cpu/cpu.c: At top level: arch/sandbox/cpu/cpu.c:97:7: error: redefinition of ‘phys_to_virt’ void *phys_to_virt(phys_addr_t paddr) ^~~~ In file included from include/asm/io.h:495:0, from arch/sandbox/cpu/cpu.c:15: include/asm-generic/io.h:30:21: note: previous definition of ‘phys_to_virt’ was here static inline void *phys_to_virt(phys_addr_t paddr) ^~~~ arch/sandbox/cpu/cpu.c: In function ‘phys_to_virt’: arch/sandbox/cpu/cpu.c:104:27: error: ‘volatile struct arch_global_data’ has no member named ‘ram_buf’ return (void *)(gd->arch.ram_buf + paddr); ^ In file included from include/linux/posix_types.h:4:0, from include/linux/types.h:4, from include/time.h:7, from include/common.h:18, from arch/sandbox/cpu/cpu.c:6: include/linux/stddef.h:17:33: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) ^ include/linux/kernel.h:274:29: note: in expansion of macro ‘offsetof’ (type *)( (char *)__mptr - offsetof(type,member) );}) ^~~~ include/linux/list.h:327:2: note: in expansion of macro ‘container_of’ container_of(ptr, type, member) ^~~~ include/linux/list.h:424:13: note: in expansion of macro ‘list_entry’ for (pos = list_entry((head)->next, typeof(*pos), member); \ ^~ arch/sandbox/cpu/cpu.c:111:2: note: in expansion of macro ‘list_for_each_entry’ list_for_each_entry(mentry, >mapmem_head, sibling_node) { ^~~ include/linux/stddef.h:17:33: warning: cast from pointer to intege
Re: [PATCH v5 2/4] button: add a simple Analog to Digital Converter device based button driver
Hi Simon, On 01.02.2021 21:38, Simon Glass wrote: > On Tue, 26 Jan 2021 at 06:03, Heinrich Schuchardt wrote: >> On 26.01.21 12:25, Marek Szyprowski wrote: >>> On 26.01.2021 12:10, Heinrich Schuchardt wrote: >>>> On 1/26/21 10:50 AM, Marek Szyprowski wrote: >>>>> Add a simple Analog to Digital Converter device based button driver. >>>>> This >>>>> driver binds to the 'adc-keys' device tree node. >>>>> >>>>> Signed-off-by: Marek Szyprowski >>>>> --- >>>>>drivers/button/Kconfig | 8 ++ >>>>>drivers/button/Makefile | 1 + >>>>>drivers/button/button-adc.c | 156 >>>>>3 files changed, 165 insertions(+) >>>>>create mode 100644 drivers/button/button-adc.c >>>>> >>>>> diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig >>>>> index 6b3ec7e55d..6db3c5e93a 100644 >>>>> --- a/drivers/button/Kconfig >>>>> +++ b/drivers/button/Kconfig >>>>> @@ -9,6 +9,14 @@ config BUTTON >>>>> can provide access to board-specific buttons. Use of the >>>>> device tree >>>>> for configuration is encouraged. >>>>> >>>>> +config BUTTON_ADC >>>>> +bool "Button adc" >>>>> +depends on BUTTON >>>>> +help >>>>> + Enable support for buttons which are connected to Analog to >>>>> Digital >>>>> + Converter device. The ADC driver must use driver model. >>>>> Buttons are >>>>> + configured using the device tree. >>>>> + >>>>>config BUTTON_GPIO >>>>>bool "Button gpio" >>>>>depends on BUTTON >>>>> diff --git a/drivers/button/Makefile b/drivers/button/Makefile >>>>> index fcc10ebe8d..bbd18af149 100644 >>>>> --- a/drivers/button/Makefile >>>>> +++ b/drivers/button/Makefile >>>>> @@ -3,4 +3,5 @@ >>>>># Copyright (C) 2020 Philippe Reynes >>>>> >>>>>obj-$(CONFIG_BUTTON) += button-uclass.o >>>>> +obj-$(CONFIG_BUTTON_ADC) += button-adc.o >>>>>obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o >>>>> diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c >>>>> new file mode 100644 >>>>> index 00..1901d59a0e >>>>> --- /dev/null >>>>> +++ b/drivers/button/button-adc.c >>>>> @@ -0,0 +1,156 @@ >>>>> +// SPDX-License-Identifier: GPL-2.0 >>>>> +/* >>>>> + * Copyright (C) 2021 Samsung Electronics Co., Ltd. >>>>> + *http://www.samsung.com >>>>> + * Author: Marek Szyprowski >>>>> + */ >>>>> + >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> +#include >>>>> + >>>>> +/** >>>>> + * struct button_adc_priv - private data for button-adc driver. >>>>> + * >>>>> + * @adc: Analog to Digital Converter device to which button is >>>>> connected. >>>>> + * @channel: channel of the ADC device to probe the button state. >>>>> + * @min: minimal raw ADC sample value to consider button as pressed. >>>>> + * @max: maximal raw ADC sample value to consider button as pressed. >>>>> + */ >>>>> +struct button_adc_priv { >>>>> +struct udevice *adc; >>>>> +int channel; >>>>> +int min; >>>>> +int max; >>>>> +}; >>>>> + >>>>> +static enum button_state_t button_adc_get_state(struct udevice *dev) >>>>> +{ >>>>> +struct button_adc_priv *priv = dev_get_priv(dev); >>>>> +unsigned int val; >>>>> +int ret; >>>>> + >>>>> +ret = adc_start_channel(priv->adc, priv->channel); >>>>> +if (ret) >>>>> +return ret; >>>>> + >>>>> +ret = adc_channel_data(priv->adc, priv->channel, ); >>>>> +if (ret) >>>>> +return ret; >&g
[PATCH] board: amlogic: odroid: add runtime detection of the N2/N2+/C4/HC4 variants
Use the ADC channel 1 to check the hardware revision of the board and detect the N2 vs. N2+ and the C4 vs. HC4 variants. Each of them use different dtb file, so adjust fdtfile environment variable to the detected variant. The ADC min/max values for each variant are taken from the vendor code, adjusted to the 12-bit ADC driver operation mode (vendor code use 10-bit mode). Signed-off-by: Marek Szyprowski --- The relevant vendor's code is here: https://github.com/hardkernel/u-boot/blob/odroidg12-v2015.01/board/hardkernel/odroid-common/board.c#L55 --- arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi | 6 ++ arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi | 6 ++ board/amlogic/odroid-n2/odroid-n2.c | 80 +++ configs/odroid-c4_defconfig | 4 +- configs/odroid-n2_defconfig | 4 +- 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi index 236f2468dc..a92f9e9ff1 100644 --- a/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi +++ b/arch/arm/dts/meson-g12b-odroid-n2-u-boot.dtsi @@ -5,3 +5,9 @@ */ #include "meson-g12-common-u-boot.dtsi" + +/* SARADC is needed for proper board variant detection */ + { + status = "okay"; + vref-supply = <_1v8>; +}; diff --git a/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi b/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi index fbcc8287c5..963bf96b25 100644 --- a/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi +++ b/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi @@ -12,6 +12,12 @@ snps,reset-active-low; }; +/* SARADC is needed for proper board variant detection */ + { + status = "okay"; + vref-supply = <_1v8>; +}; + _vdd { gpio = <_ao GPIOAO_3 GPIO_OPEN_DRAIN>; }; diff --git a/board/amlogic/odroid-n2/odroid-n2.c b/board/amlogic/odroid-n2/odroid-n2.c index d9955433bf..2eb7fa93be 100644 --- a/board/amlogic/odroid-n2/odroid-n2.c +++ b/board/amlogic/odroid-n2/odroid-n2.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -19,6 +20,11 @@ #define EFUSE_MAC_SIZE 12 #define MAC_ADDR_LEN 6 +#define ODROID_HW_VS_ADC_CHANNEL 1 + +#define MESON_SOC_ID_G12B 0x29 +#define MESON_SOC_ID_SM1 0x2b + int mmc_get_env_dev(void) { if (meson_get_boot_device() == BOOT_DEVICE_EMMC) @@ -26,6 +32,79 @@ int mmc_get_env_dev(void) return 0; } +/* Variant detection is based on the ADC RAW values for the channel #1 */ +static struct meson_odroid_boards { + unsigned int soc_id; + unsigned int adc_min; + unsigned int adc_max; + char *variant; +} boards[] = { + /* OdroidN2 rev 2018,7,23 */ + { MESON_SOC_ID_G12B, 80 * 4, 90 * 4, "n2" }, + /* OdroidN2 rev 2018,12,6 */ + { MESON_SOC_ID_G12B, 160 * 4, 170 * 4, "n2" }, + /* OdroidN2 rev 2019,1,17 */ + { MESON_SOC_ID_G12B, 245 * 4, 255 * 4, "n2" }, + /* OdroidN2 rev 2019,2,7 */ + { MESON_SOC_ID_G12B, 330 * 4, 350 * 4, "n2" }, + /* OdroidN2plus rev 2019,11,20 */ + { MESON_SOC_ID_G12B, 410 * 4, 430 * 4, "n2_plus" }, + /* OdroidC4 rev 2020,01,29 */ + { MESON_SOC_ID_SM1, 80 * 4, 100 * 4, "c4" }, + /* OdroidHC4 rev 2019,12,10 */ + { MESON_SOC_ID_SM1, 300 * 4, 320 * 4, "hc4" }, + /* OdroidC4 rev 2019,11,29 */ + { MESON_SOC_ID_SM1, 335 * 4, 345 * 4, "c4" }, + /* OdroidHC4 rev 2020,8,7 */ + { MESON_SOC_ID_SM1, 590 * 4, 610 * 4, "hc4" }, +}; + +static void odroid_set_fdtfile(char *soc, char *variant) +{ + char s[128]; + + snprintf(s, sizeof(s), "amlogic/meson-%s-odroid-%s.dtb", soc, variant); + env_set("fdtfile", s); +} + +static int odroid_detect_variant(void) +{ + char *variant = "", *soc = ""; + unsigned int adcval = 0; + int ret, i, soc_id = 0; + + if (of_machine_is_compatible("amlogic,sm1")) { + soc_id = MESON_SOC_ID_SM1; + soc = "sm1"; + } else if (of_machine_is_compatible("amlogic,g12b")) { + soc_id = MESON_SOC_ID_G12B; + soc = "g12b"; + } else { + return -1; + } + + ret = adc_channel_single_shot("adc@9000", ODROID_HW_VS_ADC_CHANNEL, + ); + if (ret) + return ret; + + for (i = 0 ; i < ARRAY_SIZE(boards) ; ++i) { + if (soc_id == boards[i].soc_id && + adcval >= boards[i].adc_min && + adcval < boards[i].adc_max) { + variant = boards[i].variant; + break; + } + } + +
[PATCH] rpi: limit size of the RAM to the multiple of the MMU_SECTION_SIZE
When RPi4 is booted from USB Mass Storage, the firmware reports 947MiB of the ARM memory (948 in case of the standard SD-card boot). This value is not MMU_SECTION_SIZE aligned, so the dram_bank_mmu_setup() skips mapping of the last 1MiB. This later causes u-boot in ARM 32bit mode to freeze, because it relocated itself into that unmapped memory and fails to execute. Fix this by limiting the size of the first bank to the multiple of MMU_SECTION_SIZE. Signed-off-by: Marek Szyprowski --- board/raspberrypi/rpi/rpi.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/board/raspberrypi/rpi/rpi.c b/board/raspberrypi/rpi/rpi.c index 6b1fa5fc14..83ccd3e3fc 100644 --- a/board/raspberrypi/rpi/rpi.c +++ b/board/raspberrypi/rpi/rpi.c @@ -268,6 +268,13 @@ int dram_init(void) gd->ram_size = msg->get_arm_mem.body.resp.mem_size; + /* +* In some configurations the memory size returned by VideoCore +* is not aligned to the section size, what is mandatory for +* the u-boot's memory setup. +*/ + gd->ram_size &= ~MMU_SECTION_SIZE; + return 0; } -- 2.17.1
Re: [PATCH v2] disk: part_dos: update partition table entries after write
Hi, On 28.01.2021 09:10, Gary Bisson wrote: > Fixes issues when switching from GPT to MBR partition tables. > > Signed-off-by: Gary Bisson Acked-by: Marek Szyprowski > --- > Changes for v2: > - added part_init() inside write_mbr_partitions(), as suggested by >Heinrich > --- > disk/part_dos.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/disk/part_dos.c b/disk/part_dos.c > index f431925745c..60addc6e00d 100644 > --- a/disk/part_dos.c > +++ b/disk/part_dos.c > @@ -423,6 +423,9 @@ int write_mbr_partitions(struct blk_desc *dev, > ext_part_sect = next_ebr; > } > > + /* Update the partition table entries*/ > + part_init(dev_desc); > + > return 0; > } > > @@ -499,6 +502,9 @@ int write_mbr_sector(struct blk_desc *dev_desc, void *buf) > return 1; > } > > + /* Update the partition table entries*/ > + part_init(dev_desc); > + > return 0; > } > Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
Re: [PATCH v5 2/4] button: add a simple Analog to Digital Converter device based button driver
Hi Heinrich, On 26.01.2021 12:10, Heinrich Schuchardt wrote: > On 1/26/21 10:50 AM, Marek Szyprowski wrote: >> Add a simple Analog to Digital Converter device based button driver. >> This >> driver binds to the 'adc-keys' device tree node. >> >> Signed-off-by: Marek Szyprowski >> --- >> drivers/button/Kconfig | 8 ++ >> drivers/button/Makefile | 1 + >> drivers/button/button-adc.c | 156 >> 3 files changed, 165 insertions(+) >> create mode 100644 drivers/button/button-adc.c >> >> diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig >> index 6b3ec7e55d..6db3c5e93a 100644 >> --- a/drivers/button/Kconfig >> +++ b/drivers/button/Kconfig >> @@ -9,6 +9,14 @@ config BUTTON >> can provide access to board-specific buttons. Use of the >> device tree >> for configuration is encouraged. >> >> +config BUTTON_ADC >> + bool "Button adc" >> + depends on BUTTON >> + help >> + Enable support for buttons which are connected to Analog to >> Digital >> + Converter device. The ADC driver must use driver model. >> Buttons are >> + configured using the device tree. >> + >> config BUTTON_GPIO >> bool "Button gpio" >> depends on BUTTON >> diff --git a/drivers/button/Makefile b/drivers/button/Makefile >> index fcc10ebe8d..bbd18af149 100644 >> --- a/drivers/button/Makefile >> +++ b/drivers/button/Makefile >> @@ -3,4 +3,5 @@ >> # Copyright (C) 2020 Philippe Reynes >> >> obj-$(CONFIG_BUTTON) += button-uclass.o >> +obj-$(CONFIG_BUTTON_ADC) += button-adc.o >> obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o >> diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c >> new file mode 100644 >> index 00..1901d59a0e >> --- /dev/null >> +++ b/drivers/button/button-adc.c >> @@ -0,0 +1,156 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * Copyright (C) 2021 Samsung Electronics Co., Ltd. >> + * http://www.samsung.com >> + * Author: Marek Szyprowski >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +/** >> + * struct button_adc_priv - private data for button-adc driver. >> + * >> + * @adc: Analog to Digital Converter device to which button is >> connected. >> + * @channel: channel of the ADC device to probe the button state. >> + * @min: minimal raw ADC sample value to consider button as pressed. >> + * @max: maximal raw ADC sample value to consider button as pressed. >> + */ >> +struct button_adc_priv { >> + struct udevice *adc; >> + int channel; >> + int min; >> + int max; >> +}; >> + >> +static enum button_state_t button_adc_get_state(struct udevice *dev) >> +{ >> + struct button_adc_priv *priv = dev_get_priv(dev); >> + unsigned int val; >> + int ret; >> + >> + ret = adc_start_channel(priv->adc, priv->channel); >> + if (ret) >> + return ret; >> + >> + ret = adc_channel_data(priv->adc, priv->channel, ); >> + if (ret) >> + return ret; >> + >> + if (ret == 0) >> + return (val >= priv->min && val < priv->max) ? >> + BUTTON_ON : BUTTON_OFF; >> + >> + return ret; >> +} >> + >> +static int button_adc_probe(struct udevice *dev) >> +{ >> + struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); >> + struct button_adc_priv *priv = dev_get_priv(dev); >> + struct ofnode_phandle_args args; >> + u32 treshold, up_treshold, t; >> + unsigned int mask; >> + ofnode node; >> + int ret, vdd; >> + >> + /* Ignore the top-level button node */ >> + if (!uc_plat->label) >> + return 0; >> + >> + ret = dev_read_phandle_with_args(dev->parent, "io-channels", >> + "#io-channel-cells", 0, 0, ); >> + if (ret) >> + return ret; >> + >> + ret = uclass_get_device_by_ofnode(UCLASS_ADC, args.node, >> >adc); >> + if (ret) >> + return ret; >> + >> + ret = ofnode_read_u32(dev_ofnode(dev->parent), >> + "keyup-threshold-microvolt", _treshold); >> + if (ret) >> + return ret; >> + >&
[PATCH v5 2/4] button: add a simple Analog to Digital Converter device based button driver
Add a simple Analog to Digital Converter device based button driver. This driver binds to the 'adc-keys' device tree node. Signed-off-by: Marek Szyprowski --- drivers/button/Kconfig | 8 ++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 156 3 files changed, 165 insertions(+) create mode 100644 drivers/button/button-adc.c diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 6b3ec7e55d..6db3c5e93a 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -9,6 +9,14 @@ config BUTTON can provide access to board-specific buttons. Use of the device tree for configuration is encouraged. +config BUTTON_ADC + bool "Button adc" + depends on BUTTON + help + Enable support for buttons which are connected to Analog to Digital + Converter device. The ADC driver must use driver model. Buttons are + configured using the device tree. + config BUTTON_GPIO bool "Button gpio" depends on BUTTON diff --git a/drivers/button/Makefile b/drivers/button/Makefile index fcc10ebe8d..bbd18af149 100644 --- a/drivers/button/Makefile +++ b/drivers/button/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2020 Philippe Reynes obj-$(CONFIG_BUTTON) += button-uclass.o +obj-$(CONFIG_BUTTON_ADC) += button-adc.o obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c new file mode 100644 index 00..1901d59a0e --- /dev/null +++ b/drivers/button/button-adc.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2021 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * struct button_adc_priv - private data for button-adc driver. + * + * @adc: Analog to Digital Converter device to which button is connected. + * @channel: channel of the ADC device to probe the button state. + * @min: minimal raw ADC sample value to consider button as pressed. + * @max: maximal raw ADC sample value to consider button as pressed. + */ +struct button_adc_priv { + struct udevice *adc; + int channel; + int min; + int max; +}; + +static enum button_state_t button_adc_get_state(struct udevice *dev) +{ + struct button_adc_priv *priv = dev_get_priv(dev); + unsigned int val; + int ret; + + ret = adc_start_channel(priv->adc, priv->channel); + if (ret) + return ret; + + ret = adc_channel_data(priv->adc, priv->channel, ); + if (ret) + return ret; + + if (ret == 0) + return (val >= priv->min && val < priv->max) ? + BUTTON_ON : BUTTON_OFF; + + return ret; +} + +static int button_adc_probe(struct udevice *dev) +{ + struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev); + struct button_adc_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + u32 treshold, up_treshold, t; + unsigned int mask; + ofnode node; + int ret, vdd; + + /* Ignore the top-level button node */ + if (!uc_plat->label) + return 0; + + ret = dev_read_phandle_with_args(dev->parent, "io-channels", +"#io-channel-cells", 0, 0, ); + if (ret) + return ret; + + ret = uclass_get_device_by_ofnode(UCLASS_ADC, args.node, >adc); + if (ret) + return ret; + + ret = ofnode_read_u32(dev_ofnode(dev->parent), + "keyup-threshold-microvolt", _treshold); + if (ret) + return ret; + + ret = ofnode_read_u32(dev_ofnode(dev), "press-threshold-microvolt", + ); + if (ret) + return ret; + + dev_for_each_subnode(node, dev->parent) { + ret = ofnode_read_u32(dev_ofnode(dev), + "press-threshold-microvolt", ); + if (ret) + return ret; + + if (t > treshold) + up_treshold = t; + } + + ret = adc_vdd_value(priv->adc, ); + if (ret) + return ret; + + ret = adc_data_mask(priv->adc, ); + if (ret) + return ret; + + priv->channel = args.args[0]; + priv->min = mask * (treshold / 1000) / (vdd / 1000); + priv->max = mask * (up_treshold / 1000) / (vdd / 1000); + + return ret; +} + +static int button_adc_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + struct button_uc_pl
[PATCH v5 3/4] adc: meson-saradc: add support for getting reference voltage value
Add support for getting the 'vref-supply' regulator and register it as ADC's reference voltage regulator, so clients can translate sampled ADC values to the voltage. Signed-off-by: Marek Szyprowski --- drivers/adc/meson-saradc.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c index 21db55831d..1a45a3a265 100644 --- a/drivers/adc/meson-saradc.c +++ b/drivers/adc/meson-saradc.c @@ -18,6 +18,7 @@ #include #include #include +#include #define MESON_SAR_ADC_REG0 0x00 #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) @@ -656,7 +657,10 @@ static int meson_saradc_stop(struct udevice *dev) static int meson_saradc_probe(struct udevice *dev) { + struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev); struct meson_saradc_priv *priv = dev_get_priv(dev); + struct udevice *vref; + int vref_uv; int ret; ret = regmap_init_mem(dev_ofnode(dev), >regmap); @@ -675,6 +679,23 @@ static int meson_saradc_probe(struct udevice *dev) priv->active_channel = -1; + ret = device_get_supply_regulator(dev, "vref-supply", ); + if (ret) { + printf("can't get vref-supply: %d\n", ret); + return ret; + } + + vref_uv = regulator_get_value(vref); + if (vref_uv < 0) { + printf("can't get vref-supply value: %d\n", vref_uv); + return vref_uv; + } + + /* VDD supplied by common vref pin */ + uc_pdata->vdd_supply = vref; + uc_pdata->vdd_microvolts = vref_uv; + uc_pdata->vss_microvolts = 0; + return 0; } -- 2.17.1
[PATCH v5 4/4] configs: khadas-vim3(l): enable Function button support
Add options required to check the 'Function' button state. Signed-off-by: Marek Szyprowski --- configs/khadas-vim3_defconfig | 2 ++ configs/khadas-vim3l_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 5d16652fd6..bc17430569 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y diff --git a/configs/khadas-vim3l_defconfig b/configs/khadas-vim3l_defconfig index 6b13ce045c..c1877922c7 100644 --- a/configs/khadas-vim3l_defconfig +++ b/configs/khadas-vim3l_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v5 1/4] dt-bindings: input: adc-keys bindings documentation
Dump adc-keys bindings documentation from Linux kernel source tree from commit 698dc0cf9447 ("dt-bindings: input: adc-keys: clarify description"). Signed-off-by: Marek Szyprowski --- doc/device-tree-bindings/input/adc-keys.txt | 67 + 1 file changed, 67 insertions(+) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt diff --git a/doc/device-tree-bindings/input/adc-keys.txt b/doc/device-tree-bindings/input/adc-keys.txt new file mode 100644 index 00..6c8be6a9ac --- /dev/null +++ b/doc/device-tree-bindings/input/adc-keys.txt @@ -0,0 +1,67 @@ +ADC attached resistor ladder buttons + + +Required properties: + - compatible: "adc-keys" + - io-channels: Phandle to an ADC channel + - io-channel-names = "buttons"; + - keyup-threshold-microvolt: Voltage above or equal to which all the keys are + considered up. + +Optional properties: + - poll-interval: Poll interval time in milliseconds + - autorepeat: Boolean, Enable auto repeat feature of Linux input + subsystem. + +Each button (key) is represented as a sub-node of "adc-keys": + +Required subnode-properties: + - label: Descriptive name of the key. + - linux,code: Keycode to emit. + - press-threshold-microvolt: voltage above or equal to which this key is +considered pressed. + +No two values of press-threshold-microvolt may be the same. +All values of press-threshold-microvolt must be less than +keyup-threshold-microvolt. + +Example: + +#include + + adc-keys { + compatible = "adc-keys"; + io-channels = < 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <200>; + + button-up { + label = "Volume Up"; + linux,code = ; + press-threshold-microvolt = <150>; + }; + + button-down { + label = "Volume Down"; + linux,code = ; + press-threshold-microvolt = <100>; + }; + + button-enter { + label = "Enter"; + linux,code = ; + press-threshold-microvolt = <50>; + }; + }; + ++++ +| 2.000.000 <= value | no key pressed | ++++ +| 1.500.000 <= value < 2.000.000 | KEY_VOLUMEUP pressed | ++++ +| 1.000.000 <= value < 1.500.000 | KEY_VOLUMEDOWN pressed | ++++ +| 500.000 <= value < 1.000.000 | KEY_ENTER pressed | ++++ +| value < 500.000 | no key pressed | ++++ -- 2.17.1
[PATCH v5 0/4] VIM3: add support for checking 'Function' button state
Hi All, This patchset adds all building blocks needed for checking the 'Function' button state in the boot script on Amlogic A311D based VIM3 board. This button is connected to the ADC lines of the SoC, so it required to enable meson SARADC, the clocks needed for it and a simple button-adc drivers. Once applied, one can use following commands in the boot scripts: -->8--- echo Checking Func button state: \\c if button Function then echo Selected alternative boot ... fi --->8--- Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v5: - rebased onto latest uboot-amlogic/u-boot-amlogic-next branch - synchronized adc-keys binding with the recent version from the Linux kernel - updated adc-keys driver to match behavior from dt-bindings - added a patch for meson-saradc driver to register vdd reference supply to the ADC framework v4: https://lists.denx.de/pipermail/u-boot/2020-December/435641.html - rebased onto uboot-amlogic/u-boot-amlogic-next and dropped merged patches - added adc-keys bindings docs (copied from Linux kernel) - minor code adjustments pointed by Simon - enabled driver also in khadas-vim3l_defconfig v3: https://lists.denx.de/pipermail/u-boot/2020-December/435072.html - removed 'button' env variable - extended kconfig and patch descriptions v2: https://lists.denx.de/pipermail/u-boot/2020-December/434991.html - removed Change-Id tags - split defconfig changes into ADC and button related v1: https://lists.denx.de/pipermail/u-boot/2020-December/434875.html - initial submission Patch summary: Marek Szyprowski (4): dt-bindings: input: adc-keys bindings documentation button: add a simple Analog to Digital Converter device based button driver adc: meson-saradc: add support for getting reference voltage value configs: khadas-vim3(l): enable Function button support configs/khadas-vim3_defconfig | 2 + configs/khadas-vim3l_defconfig | 2 + doc/device-tree-bindings/input/adc-keys.txt | 67 + drivers/adc/meson-saradc.c | 21 +++ drivers/button/Kconfig | 8 + drivers/button/Makefile | 1 + drivers/button/button-adc.c | 156 7 files changed, 257 insertions(+) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt create mode 100644 drivers/button/button-adc.c -- 2.17.1
Re: [PATCH v4 0/3] VIM3: add support for checking 'Function' button state
Hi Neil, On 18.01.2021 13:55, Neil Armstrong wrote: > On 18/01/2021 13:48, Heinrich Schuchardt wrote: >> On 18.01.21 11:24, Neil Armstrong wrote: >>> On 22/12/2020 09:56, Marek Szyprowski wrote: >>>> Hi All, >>>> >>>> This patchset adds all building blocks needed for checking the 'Function' >>>> button state in the boot script on Amlogic A311D based VIM3 board. This >>>> button is connected to the ADC lines of the SoC, so it required to enable >>>> meson SARADC, the clocks needed for it and a simple button-adc drivers. >>>> >>>> Once applied, one can use following commands in the boot scripts: >>>> -->8--- >>>> echo Checking Func button state: \\c >>>> if button Function >>>> then >>>>echo Selected alternative boot >>>>... >>>> fi >>>> --->8--- >>>> >>>> Best regards >>>> Marek Szyprowski >>>> Samsung R Institute Poland >>>> >>>> >>>> Changelog: >>>> v4: >>>> - rebased onto uboot-amlogic/u-boot-amlogic-next and dropped merged patches >>>> - added adc-keys bindings docs (copied from Linux kernel) >>>> - minor code adjustments pointed by Simon >>>> - enabled driver also in khadas-vim3l_defconfig >>>> >>>> v3: >>>> https://protect2.fireeye.com/v1/url?k=fc4a4b97-a3d1734e-fc4bc0d8-0cc47a3356b2-eb4ba315795a3f17=1=b660ed0e-7d37-47e8-877d-c8391317e3e0=https%3A%2F%2Flists.denx.de%2Fpipermail%2Fu-boot%2F2020-December%2F435072.html >>>> - removed 'button' env variable >>>> - extended kconfig and patch descriptions >>>> >>>> v2: >>>> https://protect2.fireeye.com/v1/url?k=11f0ed69-4e6bd5b0-11f16626-0cc47a3356b2-f341d16b01448534=1=b660ed0e-7d37-47e8-877d-c8391317e3e0=https%3A%2F%2Flists.denx.de%2Fpipermail%2Fu-boot%2F2020-December%2F434991.html >>>> - removed Change-Id tags >>>> - split defconfig changes into ADC and button related >>>> >>>> v1: >>>> https://protect2.fireeye.com/v1/url?k=7c601119-23fb29c0-7c619a56-0cc47a3356b2-55caa8afe3085a65=1=b660ed0e-7d37-47e8-877d-c8391317e3e0=https%3A%2F%2Flists.denx.de%2Fpipermail%2Fu-boot%2F2020-December%2F434875.html >>>> - initial submission >>> What's the state of the patchset ? >> Hello Neil, >> >> the series is assigned to you. Patch 2 is incorrect. Patch 1 can be >> updated to match Linux. So I suggest to set the status for the series to >> "changes requested". > Sure, it was more a question to Marek, but yeah I'll tag them "changes > requested" I'm sorry for the late reply, I've been busy with other stuff. I will try to update the adc-keys driver to use the threshold values and add the updated device tree bindings soon. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
[PATCH] cmd: misc: Fix return value for the sleep command
If sleeping has been interrupted, return CMD_RET_FAILURE instead of -1 (CMD_RET_USAGE). Signed-off-by: Marek Szyprowski --- cmd/sleep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/sleep.c b/cmd/sleep.c index f0c78a8efb..1fff400c79 100644 --- a/cmd/sleep.c +++ b/cmd/sleep.c @@ -40,7 +40,7 @@ static int do_sleep(struct cmd_tbl *cmdtp, int flag, int argc, while (get_timer(start) < delay) { if (ctrlc()) - return (-1); + return CMD_RET_FAILURE; udelay(100); } -- 2.17.1
Re: [PATCH] board: amlogic: vim3: fix setup ethernet mac from efuse
Hi Artem, On 12.01.2021 06:03, Artem Lapkin wrote: > Fix reading built-in ethernet MAC address from efuse > > NOTE: MAC is stored in ASCII format, 1bytes = 2characters by 0 offset > > if mac from efuse not valid we use meson_generate_serial_ethaddr > > NOTE: remake odroid-n2.c variant from Neil Armstrong > > Signed-off-by: Artem Lapkin First of all, thanks pointing again at this issue. I've implemented reading of MAC address from EFUSE for VIM boards and I was convinced that it is stored in binary format. I've based my assumptions on the vendor code, especially the message from the vendor kernel: [ 4.028236] efusekeynum: 1 [ 4.031072] efusekeyname: mac offset: 0 size: 6 [ 4.037542] efuse efuse: probe OK! and the vendors dts: https://github.com/khadas/linux/blob/khadas-vims-4.9.y/arch/arm64/boot/dts/amlogic/kvim3_linux.dts#L506 which both points that the EFUSE key has only 6 bytes, what means binary format. I didn't check it further what is really stored there. Now I checked again and it looks that the DTS (and thus vendor's kernel message) is incorrect, as the MAC is stored in ASCII and occupies 12 bytes in efuse. One can check that with vendor's kernel: # cat /sys/class/efuse/userdata 0x00: 43 38 36 33 31 34 37 30 41 38 44 37 00 00 00 00 0x10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... This means that your patch is correct, although I would change it a bit. BTW, the Odroid N2/C4 boards don't have MAC stored explicitly in the EFUSE, but the boards UUID. The original code use the last bytes of the UUID as the MAC address. > --- > board/amlogic/vim3/vim3.c | 22 +++--- > 1 file changed, 19 insertions(+), 3 deletions(-) > > diff --git a/board/amlogic/vim3/vim3.c b/board/amlogic/vim3/vim3.c > index 824fff8262..87d9fe1f02 100644 > --- a/board/amlogic/vim3/vim3.c > +++ b/board/amlogic/vim3/vim3.c > @@ -139,26 +139,42 @@ int meson_ft_board_setup(void *blob, struct bd_info *bd) > } > > #define EFUSE_MAC_OFFSET0 > -#define EFUSE_MAC_SIZE 6 > +#define EFUSE_MAC_SIZE 12 > +#define MAC_ADDR_LEN 6 > > int misc_init_r(void) > { > - uint8_t mac_addr[EFUSE_MAC_SIZE]; > + uint8_t mac_addr[MAC_ADDR_LEN]; > + char efuse_mac_addr[EFUSE_MAC_SIZE], tmp[3]; > ssize_t len; > > meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0); > > if (!eth_env_get_enetaddr("ethaddr", mac_addr)) { > len = meson_sm_read_efuse(EFUSE_MAC_OFFSET, > - mac_addr, EFUSE_MAC_SIZE); > + efuse_mac_addr, EFUSE_MAC_SIZE); > if (len != EFUSE_MAC_SIZE) > return 0; > > + /* MAC is stored in ASCII format, 1bytes = 2characters */ > + for (int i = 0; i < 6; i++) { > + tmp[0] = efuse_mac_addr[i * 2]; > + tmp[1] = efuse_mac_addr[i * 2 + 1]; > + tmp[2] = '\0'; > + mac_addr[i] = simple_strtoul(tmp, NULL, 16); > + } > + > if (is_valid_ethaddr(mac_addr)) > eth_env_set_enetaddr("ethaddr", mac_addr); > else > meson_generate_serial_ethaddr(); Now the above code is the same as for Odroid N2/C4, so it can be moved to arch/arm/mach-meson/board-common.c, maybe as meson_read_efuse_mac_addr() with the offset as parameter, so it can be directly used by Odroids and VIMs. > + > + eth_env_get_enetaddr("ethaddr", mac_addr); > + printf("[i] setup onboard mac %02X:%02X:%02X:%02X:%02X:%02X\n", > + mac_addr[0],mac_addr[1],mac_addr[2], > + mac_addr[3],mac_addr[4],mac_addr[5]); I'm not really convinced that this message has to be displayed. If so, then use "%pM" for printing MAC address. > } > > return 0; > } > + Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
[PATCH v3 0/6] Add MBR partition table creation and verify command
Hi All, This patchset adds 'mbr' command to let one to create or verify MBR (Master Boot Record) partition layout based on the provided text description. This can be used in scripts to help system flashing tools/scripts to ensure proper partition layout. It has been inspired by the 'gpt' command already present in u-boot. Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v3: - fixed minor issues in the docs v2: https://lists.denx.de/pipermail/u-boot/2020-December/435689.html - added docs and minor fixes in the code style v1: https://lists.denx.de/pipermail/u-boot/2020-December/435208.html - initial version Patch summary: Marek Szyprowski (6): disk: dos: rename write_mbr_partition to write_mbr_sector disk: dos: add some defines for the hardcoded numbers disk: dos: use generic macro for unaligned le32 access disk: dos: make some functions static disk: dos: add code for creating MBR partition layout cmd: Add MBR partition layout control utility cmd/Kconfig | 8 + cmd/Makefile | 1 + cmd/mbr.c | 314 ++ disk/part_dos.c | 207 ++--- disk/part_dos.h | 5 + doc/usage/index.rst | 1 + doc/usage/mbr.rst | 93 +++ drivers/fastboot/fb_mmc.c | 2 +- include/part.h| 9 +- 9 files changed, 612 insertions(+), 28 deletions(-) create mode 100644 cmd/mbr.c create mode 100644 doc/usage/mbr.rst -- 2.17.1
[PATCH v3 4/6] disk: dos: make some functions static
Make functions not used outside this file static. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 3b79b9b1b8..2c4ad0b6ba 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -302,13 +302,13 @@ static int part_get_info_extended(struct blk_desc *dev_desc, return -1; } -void part_print_dos(struct blk_desc *dev_desc) +static void part_print_dos(struct blk_desc *dev_desc) { printf("Part\tStart Sector\tNum Sectors\tUUID\t\tType\n"); print_partition_extended(dev_desc, 0, 0, 1, 0); } -int part_get_info_dos(struct blk_desc *dev_desc, int part, +static int part_get_info_dos(struct blk_desc *dev_desc, int part, struct disk_partition *info) { return part_get_info_extended(dev_desc, 0, 0, 1, part, info, 0); -- 2.17.1
[PATCH v3 6/6] cmd: Add MBR partition layout control utility
Add a 'mbr' command to let users create or verify MBR partition layout based on the provided text description. The partition layout is alternatively read from the 'mbr_parts' environment variable. This can be used in scripts to help system image flashing tools to ensure proper partition layout. The syntax of the text description of the partition list is similar to the one used by the 'gpt' command. Supported parameters are: name (currently ignored), start (partition start offset in bytes), size (in bytes or '-' to expand it to the whole free area), bootable (boolean flag) and id (MBR partition type). If one wants to create more than 4 partitions, an 'Extended' primary partition (with 0x05 ID) has to be explicitely provided as a one of the first 4 entries. Here is an example how to create a 6 partitions (3 on the 'extended volume'), some of the predefined sizes: > setenv mbr_parts 'name=boot,start=4M,size=128M,bootable,id=0x0e; name=rootfs,size=3072M,id=0x83; name=system-data,size=512M,id=0x83; name=[ext],size=-,id=0x05; name=user,size=-,id=0x83; name=modules,size=100M,id=0x83; name=ramdisk,size=8M,id=0x83' > mbr write mmc 0 Signed-off-by: Marek Szyprowski --- cmd/Kconfig | 8 ++ cmd/Makefile| 1 + cmd/mbr.c | 314 doc/usage/index.rst | 1 + doc/usage/mbr.rst | 93 + 5 files changed, 417 insertions(+) create mode 100644 cmd/mbr.c create mode 100644 doc/usage/mbr.rst diff --git a/cmd/Kconfig b/cmd/Kconfig index 1595de999b..2c3358e359 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1025,6 +1025,14 @@ config CMD_LSBLK Print list of available block device drivers, and for each, the list of known block devices. +config CMD_MBR + bool "MBR (Master Boot Record) command" + select DOS_PARTITION + select HAVE_BLOCK_DEVICE + help + Enable the 'mbr' command to ready and write MBR (Master Boot Record) + style partition tables. + config CMD_MISC bool "misc" depends on MISC diff --git a/cmd/Makefile b/cmd/Makefile index dd86675bf2..41379d9a0e 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -178,6 +178,7 @@ obj-$(CONFIG_CMD_ZFS) += zfs.o obj-$(CONFIG_CMD_DFU) += dfu.o obj-$(CONFIG_CMD_GPT) += gpt.o +obj-$(CONFIG_CMD_MBR) += mbr.o obj-$(CONFIG_CMD_ETHSW) += ethsw.o obj-$(CONFIG_CMD_AXI) += axi.o obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o diff --git a/cmd/mbr.c b/cmd/mbr.c new file mode 100644 index 00..da2e3a4722 --- /dev/null +++ b/cmd/mbr.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * cmd_mbr.c -- MBR (Master Boot Record) handling command + * + * Copyright (C) 2020 Samsung Electronics + * author: Marek Szyprowski + * + * based on the gpt command. + */ + +#include +#include +#include +#include +#include + +/** + * extract_val() - Extract a value from the key=value pair list + * @str: pointer to string with key=values pairs + * @key: pointer to the key to search for + * + * The list of parameters is come separated, only a value for + * the given key is returend. + * + * Function allocates memory for the value, remember to free! + * + * Return: Pointer to allocated string with the value. + */ +static char *extract_val(const char *str, const char *key) +{ + char *v, *k; + char *s, *strcopy; + char *new = NULL; + + strcopy = strdup(str); + if (strcopy == NULL) + return NULL; + + s = strcopy; + while (s) { + v = strsep(, ","); + if (!v) + break; + k = strsep(, "="); + if (!k) + break; + if (strcmp(k, key) == 0) { + new = strdup(v); + break; + } + } + + free(strcopy); + + return new; +} + +/** + * found_key() - Search for a key without a value in the parameter list + * @str: pointer to string with key + * @key: pointer to the key to search for + * + * The list of parameters is come separated. + * + * Return: True if key has been found. + */ +static bool found_key(const char *str, const char *key) +{ + char *k; + char *s, *strcopy; + bool result = false; + + strcopy = strdup(str); + if (!strcopy) + return NULL; + + s = strcopy; + while (s) { + k = strsep(, ","); + if (!k) + break; + if (strcmp(k, key) == 0) { + result = true; + break; + } + } + + free(strcopy); + + return result; +} + +static int str_to_partitions(const char *str_part, int blksz, + unsigned long *disk_uuid, struct disk_partition **partitions, + int *parts_count) +{ + char *tok, *str, *s; + int i; + char *val, *p; +
[PATCH v3 5/6] disk: dos: add code for creating MBR partition layout
Add a code for creating and writing MBR partition layout. The code generates similar layout of EBRs (Exteneded Block Records) and logical volumes as Linux's fdisk utility. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 167 disk/part_dos.h | 2 + include/part.h | 5 ++ 3 files changed, 174 insertions(+) diff --git a/disk/part_dos.c b/disk/part_dos.c index 2c4ad0b6ba..f77f927995 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -319,6 +319,173 @@ int is_valid_dos_buf(void *buf) return test_block_type(buf) == DOS_MBR ? 0 : -1; } +#if CONFIG_IS_ENABLED(CMD_MBR) +static void lba_to_chs(lbaint_t lba, unsigned char *rc, unsigned char *rh, + unsigned char *rs) +{ + unsigned int c, h, s; + /* use fixed CHS geometry */ + unsigned int sectpertrack = 63; + unsigned int heads = 255; + + c = (lba + 1) / sectpertrack / heads; + h = (lba + 1) / sectpertrack - c * heads; + s = (lba + 1) - (c * heads + h) * sectpertrack; + + if (c > 1023) { + c = 1023; + h = 254; + s = 63; + } + + *rc = c & 0xff; + *rh = h; + *rs = s + ((c & 0x300) >> 2); +} + +static void mbr_fill_pt_entry(dos_partition_t *pt, lbaint_t start, + lbaint_t relative, lbaint_t size, uchar sys_ind, bool bootable) +{ + pt->boot_ind = bootable ? 0x80 : 0x00; + pt->sys_ind = sys_ind; + lba_to_chs(start, >cyl, >head, >sector); + lba_to_chs(start + size - 1, >end_cyl, >end_head, >end_sector); + put_unaligned_le32(relative, >start4); + put_unaligned_le32(size, >size4); +} + +int write_mbr_partitions(struct blk_desc *dev, + struct disk_partition *p, int count, unsigned int disksig) +{ + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev->blksz); + lbaint_t ext_part_start = 0, ext_part_size = 0, ext_part_sect = 0; + dos_partition_t *pt; + int i; + + memset(buffer, 0, dev->blksz); + buffer[DOS_PART_MAGIC_OFFSET] = 0x55; + buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa; + put_unaligned_le32(disksig, [DOS_PART_DISKSIG_OFFSET]); + pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); + + /* create all primary partitions */ + for (i = 0; i < 4 && i < count; i++, pt++) { + mbr_fill_pt_entry(pt, p[i].start, p[i].start, p[i].size, + p[i].sys_ind, p[i].bootable); + if (is_extended(p[i].sys_ind)) { + ext_part_start = p[i].start; + ext_part_size = p[i].size; + ext_part_sect = p[i].start; + } + } + + if (i < count && !ext_part_start) { + printf("%s: extended partition is needed for more than 4 partitions\n", + __func__); + return -1; + } + + /* write MBR */ + if (blk_dwrite(dev, 0, 1, buffer) != 1) { + printf("%s: failed writing 'MBR' (1 blks at 0x0)\n", + __func__); + return -1; + } + + /* create extended volumes */ + for (; i < count; i++) { + lbaint_t next_ebr = 0; + + memset(buffer, 0, dev->blksz); + buffer[DOS_PART_MAGIC_OFFSET] = 0x55; + buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa; + pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); + + mbr_fill_pt_entry(pt, p[i].start, p[i].start - ext_part_sect, + p[i].size, p[i].sys_ind, p[i].bootable); + + if (i + 1 < count) { + pt++; + next_ebr = p[i].start + p[i].size; + mbr_fill_pt_entry(pt, next_ebr, + next_ebr - ext_part_start, + p[i+1].start + p[i+1].size - next_ebr, + DOS_PART_TYPE_EXTENDED, 0); + } + + /* write EBR */ + if (blk_dwrite(dev, ext_part_sect, 1, buffer) != 1) { + printf("%s: failed writing 'EBR' (1 blks at 0x%lx)\n", + __func__, ext_part_sect); + return -1; + } + ext_part_sect = next_ebr; + } + + return 0; +} + +int layout_mbr_partitions(struct disk_partition *p, int count, + lbaint_t total_sectors) +{ + struct disk_partition *ext = NULL; + int i, j; + lbaint_t ext_vol_start; + + /* calculate primary partitions start and size if needed */ + if (!p[0].start) + p[0].start = DOS_PART_DEFAULT_GAP; + for (i = 0; i < 4 && i < count; i+
[PATCH v3 2/6] disk: dos: add some defines for the hardcoded numbers
Add some handy defines for some hardcoded magic numbers related to extended partition handling. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 6 +++--- disk/part_dos.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index ef706fb59c..20d35dc9cd 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -42,9 +42,9 @@ static inline unsigned int le32_to_int(unsigned char *le32) static inline int is_extended(int part_type) { -return (part_type == 0x5 || - part_type == 0xf || - part_type == 0x85); +return (part_type == DOS_PART_TYPE_EXTENDED || + part_type == DOS_PART_TYPE_EXTENDED_LBA || + part_type == DOS_PART_TYPE_EXTENDED_LINUX); } static int get_bootable(dos_partition_t *p) diff --git a/disk/part_dos.h b/disk/part_dos.h index 434b021ae8..dd909a9317 100644 --- a/disk/part_dos.h +++ b/disk/part_dos.h @@ -15,6 +15,9 @@ #define DOS_PBR_MEDIA_TYPE_OFFSET 0x15 #define DOS_MBR0 #define DOS_PBR1 +#define DOS_PART_TYPE_EXTENDED 0x05 +#define DOS_PART_TYPE_EXTENDED_LBA 0x0F +#define DOS_PART_TYPE_EXTENDED_LINUX 0x85 typedef struct dos_partition { unsigned char boot_ind; /* 0x80 - active */ -- 2.17.1
[PATCH v3 1/6] disk: dos: rename write_mbr_partition to write_mbr_sector
write_mbr_partition() function name is a bit misleading, so rename it to write_mbr_sector(). This is a preparation for adding code for writing a complete MBR partition layout. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 2 +- drivers/fastboot/fb_mmc.c | 2 +- include/part.h| 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 04f53106f7..ef706fb59c 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -329,7 +329,7 @@ int is_valid_dos_buf(void *buf) return test_block_type(buf) == DOS_MBR ? 0 : -1; } -int write_mbr_partition(struct blk_desc *dev_desc, void *buf) +int write_mbr_sector(struct blk_desc *dev_desc, void *buf) { if (is_valid_dos_buf(buf)) return -1; diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index ae8e8e512f..4e26cef941 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -508,7 +508,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer, fastboot_fail("invalid MBR partition", response); return; } - if (write_mbr_partition(dev_desc, download_buffer)) { + if (write_mbr_sector(dev_desc, download_buffer)) { printf("%s: writing MBR partition failed\n", __func__); fastboot_fail("writing MBR partition failed", response); diff --git a/include/part.h b/include/part.h index 55be724d20..67b8b2a5cc 100644 --- a/include/part.h +++ b/include/part.h @@ -465,14 +465,14 @@ int get_disk_guid(struct blk_desc *dev_desc, char *guid); int is_valid_dos_buf(void *buf); /** - * write_mbr_partition() - write DOS MBR + * write_mbr_sector() - write DOS MBR * * @param dev_desc - block device descriptor * @param buf - buffer which contains the MBR * * @return - '0' on success, otherwise error */ -int write_mbr_partition(struct blk_desc *dev_desc, void *buf); +int write_mbr_sector(struct blk_desc *dev_desc, void *buf); #endif -- 2.17.1
[PATCH v3 3/6] disk: dos: use generic macro for unaligned le32 access
Use a generic helper for reading LE32 integers. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 28 +--- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 20d35dc9cd..3b79b9b1b8 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "part_dos.h" #include @@ -29,17 +30,6 @@ * to use large numbers of partitions */ #define MAX_EXT_PARTS 256 -/* Convert char[4] in little endian format to the host format integer - */ -static inline unsigned int le32_to_int(unsigned char *le32) -{ -return ((le32[3] << 24) + - (le32[2] << 16) + - (le32[1] << 8) + -le32[0] - ); -} - static inline int is_extended(int part_type) { return (part_type == DOS_PART_TYPE_EXTENDED || @@ -61,8 +51,8 @@ static int get_bootable(dos_partition_t *p) static void print_one_part(dos_partition_t *p, lbaint_t ext_part_sector, int part_num, unsigned int disksig) { - lbaint_t lba_start = ext_part_sector + le32_to_int (p->start4); - lbaint_t lba_size = le32_to_int (p->size4); + lbaint_t lba_start = ext_part_sector + get_unaligned_le32(p->start4); + lbaint_t lba_size = get_unaligned_le32(p->size4); printf("%3d\t%-10" LBAFlength "u\t%-10" LBAFlength "u\t%08x-%02x\t%02x%s%s\n", @@ -171,7 +161,7 @@ static void print_partition_extended(struct blk_desc *dev_desc, } if (!ext_part_sector) - disksig = le32_to_int([DOS_PART_DISKSIG_OFFSET]); + disksig = get_unaligned_le32([DOS_PART_DISKSIG_OFFSET]); /* Print all primary/logical partitions */ pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); @@ -198,7 +188,7 @@ static void print_partition_extended(struct blk_desc *dev_desc, for (i = 0; i < 4; i++, pt++) { if (is_extended (pt->sys_ind)) { lbaint_t lba_start - = le32_to_int (pt->start4) + relative; + = get_unaligned_le32 (pt->start4) + relative; print_partition_extended(dev_desc, lba_start, ext_part_sector == 0 ? lba_start : relative, @@ -244,7 +234,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc, #if CONFIG_IS_ENABLED(PARTITION_UUIDS) if (!ext_part_sector) - disksig = le32_to_int([DOS_PART_DISKSIG_OFFSET]); + disksig = get_unaligned_le32([DOS_PART_DISKSIG_OFFSET]); #endif /* Print all primary/logical partitions */ @@ -260,8 +250,8 @@ static int part_get_info_extended(struct blk_desc *dev_desc, (ext_part_sector == 0 || is_extended(pt->sys_ind) == 0)) { info->blksz = DOS_PART_DEFAULT_SECTOR; info->start = (lbaint_t)(ext_part_sector + - le32_to_int(pt->start4)); - info->size = (lbaint_t)le32_to_int(pt->size4); + get_unaligned_le32(pt->start4)); + info->size = (lbaint_t)get_unaligned_le32(pt->size4); part_set_generic_name(dev_desc, part_num, (char *)info->name); /* sprintf(info->type, "%d, pt->sys_ind); */ @@ -286,7 +276,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc, for (i = 0; i < 4; i++, pt++) { if (is_extended (pt->sys_ind)) { lbaint_t lba_start - = le32_to_int (pt->start4) + relative; + = get_unaligned_le32 (pt->start4) + relative; return part_get_info_extended(dev_desc, lba_start, ext_part_sector == 0 ? lba_start : relative, -- 2.17.1
[PATCH v2 0/6] Add MBR partition table creation and verify command
Hi All, This patchset adds 'mbr' command to let one create or verify MBR (Master Boot Record) partition layout based on the provided text description. This can be used in scripts to help system flashing tools/scripts to ensure proper partition layout. It has been inspired by the 'gpt' command already present in u-boot. Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v2: - added docs and minor fixes in the code style v1: https://lists.denx.de/pipermail/u-boot/2020-December/435208.html - initial version Patch summary: Marek Szyprowski (6): disk: dos: rename write_mbr_partition to write_mbr_sector disk: dos: add some defines for the hardcoded numbers disk: dos: use generic macro for unaligned le32 access disk: dos: make some functions static disk: dos: add code for creating MBR partition layout cmd: Add MBR partition layout control utility cmd/Kconfig | 8 + cmd/Makefile | 1 + cmd/mbr.c | 314 ++ disk/part_dos.c | 207 ++--- disk/part_dos.h | 5 + doc/usage/index.rst | 1 + doc/usage/mbr.rst | 93 +++ drivers/fastboot/fb_mmc.c | 2 +- include/part.h| 9 +- 9 files changed, 612 insertions(+), 28 deletions(-) create mode 100644 cmd/mbr.c create mode 100644 doc/usage/mbr.rst -- 2.17.1
[PATCH v2 6/6] cmd: Add MBR partition layout control utility
Add a 'mbr' command to let user create or verify MBR partition layout based on the provided text description. The partition layout is altearnatively read from 'mbr_parts' environment variable. This can be used in scripts to help system image flashing tools to ensure proper partition layout. The syntax of the text description of the partition list is similar to the one used by the 'gpt' command. Supported parameters are: name (currently ignored), start (partition start offset in bytes), size (in bytes or '-' to expand it to the whole free area), bootable (boolean flag) and id (MBR partition system ID). If one wants to create more than 4 partitions, an 'Extended' primary partition (with 0x05 ID) has to be explicitely provided as a one of the first 4 entries. Here is the example how to create a 6 partitions (3 on the 'extended volume'), some of the predefined sizes: > setenv mbr_parts 'name=boot,start=4M,size=128M,bootable,id=0x0e; name=rootfs,size=3072M,id=0x83; name=system-data,size=512M,id=0x83; name=[ext],size=-,id=0x05; name=user,size=-,id=0x83; name=modules,size=100M,id=0x83; name=ramdisk,size=8M,id=0x83' > mbr write mmc 0 Signed-off-by: Marek Szyprowski --- cmd/Kconfig | 8 ++ cmd/Makefile| 1 + cmd/mbr.c | 314 doc/usage/index.rst | 1 + doc/usage/mbr.rst | 93 + 5 files changed, 417 insertions(+) create mode 100644 cmd/mbr.c create mode 100644 doc/usage/mbr.rst diff --git a/cmd/Kconfig b/cmd/Kconfig index 1595de999b..2c3358e359 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1025,6 +1025,14 @@ config CMD_LSBLK Print list of available block device drivers, and for each, the list of known block devices. +config CMD_MBR + bool "MBR (Master Boot Record) command" + select DOS_PARTITION + select HAVE_BLOCK_DEVICE + help + Enable the 'mbr' command to ready and write MBR (Master Boot Record) + style partition tables. + config CMD_MISC bool "misc" depends on MISC diff --git a/cmd/Makefile b/cmd/Makefile index dd86675bf2..41379d9a0e 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -178,6 +178,7 @@ obj-$(CONFIG_CMD_ZFS) += zfs.o obj-$(CONFIG_CMD_DFU) += dfu.o obj-$(CONFIG_CMD_GPT) += gpt.o +obj-$(CONFIG_CMD_MBR) += mbr.o obj-$(CONFIG_CMD_ETHSW) += ethsw.o obj-$(CONFIG_CMD_AXI) += axi.o obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o diff --git a/cmd/mbr.c b/cmd/mbr.c new file mode 100644 index 00..da2e3a4722 --- /dev/null +++ b/cmd/mbr.c @@ -0,0 +1,314 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * cmd_mbr.c -- MBR (Master Boot Record) handling command + * + * Copyright (C) 2020 Samsung Electronics + * author: Marek Szyprowski + * + * based on the gpt command. + */ + +#include +#include +#include +#include +#include + +/** + * extract_val() - Extract a value from the key=value pair list + * @str: pointer to string with key=values pairs + * @key: pointer to the key to search for + * + * The list of parameters is come separated, only a value for + * the given key is returend. + * + * Function allocates memory for the value, remember to free! + * + * Return: Pointer to allocated string with the value. + */ +static char *extract_val(const char *str, const char *key) +{ + char *v, *k; + char *s, *strcopy; + char *new = NULL; + + strcopy = strdup(str); + if (strcopy == NULL) + return NULL; + + s = strcopy; + while (s) { + v = strsep(, ","); + if (!v) + break; + k = strsep(, "="); + if (!k) + break; + if (strcmp(k, key) == 0) { + new = strdup(v); + break; + } + } + + free(strcopy); + + return new; +} + +/** + * found_key() - Search for a key without a value in the parameter list + * @str: pointer to string with key + * @key: pointer to the key to search for + * + * The list of parameters is come separated. + * + * Return: True if key has been found. + */ +static bool found_key(const char *str, const char *key) +{ + char *k; + char *s, *strcopy; + bool result = false; + + strcopy = strdup(str); + if (!strcopy) + return NULL; + + s = strcopy; + while (s) { + k = strsep(, ","); + if (!k) + break; + if (strcmp(k, key) == 0) { + result = true; + break; + } + } + + free(strcopy); + + return result; +} + +static int str_to_partitions(const char *str_part, int blksz, + unsigned long *disk_uuid, struct disk_partition **partitions, + int *parts_count) +{ + char *tok, *str, *s; + int i; + char *val, *p; +
[PATCH v2 3/6] disk: dos: use generic macro for unaligned le32 access
Use a generic helper for reading LE32 integers. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 28 +--- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 20d35dc9cd..3b79b9b1b8 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "part_dos.h" #include @@ -29,17 +30,6 @@ * to use large numbers of partitions */ #define MAX_EXT_PARTS 256 -/* Convert char[4] in little endian format to the host format integer - */ -static inline unsigned int le32_to_int(unsigned char *le32) -{ -return ((le32[3] << 24) + - (le32[2] << 16) + - (le32[1] << 8) + -le32[0] - ); -} - static inline int is_extended(int part_type) { return (part_type == DOS_PART_TYPE_EXTENDED || @@ -61,8 +51,8 @@ static int get_bootable(dos_partition_t *p) static void print_one_part(dos_partition_t *p, lbaint_t ext_part_sector, int part_num, unsigned int disksig) { - lbaint_t lba_start = ext_part_sector + le32_to_int (p->start4); - lbaint_t lba_size = le32_to_int (p->size4); + lbaint_t lba_start = ext_part_sector + get_unaligned_le32(p->start4); + lbaint_t lba_size = get_unaligned_le32(p->size4); printf("%3d\t%-10" LBAFlength "u\t%-10" LBAFlength "u\t%08x-%02x\t%02x%s%s\n", @@ -171,7 +161,7 @@ static void print_partition_extended(struct blk_desc *dev_desc, } if (!ext_part_sector) - disksig = le32_to_int([DOS_PART_DISKSIG_OFFSET]); + disksig = get_unaligned_le32([DOS_PART_DISKSIG_OFFSET]); /* Print all primary/logical partitions */ pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); @@ -198,7 +188,7 @@ static void print_partition_extended(struct blk_desc *dev_desc, for (i = 0; i < 4; i++, pt++) { if (is_extended (pt->sys_ind)) { lbaint_t lba_start - = le32_to_int (pt->start4) + relative; + = get_unaligned_le32 (pt->start4) + relative; print_partition_extended(dev_desc, lba_start, ext_part_sector == 0 ? lba_start : relative, @@ -244,7 +234,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc, #if CONFIG_IS_ENABLED(PARTITION_UUIDS) if (!ext_part_sector) - disksig = le32_to_int([DOS_PART_DISKSIG_OFFSET]); + disksig = get_unaligned_le32([DOS_PART_DISKSIG_OFFSET]); #endif /* Print all primary/logical partitions */ @@ -260,8 +250,8 @@ static int part_get_info_extended(struct blk_desc *dev_desc, (ext_part_sector == 0 || is_extended(pt->sys_ind) == 0)) { info->blksz = DOS_PART_DEFAULT_SECTOR; info->start = (lbaint_t)(ext_part_sector + - le32_to_int(pt->start4)); - info->size = (lbaint_t)le32_to_int(pt->size4); + get_unaligned_le32(pt->start4)); + info->size = (lbaint_t)get_unaligned_le32(pt->size4); part_set_generic_name(dev_desc, part_num, (char *)info->name); /* sprintf(info->type, "%d, pt->sys_ind); */ @@ -286,7 +276,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc, for (i = 0; i < 4; i++, pt++) { if (is_extended (pt->sys_ind)) { lbaint_t lba_start - = le32_to_int (pt->start4) + relative; + = get_unaligned_le32 (pt->start4) + relative; return part_get_info_extended(dev_desc, lba_start, ext_part_sector == 0 ? lba_start : relative, -- 2.17.1
[PATCH v2 5/6] disk: dos: add code for creating MBR partition layout
Add a code for creating and writing MBR partition layout. The code generates similar layout of EBRs (Exteneded Block Records) and logical volumes as Linux's fdisk utility. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 167 disk/part_dos.h | 2 + include/part.h | 5 ++ 3 files changed, 174 insertions(+) diff --git a/disk/part_dos.c b/disk/part_dos.c index 2c4ad0b6ba..f77f927995 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -319,6 +319,173 @@ int is_valid_dos_buf(void *buf) return test_block_type(buf) == DOS_MBR ? 0 : -1; } +#if CONFIG_IS_ENABLED(CMD_MBR) +static void lba_to_chs(lbaint_t lba, unsigned char *rc, unsigned char *rh, + unsigned char *rs) +{ + unsigned int c, h, s; + /* use fixed CHS geometry */ + unsigned int sectpertrack = 63; + unsigned int heads = 255; + + c = (lba + 1) / sectpertrack / heads; + h = (lba + 1) / sectpertrack - c * heads; + s = (lba + 1) - (c * heads + h) * sectpertrack; + + if (c > 1023) { + c = 1023; + h = 254; + s = 63; + } + + *rc = c & 0xff; + *rh = h; + *rs = s + ((c & 0x300) >> 2); +} + +static void mbr_fill_pt_entry(dos_partition_t *pt, lbaint_t start, + lbaint_t relative, lbaint_t size, uchar sys_ind, bool bootable) +{ + pt->boot_ind = bootable ? 0x80 : 0x00; + pt->sys_ind = sys_ind; + lba_to_chs(start, >cyl, >head, >sector); + lba_to_chs(start + size - 1, >end_cyl, >end_head, >end_sector); + put_unaligned_le32(relative, >start4); + put_unaligned_le32(size, >size4); +} + +int write_mbr_partitions(struct blk_desc *dev, + struct disk_partition *p, int count, unsigned int disksig) +{ + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev->blksz); + lbaint_t ext_part_start = 0, ext_part_size = 0, ext_part_sect = 0; + dos_partition_t *pt; + int i; + + memset(buffer, 0, dev->blksz); + buffer[DOS_PART_MAGIC_OFFSET] = 0x55; + buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa; + put_unaligned_le32(disksig, [DOS_PART_DISKSIG_OFFSET]); + pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); + + /* create all primary partitions */ + for (i = 0; i < 4 && i < count; i++, pt++) { + mbr_fill_pt_entry(pt, p[i].start, p[i].start, p[i].size, + p[i].sys_ind, p[i].bootable); + if (is_extended(p[i].sys_ind)) { + ext_part_start = p[i].start; + ext_part_size = p[i].size; + ext_part_sect = p[i].start; + } + } + + if (i < count && !ext_part_start) { + printf("%s: extended partition is needed for more than 4 partitions\n", + __func__); + return -1; + } + + /* write MBR */ + if (blk_dwrite(dev, 0, 1, buffer) != 1) { + printf("%s: failed writing 'MBR' (1 blks at 0x0)\n", + __func__); + return -1; + } + + /* create extended volumes */ + for (; i < count; i++) { + lbaint_t next_ebr = 0; + + memset(buffer, 0, dev->blksz); + buffer[DOS_PART_MAGIC_OFFSET] = 0x55; + buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa; + pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); + + mbr_fill_pt_entry(pt, p[i].start, p[i].start - ext_part_sect, + p[i].size, p[i].sys_ind, p[i].bootable); + + if (i + 1 < count) { + pt++; + next_ebr = p[i].start + p[i].size; + mbr_fill_pt_entry(pt, next_ebr, + next_ebr - ext_part_start, + p[i+1].start + p[i+1].size - next_ebr, + DOS_PART_TYPE_EXTENDED, 0); + } + + /* write EBR */ + if (blk_dwrite(dev, ext_part_sect, 1, buffer) != 1) { + printf("%s: failed writing 'EBR' (1 blks at 0x%lx)\n", + __func__, ext_part_sect); + return -1; + } + ext_part_sect = next_ebr; + } + + return 0; +} + +int layout_mbr_partitions(struct disk_partition *p, int count, + lbaint_t total_sectors) +{ + struct disk_partition *ext = NULL; + int i, j; + lbaint_t ext_vol_start; + + /* calculate primary partitions start and size if needed */ + if (!p[0].start) + p[0].start = DOS_PART_DEFAULT_GAP; + for (i = 0; i < 4 && i < count; i+
[PATCH v2 4/6] disk: dos: make some functions static
Make functions not used outside this file static. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 3b79b9b1b8..2c4ad0b6ba 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -302,13 +302,13 @@ static int part_get_info_extended(struct blk_desc *dev_desc, return -1; } -void part_print_dos(struct blk_desc *dev_desc) +static void part_print_dos(struct blk_desc *dev_desc) { printf("Part\tStart Sector\tNum Sectors\tUUID\t\tType\n"); print_partition_extended(dev_desc, 0, 0, 1, 0); } -int part_get_info_dos(struct blk_desc *dev_desc, int part, +static int part_get_info_dos(struct blk_desc *dev_desc, int part, struct disk_partition *info) { return part_get_info_extended(dev_desc, 0, 0, 1, part, info, 0); -- 2.17.1
[PATCH v2 1/6] disk: dos: rename write_mbr_partition to write_mbr_sector
write_mbr_partition() function name is a bit misleading, so rename it to write_mbr_sector(). This is a preparation for adding code for writing a complete MBR partition layout. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 2 +- drivers/fastboot/fb_mmc.c | 2 +- include/part.h| 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 04f53106f7..ef706fb59c 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -329,7 +329,7 @@ int is_valid_dos_buf(void *buf) return test_block_type(buf) == DOS_MBR ? 0 : -1; } -int write_mbr_partition(struct blk_desc *dev_desc, void *buf) +int write_mbr_sector(struct blk_desc *dev_desc, void *buf) { if (is_valid_dos_buf(buf)) return -1; diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index ae8e8e512f..4e26cef941 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -508,7 +508,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer, fastboot_fail("invalid MBR partition", response); return; } - if (write_mbr_partition(dev_desc, download_buffer)) { + if (write_mbr_sector(dev_desc, download_buffer)) { printf("%s: writing MBR partition failed\n", __func__); fastboot_fail("writing MBR partition failed", response); diff --git a/include/part.h b/include/part.h index 55be724d20..67b8b2a5cc 100644 --- a/include/part.h +++ b/include/part.h @@ -465,14 +465,14 @@ int get_disk_guid(struct blk_desc *dev_desc, char *guid); int is_valid_dos_buf(void *buf); /** - * write_mbr_partition() - write DOS MBR + * write_mbr_sector() - write DOS MBR * * @param dev_desc - block device descriptor * @param buf - buffer which contains the MBR * * @return - '0' on success, otherwise error */ -int write_mbr_partition(struct blk_desc *dev_desc, void *buf); +int write_mbr_sector(struct blk_desc *dev_desc, void *buf); #endif -- 2.17.1
[PATCH v2 2/6] disk: dos: add some defines for the hardcoded numbers
Add some handy defines for some hardcoded magic numbers related to extended partition handling. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 6 +++--- disk/part_dos.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index ef706fb59c..20d35dc9cd 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -42,9 +42,9 @@ static inline unsigned int le32_to_int(unsigned char *le32) static inline int is_extended(int part_type) { -return (part_type == 0x5 || - part_type == 0xf || - part_type == 0x85); +return (part_type == DOS_PART_TYPE_EXTENDED || + part_type == DOS_PART_TYPE_EXTENDED_LBA || + part_type == DOS_PART_TYPE_EXTENDED_LINUX); } static int get_bootable(dos_partition_t *p) diff --git a/disk/part_dos.h b/disk/part_dos.h index 434b021ae8..dd909a9317 100644 --- a/disk/part_dos.h +++ b/disk/part_dos.h @@ -15,6 +15,9 @@ #define DOS_PBR_MEDIA_TYPE_OFFSET 0x15 #define DOS_MBR0 #define DOS_PBR1 +#define DOS_PART_TYPE_EXTENDED 0x05 +#define DOS_PART_TYPE_EXTENDED_LBA 0x0F +#define DOS_PART_TYPE_EXTENDED_LINUX 0x85 typedef struct dos_partition { unsigned char boot_ind; /* 0x80 - active */ -- 2.17.1
[PATCH v2 1/5] dfu: mmc: use the default MMC device if entity specifies it as -1
Use the default MMC device set in the command line if entity specifies it as -1. This allows to use the same dfu_alt_info string for different MMC devices (like embedded eMMC and external SD card if data layout is the same on both devices). Signed-off-by: Marek Szyprowski --- drivers/dfu/dfu_mmc.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 691d01c7eb..784d0ec76b 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -316,7 +316,7 @@ void dfu_free_entity_mmc(struct dfu_entity *dfu) int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) { const char *entity_type; - size_t second_arg; + ssize_t second_arg; size_t third_arg; struct mmc *mmc; @@ -339,7 +339,7 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8, * with default 10. */ - second_arg = simple_strtoul(argv[1], NULL, 0); + second_arg = simple_strtol(argv[1], NULL, 0); third_arg = simple_strtoul(argv[2], NULL, 0); mmc = find_mmc_device(dfu->data.mmc.dev_num); @@ -406,7 +406,8 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) /* if it's NOT a raw write */ if (strcmp(entity_type, "raw")) { - dfu->data.mmc.dev = second_arg; + dfu->data.mmc.dev = (second_arg != -1) ? second_arg : +dfu->data.mmc.dev_num; dfu->data.mmc.part = third_arg; } -- 2.17.1
[PATCH v2 3/5] dfu: add 'SCRIPT' entity
Define a new 'SCRIPT' type for DFU entities. The downloaded data are treated as simple u-boot's scripts and executed with run_command_list() function. Flashing the 'SCRIPT' entity might result in changing the 'dfu_alt_info' environment variable from the flashed script, so add a global variable for tracking the potential need to reinitialize the dfu_alt_info related structures. Signed-off-by: Marek Szyprowski --- doc/README.dfu| 17 - drivers/dfu/dfu.c | 7 ++- drivers/dfu/dfu_mmc.c | 23 +-- include/dfu.h | 3 +++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/doc/README.dfu b/doc/README.dfu index 6cb1cba9d7..eacd5bbfb4 100644 --- a/doc/README.dfu +++ b/doc/README.dfu @@ -17,7 +17,7 @@ Overview: - The access to mediums is done in DFU backends (driver/dfu) Today the supported DFU backends are: - - MMC (RAW or FAT / EXT2 / EXT3 / EXT4 file system / SKIP) + - MMC (RAW or FAT / EXT2 / EXT3 / EXT4 file system / SKIP / SCRIPT) - NAND - RAM - SF (serial flash) @@ -92,6 +92,7 @@ Commands: fat [mmcpart ] file in FAT partition ext4 [mmcpart ] file in EXT4 partition skip 0 0 ignore flashed data + script 0 0execute commands in shell with being the GPT or DOS partition index, with being the eMMC hardware partition number. @@ -116,6 +117,20 @@ Commands: "u-boot-.bin raw 0x80 0x800; u-boot-.bin skip 0 0" +When flashing new system image requires do some more complex things +than just writing data to the storage medium, one can use 'script' +type. Data written to such entity will be executed as a command list +in the u-boot's shell. This for example allows to re-create partition +layout and even set new dfu_alt_info for the newly created paritions. +Such script would look like: + --->8--- + setenv dfu_alt_info ... + setenv mbr_parts ... + mbr write ... + --->8--- +Please note that this means that user will be able to execute any +arbitrary commands just like in the u-boot's shell. + "nand" (raw slc nand device) cmd: dfu 0 nand each element in "dfu_alt_info" = diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index fc32a53323..213a20e7bc 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -26,6 +26,8 @@ static struct hash_algo *dfu_hash_algo; static unsigned long dfu_timeout = 0; #endif +bool dfu_reinit_needed = false; + /* * The purpose of the dfu_flush_callback() function is to * provide callback for dfu user @@ -139,6 +141,8 @@ int dfu_init_env_entities(char *interface, char *devstr) char *env_bkp; int ret = 0; + dfu_reinit_needed = false; + #ifdef CONFIG_SET_DFU_ALT_INFO set_dfu_alt_info(interface, devstr); #endif @@ -614,7 +618,8 @@ const char *dfu_get_dev_type(enum dfu_device_type t) const char *dfu_get_layout(enum dfu_layout l) { const char *const dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", - "EXT3", "EXT4", "RAM_ADDR", "SKIP" }; + "EXT3", "EXT4", "RAM_ADDR", "SKIP", + "SCRIPT" }; return dfu_layout[l]; } diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index d1af11d94c..e63fa84ce4 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -16,6 +16,7 @@ #include #include #include +#include static unsigned char *dfu_file_buf; static u64 dfu_file_buf_len; @@ -206,6 +207,9 @@ int dfu_write_medium_mmc(struct dfu_entity *dfu, case DFU_FS_EXT4: ret = mmc_file_buf_write(dfu, offset, buf, len); break; + case DFU_SCRIPT: + ret = run_command_list(buf, *len, 0); + break; case DFU_SKIP: ret = 0; break; @@ -221,9 +225,21 @@ int dfu_flush_medium_mmc(struct dfu_entity *dfu) { int ret = 0; - if (dfu->layout != DFU_RAW_ADDR) { - /* Do stuff here. */ + switch (dfu->layout) { + case DFU_FS_FAT: + case DFU_FS_EXT4: ret = mmc_file_buf_write_finish(dfu); + break; + case DFU_SCRIPT: + /* script may have changed the dfu_alt_info */ + dfu_reinit_needed = true; + break; + case DFU_RAW_ADDR: + case DFU_SKIP: + break; + default: + printf("%s: Layout (%s) not (yet) supported!\n", __func__, + dfu_get_layout(dfu->layout)); } return ret; @@ -243,6 +259,7 @@ int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size)
[PATCH v2 4/5] dfu: add support for the dfu_alt_info reintialization from the flashed script
Reinitialize DFU USB gadget after flashing the 'SCRIPT' entity to ensure that the potential changes to the 'dfu_alt_info' environment variable are applied. Signed-off-by: Marek Szyprowski --- cmd/dfu.c| 14 +- common/dfu.c | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/cmd/dfu.c b/cmd/dfu.c index 7310595a02..89b1b2268e 100644 --- a/cmd/dfu.c +++ b/cmd/dfu.c @@ -34,6 +34,7 @@ static int do_dfu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) #if defined(CONFIG_DFU_TIMEOUT) || defined(CONFIG_DFU_OVER_TFTP) unsigned long value = 0; #endif + bool retry = false; if (argc >= 4) { interface = argv[2]; @@ -68,7 +69,18 @@ static int do_dfu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) int controller_index = simple_strtoul(usb_controller, NULL, 0); - run_usb_dnl_gadget(controller_index, "usb_dnl_dfu"); + do { + retry = false; + run_usb_dnl_gadget(controller_index, "usb_dnl_dfu"); + + if (dfu_reinit_needed) { + dfu_free_entities(); + ret = dfu_init_env_entities(interface, devstring); + if (ret) + goto done; + retry = true; + } + } while (retry); done: dfu_free_entities(); diff --git a/common/dfu.c b/common/dfu.c index d23cf67f19..16bd1ba588 100644 --- a/common/dfu.c +++ b/common/dfu.c @@ -98,6 +98,9 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget) } #endif + if (dfu_reinit_needed) + goto exit; + WATCHDOG_RESET(); usb_gadget_handle_interrupts(usbctrl_index); } -- 2.17.1
[PATCH v2 5/5] thor: add support for the dfu_alt_info reintialization from the flashed script
Reinitialize dfu_env_entities after flashing the 'SCRIPT' entity to ensure that the potential changes to the 'dfu_alt_info' environment variable are applied. Signed-off-by: Marek Szyprowski --- cmd/thordown.c | 19 --- drivers/usb/gadget/f_thor.c | 3 +++ include/thor.h | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cmd/thordown.c b/cmd/thordown.c index ae20dddfdd..838764ccef 100644 --- a/cmd/thordown.c +++ b/cmd/thordown.c @@ -52,13 +52,18 @@ int do_thor_down(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) goto exit; } - ret = thor_handle(); - if (ret) { - pr_err("THOR failed: %d\n", ret); - ret = CMD_RET_FAILURE; - goto exit; - } - + do { + ret = thor_handle(); + if (ret == THOR_DFU_REINIT_NEEDED) { + dfu_free_entities(); + ret = dfu_init_env_entities(interface, devstring); + } + if (ret) { + pr_err("THOR failed: %d\n", ret); + ret = CMD_RET_FAILURE; + goto exit; + } + } while (ret == 0); exit: g_dnl_unregister(); usb_gadget_release(controller_index); diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index 88fc87f2e9..3e69746ee6 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "f_thor.h" @@ -735,6 +736,8 @@ int thor_handle(void) printf("%s: No data received!\n", __func__); break; } + if (dfu_reinit_needed) + return THOR_DFU_REINIT_NEEDED; } return 0; diff --git a/include/thor.h b/include/thor.h index 62501bda17..ee67ab0a27 100644 --- a/include/thor.h +++ b/include/thor.h @@ -12,6 +12,8 @@ #include +#define THOR_DFU_REINIT_NEEDED 0xFFFE + int thor_handle(void); int thor_init(void); int thor_add(struct usb_configuration *c); -- 2.17.1
[PATCH v2 2/5] dfu: add 'SKIP' entity
From: Jaehoon Chung Define a new 'SKIP' type for the DFU entities. The flashed data for that entity is simply ignored without returning any error values. This allows to have one flashing procedure and images for the different board types or variants, where each board uses only the images relevant to it and skips the rest. This is especially usefull for the THOR protocol, which usually transfers more than one file in a single session. Signed-off-by: Jaehoon Chung Reviewed-by: Minkyu Kang [mszyprow: rephrased commit message and docs for easier reading, changed subject to "dfu: add 'SKIP' entity"] Signed-off-by: Marek Szyprowski --- Original version of this patch is available here: https://patchwork.ozlabs.org/project/uboot/patch/20201109115757.24601-1-jh80.ch...@samsung.com/ --- doc/README.dfu| 15 ++- drivers/dfu/dfu.c | 2 +- drivers/dfu/dfu_mmc.c | 9 + include/dfu.h | 1 + 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/doc/README.dfu b/doc/README.dfu index be53b5b393..6cb1cba9d7 100644 --- a/doc/README.dfu +++ b/doc/README.dfu @@ -17,7 +17,7 @@ Overview: - The access to mediums is done in DFU backends (driver/dfu) Today the supported DFU backends are: - - MMC (RAW or FAT / EXT2 / EXT3 / EXT4 file system) + - MMC (RAW or FAT / EXT2 / EXT3 / EXT4 file system / SKIP) - NAND - RAM - SF (serial flash) @@ -91,6 +91,7 @@ Commands: part [mmcpart ] raw access to partition fat [mmcpart ] file in FAT partition ext4 [mmcpart ] file in EXT4 partition + skip 0 0 ignore flashed data with being the GPT or DOS partition index, with being the eMMC hardware partition number. @@ -103,6 +104,18 @@ Commands: "u-boot raw 0x80 0x800;uImage ext4 0 2" +If don't want to flash given image file to storage, use "skip" type +entity. +- It can be used to protect flashing wrong image for the specific board. +- Especailly, this layout will be useful when thor protocol is used, + which performs flashing in batch mode, where more than one file is + processed. +For example, if one makes a single tar file with support for the two +boards with u-boot-.bin and u-boot-.bin files, one +can use it to flash a proper u-boot image on both without a failure: + + "u-boot-.bin raw 0x80 0x800; u-boot-.bin skip 0 0" + "nand" (raw slc nand device) cmd: dfu 0 nand each element in "dfu_alt_info" = diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 501a60b344..fc32a53323 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -614,7 +614,7 @@ const char *dfu_get_dev_type(enum dfu_device_type t) const char *dfu_get_layout(enum dfu_layout l) { const char *const dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", - "EXT3", "EXT4", "RAM_ADDR" }; + "EXT3", "EXT4", "RAM_ADDR", "SKIP" }; return dfu_layout[l]; } diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 784d0ec76b..d1af11d94c 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -108,6 +108,8 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu, case DFU_FS_EXT4: fstype = FS_TYPE_EXT; break; + case DFU_SKIP: + return 0; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); @@ -204,6 +206,9 @@ int dfu_write_medium_mmc(struct dfu_entity *dfu, case DFU_FS_EXT4: ret = mmc_file_buf_write(dfu, offset, buf, len); break; + case DFU_SKIP: + ret = 0; + break; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); @@ -238,6 +243,8 @@ int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size) if (ret < 0) return ret; return 0; + case DFU_SKIP: + return 0; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); @@ -399,6 +406,8 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) dfu->layout = DFU_FS_FAT; } else if (!strcmp(entity_type, "ext4")) { dfu->layout = DFU_FS_EXT4; + } else if (!strcmp(entity_type, "skip")) { + dfu->layout = DFU_SKIP; } else { pr_err("Memory layout (%s) not supported!\n",
[PATCH v2 0/5] DFU: new entity types and minor improvements
Hi All, This patchset adds support for SKIP and SCRIPT entity types to the DFU subsystem. They significantly extends the flexibility of the storage flashing commands. Together with the recently posted 'Add MBR partition table creation and verify command' patchset and proper script it allows to create the whole partition table during the board flashing. It also easies the flashing by allowing to use the same images for different board variants/types, as each board can now use only the relevant images and skip the other ones without returning a failure. Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v2: - updated the "dfu: add 'SKIP' entity" patch to the latest version - added 'SCRIPT' DFU entity docs v1: https://lists.denx.de/pipermail/u-boot/2020-December/435214.html - initial version Patch summary: Jaehoon Chung (1): dfu: add 'SKIP' entity Marek Szyprowski (4): dfu: mmc: use the default MMC device if entity specifies it as -1 dfu: add 'SCRIPT' entity dfu: add support for the dfu_alt_info reintialization from the flashed script thor: add support for the dfu_alt_info reintialization from the flashed script cmd/dfu.c | 14 - cmd/thordown.c | 19 +++--- common/dfu.c| 3 +++ doc/README.dfu | 30 +++- drivers/dfu/dfu.c | 7 ++- drivers/dfu/dfu_mmc.c | 39 - drivers/usb/gadget/f_thor.c | 3 +++ include/dfu.h | 4 include/thor.h | 2 ++ 9 files changed, 106 insertions(+), 15 deletions(-) -- 2.17.1
[PATCH v4 3/3] configs: khadas-vim3(l): enable Function button support
Add options required to check the 'Function' button state. Signed-off-by: Marek Szyprowski --- configs/khadas-vim3_defconfig | 2 ++ configs/khadas-vim3l_defconfig | 2 ++ 2 files changed, 4 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 5d16652fd6..bc17430569 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y diff --git a/configs/khadas-vim3l_defconfig b/configs/khadas-vim3l_defconfig index 6b13ce045c..c1877922c7 100644 --- a/configs/khadas-vim3l_defconfig +++ b/configs/khadas-vim3l_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v4 2/3] button: add a simple Analog to Digital Converter device based button driver
Add a simple Analog to Digital Converter device based button driver. This driver binds to the 'adc-keys' device tree node. Signed-off-by: Marek Szyprowski --- drivers/button/Kconfig | 8 +++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 121 3 files changed, 130 insertions(+) create mode 100644 drivers/button/button-adc.c diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 6b3ec7e55d..6db3c5e93a 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -9,6 +9,14 @@ config BUTTON can provide access to board-specific buttons. Use of the device tree for configuration is encouraged. +config BUTTON_ADC + bool "Button adc" + depends on BUTTON + help + Enable support for buttons which are connected to Analog to Digital + Converter device. The ADC driver must use driver model. Buttons are + configured using the device tree. + config BUTTON_GPIO bool "Button gpio" depends on BUTTON diff --git a/drivers/button/Makefile b/drivers/button/Makefile index fcc10ebe8d..bbd18af149 100644 --- a/drivers/button/Makefile +++ b/drivers/button/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2020 Philippe Reynes obj-$(CONFIG_BUTTON) += button-uclass.o +obj-$(CONFIG_BUTTON_ADC) += button-adc.o obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c new file mode 100644 index 00..bf99dd8b43 --- /dev/null +++ b/drivers/button/button-adc.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + */ + +#include +#include +#include +#include +#include +#include + +/** + * struct button_adc_priv - private data for button-adc driver. + * + * @adc: Analog to Digital Converter device to which button is connected. + * @channel: channel of the ADC device to probe the button state. + */ +struct button_adc_priv { + struct udevice *adc; + int channel; +}; + +static enum button_state_t button_adc_get_state(struct udevice *dev) +{ + struct button_adc_priv *priv = dev_get_priv(dev); + unsigned int val, mask; + int ret; + + ret = adc_start_channel(priv->adc, priv->channel); + if (ret) + return ret; + + ret = adc_channel_data(priv->adc, priv->channel, ); + if (ret) + return ret; + + ret = adc_data_mask(priv->adc, ); + if (ret) + return ret; + + /* getting state is simplified a bit */ + if (ret == 0) + return (val < mask / 2) ? BUTTON_ON : BUTTON_OFF; + + return ret; +} + +static int button_adc_probe(struct udevice *dev) +{ + struct button_uc_plat *uc_plat = dev_get_uclass_platdata(dev); + struct button_adc_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + int ret; + + /* Ignore the top-level button node */ + if (!uc_plat->label) + return 0; + + ret = dev_read_phandle_with_args(dev->parent, "io-channels", +"#io-channel-cells", 0, 0, ); + if (ret) + return ret; + + ret = uclass_get_device_by_ofnode(UCLASS_ADC, args.node, >adc); + if (ret) + return ret; + + priv->channel = args.args[0]; + + return ret; +} + +static int button_adc_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + struct button_uc_plat *uc_plat; + const char *label; + + label = ofnode_read_string(node, "label"); + if (!label) { + debug("%s: node %s has no label\n", __func__, + ofnode_get_name(node)); + return -EINVAL; + } + ret = device_bind_driver_to_node(parent, "button_adc", +ofnode_get_name(node), +node, ); + if (ret) + return ret; + uc_plat = dev_get_uclass_platdata(dev); + uc_plat->label = label; + } + + return 0; +} + +static const struct button_ops button_adc_ops = { + .get_state = button_adc_get_state, +}; + +static const struct udevice_id button_adc_ids[] = { + { .compatible = "adc-keys" }, + { } +}; + +U_BOOT_DRIVER(button_adc) = { + .name = "button_adc", + .id = UCLASS_BUTTON, + .of_match = button_adc_ids, + .ops= _adc_ops, + .priv_auto_alloc_size = sizeof(struct button_adc_priv), + .bind = button_adc_bind, + .probe = button_adc_probe, +}; -- 2.17.1
[PATCH v4 0/3] VIM3: add support for checking 'Function' button state
Hi All, This patchset adds all building blocks needed for checking the 'Function' button state in the boot script on Amlogic A311D based VIM3 board. This button is connected to the ADC lines of the SoC, so it required to enable meson SARADC, the clocks needed for it and a simple button-adc drivers. Once applied, one can use following commands in the boot scripts: -->8--- echo Checking Func button state: \\c if button Function then echo Selected alternative boot ... fi --->8--- Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v4: - rebased onto uboot-amlogic/u-boot-amlogic-next and dropped merged patches - added adc-keys bindings docs (copied from Linux kernel) - minor code adjustments pointed by Simon - enabled driver also in khadas-vim3l_defconfig v3: https://lists.denx.de/pipermail/u-boot/2020-December/435072.html - removed 'button' env variable - extended kconfig and patch descriptions v2: https://lists.denx.de/pipermail/u-boot/2020-December/434991.html - removed Change-Id tags - split defconfig changes into ADC and button related v1: https://lists.denx.de/pipermail/u-boot/2020-December/434875.html - initial submission Patch summary: Marek Szyprowski (3): dt-bindings: input: adc-keys bindings documentation button: add a simple Analog to Digital Converter device based button driver configs: khadas-vim3(l): enable Function button support configs/khadas-vim3_defconfig | 2 + configs/khadas-vim3l_defconfig | 2 + doc/device-tree-bindings/input/adc-keys.txt | 49 drivers/button/Kconfig | 8 ++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 121 6 files changed, 183 insertions(+) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt create mode 100644 drivers/button/button-adc.c -- 2.17.1
[PATCH v4 1/3] dt-bindings: input: adc-keys bindings documentation
Dump adc-keys bindings documentation from Linux kernel source tree v5.10. Signed-off-by: Marek Szyprowski --- doc/device-tree-bindings/input/adc-keys.txt | 49 + 1 file changed, 49 insertions(+) create mode 100644 doc/device-tree-bindings/input/adc-keys.txt diff --git a/doc/device-tree-bindings/input/adc-keys.txt b/doc/device-tree-bindings/input/adc-keys.txt new file mode 100644 index 00..e551814629 --- /dev/null +++ b/doc/device-tree-bindings/input/adc-keys.txt @@ -0,0 +1,49 @@ +ADC attached resistor ladder buttons + + +Required properties: + - compatible: "adc-keys" + - io-channels: Phandle to an ADC channel + - io-channel-names = "buttons"; + - keyup-threshold-microvolt: Voltage at which all the keys are considered up. + +Optional properties: + - poll-interval: Poll interval time in milliseconds + - autorepeat: Boolean, Enable auto repeat feature of Linux input + subsystem. + +Each button (key) is represented as a sub-node of "adc-keys": + +Required subnode-properties: + - label: Descriptive name of the key. + - linux,code: Keycode to emit. + - press-threshold-microvolt: Voltage ADC input when this key is pressed. + +Example: + +#include + + adc-keys { + compatible = "adc-keys"; + io-channels = < 0>; + io-channel-names = "buttons"; + keyup-threshold-microvolt = <200>; + + button-up { + label = "Volume Up"; + linux,code = ; + press-threshold-microvolt = <150>; + }; + + button-down { + label = "Volume Down"; + linux,code = ; + press-threshold-microvolt = <100>; + }; + + button-enter { + label = "Enter"; + linux,code = ; + press-threshold-microvolt = <50>; + }; + }; -- 2.17.1
Re: [PATCH 4/6] button: add a simple ADC-based button driver
Hi Simon, On 19.12.2020 03:28, Simon Glass wrote: > On Mon, 14 Dec 2020 at 04:25, Marek Szyprowski > wrote: >> Add a simple ADC-based button driver. This driver binds to the 'adc-keys' >> device tree node. >> >> Signed-off-by: Marek Szyprowski >> Change-Id: I6da7101eff3ce53766d899f49f5839d728d52fb3 >> --- >> drivers/button/Kconfig | 8 +++ >> drivers/button/Makefile | 1 + >> drivers/button/button-adc.c | 117 >> 3 files changed, 126 insertions(+) >> create mode 100644 drivers/button/button-adc.c >> >> diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig >> index 6b3ec7e55de..283367f2bd3 100644 >> --- a/drivers/button/Kconfig >> +++ b/drivers/button/Kconfig >> @@ -9,6 +9,14 @@ config BUTTON >>can provide access to board-specific buttons. Use of the device >> tree >>for configuration is encouraged. >> >> +config BUTTON_ADC >> + bool "Button adc" >> + depends on BUTTON >> + help >> + Enable support for buttons which are connected to ADC lines. The >> ADC >> + driver must use driver model. Buttons are configured using the >> device >> + tree. >> + >> config BUTTON_GPIO >> bool "Button gpio" >> depends on BUTTON >> diff --git a/drivers/button/Makefile b/drivers/button/Makefile >> index fcc10ebe8db..bbd18af1494 100644 >> --- a/drivers/button/Makefile >> +++ b/drivers/button/Makefile >> @@ -3,4 +3,5 @@ >> # Copyright (C) 2020 Philippe Reynes >> >> obj-$(CONFIG_BUTTON) += button-uclass.o >> +obj-$(CONFIG_BUTTON_ADC) += button-adc.o >> obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o >> diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c >> new file mode 100644 >> index 000..086c676c02a >> --- /dev/null >> +++ b/drivers/button/button-adc.c >> @@ -0,0 +1,117 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +/* >> + * Copyright (C) 2020 Samsung Electronics Co., Ltd. >> + * http://www.samsung.com >> + * Author: Marek Szyprowski >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include > Please check header order > > https://protect2.fireeye.com/v1/url?k=0827922c-57bcaba3-08261963-0cc47a31307c-c2add94742a708a4=1=e6ddd072-23a6-4591-9ca7-8d41aa498536=https%3A%2F%2Fwww.denx.de%2Fwiki%2FU-Boot%2FCodingStyle > >> + >> +struct button_adc_priv { >> + struct udevice *adc; >> + int channel; > comments > >> +}; >> + >> +static enum button_state_t button_adc_get_state(struct udevice *dev) >> +{ >> + struct button_adc_priv *priv = dev_get_priv(dev); >> + unsigned int val, mask; >> + int ret; >> + >> + ret = adc_start_channel(priv->adc, priv->channel); >> + if (ret) >> + return ret; >> + >> + ret = adc_channel_data(priv->adc, priv->channel, ); >> + if (ret) >> + return ret; >> + >> + ret = adc_data_mask(priv->adc, ); >> + if (ret) >> + return ret; >> + >> + /* getting state is simplified a bit */ >> + if (ret == 0) >> + return (val < mask / 2) ? BUTTON_ON : BUTTON_OFF; >> + >> + return ret; >> +} >> + >> +static int button_adc_probe(struct udevice *dev) >> +{ >> + struct button_uc_plat *uc_plat = dev_get_uclass_platdata(dev); >> + struct button_adc_priv *priv = dev_get_priv(dev); >> + struct ofnode_phandle_args args; >> + int ret; >> + >> + /* Ignore the top-level button node */ >> + if (!uc_plat->label) >> + return 0; >> + >> + ret = dev_read_phandle_with_args(dev->parent, "io-channels", >> +"#io-channel-cells", 0, 0, ); >> + if (ret) >> + return ret; >> + >> + ret = uclass_get_device_by_name(UCLASS_ADC, >> ofnode_get_name(args.node), >> + >adc); > How about uclass_get_device_by_ofnode() ? > >> + if (ret) >> + return ret; >> + >> + priv->channel = args.args[0]; >> + >> + return ret; >> +} >> + >> +static int button_adc_bind(struct
Re: [PATCH 0/5] DFU: new entity types and minor improvements
Hi Jaehoon, On 20.12.2020 23:17, Jaehoon Chung wrote: > On 12/17/20 9:10 PM, Marek Szyprowski wrote: >> This patchset adds support for SKIP and SCRIPT entity types to the DFU >> subsystem. They significantly extends the flexibility of the DFU >> subsystem. Together with the recently posted 'Add MBR partition table >> creation and verify command' patchset it allows to create the whole >> partition table during the board flashing when one prepares a proper >> script. It also easies the flashing by allowing to use the same images >> for different board variants/types, as each board can now use only the >> relevant images and skip the other ones without returning a failure. > I sent the patch about skip entity. At that time, Lukasz mentioned to update > dfu documentation. > > https://patchwork.ozlabs.org/project/uboot/patch/20201109115757.24601-1-jh80.ch...@samsung.com/ > > Could you update also README.dfu and Minkyu's reviewed-tag about my patch? Thanks for pointing this. I missed that. I will include your v2 patch and also update the readme about the SCRIPT type. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
[PATCH] board: amlogic: add MMC boot device detection for environment load
Detect eMMC or SD card boot on Odroid-C4/N2 and Khadas VIM3(l) boards and report proper MMC device for the environment loading code. This allows to automatically load and store environment variables on the FAT partition or RAW offset of the MMC device without the need to use different configurations on eMMC and SD card. To use this feature with environment stored on FAT partition, one has to specify an empty device part (i.e. ":1" for the first partition) in CONFIG_ENV_FAT_DEVICE_AND_PART to let the code to set the device to the value returned by mmc_get_env_dev() function. Signed-off-by: Marek Szyprowski --- board/amlogic/odroid-n2/odroid-n2.c | 8 board/amlogic/vim3/vim3.c | 8 2 files changed, 16 insertions(+) diff --git a/board/amlogic/odroid-n2/odroid-n2.c b/board/amlogic/odroid-n2/odroid-n2.c index caf7fd6810..12ee5d3abc 100644 --- a/board/amlogic/odroid-n2/odroid-n2.c +++ b/board/amlogic/odroid-n2/odroid-n2.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,13 @@ #define EFUSE_MAC_SIZE 12 #define MAC_ADDR_LEN 6 +int mmc_get_env_dev(void) +{ + if (meson_get_boot_device() == BOOT_DEVICE_EMMC) + return 1; + return 0; +} + int misc_init_r(void) { u8 mac_addr[MAC_ADDR_LEN]; diff --git a/board/amlogic/vim3/vim3.c b/board/amlogic/vim3/vim3.c index 09ef39ff30..f9049e0172 100644 --- a/board/amlogic/vim3/vim3.c +++ b/board/amlogic/vim3/vim3.c @@ -10,10 +10,18 @@ #include #include #include +#include #include #include #include "khadas-mcu.h" +int mmc_get_env_dev(void) +{ + if (meson_get_boot_device() == BOOT_DEVICE_EMMC) + return 2; + return 1; +} + /* * The VIM3 on-board MCU can mux the PCIe/USB3.0 shared differential * lines using a FUSB340TMX USB 3.1 SuperSpeed Data Switch between -- 2.17.1
[PATCH] ARM: dts: meson: switch TFLASH_VDD_EN pin to open drain on Odroid-C4
For the proper reboot Odroid-C4 board requires to switch TFLASH_VDD_EN pin to the high impedance mode, otherwise the board is stuck in the middle of loading early stages of the bootloader from SD card. This can be achieved by using the OPEN_DRAIN flag instead if the ACTIVE_HIGH, what will leave the pin in input to achieve high state (pin has the pull-up) and solve the issue. Suggested-by: Neil Armstrong Signed-off-by: Marek Szyprowski --- This is a result of the discussion in the "[PATCH/RFC] board: amlogic: Fix Odroid-C4 SD card reboot issue" thread: https://lists.denx.de/pipermail/u-boot/2020-December/435295.html Patch for the upstream Linux DTS has been already submitted: https://lore.kernel.org/linux-amlogic/20201218102228.16211-1-m.szyprow...@samsung.com/ --- arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi | 4 1 file changed, 4 insertions(+) diff --git a/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi b/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi index c431988075..fbcc8287c5 100644 --- a/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi +++ b/arch/arm/dts/meson-sm1-odroid-c4-u-boot.dtsi @@ -11,3 +11,7 @@ snps,reset-delays-us = <0 1 100>; snps,reset-active-low; }; + +_vdd { + gpio = <_ao GPIOAO_3 GPIO_OPEN_DRAIN>; +}; -- 2.17.1
Re: [PATCH/RFC] board: amlogic: Fix Odroid-C4 SD card reboot issue
Hi Neil, On 18.12.2020 10:24, Neil Armstrong wrote: > On 18/12/2020 10:11, Marek Szyprowski wrote: >> On 18.12.2020 09:36, Neil Armstrong wrote: >>> On 17/12/2020 10:06, Marek Szyprowski wrote: >>>> For the proper reboot Odroid C4 board requires to switch TFLASH_VDD_EN >>>> pin to the input (high impedance?) mode, otherwise the board is stuck >>>> in the middle of loading early stages of the bootloader from SD card. >>> Did you try taking the regulator-tflash_vdd and doing a disable/enable >>> sequence >>> to reset the card ? >>> >>> The GPIOAO_3 has a default pull-up, so I don't see why moving it to input >>> could change >>> anything. >>> >>> So maybe simply doing a 0->1 transition could do the same, using the >>> regulator >>> would be much better. >>> >>> Can't we add "shutdown" or equivalent method to the mmc driver that could >>> do this >>> directly with the vdd regulator ? >> Yes, I've tried all combinations of playing this that GPIO and regulator >> that came to my mind. Switching pin to the input is the only one I've >> found working. > Thanks for the dumps ! > > Could you try switching the tflash_vdd to opendrain like : > > --->8--- > > --- a/arch/arm/dts/meson-sm1-odroid-c4.dts > +++ b/arch/arm/dts/meson-sm1-odroid-c4.dts > @@ -52,7 +52,7 @@ > regulator-min-microvolt = <330>; > regulator-max-microvolt = <330>; > > - gpio = <_ao GPIOAO_3 GPIO_ACTIVE_HIGH>; > + gpio = <_ao GPIOAO_3 GPIO_OPEN_DRAIN>; > enable-active-high; > regulator-always-on; > }; > > --->8--- > > This should leave the pin in input to achieve high state, and solve the issue. > Right, this fixed the issue! Thanks! Do you want me to submit it as a patch to uboot and mainline Linux kernel or do you want to handle it by yourself? Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
Re: [PATCH/RFC] board: amlogic: Fix Odroid-C4 SD card reboot issue
Hi Neil, On 18.12.2020 09:36, Neil Armstrong wrote: > On 17/12/2020 10:06, Marek Szyprowski wrote: >> For the proper reboot Odroid C4 board requires to switch TFLASH_VDD_EN >> pin to the input (high impedance?) mode, otherwise the board is stuck >> in the middle of loading early stages of the bootloader from SD card. > Did you try taking the regulator-tflash_vdd and doing a disable/enable > sequence > to reset the card ? > > The GPIOAO_3 has a default pull-up, so I don't see why moving it to input > could change > anything. > > So maybe simply doing a 0->1 transition could do the same, using the regulator > would be much better. > > Can't we add "shutdown" or equivalent method to the mmc driver that could do > this > directly with the vdd regulator ? Yes, I've tried all combinations of playing this that GPIO and regulator that came to my mind. Switching pin to the input is the only one I've found working. It looks that there must be some additional (hw?) logic there, which does the SD card reset during the BL, which in turn conflicts with the constant 0 or constant 1 driven from TFLASH_VDD_EN gpio. This is also what the vendor's kernel does: https://github.com/hardkernel/linux/commit/84628497332a5cd2154c92436ec86fad900fe0af That commit states that it is according to the odroid schematic, but on the public schematics of C4 I cannot find anything what might need such workaround/fix. Here is how it behaves without the fix: 1. if SD card is not used (TFLASH regulator is not even instantiated, so GPIO pin is in input state as its initial value left by earlier BL stages), the reboot works fine: --->8--- U-Boot 2021.01-rc3 (Dec 18 2020 - 10:00:48 +0100) odroid-c4 Model: Hardkernel ODROID-C4 SoC: Amlogic Meson SM1 (S905X3) Revision 2b:c (10:2) DRAM: 3.8 GiB MMC: sd@ffe05000: 0, mmc@ffe07000: 1 In: serial Out: serial Err: serial Net: eth0: ethernet@ff3f Hit any key to stop autoboot: 0 => => reset resetting ... bl31 reboot reason: 0xd bl31 reboot reason: 0x0 system cmd 1. SM1:BL:511f6b:81ca2f;FEAT:A0F83180:20282000;POC:F;RCY:0;EMMC:800;NAND:81;SD?:0;SD:0;READ:0;0.0;CHK:0; bl2_stage_init 0x01 bl2_stage_init 0x81 hw id: 0x - pwm id 0x01 bl2_stage_init 0xc1 bl2_stage_init 0x02 no sdio debug board detected L0: L1:0703 L2:8067 L3:1520 S1: B2:20282000 B1:a0f83180 TE: 143230 BL2 Built : 22:54:32, Apr 28 2020. g12a ga659aac-dirty - changqing.gao@droid11 Board ID = 1 Set cpu clk to 24M Set clk81 to 24M Use GP1_pll as DSU clk. DSU clk: 1200 Mhz CPU clk: 1200 MHz Set clk81 to 166.6M DDR driver_vesion: LPDDR4_PHY_V_0_1_15 build time: Apr 28 2020 22:54:28 board id: 1 Load FIP HDR from SD, src: 0x00010200, des: 0xfffd, size: 0x4000, part: 0 fw parse done Load ddrfw from SD, src: 0x00060200, des: 0xfffd, size: 0xc000, part: 0 Load ddrfw from SD, src: 0x00038200, des: 0xfffd, size: 0x4000, part: 0 PIEI prepare done fastboot data load fastboot data verify verify result: 255 Cfg max: 2, cur: 1. Board id: 255. Force loop cfg DDR4 probe ddr clk to 1320MHz Load ddrfw from SD, src: 0x00014200, des: 0xfffd, size: 0xc000, part: 0 dmc_version 0001 Check phy result INFO : End of initialization INFO : End of read enable training INFO : End of fine write leveling INFO : End of read dq deskew training INFO : End of MPR read delay center optimization INFO : End of Write leveling coarse delay INFO : End of write delay center optimization INFO : End of read delay center optimization INFO : End of max read latency training INFO : Training has run successfully! 1D training succeed Load ddrfw from SD, src: 0x00020200, des: 0xfffd, size: 0xc000, part: 0 Check phy result INFO : End of initialization INFO : End of 2D read delay Voltage center optimization INFO : End of 2D write delay Voltage center optimization INFO : Training has run successfully! R0_RxClkDly_Margin==94 ps 8 R0_TxDqDly_Margi==106 ps 9 R1_RxClkDly_Margin==0 ps 0 R1_TxDqDly_Margi==0 ps 0 dwc_ddrphy_apb_wr((0<<20)|(2<<16)|(0<<12)|(0xb0):0001 soc_vref_reg_value 0x 004e 004f 004e 004f 0050 004f 004f 004e 004d 004c 004f 004d 0050 0050 004f 004f 004e 004f 004e 004e 004e 004d 004e 004e 0050 004e 004f 004d 004d 004e 004e 004d dram_vref_reg_value 0x 0022 2D training succeed aml_ddr_fw_vesion: LPDDR4_PHY_V_0_1_15 build time: Jun 18 2019 20:29:43 auto size-- 65535DDR cs0 size: 2048MB DDR cs1 size: 2048MB DMC_DDR_CTRL: 00700024DDR size: 3928MB cs0 DataBus test pass cs1 DataBus test pass cs0 AddrBus test pass cs1 AddrBus test pass non-sec scramble use zero key ddr scramble enabled 100bdlr_step_size ps== 425 result report boot times 1Enable ddr reg access Load FIP HDR from SD, src: 0x00010200, des: 0x0170, size: 0x400
[PATCH 4/5] dfu: add support for the dfu_alt_info reintialization from the flashed script
Reinitialize DFU USB gadget after flashing the 'SCRIPT' entity to ensure that the potential changes to the 'dfu_alt_info' environment variable are applied. Signed-off-by: Marek Szyprowski --- cmd/dfu.c| 14 +- common/dfu.c | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/cmd/dfu.c b/cmd/dfu.c index 7310595a02..89b1b2268e 100644 --- a/cmd/dfu.c +++ b/cmd/dfu.c @@ -34,6 +34,7 @@ static int do_dfu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) #if defined(CONFIG_DFU_TIMEOUT) || defined(CONFIG_DFU_OVER_TFTP) unsigned long value = 0; #endif + bool retry = false; if (argc >= 4) { interface = argv[2]; @@ -68,7 +69,18 @@ static int do_dfu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) int controller_index = simple_strtoul(usb_controller, NULL, 0); - run_usb_dnl_gadget(controller_index, "usb_dnl_dfu"); + do { + retry = false; + run_usb_dnl_gadget(controller_index, "usb_dnl_dfu"); + + if (dfu_reinit_needed) { + dfu_free_entities(); + ret = dfu_init_env_entities(interface, devstring); + if (ret) + goto done; + retry = true; + } + } while (retry); done: dfu_free_entities(); diff --git a/common/dfu.c b/common/dfu.c index d23cf67f19..16bd1ba588 100644 --- a/common/dfu.c +++ b/common/dfu.c @@ -98,6 +98,9 @@ int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget) } #endif + if (dfu_reinit_needed) + goto exit; + WATCHDOG_RESET(); usb_gadget_handle_interrupts(usbctrl_index); } -- 2.17.1
[PATCH 0/5] DFU: new entity types and minor improvements
Hi All, This patchset adds support for SKIP and SCRIPT entity types to the DFU subsystem. They significantly extends the flexibility of the DFU subsystem. Together with the recently posted 'Add MBR partition table creation and verify command' patchset it allows to create the whole partition table during the board flashing when one prepares a proper script. It also easies the flashing by allowing to use the same images for different board variants/types, as each board can now use only the relevant images and skip the other ones without returning a failure. Best regards Marek Szyprowski Samsung R Institute Poland Jaehoon Chung (1): dfu: add 'SKIP' entity Marek Szyprowski (4): dfu: mmc: use the default MMC device if entity specifies it as -1 dfu: add 'SCRIPT' entity dfu: add support for the dfu_alt_info reintialization from the flashed script thor: add support for the dfu_alt_info reintialization from the flashed script cmd/dfu.c | 14 - cmd/thordown.c | 19 +++--- common/dfu.c| 3 +++ drivers/dfu/dfu.c | 6 +- drivers/dfu/dfu_mmc.c | 39 - drivers/usb/gadget/f_thor.c | 3 +++ include/dfu.h | 4 include/thor.h | 2 ++ 8 files changed, 76 insertions(+), 14 deletions(-) -- 2.17.1
[PATCH 1/5] dfu: mmc: use the default MMC device if entity specifies it as -1
Use the default MMC device set in the command line if entity specifies it as -1. This allows to use the same dfu_alt_info string for different MMC devices (like embedded eMMC and external SD card if data layout is the same on both devices). Signed-off-by: Marek Szyprowski --- drivers/dfu/dfu_mmc.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 691d01c7eb..784d0ec76b 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -316,7 +316,7 @@ void dfu_free_entity_mmc(struct dfu_entity *dfu) int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) { const char *entity_type; - size_t second_arg; + ssize_t second_arg; size_t third_arg; struct mmc *mmc; @@ -339,7 +339,7 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8, * with default 10. */ - second_arg = simple_strtoul(argv[1], NULL, 0); + second_arg = simple_strtol(argv[1], NULL, 0); third_arg = simple_strtoul(argv[2], NULL, 0); mmc = find_mmc_device(dfu->data.mmc.dev_num); @@ -406,7 +406,8 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) /* if it's NOT a raw write */ if (strcmp(entity_type, "raw")) { - dfu->data.mmc.dev = second_arg; + dfu->data.mmc.dev = (second_arg != -1) ? second_arg : +dfu->data.mmc.dev_num; dfu->data.mmc.part = third_arg; } -- 2.17.1
[PATCH 5/5] thor: add support for the dfu_alt_info reintialization from the flashed script
Reinitialize dfu_env_entities after flashing the 'SCRIPT' entity to ensure that the potential changes to the 'dfu_alt_info' environment variable are applied. Signed-off-by: Marek Szyprowski --- cmd/thordown.c | 19 --- drivers/usb/gadget/f_thor.c | 3 +++ include/thor.h | 2 ++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/cmd/thordown.c b/cmd/thordown.c index ae20dddfdd..838764ccef 100644 --- a/cmd/thordown.c +++ b/cmd/thordown.c @@ -52,13 +52,18 @@ int do_thor_down(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) goto exit; } - ret = thor_handle(); - if (ret) { - pr_err("THOR failed: %d\n", ret); - ret = CMD_RET_FAILURE; - goto exit; - } - + do { + ret = thor_handle(); + if (ret == THOR_DFU_REINIT_NEEDED) { + dfu_free_entities(); + ret = dfu_init_env_entities(interface, devstring); + } + if (ret) { + pr_err("THOR failed: %d\n", ret); + ret = CMD_RET_FAILURE; + goto exit; + } + } while (ret == 0); exit: g_dnl_unregister(); usb_gadget_release(controller_index); diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index 88fc87f2e9..3e69746ee6 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "f_thor.h" @@ -735,6 +736,8 @@ int thor_handle(void) printf("%s: No data received!\n", __func__); break; } + if (dfu_reinit_needed) + return THOR_DFU_REINIT_NEEDED; } return 0; diff --git a/include/thor.h b/include/thor.h index 62501bda17..ee67ab0a27 100644 --- a/include/thor.h +++ b/include/thor.h @@ -12,6 +12,8 @@ #include +#define THOR_DFU_REINIT_NEEDED 0xFFFE + int thor_handle(void); int thor_init(void); int thor_add(struct usb_configuration *c); -- 2.17.1
[PATCH 2/5] dfu: add 'SKIP' entity
From: Jaehoon Chung Define a new 'SKIP' type for DFU entities. The flashed data are simply ignored without returning any error values. This allows to have the same board flashing procedure and images for the different board types or variants, where each board uses only the images relevant to it and skips the rest. Signed-off-by: Jaehoon Chung [mszyprow: rephrased commit message and subject] Signed-off-by: Marek Szyprowski --- drivers/dfu/dfu.c | 2 +- drivers/dfu/dfu_mmc.c | 9 + include/dfu.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 501a60b344..fc32a53323 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -614,7 +614,7 @@ const char *dfu_get_dev_type(enum dfu_device_type t) const char *dfu_get_layout(enum dfu_layout l) { const char *const dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", - "EXT3", "EXT4", "RAM_ADDR" }; + "EXT3", "EXT4", "RAM_ADDR", "SKIP" }; return dfu_layout[l]; } diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 784d0ec76b..d1af11d94c 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -108,6 +108,8 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu, case DFU_FS_EXT4: fstype = FS_TYPE_EXT; break; + case DFU_SKIP: + return 0; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); @@ -204,6 +206,9 @@ int dfu_write_medium_mmc(struct dfu_entity *dfu, case DFU_FS_EXT4: ret = mmc_file_buf_write(dfu, offset, buf, len); break; + case DFU_SKIP: + ret = 0; + break; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); @@ -238,6 +243,8 @@ int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size) if (ret < 0) return ret; return 0; + case DFU_SKIP: + return 0; default: printf("%s: Layout (%s) not (yet) supported!\n", __func__, dfu_get_layout(dfu->layout)); @@ -399,6 +406,8 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) dfu->layout = DFU_FS_FAT; } else if (!strcmp(entity_type, "ext4")) { dfu->layout = DFU_FS_EXT4; + } else if (!strcmp(entity_type, "skip")) { + dfu->layout = DFU_SKIP; } else { pr_err("Memory layout (%s) not supported!\n", entity_type); return -ENODEV; diff --git a/include/dfu.h b/include/dfu.h index a767adee41..0b1dae0b3b 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -33,6 +33,7 @@ enum dfu_layout { DFU_FS_EXT3, DFU_FS_EXT4, DFU_RAM_ADDR, + DFU_SKIP, }; enum dfu_op { -- 2.17.1
[PATCH 3/5] dfu: add 'SCRIPT' entity
Define a new 'SCRIPT' type for DFU entities. The downloaded data are treated as simple u-boot's scripts and executed with run_command_list() function. Flashing the 'SCRIPT' entity might result in changing the 'dfu_alt_info' environment variable from the flashed script, so add a global variable for tracking the potential need to reinitialize the dfu_alt_info related structures. Signed-off-by: Marek Szyprowski --- drivers/dfu/dfu.c | 6 +- drivers/dfu/dfu_mmc.c | 23 +-- include/dfu.h | 3 +++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index fc32a53323..eccfb4c745 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -26,6 +26,8 @@ static struct hash_algo *dfu_hash_algo; static unsigned long dfu_timeout = 0; #endif +bool dfu_reinit_needed = false; + /* * The purpose of the dfu_flush_callback() function is to * provide callback for dfu user @@ -139,6 +141,8 @@ int dfu_init_env_entities(char *interface, char *devstr) char *env_bkp; int ret = 0; + dfu_reinit_needed = false; + #ifdef CONFIG_SET_DFU_ALT_INFO set_dfu_alt_info(interface, devstr); #endif @@ -614,7 +618,7 @@ const char *dfu_get_dev_type(enum dfu_device_type t) const char *dfu_get_layout(enum dfu_layout l) { const char *const dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2", - "EXT3", "EXT4", "RAM_ADDR", "SKIP" }; + "EXT3", "EXT4", "RAM_ADDR", "SKIP", "SCRIPT" }; return dfu_layout[l]; } diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index d1af11d94c..e63fa84ce4 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -16,6 +16,7 @@ #include #include #include +#include static unsigned char *dfu_file_buf; static u64 dfu_file_buf_len; @@ -206,6 +207,9 @@ int dfu_write_medium_mmc(struct dfu_entity *dfu, case DFU_FS_EXT4: ret = mmc_file_buf_write(dfu, offset, buf, len); break; + case DFU_SCRIPT: + ret = run_command_list(buf, *len, 0); + break; case DFU_SKIP: ret = 0; break; @@ -221,9 +225,21 @@ int dfu_flush_medium_mmc(struct dfu_entity *dfu) { int ret = 0; - if (dfu->layout != DFU_RAW_ADDR) { - /* Do stuff here. */ + switch (dfu->layout) { + case DFU_FS_FAT: + case DFU_FS_EXT4: ret = mmc_file_buf_write_finish(dfu); + break; + case DFU_SCRIPT: + /* script may have changed the dfu_alt_info */ + dfu_reinit_needed = true; + break; + case DFU_RAW_ADDR: + case DFU_SKIP: + break; + default: + printf("%s: Layout (%s) not (yet) supported!\n", __func__, + dfu_get_layout(dfu->layout)); } return ret; @@ -243,6 +259,7 @@ int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size) if (ret < 0) return ret; return 0; + case DFU_SCRIPT: case DFU_SKIP: return 0; default: @@ -408,6 +425,8 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) dfu->layout = DFU_FS_EXT4; } else if (!strcmp(entity_type, "skip")) { dfu->layout = DFU_SKIP; + } else if (!strcmp(entity_type, "script")) { + dfu->layout = DFU_SCRIPT; } else { pr_err("Memory layout (%s) not supported!\n", entity_type); return -ENODEV; diff --git a/include/dfu.h b/include/dfu.h index 0b1dae0b3b..d18b701728 100644 --- a/include/dfu.h +++ b/include/dfu.h @@ -34,6 +34,7 @@ enum dfu_layout { DFU_FS_EXT4, DFU_RAM_ADDR, DFU_SKIP, + DFU_SCRIPT, }; enum dfu_op { @@ -497,6 +498,8 @@ static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, } #endif +extern bool dfu_reinit_needed; + #if CONFIG_IS_ENABLED(DFU_WRITE_ALT) /** * dfu_write_by_name() - write data to DFU medium -- 2.17.1
[PATCH 2/6] disk: dos: add some defines for the hardcoded numbers
Add some handy defines for some hardcoded magic numbers related to extended partition handling. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 6 +++--- disk/part_dos.h | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index ef706fb59c..20d35dc9cd 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -42,9 +42,9 @@ static inline unsigned int le32_to_int(unsigned char *le32) static inline int is_extended(int part_type) { -return (part_type == 0x5 || - part_type == 0xf || - part_type == 0x85); +return (part_type == DOS_PART_TYPE_EXTENDED || + part_type == DOS_PART_TYPE_EXTENDED_LBA || + part_type == DOS_PART_TYPE_EXTENDED_LINUX); } static int get_bootable(dos_partition_t *p) diff --git a/disk/part_dos.h b/disk/part_dos.h index 434b021ae8..dd909a9317 100644 --- a/disk/part_dos.h +++ b/disk/part_dos.h @@ -15,6 +15,9 @@ #define DOS_PBR_MEDIA_TYPE_OFFSET 0x15 #define DOS_MBR0 #define DOS_PBR1 +#define DOS_PART_TYPE_EXTENDED 0x05 +#define DOS_PART_TYPE_EXTENDED_LBA 0x0F +#define DOS_PART_TYPE_EXTENDED_LINUX 0x85 typedef struct dos_partition { unsigned char boot_ind; /* 0x80 - active */ -- 2.17.1
[PATCH 0/6] Add MBR partition table creation and verify command
Hi All, This patchset adds 'mbr' command to let one create or verify MBR (Master Boot Record) partition layout based on the provided text description. This can be used in scripts to help system flashing tools/scripts to ensure proper partition layout. It has been inspired by the 'gpt' command already present in u-boot. Best regards Marek Szyprowski Samsung R Institute Poland Marek Szyprowski (6): disk: dos: rename write_mbr_partition to write_mbr_sector disk: dos: add some defines for the hardcoded numbers disk: dos: use generic macro for unaligned le32 access disk: dos: make some functions static disk: dos: add code for creating MBR partition layout cmd: Add MBR partition layout control utility cmd/Kconfig | 8 + cmd/Makefile | 1 + cmd/mbr.c | 308 ++ disk/part_dos.c | 207 + disk/part_dos.h | 5 + drivers/fastboot/fb_mmc.c | 2 +- include/part.h| 9 +- 7 files changed, 512 insertions(+), 28 deletions(-) create mode 100644 cmd/mbr.c -- 2.17.1
[PATCH 1/6] disk: dos: rename write_mbr_partition to write_mbr_sector
write_mbr_partition() function name is a bit misleading, so rename it to write_mbr_sector(). This is a preparation for adding code for writing a complete MBR partition layout. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 2 +- drivers/fastboot/fb_mmc.c | 2 +- include/part.h| 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 04f53106f7..ef706fb59c 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -329,7 +329,7 @@ int is_valid_dos_buf(void *buf) return test_block_type(buf) == DOS_MBR ? 0 : -1; } -int write_mbr_partition(struct blk_desc *dev_desc, void *buf) +int write_mbr_sector(struct blk_desc *dev_desc, void *buf) { if (is_valid_dos_buf(buf)) return -1; diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index ae8e8e512f..4e26cef941 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -508,7 +508,7 @@ void fastboot_mmc_flash_write(const char *cmd, void *download_buffer, fastboot_fail("invalid MBR partition", response); return; } - if (write_mbr_partition(dev_desc, download_buffer)) { + if (write_mbr_sector(dev_desc, download_buffer)) { printf("%s: writing MBR partition failed\n", __func__); fastboot_fail("writing MBR partition failed", response); diff --git a/include/part.h b/include/part.h index 55be724d20..67b8b2a5cc 100644 --- a/include/part.h +++ b/include/part.h @@ -465,14 +465,14 @@ int get_disk_guid(struct blk_desc *dev_desc, char *guid); int is_valid_dos_buf(void *buf); /** - * write_mbr_partition() - write DOS MBR + * write_mbr_sector() - write DOS MBR * * @param dev_desc - block device descriptor * @param buf - buffer which contains the MBR * * @return - '0' on success, otherwise error */ -int write_mbr_partition(struct blk_desc *dev_desc, void *buf); +int write_mbr_sector(struct blk_desc *dev_desc, void *buf); #endif -- 2.17.1
[PATCH 3/6] disk: dos: use generic macro for unaligned le32 access
Use a generic helper for reading LE32 integers. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 28 +--- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 20d35dc9cd..3b79b9b1b8 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "part_dos.h" #include @@ -29,17 +30,6 @@ * to use large numbers of partitions */ #define MAX_EXT_PARTS 256 -/* Convert char[4] in little endian format to the host format integer - */ -static inline unsigned int le32_to_int(unsigned char *le32) -{ -return ((le32[3] << 24) + - (le32[2] << 16) + - (le32[1] << 8) + -le32[0] - ); -} - static inline int is_extended(int part_type) { return (part_type == DOS_PART_TYPE_EXTENDED || @@ -61,8 +51,8 @@ static int get_bootable(dos_partition_t *p) static void print_one_part(dos_partition_t *p, lbaint_t ext_part_sector, int part_num, unsigned int disksig) { - lbaint_t lba_start = ext_part_sector + le32_to_int (p->start4); - lbaint_t lba_size = le32_to_int (p->size4); + lbaint_t lba_start = ext_part_sector + get_unaligned_le32(p->start4); + lbaint_t lba_size = get_unaligned_le32(p->size4); printf("%3d\t%-10" LBAFlength "u\t%-10" LBAFlength "u\t%08x-%02x\t%02x%s%s\n", @@ -171,7 +161,7 @@ static void print_partition_extended(struct blk_desc *dev_desc, } if (!ext_part_sector) - disksig = le32_to_int([DOS_PART_DISKSIG_OFFSET]); + disksig = get_unaligned_le32([DOS_PART_DISKSIG_OFFSET]); /* Print all primary/logical partitions */ pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); @@ -198,7 +188,7 @@ static void print_partition_extended(struct blk_desc *dev_desc, for (i = 0; i < 4; i++, pt++) { if (is_extended (pt->sys_ind)) { lbaint_t lba_start - = le32_to_int (pt->start4) + relative; + = get_unaligned_le32 (pt->start4) + relative; print_partition_extended(dev_desc, lba_start, ext_part_sector == 0 ? lba_start : relative, @@ -244,7 +234,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc, #if CONFIG_IS_ENABLED(PARTITION_UUIDS) if (!ext_part_sector) - disksig = le32_to_int([DOS_PART_DISKSIG_OFFSET]); + disksig = get_unaligned_le32([DOS_PART_DISKSIG_OFFSET]); #endif /* Print all primary/logical partitions */ @@ -260,8 +250,8 @@ static int part_get_info_extended(struct blk_desc *dev_desc, (ext_part_sector == 0 || is_extended(pt->sys_ind) == 0)) { info->blksz = DOS_PART_DEFAULT_SECTOR; info->start = (lbaint_t)(ext_part_sector + - le32_to_int(pt->start4)); - info->size = (lbaint_t)le32_to_int(pt->size4); + get_unaligned_le32(pt->start4)); + info->size = (lbaint_t)get_unaligned_le32(pt->size4); part_set_generic_name(dev_desc, part_num, (char *)info->name); /* sprintf(info->type, "%d, pt->sys_ind); */ @@ -286,7 +276,7 @@ static int part_get_info_extended(struct blk_desc *dev_desc, for (i = 0; i < 4; i++, pt++) { if (is_extended (pt->sys_ind)) { lbaint_t lba_start - = le32_to_int (pt->start4) + relative; + = get_unaligned_le32 (pt->start4) + relative; return part_get_info_extended(dev_desc, lba_start, ext_part_sector == 0 ? lba_start : relative, -- 2.17.1
[PATCH 6/6] cmd: Add MBR partition layout control utility
Add a 'mbr' command to let user create or verify MBR partition layout based on the provided text description. The partition layout is altearnatively read from 'mbr_parts' environment variable. This can be used in scripts to help system image flashing tools to ensure proper partition layout. The syntax of the text description of the partition list is similar to the one used by the 'gpt' command. Supported parameters are: name (currently ignored), start (partition start offset in bytes), size (in bytes or '-' to expand it to the whole free area), bootable (boolean flag) and id (MBR partition system ID). If one wants to create more than 4 partitions, an 'Extended' primary partition (with 0x05 ID) has to be explicitely provided as a one of the first 4 entries. Here is the example how to create a 6 partitions (3 on the 'extended volume'), some of the predefined sizes: > setenv mbr_parts 'name=boot,start=4M,size=128M,bootable,id=0x0e; name=rootfs,size=3072M,id=0x83; name=system-data,size=512M,id=0x83; name=[ext],size=-,id=0x05; name=user,size=-,id=0x83; name=modules,size=100M,id=0x83; name=ramdisk,size=8M,id=0x83' > mbr write mmc 0 Signed-off-by: Marek Szyprowski --- cmd/Kconfig | 8 ++ cmd/Makefile | 1 + cmd/mbr.c| 308 +++ 3 files changed, 317 insertions(+) create mode 100644 cmd/mbr.c diff --git a/cmd/Kconfig b/cmd/Kconfig index 1595de999b..2c3358e359 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1025,6 +1025,14 @@ config CMD_LSBLK Print list of available block device drivers, and for each, the list of known block devices. +config CMD_MBR + bool "MBR (Master Boot Record) command" + select DOS_PARTITION + select HAVE_BLOCK_DEVICE + help + Enable the 'mbr' command to ready and write MBR (Master Boot Record) + style partition tables. + config CMD_MISC bool "misc" depends on MISC diff --git a/cmd/Makefile b/cmd/Makefile index dd86675bf2..41379d9a0e 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -178,6 +178,7 @@ obj-$(CONFIG_CMD_ZFS) += zfs.o obj-$(CONFIG_CMD_DFU) += dfu.o obj-$(CONFIG_CMD_GPT) += gpt.o +obj-$(CONFIG_CMD_MBR) += mbr.o obj-$(CONFIG_CMD_ETHSW) += ethsw.o obj-$(CONFIG_CMD_AXI) += axi.o obj-$(CONFIG_CMD_PVBLOCK) += pvblock.o diff --git a/cmd/mbr.c b/cmd/mbr.c new file mode 100644 index 00..25a3f694d3 --- /dev/null +++ b/cmd/mbr.c @@ -0,0 +1,308 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * cmd_mbr.c -- MBR (Master Boot Record) handling command + * + * Copyright (C) 2020 Samsung Electronics + * author: Marek Szyprowski + * + * based on the gpt command. + */ + +#include +#include +#include +#include +#include + +/** + * extract_val(): Extract value from a key=value pair list (comma separated). + *Only value for the given key is returend. + *Function allocates memory for the value, remember to free! + * + * @param str - pointer to string with key=values pairs + * @param key - pointer to the key to search for + * + * @return - pointer to allocated string with the value + */ +static char *extract_val(const char *str, const char *key) +{ + char *v, *k; + char *s, *strcopy; + char *new = NULL; + + strcopy = strdup(str); + if (strcopy == NULL) + return NULL; + + s = strcopy; + while (s) { + v = strsep(, ","); + if (!v) + break; + k = strsep(, "="); + if (!k) + break; + if (strcmp(k, key) == 0) { + new = strdup(v); + break; + } + } + + free(strcopy); + + return new; +} + +/** + * found_key(): Found key without value in parameter list (comma separated). + * + * @param str - pointer to string with key + * @param key - pointer to the key to search for + * + * @return - true on found key + */ +static bool found_key(const char *str, const char *key) +{ + char *k; + char *s, *strcopy; + bool result = false; + + strcopy = strdup(str); + if (!strcopy) + return NULL; + + s = strcopy; + while (s) { + k = strsep(, ","); + if (!k) + break; + if (strcmp(k, key) == 0) { + result = true; + break; + } + } + + free(strcopy); + + return result; +} + +static int str_to_partition_info(const char *str_part, unsigned long *disk_uuid, + struct disk_partition **partitions, int *parts_count) +{ + char *tok, *str, *s; + int i; + char *val, *p; + int p_count; + struct disk_partition *parts; + int errno = 0; + uint64_t size_ll, start_ll; + + if (str_part == NULL) +
[PATCH 5/6] disk: dos: add code for creating MBR partition layout
Add a code for creating and writing MBR partition layout. The code generates similar layout of EBRs (Exteneded Block Records) and logical volumes as Linux's fdisk utility. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 167 disk/part_dos.h | 2 + include/part.h | 5 ++ 3 files changed, 174 insertions(+) diff --git a/disk/part_dos.c b/disk/part_dos.c index 2c4ad0b6ba..f77f927995 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -319,6 +319,173 @@ int is_valid_dos_buf(void *buf) return test_block_type(buf) == DOS_MBR ? 0 : -1; } +#if CONFIG_IS_ENABLED(CMD_MBR) +static void lba_to_chs(lbaint_t lba, unsigned char *rc, unsigned char *rh, + unsigned char *rs) +{ + unsigned int c, h, s; + /* use fixed CHS geometry */ + unsigned int sectpertrack = 63; + unsigned int heads = 255; + + c = (lba + 1) / sectpertrack / heads; + h = (lba + 1) / sectpertrack - c * heads; + s = (lba + 1) - (c * heads + h) * sectpertrack; + + if (c > 1023) { + c = 1023; + h = 254; + s = 63; + } + + *rc = c & 0xff; + *rh = h; + *rs = s + ((c & 0x300) >> 2); +} + +static void mbr_fill_pt_entry(dos_partition_t *pt, lbaint_t start, + lbaint_t relative, lbaint_t size, uchar sys_ind, bool bootable) +{ + pt->boot_ind = bootable ? 0x80 : 0x00; + pt->sys_ind = sys_ind; + lba_to_chs(start, >cyl, >head, >sector); + lba_to_chs(start + size - 1, >end_cyl, >end_head, >end_sector); + put_unaligned_le32(relative, >start4); + put_unaligned_le32(size, >size4); +} + +int write_mbr_partitions(struct blk_desc *dev, + struct disk_partition *p, int count, unsigned int disksig) +{ + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, dev->blksz); + lbaint_t ext_part_start = 0, ext_part_size = 0, ext_part_sect = 0; + dos_partition_t *pt; + int i; + + memset(buffer, 0, dev->blksz); + buffer[DOS_PART_MAGIC_OFFSET] = 0x55; + buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa; + put_unaligned_le32(disksig, [DOS_PART_DISKSIG_OFFSET]); + pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); + + /* create all primary partitions */ + for (i = 0; i < 4 && i < count; i++, pt++) { + mbr_fill_pt_entry(pt, p[i].start, p[i].start, p[i].size, + p[i].sys_ind, p[i].bootable); + if (is_extended(p[i].sys_ind)) { + ext_part_start = p[i].start; + ext_part_size = p[i].size; + ext_part_sect = p[i].start; + } + } + + if (i < count && !ext_part_start) { + printf("%s: extended partition is needed for more than 4 partitions\n", + __func__); + return -1; + } + + /* write MBR */ + if (blk_dwrite(dev, 0, 1, buffer) != 1) { + printf("%s: failed writing 'MBR' (1 blks at 0x0)\n", + __func__); + return -1; + } + + /* create extended volumes */ + for (; i < count; i++) { + lbaint_t next_ebr = 0; + + memset(buffer, 0, dev->blksz); + buffer[DOS_PART_MAGIC_OFFSET] = 0x55; + buffer[DOS_PART_MAGIC_OFFSET + 1] = 0xaa; + pt = (dos_partition_t *) (buffer + DOS_PART_TBL_OFFSET); + + mbr_fill_pt_entry(pt, p[i].start, p[i].start - ext_part_sect, + p[i].size, p[i].sys_ind, p[i].bootable); + + if (i + 1 < count) { + pt++; + next_ebr = p[i].start + p[i].size; + mbr_fill_pt_entry(pt, next_ebr, + next_ebr - ext_part_start, + p[i+1].start + p[i+1].size - next_ebr, + DOS_PART_TYPE_EXTENDED, 0); + } + + /* write EBR */ + if (blk_dwrite(dev, ext_part_sect, 1, buffer) != 1) { + printf("%s: failed writing 'EBR' (1 blks at 0x%lx)\n", + __func__, ext_part_sect); + return -1; + } + ext_part_sect = next_ebr; + } + + return 0; +} + +int layout_mbr_partitions(struct disk_partition *p, int count, + lbaint_t total_sectors) +{ + struct disk_partition *ext = NULL; + int i, j; + lbaint_t ext_vol_start; + + /* calculate primary partitions start and size if needed */ + if (!p[0].start) + p[0].start = DOS_PART_DEFAULT_GAP; + for (i = 0; i < 4 && i < count; i+
[PATCH 4/6] disk: dos: make some functions static
Make functions not used outside this file static. Signed-off-by: Marek Szyprowski --- disk/part_dos.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/disk/part_dos.c b/disk/part_dos.c index 3b79b9b1b8..2c4ad0b6ba 100644 --- a/disk/part_dos.c +++ b/disk/part_dos.c @@ -302,13 +302,13 @@ static int part_get_info_extended(struct blk_desc *dev_desc, return -1; } -void part_print_dos(struct blk_desc *dev_desc) +static void part_print_dos(struct blk_desc *dev_desc) { printf("Part\tStart Sector\tNum Sectors\tUUID\t\tType\n"); print_partition_extended(dev_desc, 0, 0, 1, 0); } -int part_get_info_dos(struct blk_desc *dev_desc, int part, +static int part_get_info_dos(struct blk_desc *dev_desc, int part, struct disk_partition *info) { return part_get_info_extended(dev_desc, 0, 0, 1, part, info, 0); -- 2.17.1
[PATCH] cmd: usb_mass_storage: show device interface name
Show the interface name (i.e. 'mmc') in the information string to ease user checking which device is exported via USB Mass Storage protocol. Signed-off-by: Marek Szyprowski --- cmd/usb_mass_storage.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/usb_mass_storage.c b/cmd/usb_mass_storage.c index cf2f55994e..14fa7233c7 100644 --- a/cmd/usb_mass_storage.c +++ b/cmd/usb_mass_storage.c @@ -115,8 +115,8 @@ static int ums_init(const char *devtype, const char *devnums_part_str) ums[ums_count].name = name; ums[ums_count].block_dev = *block_dev; - printf("UMS: LUN %d, dev %d, hwpart %d, sector %#x, count %#x\n", - ums_count, ums[ums_count].block_dev.devnum, + printf("UMS: LUN %d, dev %s %d, hwpart %d, sector %#x, count %#x\n", + ums_count, devtype, ums[ums_count].block_dev.devnum, ums[ums_count].block_dev.hwpart, ums[ums_count].start_sector, ums[ums_count].num_sectors); -- 2.17.1
[PATCH/RFC] board: amlogic: Fix Odroid-C4 SD card reboot issue
For the proper reboot Odroid C4 board requires to switch TFLASH_VDD_EN pin to the input (high impedance?) mode, otherwise the board is stuck in the middle of loading early stages of the bootloader from SD card. This has been achieved by hijacking reset_misc() callback from the PSCI firmware in the Odroid board code. The common meson cpu_reset() function, which is called later during the reboot procedure, will call PSCI reboot anyway. This issue doesn't happen if board is booted from eMMC. Signed-off-by: Marek Szyprowski --- board/amlogic/odroid-n2/odroid-n2.c | 15 +++ configs/odroid-c4_defconfig | 1 + 2 files changed, 16 insertions(+) diff --git a/board/amlogic/odroid-n2/odroid-n2.c b/board/amlogic/odroid-n2/odroid-n2.c index caf7fd6810..ad91de7ac5 100644 --- a/board/amlogic/odroid-n2/odroid-n2.c +++ b/board/amlogic/odroid-n2/odroid-n2.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -47,3 +48,17 @@ int misc_init_r(void) return 0; } + +#ifndef CONFIG_PSCI_RESET +void reset_misc(void) +{ + if (of_machine_is_compatible("hardkernel,odroid-c4")) { + unsigned int gpio; + const char *str_gpio = "aobus-banks3"; + + gpio_lookup_name(str_gpio, NULL, NULL, ); + gpio_request(gpio, "reboot"); + gpio_direction_input(gpio); + } +} +#endif diff --git a/configs/odroid-c4_defconfig b/configs/odroid-c4_defconfig index 367d22db0b..ca0ab71a7a 100644 --- a/configs/odroid-c4_defconfig +++ b/configs/odroid-c4_defconfig @@ -14,6 +14,7 @@ CONFIG_DEBUG_UART=y CONFIG_OF_BOARD_SETUP=y # CONFIG_DISPLAY_CPUINFO is not set CONFIG_MISC_INIT_R=y +# CONFIG_PSCI_RESET is not set # CONFIG_CMD_BDI is not set # CONFIG_CMD_IMI is not set CONFIG_CMD_GPIO=y -- 2.17.1
[PATCH] board: amlogic: vim3: read ethernet MAC address from efuse
Add the board specific code for reading built-in ethernet MAC address from efuse. Signed-off-by: Marek Szyprowski --- board/amlogic/vim3/vim3.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/board/amlogic/vim3/vim3.c b/board/amlogic/vim3/vim3.c index 09ef39ff30..a36df61583 100644 --- a/board/amlogic/vim3/vim3.c +++ b/board/amlogic/vim3/vim3.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "khadas-mcu.h" @@ -129,9 +130,27 @@ int meson_ft_board_setup(void *blob, struct bd_info *bd) return 0; } +#define EFUSE_MAC_OFFSET 0 +#define EFUSE_MAC_SIZE 6 + int misc_init_r(void) { + uint8_t mac_addr[EFUSE_MAC_SIZE]; + ssize_t len; + meson_eth_init(PHY_INTERFACE_MODE_RGMII, 0); + if (!eth_env_get_enetaddr("ethaddr", mac_addr)) { + len = meson_sm_read_efuse(EFUSE_MAC_OFFSET, + mac_addr, EFUSE_MAC_SIZE); + if (len != EFUSE_MAC_SIZE) + return 0; + + if (is_valid_ethaddr(mac_addr)) + eth_env_set_enetaddr("ethaddr", mac_addr); + else + meson_generate_serial_ethaddr(); + } + return 0; } -- 2.17.1
[PATCH v3 5/6] button: add a simple ADC-based button driver
Add a simple Analog to Digital Converter device based button driver. This driver binds to the 'adc-keys' device tree node. Signed-off-by: Marek Szyprowski --- drivers/button/Kconfig | 8 +++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 117 3 files changed, 126 insertions(+) create mode 100644 drivers/button/button-adc.c diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 6b3ec7e55d..6db3c5e93a 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -9,6 +9,14 @@ config BUTTON can provide access to board-specific buttons. Use of the device tree for configuration is encouraged. +config BUTTON_ADC + bool "Button adc" + depends on BUTTON + help + Enable support for buttons which are connected to Analog to Digital + Converter device. The ADC driver must use driver model. Buttons are + configured using the device tree. + config BUTTON_GPIO bool "Button gpio" depends on BUTTON diff --git a/drivers/button/Makefile b/drivers/button/Makefile index fcc10ebe8d..bbd18af149 100644 --- a/drivers/button/Makefile +++ b/drivers/button/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2020 Philippe Reynes obj-$(CONFIG_BUTTON) += button-uclass.o +obj-$(CONFIG_BUTTON_ADC) += button-adc.o obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c new file mode 100644 index 00..086c676c02 --- /dev/null +++ b/drivers/button/button-adc.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + */ + +#include +#include +#include +#include +#include +#include +#include + +struct button_adc_priv { + struct udevice *adc; + int channel; +}; + +static enum button_state_t button_adc_get_state(struct udevice *dev) +{ + struct button_adc_priv *priv = dev_get_priv(dev); + unsigned int val, mask; + int ret; + + ret = adc_start_channel(priv->adc, priv->channel); + if (ret) + return ret; + + ret = adc_channel_data(priv->adc, priv->channel, ); + if (ret) + return ret; + + ret = adc_data_mask(priv->adc, ); + if (ret) + return ret; + + /* getting state is simplified a bit */ + if (ret == 0) + return (val < mask / 2) ? BUTTON_ON : BUTTON_OFF; + + return ret; +} + +static int button_adc_probe(struct udevice *dev) +{ + struct button_uc_plat *uc_plat = dev_get_uclass_platdata(dev); + struct button_adc_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + int ret; + + /* Ignore the top-level button node */ + if (!uc_plat->label) + return 0; + + ret = dev_read_phandle_with_args(dev->parent, "io-channels", +"#io-channel-cells", 0, 0, ); + if (ret) + return ret; + + ret = uclass_get_device_by_name(UCLASS_ADC, ofnode_get_name(args.node), + >adc); + if (ret) + return ret; + + priv->channel = args.args[0]; + + return ret; +} + +static int button_adc_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + struct button_uc_plat *uc_plat; + const char *label; + + label = ofnode_read_string(node, "label"); + if (!label) { + debug("%s: node %s has no label\n", __func__, + ofnode_get_name(node)); + return -EINVAL; + } + ret = device_bind_driver_to_node(parent, "button_adc", +ofnode_get_name(node), +node, ); + if (ret) + return ret; + uc_plat = dev_get_uclass_platdata(dev); + uc_plat->label = label; + } + + return 0; +} + +static const struct button_ops button_adc_ops = { + .get_state = button_adc_get_state, +}; + +static const struct udevice_id button_adc_ids[] = { + { .compatible = "adc-keys" }, + { } +}; + +U_BOOT_DRIVER(button_adc) = { + .name = "button_adc", + .id = UCLASS_BUTTON, + .of_match = button_adc_ids, + .ops= _adc_ops, + .priv_auto_alloc_size = sizeof(struct button_adc_priv), + .bind = button_adc_bind, + .probe = button_adc_probe, +}; -- 2.17.1
[PATCH v3 6/6] configs: khadas-vim3: enable Function button support
Add options required to check the 'Function' button state. Signed-off-by: Marek Szyprowski --- configs/khadas-vim3_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 5d16652fd6..bc17430569 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v3 0/6] VIM3: add support for checking 'Function' button state
Hi All, This patchset adds all building blocks needed for checking the 'Function' button state in the boot script on Amlogic A311D based VIM3 board. This button is connected to the ADC lines of the SoC, so it required to enable meson SARADC, the clocks needed for it and a simple button-adc drivers. Once applied, one can use following commands in the boot scripts: -->8--- echo Checking Func button state: \\c if button Function then echo Selected alternative boot ... fi --->8--- The above script requires commit a6bfd71a96 ("cmd/button: return button status") already present in mainline tree. Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v3: - removed 'button' env variable - extended kconfig and patch descriptions v2: https://lists.denx.de/pipermail/u-boot/2020-December/434991.html - removed Change-Id tags - split defconfig changes into ADC and button related v1: https://lists.denx.de/pipermail/u-boot/2020-December/434875.html - initial submission Patch summary: Marek Szyprowski (6): clk: meson: add minimal driver for g12a-ao clocks adc: meson-saradc: add G12A variant adc: meson-saradc: skip hardware init only if ADC is enabled configs: khadas-vim3: enable ADC device support button: add a simple ADC-based button driver configs: khadas-vim3: enable Function button support configs/khadas-vim3_defconfig | 4 ++ drivers/adc/meson-saradc.c| 9 ++- drivers/button/Kconfig| 8 +++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 117 ++ drivers/clk/meson/Makefile| 1 + drivers/clk/meson/g12a-ao.c | 83 7 files changed, 221 insertions(+), 2 deletions(-) create mode 100644 drivers/button/button-adc.c create mode 100644 drivers/clk/meson/g12a-ao.c -- 2.17.1
[PATCH v3 4/6] configs: khadas-vim3: enable ADC device support
Analog to Digital Converter device (Meson SARADC) will be used for probing 'Function' button state. Signed-off-by: Marek Szyprowski --- configs/khadas-vim3_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 9d7ba72d44..5d16652fd6 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -29,6 +29,8 @@ CONFIG_CMD_REGULATOR=y CONFIG_OF_CONTROL=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_ADC=y +CONFIG_SARADC_MESON=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v3 3/6] adc: meson-saradc: skip hardware init only if ADC is enabled
The driver skips hardware initialization if it is already configured by the earlier bootloader stage (BL30). Skip the initialization only if the hardware is really initialized and enabled. Signed-off-by: Marek Szyprowski Reviewed-by: Neil Armstrong Tested-by: Jaehoon Chung Reviewed-by: Jaehoon Chung --- drivers/adc/meson-saradc.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c index 998cef24d8..ce7ae990ad 100644 --- a/drivers/adc/meson-saradc.c +++ b/drivers/adc/meson-saradc.c @@ -512,8 +512,11 @@ static int meson_saradc_init(struct meson_saradc_priv *priv) * reading the temperature sensor. */ regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ); - if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) - return 0; + if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) { + regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ); + if (regval & MESON_SAR_ADC_REG3_ADC_EN) + return 0; + } meson_saradc_stop_sample_engine(priv); -- 2.17.1
[PATCH v3 2/6] adc: meson-saradc: add G12A variant
Add support for the SARADC variant found on the G12A SoCs family. Signed-off-by: Marek Szyprowski Reviewed-by: Neil Armstrong Tested-by: Jaehoon Chung Reviewed-by: Jaehoon Chung --- drivers/adc/meson-saradc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c index 72b0cc4e5b..998cef24d8 100644 --- a/drivers/adc/meson-saradc.c +++ b/drivers/adc/meson-saradc.c @@ -711,6 +711,8 @@ static const struct udevice_id meson_saradc_ids[] = { .data = (ulong)_saradc_data }, { .compatible = "amlogic,meson-gxm-saradc", .data = (ulong)_saradc_data }, + { .compatible = "amlogic,meson-g12a-saradc", + .data = (ulong)_saradc_data }, { } }; -- 2.17.1
[PATCH v3 1/6] clk: meson: add minimal driver for g12a-ao clocks
Add minimal driver AO clocks on meson G12A family. Only ADC related clocks are supported. Signed-off-by: Marek Szyprowski Reviewed-by: Neil Armstrong Tested-by: Jaehoon Chung Reviewed-by: Jaehoon Chung --- drivers/clk/meson/Makefile | 1 + drivers/clk/meson/g12a-ao.c | 83 + 2 files changed, 84 insertions(+) create mode 100644 drivers/clk/meson/g12a-ao.c diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index c873d6976f..7204383e17 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_CLK_MESON_GX) += gxbb.o obj-$(CONFIG_CLK_MESON_AXG) += axg.o obj-$(CONFIG_CLK_MESON_G12A) += g12a.o +obj-$(CONFIG_CLK_MESON_G12A) += g12a-ao.o diff --git a/drivers/clk/meson/g12a-ao.c b/drivers/clk/meson/g12a-ao.c new file mode 100644 index 00..7a0abea77c --- /dev/null +++ b/drivers/clk/meson/g12a-ao.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk_meson.h" + +struct meson_clk { + struct regmap *map; +}; + +#define AO_CLK_GATE0 0x4c +#define AO_SAR_CLK 0x90 + +static struct meson_gate gates[] = { + MESON_GATE(CLKID_AO_SAR_ADC, AO_CLK_GATE0, 8), + MESON_GATE(CLKID_AO_SAR_ADC_CLK, AO_SAR_CLK, 8), +}; + +static int meson_set_gate(struct clk *clk, bool on) +{ + struct meson_clk *priv = dev_get_priv(clk->dev); + struct meson_gate *gate; + + if (clk->id >= ARRAY_SIZE(gates)) + return -ENOENT; + + gate = [clk->id]; + + if (gate->reg == 0) + return 0; + + regmap_update_bits(priv->map, gate->reg, + BIT(gate->bit), on ? BIT(gate->bit) : 0); + + return 0; +} + +static int meson_clk_enable(struct clk *clk) +{ + return meson_set_gate(clk, true); +} + +static int meson_clk_disable(struct clk *clk) +{ + return meson_set_gate(clk, false); +} + +static int meson_clk_probe(struct udevice *dev) +{ + struct meson_clk *priv = dev_get_priv(dev); + + priv->map = syscon_node_to_regmap(dev_get_parent(dev)->node); + if (IS_ERR(priv->map)) + return PTR_ERR(priv->map); + + return 0; +} + +static struct clk_ops meson_clk_ops = { + .disable= meson_clk_disable, + .enable = meson_clk_enable, +}; + +static const struct udevice_id meson_clk_ids[] = { + { .compatible = "amlogic,meson-g12a-aoclkc" }, + { } +}; + +U_BOOT_DRIVER(meson_clk_axg) = { + .name = "meson_clk_g12a_ao", + .id = UCLASS_CLK, + .of_match = meson_clk_ids, + .priv_auto_alloc_size = sizeof(struct meson_clk), + .ops= _clk_ops, + .probe = meson_clk_probe, +}; -- 2.17.1
Re: [PATCH v2 6/7 RESEND] cmd: button: store button state in the 'button' env
On 16.12.2020 08:29, Heinrich Schuchardt wrote: > On 12/16/20 8:08 AM, Marek Szyprowski wrote: >> On 15.12.2020 20:07, Heinrich Schuchardt wrote: >>> On 12/15/20 5:54 PM, Marek Szyprowski wrote: >>>> Save examined button state in 'button' environment variable to enable >>>> checking button state in the scripts. >>>> >>>> Signed-off-by: Marek Szyprowski >>>> --- >>>> Resend reason: get rid of the Change-Id tag, that was still in v2. >>>> --- >>>> cmd/button.c | 4 +++- >>>> 1 file changed, 3 insertions(+), 1 deletion(-) >>>> >>>> diff --git a/cmd/button.c b/cmd/button.c >>>> index 64c5a8fa04..8da911068a 100644 >>>> --- a/cmd/button.c >>>> +++ b/cmd/button.c >>>> @@ -23,8 +23,10 @@ static int show_button_state(struct udevice *dev) >>>> ret = button_get_state(dev); >>>> if (ret >= BUTTON_COUNT) >>>> ret = -EINVAL; >>>> - if (ret >= 0) >>>> + if (ret >= 0) { >>>> printf("%s\n", state_label[ret]); >>>> + env_set("button", state_label[ret]); >>> >>> Using a hard coded environment variable does not make much sense to me. >>> The button command has a return value. So just use >>> >>> button mybutton; setenv myvar $? >>> >> Thanks for the hint, I wasn't aware that uboot supports '$?'. By setting >> the 'button' env variable I've tried to mimic the behavior of the >> various network and file related commands, which sets 'filesize' env >> variable. >> >> I will need to add the return value propagation to the button command >> anyway to make it usable from the scripts. > > Nothing to be done for the button command. Since > > a6bfd71a96201127836d59736abcb54dc2d5e1a5 > cmd/button: return button status > > the button command returns > > 0 (true) - pressed, on > 1 (false) - not pressed, off > Right, I've missed that commit. I've developed my code on top of v2020.10 release. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
Re: [PATCH v2 6/7 RESEND] cmd: button: store button state in the 'button' env
On 15.12.2020 20:07, Heinrich Schuchardt wrote: > On 12/15/20 5:54 PM, Marek Szyprowski wrote: >> Save examined button state in 'button' environment variable to enable >> checking button state in the scripts. >> >> Signed-off-by: Marek Szyprowski >> --- >> Resend reason: get rid of the Change-Id tag, that was still in v2. >> --- >> cmd/button.c | 4 +++- >> 1 file changed, 3 insertions(+), 1 deletion(-) >> >> diff --git a/cmd/button.c b/cmd/button.c >> index 64c5a8fa04..8da911068a 100644 >> --- a/cmd/button.c >> +++ b/cmd/button.c >> @@ -23,8 +23,10 @@ static int show_button_state(struct udevice *dev) >> ret = button_get_state(dev); >> if (ret >= BUTTON_COUNT) >> ret = -EINVAL; >> - if (ret >= 0) >> + if (ret >= 0) { >> printf("%s\n", state_label[ret]); >> + env_set("button", state_label[ret]); > > Using a hard coded environment variable does not make much sense to me. > The button command has a return value. So just use > > button mybutton; setenv myvar $? > Thanks for the hint, I wasn't aware that uboot supports '$?'. By setting the 'button' env variable I've tried to mimic the behavior of the various network and file related commands, which sets 'filesize' env variable. I will need to add the return value propagation to the button command anyway to make it usable from the scripts. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland
[PATCH v2 6/7 RESEND] cmd: button: store button state in the 'button' env
Save examined button state in 'button' environment variable to enable checking button state in the scripts. Signed-off-by: Marek Szyprowski --- Resend reason: get rid of the Change-Id tag, that was still in v2. --- cmd/button.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/button.c b/cmd/button.c index 64c5a8fa04..8da911068a 100644 --- a/cmd/button.c +++ b/cmd/button.c @@ -23,8 +23,10 @@ static int show_button_state(struct udevice *dev) ret = button_get_state(dev); if (ret >= BUTTON_COUNT) ret = -EINVAL; - if (ret >= 0) + if (ret >= 0) { printf("%s\n", state_label[ret]); + env_set("button", state_label[ret]); + } return ret; } -- 2.17.1
[PATCH v2 5/7] button: add a simple ADC-based button driver
Add a simple ADC-based button driver. This driver binds to the 'adc-keys' device tree node. Signed-off-by: Marek Szyprowski --- drivers/button/Kconfig | 8 +++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 117 3 files changed, 126 insertions(+) create mode 100644 drivers/button/button-adc.c diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig index 6b3ec7e55d..283367f2bd 100644 --- a/drivers/button/Kconfig +++ b/drivers/button/Kconfig @@ -9,6 +9,14 @@ config BUTTON can provide access to board-specific buttons. Use of the device tree for configuration is encouraged. +config BUTTON_ADC + bool "Button adc" + depends on BUTTON + help + Enable support for buttons which are connected to ADC lines. The ADC + driver must use driver model. Buttons are configured using the device + tree. + config BUTTON_GPIO bool "Button gpio" depends on BUTTON diff --git a/drivers/button/Makefile b/drivers/button/Makefile index fcc10ebe8d..bbd18af149 100644 --- a/drivers/button/Makefile +++ b/drivers/button/Makefile @@ -3,4 +3,5 @@ # Copyright (C) 2020 Philippe Reynes obj-$(CONFIG_BUTTON) += button-uclass.o +obj-$(CONFIG_BUTTON_ADC) += button-adc.o obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c new file mode 100644 index 00..086c676c02 --- /dev/null +++ b/drivers/button/button-adc.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + */ + +#include +#include +#include +#include +#include +#include +#include + +struct button_adc_priv { + struct udevice *adc; + int channel; +}; + +static enum button_state_t button_adc_get_state(struct udevice *dev) +{ + struct button_adc_priv *priv = dev_get_priv(dev); + unsigned int val, mask; + int ret; + + ret = adc_start_channel(priv->adc, priv->channel); + if (ret) + return ret; + + ret = adc_channel_data(priv->adc, priv->channel, ); + if (ret) + return ret; + + ret = adc_data_mask(priv->adc, ); + if (ret) + return ret; + + /* getting state is simplified a bit */ + if (ret == 0) + return (val < mask / 2) ? BUTTON_ON : BUTTON_OFF; + + return ret; +} + +static int button_adc_probe(struct udevice *dev) +{ + struct button_uc_plat *uc_plat = dev_get_uclass_platdata(dev); + struct button_adc_priv *priv = dev_get_priv(dev); + struct ofnode_phandle_args args; + int ret; + + /* Ignore the top-level button node */ + if (!uc_plat->label) + return 0; + + ret = dev_read_phandle_with_args(dev->parent, "io-channels", +"#io-channel-cells", 0, 0, ); + if (ret) + return ret; + + ret = uclass_get_device_by_name(UCLASS_ADC, ofnode_get_name(args.node), + >adc); + if (ret) + return ret; + + priv->channel = args.args[0]; + + return ret; +} + +static int button_adc_bind(struct udevice *parent) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + struct button_uc_plat *uc_plat; + const char *label; + + label = ofnode_read_string(node, "label"); + if (!label) { + debug("%s: node %s has no label\n", __func__, + ofnode_get_name(node)); + return -EINVAL; + } + ret = device_bind_driver_to_node(parent, "button_adc", +ofnode_get_name(node), +node, ); + if (ret) + return ret; + uc_plat = dev_get_uclass_platdata(dev); + uc_plat->label = label; + } + + return 0; +} + +static const struct button_ops button_adc_ops = { + .get_state = button_adc_get_state, +}; + +static const struct udevice_id button_adc_ids[] = { + { .compatible = "adc-keys" }, + { } +}; + +U_BOOT_DRIVER(button_adc) = { + .name = "button_adc", + .id = UCLASS_BUTTON, + .of_match = button_adc_ids, + .ops= _adc_ops, + .priv_auto_alloc_size = sizeof(struct button_adc_priv), + .bind = button_adc_bind, + .probe = button_adc_probe, +}; -- 2.17.1
[PATCH v2 1/7] clk: meson: add minimal driver for g12a-ao clocks
Add minimal driver AO clocks on meson G12A family. Only ADC related clocks are supported. Signed-off-by: Marek Szyprowski Reviewed-by: Neil Armstrong Tested-by: Jaehoon Chung Reviewed-by: Jaehoon Chung --- drivers/clk/meson/Makefile | 1 + drivers/clk/meson/g12a-ao.c | 83 + 2 files changed, 84 insertions(+) create mode 100644 drivers/clk/meson/g12a-ao.c diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index c873d6976f..7204383e17 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_CLK_MESON_GX) += gxbb.o obj-$(CONFIG_CLK_MESON_AXG) += axg.o obj-$(CONFIG_CLK_MESON_G12A) += g12a.o +obj-$(CONFIG_CLK_MESON_G12A) += g12a-ao.o diff --git a/drivers/clk/meson/g12a-ao.c b/drivers/clk/meson/g12a-ao.c new file mode 100644 index 00..7a0abea77c --- /dev/null +++ b/drivers/clk/meson/g12a-ao.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "clk_meson.h" + +struct meson_clk { + struct regmap *map; +}; + +#define AO_CLK_GATE0 0x4c +#define AO_SAR_CLK 0x90 + +static struct meson_gate gates[] = { + MESON_GATE(CLKID_AO_SAR_ADC, AO_CLK_GATE0, 8), + MESON_GATE(CLKID_AO_SAR_ADC_CLK, AO_SAR_CLK, 8), +}; + +static int meson_set_gate(struct clk *clk, bool on) +{ + struct meson_clk *priv = dev_get_priv(clk->dev); + struct meson_gate *gate; + + if (clk->id >= ARRAY_SIZE(gates)) + return -ENOENT; + + gate = [clk->id]; + + if (gate->reg == 0) + return 0; + + regmap_update_bits(priv->map, gate->reg, + BIT(gate->bit), on ? BIT(gate->bit) : 0); + + return 0; +} + +static int meson_clk_enable(struct clk *clk) +{ + return meson_set_gate(clk, true); +} + +static int meson_clk_disable(struct clk *clk) +{ + return meson_set_gate(clk, false); +} + +static int meson_clk_probe(struct udevice *dev) +{ + struct meson_clk *priv = dev_get_priv(dev); + + priv->map = syscon_node_to_regmap(dev_get_parent(dev)->node); + if (IS_ERR(priv->map)) + return PTR_ERR(priv->map); + + return 0; +} + +static struct clk_ops meson_clk_ops = { + .disable= meson_clk_disable, + .enable = meson_clk_enable, +}; + +static const struct udevice_id meson_clk_ids[] = { + { .compatible = "amlogic,meson-g12a-aoclkc" }, + { } +}; + +U_BOOT_DRIVER(meson_clk_axg) = { + .name = "meson_clk_g12a_ao", + .id = UCLASS_CLK, + .of_match = meson_clk_ids, + .priv_auto_alloc_size = sizeof(struct meson_clk), + .ops= _clk_ops, + .probe = meson_clk_probe, +}; -- 2.17.1
[PATCH v2 4/7] configs: khadas-vim3: enable ADC device support
ADC device (Meson SARADC) will be used for probing 'Function' button state. Signed-off-by: Marek Szyprowski --- configs/khadas-vim3_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 9d7ba72d44..5d16652fd6 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -29,6 +29,8 @@ CONFIG_CMD_REGULATOR=y CONFIG_OF_CONTROL=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_ADC=y +CONFIG_SARADC_MESON=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v2 0/7] VIM3: add support for checking 'Function' button state
Hi All, This patchset adds all building blocks needed for checking the 'Function' button state in the boot script on Amlogic A311D based VIM3 board. This button is connected to the ADC lines of the SoC, so it required to enable meson SARADC, the clocks needed for it and a simple button-adc drivers. Once applied, one can use following commands in the boot scripts: -->8--- echo Checking Func button state: \\c button Function if test ${button} = on then echo Selected alternative boot ... fi --->8--- Best regards Marek Szyprowski Samsung R Institute Poland Changelog: v2: - removed Change-Id tags - split defconfig changes into ADC and button related v1: https://lists.denx.de/pipermail/u-boot/2020-December/434875.html - initial submission Patch summary: Marek Szyprowski (7): clk: meson: add minimal driver for g12a-ao clocks adc: meson-saradc: add G12A variant adc: meson-saradc: skip hardware init only if ADC is enabled configs: khadas-vim3: enable ADC device support button: add a simple ADC-based button driver cmd: button: store button state in the 'button' env configs: khadas-vim3: enable Function button support cmd/button.c | 4 +- configs/khadas-vim3_defconfig | 4 ++ drivers/adc/meson-saradc.c| 9 ++- drivers/button/Kconfig| 8 +++ drivers/button/Makefile | 1 + drivers/button/button-adc.c | 117 ++ drivers/clk/meson/Makefile| 1 + drivers/clk/meson/g12a-ao.c | 83 8 files changed, 224 insertions(+), 3 deletions(-) create mode 100644 drivers/button/button-adc.c create mode 100644 drivers/clk/meson/g12a-ao.c -- 2.17.1
[PATCH v2 2/7] adc: meson-saradc: add G12A variant
Add support for the SARADC variant found on the G12A SoCs family. Signed-off-by: Marek Szyprowski Reviewed-by: Neil Armstrong Tested-by: Jaehoon Chung Reviewed-by: Jaehoon Chung --- drivers/adc/meson-saradc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c index 72b0cc4e5b..998cef24d8 100644 --- a/drivers/adc/meson-saradc.c +++ b/drivers/adc/meson-saradc.c @@ -711,6 +711,8 @@ static const struct udevice_id meson_saradc_ids[] = { .data = (ulong)_saradc_data }, { .compatible = "amlogic,meson-gxm-saradc", .data = (ulong)_saradc_data }, + { .compatible = "amlogic,meson-g12a-saradc", + .data = (ulong)_saradc_data }, { } }; -- 2.17.1
[PATCH v2 7/7] configs: khadas-vim3: enable Function button support
Add options needed to check the 'Function' button state. Signed-off-by: Marek Szyprowski --- configs/khadas-vim3_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig index 5d16652fd6..bc17430569 100644 --- a/configs/khadas-vim3_defconfig +++ b/configs/khadas-vim3_defconfig @@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_ADC=y CONFIG_SARADC_MESON=y +CONFIG_BUTTON=y +CONFIG_BUTTON_ADC=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_MESON=y CONFIG_DM_MMC=y -- 2.17.1
[PATCH v2 6/7] cmd: button: store button state in the 'button' env
Save examined button state in 'button' environment variable to enable checking button state in the scripts. Signed-off-by: Marek Szyprowski Change-Id: I78b539e1516573fcfea4401f75469291844daae4 --- cmd/button.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/button.c b/cmd/button.c index 64c5a8fa04..8da911068a 100644 --- a/cmd/button.c +++ b/cmd/button.c @@ -23,8 +23,10 @@ static int show_button_state(struct udevice *dev) ret = button_get_state(dev); if (ret >= BUTTON_COUNT) ret = -EINVAL; - if (ret >= 0) + if (ret >= 0) { printf("%s\n", state_label[ret]); + env_set("button", state_label[ret]); + } return ret; } -- 2.17.1
[PATCH v2 3/7] adc: meson-saradc: skip hardware init only if ADC is enabled
The driver skips hardware initialization if it is already configured by the earlier bootloader stage (BL30). Skip the initialization only if the hardware is really initialized and enabled. Signed-off-by: Marek Szyprowski Reviewed-by: Neil Armstrong Tested-by: Jaehoon Chung Reviewed-by: Jaehoon Chung --- drivers/adc/meson-saradc.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/adc/meson-saradc.c b/drivers/adc/meson-saradc.c index 998cef24d8..ce7ae990ad 100644 --- a/drivers/adc/meson-saradc.c +++ b/drivers/adc/meson-saradc.c @@ -512,8 +512,11 @@ static int meson_saradc_init(struct meson_saradc_priv *priv) * reading the temperature sensor. */ regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ); - if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) - return 0; + if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) { + regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ); + if (regval & MESON_SAR_ADC_REG3_ADC_EN) + return 0; + } meson_saradc_stop_sample_engine(priv); -- 2.17.1
Re: [PATCH 6/6] configs: khadas-vim3: enable Function button support
Hi Neil, On 14.12.2020 19:55, Neil Armstrong wrote: > On 14/12/2020 12:24, Marek Szyprowski wrote: >> Add options required to check the 'Function' button state. >> >> Signed-off-by: Marek Szyprowski >> --- >> configs/khadas-vim3_defconfig | 4 >> 1 file changed, 4 insertions(+) >> >> diff --git a/configs/khadas-vim3_defconfig b/configs/khadas-vim3_defconfig >> index 9d7ba72d440..bc174305692 100644 >> --- a/configs/khadas-vim3_defconfig >> +++ b/configs/khadas-vim3_defconfig >> @@ -29,6 +29,10 @@ CONFIG_CMD_REGULATOR=y >> CONFIG_OF_CONTROL=y >> CONFIG_SYS_RELOC_GD_ENV_ADDR=y >> CONFIG_NET_RANDOM_ETHADDR=y >> +CONFIG_ADC=y >> +CONFIG_SARADC_MESON=y >> +CONFIG_BUTTON=y >> +CONFIG_BUTTON_ADC=y >> CONFIG_DM_I2C=y >> CONFIG_SYS_I2C_MESON=y >> CONFIG_DM_MMC=y >> > If you separate the ADC configs and Button configs, I can directly apply the > clk-ao & adc patches > for next release. Sure, no problem. I'm sorry for the change-id mess, I forgot to clean it before submission. I will send v2 soon. Best regards -- Marek Szyprowski, PhD Samsung R Institute Poland