diff --git a/.gitignore b/.gitignore
index 5937c74d3dc1e4ca56d93ea0b8d5ff9fc64ec839..5a0b06a75bc10f059b587ae6d70f7cf5b946333f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -113,6 +113,7 @@ modules.order
 !.kunitconfig
 !.mailmap
 !.rustfmt.toml
+!.gitlab-ci.yml
 
 #
 # Generated include files
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f9f10aef4bfc8be42f8d6d5e26c7743c67ae0bb1
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,145 @@
+default:
+  image: debian:testing
+  tags:
+    - trixie
+
+stages:
+  - build
+  - test
+  - generate
+  - lava
+
+check devicetrees:
+  stage: build
+  tags:
+    - ultra-heavyweight
+  variables:
+    DEBIAN_FRONTEND: noninteractive
+    GIT_SUBMODULE_STRATEGY: normal
+    ARCH: arm64
+    DEFCONFIG: defconfig
+    CROSS_COMPILE: aarch64-linux-gnu-
+    DUT: rockchip/rk3588s-rock-5a.dtb rockchip/rk3588-rock-5b.dtb rockchip/rk3588-evb1-v10.dtb
+  before_script:
+    - apt update
+    - apt install -y devscripts
+                     build-essential
+                     crossbuild-essential-arm64
+                     bc
+                     bison
+                     flex
+                     swig
+                     python3-dev
+                     python3-pip
+                     python3-setuptools
+                     yamllint
+    - pip3 install --break-system-packages dtschema
+  script:
+    - make $DEFCONFIG
+    - make -j$(nproc) dt_binding_check
+    - make -j$(nproc) CHECK_DTBS=y $DUT 2> dt-warnings.txt
+    - if [[ $(cat dt-warnings.txt | wc -l) > 0 ]]; then cat dt-warnings.txt; exit 42; fi
+  allow_failure:
+    exit_codes:
+      - 42
+
+.build debian package:
+  stage: build
+  tags:
+    - ultra-heavyweight
+  cache:
+    when: on_success
+    key: $CI_COMMIT_REF_SLUG
+    paths:
+      - ccache
+  variables:
+    DEBIAN_FRONTEND: noninteractive
+    GIT_SUBMODULE_STRATEGY: normal
+    ARCH: amd64
+    DEFCONFIG: defconfig
+    CCACHE_BASEDIR: $CI_PROJECT_DIR
+    CCACHE_DIR: $CI_PROJECT_DIR/ccache
+  before_script:
+    - dpkg --add-architecture arm64
+    - apt update
+    - apt install -y devscripts
+                     build-essential
+                     crossbuild-essential-arm64
+                     bc
+                     bison
+                     ccache
+                     flex
+                     rsync
+                     kmod
+                     cpio
+                     libelf-dev
+                     libssl-dev
+                     libssl-dev:arm64
+    # Setup ccache
+    - export PATH="/usr/lib/ccache:$PATH"
+    - ccache -s
+  script:
+    - make $DEFCONFIG
+    - ./scripts/config -e WLAN -e WLAN_VENDOR_BROADCOM -m BRCMUTIL -m BRCMFMAC
+                       -e BRCMFMAC_PROTO_BCDC -e BRCMFMAC_PROTO_MSGBUF
+                       -e BRCMFMAC_USB
+                       -e WLAN_VENDOR_REALTEK -m RTW89 -m RTW89_CORE
+                       -m RTW89_PCI -m RTW89_8825B -m RTW89_8852BE
+                       -m BINFMT_MISC
+    - make -j$(nproc) $ADDITIONAL_BUILD_CMD bindeb-pkg
+    - mkdir artifacts && dcmd mv ../*.changes artifacts/
+  artifacts:
+    paths:
+      - artifacts
+
+build arm64 debian package:
+  extends: .build debian package
+  variables:
+    ARCH: arm64
+    CROSS_COMPILE: aarch64-linux-gnu-
+    ADDITIONAL_BUILD_CMD: KBUILD_IMAGE=arch/arm64/boot/Image
+
+generate tests:
+  image: debian:trixie-slim
+  stage: generate
+  tags:
+    - lightweight
+  variables:
+    GIT_STRATEGY: fetch
+    GIT_DEPTH: "1"
+  needs:
+    - "build arm64 debian package"
+  before_script:
+    - apt update
+    - apt install -y wget
+  script:
+    - mkdir deb
+    - "for x in artifacts/linux-image*.deb ; do dpkg -x ${x} deb ; done"
+    - cp deb/boot/vmlinuz* vmlinuz
+    - mkdir -p deb/lib/firmware/arm/mali/arch10.8
+    - wget -O deb/lib/firmware/arm/mali/arch10.8/mali_csffw.bin "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/arm/mali/arch10.8/mali_csffw.bin"
+    - tar -f modules.tar.gz  -C deb  -c -z -v lib/modules lib/firmware
+    - mkdir dtbs
+    - cp -r deb/usr/lib/linux-image*/* dtbs
+    - sed -i s,%%KERNEL_BUILD_JOB%%,${CI_JOB_ID},g lava/testjob.yaml
+  artifacts:
+    paths:
+      - vmlinuz*
+      - modules.tar.gz
+      - dtbs
+      - lava/testjob.yaml
+
+lava test:
+  stage: lava
+  tags:
+    - lava-runner
+  script:
+    - submit lava/testjob.yaml
+  needs:
+    - "generate tests"
+  artifacts:
+    when: always
+    paths:
+      - "*"
+    reports:
+      junit: "*_junit.xml"
diff --git a/lava/testjob.yaml b/lava/testjob.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..481ea76eb6b9ff48d6eaf78e553a968e15c168a6
--- /dev/null
+++ b/lava/testjob.yaml
@@ -0,0 +1,231 @@
+device_type:  rk3588-rock-5b
+
+job_name: Hardware enablement tests {{job.CI_JOB_ID}}
+timeouts:
+  job:
+    minutes: 15
+  action:
+   minutes: 5
+priority: high
+visibility: public
+
+context:
+  extra_kernel_args: rootwait
+
+actions:
+  - deploy:
+      timeout:
+        minutes: 2
+      to: tftp
+      kernel:
+        url: "{{job.CI_PROJECT_URL}}/-/jobs/%%KERNEL_BUILD_JOB%%/artifacts/raw/vmlinuz"
+        type: image
+      modules:
+        url: "{{job.CI_PROJECT_URL}}/-/jobs/%%KERNEL_BUILD_JOB%%/artifacts/raw/modules.tar.gz"
+        compression: gz
+      dtb:
+        url: "{{job.CI_PROJECT_URL}}/-/jobs/%%KERNEL_BUILD_JOB%%/artifacts/raw/dtbs/rockchip/rk3588-rock-5b.dtb"
+      ramdisk:
+        url: https://gitlab.collabora.com/hardware-enablement/rockchip-3588/debian-image-recipes/-/jobs/artifacts/main/raw/out/trixie-rootfs-arm64-initramfs.gz?job=ci+images
+        compression: gz
+      nfsrootfs:
+        url: https://gitlab.collabora.com/hardware-enablement/rockchip-3588/debian-image-recipes/-/jobs/artifacts/main/raw/out/trixie-rootfs-arm64.tar.gz?job=ci+images
+        compression: gz
+
+  - boot:
+      method: u-boot
+      commands: nfs
+      timeout:
+        minutes: 10
+      auto_login:
+        login_prompt: 'login:'
+        username: user
+        password_prompt: 'Password:'
+        password: user
+        login_commands:
+          - sudo su
+          - env
+          - systemctl --failed
+      prompts:
+        - 'user@rk3588-ci(.*)$'
+        - 'root@rk3588-ci(.*)#'
+
+  - test:
+      timeout:
+        minutes: 5
+      definitions:
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: rtc
+            description: "Run some RTC/NTP tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - ip link
+              - hwclock -w
+              - timedatectl set-ntp true
+              - systemctl restart systemd-timesyncd
+              - timedatectl status
+              - timedatectl timesync-status
+        from: inline
+        name: rtc
+        path: inline/rtc.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: usb
+            description: "Run USB tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - lsusb
+        from: inline
+        name: usb
+        path: inline/usb.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: pci
+            description: "Run PCI tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - lspci -nn
+        from: inline
+        name: pci
+        path: inline/pci.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: i2c
+            description: "Run I2C tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - i2cdetect -l
+        from: inline
+        name: i2c
+        path: inline/i2c.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: alsa
+            description: "Run ALSA tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - cat /proc/asound/cards
+        from: inline
+        name: alsa
+        path: inline/alsa.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: hwmon
+            description: "Run hwmon tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - sensors
+        from: inline
+        name: hwmon
+        path: inline/hwmon.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: iio
+            description: "Run iio tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - iio_info
+        from: inline
+        name: iio
+        path: inline/iio.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: nvmem
+            description: "Run nvmem tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - hexdump /sys/bus/nvmem/devices/rockchip-otp0/nvmem
+        from: inline
+        name: nvmem
+        path: inline/nvmem.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: tcpm
+            description: "Run tcpm tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - cat /sys/class/power_supply/tcpm-source-psy-4-0022/uevent || true
+        from: inline
+        name: tcpm
+        path: inline/tcpm.yaml
+      - repository:
+          metadata:
+            format: Lava-Test Test Definition 1.0
+            name: v4l2
+            description: "Run v4l2 tests"
+            os:
+              - apertis
+            scope:
+              - functional
+            environment:
+              - lava-test-shell
+          run:
+            steps:
+              - for dev in /dev/video* ; do echo "Device $dev" ; v4l2-ctl -d $dev -l -D ; echo "" ; done
+        from: inline
+        name: v4l2
+        path: inline/v4l2.yaml