diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..9668c64 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +debootstrap +debootstrap-prefetched +deploy +toolchain/extracted diff --git a/.gitignore b/.gitignore index 5178f5a..6087527 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ toolchain/extracted *.tsv *.xml *.bak +pcb/ +opencode.json +.config/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..09170e8 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,104 @@ +# AGENTS.md + +## Build SD card image + +Uses Docker - no host dependencies needed. + +```bash +# First run (prefetch debootstrap + build kernel/uboot/tfa) +docker compose run build --variant decktrix --prefetch-debootstrap + +# Subsequent builds (uses cached debootstrap) +docker compose run build --variant decktrix --use-prefetch-debootstrap +``` + +Output: `deploy/sdcard.img.gz` + +Variants: `stm32`, `stm32-jadard`, `decktrix` + +## Project structure + +- `Dockerfile` + `docker-compose.yml` - build environment +- `build-image.sh` - main build script +- `board/linux/patches/` - kernel patches (Jadard driver, DTS, pinctrl) +- `board/tfa/patches/` - TF-A patches (pinctrl) +- `board/u-boot/patches/` - U-Boot patches (DSI disable, pinctrl) +- `board/tfa/decktrix-v1.dts` - TF-A device tree (LDO overrides) +- `board/u-boot/decktrix-v1.dts` - U-Boot device tree +- `scripts/gdrive-upload.sh` - upload file to Google Drive +- `scripts/gdrive-auth.sh` - re-authenticate when token expires + +## Decktrix v1 board differences from DK2 + +| Component | Devboard (DK2) | Decktrix PCB | +|---|---|---| +| PMIC I2C4 SCL | PZ4 | PD12 (AF4) | +| PMIC I2C4 SDA | PZ5 | PD13 (AF4) | +| LDO1 | 1.8V (v1v8_audio) | 2.8V (display AVDD) | +| LDO6 | 1.2V (v1v2_hdmi) | 1.8V (display IOVCC) | +| LCD reset | PE4 | PD11 | +| LCD backlight | PA15 | PF6 (TPS61042 ctrl) | +| Touch IRQ | PF2 | PG7 | +| Touch reset | PF4 | PE10 | +| BT UART | USART2 (PA2/PA3) | UART8 (PE0/PE1) | +| BT shutdown | PZ6 | PB10 | +| WiFi reset | PH4 | PE6 | +| WiFi chip | BCM43430 | u-blox MAYA-W166 (NXP IW416) | +| Display power | GPIO vdd/vccio | Always-on PMIC rails | + +Display is powered by PMIC regulators (always-on): +- LDO1 (2.8V) -> display AVDD +- LDO6 (1.8V) -> display IOVCC +- No GPIO enable needed + +Jadard driver uses `devm_gpiod_get_optional()` for vdd/vccio/dbg GPIOs. + +## Creating patches + +**Do NOT write patch files manually.** Always: +1. Reset the relevant git tree to clean state +2. Apply existing patches in order +3. Make the desired changes to the source files +4. Run `git diff` (or `git diff --cached` after `git add`) +5. Wrap the diff in a proper patch header (From/Date/Subject/Signed-off-by) +6. Save as the next numbered patch file in the `patches/` directory +7. Remove any standalone files that should be in the patch (not copied) + +## Google Drive upload + +```bash +./scripts/gdrive-upload.sh +``` + +Credentials in `.config/opencode/gdrive-token.json` (not in git). + +### Initial setup (from scratch) + +1. Go to [Google Cloud Console](https://console.cloud.google.com/) +2. Create project `decktrix` +3. Enable **Google Drive API** (APIs & Services -> Library) +4. Go to **APIs & Services -> OAuth consent screen** +5. Set User type to **External** +6. Add your email under **Test users** +7. Go to **APIs & Services -> Credentials** +8. Click **Create Credentials -> OAuth client ID** +9. Application type: **Desktop app**, name: `decktrix` +10. Click **Create** +11. Click **Download JSON** on the popup +12. Save as `~/.config/opencode/gcp-oauth.json` +13. Run `./scripts/gdrive-auth.sh` +14. It prints an OAuth URL - open in browser +15. Sign in with your Google account, approve access +16. Browser redirects to `http://localhost/?code=XXXXX...` +17. Copy the code from the URL (everything between `code=` and `&`) +18. Paste it into the terminal +19. Script creates `.config/opencode/gdrive-token.json` + +### When token expires (after 7 days) + +The refresh token expires after 7 days. When this happens: +1. `gdrive-upload.sh` will fail with "Failed to refresh access token" +2. Run `./scripts/gdrive-auth.sh` +3. It prints an OAuth URL - open it, approve, paste the code +4. Token file is updated automatically +5. Run `gdrive-upload.sh` again diff --git a/Dockerfile b/Dockerfile index c73ba8d..3fc4d7c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,13 @@ FROM ubuntu:noble -RUN apt-get update +ENV DEBIAN_FRONTEND=noninteractive -RUN apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ wget \ + curl \ + ca-certificates \ + git \ bc \ bison \ build-essential \ @@ -16,11 +19,24 @@ RUN apt-get install -y \ python3-setuptools \ swig \ uuid-dev \ - build-essential \ python3-cryptography \ python3-pyelftools \ - build-essential \ device-tree-compiler \ dosfstools \ genimage \ mtools \ + debootstrap \ + qemu-user-static \ + && rm -rf /var/lib/apt/lists/* + +RUN echo "ubuntu ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/builduser \ + && chmod 0440 /etc/sudoers.d/builduser + +WORKDIR /build + +COPY build-image.sh . +RUN chmod +x build-image.sh + +USER ubuntu + +ENTRYPOINT ["./build-image.sh"] diff --git a/README.md b/README.md index e602779..000c8bc 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,25 @@ design and features are expected. git submodule update --init --recursive --depth 1 ``` -2. Prefetch debootstrap on first run to speed next iterations +### Using Docker (recommended) + +No need to install dependencies on the host or provide sudo password. + +2. Prefetch debootstrap on first run to speed up next iterations + +``` +docker compose run build --prefetch-debootstrap +``` + +3. Build SD card image + +``` +docker compose run build --use-prefetch-debootstrap +``` + +### Using host directly + +2. Prefetch debootstrap on first run to speed up next iterations ``` sudo ./build-image.sh --prefetch-debootstrap diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..fcca093 --- /dev/null +++ b/TODO.md @@ -0,0 +1,4 @@ +# TODO + +- [ ] SD card detect: replace `broken-cd` with actual GPIO `<&gpioe 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>` (PE3) in both U-Boot and kernel DTS patches +- [ ] WiFi/BT: u-blox MAYA-W166 (NXP IW416) driver, SDMMC3, UART8 diff --git a/board/linux/patches/0003-display-Add-Jadard-MIPI-driver.patch b/board/linux/patches/0003-display-Add-Jadard-MIPI-driver.patch index b64de50..15b5a71 100644 --- a/board/linux/patches/0003-display-Add-Jadard-MIPI-driver.patch +++ b/board/linux/patches/0003-display-Add-Jadard-MIPI-driver.patch @@ -10,7 +10,7 @@ Signed-off-by: Kirill Yatsenko drivers/gpu/drm/panel/Kconfig | 8 + drivers/gpu/drm/panel/Makefile | 1 + drivers/gpu/drm/panel/panel-jadard-jd9365tn.c | 489 ++++++++++++++++++ - 5 files changed, 506 insertions(+), 3 deletions(-) + 5 files changed, 494 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/panel/panel-jadard-jd9365tn.c diff --git a/arch/arm/boot/dts/st/stm32mp157c-dk2-jadard.dts b/arch/arm/boot/dts/st/stm32mp157c-dk2-jadard.dts @@ -84,7 +84,7 @@ new file mode 100644 index 000000000000..2537338a081b --- /dev/null +++ b/drivers/gpu/drm/panel/panel-jadard-jd9365tn.c -@@ -0,0 +1,489 @@ +@@ -0,0 +1,477 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Author: @@ -500,25 +500,13 @@ index 000000000000..2537338a081b + } + + /* VDD pin is connected to power regulator enable pin on adapter board */ -+ jadard->vdd = devm_gpiod_get(dev, "vdd", GPIOD_OUT_LOW); -+ if (IS_ERR(jadard->vdd)) { -+ DRM_DEV_ERROR(&dsi->dev, "failed to get vdd GPIO\n"); -+ return PTR_ERR(jadard->vdd); -+ } ++ jadard->vdd = devm_gpiod_get_optional(dev, "vdd", GPIOD_OUT_LOW); + + /* VCCIO pin is connected to power regulator enable pin on adapter board */ -+ jadard->vccio = devm_gpiod_get(dev, "vccio", GPIOD_OUT_LOW); -+ if (IS_ERR(jadard->vccio)) { -+ DRM_DEV_ERROR(&dsi->dev, "failed to get vccio GPIO\n"); -+ return PTR_ERR(jadard->vccio); -+ } ++ jadard->vccio = devm_gpiod_get_optional(dev, "vccio", GPIOD_OUT_LOW); + -+ /* DBG pin is used for osciloscope debugging */ -+ jadard->dbg = devm_gpiod_get(dev, "dbg", GPIOD_OUT_HIGH); -+ if (IS_ERR(jadard->dbg)) { -+ DRM_DEV_ERROR(&dsi->dev, "failed to get dbg GPIO\n"); -+ return PTR_ERR(jadard->dbg); -+ } ++ /* DBG pin is used for oscilloscope debugging */ ++ jadard->dbg = devm_gpiod_get_optional(dev, "dbg", GPIOD_OUT_HIGH); + + drm_panel_init(&jadard->panel, dev, &jadard_funcs, + DRM_MODE_CONNECTOR_DSI); diff --git a/board/linux/patches/0006-dts-Add-Decktrix-custom-PCB-device-tree.patch b/board/linux/patches/0006-dts-Add-Decktrix-custom-PCB-device-tree.patch new file mode 100644 index 0000000..e09a29b --- /dev/null +++ b/board/linux/patches/0006-dts-Add-Decktrix-custom-PCB-device-tree.patch @@ -0,0 +1,275 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kirill Yatsenko +Date: Thu, 03 Apr 2026 13:00:00 +0200 +Subject: dts: Add device tree for decktrix custom PCB + +The decktrix board is based on STM32MP157F with different pinout: + +- STPMIC1 PMIC on I2C4 at PD12/PD13 instead of PZ4/PZ5 +- Jadard JD9365TN touchscreen on I2C1 at PB7/PB8 (IRQ=PG7, reset=PE10) +- Jadard DSI display (reset=PD11, backlight=PF6, powered by PMIC LDO1/LDO6) +- LDO1 at 2.8V for display AVDD (not 1.8V for audio) +- LDO6 at 1.8V for display IOVCC (not 1.2V for HDMI) + +Signed-off-by: Kirill Yatsenko +--- +diff --git a/arch/arm/boot/dts/st/decktrix-v1.dts b/arch/arm/boot/dts/st/decktrix-v1.dts +new file mode 100644 +index 000000000..869ca7153 +--- /dev/null ++++ b/arch/arm/boot/dts/st/decktrix-v1.dts +@@ -0,0 +1,252 @@ ++#include "stm32mp157c-dk2.dts" ++ ++/ { ++ model = "Decktrix v1"; ++ compatible = "decktrix,v1", "st,stm32mp157"; ++}; ++ ++&i2c4 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&i2c4_pins_a>; ++ pinctrl-1 = <&i2c4_sleep_pins_a>; ++ i2c-scl-rising-time-ns = <185>; ++ i2c-scl-falling-time-ns = <20>; ++ clock-frequency = <400000>; ++ status = "okay"; ++ ++ pmic: stpmic@33 { ++ compatible = "st,stpmic1"; ++ reg = <0x33>; ++ interrupts-extended = <&exti 55 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-controller; ++ #interrupt-cells = <2>; ++ status = "okay"; ++ ++ regulators { ++ compatible = "st,stpmic1-regulators"; ++ status = "okay"; ++ ++ ldo1-supply = <&v3v3>; ++ ldo2-supply = <&v3v3>; ++ ldo3-supply = <&vdd_ddr>; ++ ldo5-supply = <&v3v3>; ++ ldo6-supply = <&v3v3>; ++ pwr_sw1-supply = <&bst_out>; ++ pwr_sw2-supply = <&bst_out>; ++ ++ vddcore: buck1 { ++ regulator-name = "vddcore"; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ regulator-initial-mode = <0>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ vdd_ddr: buck2 { ++ regulator-name = "vdd_ddr"; ++ regulator-min-microvolt = <1350000>; ++ regulator-max-microvolt = <1350000>; ++ regulator-always-on; ++ regulator-active-discharge = <1>; ++ regulator-initial-mode = <0>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1350000>; ++ }; ++ }; ++ ++ vdd: buck3 { ++ regulator-name = "vdd"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ st,mask-reset; ++ regulator-initial-mode = <0>; ++ regulator-state-mem { ++ regulator-off-in-suspend; ++ }; ++ }; ++ ++ v3v3: buck4 { ++ regulator-name = "v3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-active-discharge = <1>; ++ regulator-initial-mode = <0>; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ ldo1 { ++ regulator-name = "ldo1"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ interrupts = ; ++ }; ++ ++ v2v8: ldo2 { ++ regulator-name = "ldo2"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ interrupts = ; ++ }; ++ ++ ldo3 { ++ regulator-name = "ldo3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-always-on; ++ regulator-active-discharge = <1>; ++ interrupts = ; ++ }; ++ ++ vdd_usb: ldo4 { ++ regulator-name = "ldo4"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-active-discharge = <1>; ++ interrupts = ; ++ }; ++ ++ vdd_sd: ldo5 { ++ regulator-name = "ldo5"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-boot-on; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ interrupts = ; ++ regulator-state-mem { ++ regulator-suspend-microvolt = <3300000>; ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ ldo6 { ++ regulator-name = "ldo6"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-active-discharge = <1>; ++ regulator-always-on; ++ interrupts = ; ++ }; ++ ++ vref_ddr: vref_ddr { ++ regulator-name = "vref_ddr"; ++ regulator-always-on; ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ bst_out: boost { ++ regulator-name = "bst_out"; ++ interrupts = ; ++ }; ++ ++ vbus_otg: pwr_sw1 { ++ regulator-name = "vbus_otg"; ++ interrupts = ; ++ regulator-active-discharge = <1>; ++ }; ++ ++ vbus_sw: pwr_sw2 { ++ regulator-name = "vbus_sw"; ++ interrupts = ; ++ regulator-active-discharge = <1>; ++ regulator-boot-on; ++ }; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&i2c1_pins_d>; ++ pinctrl-1 = <&i2c1_sleep_pins_d>; ++ status = "okay"; ++ ++ jadard@68 { ++ compatible = "jadard,jdcommon"; ++ reg = <0x68>; ++ interrupts = <13 IRQ_TYPE_EDGE_FALLING>; ++ interrupt-parent = <&gpiog>; ++ jadard,irq-gpio = <&gpiog 7 GPIO_ACTIVE_HIGH>; ++ jadard,rst-gpio = <&gpioe 10 GPIO_ACTIVE_HIGH>; ++ jadard,panel-sense-nums = <30 48>; ++ jadard,panel-coords = <0 480 0 1080>; ++ jadard,panel-max-points = <10>; ++ jadard,int-is-edge = <1>; ++ status = "okay"; ++ }; ++}; ++ ++&dsi { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ status = "okay"; ++ ++ panel@0 { ++ compatible = "shenzen,z34014p30365ty1","jadard,jd9365tn"; ++ reg = <0>; ++ reset-gpios = <&gpiod 11 GPIO_ACTIVE_HIGH>; ++ backlight-gpios = <&gpiof 6 GPIO_ACTIVE_HIGH>; ++ status = "okay"; ++ ++ port { ++ panel_in: endpoint { ++ remote-endpoint = <&dsi_out>; ++ }; ++ }; ++ }; ++}; ++ ++&dsi_in { ++ remote-endpoint = <<dc_ep1_out>; ++}; ++ ++&dsi_out { ++ remote-endpoint = <&panel_in>; ++}; ++ ++<dc { ++ status = "okay"; ++ ++ port { ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ltdc_ep1_out: endpoint@1 { ++ reg = <1>; ++ remote-endpoint = <&dsi_in>; ++ }; ++ }; ++}; ++ ++&sdmmc1 { ++ /delete-property/ cd-gpios; ++ broken-cd; ++}; ++ ++&sdmmc2 { ++ status = "disabled"; ++}; ++ ++&uart7 { ++ status = "disabled"; ++}; +-- +2.43.0 diff --git a/board/linux/patches/0009-dts-stm32mp15-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch b/board/linux/patches/0009-dts-stm32mp15-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch new file mode 100644 index 0000000..885c25a --- /dev/null +++ b/board/linux/patches/0009-dts-stm32mp15-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch @@ -0,0 +1,94 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kirill Yatsenko +Date: Thu, 03 Apr 2026 17:00:00 +0200 +Subject: dts: stm32mp15-pinctrl: Move I2C4 to PD12/PD13, add I2C1 PB7/PB8 + +On the decktrix v1 custom PCB: +- PMIC (STPMIC1) I2C4 bus uses PD12 (SCL) and PD13 (SDA) instead of PZ4/PZ5 +- Touchscreen I2C1 uses PB7 (SCL) and PB8 (SDA) instead of PD12/PF15 + +Signed-off-by: Kirill Yatsenko +--- +diff --git a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi +index 40605ea85..dd0e34eb6 100644 +--- a/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi ++++ b/arch/arm/boot/dts/st/stm32mp15-pinctrl.dtsi +@@ -18,6 +18,25 @@ pins { + }; + }; + ++ /omit-if-no-ref/ ++ i2c4_pins_a: i2c4-0 { ++ pins { ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ ++ bias-disable; ++ drive-open-drain; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ /omit-if-no-ref/ ++ i2c4_sleep_pins_a: i2c4-sleep-0 { ++ pins { ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ ++ }; ++ }; ++ + /omit-if-no-ref/ + adc1_in6_pins_a: adc1-in6-0 { + pins { +@@ -788,6 +807,25 @@ pins { + }; + }; + ++ /omit-if-no-ref/ ++ i2c1_pins_d: i2c1-3 { ++ pins { ++ pinmux = , /* I2C1_SCL */ ++ ; /* I2C1_SDA */ ++ bias-disable; ++ drive-open-drain; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ /omit-if-no-ref/ ++ i2c1_sleep_pins_d: i2c1-sleep-3 { ++ pins { ++ pinmux = , /* I2C1_SCL */ ++ ; /* I2C1_SDA */ ++ }; ++ }; ++ + /omit-if-no-ref/ + i2c2_pins_a: i2c2-0 { + pins { +@@ -3353,24 +3391,6 @@ pins { + }; + }; + +- /omit-if-no-ref/ +- i2c4_pins_a: i2c4-0 { +- pins { +- pinmux = , /* I2C4_SCL */ +- ; /* I2C4_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- /omit-if-no-ref/ +- i2c4_sleep_pins_a: i2c4-sleep-0 { +- pins { +- pinmux = , /* I2C4_SCL */ +- ; /* I2C4_SDA */ +- }; +- }; + + /omit-if-no-ref/ + i2c6_pins_a: i2c6-0 { +-- +2.43.0 diff --git a/board/tfa/patches/0001-tfa-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch b/board/tfa/patches/0001-tfa-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch new file mode 100644 index 0000000..1807c12 --- /dev/null +++ b/board/tfa/patches/0001-tfa-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch @@ -0,0 +1,46 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kirill Yatsenko +Date: Thu, 03 Apr 2026 18:00:00 +0200 +Subject: stm32mp15-pinctrl: Move I2C4 to pinctrl with PD12/PD13 + +On the decktrix v1 custom PCB, the PMIC (STPMIC1) I2C4 bus uses +PD12 (SCL) and PD13 (SDA) instead of the default PZ4/PZ5. + +PD12/PD13 belong to GPIO port D, so the pinctrl node must be under +&pinctrl (not &pinctrl_z which is only for port Z). + +Signed-off-by: Kirill Yatsenko +--- + fdts/stm32mp15-pinctrl.dtsi | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/fdts/stm32mp15-pinctrl.dtsi b/fdts/stm32mp15-pinctrl.dtsi +index 70d1db140..22262587a 100644 +--- a/fdts/stm32mp15-pinctrl.dtsi ++++ b/fdts/stm32mp15-pinctrl.dtsi +@@ -434,17 +434,18 @@ + ; /* OTG_FS_DP */ + }; + }; +-}; +- +-&pinctrl_z { + /omit-if-no-ref/ + i2c4_pins_a: i2c4-0 { + pins { +- pinmux = , /* I2C4_SCL */ +- ; /* I2C4_SDA */ ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; ++ ++}; ++ ++&pinctrl_z { + }; +-- +2.43.0 diff --git a/board/tfa/patches/0002-tfa-dts-Add-Decktrix-custom-PCB-device-tree.patch b/board/tfa/patches/0002-tfa-dts-Add-Decktrix-custom-PCB-device-tree.patch new file mode 100644 index 0000000..fcc56df --- /dev/null +++ b/board/tfa/patches/0002-tfa-dts-Add-Decktrix-custom-PCB-device-tree.patch @@ -0,0 +1,85 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kirill Yatsenko +Date: Thu, 03 Apr 2026 15:00:00 +0200 +Subject: dts: Add device tree for decktrix custom PCB + +Decktrix v1 custom PCB based on STM32MP157F. +LDO1 at 2.8V for display AVDD, LDO6 at 1.8V for display IOVCC. + +Signed-off-by: Kirill Yatsenko +--- + fdts/decktrix-v1.dts | 47 ++++++++++++++++++++++++++++++++ + fdts/decktrix-v1-fw-config.dts | 7 ++++ + 2 files changed, 54 insertions(+) + create mode 100644 fdts/decktrix-v1.dts + create mode 100644 fdts/decktrix-v1-fw-config.dts + +diff --git a/fdts/decktrix-v1.dts b/fdts/decktrix-v1.dts +new file mode 100644 +index 00000000..3b4dfd1f +--- /dev/null ++++ b/fdts/decktrix-v1.dts +@@ -0,0 +1,47 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) Decktrix Lab ++ * Author: Kirill Yatsenko ++ * ++ * Decktrix v1 custom PCB based on STM32MP157F. ++ * I2C4 pinctrl configured via patch in stm32mp15-pinctrl.dtsi. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xc.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++ ++/ { ++ model = "Decktrix v1"; ++ compatible = "decktrix,v1", "st,stm32mp157"; ++ ++ aliases { ++ serial3 = &usart2; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++/* PMIC LDO1: 2.8V for display AVDD (2V8 rail on decktrix PCB) */ ++&v1v8_audio { ++ regulator-name = "ldo1"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++}; ++ ++/* PMIC LDO6: 1.8V for display IOVCC (1V8 rail on decktrix PCB) */ ++&v1v2_hdmi { ++ regulator-name = "ldo6"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++}; +diff --git a/fdts/decktrix-v1-fw-config.dts b/fdts/decktrix-v1-fw-config.dts +new file mode 100644 +index 00000000..346fc98f +--- /dev/null ++++ b/fdts/decktrix-v1-fw-config.dts +@@ -0,0 +1,7 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) Decktrix Lab ++ */ ++ ++#define DDR_SIZE 0x20000000 /* 512MB */ ++#include "stm32mp15-fw-config.dtsi" +-- +2.43.0 + diff --git a/board/u-boot/patches/0002-dts-stm32mp15-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch b/board/u-boot/patches/0002-dts-stm32mp15-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch new file mode 100644 index 0000000..b3b9bca --- /dev/null +++ b/board/u-boot/patches/0002-dts-stm32mp15-pinctrl-Change-I2C4-default-pins-to-PD12-PD13.patch @@ -0,0 +1,69 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kirill Yatsenko +Date: Thu, 03 Apr 2026 19:00:00 +0200 +Subject: dts: stm32mp15-pinctrl: Move I2C4 to PD12/PD13 + +On the decktrix v1 custom PCB, the PMIC (STPMIC1) I2C4 bus uses +PD12 (SCL) and PD13 (SDA) instead of the default PZ4/PZ5. + +Move the i2c4 pinctrl nodes to the top of the controller section +and add sleep pin configuration. + +Signed-off-by: Kirill Yatsenko +--- + arch/arm/dts/stm32mp15-pinctrl.dtsi | 36 +++++++++++++++++----------- + 1 file changed, 22 insertions(+), 14 deletions(-) + +diff --git a/arch/arm/dts/stm32mp15-pinctrl.dtsi b/arch/arm/dts/stm32mp15-pinctrl.dtsi +index 534a03da21..9abd1125a9 100644 +--- a/arch/arm/dts/stm32mp15-pinctrl.dtsi ++++ b/arch/arm/dts/stm32mp15-pinctrl.dtsi +@@ -25,6 +25,23 @@ + }; + }; + ++ i2c4_pins_a: i2c4-0 { ++ pins { ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ ++ bias-disable; ++ drive-open-drain; ++ slew-rate = <0>; ++ }; ++ }; ++ ++ i2c4_sleep_pins_a: i2c4-sleep-0 { ++ pins { ++ pinmux = , /* I2C4_SCL */ ++ ; /* I2C4_SDA */ ++ }; ++ }; ++ + adc1_in6_pins_a: adc1-in6-0 { + pins { + pinmux = ; +@@ -2831,22 +2848,6 @@ + }; + }; + +- i2c4_pins_a: i2c4-0 { +- pins { +- pinmux = , /* I2C4_SCL */ +- ; /* I2C4_SDA */ +- bias-disable; +- drive-open-drain; +- slew-rate = <0>; +- }; +- }; +- +- i2c4_sleep_pins_a: i2c4-sleep-0 { +- pins { +- pinmux = , /* I2C4_SCL */ +- ; /* I2C4_SDA */ +- }; +- }; + + i2c6_pins_a: i2c6-0 { + pins { +-- +2.43.0 diff --git a/board/u-boot/patches/0003-dts-Add-Decktrix-custom-PCB-device-tree.patch b/board/u-boot/patches/0003-dts-Add-Decktrix-custom-PCB-device-tree.patch new file mode 100644 index 0000000..f909378 --- /dev/null +++ b/board/u-boot/patches/0003-dts-Add-Decktrix-custom-PCB-device-tree.patch @@ -0,0 +1,102 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kirill Yatsenko +Date: Thu, 03 Apr 2026 14:00:00 +0200 +Subject: dts: Add device tree for decktrix custom PCB + +Decktrix v1 custom PCB based on STM32MP157F. +DSI disabled to avoid conflict with kernel Jadard driver. +PMIC LDO1 at 2.8V for display AVDD, LDO6 at 1.8V for display IOVCC. + +Signed-off-by: Kirill Yatsenko +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/decktrix-v1.dts | 51 +++++++++++++++++++++++++ + arch/arm/dts/decktrix-v1-u-boot.dtsi | 6 +++ + 3 files changed, 58 insertions(+) + create mode 100644 arch/arm/dts/decktrix-v1.dts + create mode 100644 arch/arm/dts/decktrix-v1-u-boot.dtsi + +diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile +index 267b0179..78206161 100644 +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -1090,6 +1090,7 @@ dtb-$(CONFIG_STM32MP15X) += \ + stm32mp157a-microgea-stm32mp1-microdev2.0-of7.dtb \ + stm32mp157c-dk2.dtb \ + stm32mp157c-dk2-scmi.dtb \ ++ decktrix-v1.dtb \ + stm32mp157c-ed1.dtb \ + stm32mp157c-ed1-scmi.dtb \ + stm32mp157c-ev1.dtb \ +diff --git a/arch/arm/dts/decktrix-v1.dts b/arch/arm/dts/decktrix-v1.dts +new file mode 100644 +index 00000000..c1ca7a1b +--- /dev/null ++++ b/arch/arm/dts/decktrix-v1.dts +@@ -0,0 +1,51 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) Decktrix Lab ++ * Author: Kirill Yatsenko ++ * ++ * Decktrix v1 custom PCB based on STM32MP157F. ++ * DSI disabled to avoid conflict with kernel Jadard driver. ++ */ ++ ++/dts-v1/; ++ ++#include "stm32mp157.dtsi" ++#include "stm32mp15xc.dtsi" ++#include "stm32mp15-pinctrl.dtsi" ++#include "stm32mp15xxac-pinctrl.dtsi" ++#include "stm32mp15xx-dkx.dtsi" ++ ++/ { ++ model = "Decktrix v1"; ++ compatible = "decktrix,v1", "st,stm32mp157"; ++ ++ aliases { ++ ethernet0 = ðernet0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++}; ++ ++&cryp1 { ++ status = "okay"; ++}; ++ ++&dsi { ++ status = "disabled"; ++}; ++ ++/* PMIC LDO1: 2.8V for display AVDD (not 1.8V for audio) */ ++&v1v8_audio { ++ regulator-name = "ldo1"; ++ regulator-min-microvolt = <2800000>; ++ regulator-max-microvolt = <2800000>; ++}; ++ ++/* PMIC LDO6: 1.8V for display IOVCC (not 1.2V for HDMI) */ ++&v1v2_hdmi { ++ regulator-name = "ldo6"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++}; +diff --git a/arch/arm/dts/decktrix-v1-u-boot.dtsi b/arch/arm/dts/decktrix-v1-u-boot.dtsi +new file mode 100644 +index 00000000..384f306c +--- /dev/null ++++ b/arch/arm/dts/decktrix-v1-u-boot.dtsi +@@ -0,0 +1,6 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) ++/* ++ * Copyright (C) Decktrix Lab ++ */ ++ ++#include "stm32mp157a-dk1-u-boot.dtsi" +-- +2.43.0 + diff --git a/board/u-boot/patches/0004-dts-sdmmc1-Use-broken-cd.patch b/board/u-boot/patches/0004-dts-sdmmc1-Use-broken-cd.patch new file mode 100644 index 0000000..a310884 --- /dev/null +++ b/board/u-boot/patches/0004-dts-sdmmc1-Use-broken-cd.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Kirill Yatsenko +Date: Thu, 17 Apr 2026 20:00:00 +0200 +Subject: dts: sdmmc1: Use broken-cd + +Decktrix v1 PCB has no card detect on PB7. +Use broken-cd to skip GPIO card detect check. + +Signed-off-by: Kirill Yatsenko +--- + arch/arm/dts/decktrix-v1.dts | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/arch/arm/dts/decktrix-v1.dts b/arch/arm/dts/decktrix-v1.dts +index c1ca7a1b..008dc8e3 100644 +--- a/arch/arm/dts/decktrix-v1.dts ++++ b/arch/arm/dts/decktrix-v1.dts +@@ -49,3 +49,8 @@ + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; ++ ++&sdmmc1 { ++ /delete-property/ cd-gpios; ++ broken-cd; ++}; +-- +2.43.0 + diff --git a/build-image.sh b/build-image.sh index f39e93f..36d8826 100755 --- a/build-image.sh +++ b/build-image.sh @@ -3,6 +3,12 @@ set -e # exit on error # set -x # debug +if [ "$(id -u)" -eq 0 ]; then + MAYBE_SUDO="" +else + MAYBE_SUDO="sudo" +fi + readonly TOOLCHAIN_NAME="x86_64-gcc-11.3.0-nolibc-arm-linux-gnueabi.tar.xz" readonly TOOLCHAIN_EXTRACTED_PATH="gcc-11.3.0-nolibc/arm-linux-gnueabi/bin/arm-linux-gnueabi-" readonly TFA_DIR="board/tfa/trusted-firmware-a-v2.10.19" @@ -14,62 +20,92 @@ readonly DEPLOY_DIR="deploy" readonly STM32_DT="stm32mp157c-dk2.dtb" readonly STM32_JADARD_DT="stm32mp157c-dk2-jadard.dtb" +readonly DECKTRIX_DT="decktrix-v1.dtb" + +# Board DT name for TFA and U-Boot (differs for custom PCB) +BOARD_DT="stm32mp157c-dk2" prepare_toolchain() { echo "-I preparing toolchain for cross compilation" + # Allow git operations inside Docker (different file ownership) + git config --global --add safe.directory "*" + mkdir -p toolchain/extracted tar -xf $(pwd)/toolchain/${TOOLCHAIN_NAME} -C toolchain/extracted CC="$(pwd)/toolchain/extracted/${TOOLCHAIN_EXTRACTED_PATH}" } apply_kernel_patches() { - # The patch may already be applied on the second run which will return error - # so let's ignore it - git apply --reject --directory ${KERNEL_DIR} \ - board/linux/patches/0001-defconfig-Add-separate-config-based-on-multi_v7_defc.patch \ - board/linux/patches/0002-dts-Add-separate-device-tree-for-stm32-devboard-with.patch \ - board/linux/patches/0003-display-Add-Jadard-MIPI-driver.patch \ - board/linux/patches/0004-display-Add-Jadard-touch-driver.patch \ - board/linux/patches/0005-dts-Add-support-for-home-button.patch || true + git -C ${KERNEL_DIR} reset --hard HEAD + git -C ${KERNEL_DIR} clean -fd + + for p in board/linux/patches/*.patch; do + echo " Applying $(basename $p)" + git apply --directory ${KERNEL_DIR} "$p" + done } build_kernel() { echo "-I start kernel build" apply_kernel_patches + make -C ${KERNEL_DIR} ARCH=arm CROSS_COMPILE=${CC} decktrix_defconfig make -C ${KERNEL_DIR} ARCH=arm CROSS_COMPILE=${CC} zImage modules dtbs -j$(nproc) } apply_uboot_patches() { - git apply --reject --directory ${UBOOT_DIR} \ - board/u-boot/patches/0001-DT-disable-DSI-node.patch || true + echo "-I apply u-boot patches" + + git -C ${UBOOT_DIR} reset --hard HEAD + git -C ${UBOOT_DIR} clean -fd + + for p in board/u-boot/patches/*.patch; do + echo " Applying $(basename $p)" + git apply --directory ${UBOOT_DIR} "$p" + done +} + +apply_tfa_patches() { + echo "-I apply tfa patches" + + git -C ${TFA_DIR} reset --hard HEAD + git -C ${TFA_DIR} clean -fd + + for p in board/tfa/patches/*.patch; do + echo " Applying $(basename $p)" + git apply --directory ${TFA_DIR} "$p" + done } build_uboot() { echo "-I start u-boot build" apply_uboot_patches + make -C ${UBOOT_DIR} CROSS_COMPILE=${CC} stm32mp15_trusted_defconfig - make -C ${UBOOT_DIR} CROSS_COMPILE=${CC} DEVICE_TREE=stm32mp157c-dk2 -j all + make -C ${UBOOT_DIR} CROSS_COMPILE=${CC} DEVICE_TREE=${BOARD_DT} -j all } build_tfa() { echo "-I start tfa build" + apply_tfa_patches + make -C ${TFA_DIR} \ PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 CROSS_COMPILE=${CC} \ STM32MP_SDMMC=1 STM32MP_EMMC=1 \ AARCH32_SP=sp_min \ - DTB_FILE_NAME=stm32mp157c-dk2.dtb \ + DTB_FILE_NAME=${BOARD_DT}.dtb \ BL33_CFG=../../u-boot/u-boot-v2025.04/u-boot.dtb \ BL33=../../u-boot/u-boot-v2025.04/u-boot-nodtb.bin \ + STM32MP15=1 \ all fip } run_in_chroot() { - sudo chroot ${DEBOOTSTRAP_DIR} /usr/bin/qemu-arm-static /bin/sh -c "$1" + $MAYBE_SUDO chroot ${DEBOOTSTRAP_DIR} /usr/bin/qemu-arm-static /bin/sh -c "$1" } mount_vfs() { @@ -86,21 +122,21 @@ umount_vfs() { run_in_chroot "umount /proc" } -debootstrap() { +run_debootstrap() { echo "-I starting debootstrap" - sudo umount ${DEBOOTSTRAP_DIR}/proc ${DEBOOTSTRAP_DIR}/sys || true - sudo rm -rf ${DEBOOTSTRAP_DIR} + $MAYBE_SUDO umount ${DEBOOTSTRAP_DIR}/proc ${DEBOOTSTRAP_DIR}/sys || true + $MAYBE_SUDO rm -rf ${DEBOOTSTRAP_DIR} - sudo debootstrap --arch=armhf --foreign trixie ${DEBOOTSTRAP_DIR} - sudo cp /usr/bin/qemu-arm-static ${DEBOOTSTRAP_DIR}/usr/bin + $MAYBE_SUDO command debootstrap --arch=armhf --foreign trixie ${DEBOOTSTRAP_DIR} + $MAYBE_SUDO cp /usr/bin/qemu-arm-static ${DEBOOTSTRAP_DIR}/usr/bin run_in_chroot "/debootstrap/debootstrap --second-stage" } save_debootstrap_prefetched() { - sudo rm -rf ${DEBOOTSTRAP_PREFETCHED_DIR} - sudo cp -r -p ${DEBOOTSTRAP_DIR} ${DEBOOTSTRAP_PREFETCHED_DIR} + $MAYBE_SUDO find ${DEBOOTSTRAP_PREFETCHED_DIR} -mindepth 1 -delete 2>/dev/null || true + $MAYBE_SUDO cp -a ${DEBOOTSTRAP_DIR}/. ${DEBOOTSTRAP_PREFETCHED_DIR}/ } install_apt_packages() { @@ -145,47 +181,47 @@ install_apt_packages() { install_overlays() { echo "-I installing files overlays" - sudo install --verbose --owner=root --group=root --mode=777 \ + $MAYBE_SUDO install --verbose --owner=root --group=root --mode=777 \ overlay/network/etc/resolv.conf ${DEBOOTSTRAP_DIR}/etc/resolv.conf - sudo install --verbose --owner=root --group=root --mode=664 \ + $MAYBE_SUDO install --verbose --owner=root --group=root --mode=664 \ overlay/sway/usr/lib/systemd/system/sway.service \ ${DEBOOTSTRAP_DIR}/usr/lib/systemd/system/sway.service - sudo install --verbose -D --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose -D --owner=root --group=root --mode=644 \ overlay/weston/etc/xdg/weston/weston.ini \ ${DEBOOTSTRAP_DIR}/etc/xdg/weston/weston.ini - sudo install --verbose -D --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose -D --owner=root --group=root --mode=644 \ overlay/weston/usr/lib/systemd/user/weston.service \ ${DEBOOTSTRAP_DIR}/usr/lib/systemd/user/weston.service - sudo install --verbose -D --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose -D --owner=root --group=root --mode=644 \ overlay/weston/usr/lib/systemd/user/weston.socket \ ${DEBOOTSTRAP_DIR}/usr/lib/systemd/user/weston.socket - sudo install --verbose -D --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose -D --owner=root --group=root --mode=644 \ overlay/weston/usr/lib/systemd/system/weston-graphical-session.service \ ${DEBOOTSTRAP_DIR}/usr/lib/systemd/system/weston-graphical-session.service } install_opengles_lib() { echo "-I install opengles lib" - sudo install --verbose board/opengles-lib/* ${DEBOOTSTRAP_DIR}/lib || true + $MAYBE_SUDO install --verbose board/opengles-lib/* ${DEBOOTSTRAP_DIR}/lib || true } install_wifi_firmware() { echo "-I install wifi firmware" - sudo install --verbose -D --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose -D --owner=root --group=root --mode=644 \ board/wifi-firmware/brcmfmac43430-sdio.txt \ ${DEBOOTSTRAP_DIR}/lib/firmware/brcm/brcmfmac43430-sdio.st,stm32mp157c-dk2.txt - sudo install --verbose -D --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose -D --owner=root --group=root --mode=644 \ board/wifi-firmware/cyfmac43430-sdio.bin \ ${DEBOOTSTRAP_DIR}/lib/firmware/brcm/brcmfmac43430-sdio.bin - sudo install --verbose -D --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose -D --owner=root --group=root --mode=644 \ board/wifi-firmware/cyfmac43430-sdio.1DX.clm_blob \ ${DEBOOTSTRAP_DIR}/lib/firmware/brcm/brcmfmac43430-sdio.clm_blob } @@ -252,27 +288,28 @@ setup_extlinux() { install_kernel_image() { echo "-I install kernel image" - sudo install --verbose --owner=root --group=root --mode=644 \ + $MAYBE_SUDO install --verbose --owner=root --group=root --mode=644 \ ${KERNEL_DIR}/arch/arm/boot/zImage ${DEBOOTSTRAP_DIR}/boot/vmlinuz-${KERNEL_VERSION} } install_kernel_modules() { echo "-I install kernel modules" - sudo make -C ${KERNEL_DIR} ARCH=arm CROSS_COMPILE=${CC} modules_install \ + $MAYBE_SUDO make -C ${KERNEL_DIR} ARCH=arm CROSS_COMPILE=${CC} modules_install \ INSTALL_MOD_PATH="../../../${DEBOOTSTRAP_DIR}/usr" } install_device_tree() { echo "-I install device tree" run_in_chroot "mkdir -p boot/dtbs/${KERNEL_VERSION}" - sudo make -C ${KERNEL_DIR} ARCH=arm CROSS_COMPILE=${CC} dtbs_install \ + $MAYBE_SUDO make -C ${KERNEL_DIR} ARCH=arm CROSS_COMPILE=${CC} dtbs_install \ INSTALL_DTBS_PATH="../../../${DEBOOTSTRAP_DIR}/boot/dtbs/${KERNEL_VERSION}" } install_tfa() { echo "-I install TFA" - cp ${TFA_DIR}/build/stm32mp1/release/tf-a-stm32mp157c-dk2.stm32 \ - ${TFA_DIR}/build/stm32mp1/release/fip.bin ${DEPLOY_DIR} + cp ${TFA_DIR}/build/stm32mp1/release/tf-a-${BOARD_DT}.stm32 \ + ${DEPLOY_DIR}/tf-a-stm32mp157c-dk2.stm32 + cp ${TFA_DIR}/build/stm32mp1/release/fip.bin ${DEPLOY_DIR} } enable_serial_console() { @@ -288,20 +325,26 @@ use_prefetched_download() { echo "Run this script with '-p|--prefetch-debootstrap' option first" exit 1 fi - sudo umount ${DEBOOTSTRAP_DIR}/proc ${DEBOOTSTRAP_DIR}/sys || true - sudo rm -rf ${DEBOOTSTRAP_DIR} - sudo cp -p -r ${DEBOOTSTRAP_PREFETCHED_DIR} ${DEBOOTSTRAP_DIR} + $MAYBE_SUDO umount ${DEBOOTSTRAP_DIR}/proc ${DEBOOTSTRAP_DIR}/sys || true + $MAYBE_SUDO rm -rf ${DEBOOTSTRAP_DIR} + $MAYBE_SUDO cp -p -r ${DEBOOTSTRAP_PREFETCHED_DIR} ${DEBOOTSTRAP_DIR} } create_rootfs_ext4() { - sudo rm -rf ${DEPLOY_DIR} && mkdir -p ${DEPLOY_DIR} - sudo dd if=/dev/zero of=${DEPLOY_DIR}/rootfs.ext4 bs=1 count=0 seek=2500M - sudo mkfs.ext4 -F ${DEPLOY_DIR}/rootfs.ext4 -d ${DEBOOTSTRAP_DIR} + $MAYBE_SUDO rm -rf ${DEPLOY_DIR} && mkdir -p ${DEPLOY_DIR} + $MAYBE_SUDO dd if=/dev/zero of=${DEPLOY_DIR}/rootfs.ext4 bs=1 count=0 seek=2500M + $MAYBE_SUDO mkfs.ext4 -F ${DEPLOY_DIR}/rootfs.ext4 -d ${DEBOOTSTRAP_DIR} } generate_sdcard_img() { echo "-I generate sdcard image" - genimage --inputpath deploy --outputpath deploy --config genimage.cfg + $MAYBE_SUDO genimage --inputpath deploy --outputpath deploy --config genimage.cfg +} + +gzip_sdcard_img() { + echo "-I compress sdcard image" + gzip -f deploy/sdcard.img + echo "-I compressed: deploy/sdcard.img.gz ($(du -h deploy/sdcard.img.gz | cut -f1))" } print_help() { @@ -323,12 +366,13 @@ print_help() { echo " -p, --prefetch-debootstrap downloads debian and saves the result" echo " -u, --use-prefetch-debootstrap use cached download folder" echo " -s, --skip skip tfa, u-boot and kernel builds" - echo " -v, --variant [stm32, stm32-jadard] select device variant" + echo " -v, --variant [stm32, stm32-jadard, decktrix] select device variant" } start_image_build() { skip_board=false - selected_dt=${STM32_DT} + selected_dt=${DECKTRIX_DT} + BOARD_DT="decktrix-v1" POSITIONAL_ARGS=() @@ -351,8 +395,11 @@ start_image_build() { selected_dt=${STM32_DT} elif [ "$2" = "stm32-jadard" ]; then selected_dt=${STM32_JADARD_DT} + elif [ "$2" = "decktrix" ]; then + selected_dt=${DECKTRIX_DT} + BOARD_DT="decktrix-v1" else - echo "Invalid selected variant, valid are: [stm32, stm32-jadard]" + echo "Invalid selected variant, valid are: [stm32, stm32-jadard, decktrix]" exit 1 fi shift @@ -385,7 +432,7 @@ start_image_build() { # Prefetch debootstrap and install apt packages if [ "${prefetch_debootstrap}" = true ] ; then - debootstrap + run_debootstrap mount_vfs install_apt_packages umount_vfs @@ -396,7 +443,7 @@ start_image_build() { if [ "${use_prefetched_debootstrap}" = true ] ; then use_prefetched_download else - debootstrap + run_debootstrap fi mount_vfs @@ -434,6 +481,7 @@ start_image_build() { install_tfa generate_sdcard_img + gzip_sdcard_img } start_image_build "$@" diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..e15522f --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +docker compose run --remove-orphans build "$@" +sudo chown -R "$(id -u):$(id -g)" deploy/ diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..81e686b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +services: + build: + build: . + privileged: true + volumes: + - ./.git:/build/.git + - ./board:/build/board + - ./scripts:/build/scripts + - ./toolchain:/build/toolchain + - ./overlay:/build/overlay + - ./genimage.cfg:/build/genimage.cfg + - ./deploy:/build/deploy + - ./debootstrap-prefetched:/build/debootstrap-prefetched + command: ["--use-prefetch-debootstrap"] diff --git a/scripts/gdrive-auth.sh b/scripts/gdrive-auth.sh new file mode 100755 index 0000000..96773c9 --- /dev/null +++ b/scripts/gdrive-auth.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# +# Re-authenticate with Google Drive when the refresh token expires. +# The refresh token lasts 7 days. When it expires, run this script. +# +# Usage: ./scripts/gdrive-auth.sh +# +# Steps: +# 1. Opens the OAuth URL in your browser +# 2. You approve access +# 3. Browser redirects to http://localhost/?code=... +# 4. Copy the code from the URL and paste it here +# 5. Token file is updated automatically +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +TOKEN_FILE="${PROJECT_ROOT}/.config/opencode/gdrive-token.json" + +if [ ! -f "$TOKEN_FILE" ]; then + echo "Error: Token file not found: $TOKEN_FILE" + exit 1 +fi + +CLIENT_ID=$(python3 -c "import json; print(json.load(open('$TOKEN_FILE'))['client_id'])") +CLIENT_SECRET=$(python3 -c "import json; print(json.load(open('$TOKEN_FILE'))['client_secret'])") +REDIRECT_URI="http://localhost" + +AUTH_URL="https://accounts.google.com/o/oauth2/auth?client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=https://www.googleapis.com/auth/drive.file&access_type=offline&prompt=consent" + +echo "" +echo "Open this URL in your browser to authorize:" +echo "" +echo "$AUTH_URL" +echo "" +echo "After approving, you will be redirected to:" +echo " http://localhost/?code=XXXXX&scope=..." +echo "" +read -p "Paste the code from the URL: " AUTH_CODE + +if [ -z "$AUTH_CODE" ]; then + echo "Error: No code provided" + exit 1 +fi + +# Exchange code for tokens +TOKEN_RESPONSE=$(curl -s -X POST https://oauth2.googleapis.com/token \ + -d "code=$AUTH_CODE" \ + -d "client_id=$CLIENT_ID" \ + -d "client_secret=$CLIENT_SECRET" \ + -d "redirect_uri=$REDIRECT_URI" \ + -d "grant_type=authorization_code") + +NEW_ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])" 2>/dev/null) +NEW_REFRESH_TOKEN=$(echo "$TOKEN_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['refresh_token'])" 2>/dev/null) + +if [ -z "$NEW_REFRESH_TOKEN" ]; then + echo "Error: Failed to get new tokens" + echo "$TOKEN_RESPONSE" + exit 1 +fi + +# Update token file with new refresh token +python3 -c " +import json +with open('$TOKEN_FILE', 'r') as f: + data = json.load(f) +data['refresh_token'] = '$NEW_REFRESH_TOKEN' +with open('$TOKEN_FILE', 'w') as f: + json.dump(data, f, indent=2) +" + +echo "" +echo "Token updated successfully!" +echo "You can now use: ./scripts/gdrive-upload.sh " diff --git a/scripts/gdrive-upload.sh b/scripts/gdrive-upload.sh new file mode 100755 index 0000000..4b8ae90 --- /dev/null +++ b/scripts/gdrive-upload.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# +# Upload a file to Google Drive (decktrix folder) and share it. +# +# Usage: ./scripts/gdrive-upload.sh +# +# Credentials stored in: .config/opencode/gdrive-token.json +# If token expires, run: ./scripts/gdrive-auth.sh +# + +set -e + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +TOKEN_FILE="${PROJECT_ROOT}/.config/opencode/gdrive-token.json" + +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +FILE="$1" + +if [ ! -f "$FILE" ]; then + echo "Error: File not found: $FILE" + exit 1 +fi + +if [ ! -f "$TOKEN_FILE" ]; then + echo "Error: Token file not found: $TOKEN_FILE" + echo "Run: ./scripts/gdrive-auth.sh" + exit 1 +fi + +CLIENT_ID=$(python3 -c "import json; print(json.load(open('$TOKEN_FILE'))['client_id'])") +CLIENT_SECRET=$(python3 -c "import json; print(json.load(open('$TOKEN_FILE'))['client_secret'])") +REFRESH_TOKEN=$(python3 -c "import json; print(json.load(open('$TOKEN_FILE'))['refresh_token'])") +FOLDER_ID=$(python3 -c "import json; print(json.load(open('$TOKEN_FILE'))['folder_id'])") + +# Refresh access token +TOKEN_RESPONSE=$(curl -s -X POST https://oauth2.googleapis.com/token \ + -d "client_id=$CLIENT_ID" \ + -d "client_secret=$CLIENT_SECRET" \ + -d "refresh_token=$REFRESH_TOKEN" \ + -d "grant_type=refresh_token") + +ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])" 2>/dev/null) + +if [ -z "$ACCESS_TOKEN" ]; then + echo "Error: Failed to refresh access token. Token may be expired." + echo "Run: ./scripts/gdrive-auth.sh" + exit 1 +fi + +FILENAME=$(basename "$FILE") +MIME_TYPE=$(file -b --mime-type "$FILE") + +echo "Uploading $FILENAME ($MIME_TYPE) to Google Drive..." + +# Upload file +UPLOAD_RESPONSE=$(curl -s -X POST \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + -F "metadata={\"name\": \"$FILENAME\", \"parents\": [\"$FOLDER_ID\"]};type=application/json" \ + -F "file=@$FILE;type=$MIME_TYPE" \ + "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id,name,webViewLink") + +FILE_ID=$(echo "$UPLOAD_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" 2>/dev/null) +WEB_LINK=$(echo "$UPLOAD_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)['webViewLink'])" 2>/dev/null) + +if [ -z "$FILE_ID" ]; then + echo "Error: Upload failed" + echo "$UPLOAD_RESPONSE" + exit 1 +fi + +# Share with anyone who has the link +curl -s -X POST \ + -H "Authorization: Bearer $ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"role": "reader", "type": "anyone"}' \ + "https://www.googleapis.com/drive/v3/files/$FILE_ID/permissions" > /dev/null + +echo "" +echo "Uploaded: $FILENAME" +echo "Link: $WEB_LINK"