├── .github └── workflows │ └── main.yml ├── .gitignore ├── README.md ├── build_docker.sh ├── build_image.sh ├── configs ├── common │ ├── dts │ │ ├── cv180x │ │ │ ├── cv180x_asic_bga.dtsi │ │ │ ├── cv180x_asic_qfn.dtsi │ │ │ ├── cv180x_asic_sd.dtsi │ │ │ ├── cv180x_asic_spinand.dtsi │ │ │ ├── cv180x_asic_spinor.dtsi │ │ │ ├── cv180x_base.dtsi │ │ │ └── cv180x_default_memmap.dtsi │ │ ├── cv180x_riscv │ │ │ └── cv180x_base_riscv.dtsi │ │ ├── cv181x │ │ │ ├── cv181x_asic_bga.dtsi │ │ │ ├── cv181x_asic_emmc.dtsi │ │ │ ├── cv181x_asic_qfn.dtsi │ │ │ ├── cv181x_asic_sd.dtsi │ │ │ ├── cv181x_asic_spinand.dtsi │ │ │ ├── cv181x_asic_spinor.dtsi │ │ │ ├── cv181x_base.dtsi │ │ │ └── cv181x_default_memmap.dtsi │ │ ├── cv181x_arm │ │ │ └── cv181x_base_arm.dtsi │ │ ├── cv181x_riscv │ │ │ └── cv181x_base_riscv.dtsi │ │ ├── sg200x │ │ │ ├── sg200x_asic_bga.dtsi │ │ │ ├── sg200x_asic_emmc.dtsi │ │ │ ├── sg200x_asic_qfn.dtsi │ │ │ ├── sg200x_asic_sd.dtsi │ │ │ ├── sg200x_asic_spinand.dtsi │ │ │ ├── sg200x_asic_spinor.dtsi │ │ │ ├── sg200x_base.dtsi │ │ │ └── sg200x_default_memmap.dtsi │ │ ├── sg200x_arm │ │ │ └── sg200x_base_arm.dtsi │ │ └── sg200x_riscv │ │ │ └── sg200x_base_riscv.dtsi │ └── patches │ │ ├── fsbl │ │ └── 0001-fix-compile-error.patch │ │ ├── linux │ │ ├── 0001-Add-Mailbox-Driver-for-cvitek.patch │ │ ├── 0002-Add-Reset-for-C906L-ignore-clock-status-for-C906L-an.patch │ │ ├── 0003-Add-Remoteproc-Driver-for-cvitek.patch │ │ ├── 0004-backport-rpmsg-driver.patch │ │ ├── 0005-add-cvitek-pwm-driver.patch │ │ ├── 0006-add-cvitek-watchdog.patch │ │ ├── 0007-add-cvitek-rtc-driver.patch │ │ ├── 0008-add-saradc-driver.patch │ │ ├── 0009-add-cooling-driver.patch │ │ └── 0010-add-aic8800-wireless-driver.patch │ │ ├── opensbi │ │ ├── 0002-add-fence-tso-emulation.patch │ │ └── 0002-fix-illegal-ins-infinite-loop.patch │ │ └── u-boot │ │ └── 0001-enable-distroboot.patch ├── duo256 │ ├── dts │ │ └── cv181x_milkv_duo256m_sd.dts │ ├── linux │ │ └── defconfig │ ├── memmap.py │ ├── partition_sd.xml │ ├── settings.mk │ └── u-boot │ │ ├── cvi_board_init.c │ │ ├── cvitek.h │ │ └── defconfig ├── duos │ ├── dts │ │ ├── cv181x_milkv_duos_emmc.dts │ │ └── cv181x_milkv_duos_sd.dts │ ├── linux │ │ └── defconfig │ ├── memmap.py │ ├── partition_emmc.xml │ ├── partition_sd.xml │ ├── settings.mk │ └── u-boot │ │ ├── cvi_board_init.c │ │ ├── cvitek.h │ │ └── defconfig ├── licheervnano │ ├── dts │ │ └── sg2002_licheervnano_sd.dts │ ├── linux │ │ └── defconfig │ ├── memmap.py │ ├── partition_sd.xml │ ├── patches │ │ └── fsbl │ │ │ └── 0002-add-debug-mode.patch │ ├── settings.mk │ └── u-boot │ │ ├── cvi_board_init.c │ │ ├── cvitek.h │ │ └── defconfig └── settings.mk └── scripts ├── Dockerfile ├── Makefile ├── addons ├── aic8800-firmware │ └── addon.mk ├── ethernet-leds │ ├── addon.mk │ └── ethernet-leds.service ├── hciattach-service │ ├── addon.mk │ └── hciattach.service ├── usb-gadget │ ├── addon.mk │ ├── run_usb.sh │ ├── usb-gadget-acm.service │ ├── usb-gadget-rndis-usb0.service │ ├── usb-gadget-rndis.service │ └── usb0 └── usb-switch │ ├── addon.mk │ └── usb-switch.service ├── deb └── cvitek-fsbl │ └── DEBIAN │ └── control ├── genimage_emmc.cfg ├── genimage_sd.cfg ├── python ├── XmlParser.py ├── mk_imgHeader.py ├── mkcvipart.py ├── mmap_conv.py └── raw2cimg.py └── setup_rootfs.sh /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build Docker Image 2 | on: 3 | push: 4 | tags: 5 | - '*' 6 | branches: 7 | - '*' 8 | workflow_dispatch: 9 | 10 | jobs: 11 | build-docker-image: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: read 15 | packages: write 16 | steps: 17 | - name: checkout 18 | uses: actions/checkout@v4 19 | - uses: dorny/paths-filter@v3 20 | id: filter 21 | with: 22 | filters: | 23 | src: 24 | - 'scripts/**' 25 | - '.github/**' 26 | - name: Log into registry ghcr.io 27 | if: (github.event_name != 'pull_request' && steps.filter.outputs.src == 'true') || startsWith(github.event.ref, 'refs/tags/v') 28 | uses: docker/login-action@v3 29 | with: 30 | registry: ghcr.io 31 | username: ${{ github.actor }} 32 | password: ${{ secrets.GITHUB_TOKEN }} 33 | 34 | - name: Extract Docker metadata 35 | if: (github.event_name != 'pull_request' && steps.filter.outputs.src == 'true') || startsWith(github.event.ref, 'refs/tags/v') 36 | id: meta 37 | uses: docker/metadata-action@v5 38 | with: 39 | images: ghcr.io/fishwaldo/sophgo-sg200x-debian 40 | 41 | - name: Build and push Docker image 42 | if: (github.event_name != 'pull_request' && steps.filter.outputs.src == 'true') || startsWith(github.event.ref, 'refs/tags/v') 43 | id: build-and-push 44 | uses: docker/build-push-action@v5 45 | with: 46 | context: . 47 | file: ./scripts/Dockerfile 48 | push: ${{ github.event_name != 'pull_request' }} 49 | tags: ${{ steps.meta.outputs.tags }} 50 | labels: ${{ steps.meta.outputs.labels }} 51 | - name: pause 52 | if: (github.event_name != 'pull_request' && steps.filter.outputs.src == 'true') || startsWith(github.event.ref, 'refs/tags/v') 53 | run: sleep 120 54 | 55 | build-image: 56 | strategy: 57 | matrix: 58 | boards: [licheervnano, duo256, duos] 59 | storage: [sd] 60 | include: 61 | - boards: duos 62 | storage: emmc 63 | runs-on: ubuntu-latest 64 | needs: build-docker-image 65 | steps: 66 | - name: Set up QEMU 67 | uses: docker/setup-qemu-action@v3 68 | - name: Get Board Configs 69 | uses: actions/checkout@v4 70 | - name: Build Images 71 | uses: addnab/docker-run-action@v3 72 | with: 73 | image: ghcr.io/fishwaldo/sophgo-sg200x-debian:master 74 | options: --privileged -v ${{ github.workspace }}/images/:/output -v ${{ github.workspace }}/configs/:/configs/ 75 | run: | 76 | make BOARD=${{ matrix.boards }} STORAGE_TYPE=${{ matrix.storage }} image 77 | chmod 777 /output/ 78 | - name: Pack 79 | run: | 80 | cd images/ 81 | ls -lah 82 | if [ -f ${{ matrix.boards }}_${{ matrix.storage }}.img ]; then 83 | lz4 -9 -f ${{ matrix.boards }}_${{ matrix.storage }}.img ${{ matrix.boards }}_${{ matrix.storage }}.img.lz4 84 | rm ${{ matrix.boards }}_${{ matrix.storage }}.img 85 | fi 86 | tar czvf ${{ matrix.boards }}-${{ matrix.storage }}_debs.tar.gz *.deb 87 | rm *.deb 88 | echo "PACKAGE=${{ github.workspace }}/images/*" >> $GITHUB_ENV 89 | - name: Upload package 90 | uses: actions/upload-artifact@v4 91 | with: 92 | name: image-files-${{ matrix.boards }}-${{ matrix.storage }} 93 | path: | 94 | ${{env.PACKAGE}} 95 | release: 96 | if: startsWith(github.ref, 'refs/tags/') 97 | runs-on: ubuntu-latest 98 | needs: [build-image] 99 | permissions: write-all 100 | steps: 101 | - name: download firmware 102 | uses: actions/download-artifact@v4 103 | - name: list images 104 | run: | 105 | ls -lah 106 | ls -lah image-files-*/ 107 | - name: publish artifacts 108 | uses: softprops/action-gh-release@v2 109 | with: 110 | append_body: true 111 | files: | 112 | image-files-*/* 113 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | image/* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Debian Images for Sophgo cv181x/sg200x based boards 2 | This repository builds debian sid images for Sophgo cv181x/sg200x based boards such as MilkV Duo256/DuoS and Sipeed LicheeRvNano. 3 | 4 | (Note, we don't support the MilkV Duo, as it does not have enough ram to run Debian) 5 | 6 | The images aim to be as close to possible to debian best practices as possible 7 | 8 | ## Flashing the Image 9 | 10 | ### Duo256, DuoS, and LicheeRVNano 11 | To flash from linux, either build your own image, or download a image from the releases page, and then run the following command: 12 | ``` 13 | sudo dd if=image/(board)_sd.img of=/dev/sdX bs=4M status=progress 14 | ``` 15 | 16 | From windows, you can use tools such as balena etcher 17 | 18 | where the (board)_sd.img is the image file you want to flash, and /dev/sdX is the device you want to flash to. 19 | (if you build for a different board, the image file name will be different) 20 | 21 | ### DuoS with EMMC 22 | To flash the DuoS with EMMC, you need to use the vendor tools to flash the image to the EMMC. You can follow the 23 | instructions at https://milkv.io/docs/duo/getting-started/duos#emmc-version-firmware-burning but instead of downloading 24 | the milkv-duos-emmc-v1.1.0-2024-0410.zip file, you download the duos_emmc.zip from the releases on this repository. 25 | 26 | if you already have a image installed, but wish to upgrade, when u-boot loads up, interupt the boot process by pressing any 27 | key and typing the following commands: 28 | ``` 29 | cvi_update 30 | ``` 31 | 32 | The flashing should then continue 33 | 34 | 35 | ## Image Info 36 | Logins: root/rv and debian/rv 37 | 38 | (root login is disabled via SSH, login via debian, and SU to root if needed) 39 | 40 | ### USB Gadget Support 41 | by default, a rndis interface is started on the USB port, and the IP address is 42 | 10.42.0.1 - It also starts a DHCP Server on that interface, so your PC should automatically get an IP address in the 10.42.0.x range 43 | 44 | To Disable the rndis interface, you can run the following command: 45 | ``` 46 | systemctl disable usb-gadget-rndis 47 | ``` 48 | 49 | There is also a option to start a serial port (ACM) interface instead of the rndis interface, to do this, you can run the following command: 50 | ``` 51 | systemctl disable usb-gadget-rndis 52 | systemctl enable usb-gadget-acm 53 | ``` 54 | 55 | After executing these commands, you need to reboot. 56 | 57 | ### DuoS - USB Type A Port 58 | After disabling the usb-gadgets, if you want to use the USB Type A Ports, then you need to turn them on: 59 | ``` 60 | systemctl enable usb-switch 61 | ``` 62 | 63 | and reboot afterwards. 64 | 65 | ### Wifi on DuoS/LicheeRVNano 66 | For the LicheeRVNano/DuoS board, Wifi is enabled. To connect to your wifi network, execute the following command and select "Activate a connection" and select your wifi network: 67 | ``` 68 | nmtui 69 | ``` 70 | 71 | ### Ethernet 72 | For Boards with eithernet, they should automatically get a IP address if your network has a DHCP Server. You can configure the 73 | ethernet port in nmtui 74 | 75 | ### Camera/ISP/Panel Support 76 | The images are based on the vendor 5.10 kernel, but exclude the following drivers: 77 | - mipi-rx/csi drivers 78 | - mipi-tx/dsi drivers 79 | - TPU Drivers 80 | - Any of the Video Encoding Drivers 81 | 82 | (this is mainly due to compatibility reasons with the glibc version in debian and musl version used in the vendor images) 83 | 84 | The images, by default, do not allocate any memory for the ION heap, as they are unused in this image, so you get the full memory of each device 85 | 86 | ### Ardunio/Freertos Support 87 | The images also include the remoteproc and mailbox drivers so you can load up ardunio/freertos images on the small C906 core. 88 | 89 | ### Additional Packages 90 | This image also adds the debian repository for https://github.com/Fishwaldo/sophgo-sg200x-packages so you can install additional repositories. The debian repository is hosted at 91 | https://sophgo.my-ho.st:8443/ which pulls down the compiled debian packages from the above github repository occasionally. 92 | 93 | 94 | ## Building the Image 95 | To build a stock image with no modifications: 96 | ``` 97 | podman run --privileged -it --rm -v ./configs/:/configs -v ./image:/output ghcr.io/fishwaldo/sophgo-sg200x-debian:master make BOARD=licheervnano image 98 | ``` 99 | 100 | Replace the licheervnano with the board you want to build for: 101 | - duo256 102 | - duos 103 | - licheervnano 104 | 105 | If you want to create a image for the DuoS with EMMC, you can add "STORAGE_TYPE=emmc" to the make command: 106 | ``` 107 | podman run --privileged -it --rm -v ./configs/:/configs -v ./image:/output ghcr.io/fishwaldo/sophgo-sg200x-debian:master make BOARD=duos STORAGE_TYPE=emmc image 108 | ``` 109 | 110 | The Docker image will build the image and place it in the image directory 111 | 112 | addition make targets are available when building: 113 | - image - builds the image 114 | - clean - cleans the build directory 115 | - linux - build a kernel debian package 116 | - fsbl - build the fsbl debain package (that includes cvitek-fsbl, opensbi and u-boot) 117 | 118 | ## Customizing the Image 119 | The configs directory contains patches, configuration and device tree files that are used to build the image. 120 | 121 | The configs/common directory contains the common configuration for all boards, and the configs/licheervnano and configs/duo256 directories contain the board specific configuration. 122 | 123 | To add packages to the image, either add the package name in PACKAGES variable of configs/settings.mk or if the packae is specific to a board, add it to the configs/\/settings.mk file 124 | 125 | Patches for the kernel, opensbi, u-boot or fsbl can be placed in configs/common/patches/ or configs/\/patches/ depending what they are for. 126 | 127 | To assist with developing the image, you can get a shell in the docker container by running: 128 | ``` 129 | docker run --privileged -it --rm -v ./configs/:/configs -v ./image:/output -v ./scripts/:/builder builder /bin/bash 130 | ``` 131 | inside the container, packages are build in the /builder/ directory, and the rootfs is placed at /rootfs/ directory 132 | 133 | # TODO 134 | - DeviceTree Overlay Support 135 | - Add support for the MIPI-CSI/DSI drivers (Sample applications would be in the sophgo-sg200x-packages repository if they do not depend upon a musl libc version) 136 | - Add support for the TPU drivers 137 | - Possibly mainline kernel support via the sophgo linux for-next repositories 138 | -------------------------------------------------------------------------------- /build_docker.sh: -------------------------------------------------------------------------------- 1 | docker build -t builder -f scripts/Dockerfile . 2 | -------------------------------------------------------------------------------- /build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker run --privileged -it --rm -v ./configs/:/configs -v ./image:/output builder make BOARD=licheervnano image 3 | -------------------------------------------------------------------------------- /configs/common/dts/cv180x/cv180x_asic_bga.dtsi: -------------------------------------------------------------------------------- 1 | &dac{ 2 | mute-gpio-l = <&porta 15 GPIO_ACTIVE_LOW>; 3 | mute-gpio-r = <&porta 30 GPIO_ACTIVE_LOW>; 4 | }; 5 | 6 | / { 7 | /delete-node/ i2s@04110000; 8 | /delete-node/ i2s@04120000; 9 | /delete-node/ sound_ext1; 10 | /delete-node/ sound_ext2; 11 | /delete-node/ sound_PDM; 12 | }; 13 | -------------------------------------------------------------------------------- /configs/common/dts/cv180x/cv180x_asic_qfn.dtsi: -------------------------------------------------------------------------------- 1 | &sd { 2 | no-1-8-v; 3 | }; 4 | 5 | &mipi_rx{ 6 | snsr-reset = <&portc 13 GPIO_ACTIVE_LOW>, <&portc 13 GPIO_ACTIVE_LOW>, <&portc 13 GPIO_ACTIVE_LOW>; 7 | }; 8 | 9 | &dac{ 10 | mute-gpio-r = <&porte 2 GPIO_ACTIVE_LOW>; 11 | }; 12 | 13 | &spi0 { 14 | status = "disabled"; 15 | num-cs = <1>; 16 | spidev@0 { 17 | compatible = "rohm,dh2228fv"; 18 | spi-max-frequency = <1000000>; 19 | reg = <0>; 20 | }; 21 | }; 22 | 23 | &spi1 { 24 | status = "disabled"; 25 | num-cs = <1>; 26 | spidev@0 { 27 | compatible = "rohm,dh2228fv"; 28 | spi-max-frequency = <1000000>; 29 | reg = <0>; 30 | }; 31 | }; 32 | 33 | &spi2 { 34 | status = "disabled"; 35 | num-cs = <1>; 36 | spidev@0 { 37 | compatible = "rohm,dh2228fv"; 38 | spi-max-frequency = <1000000>; 39 | reg = <0>; 40 | }; 41 | }; 42 | 43 | &spi3 { 44 | status = "okay"; 45 | num-cs = <1>; 46 | spidev@0 { 47 | compatible = "rohm,dh2228fv"; 48 | spi-max-frequency = <1000000>; 49 | reg = <0>; 50 | }; 51 | }; 52 | 53 | / { 54 | /delete-node/ wifi-sd@4320000; 55 | /delete-node/ i2s@04110000; 56 | /delete-node/ sound_ext1; 57 | /delete-node/ sound_ext2; 58 | /delete-node/ sound_PDM; 59 | 60 | wifi_pin { 61 | compatible = "cvitek,wifi-pin"; 62 | poweron-gpio = <&porte 2 GPIO_ACTIVE_HIGH>; 63 | wakeup-gpio = <&porte 6 GPIO_ACTIVE_HIGH>; 64 | }; 65 | 66 | }; 67 | -------------------------------------------------------------------------------- /configs/common/dts/cv180x/cv180x_asic_sd.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cv-emmc@4300000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | -------------------------------------------------------------------------------- /configs/common/dts/cv180x/cv180x_asic_spinand.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cvi-spif@10000000; 3 | /delete-node/ cv-emmc@4300000; 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /configs/common/dts/cv180x/cv180x_asic_spinor.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cv-emmc@4300000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /configs/common/dts/cv180x/cv180x_default_memmap.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | memory@80000000 { 3 | device_type = "memory"; 4 | reg = <0x00 CVIMMAP_KERNEL_MEMORY_ADDR 0x00 CVIMMAP_KERNEL_MEMORY_SIZE>; 5 | }; 6 | 7 | 8 | fast_image { 9 | compatible = "cvitek,rtos_image"; 10 | reg-names = "rtos_region"; 11 | reg = <0x0 CVIMMAP_FREERTOS_ADDR 0x0 CVIMMAP_FREERTOS_SIZE>; 12 | ion-size = ; //reserved ion size for freertos 13 | }; 14 | 15 | reserved-memory { 16 | #size-cells = <0x2>; 17 | #address-cells = <0x2>; 18 | ranges; 19 | 20 | ion_reserved: ion { 21 | compatible = "ion-region"; 22 | size = <0x0 CVIMMAP_ION_SIZE>; 23 | }; 24 | }; 25 | }; 26 | -------------------------------------------------------------------------------- /configs/common/dts/cv180x_riscv/cv180x_base_riscv.dtsi: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "cvi_board_memmap.h" 8 | 9 | /* 10 | * OpenSBI will add below subnode into reserved memory automatically 11 | * mmode_resv0@80000000 { 12 | * reg = <0x00 0x80000000 0x00 0x20000>; 13 | * phandle = <0x0d>; 14 | * }; 15 | * Skip below to avoid lmb region reseved conflict in uboot. 16 | * 17 | */ 18 | #ifndef __UBOOT__ 19 | /memreserve/ CVIMMAP_MONITOR_ADDR CVIMMAP_OPENSBI_SIZE; // OpenSBI 20 | #endif 21 | 22 | #include "cv180x_base.dtsi" 23 | 24 | / { 25 | model = "Cvitek. CV180X ASIC. C906."; 26 | 27 | #size-cells = <0x2>; 28 | #address-cells = <0x2>; 29 | 30 | c906_cpus:cpus { 31 | #address-cells = <0x01>; 32 | #size-cells = <0x00>; 33 | timebase-frequency = <25000000>; 34 | 35 | cpu-map { 36 | 37 | cluster0 { 38 | 39 | core0 { 40 | cpu = <0x01>; 41 | }; 42 | }; 43 | }; 44 | 45 | cpu@0 { 46 | device_type = "cpu"; 47 | reg = <0x00>; 48 | status = "okay"; 49 | compatible = "riscv"; 50 | riscv,isa = "rv64imafdvcsu"; 51 | mmu-type = "riscv,sv39"; 52 | clock-frequency = <25000000>; 53 | 54 | cpu0_intc: interrupt-controller { 55 | #interrupt-cells = <0x01>; 56 | interrupt-controller; 57 | compatible = "riscv,cpu-intc"; 58 | }; 59 | }; 60 | }; 61 | 62 | soc { 63 | #address-cells = <0x02>; 64 | #size-cells = <0x02>; 65 | compatible = "simple-bus"; 66 | ranges; 67 | 68 | plic0: interrupt-controller@70000000 { 69 | riscv,ndev = <101>; 70 | riscv,max-priority = <0x07>; 71 | reg-names = "control"; 72 | reg = <0x00 0x70000000 0x00 0x4000000>; 73 | interrupts-extended = <&cpu0_intc 0xffffffff &cpu0_intc 0x09>; 74 | interrupt-controller; 75 | compatible = "riscv,plic0"; 76 | #interrupt-cells = <0x02>; 77 | #address-cells = <0x00>; 78 | }; 79 | 80 | clint@74000000 { 81 | interrupts-extended = <&cpu0_intc 0x03 &cpu0_intc 0x07>; 82 | reg = <0x00 0x74000000 0x00 0x10000>; 83 | compatible = "riscv,clint0"; 84 | clint,has-no-64bit-mmio; 85 | }; 86 | 87 | }; 88 | 89 | 90 | cv180x_cooling:cv180x_cooling { 91 | clocks = <&clk CV180X_CLK_C906_0>, <&clk CV180X_CLK_TPU>; 92 | clock-names = "clk_cpu", "clk_tpu_axi"; 93 | dev-freqs = <850000000 500000000>, 94 | <425000000 375000000>, 95 | <425000000 300000000>; 96 | compatible = "cvitek,cv180x-cooling"; 97 | #cooling-cells = <2>; 98 | }; 99 | 100 | tpu { 101 | interrupts = <75 IRQ_TYPE_LEVEL_HIGH>, 102 | <76 IRQ_TYPE_LEVEL_HIGH>; 103 | interrupt-names = "tiu_irq", "tdma_irq"; 104 | interrupt-parent = <&plic0>; 105 | }; 106 | 107 | mon { 108 | interrupts = <93 IRQ_TYPE_LEVEL_HIGH>; 109 | interrupt-names = "mon_irq"; 110 | interrupt-parent = <&plic0>; 111 | }; 112 | 113 | wiegand0 { 114 | interrupts = <64 IRQ_TYPE_LEVEL_HIGH>; 115 | interrupt-parent = <&plic0>; 116 | }; 117 | 118 | wiegand1 { 119 | interrupts = <65 IRQ_TYPE_LEVEL_HIGH>; 120 | interrupt-parent = <&plic0>; 121 | }; 122 | 123 | wiegand2 { 124 | interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; 125 | interrupt-parent = <&plic0>; 126 | }; 127 | 128 | saradc { 129 | interrupts = <100 IRQ_TYPE_EDGE_RISING>; 130 | interrupt-parent = <&plic0>; 131 | }; 132 | 133 | rtc { 134 | interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; 135 | interrupt-parent = <&plic0>; 136 | }; 137 | 138 | sysdma_remap { 139 | int_mux = <0x7FC00>; /* enable bit [10..18] for CPU1(906B) */ 140 | }; 141 | 142 | dmac: dma@0x4330000 { 143 | interrupts = <29 IRQ_TYPE_LEVEL_HIGH>; 144 | interrupt-parent = <&plic0>; 145 | }; 146 | 147 | watchdog0: cv-wd@0x3010000 { 148 | interrupts = <58 IRQ_TYPE_LEVEL_HIGH>; 149 | }; 150 | 151 | spinand:cv-spinf@4060000 { 152 | interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; 153 | interrupt-parent = <&plic0>; 154 | }; 155 | 156 | spif:cvi-spif@10000000 { 157 | interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; 158 | interrupt-parent = <&plic0>; 159 | }; 160 | 161 | spi0:spi0@04180000 { 162 | interrupts = <54 IRQ_TYPE_LEVEL_HIGH>; 163 | interrupt-parent = <&plic0>; 164 | }; 165 | 166 | spi1:spi1@04190000 { 167 | interrupts = <55 IRQ_TYPE_LEVEL_HIGH>; 168 | interrupt-parent = <&plic0>; 169 | }; 170 | 171 | spi2:spi2@041A0000 { 172 | interrupts = <56 IRQ_TYPE_LEVEL_HIGH>; 173 | interrupt-parent = <&plic0>; 174 | }; 175 | 176 | spi3:spi3@041B0000 { 177 | interrupts = <57 IRQ_TYPE_LEVEL_HIGH>; 178 | interrupt-parent = <&plic0>; 179 | }; 180 | 181 | uart0: serial@04140000 { 182 | interrupts = <44 IRQ_TYPE_LEVEL_HIGH>; 183 | interrupt-parent = <&plic0>; 184 | }; 185 | 186 | uart1: serial@04150000 { 187 | interrupts = <45 IRQ_TYPE_LEVEL_HIGH>; 188 | interrupt-parent = <&plic0>; 189 | }; 190 | 191 | uart2: serial@04160000 { 192 | interrupts = <46 IRQ_TYPE_LEVEL_HIGH>; 193 | interrupt-parent = <&plic0>; 194 | }; 195 | 196 | uart3: serial@04170000 { 197 | interrupts = <47 IRQ_TYPE_LEVEL_HIGH>; 198 | interrupt-parent = <&plic0>; 199 | }; 200 | 201 | uart4: serial@041C0000 { 202 | interrupts = <48 IRQ_TYPE_LEVEL_HIGH>; 203 | interrupt-parent = <&plic0>; 204 | }; 205 | 206 | gpio0: gpio@03020000 { 207 | porta: gpio-controller@0 { 208 | interrupt-controller; 209 | interrupts = <60 IRQ_TYPE_LEVEL_HIGH>; 210 | interrupt-parent = <&plic0>; 211 | }; 212 | }; 213 | 214 | gpio1: gpio@03021000 { 215 | portb: gpio-controller@1 { 216 | interrupt-controller; 217 | interrupts = <61 IRQ_TYPE_LEVEL_HIGH>; 218 | interrupt-parent = <&plic0>; 219 | }; 220 | }; 221 | 222 | gpio2: gpio@03022000 { 223 | portc: gpio-controller@2 { 224 | interrupt-controller; 225 | interrupts = <62 IRQ_TYPE_LEVEL_HIGH>; 226 | interrupt-parent = <&plic0>; 227 | }; 228 | }; 229 | 230 | gpio3: gpio@03023000 { 231 | portd: gpio-controller@3 { 232 | interrupt-controller; 233 | interrupts = <63 IRQ_TYPE_LEVEL_HIGH>; 234 | interrupt-parent = <&plic0>; 235 | }; 236 | }; 237 | 238 | gpio4: gpio@05021000 { 239 | porte: gpio-controller@4 { 240 | interrupt-controller; 241 | interrupts = <70 IRQ_TYPE_LEVEL_HIGH>; 242 | interrupt-parent = <&plic0>; 243 | }; 244 | }; 245 | 246 | i2c0: i2c@04000000 { 247 | interrupts = <49 IRQ_TYPE_LEVEL_HIGH>; 248 | interrupt-parent = <&plic0>; 249 | }; 250 | 251 | i2c1: i2c@04010000 { 252 | interrupts = <50 IRQ_TYPE_LEVEL_HIGH>; 253 | interrupt-parent = <&plic0>; 254 | }; 255 | 256 | i2c2: i2c@04020000 { 257 | interrupts = <51 IRQ_TYPE_LEVEL_HIGH>; 258 | interrupt-parent = <&plic0>; 259 | }; 260 | 261 | i2c3: i2c@04030000 { 262 | interrupts = <52 IRQ_TYPE_LEVEL_HIGH>; 263 | interrupt-parent = <&plic0>; 264 | }; 265 | 266 | i2c4: i2c@04040000 { 267 | interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; 268 | interrupt-parent = <&plic0>; 269 | }; 270 | 271 | ethernet0: ethernet@4070000 { 272 | interrupt-names = "macirq"; 273 | interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; 274 | interrupt-parent = <&plic0>; 275 | }; 276 | #if 0 277 | emmc:cv-emmc@4300000 { 278 | interrupts = <34 IRQ_TYPE_LEVEL_HIGH>; 279 | interrupt-parent = <&plic0>; 280 | }; 281 | #endif 282 | sd:cv-sd@4310000 { 283 | interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; 284 | interrupt-parent = <&plic0>; 285 | }; 286 | 287 | i2s0: i2s@04100000 { 288 | interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; 289 | interrupt-parent = <&plic0>; 290 | }; 291 | 292 | i2s1: i2s@04110000 { 293 | interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; 294 | interrupt-parent = <&plic0>; 295 | }; 296 | 297 | i2s2: i2s@04120000 { 298 | interrupts = <42 IRQ_TYPE_LEVEL_HIGH>; 299 | interrupt-parent = <&plic0>; 300 | }; 301 | 302 | i2s3: i2s@04130000 { 303 | interrupts = <43 IRQ_TYPE_LEVEL_HIGH>; 304 | interrupt-parent = <&plic0>; 305 | }; 306 | 307 | vi { 308 | interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; 309 | interrupt-parent = <&plic0>; 310 | interrupt-names = "isp"; 311 | }; 312 | 313 | vcodec { 314 | interrupts = <22 IRQ_TYPE_LEVEL_HIGH>, 315 | <21 IRQ_TYPE_LEVEL_HIGH>, 316 | <23 IRQ_TYPE_LEVEL_HIGH>; 317 | interrupt-names = "h265","h264","sbm"; 318 | interrupt-parent = <&plic0>; 319 | }; 320 | 321 | jpu { 322 | interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; 323 | interrupt-names = "jpeg"; 324 | interrupt-parent = <&plic0>; 325 | }; 326 | 327 | rtos_cmdqu { 328 | interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; 329 | interrupt-names = "mailbox"; 330 | interrupt-parent = <&plic0>; 331 | }; 332 | 333 | wifisd:wifi-sd@4320000 { 334 | interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; 335 | interrupt-parent = <&plic0>; 336 | }; 337 | 338 | mipi_rx: cif { 339 | interrupts = <26 IRQ_TYPE_LEVEL_HIGH>, 340 | <27 IRQ_TYPE_LEVEL_HIGH>; 341 | interrupt-names = "csi0", "csi1"; 342 | interrupt-parent = <&plic0>; 343 | }; 344 | #if 0 345 | ive { 346 | interrupt-names = "ive_irq"; 347 | interrupt-parent = <&plic0>; 348 | interrupts = <97 IRQ_TYPE_LEVEL_HIGH>; 349 | }; 350 | #endif 351 | vpss { 352 | interrupts = <25 IRQ_TYPE_LEVEL_HIGH>; 353 | interrupt-names = "sc"; 354 | interrupt-parent = <&plic0>; 355 | }; 356 | 357 | dwa { 358 | interrupts = <28 IRQ_TYPE_LEVEL_HIGH>; 359 | interrupt-names = "dwa"; 360 | interrupt-parent = <&plic0>; 361 | }; 362 | 363 | usb: usb@04340000 { 364 | interrupts = <30 IRQ_TYPE_LEVEL_HIGH>; 365 | interrupt-parent = <&plic0>; 366 | }; 367 | 368 | thermal:thermal@030E0000 { 369 | interrupts = <16 IRQ_TYPE_LEVEL_HIGH>; 370 | interrupt-names = "tempsen"; 371 | interrupt-parent = <&plic0>; 372 | }; 373 | 374 | }; 375 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x/cv181x_asic_bga.dtsi: -------------------------------------------------------------------------------- 1 | &dac{ 2 | mute-gpio-l = <&porta 15 GPIO_ACTIVE_LOW>; 3 | mute-gpio-r = <&porta 30 GPIO_ACTIVE_LOW>; 4 | }; 5 | 6 | &spi0 { 7 | status = "disabled"; 8 | num-cs = <1>; 9 | spidev@0 { 10 | compatible = "rohm,dh2228fv"; 11 | spi-max-frequency = <1000000>; 12 | reg = <0>; 13 | }; 14 | }; 15 | 16 | &spi1 { 17 | status = "disabled"; 18 | num-cs = <1>; 19 | spidev@0 { 20 | compatible = "rohm,dh2228fv"; 21 | spi-max-frequency = <1000000>; 22 | reg = <0>; 23 | }; 24 | }; 25 | 26 | &spi2 { 27 | status = "disabled"; 28 | num-cs = <1>; 29 | spidev@0 { 30 | compatible = "rohm,dh2228fv"; 31 | spi-max-frequency = <1000000>; 32 | reg = <0>; 33 | }; 34 | }; 35 | 36 | &spi3 { 37 | status = "okay"; 38 | num-cs = <1>; 39 | spidev@0 { 40 | compatible = "rohm,dh2228fv"; 41 | spi-max-frequency = <1000000>; 42 | reg = <0>; 43 | }; 44 | }; 45 | 46 | &i2c1 { 47 | status = "disabled"; 48 | }; 49 | 50 | / { 51 | /delete-node/ i2s@04110000; 52 | /delete-node/ i2s@04120000; 53 | /delete-node/ sound_ext1; 54 | /delete-node/ sound_ext2; 55 | /delete-node/ sound_PDM; 56 | }; 57 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x/cv181x_asic_emmc.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cvi-spif@10000000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x/cv181x_asic_qfn.dtsi: -------------------------------------------------------------------------------- 1 | &sd { 2 | no-1-8-v; 3 | }; 4 | 5 | &mipi_rx{ 6 | snsr-reset = <&portc 13 GPIO_ACTIVE_LOW>, <&portc 13 GPIO_ACTIVE_LOW>, <&portc 13 GPIO_ACTIVE_LOW>; 7 | }; 8 | 9 | &mipi_tx { 10 | reset-gpio = <&porta 15 GPIO_ACTIVE_LOW>; 11 | pwm-gpio = <&porta 18 GPIO_ACTIVE_HIGH>; 12 | power-ct-gpio = <&porta 19 GPIO_ACTIVE_HIGH>; 13 | }; 14 | 15 | &spi0 { 16 | status = "disabled"; 17 | num-cs = <1>; 18 | spidev@0 { 19 | compatible = "rohm,dh2228fv"; 20 | spi-max-frequency = <1000000>; 21 | reg = <0>; 22 | }; 23 | }; 24 | 25 | &spi1 { 26 | status = "disabled"; 27 | num-cs = <1>; 28 | spidev@0 { 29 | compatible = "rohm,dh2228fv"; 30 | spi-max-frequency = <1000000>; 31 | reg = <0>; 32 | }; 33 | }; 34 | 35 | &spi2 { 36 | status = "disabled"; 37 | num-cs = <1>; 38 | spidev@0 { 39 | compatible = "rohm,dh2228fv"; 40 | spi-max-frequency = <1000000>; 41 | reg = <0>; 42 | }; 43 | }; 44 | 45 | &spi3 { 46 | status = "okay"; 47 | num-cs = <1>; 48 | spidev@0 { 49 | compatible = "rohm,dh2228fv"; 50 | spi-max-frequency = <1000000>; 51 | reg = <0>; 52 | }; 53 | }; 54 | 55 | &i2c0 { 56 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 57 | scl-pinmux = <0x03001070 0x0 0x3>; // IIC0_SCL/IIC0_SCL/XGPIOA[28] 58 | sda-pinmux = <0x03001074 0x0 0x3>; // IIC0_SDA/IIC0_SDA/XGPIOA[29] 59 | /* gpio port */ 60 | scl-gpios = <&porta 28 GPIO_ACTIVE_HIGH>; 61 | sda-gpios = <&porta 29 GPIO_ACTIVE_HIGH>; 62 | }; 63 | 64 | &i2c1 { 65 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 66 | scl-pinmux = <0x03009408 0x2 0x3>; // SPI1_MOSI/IIC1_SCL/XGPIOB[7] 67 | sda-pinmux = <0x0300940c 0x2 0x3>; // SPI1_MISO/IIC1_SDA/XGPIOB[8] 68 | /* gpio port */ 69 | scl-gpios = <&portb 7 GPIO_ACTIVE_HIGH>; 70 | sda-gpios = <&portb 8 GPIO_ACTIVE_HIGH>; 71 | }; 72 | 73 | &i2c2 { 74 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 75 | scl-pinmux = <0x030011a0 0x4 0x3>; // PAD_MIPI_TXP1/IIC2_SCL/XGPIOC[15] 76 | sda-pinmux = <0x0300119c 0x4 0x3>; // PAD_MIPI_TXM1/IIC2_SDA/XGPIOC[14] 77 | /* gpio port */ 78 | scl-gpios = <&portc 15 GPIO_ACTIVE_HIGH>; 79 | sda-gpios = <&portc 14 GPIO_ACTIVE_HIGH>; 80 | }; 81 | 82 | &i2c3 { 83 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 84 | scl-pinmux = <0x03001014 0x0 0x3>; // IIC3_SCL/IIC3_SCL/XGPIOA[5] 85 | sda-pinmux = <0x03001018 0x0 0x3>; // IIC3_SDA/IIC3_SDA/XGPIOA[6] 86 | /* gpio port */ 87 | scl-gpios = <&porta 5 GPIO_ACTIVE_HIGH>; 88 | sda-gpios = <&porta 6 GPIO_ACTIVE_HIGH>; 89 | }; 90 | 91 | &i2c4 { 92 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 93 | scl-pinmux = <0x030010f0 0x2 0x3>; // ADC3/IIC4_SCL/XGPIOB[1] 94 | sda-pinmux = <0x030010f4 0x2 0x3>; // ADC2/IIC4_SDA/XGPIOB[2] 95 | /* gpio port */ 96 | scl-gpios = <&portb 1 GPIO_ACTIVE_HIGH>; 97 | sda-gpios = <&portb 2 GPIO_ACTIVE_HIGH>; 98 | }; 99 | 100 | / { 101 | /delete-node/ wifi-sd@4320000; 102 | /delete-node/ i2s@04110000; 103 | /delete-node/ i2s@04120000; 104 | /delete-node/ sound_ext1; 105 | /delete-node/ sound_ext2; 106 | /delete-node/ sound_PDM; 107 | 108 | wifi_pin { 109 | compatible = "cvitek,wifi-pin"; 110 | poweron-gpio = <&porte 2 GPIO_ACTIVE_HIGH>; 111 | wakeup-gpio = <&porte 6 GPIO_ACTIVE_HIGH>; 112 | }; 113 | 114 | }; 115 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x/cv181x_asic_sd.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cv-emmc@4300000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x/cv181x_asic_spinand.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cvi-spif@10000000; 3 | /delete-node/ cv-emmc@4300000; 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x/cv181x_asic_spinor.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cv-emmc@4300000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x/cv181x_default_memmap.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | memory@80000000 { 3 | device_type = "memory"; 4 | reg = <0x00 CVIMMAP_KERNEL_MEMORY_ADDR 0x00 CVIMMAP_KERNEL_MEMORY_SIZE>; 5 | }; 6 | 7 | reserved-memory { 8 | #size-cells = <0x2>; 9 | #address-cells = <0x2>; 10 | ranges; 11 | 12 | fast_image: rproc { 13 | reg = <0x0 CVIMMAP_FREERTOS_ADDR 0x0 CVIMMAP_FREERTOS_SIZE>; 14 | no-map; 15 | }; 16 | 17 | vdev0vring0: vdev0vring0 { 18 | compatible = "shared-dma-pool"; 19 | alloc-ranges = <0x0 0x8f528000 0 0x4000>; 20 | size = <0x0 0x4000>; 21 | no-map; 22 | }; 23 | 24 | vdev0vring1: vdev0vring1 { 25 | compatible = "shared-dma-pool"; 26 | alloc-ranges = <0x0 0x8f52C000 0 0x4000>; 27 | size = <0x0 0x4000>; 28 | no-map; 29 | }; 30 | 31 | vdev0buffer: vdev0buffer { 32 | compatible = "shared-dma-pool"; 33 | alloc-ranges = <0x0 0x8f530000 0 0x100000>; 34 | size = <0x0 0x100000>; 35 | no-map; 36 | }; 37 | 38 | 39 | #if (CVIMMAP_ION_SIZE > 0) 40 | ion_reserved: ion { 41 | compatible = "ion-region"; 42 | size = <0x0 CVIMMAP_ION_SIZE>; 43 | }; 44 | #endif 45 | }; 46 | }; 47 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x_arm/cv181x_base_arm.dtsi: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "cvi_board_memmap.h" 8 | 9 | /memreserve/ CVIMMAP_MONITOR_ADDR CVIMMAP_ATF_SIZE; // ATF (BL31 + BL32) 512KB 10 | 11 | #include "cv181x_base.dtsi" 12 | 13 | / { 14 | model = "Cvitek. CV181X ASIC. ARM."; 15 | interrupt-parent = <&gic>; 16 | 17 | #size-cells = <0x2>; 18 | #address-cells = <0x2>; 19 | 20 | gic: interrupt-controller { 21 | compatible = "arm,cortex-a15-gic"; 22 | ranges; 23 | #size-cells = <0x2>; 24 | #address-cells = <0x2>; 25 | interrupt-controller; 26 | #interrupt-cells = <0x3>; 27 | reg = <0x0 0x01F01000 0x0 0x1000>, 28 | <0x0 0x01F02000 0x0 0x2000>; 29 | }; 30 | 31 | pmu_a53 { 32 | compatible = "arm,cortex-a53-pmu"; 33 | interrupts = , 34 | ; 35 | interrupt-affinity = <&A53_0>; 36 | }; 37 | 38 | psci { 39 | migrate = <0xc4000005>; 40 | cpu_on = <0xc4000003>; 41 | cpu_off = <0x84000002>; 42 | cpu_suspend = <0xc4000001>; 43 | sys_poweroff = <0x84000008>; 44 | sys_reset = <0x84000009>; 45 | method = "smc"; 46 | compatible = "arm,psci-0.2", "arm,psci"; 47 | }; 48 | 49 | cpus { 50 | #size-cells = <0x0>; 51 | #address-cells = <0x1>; 52 | 53 | A53_0: cpu@0 { 54 | reg = <0x0>; 55 | enable-method = "psci"; 56 | compatible = "arm,cortex-a53"; 57 | device_type = "cpu"; 58 | next-level-cache = <&CA53_L2>; 59 | }; 60 | 61 | CA53_L2: l2-cache0 { 62 | compatible = "cache"; 63 | }; 64 | }; 65 | 66 | timer { 67 | interrupts = , 68 | , 69 | , 70 | ; 71 | always-on; 72 | clock-frequency = <25000000>; 73 | compatible = "arm,armv8-timer"; 74 | }; 75 | 76 | firmware { 77 | optee { 78 | compatible = "linaro,optee-tz"; 79 | method = "smc"; 80 | }; 81 | }; 82 | 83 | cv181x_cooling:cv181x_cooling { 84 | clocks = <&clk CV181X_CLK_A53>, <&clk CV181X_CLK_TPU>; 85 | clock-names = "clk_cpu", "clk_tpu_axi"; 86 | dev-freqs = <800000000 500000000>, 87 | <400000000 375000000>, 88 | <400000000 300000000>; 89 | compatible = "cvitek,cv181x-cooling"; 90 | #cooling-cells = <2>; 91 | }; 92 | 93 | tpu { 94 | interrupts = , 95 | ; 96 | }; 97 | 98 | mon { 99 | interrupts = ; 100 | }; 101 | 102 | wiegand0 { 103 | interrupts = ; 104 | }; 105 | 106 | wiegand1 { 107 | interrupts = ; 108 | }; 109 | 110 | wiegand2 { 111 | interrupts = ; 112 | }; 113 | 114 | saradc { 115 | interrupts = ; 116 | }; 117 | 118 | rtc { 119 | interrupts = ; 120 | }; 121 | 122 | sysdma_remap { 123 | int_mux = <0x1FF>; /* enable bit [0..8] for CPU0(CA53) */ 124 | }; 125 | 126 | dmac: dma@0x4330000 { 127 | interrupts = ; 128 | }; 129 | 130 | #if 0 131 | watchdog0: cv-wd@0x3010000 { 132 | interrupts = ; 133 | }; 134 | #endif 135 | 136 | spinand:cv-spinf@4060000 { 137 | interrupts = ; 138 | }; 139 | 140 | spif:cvi-spif@10000000 { 141 | interrupts = ; 142 | }; 143 | 144 | spi0:spi0@04180000 { 145 | interrupts = ; 146 | }; 147 | 148 | spi1:spi1@04190000 { 149 | interrupts = ; 150 | }; 151 | 152 | spi2:spi2@041A0000 { 153 | interrupts = ; 154 | }; 155 | 156 | spi3:spi3@041B0000 { 157 | interrupts = ; 158 | }; 159 | 160 | uart0: serial@04140000 { 161 | interrupts = ; 162 | }; 163 | 164 | uart1: serial@04150000 { 165 | interrupts = ; 166 | }; 167 | 168 | uart2: serial@04160000 { 169 | interrupts = ; 170 | }; 171 | 172 | uart3: serial@04170000 { 173 | interrupts = ; 174 | }; 175 | 176 | uart4: serial@041C0000 { 177 | interrupts = ; 178 | }; 179 | 180 | gpio0: gpio@03020000 { 181 | porta: gpio-controller@0 { 182 | interrupt-controller; 183 | interrupts = ; 184 | }; 185 | }; 186 | 187 | gpio1: gpio@03021000 { 188 | portb: gpio-controller@1 { 189 | interrupt-controller; 190 | interrupts = ; 191 | }; 192 | }; 193 | 194 | gpio2: gpio@03022000 { 195 | portc: gpio-controller@2 { 196 | interrupt-controller; 197 | interrupts = ; 198 | }; 199 | }; 200 | 201 | gpio3: gpio@03023000 { 202 | portd: gpio-controller@3 { 203 | interrupt-controller; 204 | interrupts = ; 205 | }; 206 | }; 207 | 208 | gpio4: gpio@05021000 { 209 | porte: gpio-controller@4 { 210 | interrupt-controller; 211 | interrupts = ; 212 | }; 213 | }; 214 | 215 | i2c0: i2c@04000000 { 216 | interrupts = ; 217 | }; 218 | 219 | i2c1: i2c@04010000 { 220 | interrupts = ; 221 | }; 222 | 223 | i2c2: i2c@04020000 { 224 | interrupts = ; 225 | }; 226 | 227 | i2c3: i2c@04030000 { 228 | interrupts = ; 229 | }; 230 | 231 | i2c4: i2c@04040000 { 232 | interrupts = ; 233 | }; 234 | 235 | ethernet0: ethernet@4070000 { 236 | interrupt-names = "macirq"; 237 | interrupts = ; 238 | }; 239 | 240 | emmc:cv-emmc@4300000 { 241 | interrupts = ; 242 | }; 243 | 244 | sd:cv-sd@4310000 { 245 | interrupts = ; 246 | }; 247 | 248 | i2s0: i2s@04100000 { 249 | interrupts = ; 250 | }; 251 | 252 | i2s1: i2s@04110000 { 253 | interrupts = ; 254 | }; 255 | 256 | i2s2: i2s@04120000 { 257 | interrupts = ; 258 | }; 259 | 260 | i2s3: i2s@04130000 { 261 | interrupts = ; 262 | }; 263 | 264 | wifisd:wifi-sd@4320000 { 265 | interrupts = ; 266 | }; 267 | 268 | mipi_rx: cif { 269 | interrupts = , 270 | ; 271 | interrupt-names = "csi0", "csi1"; 272 | }; 273 | 274 | vi { 275 | interrupts = ; 276 | interrupt-names = "isp"; 277 | }; 278 | 279 | ive { 280 | interrupt-names = "ive_irq"; 281 | interrupts = ; 282 | }; 283 | 284 | vpss { 285 | interrupts = ; 286 | interrupt-names = "sc"; 287 | }; 288 | 289 | dwa { 290 | interrupts = ; 291 | interrupt-names = "dwa"; 292 | }; 293 | 294 | vcodec { 295 | interrupts = , 296 | , 297 | ; 298 | interrupt-names = "h265","h264","sbm"; 299 | }; 300 | 301 | jpu { 302 | interrupts = ; 303 | interrupt-names = "jpeg"; 304 | }; 305 | 306 | rtos_cmdqu { 307 | interrupts = ; 308 | interrupt-names = "mailbox"; 309 | }; 310 | 311 | usb: usb@04340000 { 312 | interrupts = ; 313 | }; 314 | 315 | thermal:thermal@030E0000 { 316 | interrupts = ; 317 | interrupt-names = "tempsen"; 318 | }; 319 | 320 | }; 321 | -------------------------------------------------------------------------------- /configs/common/dts/cv181x_riscv/cv181x_base_riscv.dtsi: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "cvi_board_memmap.h" 8 | 9 | /* 10 | * OpenSBI will add below subnode into reserved memory automatically 11 | * mmode_resv0@80000000 { 12 | * reg = <0x00 0x80000000 0x00 0x20000>; 13 | * phandle = <0x0d>; 14 | * }; 15 | * Skip below to avoid lmb region reseved conflict in uboot. 16 | * 17 | */ 18 | #ifndef __UBOOT__ 19 | /memreserve/ CVIMMAP_MONITOR_ADDR CVIMMAP_OPENSBI_SIZE; // OpenSBI 20 | #endif 21 | 22 | #include "cv181x_base.dtsi" 23 | 24 | / { 25 | model = "Cvitek. CV181X ASIC. C906."; 26 | 27 | #size-cells = <0x2>; 28 | #address-cells = <0x2>; 29 | 30 | cpus { 31 | #address-cells = <0x01>; 32 | #size-cells = <0x00>; 33 | timebase-frequency = <25000000>; 34 | 35 | cpu-map { 36 | 37 | cluster0 { 38 | 39 | core0 { 40 | cpu = <0x01>; 41 | }; 42 | }; 43 | }; 44 | 45 | cpu@0 { 46 | device_type = "cpu"; 47 | reg = <0x00>; 48 | status = "okay"; 49 | compatible = "riscv"; 50 | riscv,isa = "rv64imafdvcsu"; 51 | mmu-type = "riscv,sv39"; 52 | clock-frequency = <25000000>; 53 | 54 | cpu0_intc: interrupt-controller { 55 | #interrupt-cells = <0x01>; 56 | interrupt-controller; 57 | compatible = "riscv,cpu-intc"; 58 | }; 59 | }; 60 | }; 61 | 62 | soc { 63 | #address-cells = <0x02>; 64 | #size-cells = <0x02>; 65 | compatible = "simple-bus"; 66 | ranges; 67 | 68 | plic0: interrupt-controller@70000000 { 69 | riscv,ndev = <101>; 70 | riscv,max-priority = <0x07>; 71 | reg-names = "control"; 72 | reg = <0x00 0x70000000 0x00 0x4000000>; 73 | interrupts-extended = <&cpu0_intc 0xffffffff &cpu0_intc 0x09>; 74 | interrupt-controller; 75 | compatible = "riscv,plic0"; 76 | #interrupt-cells = <0x02>; 77 | #address-cells = <0x00>; 78 | }; 79 | 80 | clint@74000000 { 81 | interrupts-extended = <&cpu0_intc 0x03 &cpu0_intc 0x07>; 82 | reg = <0x00 0x74000000 0x00 0x10000>; 83 | compatible = "riscv,clint0"; 84 | clint,has-no-64bit-mmio; 85 | }; 86 | 87 | }; 88 | 89 | cv181x_cooling:cv181x_cooling { 90 | clocks = <&clk CV181X_CLK_C906_0>, <&clk CV181X_CLK_TPU>; 91 | clock-names = "clk_cpu", "clk_tpu_axi"; 92 | dev-freqs = <850000000 500000000>, 93 | <425000000 375000000>, 94 | <425000000 300000000>; 95 | compatible = "cvitek,cv181x-cooling"; 96 | #cooling-cells = <2>; 97 | }; 98 | 99 | tpu { 100 | interrupts = <75 IRQ_TYPE_LEVEL_HIGH>, 101 | <76 IRQ_TYPE_LEVEL_HIGH>; 102 | interrupt-names = "tiu_irq", "tdma_irq"; 103 | interrupt-parent = <&plic0>; 104 | }; 105 | 106 | mon { 107 | interrupts = <93 IRQ_TYPE_LEVEL_HIGH>; 108 | interrupt-names = "mon_irq"; 109 | interrupt-parent = <&plic0>; 110 | }; 111 | 112 | wiegand0 { 113 | interrupts = <64 IRQ_TYPE_LEVEL_HIGH>; 114 | interrupt-parent = <&plic0>; 115 | }; 116 | 117 | wiegand1 { 118 | interrupts = <65 IRQ_TYPE_LEVEL_HIGH>; 119 | interrupt-parent = <&plic0>; 120 | }; 121 | 122 | wiegand2 { 123 | interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; 124 | interrupt-parent = <&plic0>; 125 | }; 126 | 127 | saradc { 128 | interrupts = <100 IRQ_TYPE_EDGE_RISING>; 129 | interrupt-parent = <&plic0>; 130 | }; 131 | 132 | rtc { 133 | interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; 134 | interrupt-parent = <&plic0>; 135 | }; 136 | 137 | sysdma_remap { 138 | int_mux = <0x7FC00>; /* enable bit [10..18] for CPU1(906B) */ 139 | }; 140 | 141 | dmac: dma@0x4330000 { 142 | interrupts = <29 IRQ_TYPE_LEVEL_HIGH>; 143 | interrupt-parent = <&plic0>; 144 | }; 145 | 146 | watchdog0: cv-wd@0x3010000 { 147 | interrupts = <58 IRQ_TYPE_LEVEL_HIGH>; 148 | }; 149 | 150 | spinand:cv-spinf@4060000 { 151 | interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; 152 | interrupt-parent = <&plic0>; 153 | }; 154 | 155 | spif:cvi-spif@10000000 { 156 | interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; 157 | interrupt-parent = <&plic0>; 158 | }; 159 | 160 | spi0:spi0@04180000 { 161 | interrupts = <54 IRQ_TYPE_LEVEL_HIGH>; 162 | interrupt-parent = <&plic0>; 163 | }; 164 | 165 | spi1:spi1@04190000 { 166 | interrupts = <55 IRQ_TYPE_LEVEL_HIGH>; 167 | interrupt-parent = <&plic0>; 168 | }; 169 | 170 | spi2:spi2@041A0000 { 171 | interrupts = <56 IRQ_TYPE_LEVEL_HIGH>; 172 | interrupt-parent = <&plic0>; 173 | }; 174 | 175 | spi3:spi3@041B0000 { 176 | interrupts = <57 IRQ_TYPE_LEVEL_HIGH>; 177 | interrupt-parent = <&plic0>; 178 | }; 179 | 180 | uart0: serial@04140000 { 181 | interrupts = <44 IRQ_TYPE_LEVEL_HIGH>; 182 | interrupt-parent = <&plic0>; 183 | }; 184 | 185 | uart1: serial@04150000 { 186 | interrupts = <45 IRQ_TYPE_LEVEL_HIGH>; 187 | interrupt-parent = <&plic0>; 188 | }; 189 | 190 | uart2: serial@04160000 { 191 | interrupts = <46 IRQ_TYPE_LEVEL_HIGH>; 192 | interrupt-parent = <&plic0>; 193 | }; 194 | 195 | uart3: serial@04170000 { 196 | interrupts = <47 IRQ_TYPE_LEVEL_HIGH>; 197 | interrupt-parent = <&plic0>; 198 | }; 199 | 200 | uart4: serial@041C0000 { 201 | interrupts = <48 IRQ_TYPE_LEVEL_HIGH>; 202 | interrupt-parent = <&plic0>; 203 | }; 204 | 205 | gpio0: gpio@03020000 { 206 | porta: gpio-controller@0 { 207 | interrupt-controller; 208 | interrupts = <60 IRQ_TYPE_LEVEL_HIGH>; 209 | interrupt-parent = <&plic0>; 210 | }; 211 | }; 212 | 213 | gpio1: gpio@03021000 { 214 | portb: gpio-controller@1 { 215 | interrupt-controller; 216 | interrupts = <61 IRQ_TYPE_LEVEL_HIGH>; 217 | interrupt-parent = <&plic0>; 218 | }; 219 | }; 220 | 221 | gpio2: gpio@03022000 { 222 | portc: gpio-controller@2 { 223 | interrupt-controller; 224 | interrupts = <62 IRQ_TYPE_LEVEL_HIGH>; 225 | interrupt-parent = <&plic0>; 226 | }; 227 | }; 228 | 229 | gpio3: gpio@03023000 { 230 | portd: gpio-controller@3 { 231 | interrupt-controller; 232 | interrupts = <63 IRQ_TYPE_LEVEL_HIGH>; 233 | interrupt-parent = <&plic0>; 234 | }; 235 | }; 236 | 237 | gpio4: gpio@05021000 { 238 | porte: gpio-controller@4 { 239 | interrupt-controller; 240 | interrupts = <70 IRQ_TYPE_LEVEL_HIGH>; 241 | interrupt-parent = <&plic0>; 242 | }; 243 | }; 244 | 245 | i2c0: i2c@04000000 { 246 | interrupts = <49 IRQ_TYPE_LEVEL_HIGH>; 247 | interrupt-parent = <&plic0>; 248 | }; 249 | 250 | i2c1: i2c@04010000 { 251 | interrupts = <50 IRQ_TYPE_LEVEL_HIGH>; 252 | interrupt-parent = <&plic0>; 253 | }; 254 | 255 | i2c2: i2c@04020000 { 256 | interrupts = <51 IRQ_TYPE_LEVEL_HIGH>; 257 | interrupt-parent = <&plic0>; 258 | }; 259 | 260 | i2c3: i2c@04030000 { 261 | interrupts = <52 IRQ_TYPE_LEVEL_HIGH>; 262 | interrupt-parent = <&plic0>; 263 | }; 264 | 265 | i2c4: i2c@04040000 { 266 | interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; 267 | interrupt-parent = <&plic0>; 268 | }; 269 | 270 | ethernet0: ethernet@4070000 { 271 | interrupt-names = "macirq"; 272 | interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; 273 | interrupt-parent = <&plic0>; 274 | }; 275 | 276 | emmc:cv-emmc@4300000 { 277 | interrupts = <34 IRQ_TYPE_LEVEL_HIGH>; 278 | interrupt-parent = <&plic0>; 279 | }; 280 | 281 | sd:cv-sd@4310000 { 282 | interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; 283 | interrupt-parent = <&plic0>; 284 | }; 285 | 286 | i2s0: i2s@04100000 { 287 | interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; 288 | interrupt-parent = <&plic0>; 289 | }; 290 | 291 | i2s1: i2s@04110000 { 292 | interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; 293 | interrupt-parent = <&plic0>; 294 | }; 295 | 296 | i2s2: i2s@04120000 { 297 | interrupts = <42 IRQ_TYPE_LEVEL_HIGH>; 298 | interrupt-parent = <&plic0>; 299 | }; 300 | 301 | i2s3: i2s@04130000 { 302 | interrupts = <43 IRQ_TYPE_LEVEL_HIGH>; 303 | interrupt-parent = <&plic0>; 304 | }; 305 | 306 | vi { 307 | interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; 308 | interrupt-parent = <&plic0>; 309 | interrupt-names = "isp"; 310 | }; 311 | 312 | vcodec { 313 | interrupts = <22 IRQ_TYPE_LEVEL_HIGH>, 314 | <21 IRQ_TYPE_LEVEL_HIGH>, 315 | <23 IRQ_TYPE_LEVEL_HIGH>; 316 | interrupt-names = "h265","h264","sbm"; 317 | interrupt-parent = <&plic0>; 318 | }; 319 | 320 | jpu { 321 | interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; 322 | interrupt-names = "jpeg"; 323 | interrupt-parent = <&plic0>; 324 | }; 325 | 326 | rtos_cmdqu { 327 | interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; 328 | interrupt-names = "mailbox"; 329 | interrupt-parent = <&plic0>; 330 | }; 331 | 332 | wifisd:wifi-sd@4320000 { 333 | interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; 334 | interrupt-parent = <&plic0>; 335 | }; 336 | 337 | mipi_rx: cif { 338 | interrupts = <26 IRQ_TYPE_LEVEL_HIGH>, 339 | <27 IRQ_TYPE_LEVEL_HIGH>; 340 | interrupt-names = "csi0", "csi1"; 341 | interrupt-parent = <&plic0>; 342 | }; 343 | 344 | ive { 345 | interrupt-names = "ive_irq"; 346 | interrupt-parent = <&plic0>; 347 | interrupts = <97 IRQ_TYPE_LEVEL_HIGH>; 348 | }; 349 | 350 | vpss { 351 | interrupts = <25 IRQ_TYPE_LEVEL_HIGH>; 352 | interrupt-names = "sc"; 353 | interrupt-parent = <&plic0>; 354 | }; 355 | 356 | dwa { 357 | interrupts = <28 IRQ_TYPE_LEVEL_HIGH>; 358 | interrupt-names = "dwa"; 359 | interrupt-parent = <&plic0>; 360 | }; 361 | 362 | usb: usb@04340000 { 363 | interrupts = <30 IRQ_TYPE_LEVEL_HIGH>; 364 | interrupt-parent = <&plic0>; 365 | }; 366 | 367 | thermal:thermal@030E0000 { 368 | interrupts = <16 IRQ_TYPE_LEVEL_HIGH>; 369 | interrupt-names = "tempsen"; 370 | interrupt-parent = <&plic0>; 371 | }; 372 | 373 | }; 374 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x/sg200x_asic_bga.dtsi: -------------------------------------------------------------------------------- 1 | &dac{ 2 | mute-gpio-l = <&porta 15 GPIO_ACTIVE_LOW>; 3 | mute-gpio-r = <&porta 30 GPIO_ACTIVE_LOW>; 4 | }; 5 | 6 | &spi0 { 7 | status = "disabled"; 8 | num-cs = <1>; 9 | spidev@0 { 10 | compatible = "rohm,dh2228fv"; 11 | spi-max-frequency = <1000000>; 12 | reg = <0>; 13 | }; 14 | }; 15 | 16 | &spi1 { 17 | status = "disabled"; 18 | num-cs = <1>; 19 | spidev@0 { 20 | compatible = "rohm,dh2228fv"; 21 | spi-max-frequency = <1000000>; 22 | reg = <0>; 23 | }; 24 | }; 25 | 26 | &spi2 { 27 | status = "disabled"; 28 | num-cs = <1>; 29 | spidev@0 { 30 | compatible = "rohm,dh2228fv"; 31 | spi-max-frequency = <1000000>; 32 | reg = <0>; 33 | }; 34 | }; 35 | 36 | &spi3 { 37 | status = "okay"; 38 | num-cs = <1>; 39 | spidev@0 { 40 | compatible = "rohm,dh2228fv"; 41 | spi-max-frequency = <1000000>; 42 | reg = <0>; 43 | }; 44 | }; 45 | 46 | &i2c1 { 47 | status = "disabled"; 48 | }; 49 | 50 | / { 51 | /delete-node/ i2s@04110000; 52 | /delete-node/ i2s@04120000; 53 | /delete-node/ sound_ext1; 54 | /delete-node/ sound_ext2; 55 | /delete-node/ sound_PDM; 56 | }; 57 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x/sg200x_asic_emmc.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cvi-spif@10000000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x/sg200x_asic_qfn.dtsi: -------------------------------------------------------------------------------- 1 | &sd { 2 | no-1-8-v; 3 | }; 4 | 5 | &mipi_rx{ 6 | snsr-reset = <&portc 13 GPIO_ACTIVE_LOW>, <&portc 13 GPIO_ACTIVE_LOW>, <&portc 13 GPIO_ACTIVE_LOW>; 7 | }; 8 | 9 | &mipi_tx { 10 | reset-gpio = <&porta 15 GPIO_ACTIVE_LOW>; 11 | pwm-gpio = <&porta 18 GPIO_ACTIVE_HIGH>; 12 | power-ct-gpio = <&porta 19 GPIO_ACTIVE_HIGH>; 13 | }; 14 | 15 | &dac{ 16 | mute-gpio-r = <&porte 1 GPIO_ACTIVE_LOW>; 17 | }; 18 | 19 | &spi0 { 20 | status = "disabled"; 21 | num-cs = <1>; 22 | spidev@0 { 23 | compatible = "rohm,dh2228fv"; 24 | spi-max-frequency = <1000000>; 25 | reg = <0>; 26 | }; 27 | }; 28 | 29 | &spi1 { 30 | status = "disabled"; 31 | num-cs = <1>; 32 | spidev@0 { 33 | compatible = "rohm,dh2228fv"; 34 | spi-max-frequency = <1000000>; 35 | reg = <0>; 36 | }; 37 | }; 38 | 39 | &spi2 { 40 | status = "disabled"; 41 | num-cs = <1>; 42 | spidev@0 { 43 | compatible = "rohm,dh2228fv"; 44 | spi-max-frequency = <1000000>; 45 | reg = <0>; 46 | }; 47 | }; 48 | 49 | &spi3 { 50 | status = "okay"; 51 | num-cs = <1>; 52 | spidev@0 { 53 | compatible = "rohm,dh2228fv"; 54 | spi-max-frequency = <1000000>; 55 | reg = <0>; 56 | }; 57 | }; 58 | 59 | &i2c0 { 60 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 61 | scl-pinmux = <0x03001070 0x0 0x3>; // IIC0_SCL/IIC0_SCL/XGPIOA[28] 62 | sda-pinmux = <0x03001074 0x0 0x3>; // IIC0_SDA/IIC0_SDA/XGPIOA[29] 63 | /* gpio port */ 64 | scl-gpios = <&porta 28 GPIO_ACTIVE_HIGH>; 65 | sda-gpios = <&porta 29 GPIO_ACTIVE_HIGH>; 66 | }; 67 | 68 | &i2c1 { 69 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 70 | scl-pinmux = <0x03009408 0x2 0x3>; // SPI1_MOSI/IIC1_SCL/XGPIOB[7] 71 | sda-pinmux = <0x0300940c 0x2 0x3>; // SPI1_MISO/IIC1_SDA/XGPIOB[8] 72 | /* gpio port */ 73 | scl-gpios = <&portb 7 GPIO_ACTIVE_HIGH>; 74 | sda-gpios = <&portb 8 GPIO_ACTIVE_HIGH>; 75 | }; 76 | 77 | &i2c2 { 78 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 79 | scl-pinmux = <0x030011a0 0x4 0x3>; // PAD_MIPI_TXP1/IIC2_SCL/XGPIOC[15] 80 | sda-pinmux = <0x0300119c 0x4 0x3>; // PAD_MIPI_TXM1/IIC2_SDA/XGPIOC[14] 81 | /* gpio port */ 82 | scl-gpios = <&portc 15 GPIO_ACTIVE_HIGH>; 83 | sda-gpios = <&portc 14 GPIO_ACTIVE_HIGH>; 84 | }; 85 | 86 | &i2c3 { 87 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 88 | scl-pinmux = <0x03001014 0x0 0x3>; // IIC3_SCL/IIC3_SCL/XGPIOA[5] 89 | sda-pinmux = <0x03001018 0x0 0x3>; // IIC3_SDA/IIC3_SDA/XGPIOA[6] 90 | /* gpio port */ 91 | scl-gpios = <&porta 5 GPIO_ACTIVE_HIGH>; 92 | sda-gpios = <&porta 6 GPIO_ACTIVE_HIGH>; 93 | }; 94 | 95 | &i2c4 { 96 | /* FMUX_GPIO_REG iic_func_sel gpio_func_sel */ 97 | scl-pinmux = <0x030010f0 0x2 0x3>; // ADC3/IIC4_SCL/XGPIOB[1] 98 | sda-pinmux = <0x030010f4 0x2 0x3>; // ADC2/IIC4_SDA/XGPIOB[2] 99 | /* gpio port */ 100 | scl-gpios = <&portb 1 GPIO_ACTIVE_HIGH>; 101 | sda-gpios = <&portb 2 GPIO_ACTIVE_HIGH>; 102 | }; 103 | 104 | / { 105 | /delete-node/ wifi-sd@4320000; 106 | /delete-node/ i2s@04110000; 107 | /delete-node/ i2s@04120000; 108 | /delete-node/ sound_ext1; 109 | /delete-node/ sound_ext2; 110 | /delete-node/ sound_PDM; 111 | 112 | wifi_pin { 113 | compatible = "cvitek,wifi-pin"; 114 | poweron-gpio = <&porte 2 GPIO_ACTIVE_HIGH>; 115 | wakeup-gpio = <&porte 6 GPIO_ACTIVE_HIGH>; 116 | }; 117 | 118 | }; 119 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x/sg200x_asic_sd.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cv-emmc@4300000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x/sg200x_asic_spinand.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cvi-spif@10000000; 3 | /delete-node/ cv-emmc@4300000; 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x/sg200x_asic_spinor.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | /delete-node/ cv-emmc@4300000; 3 | /delete-node/ cv-spinf@4060000; 4 | }; 5 | 6 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x/sg200x_default_memmap.dtsi: -------------------------------------------------------------------------------- 1 | / { 2 | memory@80000000 { 3 | device_type = "memory"; 4 | reg = <0x00 CVIMMAP_KERNEL_MEMORY_ADDR 0x00 CVIMMAP_KERNEL_MEMORY_SIZE>; 5 | }; 6 | 7 | 8 | reserved-memory { 9 | #size-cells = <0x2>; 10 | #address-cells = <0x2>; 11 | ranges; 12 | 13 | fast_image: rproc { 14 | reg = <0x0 CVIMMAP_FREERTOS_ADDR 0x0 CVIMMAP_FREERTOS_SIZE>; 15 | no-map; 16 | }; 17 | 18 | vdev0vring0: vdev0vring0 { 19 | compatible = "shared-dma-pool"; 20 | alloc-ranges = <0x0 0x8f528000 0 0x4000>; 21 | size = <0x0 0x4000>; 22 | no-map; 23 | }; 24 | 25 | vdev0vring1: vdev0vring1 { 26 | compatible = "shared-dma-pool"; 27 | alloc-ranges = <0x0 0x8f52C000 0 0x4000>; 28 | size = <0x0 0x4000>; 29 | no-map; 30 | }; 31 | 32 | vdev0buffer: vdev0buffer { 33 | compatible = "shared-dma-pool"; 34 | alloc-ranges = <0x0 0x8f530000 0 0x100000>; 35 | size = <0x0 0x100000>; 36 | no-map; 37 | }; 38 | #if (CVIMMAP_ION_SIZE > 0) 39 | ion_reserved: ion { 40 | compatible = "ion-region"; 41 | size = <0x0 CVIMMAP_ION_SIZE>; 42 | }; 43 | #endif 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x_arm/sg200x_base_arm.dtsi: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "cvi_board_memmap.h" 8 | 9 | /memreserve/ CVIMMAP_MONITOR_ADDR CVIMMAP_ATF_SIZE; // ATF (BL31 + BL32) 512KB 10 | 11 | #include "soph_base.dtsi" 12 | 13 | / { 14 | model = "SOPHGO ASIC. ARM."; 15 | interrupt-parent = <&gic>; 16 | 17 | #size-cells = <0x2>; 18 | #address-cells = <0x2>; 19 | 20 | gic: interrupt-controller { 21 | compatible = "arm,cortex-a15-gic"; 22 | ranges; 23 | #size-cells = <0x2>; 24 | #address-cells = <0x2>; 25 | interrupt-controller; 26 | #interrupt-cells = <0x3>; 27 | reg = <0x0 0x01F01000 0x0 0x1000>, 28 | <0x0 0x01F02000 0x0 0x2000>; 29 | }; 30 | 31 | pmu_a53 { 32 | compatible = "arm,cortex-a53-pmu"; 33 | interrupts = , 34 | ; 35 | interrupt-affinity = <&A53_0>; 36 | }; 37 | 38 | psci { 39 | migrate = <0xc4000005>; 40 | cpu_on = <0xc4000003>; 41 | cpu_off = <0x84000002>; 42 | cpu_suspend = <0xc4000001>; 43 | sys_poweroff = <0x84000008>; 44 | sys_reset = <0x84000009>; 45 | method = "smc"; 46 | compatible = "arm,psci-0.2", "arm,psci"; 47 | }; 48 | 49 | cpus { 50 | #size-cells = <0x0>; 51 | #address-cells = <0x1>; 52 | 53 | A53_0: cpu@0 { 54 | reg = <0x0>; 55 | enable-method = "psci"; 56 | compatible = "arm,cortex-a53"; 57 | device_type = "cpu"; 58 | next-level-cache = <&CA53_L2>; 59 | }; 60 | 61 | CA53_L2: l2-cache0 { 62 | compatible = "cache"; 63 | }; 64 | }; 65 | 66 | timer { 67 | interrupts = , 68 | , 69 | , 70 | ; 71 | always-on; 72 | clock-frequency = <25000000>; 73 | compatible = "arm,armv8-timer"; 74 | }; 75 | 76 | firmware { 77 | optee { 78 | compatible = "linaro,optee-tz"; 79 | method = "smc"; 80 | }; 81 | }; 82 | 83 | cooling:cooling { 84 | clocks = <&clk CV181X_CLK_A53>, <&clk CV181X_CLK_TPU>; 85 | clock-names = "clk_cpu", "clk_tpu_axi"; 86 | dev-freqs = <800000000 500000000>, 87 | <400000000 375000000>, 88 | <400000000 300000000>; 89 | compatible = "sophgo,cooling"; 90 | #cooling-cells = <2>; 91 | }; 92 | 93 | tpu { 94 | interrupts = , 95 | ; 96 | }; 97 | 98 | mon { 99 | interrupts = ; 100 | }; 101 | 102 | wiegand0 { 103 | interrupts = ; 104 | }; 105 | 106 | wiegand1 { 107 | interrupts = ; 108 | }; 109 | 110 | wiegand2 { 111 | interrupts = ; 112 | }; 113 | 114 | saradc { 115 | interrupts = ; 116 | }; 117 | 118 | rtc { 119 | interrupts = ; 120 | }; 121 | 122 | sysdma_remap { 123 | int_mux = <0x1FF>; /* enable bit [0..8] for CPU0(CA53) */ 124 | }; 125 | 126 | dmac: dma@0x4330000 { 127 | interrupts = ; 128 | }; 129 | 130 | #if 0 131 | watchdog0: cv-wd@0x3010000 { 132 | interrupts = ; 133 | }; 134 | #endif 135 | 136 | spinand:cv-spinf@4060000 { 137 | interrupts = ; 138 | }; 139 | 140 | spif:cvi-spif@10000000 { 141 | interrupts = ; 142 | }; 143 | 144 | spi0:spi0@04180000 { 145 | interrupts = ; 146 | }; 147 | 148 | spi1:spi1@04190000 { 149 | interrupts = ; 150 | }; 151 | 152 | spi2:spi2@041A0000 { 153 | interrupts = ; 154 | }; 155 | 156 | spi3:spi3@041B0000 { 157 | interrupts = ; 158 | }; 159 | 160 | uart0: serial@04140000 { 161 | interrupts = ; 162 | }; 163 | 164 | uart1: serial@04150000 { 165 | interrupts = ; 166 | }; 167 | 168 | uart2: serial@04160000 { 169 | interrupts = ; 170 | }; 171 | 172 | uart3: serial@04170000 { 173 | interrupts = ; 174 | }; 175 | 176 | uart4: serial@041C0000 { 177 | interrupts = ; 178 | }; 179 | 180 | gpio0: gpio@03020000 { 181 | porta: gpio-controller@0 { 182 | interrupt-controller; 183 | interrupts = ; 184 | }; 185 | }; 186 | 187 | gpio1: gpio@03021000 { 188 | portb: gpio-controller@1 { 189 | interrupt-controller; 190 | interrupts = ; 191 | }; 192 | }; 193 | 194 | gpio2: gpio@03022000 { 195 | portc: gpio-controller@2 { 196 | interrupt-controller; 197 | interrupts = ; 198 | }; 199 | }; 200 | 201 | gpio3: gpio@03023000 { 202 | portd: gpio-controller@3 { 203 | interrupt-controller; 204 | interrupts = ; 205 | }; 206 | }; 207 | 208 | gpio4: gpio@05021000 { 209 | porte: gpio-controller@4 { 210 | interrupt-controller; 211 | interrupts = ; 212 | }; 213 | }; 214 | 215 | i2c0: i2c@04000000 { 216 | interrupts = ; 217 | }; 218 | 219 | i2c1: i2c@04010000 { 220 | interrupts = ; 221 | }; 222 | 223 | i2c2: i2c@04020000 { 224 | interrupts = ; 225 | }; 226 | 227 | i2c3: i2c@04030000 { 228 | interrupts = ; 229 | }; 230 | 231 | i2c4: i2c@04040000 { 232 | interrupts = ; 233 | }; 234 | 235 | ethernet0: ethernet@4070000 { 236 | interrupt-names = "macirq"; 237 | interrupts = ; 238 | }; 239 | 240 | emmc:cv-emmc@4300000 { 241 | interrupts = ; 242 | }; 243 | 244 | sd:cv-sd@4310000 { 245 | interrupts = ; 246 | }; 247 | 248 | i2s0: i2s@04100000 { 249 | interrupts = ; 250 | }; 251 | 252 | i2s1: i2s@04110000 { 253 | interrupts = ; 254 | }; 255 | 256 | i2s2: i2s@04120000 { 257 | interrupts = ; 258 | }; 259 | 260 | i2s3: i2s@04130000 { 261 | interrupts = ; 262 | }; 263 | 264 | wifisd:wifi-sd@4320000 { 265 | interrupts = ; 266 | }; 267 | 268 | mipi_rx: cif { 269 | interrupts = , 270 | ; 271 | interrupt-names = "csi0", "csi1"; 272 | }; 273 | 274 | vi { 275 | interrupts = ; 276 | interrupt-names = "isp"; 277 | }; 278 | 279 | ive { 280 | interrupt-names = "ive_irq"; 281 | interrupts = ; 282 | }; 283 | 284 | vpss { 285 | interrupts = ; 286 | interrupt-names = "sc"; 287 | }; 288 | 289 | dwa { 290 | interrupts = ; 291 | interrupt-names = "dwa"; 292 | }; 293 | 294 | vcodec { 295 | interrupts = , 296 | , 297 | ; 298 | interrupt-names = "h265","h264","sbm"; 299 | }; 300 | 301 | jpu { 302 | interrupts = ; 303 | interrupt-names = "jpeg"; 304 | }; 305 | 306 | rtos_cmdqu { 307 | interrupts = ; 308 | interrupt-names = "mailbox"; 309 | }; 310 | 311 | usb: usb@04340000 { 312 | interrupts = ; 313 | }; 314 | 315 | thermal:thermal@030E0000 { 316 | interrupts = ; 317 | interrupt-names = "tempsen"; 318 | }; 319 | 320 | }; 321 | -------------------------------------------------------------------------------- /configs/common/dts/sg200x_riscv/sg200x_base_riscv.dtsi: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "cvi_board_memmap.h" 8 | 9 | /* 10 | * OpenSBI will add below subnode into reserved memory automatically 11 | * mmode_resv0@80000000 { 12 | * reg = <0x00 0x80000000 0x00 0x20000>; 13 | * phandle = <0x0d>; 14 | * }; 15 | * Skip below to avoid lmb region reseved conflict in uboot. 16 | * 17 | */ 18 | #ifndef __UBOOT__ 19 | /memreserve/ CVIMMAP_MONITOR_ADDR CVIMMAP_OPENSBI_SIZE; // OpenSBI 20 | #endif 21 | 22 | #include "sg200x_base.dtsi" 23 | 24 | / { 25 | model = "SOPHGO ASIC. C906."; 26 | 27 | #size-cells = <0x2>; 28 | #address-cells = <0x2>; 29 | 30 | cpus { 31 | #address-cells = <0x01>; 32 | #size-cells = <0x00>; 33 | timebase-frequency = <25000000>; 34 | 35 | cpu-map { 36 | 37 | cluster0 { 38 | 39 | core0 { 40 | cpu = <0x01>; 41 | }; 42 | }; 43 | }; 44 | 45 | cpu@0 { 46 | device_type = "cpu"; 47 | reg = <0x00>; 48 | status = "okay"; 49 | compatible = "riscv"; 50 | riscv,isa = "rv64imafdvcsu"; 51 | mmu-type = "riscv,sv39"; 52 | clock-frequency = <25000000>; 53 | 54 | cpu0_intc: interrupt-controller { 55 | #interrupt-cells = <0x01>; 56 | interrupt-controller; 57 | compatible = "riscv,cpu-intc"; 58 | }; 59 | }; 60 | }; 61 | 62 | soc { 63 | #address-cells = <0x02>; 64 | #size-cells = <0x02>; 65 | compatible = "simple-bus"; 66 | ranges; 67 | 68 | plic0: interrupt-controller@70000000 { 69 | riscv,ndev = <101>; 70 | riscv,max-priority = <0x07>; 71 | reg-names = "control"; 72 | reg = <0x00 0x70000000 0x00 0x4000000>; 73 | interrupts-extended = <&cpu0_intc 0xffffffff &cpu0_intc 0x09>; 74 | interrupt-controller; 75 | compatible = "riscv,plic0"; 76 | #interrupt-cells = <0x02>; 77 | #address-cells = <0x00>; 78 | }; 79 | 80 | clint@74000000 { 81 | interrupts-extended = <&cpu0_intc 0x03 &cpu0_intc 0x07>; 82 | reg = <0x00 0x74000000 0x00 0x10000>; 83 | compatible = "riscv,clint0"; 84 | clint,has-no-64bit-mmio; 85 | }; 86 | 87 | }; 88 | 89 | cooling:cooling { 90 | clocks = <&clk CV181X_CLK_C906_0>, <&clk CV181X_CLK_TPU>; 91 | clock-names = "clk_cpu", "clk_tpu_axi"; 92 | dev-freqs = <850000000 500000000>, 93 | <425000000 375000000>, 94 | <425000000 300000000>; 95 | compatible = "sophgo,cooling"; 96 | #cooling-cells = <2>; 97 | }; 98 | 99 | tpu { 100 | interrupts = <75 IRQ_TYPE_LEVEL_HIGH>, 101 | <76 IRQ_TYPE_LEVEL_HIGH>; 102 | interrupt-names = "tiu_irq", "tdma_irq"; 103 | interrupt-parent = <&plic0>; 104 | }; 105 | 106 | mon { 107 | interrupts = <93 IRQ_TYPE_LEVEL_HIGH>; 108 | interrupt-names = "mon_irq"; 109 | interrupt-parent = <&plic0>; 110 | }; 111 | 112 | wiegand0 { 113 | interrupts = <64 IRQ_TYPE_LEVEL_HIGH>; 114 | interrupt-parent = <&plic0>; 115 | }; 116 | 117 | wiegand1 { 118 | interrupts = <65 IRQ_TYPE_LEVEL_HIGH>; 119 | interrupt-parent = <&plic0>; 120 | }; 121 | 122 | wiegand2 { 123 | interrupts = <66 IRQ_TYPE_LEVEL_HIGH>; 124 | interrupt-parent = <&plic0>; 125 | }; 126 | 127 | saradc { 128 | interrupts = <100 IRQ_TYPE_EDGE_RISING>; 129 | interrupt-parent = <&plic0>; 130 | }; 131 | 132 | rtc { 133 | interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; 134 | interrupt-parent = <&plic0>; 135 | }; 136 | 137 | sysdma_remap { 138 | int_mux = <0x7FC00>; /* enable bit [10..18] for CPU1(906B) */ 139 | }; 140 | 141 | dmac: dma@0x4330000 { 142 | interrupts = <29 IRQ_TYPE_LEVEL_HIGH>; 143 | interrupt-parent = <&plic0>; 144 | }; 145 | 146 | watchdog0: cv-wd@0x3010000 { 147 | interrupts = <58 IRQ_TYPE_LEVEL_HIGH>; 148 | }; 149 | 150 | spinand:cv-spinf@4060000 { 151 | interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; 152 | interrupt-parent = <&plic0>; 153 | }; 154 | 155 | spif:cvi-spif@10000000 { 156 | interrupts = <95 IRQ_TYPE_LEVEL_HIGH>; 157 | interrupt-parent = <&plic0>; 158 | }; 159 | 160 | spi0:spi0@04180000 { 161 | interrupts = <54 IRQ_TYPE_LEVEL_HIGH>; 162 | interrupt-parent = <&plic0>; 163 | }; 164 | 165 | spi1:spi1@04190000 { 166 | interrupts = <55 IRQ_TYPE_LEVEL_HIGH>; 167 | interrupt-parent = <&plic0>; 168 | }; 169 | 170 | spi2:spi2@041A0000 { 171 | interrupts = <56 IRQ_TYPE_LEVEL_HIGH>; 172 | interrupt-parent = <&plic0>; 173 | }; 174 | 175 | spi3:spi3@041B0000 { 176 | interrupts = <57 IRQ_TYPE_LEVEL_HIGH>; 177 | interrupt-parent = <&plic0>; 178 | }; 179 | 180 | uart0: serial@04140000 { 181 | interrupts = <44 IRQ_TYPE_LEVEL_HIGH>; 182 | interrupt-parent = <&plic0>; 183 | }; 184 | 185 | uart1: serial@04150000 { 186 | interrupts = <45 IRQ_TYPE_LEVEL_HIGH>; 187 | interrupt-parent = <&plic0>; 188 | }; 189 | 190 | uart2: serial@04160000 { 191 | interrupts = <46 IRQ_TYPE_LEVEL_HIGH>; 192 | interrupt-parent = <&plic0>; 193 | }; 194 | 195 | uart3: serial@04170000 { 196 | interrupts = <47 IRQ_TYPE_LEVEL_HIGH>; 197 | interrupt-parent = <&plic0>; 198 | }; 199 | 200 | uart4: serial@041C0000 { 201 | interrupts = <48 IRQ_TYPE_LEVEL_HIGH>; 202 | interrupt-parent = <&plic0>; 203 | }; 204 | 205 | gpio0: gpio@03020000 { 206 | porta: gpio-controller@0 { 207 | interrupt-controller; 208 | interrupts = <60 IRQ_TYPE_LEVEL_HIGH>; 209 | interrupt-parent = <&plic0>; 210 | #interrupt-cells = <3>; 211 | }; 212 | }; 213 | 214 | gpio1: gpio@03021000 { 215 | portb: gpio-controller@1 { 216 | interrupt-controller; 217 | interrupts = <61 IRQ_TYPE_LEVEL_HIGH>; 218 | interrupt-parent = <&plic0>; 219 | #interrupt-cells = <3>; 220 | }; 221 | }; 222 | 223 | gpio2: gpio@03022000 { 224 | portc: gpio-controller@2 { 225 | interrupt-controller; 226 | interrupts = <62 IRQ_TYPE_LEVEL_HIGH>; 227 | interrupt-parent = <&plic0>; 228 | #interrupt-cells = <3>; 229 | }; 230 | }; 231 | 232 | gpio3: gpio@03023000 { 233 | portd: gpio-controller@3 { 234 | interrupt-controller; 235 | interrupts = <63 IRQ_TYPE_LEVEL_HIGH>; 236 | interrupt-parent = <&plic0>; 237 | #interrupt-cells = <3>; 238 | }; 239 | }; 240 | 241 | gpio4: gpio@05021000 { 242 | porte: gpio-controller@4 { 243 | interrupt-controller; 244 | interrupts = <70 IRQ_TYPE_LEVEL_HIGH>; 245 | interrupt-parent = <&plic0>; 246 | #interrupt-cells = <3>; 247 | }; 248 | }; 249 | 250 | i2c0: i2c@04000000 { 251 | interrupts = <49 IRQ_TYPE_LEVEL_HIGH>; 252 | interrupt-parent = <&plic0>; 253 | }; 254 | 255 | i2c1: i2c@04010000 { 256 | interrupts = <50 IRQ_TYPE_LEVEL_HIGH>; 257 | interrupt-parent = <&plic0>; 258 | }; 259 | 260 | i2c2: i2c@04020000 { 261 | interrupts = <51 IRQ_TYPE_LEVEL_HIGH>; 262 | interrupt-parent = <&plic0>; 263 | }; 264 | 265 | i2c3: i2c@04030000 { 266 | interrupts = <52 IRQ_TYPE_LEVEL_HIGH>; 267 | interrupt-parent = <&plic0>; 268 | }; 269 | 270 | i2c4: i2c@04040000 { 271 | interrupts = <53 IRQ_TYPE_LEVEL_HIGH>; 272 | interrupt-parent = <&plic0>; 273 | }; 274 | 275 | ethernet0: ethernet@4070000 { 276 | interrupt-names = "macirq"; 277 | interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; 278 | interrupt-parent = <&plic0>; 279 | }; 280 | 281 | emmc:cv-emmc@4300000 { 282 | interrupts = <34 IRQ_TYPE_LEVEL_HIGH>; 283 | interrupt-parent = <&plic0>; 284 | }; 285 | 286 | sd:cv-sd@4310000 { 287 | interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; 288 | interrupt-parent = <&plic0>; 289 | }; 290 | 291 | i2s0: i2s@04100000 { 292 | interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; 293 | interrupt-parent = <&plic0>; 294 | }; 295 | 296 | i2s1: i2s@04110000 { 297 | interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; 298 | interrupt-parent = <&plic0>; 299 | }; 300 | 301 | i2s2: i2s@04120000 { 302 | interrupts = <42 IRQ_TYPE_LEVEL_HIGH>; 303 | interrupt-parent = <&plic0>; 304 | }; 305 | 306 | i2s3: i2s@04130000 { 307 | interrupts = <43 IRQ_TYPE_LEVEL_HIGH>; 308 | interrupt-parent = <&plic0>; 309 | }; 310 | 311 | vi { 312 | interrupts = <24 IRQ_TYPE_LEVEL_HIGH>; 313 | interrupt-parent = <&plic0>; 314 | interrupt-names = "isp"; 315 | }; 316 | 317 | vcodec { 318 | interrupts = <22 IRQ_TYPE_LEVEL_HIGH>, 319 | <21 IRQ_TYPE_LEVEL_HIGH>, 320 | <23 IRQ_TYPE_LEVEL_HIGH>; 321 | interrupt-names = "h265","h264","sbm"; 322 | interrupt-parent = <&plic0>; 323 | }; 324 | 325 | jpu { 326 | interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; 327 | interrupt-names = "jpeg"; 328 | interrupt-parent = <&plic0>; 329 | }; 330 | 331 | rtos_cmdqu { 332 | interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; 333 | interrupt-names = "mailbox"; 334 | interrupt-parent = <&plic0>; 335 | }; 336 | 337 | wifisd:wifi-sd@4320000 { 338 | interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; 339 | interrupt-parent = <&plic0>; 340 | }; 341 | 342 | mipi_rx: cif { 343 | interrupts = <26 IRQ_TYPE_LEVEL_HIGH>, 344 | <27 IRQ_TYPE_LEVEL_HIGH>; 345 | interrupt-names = "csi0", "csi1"; 346 | interrupt-parent = <&plic0>; 347 | }; 348 | 349 | ive { 350 | interrupt-names = "ive_irq"; 351 | interrupt-parent = <&plic0>; 352 | interrupts = <97 IRQ_TYPE_LEVEL_HIGH>; 353 | }; 354 | 355 | vpss { 356 | interrupts = <25 IRQ_TYPE_LEVEL_HIGH>; 357 | interrupt-names = "sc"; 358 | interrupt-parent = <&plic0>; 359 | }; 360 | 361 | dwa { 362 | interrupts = <28 IRQ_TYPE_LEVEL_HIGH>; 363 | interrupt-names = "dwa"; 364 | interrupt-parent = <&plic0>; 365 | }; 366 | 367 | usb: usb@04340000 { 368 | interrupts = <30 IRQ_TYPE_LEVEL_HIGH>; 369 | interrupt-parent = <&plic0>; 370 | }; 371 | 372 | thermal:thermal@030E0000 { 373 | interrupts = <16 IRQ_TYPE_LEVEL_HIGH>; 374 | interrupt-names = "tempsen"; 375 | interrupt-parent = <&plic0>; 376 | }; 377 | 378 | }; 379 | -------------------------------------------------------------------------------- /configs/common/patches/fsbl/0001-fix-compile-error.patch: -------------------------------------------------------------------------------- 1 | diff --git a/plat/cv180x/bl2/bl2_main.c b/plat/cv180x/bl2/bl2_main.c 2 | index e1eee38..f989e09 100644 3 | --- a/plat/cv180x/bl2/bl2_main.c 4 | +++ b/plat/cv180x/bl2/bl2_main.c 5 | @@ -25,8 +25,8 @@ int init_comm_info(int ret) 6 | transfer_config_s.encode_buf_size = CVIMMAP_H26X_ENC_BUFF_SIZE; 7 | transfer_config_s.dump_print_enable = RTOS_DUMP_PRINT_ENABLE; 8 | transfer_config_s.dump_print_size_idx = RTOS_DUMP_PRINT_SZ_IDX; 9 | - transfer_config_s.image_type = RTOS_FAST_IMAGE_TYPE; 10 | - transfer_config_s.mcu_status = MCU_STATUS_NONOS_DONE; 11 | +// transfer_config_s.image_type = RTOS_FAST_IMAGE_TYPE; 12 | +// transfer_config_s.mcu_status = MCU_STATUS_NONOS_DONE; 13 | for (int i = 0; i < transfer_config_s.conf_size; i++) { 14 | checksum += ptr[i]; 15 | } 16 | diff --git a/plat/cv181x/bl2/bl2_main.c b/plat/cv181x/bl2/bl2_main.c 17 | index 09b117b..b0185d9 100644 18 | --- a/plat/cv181x/bl2/bl2_main.c 19 | +++ b/plat/cv181x/bl2/bl2_main.c 20 | @@ -10,6 +10,7 @@ enum CHIP_CLK_MODE chip_clk_mode = CLK_ND; 21 | #ifdef RTOS_ENABLE_FREERTOS 22 | int init_comm_info(int ret) 23 | { 24 | +#if 0 25 | struct transfer_config_t *transfer_config = (struct transfer_config_t *)MAILBOX_FIELD; 26 | struct transfer_config_t transfer_config_s; 27 | unsigned char *ptr = (unsigned char *)&transfer_config_s; 28 | @@ -35,7 +36,7 @@ int init_comm_info(int ret) 29 | 30 | transfer_config_s.checksum = checksum; 31 | memcpy(transfer_config, &transfer_config_s, sizeof(struct transfer_config_t)); 32 | - 33 | +#endif 34 | return ret; 35 | } 36 | #endif 37 | -------------------------------------------------------------------------------- /configs/common/patches/linux/0002-Add-Reset-for-C906L-ignore-clock-status-for-C906L-an.patch: -------------------------------------------------------------------------------- 1 | From e1df28259ed82f46dc9059eae86bc26a3b4a2c4d Mon Sep 17 00:00:00 2001 2 | From: Justin Hammond 3 | Date: Sat, 6 Apr 2024 14:29:47 +0800 4 | Subject: [PATCH 2/4] Add Reset for C906L, ignore clock status for C906L, and 5 | Fix up reserved memory name size (in preperation for remoteproc driver) 6 | 7 | --- 8 | drivers/clk/cvitek/clk-cv181x.c | 2 +- 9 | drivers/of/of_reserved_mem.c | 4 ++-- 10 | include/dt-bindings/reset/cv181x-resets.h | 3 +++ 11 | include/linux/of_reserved_mem.h | 2 +- 12 | 4 files changed, 7 insertions(+), 4 deletions(-) 13 | 14 | diff --git a/drivers/clk/cvitek/clk-cv181x.c b/drivers/clk/cvitek/clk-cv181x.c 15 | index 561fb1fcb832..3afce30df616 100644 16 | --- a/drivers/clk/cvitek/clk-cv181x.c 17 | +++ b/drivers/clk/cvitek/clk-cv181x.c 18 | @@ -1645,7 +1645,7 @@ static struct cv181x_hw_clock cv181x_clks[] = { 19 | REG_CLK_BYP_1, 7, 20 | REG_CLK_SEL_0, 24, 21 | REG_DIV_CLK_C906_1_0, 8, 22 | - CLK_IS_CRITICAL), 23 | + CLK_IGNORE_UNUSED), 24 | CV181X_CLK(CV181X_CLK_SRC_VIP_SYS_3, "clk_src_vip_sys_3", 25 | ((const char *[]) {"osc", "clk_mipimpll", "clk_cam0pll", "clk_disppll", "clk_fpll"}), 26 | REG_CLK_EN_4, 15, 27 | diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c 28 | index 8093bbbe875c..1336c2d23bd6 100644 29 | --- a/drivers/of/of_reserved_mem.c 30 | +++ b/drivers/of/of_reserved_mem.c 31 | @@ -22,7 +22,7 @@ 32 | #include 33 | #include 34 | 35 | -#define MAX_RESERVED_REGIONS 4 36 | +#define MAX_RESERVED_REGIONS 64 37 | 38 | #if defined(CONFIG_ARCH_CVITEK) 39 | struct reserved_mem_size_entry { 40 | @@ -69,7 +69,7 @@ void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, 41 | } 42 | 43 | rmem->fdt_node = node; 44 | - strncpy(rmem->name, uname, 8); 45 | + strncpy(rmem->name, uname, 16); 46 | rmem->base = base; 47 | rmem->size = size; 48 | 49 | diff --git a/include/dt-bindings/reset/cv181x-resets.h b/include/dt-bindings/reset/cv181x-resets.h 50 | index e10d33b35446..c89f79418df4 100644 51 | --- a/include/dt-bindings/reset/cv181x-resets.h 52 | +++ b/include/dt-bindings/reset/cv181x-resets.h 53 | @@ -114,6 +114,9 @@ 54 | #define RST_AUTO_CLEAR_MAINRST_AP 103 55 | #define RST_AUTO_CLEAR_SECONDRST_AP 104 56 | 57 | +#define RST_C906_0 293 58 | +#define RST_C906_1 294 59 | + 60 | #define CLK_RST_A53 0 61 | #define CLK_RST_50M_A53 1 62 | #define CLK_RST_AHB_ROM 2 63 | diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h 64 | index e418313a5085..5ac862bbea7b 100644 65 | --- a/include/linux/of_reserved_mem.h 66 | +++ b/include/linux/of_reserved_mem.h 67 | @@ -9,7 +9,7 @@ struct of_phandle_args; 68 | struct reserved_mem_ops; 69 | 70 | struct reserved_mem { 71 | - char name[8]; 72 | + char name[16]; 73 | unsigned long fdt_node; 74 | unsigned long phandle; 75 | const struct reserved_mem_ops *ops; 76 | -- 77 | 2.44.0 78 | 79 | -------------------------------------------------------------------------------- /configs/common/patches/linux/0003-Add-Remoteproc-Driver-for-cvitek.patch: -------------------------------------------------------------------------------- 1 | From 172cb98bcae844f747b5ef41f05cc6073fa464b4 Mon Sep 17 00:00:00 2001 2 | From: Justin Hammond 3 | Date: Sat, 6 Apr 2024 14:30:10 +0800 4 | Subject: [PATCH 3/4] Add Remoteproc Driver for cvitek 5 | 6 | --- 7 | drivers/remoteproc/Kconfig | 10 + 8 | drivers/remoteproc/Makefile | 1 + 9 | drivers/remoteproc/cvitek_remoteproc.c | 424 +++++++++++++++++++++++++ 10 | 3 files changed, 435 insertions(+) 11 | create mode 100644 drivers/remoteproc/cvitek_remoteproc.c 12 | 13 | diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig 14 | index d99548fb5dde..0bb9fcbde9d0 100644 15 | --- a/drivers/remoteproc/Kconfig 16 | +++ b/drivers/remoteproc/Kconfig 17 | @@ -247,6 +247,16 @@ config ST_REMOTEPROC 18 | config ST_SLIM_REMOTEPROC 19 | tristate 20 | 21 | +config CVITEK_REMOTEPROC 22 | + tristate "CVITEK remoteproc support" 23 | + depends on ARCH_CVITEK 24 | + select MAILBOX 25 | + select CVITEK_MAILBOX 26 | + help 27 | + Say y here to support cvitek processors via the remote 28 | + processor framework. 29 | + This can be either built-in or a loadable module. 30 | + 31 | config STM32_RPROC 32 | tristate "STM32 remoteproc support" 33 | depends on ARCH_STM32 34 | diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile 35 | index da2ace4ec86c..047fbfa8b72d 100644 36 | --- a/drivers/remoteproc/Makefile 37 | +++ b/drivers/remoteproc/Makefile 38 | @@ -34,3 +34,4 @@ obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o 39 | obj-$(CONFIG_STM32_RPROC) += stm32_rproc.o 40 | obj-$(CONFIG_TI_K3_DSP_REMOTEPROC) += ti_k3_dsp_remoteproc.o 41 | obj-$(CONFIG_TI_K3_R5_REMOTEPROC) += ti_k3_r5_remoteproc.o 42 | +obj-$(CONFIG_CVITEK_REMOTEPROC) += cvitek_remoteproc.o 43 | diff --git a/drivers/remoteproc/cvitek_remoteproc.c b/drivers/remoteproc/cvitek_remoteproc.c 44 | new file mode 100644 45 | index 000000000000..64e0ce21d711 46 | --- /dev/null 47 | +++ b/drivers/remoteproc/cvitek_remoteproc.c 48 | @@ -0,0 +1,424 @@ 49 | +// SPDX-License-Identifier: GPL-2.0-only 50 | +/* 51 | + * ST's Remote Processor Control Driver 52 | + * 53 | + * Copyright (C) 2015 STMicroelectronics - All Rights Reserved 54 | + * 55 | + * Author: Ludovic Barre 56 | + */ 57 | + 58 | +#include 59 | +#include 60 | +#include 61 | +#include 62 | +#include 63 | +#include 64 | +#include 65 | +#include 66 | +#include 67 | +#include 68 | +#include 69 | +#include 70 | +#include 71 | +#include 72 | +#include 73 | +#include 74 | +#include 75 | + 76 | +#include "remoteproc_internal.h" 77 | + 78 | +#define CVITEK_RPROC_MAX_VRING 2 79 | + 80 | +#define MBOX_RX 0 81 | +#define MBOX_TX 1 82 | +#define MBOX_MAX 2 83 | + 84 | +struct cvitek_rproc_config {}; 85 | + 86 | +struct cvitek_rproc { 87 | + struct cvitek_rproc_config *config; 88 | + struct reset_control *sw_reset; 89 | + struct clk *clk; 90 | + struct mbox_chan *mbox_chan[MBOX_MAX]; 91 | + struct mbox_client mbox_client_vq; 92 | + struct workqueue_struct *workqueue; 93 | + struct work_struct vq_work; 94 | + uint32_t vq_msg; 95 | +}; 96 | + 97 | +static void cvitek_rproc_mbox_kick_vq(struct work_struct *work) 98 | +{ 99 | + struct cvitek_rproc *ddata = container_of(work, struct cvitek_rproc, vq_work); 100 | + struct rproc *rproc = dev_get_drvdata(ddata->mbox_client_vq.dev); 101 | + 102 | + if (ddata->vq_msg < CVITEK_RPROC_MAX_VRING) { 103 | + if (rproc_vq_interrupt(rproc, ddata->vq_msg) == IRQ_NONE) { 104 | + dev_dbg(rproc->dev.parent, "no message was found in vqid %d\n", ddata->vq_msg); 105 | + } 106 | + } 107 | + 108 | +#if 0 109 | + struct rproc *rproc = dev_get_drvdata(mbox_client->dev); 110 | + 111 | + uint32_t msg = *(uint32_t *)data; 112 | + 113 | + dev_dbg(mbox_client->dev, "mbox_callback_vq %d\n", msg); 114 | + 115 | + if (rproc_vq_interrupt(rproc, msg) == IRQ_NONE) 116 | + dev_dbg(mbox_client->dev, "no message was found in vqid %d\n", msg); 117 | +#endif 118 | +} 119 | + 120 | +static void cvitek_rproc_mbox_callback_vq(struct mbox_client *mbox_client, 121 | + void *data) 122 | +{ 123 | + struct rproc *rproc = dev_get_drvdata(mbox_client->dev); 124 | + struct cvitek_rproc *ddata = rproc->priv; 125 | + 126 | + ddata->vq_msg = *(uint32_t *)data; 127 | + 128 | + dev_dbg(mbox_client->dev, "mbox_callback_vq %d\n", ddata->vq_msg); 129 | + 130 | + queue_work(ddata->workqueue, &ddata->vq_work); 131 | + 132 | + 133 | +} 134 | + 135 | +static void cvitek_rproc_kick(struct rproc *rproc, int vqid) 136 | +{ 137 | + struct cvitek_rproc *ddata = rproc->priv; 138 | + struct device *dev = rproc->dev.parent; 139 | + int ret; 140 | + 141 | + dev_dbg(dev, "kicking Remote Processor %d", vqid); 142 | + 143 | + /* send the index of the triggered virtqueue in the mailbox payload */ 144 | + if (WARN_ON(vqid >= CVITEK_RPROC_MAX_VRING)) 145 | + return; 146 | + 147 | + ret = mbox_send_message(ddata->mbox_chan[MBOX_TX], (void *)&vqid); 148 | + if (ret < 0) 149 | + dev_err(dev, "failed to send message via mbox: %d\n", ret); 150 | +} 151 | + 152 | +static int cvitek_rproc_mem_alloc(struct rproc *rproc, 153 | + struct rproc_mem_entry *mem) 154 | +{ 155 | + struct device *dev = rproc->dev.parent; 156 | + void *va; 157 | + 158 | + dev_dbg(dev, "Allocating memory region %s: %pa+%zx\n", mem->name, 159 | + &mem->dma, mem->len); 160 | + 161 | + va = ioremap_wc(mem->dma, mem->len); 162 | + if (!va) { 163 | + dev_err(dev, "Unable to map memory region %s: %pa+%zx\n", 164 | + mem->name, &mem->dma, mem->len); 165 | + return -ENOMEM; 166 | + } 167 | + 168 | + /* Update memory entry va */ 169 | + mem->va = va; 170 | + 171 | + return 0; 172 | +} 173 | + 174 | +static int cvitek_rproc_mem_release(struct rproc *rproc, 175 | + struct rproc_mem_entry *mem) 176 | +{ 177 | + dev_dbg(rproc->dev.parent, "Releasing memory region %s: %pa+%zx\n", 178 | + mem->name, &mem->dma, mem->len); 179 | + iounmap(mem->va); 180 | + 181 | + return 0; 182 | +} 183 | + 184 | +static int cvitek_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw) 185 | +{ 186 | + struct device *dev = rproc->dev.parent; 187 | + struct device_node *np = dev->of_node; 188 | + struct rproc_mem_entry *mem; 189 | + struct reserved_mem *rmem; 190 | + struct of_phandle_iterator it; 191 | + int index = 0; 192 | + 193 | + dev_dbg(dev, "Parsing firmware\n"); 194 | + 195 | + of_phandle_iterator_init(&it, np, "memory-region", NULL, 0); 196 | + while (of_phandle_iterator_next(&it) == 0) { 197 | + dev_dbg(dev, "memory-region: %s\n", it.node->name); 198 | + rmem = of_reserved_mem_lookup(it.node); 199 | + if (!rmem) { 200 | + dev_err(dev, "unable to acquire memory-region\n"); 201 | + return -EINVAL; 202 | + } 203 | + 204 | + /* No need to map vdev buffer */ 205 | + if (strcmp(it.node->name, "vdev0buffer")) { 206 | + /* Register memory region */ 207 | + dev_dbg(dev, "Registering memory region: %pa+%llx\n", 208 | + &rmem->base, rmem->size); 209 | + mem = rproc_mem_entry_init( 210 | + dev, NULL, (dma_addr_t)rmem->base, rmem->size, 211 | + rmem->base, cvitek_rproc_mem_alloc, 212 | + cvitek_rproc_mem_release, it.node->name); 213 | + } else { 214 | + dev_dbg(dev, 215 | + "Registering reserved memory region: %pa+%llx\n", 216 | + &rmem->base, rmem->size); 217 | + /* Register reserved memory for vdev buffer allocation */ 218 | + mem = rproc_of_resm_mem_entry_init(dev, index, 219 | + rmem->size, 220 | + rmem->base, 221 | + it.node->name); 222 | + } 223 | + 224 | + if (!mem) { 225 | + dev_dbg(dev, "failed to allocate memory region\n"); 226 | + return -ENOMEM; 227 | + } 228 | + rproc_add_carveout(rproc, mem); 229 | + index++; 230 | + } 231 | + 232 | + return rproc_elf_load_rsc_table(rproc, fw); 233 | +} 234 | + 235 | +static int cvitek_rproc_start(struct rproc *rproc) 236 | +{ 237 | + struct cvitek_rproc *ddata = rproc->priv; 238 | + int err; 239 | + struct mbox_chan *chan; 240 | + 241 | + dev_dbg(&rproc->dev, "Starting\n"); 242 | + 243 | + 244 | + if (ddata->mbox_client_vq.dev) { 245 | + /* 246 | + * To control a co-processor without IPC mechanism. 247 | + * This driver can be used without mbox and rpmsg. 248 | + */ 249 | + chan = mbox_request_channel_byname(&ddata->mbox_client_vq, 250 | + "vq_rx"); 251 | + if (IS_ERR(chan)) { 252 | + dev_err(&rproc->dev, 253 | + "failed to request mbox chan vq0_rx\n"); 254 | + return PTR_ERR(chan); 255 | + } 256 | + ddata->mbox_chan[MBOX_RX] = chan; 257 | + 258 | + chan = mbox_request_channel_byname(&ddata->mbox_client_vq, 259 | + "vq_tx"); 260 | + if (IS_ERR(chan)) { 261 | + dev_err(&rproc->dev, 262 | + "failed to request mbox chan vq0_tx\n"); 263 | + return PTR_ERR(chan); 264 | + } 265 | + ddata->mbox_chan[MBOX_TX] = chan; 266 | + } 267 | + 268 | + err = clk_enable(ddata->clk); 269 | + if (err) { 270 | + dev_err(&rproc->dev, "Failed to enable clock\n"); 271 | + return err; 272 | + } 273 | + 274 | + err = reset_control_deassert(ddata->sw_reset); 275 | + if (err) { 276 | + dev_err(&rproc->dev, "Failed to deassert S/W Reset\n"); 277 | + goto sw_reset_fail; 278 | + } 279 | + 280 | + dev_info(&rproc->dev, "Started from 0x%llx\n", rproc->bootaddr); 281 | + 282 | + return 0; 283 | + 284 | +sw_reset_fail: 285 | + clk_disable(ddata->clk); 286 | + return err; 287 | +} 288 | + 289 | +static int cvitek_rproc_stop(struct rproc *rproc) 290 | +{ 291 | + struct cvitek_rproc *ddata = rproc->priv; 292 | + int sw_err = 0; 293 | + 294 | + dev_dbg(&rproc->dev, "Stopping\n"); 295 | + 296 | + sw_err = reset_control_assert(ddata->sw_reset); 297 | + if (sw_err) 298 | + dev_err(&rproc->dev, "Failed to assert S/W Reset\n"); 299 | + 300 | + clk_disable(ddata->clk); 301 | + 302 | + if (ddata->mbox_client_vq.dev) { 303 | + mbox_free_channel(ddata->mbox_chan[MBOX_RX]); 304 | + mbox_free_channel(ddata->mbox_chan[MBOX_TX]); 305 | + } 306 | + 307 | + 308 | + return sw_err; 309 | +} 310 | + 311 | +static const struct rproc_ops cvitek_rproc_ops = { 312 | + .kick = cvitek_rproc_kick, 313 | + .start = cvitek_rproc_start, 314 | + .stop = cvitek_rproc_stop, 315 | + .parse_fw = cvitek_rproc_parse_fw, 316 | + .load = rproc_elf_load_segments, 317 | + .find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table, 318 | + .sanity_check = rproc_elf_sanity_check, 319 | + .get_boot_addr = rproc_elf_get_boot_addr, 320 | +}; 321 | + 322 | +static const struct of_device_id cvitek_rproc_match[] = { 323 | + { .compatible = "cvitek,cv181x-c906_1" }, 324 | + {}, 325 | +}; 326 | + 327 | +MODULE_DEVICE_TABLE(of, cvitek_rproc_match); 328 | + 329 | +static int cvitek_rproc_parse_dt(struct platform_device *pdev) 330 | +{ 331 | + struct device *dev = &pdev->dev; 332 | + struct rproc *rproc = platform_get_drvdata(pdev); 333 | + struct cvitek_rproc *ddata = rproc->priv; 334 | + //struct device_node *np = dev->of_node; 335 | + 336 | + int ret; 337 | + 338 | + dev_dbg(dev, "Parsing device tree\n"); 339 | + 340 | + ddata->sw_reset = devm_reset_control_get_exclusive(dev, "sw_reset"); 341 | + if (IS_ERR(ddata->sw_reset)) { 342 | + dev_err(dev, "Failed to get S/W Reset\n"); 343 | + return PTR_ERR(ddata->sw_reset); 344 | + } 345 | + 346 | + ddata->clk = devm_clk_get(dev, NULL); 347 | + if (IS_ERR(ddata->clk)) { 348 | + dev_err(dev, "Failed to get clock\n"); 349 | + return PTR_ERR(ddata->clk); 350 | + } 351 | + 352 | + ret = clk_prepare(ddata->clk); 353 | + if (ret) 354 | + dev_err(dev, "failed to get clock\n"); 355 | + return ret; 356 | +} 357 | + 358 | +static int cvitek_rproc_probe(struct platform_device *pdev) 359 | +{ 360 | + struct device *dev = &pdev->dev; 361 | + const struct of_device_id *match; 362 | + struct cvitek_rproc *ddata; 363 | + struct device_node *np = dev->of_node; 364 | + struct rproc *rproc; 365 | + const char *fw_name; 366 | + int ret; 367 | + 368 | + match = of_match_device(cvitek_rproc_match, dev); 369 | + if (!match) { 370 | + dev_err(dev, "No device match found\n"); 371 | + return -ENODEV; 372 | + } 373 | + 374 | + ret = of_property_read_string(dev->of_node, "firmware", &fw_name); 375 | + if (ret) { 376 | + dev_err(dev, "No firmware filename given\n"); 377 | + return -ENODEV; 378 | + } 379 | + 380 | + rproc = rproc_alloc(dev, np->name, &cvitek_rproc_ops, fw_name, 381 | + sizeof(*ddata)); 382 | + if (!rproc) { 383 | + dev_err(dev, "failed to allocate rproc\n"); 384 | + return -ENOMEM; 385 | + } 386 | + rproc->has_iommu = false; 387 | + rproc->auto_boot = false; 388 | + 389 | + ddata = rproc->priv; 390 | + ddata->config = (struct cvitek_rproc_config *)match->data; 391 | + 392 | + platform_set_drvdata(pdev, rproc); 393 | + 394 | + ddata->workqueue = create_workqueue(dev_name(dev)); 395 | + if (!ddata->workqueue) { 396 | + dev_err(dev, "cannot create workqueue\n"); 397 | + ret = -ENOMEM; 398 | + goto free_wkq; 399 | + } 400 | + 401 | + INIT_WORK(&ddata->vq_work, cvitek_rproc_mbox_kick_vq); 402 | + 403 | + 404 | + ret = cvitek_rproc_parse_dt(pdev); 405 | + if (ret) { 406 | + dev_err(dev, "failed to parse device tree\n"); 407 | + goto free_rproc; 408 | + } 409 | + 410 | + if (of_get_property(np, "mbox-names", NULL)) { 411 | + dev_dbg(dev, "mbox-names property found\n"); 412 | + ddata->mbox_client_vq.dev = dev; 413 | + ddata->mbox_client_vq.tx_done = NULL; 414 | + ddata->mbox_client_vq.tx_block = false; 415 | + ddata->mbox_client_vq.knows_txdone = false; 416 | + ddata->mbox_client_vq.rx_callback = 417 | + cvitek_rproc_mbox_callback_vq; 418 | + } else { 419 | + ddata->mbox_client_vq.dev = NULL; 420 | + } 421 | + 422 | + ret = rproc_add(rproc); 423 | + if (ret) { 424 | + dev_err(dev, "rproc_add failed\n"); 425 | + goto free_clk; 426 | + } 427 | + 428 | + return 0; 429 | + 430 | +free_clk: 431 | + clk_unprepare(ddata->clk); 432 | +free_wkq: 433 | + destroy_workqueue(ddata->workqueue); 434 | +free_rproc: 435 | + rproc_free(rproc); 436 | + 437 | + return ret; 438 | +} 439 | + 440 | +static int cvitek_rproc_remove(struct platform_device *pdev) 441 | +{ 442 | + struct rproc *rproc = platform_get_drvdata(pdev); 443 | + struct cvitek_rproc *ddata = rproc->priv; 444 | + int i; 445 | + 446 | + rproc_del(rproc); 447 | + 448 | + clk_disable_unprepare(ddata->clk); 449 | + 450 | + for (i = 0; i < MBOX_MAX; i++) 451 | + mbox_free_channel(ddata->mbox_chan[i]); 452 | + 453 | + destroy_workqueue(ddata->workqueue); 454 | + 455 | + rproc_free(rproc); 456 | + 457 | + return 0; 458 | +} 459 | + 460 | +static struct platform_driver cvitek_rproc_driver = { 461 | + .probe = cvitek_rproc_probe, 462 | + .remove = cvitek_rproc_remove, 463 | + .driver = { 464 | + .name = "cvitek-rproc", 465 | + .of_match_table = of_match_ptr(cvitek_rproc_match), 466 | + }, 467 | +}; 468 | +module_platform_driver(cvitek_rproc_driver); 469 | + 470 | +MODULE_DESCRIPTION("CVITEK Remote Processor Control Driver"); 471 | +MODULE_AUTHOR("Justin Hammond "); 472 | +MODULE_LICENSE("GPL v2"); 473 | -- 474 | 2.44.0 475 | 476 | -------------------------------------------------------------------------------- /configs/common/patches/linux/0004-backport-rpmsg-driver.patch: -------------------------------------------------------------------------------- 1 | From d7a70bfb37c9613f38483f31ea2b34c1919a9905 Mon Sep 17 00:00:00 2001 2 | From: Justin Hammond 3 | Date: Sat, 6 Apr 2024 14:30:35 +0800 4 | Subject: [PATCH 4/4] backport rpmsg driver 5 | 6 | --- 7 | drivers/tty/Kconfig | 12 ++ 8 | drivers/tty/Makefile | 1 + 9 | drivers/tty/rpmsg_tty.c | 277 ++++++++++++++++++++++++++++++++++++++++ 10 | 3 files changed, 290 insertions(+) 11 | create mode 100644 drivers/tty/rpmsg_tty.c 12 | 13 | diff --git a/drivers/tty/Kconfig b/drivers/tty/Kconfig 14 | index 93fd984eb2f5..eb61b3401fa7 100644 15 | --- a/drivers/tty/Kconfig 16 | +++ b/drivers/tty/Kconfig 17 | @@ -480,6 +480,18 @@ config VCC 18 | 19 | source "drivers/tty/hvc/Kconfig" 20 | 21 | +config RPMSG_TTY 22 | + tristate "RPMSG tty driver" 23 | + depends on RPMSG 24 | + help 25 | + Say y here to export rpmsg endpoints as tty devices, usually found 26 | + in /dev/ttyRPMSGx. 27 | + This makes it possible for user-space programs to send and receive 28 | + rpmsg messages as a standard tty protocol. 29 | + 30 | + To compile this driver as a module, choose M here: the module will be 31 | + called rpmsg_tty. 32 | + 33 | endif # TTY 34 | 35 | source "drivers/tty/serdev/Kconfig" 36 | diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile 37 | index 020b1cd9294f..c2465e7ebc2a 100644 38 | --- a/drivers/tty/Makefile 39 | +++ b/drivers/tty/Makefile 40 | @@ -34,5 +34,6 @@ obj-$(CONFIG_PPC_EPAPR_HV_BYTECHAN) += ehv_bytechan.o 41 | obj-$(CONFIG_GOLDFISH_TTY) += goldfish.o 42 | obj-$(CONFIG_MIPS_EJTAG_FDC_TTY) += mips_ejtag_fdc.o 43 | obj-$(CONFIG_VCC) += vcc.o 44 | +obj-$(CONFIG_RPMSG_TTY) += rpmsg_tty.o 45 | 46 | obj-y += ipwireless/ 47 | diff --git a/drivers/tty/rpmsg_tty.c b/drivers/tty/rpmsg_tty.c 48 | new file mode 100644 49 | index 000000000000..af791538209a 50 | --- /dev/null 51 | +++ b/drivers/tty/rpmsg_tty.c 52 | @@ -0,0 +1,277 @@ 53 | +// SPDX-License-Identifier: GPL-2.0 54 | +/* 55 | + * Copyright (C) 2021 STMicroelectronics - All Rights Reserved 56 | + * 57 | + * The rpmsg tty driver implements serial communication on the RPMsg bus to makes 58 | + * possible for user-space programs to send and receive rpmsg messages as a standard 59 | + * tty protocol. 60 | + * 61 | + * The remote processor can instantiate a new tty by requesting a "rpmsg-tty" RPMsg service. 62 | + * The "rpmsg-tty" service is directly used for data exchange. No flow control is implemented yet. 63 | + */ 64 | + 65 | +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 66 | + 67 | +#include 68 | +#include 69 | +#include 70 | +#include 71 | +#include 72 | + 73 | +#define RPMSG_TTY_NAME "ttyRPMSG" 74 | +#define MAX_TTY_RPMSG 32 75 | + 76 | +static DEFINE_IDR(tty_idr); /* tty instance id */ 77 | +static DEFINE_MUTEX(idr_lock); /* protects tty_idr */ 78 | + 79 | +static struct tty_driver *rpmsg_tty_driver; 80 | + 81 | +struct rpmsg_tty_port { 82 | + struct tty_port port; /* TTY port data */ 83 | + int id; /* TTY rpmsg index */ 84 | + struct rpmsg_device *rpdev; /* rpmsg device */ 85 | +}; 86 | + 87 | +static int rpmsg_tty_cb(struct rpmsg_device *rpdev, void *data, int len, void *priv, u32 src) 88 | +{ 89 | + struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev); 90 | + int copied; 91 | + 92 | + if (!len) 93 | + return -EINVAL; 94 | + copied = tty_insert_flip_string(&cport->port, data, len); 95 | + if (copied != len) 96 | + dev_err_ratelimited(&rpdev->dev, "Trunc buffer: available space is %d\n", copied); 97 | + tty_flip_buffer_push(&cport->port); 98 | + 99 | + return 0; 100 | +} 101 | + 102 | +static int rpmsg_tty_install(struct tty_driver *driver, struct tty_struct *tty) 103 | +{ 104 | + struct rpmsg_tty_port *cport = idr_find(&tty_idr, tty->index); 105 | + 106 | + tty->driver_data = cport; 107 | + 108 | + return tty_port_install(&cport->port, driver, tty); 109 | +} 110 | + 111 | +static int rpmsg_tty_open(struct tty_struct *tty, struct file *filp) 112 | +{ 113 | + return tty_port_open(tty->port, tty, filp); 114 | +} 115 | + 116 | +static void rpmsg_tty_close(struct tty_struct *tty, struct file *filp) 117 | +{ 118 | + return tty_port_close(tty->port, tty, filp); 119 | +} 120 | + 121 | +static int rpmsg_tty_write(struct tty_struct *tty, const u8 *buf, int len) 122 | +{ 123 | + struct rpmsg_tty_port *cport = tty->driver_data; 124 | + struct rpmsg_device *rpdev; 125 | + int msg_max_size, msg_size; 126 | + int ret; 127 | + 128 | + rpdev = cport->rpdev; 129 | + 130 | +// msg_max_size = rpmsg_get_mtu(rpdev->ept); 131 | + msg_max_size = 512; 132 | + if (msg_max_size < 0) 133 | + return msg_max_size; 134 | + 135 | + msg_size = min(len, msg_max_size); 136 | + 137 | + /* 138 | + * Use rpmsg_trysend instead of rpmsg_send to send the message so the caller is not 139 | + * hung until a rpmsg buffer is available. In such case rpmsg_trysend returns -ENOMEM. 140 | + */ 141 | + ret = rpmsg_trysend(rpdev->ept, (void *)buf, msg_size); 142 | + if (ret) { 143 | + dev_dbg_ratelimited(&rpdev->dev, "rpmsg_send failed: %d\n", ret); 144 | + return ret; 145 | + } 146 | + 147 | + return msg_size; 148 | +} 149 | + 150 | +static int rpmsg_tty_write_room(struct tty_struct *tty) 151 | +{ 152 | + //struct rpmsg_tty_port *cport = tty->driver_data; 153 | + int size; 154 | + 155 | + //size = rpmsg_get_mtu(cport->rpdev->ept); 156 | + size = 512; 157 | + if (size < 0) 158 | + return 0; 159 | + 160 | + return size; 161 | +} 162 | + 163 | +static const struct tty_operations rpmsg_tty_ops = { 164 | + .install = rpmsg_tty_install, 165 | + .open = rpmsg_tty_open, 166 | + .close = rpmsg_tty_close, 167 | + .write = rpmsg_tty_write, 168 | + .write_room = rpmsg_tty_write_room, 169 | +}; 170 | + 171 | +static struct rpmsg_tty_port *rpmsg_tty_alloc_cport(void) 172 | +{ 173 | + struct rpmsg_tty_port *cport; 174 | + int ret; 175 | + 176 | + cport = kzalloc(sizeof(*cport), GFP_KERNEL); 177 | + if (!cport) 178 | + return ERR_PTR(-ENOMEM); 179 | + 180 | + mutex_lock(&idr_lock); 181 | + ret = idr_alloc(&tty_idr, cport, 0, MAX_TTY_RPMSG, GFP_KERNEL); 182 | + mutex_unlock(&idr_lock); 183 | + 184 | + if (ret < 0) { 185 | + kfree(cport); 186 | + return ERR_PTR(ret); 187 | + } 188 | + 189 | + cport->id = ret; 190 | + 191 | + return cport; 192 | +} 193 | + 194 | +static void rpmsg_tty_release_cport(struct rpmsg_tty_port *cport) 195 | +{ 196 | + mutex_lock(&idr_lock); 197 | + idr_remove(&tty_idr, cport->id); 198 | + mutex_unlock(&idr_lock); 199 | + 200 | + kfree(cport); 201 | +} 202 | + 203 | +static const struct tty_port_operations rpmsg_tty_port_ops = { }; 204 | + 205 | +static int rpmsg_tty_probe(struct rpmsg_device *rpdev) 206 | +{ 207 | + struct rpmsg_tty_port *cport; 208 | + struct device *dev = &rpdev->dev; 209 | + struct device *tty_dev; 210 | + int ret; 211 | + 212 | + cport = rpmsg_tty_alloc_cport(); 213 | + if (IS_ERR(cport)) 214 | + return dev_err_probe(dev, PTR_ERR(cport), "Failed to alloc tty port\n"); 215 | + 216 | + tty_port_init(&cport->port); 217 | + cport->port.ops = &rpmsg_tty_port_ops; 218 | + 219 | + tty_dev = tty_port_register_device(&cport->port, rpmsg_tty_driver, 220 | + cport->id, dev); 221 | + if (IS_ERR(tty_dev)) { 222 | + ret = dev_err_probe(dev, PTR_ERR(tty_dev), "Failed to register tty port\n"); 223 | + goto err_destroy; 224 | + } 225 | + 226 | + cport->rpdev = rpdev; 227 | + 228 | + dev_set_drvdata(dev, cport); 229 | + 230 | + dev_dbg(dev, "New channel: 0x%x -> 0x%x: " RPMSG_TTY_NAME "%d\n", 231 | + rpdev->src, rpdev->dst, cport->id); 232 | + 233 | + return 0; 234 | + 235 | +err_destroy: 236 | + tty_port_destroy(&cport->port); 237 | + rpmsg_tty_release_cport(cport); 238 | + 239 | + return ret; 240 | +} 241 | + 242 | +static void rpmsg_tty_remove(struct rpmsg_device *rpdev) 243 | +{ 244 | + struct rpmsg_tty_port *cport = dev_get_drvdata(&rpdev->dev); 245 | + 246 | + dev_dbg(&rpdev->dev, "Removing rpmsg tty device %d\n", cport->id); 247 | + 248 | + /* User hang up to release the tty */ 249 | + if (tty_port_initialized(&cport->port)) 250 | + tty_port_tty_hangup(&cport->port, false); 251 | + 252 | + tty_unregister_device(rpmsg_tty_driver, cport->id); 253 | + 254 | + tty_port_destroy(&cport->port); 255 | + rpmsg_tty_release_cport(cport); 256 | +} 257 | + 258 | +static struct rpmsg_device_id rpmsg_driver_tty_id_table[] = { 259 | + { .name = "rpmsg-tty" }, 260 | + { }, 261 | +}; 262 | +MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_tty_id_table); 263 | + 264 | +static struct rpmsg_driver rpmsg_tty_rpmsg_drv = { 265 | + .drv.name = KBUILD_MODNAME, 266 | + .id_table = rpmsg_driver_tty_id_table, 267 | + .probe = rpmsg_tty_probe, 268 | + .callback = rpmsg_tty_cb, 269 | + .remove = rpmsg_tty_remove, 270 | +}; 271 | + 272 | +static int __init rpmsg_tty_init(void) 273 | +{ 274 | + int ret; 275 | + 276 | + rpmsg_tty_driver = tty_alloc_driver(MAX_TTY_RPMSG, TTY_DRIVER_REAL_RAW | 277 | + TTY_DRIVER_DYNAMIC_DEV); 278 | + if (IS_ERR(rpmsg_tty_driver)) 279 | + return PTR_ERR(rpmsg_tty_driver); 280 | + 281 | + rpmsg_tty_driver->driver_name = "rpmsg_tty"; 282 | + rpmsg_tty_driver->name = RPMSG_TTY_NAME; 283 | + rpmsg_tty_driver->major = 0; 284 | + rpmsg_tty_driver->type = TTY_DRIVER_TYPE_CONSOLE; 285 | + 286 | + /* Disable unused mode by default */ 287 | + rpmsg_tty_driver->init_termios = tty_std_termios; 288 | + rpmsg_tty_driver->init_termios.c_lflag &= ~(ECHO | ICANON); 289 | + rpmsg_tty_driver->init_termios.c_oflag &= ~(OPOST | ONLCR); 290 | + 291 | + tty_set_operations(rpmsg_tty_driver, &rpmsg_tty_ops); 292 | + 293 | + ret = tty_register_driver(rpmsg_tty_driver); 294 | + if (ret < 0) { 295 | + pr_err("Couldn't install driver: %d\n", ret); 296 | + goto error_put; 297 | + } 298 | + 299 | + ret = register_rpmsg_driver(&rpmsg_tty_rpmsg_drv); 300 | + if (ret < 0) { 301 | + pr_err("Couldn't register driver: %d\n", ret); 302 | + goto error_unregister; 303 | + } 304 | + 305 | + return 0; 306 | + 307 | +error_unregister: 308 | + tty_unregister_driver(rpmsg_tty_driver); 309 | + 310 | +error_put: 311 | + tty_driver_kref_put(rpmsg_tty_driver); 312 | + 313 | + return ret; 314 | +} 315 | + 316 | +static void __exit rpmsg_tty_exit(void) 317 | +{ 318 | + unregister_rpmsg_driver(&rpmsg_tty_rpmsg_drv); 319 | + tty_unregister_driver(rpmsg_tty_driver); 320 | + tty_driver_kref_put(rpmsg_tty_driver); 321 | + idr_destroy(&tty_idr); 322 | +} 323 | + 324 | +module_init(rpmsg_tty_init); 325 | +module_exit(rpmsg_tty_exit); 326 | + 327 | +MODULE_AUTHOR("Arnaud Pouliquen "); 328 | +MODULE_DESCRIPTION("remote processor messaging tty driver"); 329 | +MODULE_LICENSE("GPL v2"); 330 | -- 331 | 2.44.0 332 | 333 | -------------------------------------------------------------------------------- /configs/common/patches/linux/0005-add-cvitek-pwm-driver.patch: -------------------------------------------------------------------------------- 1 | From e181713a4a003f770b47db8941743be4ddbce16e Mon Sep 17 00:00:00 2001 2 | From: Justin Hammond 3 | Date: Wed, 10 Apr 2024 16:22:30 +0800 4 | Subject: [PATCH] add cvitek pwm driver 5 | 6 | --- 7 | drivers/pwm/Kconfig | 8 + 8 | drivers/pwm/Makefile | 1 + 9 | drivers/pwm/pwm-cvitek.c | 380 +++++++++++++++++++++++++++++++++++++++ 10 | 3 files changed, 389 insertions(+) 11 | create mode 100644 drivers/pwm/pwm-cvitek.c 12 | 13 | diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig 14 | index 63be5362fd3a..4aa985b2ae69 100644 15 | --- a/drivers/pwm/Kconfig 16 | +++ b/drivers/pwm/Kconfig 17 | @@ -160,6 +160,14 @@ config PWM_CROS_EC 18 | PWM driver for exposing a PWM attached to the ChromeOS Embedded 19 | Controller. 20 | 21 | +config PWM_CVITEK 22 | + tristate "Cvitek PWM support" 23 | + depends on ARCH_CVITEK 24 | + help 25 | + Generic PWM framework driver for Cvitek SoCs. 26 | + We use it to control fan. 27 | + 28 | + 29 | config PWM_EP93XX 30 | tristate "Cirrus Logic EP93xx PWM support" 31 | depends on ARCH_EP93XX || COMPILE_TEST 32 | diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile 33 | index cbdcd55d69ee..2db39a76d7f7 100644 34 | --- a/drivers/pwm/Makefile 35 | +++ b/drivers/pwm/Makefile 36 | @@ -13,6 +13,7 @@ obj-$(CONFIG_PWM_BRCMSTB) += pwm-brcmstb.o 37 | obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o 38 | obj-$(CONFIG_PWM_CRC) += pwm-crc.o 39 | obj-$(CONFIG_PWM_CROS_EC) += pwm-cros-ec.o 40 | +obj-$(CONFIG_PWM_CVITEK) += pwm-cvitek.o 41 | obj-$(CONFIG_PWM_EP93XX) += pwm-ep93xx.o 42 | obj-$(CONFIG_PWM_FSL_FTM) += pwm-fsl-ftm.o 43 | obj-$(CONFIG_PWM_HIBVT) += pwm-hibvt.o 44 | diff --git a/drivers/pwm/pwm-cvitek.c b/drivers/pwm/pwm-cvitek.c 45 | new file mode 100644 46 | index 000000000000..fab4ec9c9af1 47 | --- /dev/null 48 | +++ b/drivers/pwm/pwm-cvitek.c 49 | @@ -0,0 +1,380 @@ 50 | +#include 51 | +#include 52 | +#include 53 | +#include 54 | +#include 55 | +#include 56 | +#include 57 | +#include 58 | +#include 59 | +#include 60 | +#include 61 | +#include 62 | +#include 63 | + 64 | +#define REG_HLPERIOD 0x0 65 | +#define REG_PERIOD 0x4 66 | +#define REG_GROUP 0x8 67 | +#define REG_FREQNUM 0x20 68 | +#define REG_FREQDATA 0x24 69 | +#define REG_POLARITY 0x40 70 | + 71 | +#define REG_PWMSTART 0x44 72 | +#define REG_PWMUPDATE 0x4C 73 | +#define REG_SHIFTCOUNT 0x80 74 | +#define REG_SHIFTSTART 0x90 75 | +#define REG_FREQEN 0x9C 76 | +#define REG_FREQ_DONE_NUM 0xC0 77 | +#define REG_PWM_OE 0xD0 78 | + 79 | +#define PWM_REG_NUM 0x80 80 | + 81 | +/** 82 | + * struct cv_pwm_channel - private data of PWM channel 83 | + * @period_ns: current period in nanoseconds programmed to the hardware 84 | + * @duty_ns: current duty time in nanoseconds programmed to the hardware 85 | + * @tin_ns: time of one timer tick in nanoseconds with current timer rate 86 | + */ 87 | +struct cv_pwm_channel { 88 | + u32 period; 89 | + u32 hlperiod; 90 | +}; 91 | + 92 | +/** 93 | + * struct cv_pwm_chip - private data of PWM chip 94 | + * @chip: generic PWM chip 95 | + * @variant: local copy of hardware variant data 96 | + * @inverter_mask: inverter status for all channels - one bit per channel 97 | + * @base: base address of mapped PWM registers 98 | + * @base_clk: base clock used to drive the timers 99 | + * @tclk0: external clock 0 (can be ERR_PTR if not present) 100 | + * @tclk1: external clock 1 (can be ERR_PTR if not present) 101 | + */ 102 | +struct cv_pwm_chip { 103 | + struct pwm_chip chip; 104 | + void __iomem *base; 105 | + struct clk *base_clk; 106 | + u8 polarity_mask; 107 | + bool no_polarity; 108 | + uint32_t pwm_saved_regs[PWM_REG_NUM]; 109 | +}; 110 | + 111 | + 112 | +static inline 113 | +struct cv_pwm_chip *to_cv_pwm_chip(struct pwm_chip *chip) 114 | +{ 115 | + return container_of(chip, struct cv_pwm_chip, chip); 116 | +} 117 | + 118 | +static int pwm_cv_request(struct pwm_chip *chip, struct pwm_device *pwm_dev) 119 | +{ 120 | + struct cv_pwm_channel *channel; 121 | + 122 | + channel = kzalloc(sizeof(*channel), GFP_KERNEL); 123 | + if (!channel) 124 | + return -ENOMEM; 125 | + 126 | + return pwm_set_chip_data(pwm_dev, channel); 127 | +} 128 | + 129 | +static void pwm_cv_free(struct pwm_chip *chip, struct pwm_device *pwm_dev) 130 | +{ 131 | + struct cv_pwm_channel *channel = pwm_get_chip_data(pwm_dev); 132 | + 133 | + pwm_set_chip_data(pwm_dev, NULL); 134 | + kfree(channel); 135 | +} 136 | + 137 | +static int pwm_cv_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, 138 | + int duty_ns, int period_ns) 139 | +{ 140 | + struct cv_pwm_chip *our_chip = to_cv_pwm_chip(chip); 141 | + struct cv_pwm_channel *channel = pwm_get_chip_data(pwm_dev); 142 | + u64 cycles; 143 | + 144 | + cycles = clk_get_rate(our_chip->base_clk); 145 | + pr_debug("clk_get_rate=%llu\n", cycles); 146 | + 147 | + cycles *= period_ns; 148 | + do_div(cycles, NSEC_PER_SEC); 149 | + 150 | + channel->period = cycles; 151 | + cycles = cycles * duty_ns; 152 | + do_div(cycles, period_ns); 153 | + 154 | + if (cycles == 0) 155 | + cycles = 1; 156 | + if (cycles == channel->period) 157 | + cycles = channel->period - 1; 158 | + 159 | + channel->hlperiod = channel->period - cycles; 160 | + 161 | + pr_debug("period_ns=%d, duty_ns=%d, period=%d, hlperiod=%d\n", 162 | + period_ns, duty_ns, channel->period, channel->hlperiod); 163 | + 164 | + return 0; 165 | +} 166 | + 167 | +static int pwm_cv_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev) 168 | +{ 169 | + struct cv_pwm_chip *our_chip = to_cv_pwm_chip(chip); 170 | + struct cv_pwm_channel *channel = pwm_get_chip_data(pwm_dev); 171 | + uint32_t pwm_start_value; 172 | + uint32_t value; 173 | + 174 | + writel(channel->period, our_chip->base + REG_GROUP * pwm_dev->hwpwm + REG_PERIOD); 175 | + if (channel->hlperiod != 0) 176 | + writel(channel->hlperiod, our_chip->base + REG_GROUP * pwm_dev->hwpwm + REG_HLPERIOD); 177 | + 178 | + pwm_start_value = readl(our_chip->base + REG_PWMSTART); 179 | + 180 | + writel(pwm_start_value & (~(1 << (pwm_dev->hwpwm))), our_chip->base + REG_PWMSTART); 181 | + 182 | + value = pwm_start_value | (1 << pwm_dev->hwpwm); 183 | + pr_debug("pwm_cv_enable: value = %x\n", value); 184 | + 185 | + writel(value, our_chip->base + REG_PWM_OE); 186 | + writel(value, our_chip->base + REG_PWMSTART); 187 | + 188 | + return 0; 189 | +} 190 | + 191 | +static void pwm_cv_disable(struct pwm_chip *chip, 192 | + struct pwm_device *pwm_dev) 193 | +{ 194 | + struct cv_pwm_chip *our_chip = to_cv_pwm_chip(chip); 195 | + uint32_t value; 196 | + 197 | + value = readl(our_chip->base + REG_PWMSTART) & (~(1 << (pwm_dev->hwpwm))); 198 | + pr_debug("pwm_cv_disable: value = %x\n", value); 199 | + writel(value, our_chip->base + REG_PWM_OE); 200 | + writel(value, our_chip->base + REG_PWMSTART); 201 | + 202 | + writel(1, our_chip->base + REG_GROUP * pwm_dev->hwpwm + REG_PERIOD); 203 | + writel(2, our_chip->base + REG_GROUP * pwm_dev->hwpwm + REG_HLPERIOD); 204 | +} 205 | + 206 | +static int pwm_cv_set_polarity(struct pwm_chip *chip, 207 | + struct pwm_device *pwm_dev, 208 | + enum pwm_polarity polarity) 209 | +{ 210 | + struct cv_pwm_chip *our_chip = to_cv_pwm_chip(chip); 211 | + 212 | + if (our_chip->no_polarity) { 213 | + dev_err(chip->dev, "no polarity\n"); 214 | + return -ENOTSUPP; 215 | + } 216 | + 217 | + if (polarity == PWM_POLARITY_NORMAL) 218 | + our_chip->polarity_mask &= ~(1 << pwm_dev->hwpwm); 219 | + else 220 | + our_chip->polarity_mask |= 1 << pwm_dev->hwpwm; 221 | + 222 | + writel(our_chip->polarity_mask, our_chip->base + REG_POLARITY); 223 | + 224 | + return 0; 225 | +} 226 | + 227 | +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)) 228 | +static int pwm_cv_apply(struct pwm_chip *chip, struct pwm_device *pwm, 229 | + const struct pwm_state *state) 230 | +#else 231 | +static int pwm_cv_apply(struct pwm_chip *chip, struct pwm_device *pwm, 232 | + struct pwm_state *state) 233 | +#endif 234 | +{ 235 | + int ret; 236 | + 237 | + ret = pwm_cv_config(chip, pwm, state->duty_cycle, state->period); 238 | + if (ret) { 239 | + dev_err(chip->dev, "pwm apply err\n"); 240 | + return ret; 241 | + } 242 | + 243 | + dev_dbg(chip->dev, "pwm_cv_apply state->enabled = %d\n", state->enabled); 244 | + if (state->enabled) 245 | + ret = pwm_cv_enable(chip, pwm); 246 | + else 247 | + pwm_cv_disable(chip, pwm); 248 | + 249 | + if (ret) { 250 | + dev_err(chip->dev, "pwm apply failed\n"); 251 | + return ret; 252 | + } 253 | + return ret; 254 | +} 255 | + 256 | +static int pwm_cv_capture(struct pwm_chip *chip, struct pwm_device *pwm_dev, 257 | + struct pwm_capture *result, unsigned long timeout) 258 | +{ 259 | + struct cv_pwm_chip *our_chip = to_cv_pwm_chip(chip); 260 | + uint32_t value; 261 | + u64 cycles; 262 | + u64 cycle_cnt; 263 | + 264 | + // Set corresponding bit in PWM_OE to 0 265 | + value = readl(our_chip->base + REG_PWM_OE) & (~(1 << (pwm_dev->hwpwm))); 266 | + writel(value, our_chip->base + REG_PWM_OE); 267 | + pr_debug("pwm_cv_capture: REG_PWM_OE = %x\n", value); 268 | + 269 | + // Enable capture 270 | + writel(1, our_chip->base + REG_GROUP * pwm_dev->hwpwm + REG_FREQNUM); 271 | + writel(1 << pwm_dev->hwpwm, our_chip->base + REG_FREQEN); 272 | + pr_debug("pwm_cv_capture: REG_FREQEN = %x\n", readl(our_chip->base + REG_FREQEN)); 273 | + 274 | + // Wait for done status 275 | + while (timeout--) { 276 | + mdelay(1); 277 | + pr_debug("delay 1ms\n"); 278 | + value = readl(our_chip->base + REG_FREQ_DONE_NUM + pwm_dev->hwpwm * 4); 279 | + if (value != 0) 280 | + break; 281 | + } 282 | + 283 | + // Read cycle count 284 | + cycle_cnt = readl(our_chip->base + REG_GROUP * pwm_dev->hwpwm + REG_FREQDATA) + 1; 285 | + pr_debug("pwm_cv_capture: cycle_cnt = %llu\n", cycle_cnt); 286 | + 287 | + // Convert from cycle count to period ns 288 | + cycles = clk_get_rate(our_chip->base_clk); 289 | + cycle_cnt *= NSEC_PER_SEC; 290 | + do_div(cycle_cnt, cycles); 291 | + 292 | + result->period = cycle_cnt; 293 | + result->duty_cycle = 0; 294 | + 295 | + // Disable capture 296 | + writel(0x0, our_chip->base + REG_FREQEN); 297 | + 298 | + return 0; 299 | +} 300 | + 301 | +static const struct pwm_ops pwm_cv_ops = { 302 | + .request = pwm_cv_request, 303 | + .free = pwm_cv_free, 304 | + .enable = pwm_cv_enable, 305 | + .disable = pwm_cv_disable, 306 | + .config = pwm_cv_config, 307 | + .set_polarity = pwm_cv_set_polarity, 308 | + /* .apply = pwm_cv_apply, */ 309 | + .capture = pwm_cv_capture, 310 | + .owner = THIS_MODULE, 311 | +}; 312 | + 313 | +static const struct of_device_id cv_pwm_match[] = { 314 | + { .compatible = "cvitek,cvi-pwm" }, 315 | + { }, 316 | +}; 317 | +MODULE_DEVICE_TABLE(of, cv_pwm_match); 318 | + 319 | +static int pwm_cv_probe(struct platform_device *pdev) 320 | +{ 321 | + struct device *dev = &pdev->dev; 322 | + struct cv_pwm_chip *chip; 323 | + struct resource *res; 324 | + int ret; 325 | + 326 | + // pr_debug("%s\n", __func__); 327 | + 328 | + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); 329 | + if (chip == NULL) 330 | + return -ENOMEM; 331 | + 332 | + chip->chip.dev = &pdev->dev; 333 | + chip->chip.ops = &pwm_cv_ops; 334 | + chip->chip.base = -1; 335 | + chip->polarity_mask = 0; 336 | + 337 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 338 | + chip->base = devm_ioremap_resource(&pdev->dev, res); 339 | + if (IS_ERR(chip->base)) 340 | + return PTR_ERR(chip->base); 341 | + 342 | + chip->base_clk = devm_clk_get(&pdev->dev, NULL); 343 | + if (IS_ERR(chip->base_clk)) { 344 | + dev_err(dev, "failed to get pwm source clk\n"); 345 | + return PTR_ERR(chip->base_clk); 346 | + } 347 | + 348 | + ret = clk_prepare_enable(chip->base_clk); 349 | + if (ret < 0) { 350 | + dev_err(dev, "failed to enable base clock\n"); 351 | + return ret; 352 | + } 353 | + 354 | + //pwm-num default is 4, compatible with bm1682 355 | + if (of_property_read_bool(pdev->dev.of_node, "pwm-num")) 356 | + device_property_read_u32(&pdev->dev, "pwm-num", &chip->chip.npwm); 357 | + else 358 | + chip->chip.npwm = 4; 359 | + 360 | + //no_polarity default is false(have polarity) , compatible with bm1682 361 | + if (of_property_read_bool(pdev->dev.of_node, "no-polarity")) 362 | + chip->no_polarity = true; 363 | + else 364 | + chip->no_polarity = false; 365 | + // pr_debug("chip->chip.npwm = %d chip->no_polarity = %d\n", chip->chip.npwm, chip->no_polarity); 366 | + 367 | + platform_set_drvdata(pdev, chip); 368 | + 369 | + ret = pwmchip_add(&chip->chip); 370 | + if (ret < 0) { 371 | + dev_err(dev, "failed to register PWM chip\n"); 372 | + clk_disable_unprepare(chip->base_clk); 373 | + return ret; 374 | + } 375 | + 376 | + return 0; 377 | +} 378 | + 379 | +static int pwm_cv_remove(struct platform_device *pdev) 380 | +{ 381 | + struct cv_pwm_chip *chip = platform_get_drvdata(pdev); 382 | + int ret; 383 | + 384 | + ret = pwmchip_remove(&chip->chip); 385 | + if (ret < 0) 386 | + return ret; 387 | + 388 | + clk_disable_unprepare(chip->base_clk); 389 | + 390 | + return 0; 391 | +} 392 | + 393 | +#ifdef CONFIG_PM_SLEEP 394 | +static int pwm_cv_suspend(struct device *dev) 395 | +{ 396 | + struct cv_pwm_chip *chip = dev_get_drvdata(dev); 397 | + 398 | + memcpy_fromio(chip->pwm_saved_regs, chip->base, PWM_REG_NUM * 4); 399 | + 400 | + return 0; 401 | +} 402 | + 403 | +static int pwm_cv_resume(struct device *dev) 404 | +{ 405 | + struct cv_pwm_chip *chip = dev_get_drvdata(dev); 406 | + 407 | + memcpy_toio(chip->base, chip->pwm_saved_regs, PWM_REG_NUM * 4); 408 | + 409 | + return 0; 410 | +} 411 | +#endif 412 | + 413 | +static SIMPLE_DEV_PM_OPS(pwm_cv_pm_ops, pwm_cv_suspend, 414 | + pwm_cv_resume); 415 | + 416 | +static struct platform_driver pwm_cv_driver = { 417 | + .driver = { 418 | + .name = "cvtek-pwm", 419 | + .pm = &pwm_cv_pm_ops, 420 | + .of_match_table = of_match_ptr(cv_pwm_match), 421 | + }, 422 | + .probe = pwm_cv_probe, 423 | + .remove = pwm_cv_remove, 424 | +}; 425 | +module_platform_driver(pwm_cv_driver); 426 | + 427 | +MODULE_LICENSE("GPL"); 428 | +MODULE_AUTHOR("Mark.Hsieh"); 429 | +MODULE_DESCRIPTION("Cvitek PWM driver"); 430 | -- 431 | 2.44.0 432 | 433 | -------------------------------------------------------------------------------- /configs/common/patches/linux/0009-add-cooling-driver.patch: -------------------------------------------------------------------------------- 1 | From 3906608b67bc4074e19abc87b617939325a12483 Mon Sep 17 00:00:00 2001 2 | From: Justin Hammond 3 | Date: Fri, 12 Apr 2024 17:49:29 +0800 4 | Subject: [PATCH] Add cvitek-cooling driver 5 | 6 | --- 7 | drivers/thermal/Kconfig | 6 + 8 | drivers/thermal/Makefile | 1 + 9 | drivers/thermal/cv181x_cooling.c | 279 +++++++++++++++++++++++++++++++ 10 | 3 files changed, 286 insertions(+) 11 | create mode 100644 drivers/thermal/cv181x_cooling.c 12 | 13 | diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig 14 | index f91f06d425fd..b220f4a1ee27 100644 15 | --- a/drivers/thermal/Kconfig 16 | +++ b/drivers/thermal/Kconfig 17 | @@ -456,6 +456,12 @@ config CV180X_THERMAL 18 | the alert trip point interrupts and notifies the thermal framework with 19 | the trip point and temperature details of the zone. 20 | 21 | +config CV180X_COOLING 22 | + tristate "CPU Throttling Cooling Driver for CVITEK CV180X" 23 | + depends on ARCH_CV181X 24 | + help 25 | + Select this driver for CVITEK CV180X cpu throttling cooling driver 26 | + 27 | config AMLOGIC_THERMAL 28 | tristate "Amlogic Thermal Support" 29 | default ARCH_MESON 30 | diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile 31 | index e35f57cc2000..6ef07777fa55 100644 32 | --- a/drivers/thermal/Makefile 33 | +++ b/drivers/thermal/Makefile 34 | @@ -66,3 +66,4 @@ obj-$(CONFIG_CV181X_THERMAL) += cv181x_thermal.o 35 | obj-$(CONFIG_CV180X_THERMAL) += cv180x_thermal.o 36 | obj-$(CONFIG_CV1835_THERMAL) += cv1835_thermal.o 37 | obj-$(CONFIG_CV182X_THERMAL) += cv182x_thermal.o 38 | +obj-$(CONFIG_CV180X_COOLING) += cv181x_cooling.o 39 | \ No newline at end of file 40 | diff --git a/drivers/thermal/cv181x_cooling.c b/drivers/thermal/cv181x_cooling.c 41 | new file mode 100644 42 | index 000000000000..fdfd396ca3d4 43 | --- /dev/null 44 | +++ b/drivers/thermal/cv181x_cooling.c 45 | @@ -0,0 +1,279 @@ 46 | +#include 47 | +#include 48 | +#include 49 | +#include 50 | +#include 51 | +#include 52 | + 53 | +struct dev_freq { 54 | + unsigned long cpu_freq; 55 | + unsigned long tpu_freq; 56 | +}; 57 | + 58 | +struct cooling_device { 59 | + struct thermal_cooling_device *cdev; 60 | + struct mutex lock; /* lock to protect the content of this struct */ 61 | + unsigned long clk_state; 62 | + unsigned long max_clk_state; 63 | + struct clk *clk_cpu; 64 | + struct clk *clk_tpu; 65 | + struct dev_freq *dev_freqs; 66 | +}; 67 | + 68 | +static const struct dev_freq default_dev_freqs[] = { 69 | +#ifdef __riscv 70 | + {850000000, 500000000}, 71 | + {425000000, 250000000}, 72 | + {425000000, 125000000}, 73 | +#else 74 | + {800000000, 500000000}, 75 | + {400000000, 250000000}, 76 | + {400000000, 125000000}, 77 | +#endif 78 | +}; 79 | + 80 | +/* cooling device thermal callback functions are defined below */ 81 | + 82 | +/** 83 | + * cooling_get_max_state - callback function to get the max cooling state. 84 | + * @cdev: thermal cooling device pointer. 85 | + * @state: fill this variable with the max cooling state. 86 | + * 87 | + * Callback for the thermal cooling device to return the 88 | + * max cooling state. 89 | + * 90 | + * Return: 0 on success, an error code otherwise. 91 | + */ 92 | +static int cooling_get_max_state(struct thermal_cooling_device *cdev, 93 | + unsigned long *state) 94 | +{ 95 | + struct cooling_device *cvcdev = cdev->devdata; 96 | + 97 | + mutex_lock(&cvcdev->lock); 98 | + *state = cvcdev->max_clk_state; 99 | + mutex_unlock(&cvcdev->lock); 100 | + 101 | + return 0; 102 | +} 103 | + 104 | +/** 105 | + * cooling_get_cur_state - function to get the current cooling state. 106 | + * @cdev: thermal cooling device pointer. 107 | + * @state: fill this variable with the current cooling state. 108 | + * 109 | + * Callback for the thermal cooling device to return the current cooling 110 | + * state. 111 | + * 112 | + * Return: 0 (success) 113 | + */ 114 | +static int cooling_get_cur_state(struct thermal_cooling_device *cdev, 115 | + unsigned long *state) 116 | +{ 117 | + struct cooling_device *cvcdev = cdev->devdata; 118 | + 119 | + mutex_lock(&cvcdev->lock); 120 | + *state = cvcdev->clk_state; 121 | + mutex_unlock(&cvcdev->lock); 122 | + 123 | + return 0; 124 | +} 125 | + 126 | +/** 127 | + * cooling_set_cur_state - function to set the current cooling state. 128 | + * @cdev: thermal cooling device pointer. 129 | + * @state: set this variable to the current cooling state. 130 | + * 131 | + * Callback for the thermal cooling device to change the cv181x cooling 132 | + * current cooling state. 133 | + * 134 | + * Return: 0 on success, an error code otherwise. 135 | + */ 136 | +static int cooling_set_cur_state(struct thermal_cooling_device *cdev, 137 | + unsigned long state) 138 | +{ 139 | + struct cooling_device *cvcdev = cdev->devdata; 140 | + 141 | + dev_dbg(&cdev->device, "set cur_state=%ld\n", state); 142 | + dev_dbg(&cdev->device, "clk_cpu=%ld Hz\n", clk_get_rate(cvcdev->clk_cpu)); 143 | + dev_dbg(&cdev->device, "clk_tpu_axi=%ld Hz\n", clk_get_rate(cvcdev->clk_tpu)); 144 | + 145 | + mutex_lock(&cvcdev->lock); 146 | + 147 | + if (state <= cvcdev->max_clk_state && state != cvcdev->clk_state) { 148 | + dev_dbg(&cdev->device, "dev_freq[%ld].cpu_freq=%ld\n", state, cvcdev->dev_freqs[state].cpu_freq); 149 | + dev_dbg(&cdev->device, "dev_freq[%ld].tpu_freq=%ld\n", state, cvcdev->dev_freqs[state].tpu_freq); 150 | + 151 | + if (cvcdev->dev_freqs[state].cpu_freq != clk_get_rate(cvcdev->clk_cpu)) { 152 | + dev_dbg(&cdev->device, "set cpu freq=%ld\n", cvcdev->dev_freqs[state].cpu_freq); 153 | + clk_set_rate(cvcdev->clk_cpu, cvcdev->dev_freqs[state].cpu_freq); 154 | + } 155 | + 156 | + if (cvcdev->dev_freqs[state].tpu_freq != clk_get_rate(cvcdev->clk_tpu)) { 157 | + dev_dbg(&cdev->device, "set tpu freq=%ld\n", cvcdev->dev_freqs[state].tpu_freq); 158 | + clk_set_rate(cvcdev->clk_tpu, cvcdev->dev_freqs[state].tpu_freq); 159 | + } 160 | + 161 | + cvcdev->clk_state = state; 162 | + } 163 | + 164 | + mutex_unlock(&cvcdev->lock); 165 | + return 0; 166 | +} 167 | + 168 | +/* Bind clock callbacks to thermal cooling device ops */ 169 | +static struct thermal_cooling_device_ops const cooling_ops = { 170 | + .get_max_state = cooling_get_max_state, 171 | + .get_cur_state = cooling_get_cur_state, 172 | + .set_cur_state = cooling_set_cur_state, 173 | +}; 174 | + 175 | +static struct cooling_device * 176 | +cooling_device_register(struct device *dev) 177 | +{ 178 | + struct thermal_cooling_device *cdev; 179 | + struct cooling_device *cvcdev = NULL; 180 | + struct device_node *np = dev->of_node; 181 | + unsigned long clk_cpu_max_freq; 182 | + unsigned long clk_tpu_max_freq; 183 | + unsigned long j; 184 | + int proplen; 185 | + int i; 186 | + 187 | + cvcdev = devm_kzalloc(dev, sizeof(*cvcdev), GFP_KERNEL); 188 | + if (!cvcdev) 189 | + return ERR_PTR(-ENOMEM); 190 | + 191 | + mutex_init(&cvcdev->lock); 192 | + 193 | + /* get clk_cpu */ 194 | + cvcdev->clk_cpu = devm_clk_get(dev, "clk_cpu"); 195 | + if (IS_ERR(cvcdev->clk_cpu)) { 196 | + dev_err(dev, "failed to get clk_cpu\n"); 197 | + return ERR_PTR(-EINVAL); 198 | + } 199 | + 200 | + cvcdev->clk_tpu = devm_clk_get(dev, "clk_tpu_axi"); 201 | + if (IS_ERR(cvcdev->clk_tpu)) { 202 | + dev_err(dev, "failed to get clk_tpu_axi\n"); 203 | + return ERR_PTR(-EINVAL); 204 | + } 205 | + 206 | + /* get device frequency list from device tree */ 207 | + proplen = of_property_count_u32_elems(np, "dev-freqs"); 208 | + dev_info(dev, "elems of dev-freqs=%d\n", proplen); 209 | + 210 | + if (proplen < 0 || proplen % 2) { 211 | + dev_info(dev, "No 'dev-freqs' property found, use default value\n"); 212 | + 213 | + cvcdev->dev_freqs = devm_kmemdup(dev, &default_dev_freqs, sizeof(default_dev_freqs), GFP_KERNEL); 214 | + if (!cvcdev->dev_freqs) 215 | + return ERR_PTR(-ENOMEM); 216 | + 217 | + cvcdev->max_clk_state = ARRAY_SIZE(default_dev_freqs) - 1; 218 | + } else { 219 | + cvcdev->dev_freqs = devm_kzalloc(dev, sizeof(struct dev_freq) * (proplen / 2), GFP_KERNEL); 220 | + 221 | + if (!cvcdev->dev_freqs) 222 | + return ERR_PTR(-ENOMEM); 223 | + 224 | + for (i = 0; i < proplen / 2; i++) { 225 | + of_property_read_u32_index(np, "dev-freqs", i * 2, 226 | + (u32 *)&cvcdev->dev_freqs[i].cpu_freq); 227 | + of_property_read_u32_index(np, "dev-freqs", i * 2 + 1, 228 | + (u32 *)&cvcdev->dev_freqs[i].tpu_freq); 229 | + } 230 | + 231 | + cvcdev->max_clk_state = (proplen / 2) - 1; 232 | + } 233 | + 234 | + /* Get the cpu/tpu original clk freq as max freq */ 235 | + clk_cpu_max_freq = clk_get_rate(cvcdev->clk_cpu); 236 | + clk_tpu_max_freq = clk_get_rate(cvcdev->clk_tpu); 237 | + 238 | + /* Check if the cpu/tpu clk freq exceeds max freq */ 239 | + for (j = 0; j <= cvcdev->max_clk_state; j++) { 240 | + if (cvcdev->dev_freqs[j].cpu_freq > clk_cpu_max_freq) { 241 | + dev_info(dev, "dev_freqs[%ld].cpu_freq=%ld exceeds max_freq=%ld\n", 242 | + j, cvcdev->dev_freqs[j].cpu_freq, clk_cpu_max_freq); 243 | + cvcdev->dev_freqs[j].cpu_freq = clk_cpu_max_freq; 244 | + } 245 | + 246 | + if (cvcdev->dev_freqs[j].tpu_freq > clk_tpu_max_freq) { 247 | + dev_info(dev, "dev_freqs[%ld].tpu_freq=%ld exceeds max_freq=%ld\n", 248 | + j, cvcdev->dev_freqs[j].tpu_freq, clk_tpu_max_freq); 249 | + cvcdev->dev_freqs[j].tpu_freq = clk_tpu_max_freq; 250 | + } 251 | + 252 | + dev_info(dev, "dev_freqs[%ld]: %ld %ld\n", 253 | + j, cvcdev->dev_freqs[j].cpu_freq, cvcdev->dev_freqs[j].tpu_freq); 254 | + } 255 | + 256 | + cvcdev->clk_state = 0; 257 | + cdev = thermal_of_cooling_device_register(dev->of_node, 258 | + "cooling", cvcdev, 259 | + &cooling_ops); 260 | + if (IS_ERR(cdev)) 261 | + return ERR_PTR(-EINVAL); 262 | + 263 | + cvcdev->cdev = cdev; 264 | + 265 | + return cvcdev; 266 | +} 267 | + 268 | +static void cooling_device_unregister(struct cooling_device 269 | + *cvcdev) 270 | +{ 271 | + thermal_cooling_device_unregister(cvcdev->cdev); 272 | +} 273 | + 274 | +static int cooling_probe(struct platform_device *pdev) 275 | +{ 276 | + struct cooling_device *cvcdev; 277 | + 278 | + cvcdev = cooling_device_register(&pdev->dev); 279 | + if (IS_ERR(cvcdev)) { 280 | + int ret = PTR_ERR(cvcdev); 281 | + 282 | + if (ret != -EPROBE_DEFER) 283 | + dev_err(&pdev->dev, "Failed to register cooling device %d\n", ret); 284 | + 285 | + return ret; 286 | + } 287 | + 288 | + platform_set_drvdata(pdev, cvcdev); 289 | + dev_info(&pdev->dev, "Cooling device registered: %s\n", cvcdev->cdev->type); 290 | + 291 | + return 0; 292 | +} 293 | + 294 | +static int cooling_remove(struct platform_device *pdev) 295 | +{ 296 | + struct cooling_device *cvcdev = platform_get_drvdata(pdev); 297 | + 298 | + if (!IS_ERR(cvcdev)) 299 | + cooling_device_unregister(cvcdev); 300 | + 301 | + return 0; 302 | +} 303 | + 304 | +static const struct of_device_id cooling_match[] = { 305 | + {.compatible = "sophgo,cooling"}, 306 | + {.compatible = "cvitek,cv181x-cooling"}, 307 | + {}, 308 | +}; 309 | +MODULE_DEVICE_TABLE(of, cooling_match); 310 | + 311 | +static struct platform_driver cooling_driver = { 312 | + .driver = { 313 | + .name = "cooling", 314 | + .of_match_table = of_match_ptr(cooling_match), 315 | + }, 316 | + .probe = cooling_probe, 317 | + .remove = cooling_remove, 318 | +}; 319 | + 320 | +module_platform_driver(cooling_driver); 321 | + 322 | +MODULE_AUTHOR("fisher.cheng@cvitek.com"); 323 | +MODULE_DESCRIPTION("sophgo cooling driver"); 324 | +MODULE_LICENSE("GPL"); 325 | -- 326 | 2.44.0 327 | 328 | -------------------------------------------------------------------------------- /configs/common/patches/opensbi/0002-add-fence-tso-emulation.patch: -------------------------------------------------------------------------------- 1 | From cb8271c8e43e3c317436b7377c4fa0ac669f8fb5 Mon Sep 17 00:00:00 2001 2 | From: Samuel Holland 3 | Date: Sun, 29 May 2022 13:25:30 -0500 4 | Subject: [PATCH] lib: sbi_illegal_insn: Add emulation for fence.tso 5 | 6 | While OpenC906 appears to properly decode `fence.tso` as a fence 7 | instruction[1], the version of the C906 taped out in the Allwinner D1 8 | does not, and raises illegal instruction. 9 | 10 | Handle this errata by emulating `fence.tso` as `fence rw, rw`. 11 | 12 | [1]: https://github.com/T-head-Semi/openc906/blob/30827e7f/C906_RTL_FACTORY/gen_rtl/idu/rtl/aq_idu_id_decd.v#L2097 13 | 14 | Signed-off-by: Samuel Holland 15 | Reviewed-by: Anup Patel 16 | --- 17 | include/sbi/riscv_encoding.h | 3 +++ 18 | lib/sbi/sbi_illegal_insn.c | 14 +++++++++++++- 19 | 2 files changed, 16 insertions(+), 1 deletion(-) 20 | 21 | diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h 22 | index 7cfbaced5..a1647688a 100644 23 | --- a/include/sbi/riscv_encoding.h 24 | +++ b/include/sbi/riscv_encoding.h 25 | @@ -838,6 +838,9 @@ 26 | #define INSN_MASK_WFI 0xffffff00 27 | #define INSN_MATCH_WFI 0x10500000 28 | 29 | +#define INSN_MASK_FENCE_TSO 0xffffffff 30 | +#define INSN_MATCH_FENCE_TSO 0x8330000f 31 | + 32 | #define INSN_16BIT_MASK 0x3 33 | #define INSN_32BIT_MASK 0x1c 34 | 35 | diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c 36 | index 386b48a9c..84c04f874 100644 37 | --- a/lib/sbi/sbi_illegal_insn.c 38 | +++ b/lib/sbi/sbi_illegal_insn.c 39 | @@ -8,6 +8,7 @@ 40 | */ 41 | 42 | #include 43 | +#include 44 | #include 45 | #include 46 | #include 47 | @@ -33,6 +34,17 @@ static int truly_illegal_insn(ulong insn, struct sbi_trap_regs *regs) 48 | return sbi_trap_redirect(regs, &trap); 49 | } 50 | 51 | +static int misc_mem_opcode_insn(ulong insn, struct sbi_trap_regs *regs) 52 | +{ 53 | + /* Errata workaround: emulate `fence.tso` as `fence rw, rw`. */ 54 | + if ((insn & INSN_MASK_FENCE_TSO) == INSN_MATCH_FENCE_TSO) { 55 | + smp_mb(); 56 | + return 0; 57 | + } 58 | + 59 | + return truly_illegal_insn(insn, regs); 60 | +} 61 | + 62 | static int system_opcode_insn(ulong insn, struct sbi_trap_regs *regs) 63 | { 64 | int do_write, rs1_num = (insn >> 15) & 0x1f; 65 | @@ -92,7 +104,7 @@ static const illegal_insn_func illegal_insn_table[32] = { 66 | truly_illegal_insn, /* 0 */ 67 | truly_illegal_insn, /* 1 */ 68 | truly_illegal_insn, /* 2 */ 69 | - truly_illegal_insn, /* 3 */ 70 | + misc_mem_opcode_insn, /* 3 */ 71 | truly_illegal_insn, /* 4 */ 72 | truly_illegal_insn, /* 5 */ 73 | truly_illegal_insn, /* 6 */ 74 | -------------------------------------------------------------------------------- /configs/common/patches/opensbi/0002-fix-illegal-ins-infinite-loop.patch: -------------------------------------------------------------------------------- 1 | From 111afc12306e4368fa112f97d31ea802c4561294 Mon Sep 17 00:00:00 2001 2 | From: Rahul Pathak 3 | Date: Fri, 12 Aug 2022 19:24:42 +0530 4 | Subject: [PATCH] lib: sbi_illegal_insn: Fix FENCE.TSO emulation infinite trap 5 | loop 6 | 7 | In case of missing "FENCE.TSO" instruction implementation, 8 | opensbi can emulate the "FENCE.TSO" with "FENCE RW,RW", but 9 | mepc was not incremented to continue from the next instruction 10 | causing infinite trap. 11 | 12 | Fixes: cb8271c8 ("lib: sbi_illegal_insn: Add emulation for fence.tso") 13 | Signed-off-by: Rahul Pathak 14 | Reviewed-by: Andrew Jones 15 | Reviewed-by: Xiang W 16 | Reviewed-by: Samuel Holland 17 | --- 18 | lib/sbi/sbi_illegal_insn.c | 1 + 19 | 1 file changed, 1 insertion(+) 20 | 21 | diff --git a/lib/sbi/sbi_illegal_insn.c b/lib/sbi/sbi_illegal_insn.c 22 | index ecd35084b..9691bce93 100644 23 | --- a/lib/sbi/sbi_illegal_insn.c 24 | +++ b/lib/sbi/sbi_illegal_insn.c 25 | @@ -40,6 +40,7 @@ static int misc_mem_opcode_insn(ulong insn, struct sbi_trap_regs *regs) 26 | /* Errata workaround: emulate `fence.tso` as `fence rw, rw`. */ 27 | if ((insn & INSN_MASK_FENCE_TSO) == INSN_MATCH_FENCE_TSO) { 28 | smp_mb(); 29 | + regs->mepc += 4; 30 | return 0; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /configs/common/patches/u-boot/0001-enable-distroboot.patch: -------------------------------------------------------------------------------- 1 | diff --git a/include/configs/cv181x-asic.h b/include/configs/cv181x-asic.h 2 | index 1c276f1c..0e80d8b3 100644 3 | --- a/include/configs/cv181x-asic.h 4 | +++ b/include/configs/cv181x-asic.h 5 | @@ -9,13 +9,14 @@ 6 | #define __CV181X_ASIC_H__ 7 | 8 | #include <../../../board/cvitek/cv181x/cv181x_reg.h> 9 | +#include 10 | 11 | /* defined in cvipart.h */ 12 | #undef CONFIG_ENV_OFFSET 13 | #undef CONFIG_ENV_OFFSET_REDUND 14 | #undef CONFIG_ENV_SIZE 15 | #undef CONFIG_ENV_IS_IN_SPI_FLASH 16 | -#undef CONFIG_ENV_IS_IN_MMC 17 | +//#undef CONFIG_ENV_IS_IN_MMC 18 | #undef CONFIG_ENV_IS_IN_NAND 19 | #undef CONFIG_ENV_SECT_SIZE 20 | 21 | @@ -181,6 +182,11 @@ 22 | #define CONFIG_GATEWAYIP 192.168.0.11 23 | #define CONFIG_SERVERIP 192.168.56.101 24 | 25 | +#define BOOT_TARGET_DEVICES(func) \ 26 | + func(MMC, mmc, 0) \ 27 | + func(DHCP, dhcp, 0) \ 28 | + func(PXE, pxe, na) 29 | + 30 | #ifdef CONFIG_USE_DEFAULT_ENV 31 | /* The following Settings are chip dependent */ 32 | /******************************************************************************/ 33 | @@ -254,7 +260,17 @@ 34 | "root=" ROOTARGS "\0" \ 35 | "sdboot=" SD_BOOTM_COMMAND "\0" \ 36 | "othbootargs=" OTHERBOOTARGS "\0" \ 37 | - PARTS_OFFSET 38 | + "kernel_addr_r=" __stringify(CONFIG_SYS_TEXT_BASE) "\0" \ 39 | + "fdt_addr_r=0x81200000\0" \ 40 | + "fdtoverlay_addr_r=0x81300000\0" \ 41 | + "pxefile_addr_r=0x81400000\0" \ 42 | + "scriptaddr=0x81500000\0" \ 43 | + "ramdisk_addr_r=0x84000000\0" \ 44 | + "kernel_comp_addr_r=" __stringify(CVIMMAP_UIMAG_ADDR) "\0" \ 45 | + "kernel_comp_size=" __stringify(CVIMMAP_UIMAG_SIZE) "\0" \ 46 | + "fdtfile=" FDT_NO ".dtb\0" \ 47 | + PARTS_OFFSET \ 48 | + BOOTENV 49 | 50 | /********************************************************************************/ 51 | /* UBOOT_VBOOT commands */ 52 | @@ -301,10 +317,10 @@ 53 | #ifdef CONFIG_ENABLE_ALIOS_UPDATE 54 | #define CONFIG_BOOTCOMMAND "cvi_update_rtos" 55 | #else 56 | - #define CONFIG_BOOTCOMMAND SHOWLOGOCMD "cvi_update || run norboot || run nandboot ||run emmcboot" 57 | + #define CONFIG_BOOTCOMMAND SHOWLOGOCMD "cvi_update || run distro_bootcmd || run norboot || run nandboot ||run emmcboot" 58 | #endif 59 | #else 60 | - #define CONFIG_BOOTCOMMAND SHOWLOGOCMD "run sdboot" 61 | + #define CONFIG_BOOTCOMMAND SHOWLOGOCMD "run distro_bootcmd || run sdboot || run sdbootauto" 62 | #endif 63 | 64 | #if defined(CONFIG_NAND_SUPPORT) 65 | -------------------------------------------------------------------------------- /configs/duo256/dts/cv181x_milkv_duo256m_sd.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | #include "cv181x_base_riscv.dtsi" 3 | #include "cv181x_asic_qfn.dtsi" 4 | #include "cv181x_asic_sd.dtsi" 5 | #include "cv181x_default_memmap.dtsi" 6 | 7 | #include "dt-bindings/leds/common.h" 8 | #ifndef __UBOOT__ 9 | #include 10 | #endif 11 | 12 | 13 | &mipi_rx{ 14 | snsr-reset = <&portc 17 GPIO_ACTIVE_LOW>, <&portc 17 GPIO_ACTIVE_LOW>, <&portc 17 GPIO_ACTIVE_LOW>; 15 | }; 16 | 17 | &mipi_tx { 18 | /delete-property/ reset-gpio; 19 | /delete-property/ pwm-gpio; 20 | /delete-property/ power-ct-gpio; 21 | }; 22 | 23 | &spi2 { 24 | status = "okay"; 25 | 26 | spidev@0 { 27 | status = "okay"; 28 | }; 29 | }; 30 | 31 | &i2c0 { 32 | status = "disabled"; 33 | }; 34 | 35 | &i2c4 { 36 | status = "disabled"; 37 | }; 38 | 39 | &soc_thermal_0 { 40 | cooling-maps { 41 | map0 { 42 | trip = <&soc_thermal_trip_0>; 43 | cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT 1>; 44 | }; 45 | map1 { 46 | trip = <&soc_thermal_trip_1>; 47 | cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; 48 | }; 49 | }; 50 | }; 51 | 52 | / { 53 | model = "Milk-V Duo256M"; 54 | 55 | /delete-node/ wifi_pin; 56 | /delete-node/ bt_pin; 57 | 58 | leds { 59 | compatible = "gpio-leds"; 60 | led0 { 61 | gpios = <&porte 2 GPIO_ACTIVE_LOW>; 62 | linux,default-trigger = "heartbeat"; 63 | function = LED_FUNCTION_HEARTBEAT; 64 | }; 65 | }; 66 | #ifndef __UBOOT__ 67 | mbox: mbox@0x01900000 { 68 | compatible = "cvitek,sg200x-mailbox"; 69 | reg = <0x0 0x01900000 0x0 0x1000>; 70 | reg-names = "mailbox"; 71 | interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; 72 | interrupt-parent = <&plic0>; 73 | status = "okay"; 74 | #mbox-cells = <4>; 75 | }; 76 | 77 | cv181x-c906_1 { 78 | compatible = "cvitek,cv181x-c906_1"; 79 | memory-region = <&fast_image &vdev0vring0 &vdev0vring1 &vdev0buffer>; 80 | firmware = "c906-mcu.elf"; 81 | resets = <&rst RST_C906_1>; 82 | reset-names = "sw_reset"; 83 | clocks = <&clk CV181X_CLK_C906_1>; 84 | clock-names = "clk_c906_1"; 85 | mboxes = <&mbox 0 CVITEK_MBOX_DIRECTION_TX CVITEK_MBOX_C906_1 1>, <&mbox 1 CVITEK_MBOX_DIRECTION_RX CVITEK_MBOX_C906_1 1>; 86 | mbox-names = "vq_tx", "vq_rx"; 87 | status = "okay"; 88 | }; 89 | #endif 90 | 91 | }; 92 | 93 | -------------------------------------------------------------------------------- /configs/duo256/memmap.py: -------------------------------------------------------------------------------- 1 | SIZE_1M = 0x100000 2 | SIZE_1K = 1024 3 | 4 | 5 | # Only attributes in class MemoryMap are generated to .h 6 | class MemoryMap: 7 | # No prefix "CVIMMAP_" for the items in _no_prefix[] 8 | _no_prefix = [ 9 | "CONFIG_SYS_TEXT_BASE" # u-boot's CONFIG_SYS_TEXT_BASE is used without CPP. 10 | ] 11 | 12 | DRAM_BASE = 0x80000000 13 | DRAM_SIZE = 256 * SIZE_1M 14 | 15 | # ============== 16 | # C906L FreeRTOS 17 | # ============== 18 | FREERTOS_SIZE = 2 * SIZE_1M 19 | # FreeRTOS is at the end of DRAM 20 | FREERTOS_ADDR = DRAM_BASE + DRAM_SIZE - FREERTOS_SIZE 21 | FSBL_C906L_START_ADDR = FREERTOS_ADDR 22 | 23 | # ============================== 24 | # OpenSBI | arm-trusted-firmware 25 | # ============================== 26 | # Monitor is at the begining of DRAM 27 | MONITOR_ADDR = DRAM_BASE 28 | 29 | ATF_SIZE = 512 * SIZE_1K 30 | OPENSBI_SIZE = 512 * SIZE_1K 31 | OPENSBI_FDT_ADDR = MONITOR_ADDR + OPENSBI_SIZE 32 | 33 | # ========================= 34 | # memory@DRAM_BASE in .dts. 35 | # ========================= 36 | # Ignore the area of FreeRTOS in u-boot and kernel 37 | KERNEL_MEMORY_ADDR = DRAM_BASE 38 | KERNEL_MEMORY_SIZE = DRAM_SIZE - FREERTOS_SIZE 39 | 40 | # ================= 41 | # Multimedia buffer. Used by u-boot/kernel/FreeRTOS 42 | # ================= 43 | ION_SIZE = 0 * SIZE_1M 44 | H26X_BITSTREAM_SIZE = 0 * SIZE_1M 45 | H26X_ENC_BUFF_SIZE = 0 46 | ISP_MEM_BASE_SIZE = 0 * SIZE_1M 47 | FREERTOS_RESERVED_ION_SIZE = H26X_BITSTREAM_SIZE + H26X_ENC_BUFF_SIZE + ISP_MEM_BASE_SIZE 48 | 49 | # ION after FreeRTOS 50 | ION_ADDR = FREERTOS_ADDR - ION_SIZE 51 | 52 | # Buffers of the fast image are inside the ION buffer 53 | H26X_BITSTREAM_ADDR = ION_ADDR 54 | H26X_ENC_BUFF_ADDR = H26X_BITSTREAM_ADDR + H26X_BITSTREAM_SIZE 55 | ISP_MEM_BASE_ADDR = H26X_ENC_BUFF_ADDR + H26X_ENC_BUFF_SIZE 56 | 57 | assert ISP_MEM_BASE_ADDR + ISP_MEM_BASE_SIZE <= ION_ADDR + ION_SIZE 58 | 59 | # Boot logo is after the ION buffer 60 | # Framebuffer uses boot logo's reserved memory 61 | BOOTLOGO_SIZE = 1800 * SIZE_1K 62 | BOOTLOGO_ADDR = ION_ADDR - BOOTLOGO_SIZE 63 | FRAMEBUFFER_SIZE = BOOTLOGO_SIZE 64 | FRAMEBUFFER_ADDR = BOOTLOGO_ADDR 65 | 66 | # =================== 67 | # FSBL and u-boot-2021 68 | # =================== 69 | CVI_UPDATE_HEADER_SIZE = SIZE_1K 70 | UIMAG_SIZE = 16 * SIZE_1M 71 | 72 | # kernel image loading buffer 73 | UIMAG_ADDR = DRAM_BASE + 24 * SIZE_1M 74 | CVI_UPDATE_HEADER_ADDR = UIMAG_ADDR - CVI_UPDATE_HEADER_SIZE 75 | 76 | # FSBL decompress buffer 77 | FSBL_UNZIP_ADDR = UIMAG_ADDR 78 | FSBL_UNZIP_SIZE = UIMAG_SIZE 79 | 80 | assert UIMAG_ADDR + UIMAG_SIZE <= BOOTLOGO_ADDR 81 | 82 | # u-boot's run address and entry point 83 | CONFIG_SYS_TEXT_BASE = DRAM_BASE + 2 * SIZE_1M 84 | # u-boot's init stack point is only used before board_init_f() 85 | CONFIG_SYS_INIT_SP_ADDR = UIMAG_ADDR + UIMAG_SIZE 86 | -------------------------------------------------------------------------------- /configs/duo256/partition_sd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /configs/duo256/settings.mk: -------------------------------------------------------------------------------- 1 | CHIP=cv181x 2 | UBOOT_CHIP=cv181x 3 | UBOOT_BOARD=milkv_duo256m_sd 4 | BOOT_CPU=riscv 5 | ARCH=riscv 6 | DDR_CFG=ddr3_1866_x16 7 | PARTITION_FILE=partition_sd.xml 8 | STORAGE_TYPE=sd 9 | 10 | PACKAGES += " duo-pinmux" 11 | #IMAGE_ADDITIONS += "aic8800-firmware" -------------------------------------------------------------------------------- /configs/duo256/u-boot/cvi_board_init.c: -------------------------------------------------------------------------------- 1 | int cvi_board_init(void) 2 | { 3 | // Camera 4 | PINMUX_CONFIG(PAD_MIPI_TXM1, IIC2_SDA); // GP10 5 | PINMUX_CONFIG(PAD_MIPI_TXP1, IIC2_SCL); // GP11 6 | PINMUX_CONFIG(PAD_MIPI_TXP0, CAM_MCLK0); // Sensor MCLK 7 | PINMUX_CONFIG(PAD_MIPI_TXP2, XGPIOC_17); // Sensor RESET 8 | 9 | // UART1 10 | PINMUX_CONFIG(IIC0_SCL, UART1_TX); // GP0 11 | PINMUX_CONFIG(IIC0_SDA, UART1_RX); // GP1 12 | 13 | // PWM 14 | PINMUX_CONFIG(JTAG_CPU_TMS, PWM_7); // GP2 15 | PINMUX_CONFIG(JTAG_CPU_TCK, PWM_6); // GP3 16 | 17 | // I2C1 18 | PINMUX_CONFIG(SD1_D2, IIC1_SCL); // GP4 19 | PINMUX_CONFIG(SD1_D1, IIC1_SDA); // GP5 20 | 21 | // SPI2 22 | PINMUX_CONFIG(SD1_CLK, SPI2_SCK); // GP6 23 | PINMUX_CONFIG(SD1_CMD, SPI2_SDO); // GP7 24 | PINMUX_CONFIG(SD1_D0, SPI2_SDI); // GP8 25 | PINMUX_CONFIG(SD1_D3, SPI2_CS_X); // GP9 26 | 27 | // All default GPIOs 28 | PINMUX_CONFIG(SD0_PWR_EN, XGPIOA_14); // GP14 29 | PINMUX_CONFIG(SPK_EN, XGPIOA_15); // GP15 30 | PINMUX_CONFIG(EMMC_CMD, XGPIOA_23); // GP16 31 | PINMUX_CONFIG(EMMC_DAT1, XGPIOA_24); // GP17 32 | PINMUX_CONFIG(EMMC_CLK, XGPIOA_22); // GP18 33 | PINMUX_CONFIG(EMMC_DAT0, XGPIOA_25); // GP19 34 | PINMUX_CONFIG(EMMC_DAT3, XGPIOA_27); // GP20 35 | PINMUX_CONFIG(EMMC_DAT2, XGPIOA_26); // GP21 36 | PINMUX_CONFIG(PWR_SEQ2, PWR_GPIO_4); // GP22 37 | 38 | // LED 39 | PINMUX_CONFIG(PWR_GPIO2, PWR_GPIO_2); // GP25 40 | 41 | // ADC pins set to GPIO 42 | PINMUX_CONFIG(ADC1, XGPIOB_3); // GP26 (ADC1) 43 | PINMUX_CONFIG(USB_VBUS_DET, XGPIOB_6); // GP27 (ADC2) 44 | 45 | return 0; 46 | } -------------------------------------------------------------------------------- /configs/duo256/u-boot/cvitek.h: -------------------------------------------------------------------------------- 1 | /* 2 | *VO control GPIOs 3 | */ 4 | #define VO_GPIO_RESET_PORT portb 5 | #define VO_GPIO_RESET_INDEX 5 6 | #define VO_GPIO_RESET_ACTIVE GPIO_ACTIVE_LOW 7 | #define VO_GPIO_PWM_PORT portb 8 | #define VO_GPIO_PWM_INDEX 4 9 | #define VO_GPIO_PWM_ACTIVE GPIO_ACTIVE_HIGH 10 | #define VO_GPIO_POWER_CT_PORT portb 11 | #define VO_GPIO_POWER_CT_INDEX 3 12 | #define VO_GPIO_POWER_CT_ACTIVE GPIO_ACTIVE_HIGH 13 | -------------------------------------------------------------------------------- /configs/duo256/u-boot/defconfig: -------------------------------------------------------------------------------- 1 | CONFIG_RISCV=y 2 | CONFIG_SYS_MALLOC_F_LEN=0x2000 3 | CONFIG_NR_DRAM_BANKS=1 4 | CONFIG_DEFAULT_DEVICE_TREE="cv181x_asic" 5 | CONFIG_IDENT_STRING=" cvitek_cv181x" 6 | CONFIG_ARCH_RV64I=y 7 | CONFIG_RISCV_SMODE=y 8 | CONFIG_TARGET_CVITEK_CV181X=y 9 | CONFIG_DISTRO_DEFAULTS=y 10 | CONFIG_FIT=y 11 | # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set 12 | CONFIG_BOOTDELAY=1 13 | CONFIG_SYS_PROMPT="cv181x_c906# " 14 | # CONFIG_CMD_CONSOLE is not set 15 | # CONFIG_CMD_XIMG is not set 16 | # CONFIG_CMD_EDITENV is not set 17 | # CONFIG_CMD_CRC32 is not set 18 | # CONFIG_CMD_LZMADEC is not set 19 | # CONFIG_CMD_UNLZ4 is not set 20 | # CONFIG_CMD_UNZIP is not set 21 | # CONFIG_CMD_LOADS is not set 22 | CONFIG_CMD_MMC=y 23 | # CONFIG_CMD_ITEST is not set 24 | CONFIG_CMD_CACHE=y 25 | CONFIG_CMD_CVI_SD_UPDATE=y 26 | # CONFIG_ISO_PARTITION is not set 27 | # CONFIG_EFI_PARTITION is not set 28 | CONFIG_NET_RANDOM_ETHADDR=y 29 | CONFIG_MMC=y 30 | CONFIG_MMC_SDHCI=y 31 | CONFIG_MMC_SDHCI_SDMA=y 32 | CONFIG_MMC_SDHCI_CVITEK=y 33 | CONFIG_MTD=y 34 | # CONFIG_PHY_SMSC is not set 35 | CONFIG_DM_ETH=y 36 | CONFIG_ETH_DESIGNWARE=y 37 | CONFIG_PHY_CVITEK=y 38 | CONFIG_SYS_NS16550=y 39 | CONFIG_SPI=y 40 | CONFIG_LZ4=y 41 | CONFIG_LZMA=y 42 | # CONFIG_TOOLS_LIBCRYPTO is not set 43 | CONFIG_ENV_IS_IN_FAT=y 44 | CONFIG_ENV_FAT_INTERFACE="mmc" 45 | CONFIG_ENV_FAT_DEVICE_AND_PART="0" 46 | CONFIG_ENV_FAT_FILE="uboot.env" 47 | -------------------------------------------------------------------------------- /configs/duos/dts/cv181x_milkv_duos_emmc.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | #include "cv181x_base_riscv.dtsi" 3 | #include "cv181x_asic_bga.dtsi" 4 | #include "cv181x_asic_emmc.dtsi" 5 | #include "cv181x_default_memmap.dtsi" 6 | 7 | #include "dt-bindings/leds/common.h" 8 | #ifndef __UBOOT__ 9 | #include 10 | #endif 11 | 12 | 13 | &mipi_rx{ 14 | snsr-reset = <&portc 17 GPIO_ACTIVE_LOW>, <&portc 17 GPIO_ACTIVE_LOW>, <&portc 17 GPIO_ACTIVE_LOW>; 15 | }; 16 | 17 | &dac{ 18 | /delete-property/ mute-gpio-l; 19 | /delete-property/ mute-gpio-r; 20 | }; 21 | 22 | &i2c0 { 23 | status = "disabled"; 24 | }; 25 | 26 | &spi3 { 27 | status = "okay"; 28 | 29 | spidev@0 { 30 | status = "okay"; 31 | }; 32 | }; 33 | 34 | &usb { 35 | vbus-gpio = <&portb 6 0>; 36 | }; 37 | 38 | &wifisd { 39 | status = "okay"; 40 | cap-sd-highspeed; 41 | sd-uhs-sdr25; 42 | sd-uhs-ddr50; 43 | sd-uhs-sdr104; 44 | min-frequency = <400000>; 45 | max-frequency = <187500000>; 46 | }; 47 | 48 | &wifi_pin { 49 | compatible = "cvitek,wifi-pin"; 50 | poweron-gpio = <&porta 15 GPIO_ACTIVE_HIGH>; 51 | wakeup-gpio = <&porte 7 GPIO_ACTIVE_HIGH>; 52 | }; 53 | 54 | &uart4 { 55 | status = "okay"; 56 | }; 57 | 58 | &soc_thermal_0 { 59 | cooling-maps { 60 | map0 { 61 | trip = <&soc_thermal_trip_0>; 62 | cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT 1>; 63 | }; 64 | map1 { 65 | trip = <&soc_thermal_trip_1>; 66 | cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; 67 | }; 68 | }; 69 | }; 70 | 71 | &porta { 72 | wifi_pwr { 73 | gpio-hog; 74 | gpios = <15 GPIO_ACTIVE_HIGH>; 75 | output-high; 76 | }; 77 | }; 78 | 79 | / { 80 | model = "Milk-V DuoS"; 81 | 82 | /delete-node/ wifi_pin; 83 | /delete-node/ bt_pin; 84 | 85 | leds { 86 | compatible = "gpio-leds"; 87 | led0 { 88 | gpios = <&porta 29 GPIO_ACTIVE_LOW>; 89 | linux,default-trigger = "heartbeat"; 90 | function = LED_FUNCTION_HEARTBEAT; 91 | label = "blue"; 92 | }; 93 | led1 { 94 | gpios = <&porte 6 GPIO_ACTIVE_HIGH>; 95 | linux,default-trigger = "netdev"; 96 | function = LED_FUNCTION_HEARTBEAT; 97 | label = "orange"; 98 | }; 99 | led2 { 100 | gpios = <&porte 8 GPIO_ACTIVE_HIGH>; 101 | linux,default-trigger = "stmmac-0:00:link"; 102 | function = LED_FUNCTION_HEARTBEAT; 103 | label = "green"; 104 | }; 105 | }; 106 | 107 | 108 | #ifndef __UBOOT__ 109 | mbox: mbox@0x01900000 { 110 | compatible = "cvitek,sg200x-mailbox"; 111 | reg = <0x0 0x01900000 0x0 0x1000>; 112 | reg-names = "mailbox"; 113 | interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; 114 | interrupt-parent = <&plic0>; 115 | status = "okay"; 116 | #mbox-cells = <4>; 117 | }; 118 | 119 | cv181x-c906_1 { 120 | compatible = "cvitek,cv181x-c906_1"; 121 | memory-region = <&fast_image &vdev0vring0 &vdev0vring1 &vdev0buffer>; 122 | firmware = "c906-mcu.elf"; 123 | resets = <&rst RST_C906_1>; 124 | reset-names = "sw_reset"; 125 | clocks = <&clk CV181X_CLK_C906_1>; 126 | clock-names = "clk_c906_1"; 127 | mboxes = <&mbox 0 CVITEK_MBOX_DIRECTION_TX CVITEK_MBOX_C906_1 1>, <&mbox 1 CVITEK_MBOX_DIRECTION_RX CVITEK_MBOX_C906_1 1>; 128 | mbox-names = "vq_tx", "vq_rx"; 129 | status = "okay"; 130 | }; 131 | #endif 132 | 133 | }; 134 | 135 | -------------------------------------------------------------------------------- /configs/duos/dts/cv181x_milkv_duos_sd.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | #include "cv181x_base_riscv.dtsi" 3 | #include "cv181x_asic_bga.dtsi" 4 | #include "cv181x_asic_sd.dtsi" 5 | #include "cv181x_default_memmap.dtsi" 6 | 7 | #include "dt-bindings/leds/common.h" 8 | #ifndef __UBOOT__ 9 | #include 10 | #endif 11 | 12 | 13 | &mipi_rx{ 14 | snsr-reset = <&portc 17 GPIO_ACTIVE_LOW>, <&portc 17 GPIO_ACTIVE_LOW>, <&portc 17 GPIO_ACTIVE_LOW>; 15 | }; 16 | 17 | &dac{ 18 | /delete-property/ mute-gpio-l; 19 | /delete-property/ mute-gpio-r; 20 | }; 21 | 22 | &i2c0 { 23 | status = "disabled"; 24 | }; 25 | 26 | &spi3 { 27 | status = "okay"; 28 | 29 | spidev@0 { 30 | status = "okay"; 31 | }; 32 | }; 33 | 34 | &usb { 35 | vbus-gpio = <&portb 6 0>; 36 | }; 37 | 38 | &wifisd { 39 | status = "okay"; 40 | cap-sd-highspeed; 41 | sd-uhs-sdr25; 42 | sd-uhs-ddr50; 43 | sd-uhs-sdr104; 44 | min-frequency = <400000>; 45 | max-frequency = <187500000>; 46 | }; 47 | 48 | &wifi_pin { 49 | compatible = "cvitek,wifi-pin"; 50 | poweron-gpio = <&porta 15 GPIO_ACTIVE_HIGH>; 51 | wakeup-gpio = <&porte 7 GPIO_ACTIVE_HIGH>; 52 | }; 53 | 54 | &uart4 { 55 | status = "okay"; 56 | }; 57 | 58 | &soc_thermal_0 { 59 | cooling-maps { 60 | map0 { 61 | trip = <&soc_thermal_trip_0>; 62 | cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT 1>; 63 | }; 64 | map1 { 65 | trip = <&soc_thermal_trip_1>; 66 | cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; 67 | }; 68 | }; 69 | }; 70 | 71 | &porta { 72 | wifi_pwr { 73 | gpio-hog; 74 | gpios = <15 GPIO_ACTIVE_HIGH>; 75 | output-high; 76 | }; 77 | }; 78 | 79 | / { 80 | model = "Milk-V DuoS"; 81 | 82 | /delete-node/ wifi_pin; 83 | /delete-node/ bt_pin; 84 | 85 | leds { 86 | compatible = "gpio-leds"; 87 | led0 { 88 | gpios = <&porta 29 GPIO_ACTIVE_LOW>; 89 | linux,default-trigger = "heartbeat"; 90 | function = LED_FUNCTION_HEARTBEAT; 91 | label = "blue"; 92 | }; 93 | led1 { 94 | gpios = <&porte 6 GPIO_ACTIVE_HIGH>; 95 | linux,default-trigger = "netdev"; 96 | function = LED_FUNCTION_HEARTBEAT; 97 | label = "orange"; 98 | }; 99 | led2 { 100 | gpios = <&porte 8 GPIO_ACTIVE_HIGH>; 101 | linux,default-trigger = "stmmac-0:00:link"; 102 | function = LED_FUNCTION_HEARTBEAT; 103 | label = "green"; 104 | }; 105 | }; 106 | 107 | 108 | #ifndef __UBOOT__ 109 | mbox: mbox@0x01900000 { 110 | compatible = "cvitek,sg200x-mailbox"; 111 | reg = <0x0 0x01900000 0x0 0x1000>; 112 | reg-names = "mailbox"; 113 | interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; 114 | interrupt-parent = <&plic0>; 115 | status = "okay"; 116 | #mbox-cells = <4>; 117 | }; 118 | 119 | cv181x-c906_1 { 120 | compatible = "cvitek,cv181x-c906_1"; 121 | memory-region = <&fast_image &vdev0vring0 &vdev0vring1 &vdev0buffer>; 122 | firmware = "c906-mcu.elf"; 123 | resets = <&rst RST_C906_1>; 124 | reset-names = "sw_reset"; 125 | clocks = <&clk CV181X_CLK_C906_1>; 126 | clock-names = "clk_c906_1"; 127 | mboxes = <&mbox 0 CVITEK_MBOX_DIRECTION_TX CVITEK_MBOX_C906_1 1>, <&mbox 1 CVITEK_MBOX_DIRECTION_RX CVITEK_MBOX_C906_1 1>; 128 | mbox-names = "vq_tx", "vq_rx"; 129 | status = "okay"; 130 | }; 131 | #endif 132 | 133 | }; 134 | 135 | -------------------------------------------------------------------------------- /configs/duos/memmap.py: -------------------------------------------------------------------------------- 1 | SIZE_1M = 0x100000 2 | SIZE_1K = 1024 3 | 4 | 5 | # Only attributes in class MemoryMap are generated to .h 6 | class MemoryMap: 7 | # No prefix "CVIMMAP_" for the items in _no_prefix[] 8 | _no_prefix = [ 9 | "CONFIG_SYS_TEXT_BASE" # u-boot's CONFIG_SYS_TEXT_BASE is used without CPP. 10 | ] 11 | 12 | DRAM_BASE = 0x80000000 13 | DRAM_SIZE = 512 * SIZE_1M 14 | 15 | # ============== 16 | # C906L FreeRTOS 17 | # ============== 18 | FREERTOS_SIZE = 2 * SIZE_1M 19 | # FreeRTOS is at the end of DRAM 20 | FREERTOS_ADDR = DRAM_BASE + DRAM_SIZE - FREERTOS_SIZE 21 | FSBL_C906L_START_ADDR = FREERTOS_ADDR 22 | 23 | # ============================== 24 | # OpenSBI | arm-trusted-firmware 25 | # ============================== 26 | # Monitor is at the begining of DRAM 27 | MONITOR_ADDR = DRAM_BASE 28 | 29 | ATF_SIZE = 512 * SIZE_1K 30 | OPENSBI_SIZE = 512 * SIZE_1K 31 | OPENSBI_FDT_ADDR = MONITOR_ADDR + OPENSBI_SIZE 32 | 33 | # ========================= 34 | # memory@DRAM_BASE in .dts. 35 | # ========================= 36 | # Ignore the area of FreeRTOS in u-boot and kernel 37 | KERNEL_MEMORY_ADDR = DRAM_BASE 38 | KERNEL_MEMORY_SIZE = DRAM_SIZE - FREERTOS_SIZE 39 | 40 | # ================= 41 | # Multimedia buffer. Used by u-boot/kernel/FreeRTOS 42 | # ================= 43 | ION_SIZE = 0 * SIZE_1M 44 | H26X_BITSTREAM_SIZE = 0 * SIZE_1M 45 | H26X_ENC_BUFF_SIZE = 0 46 | ISP_MEM_BASE_SIZE = 0 * SIZE_1M 47 | FREERTOS_RESERVED_ION_SIZE = H26X_BITSTREAM_SIZE + H26X_ENC_BUFF_SIZE + ISP_MEM_BASE_SIZE 48 | 49 | # ION after FreeRTOS 50 | ION_ADDR = FREERTOS_ADDR - ION_SIZE 51 | 52 | # Buffers of the fast image are inside the ION buffer 53 | H26X_BITSTREAM_ADDR = ION_ADDR 54 | H26X_ENC_BUFF_ADDR = H26X_BITSTREAM_ADDR + H26X_BITSTREAM_SIZE 55 | ISP_MEM_BASE_ADDR = H26X_ENC_BUFF_ADDR + H26X_ENC_BUFF_SIZE 56 | 57 | assert ISP_MEM_BASE_ADDR + ISP_MEM_BASE_SIZE <= ION_ADDR + ION_SIZE 58 | 59 | # Boot logo is after the ION buffer 60 | # Framebuffer uses boot logo's reserved memory 61 | BOOTLOGO_SIZE = 1800 * SIZE_1K 62 | BOOTLOGO_ADDR = ION_ADDR - BOOTLOGO_SIZE 63 | FRAMEBUFFER_SIZE = BOOTLOGO_SIZE 64 | FRAMEBUFFER_ADDR = BOOTLOGO_ADDR 65 | 66 | # =================== 67 | # FSBL and u-boot-2021 68 | # =================== 69 | CVI_UPDATE_HEADER_SIZE = SIZE_1K 70 | UIMAG_SIZE = 16 * SIZE_1M 71 | 72 | # kernel image loading buffer 73 | UIMAG_ADDR = DRAM_BASE + 24 * SIZE_1M 74 | CVI_UPDATE_HEADER_ADDR = UIMAG_ADDR - CVI_UPDATE_HEADER_SIZE 75 | 76 | # FSBL decompress buffer 77 | FSBL_UNZIP_ADDR = UIMAG_ADDR 78 | FSBL_UNZIP_SIZE = UIMAG_SIZE 79 | 80 | assert UIMAG_ADDR + UIMAG_SIZE <= BOOTLOGO_ADDR 81 | 82 | # u-boot's run address and entry point 83 | CONFIG_SYS_TEXT_BASE = DRAM_BASE + 2 * SIZE_1M 84 | # u-boot's init stack point is only used before board_init_f() 85 | CONFIG_SYS_INIT_SP_ADDR = UIMAG_ADDR + UIMAG_SIZE 86 | -------------------------------------------------------------------------------- /configs/duos/partition_emmc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /configs/duos/partition_sd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /configs/duos/settings.mk: -------------------------------------------------------------------------------- 1 | CHIP=cv181x 2 | STORAGE_TYPE?=sd 3 | UBOOT_CHIP=cv181x 4 | UBOOT_BOARD=milkv_duos_$(STORAGE_TYPE) 5 | BOOT_CPU=riscv 6 | ARCH=riscv 7 | DDR_CFG=ddr3_1866_x16 8 | PARTITION_FILE=partition_$(STORAGE_TYPE).xml 9 | 10 | PACKAGES += " duo-pinmux wireless-regdb wpasupplicant cvi-pinmux-cv181x bluez" 11 | 12 | IMAGE_ADDITIONS += "aic8800-firmware" 13 | IMAGE_ADDITIONS += "ethernet-leds" 14 | IMAGE_ADDITIONS += "usb-switch" 15 | IMAGE_ADDITIONS += "hciattach-service" -------------------------------------------------------------------------------- /configs/duos/u-boot/cvi_board_init.c: -------------------------------------------------------------------------------- 1 | static void set_rtc_register_for_power(void) 2 | { 3 | printf("set_rtc_register_for_power\n"); 4 | mmio_write_32(0x050260D0, 0x7); 5 | } 6 | 7 | int cvi_board_init(void) 8 | { 9 | // Camera 10 | PINMUX_CONFIG(CAM_MCLK0, CAM_MCLK0); 11 | PINMUX_CONFIG(IIC3_SCL, IIC3_SCL); 12 | PINMUX_CONFIG(IIC3_SDA, IIC3_SDA); 13 | PINMUX_CONFIG(PAD_MIPIRX4P, XGPIOC_3); 14 | PINMUX_CONFIG(PAD_MIPIRX4N, XGPIOC_2); 15 | 16 | // LED 17 | PINMUX_CONFIG(IIC0_SDA, XGPIOA_29); 18 | 19 | // I2C4 20 | // PINMUX_CONFIG(VIVO_D1, IIC4_SCL); 21 | // PINMUX_CONFIG(VIVO_D0, IIC4_SDA); 22 | 23 | // SPI3 24 | PINMUX_CONFIG(VIVO_D8, SPI3_SDO); 25 | PINMUX_CONFIG(VIVO_D7, SPI3_SDI); 26 | PINMUX_CONFIG(VIVO_D6, SPI3_SCK); 27 | PINMUX_CONFIG(VIVO_D5, SPI3_CS_X); 28 | 29 | // USB 30 | PINMUX_CONFIG(USB_VBUS_EN, XGPIOB_5); 31 | PINMUX_CONFIG(AUX0, XGPIOA_30); 32 | 33 | // WIFI/BT 34 | PINMUX_CONFIG(CLK32K, PWR_GPIO_10); 35 | PINMUX_CONFIG(UART2_RX, UART4_RX); 36 | PINMUX_CONFIG(UART2_TX, UART4_TX); 37 | PINMUX_CONFIG(UART2_CTS, UART4_CTS); 38 | PINMUX_CONFIG(UART2_RTS, UART4_RTS); 39 | 40 | // GPIOs 41 | PINMUX_CONFIG(JTAG_CPU_TCK, XGPIOA_18); 42 | PINMUX_CONFIG(JTAG_CPU_TMS, XGPIOA_19); 43 | PINMUX_CONFIG(JTAG_CPU_TRST, XGPIOA_20); 44 | PINMUX_CONFIG(IIC0_SCL, XGPIOA_28); 45 | 46 | // EPHY LEDs controlled by linux led triggers 47 | PINMUX_CONFIG(PWR_WAKEUP0, PWR_GPIO_6); 48 | PINMUX_CONFIG(PWR_BUTTON1, PWR_GPIO_8); 49 | 50 | set_rtc_register_for_power(); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /configs/duos/u-boot/cvitek.h: -------------------------------------------------------------------------------- 1 | /* 2 | *VO control GPIOs 3 | */ 4 | #define VO_GPIO_RESET_PORT portb 5 | #define VO_GPIO_RESET_INDEX 5 6 | #define VO_GPIO_RESET_ACTIVE GPIO_ACTIVE_LOW 7 | #define VO_GPIO_PWM_PORT portb 8 | #define VO_GPIO_PWM_INDEX 4 9 | #define VO_GPIO_PWM_ACTIVE GPIO_ACTIVE_HIGH 10 | #define VO_GPIO_POWER_CT_PORT portb 11 | #define VO_GPIO_POWER_CT_INDEX 3 12 | #define VO_GPIO_POWER_CT_ACTIVE GPIO_ACTIVE_HIGH 13 | -------------------------------------------------------------------------------- /configs/duos/u-boot/defconfig: -------------------------------------------------------------------------------- 1 | CONFIG_RISCV=y 2 | CONFIG_SYS_MALLOC_F_LEN=0x2000 3 | CONFIG_NR_DRAM_BANKS=1 4 | CONFIG_DEFAULT_DEVICE_TREE="cv181x_asic" 5 | CONFIG_IDENT_STRING=" cvitek_cv181x" 6 | CONFIG_ARCH_RV64I=y 7 | CONFIG_RISCV_SMODE=y 8 | CONFIG_TARGET_CVITEK_CV181X=y 9 | CONFIG_DISTRO_DEFAULTS=y 10 | # CONFIG_ANDROID_BOOT_IMAGE is not set 11 | CONFIG_FIT=y 12 | # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set 13 | CONFIG_BOOTDELAY=1 14 | CONFIG_SYS_PROMPT="cv181x_c906# " 15 | CONFIG_CMD_CONFIG=y 16 | # CONFIG_CMD_CONSOLE is not set 17 | CONFIG_CMD_SBI=y 18 | # CONFIG_CMD_XIMG is not set 19 | # CONFIG_CMD_EDITENV is not set 20 | # CONFIG_CMD_CRC32 is not set 21 | # CONFIG_CMD_LZMADEC is not set 22 | # CONFIG_CMD_UNLZ4 is not set 23 | # CONFIG_CMD_UNZIP is not set 24 | # CONFIG_CMD_LOADS is not set 25 | CONFIG_CMD_MMC=y 26 | # CONFIG_CMD_ITEST is not set 27 | CONFIG_CMD_CACHE=y 28 | # CONFIG_ISO_PARTITION is not set 29 | # CONFIG_EFI_PARTITION is not set 30 | CONFIG_ENV_IS_IN_FAT=y 31 | CONFIG_ENV_FAT_DEVICE_AND_PART="0" 32 | CONFIG_NET_RANDOM_ETHADDR=y 33 | CONFIG_UDP_FUNCTION_FASTBOOT=y 34 | CONFIG_FASTBOOT_BUF_ADDR=0x84000000 35 | CONFIG_FASTBOOT_FLASH=y 36 | CONFIG_FASTBOOT_FLASH_MMC_DEV=0 37 | CONFIG_MMC=y 38 | CONFIG_SUPPORT_EMMC_RPMB=y 39 | CONFIG_SUPPORT_EMMC_BOOT=y 40 | CONFIG_MMC_SDHCI=y 41 | CONFIG_MMC_SDHCI_SDMA=y 42 | CONFIG_MMC_SDHCI_CVITEK=y 43 | CONFIG_MTD=y 44 | CONFIG_PHY_CVITEK=y 45 | CONFIG_DM_ETH=y 46 | CONFIG_ETH_DESIGNWARE=y 47 | CONFIG_SYS_NS16550=y 48 | CONFIG_SPI=y 49 | CONFIG_LZ4=y 50 | CONFIG_LZMA=y 51 | # CONFIG_TOOLS_LIBCRYPTO is not set 52 | -------------------------------------------------------------------------------- /configs/licheervnano/dts/sg2002_licheervnano_sd.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | #include "sg200x_base_riscv.dtsi" 3 | #include "sg200x_asic_qfn.dtsi" 4 | #include "sg200x_asic_sd.dtsi" 5 | #include "sg200x_default_memmap.dtsi" 6 | 7 | #include 8 | #include 9 | #include 10 | #ifndef __UBOOT__ 11 | #include 12 | #endif 13 | 14 | &sd { 15 | min-frequency = <400000>; // 400Khz 16 | //max-frequency = <50000000>; // 50Mhz 17 | max-frequency = <25000000>; // 25Mhz 18 | //max-frequency = <10000000>; // 10Mhz 19 | //max-frequency = <5000000>; // 5Mhz 20 | }; 21 | 22 | 23 | &uart1 { 24 | status = "okay"; 25 | }; 26 | 27 | 28 | &i2c4 { 29 | statuc = "okay"; 30 | gt9xx: gt9xx@14 { 31 | compatible = "goodix,gt911"; 32 | reg = <0x14>; 33 | interrupts = <3 0 IRQ_TYPE_EDGE_FALLING>; 34 | interrupt-parent = <&porte>; 35 | irq-gpios= <&porte 3 0>; 36 | reset-gpios = <&porte 4 0>; 37 | status = "okay"; 38 | }; 39 | }; 40 | 41 | &dac { 42 | status = "okay"; 43 | /delete-property/ mute-gpio-r; 44 | }; 45 | 46 | &soc_thermal_0 { 47 | cooling-maps { 48 | map0 { 49 | trip = <&soc_thermal_trip_0>; 50 | cooling-device = <&cooling THERMAL_NO_LIMIT 1>; 51 | }; 52 | map1 { 53 | trip = <&soc_thermal_trip_1>; 54 | cooling-device = <&cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; 55 | }; 56 | }; 57 | }; 58 | 59 | / { 60 | model = "LicheeRv Nano"; 61 | 62 | /delete-node/ wifi_pin; 63 | /delete-node/ bt_pin; 64 | 65 | gpio-keys { 66 | compatible = "gpio-keys"; 67 | key-user { 68 | label = "User Key"; 69 | linux,code = ; 70 | debounce-interval = <1>; 71 | gpios = <&porta 30 1>; 72 | }; 73 | }; 74 | 75 | wifisd:wifi-sd@4320000 { 76 | compatible = "cvitek,cv181x-sdio"; 77 | bus-width = <4>; 78 | reg = <0x0 0x4320000 0x0 0x1000>; 79 | reg_names = "core_mem"; 80 | src-frequency = <375000000>; 81 | min-frequency = <400000>; // 400Khz 82 | //max-frequency = <50000000>; // 50Mhz 83 | //max-frequency = <45000000>; // 45Mhz 84 | //max-frequency = <40000000>; // 40Mhz 85 | //max-frequency = <35000000>; // 35Mhz 86 | //max-frequency = <30000000>; // 30Mhz 87 | max-frequency = <25000000>; // 25Mhz 88 | //max-frequency = <20000000>; // 20Mhz 89 | //max-frequency = <15000000>; // 15Mhz 90 | //max-frequency = <10000000>; // 10Mhz 91 | //max-frequency = <5000000>; // 5Mhz 92 | 64_addressing; 93 | reset_tx_rx_phy; 94 | non-removable; 95 | pll_index = <0x7>; 96 | pll_reg = <0x300207C>; 97 | no-mmc; 98 | no-sd; 99 | status = "okay"; 100 | interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; 101 | interrupt-parent = <&plic0>; 102 | }; 103 | 104 | leds { 105 | compatible = "gpio-leds"; 106 | led0 { 107 | gpios = <&porta 14 GPIO_ACTIVE_LOW>; 108 | linux,default-trigger = "heartbeat"; 109 | function = LED_FUNCTION_HEARTBEAT; 110 | }; 111 | }; 112 | #ifndef __UBOOT__ 113 | mbox: mbox@0x01900000 { 114 | compatible = "cvitek,sg200x-mailbox"; 115 | reg = <0x0 0x01900000 0x0 0x1000>; 116 | reg-names = "mailbox"; 117 | interrupts = <101 IRQ_TYPE_LEVEL_HIGH>; 118 | interrupt-parent = <&plic0>; 119 | status = "okay"; 120 | #mbox-cells = <4>; 121 | }; 122 | 123 | cv181x-c906_1 { 124 | compatible = "cvitek,cv181x-c906_1"; 125 | memory-region = <&fast_image &vdev0vring0 &vdev0vring1 &vdev0buffer>; 126 | firmware = "c906-mcu.elf"; 127 | resets = <&rst RST_C906_1>; 128 | reset-names = "sw_reset"; 129 | clocks = <&clk CV181X_CLK_C906_1>; 130 | clock-names = "clk_c906_1"; 131 | mboxes = <&mbox 0 CVITEK_MBOX_DIRECTION_TX CVITEK_MBOX_C906_1 1>, <&mbox 1 CVITEK_MBOX_DIRECTION_RX CVITEK_MBOX_C906_1 1>; 132 | mbox-names = "vq_tx", "vq_rx"; 133 | status = "okay"; 134 | }; 135 | #endif 136 | }; 137 | 138 | -------------------------------------------------------------------------------- /configs/licheervnano/memmap.py: -------------------------------------------------------------------------------- 1 | SIZE_1M = 0x100000 2 | SIZE_1K = 1024 3 | 4 | 5 | # Only attributes in class MemoryMap are generated to .h 6 | class MemoryMap: 7 | # No prefix "CVIMMAP_" for the items in _no_prefix[] 8 | _no_prefix = [ 9 | "CONFIG_SYS_TEXT_BASE" # u-boot's CONFIG_SYS_TEXT_BASE is used without CPP. 10 | ] 11 | 12 | DRAM_BASE = 0x80000000 13 | DRAM_SIZE = 256 * SIZE_1M 14 | 15 | # ============== 16 | # C906L FreeRTOS 17 | # ============== 18 | FREERTOS_SIZE = 2 * SIZE_1M 19 | # FreeRTOS is at the end of DRAM 20 | FREERTOS_ADDR = DRAM_BASE + DRAM_SIZE - FREERTOS_SIZE 21 | FSBL_C906L_START_ADDR = FREERTOS_ADDR 22 | 23 | # ============================== 24 | # OpenSBI | arm-trusted-firmware 25 | # ============================== 26 | # Monitor is at the begining of DRAM 27 | MONITOR_ADDR = DRAM_BASE 28 | 29 | ATF_SIZE = 512 * SIZE_1K 30 | OPENSBI_SIZE = 512 * SIZE_1K 31 | OPENSBI_FDT_ADDR = MONITOR_ADDR + OPENSBI_SIZE 32 | 33 | # ========================= 34 | # memory@DRAM_BASE in .dts. 35 | # ========================= 36 | # Ignore the area of FreeRTOS in u-boot and kernel 37 | KERNEL_MEMORY_ADDR = DRAM_BASE 38 | KERNEL_MEMORY_SIZE = DRAM_SIZE - FREERTOS_SIZE 39 | 40 | # ================= 41 | # Multimedia buffer. Used by u-boot/kernel/FreeRTOS 42 | # ================= 43 | ION_SIZE = 0 * SIZE_1M 44 | H26X_BITSTREAM_SIZE = 0 * SIZE_1M 45 | H26X_ENC_BUFF_SIZE = 0 46 | ISP_MEM_BASE_SIZE = 0 * SIZE_1M 47 | FREERTOS_RESERVED_ION_SIZE = H26X_BITSTREAM_SIZE + H26X_ENC_BUFF_SIZE + ISP_MEM_BASE_SIZE 48 | 49 | # ION after FreeRTOS 50 | ION_ADDR = FREERTOS_ADDR - ION_SIZE 51 | 52 | # Buffers of the fast image are inside the ION buffer 53 | H26X_BITSTREAM_ADDR = ION_ADDR 54 | H26X_ENC_BUFF_ADDR = H26X_BITSTREAM_ADDR + H26X_BITSTREAM_SIZE 55 | ISP_MEM_BASE_ADDR = H26X_ENC_BUFF_ADDR + H26X_ENC_BUFF_SIZE 56 | 57 | assert ISP_MEM_BASE_ADDR + ISP_MEM_BASE_SIZE <= ION_ADDR + ION_SIZE 58 | 59 | # Boot logo is after the ION buffer 60 | # Framebuffer uses boot logo's reserved memory 61 | BOOTLOGO_SIZE = 8000 * SIZE_1K 62 | BOOTLOGO_ADDR = ION_ADDR - BOOTLOGO_SIZE 63 | FRAMEBUFFER_SIZE = BOOTLOGO_SIZE 64 | FRAMEBUFFER_ADDR = BOOTLOGO_ADDR 65 | 66 | # =================== 67 | # FSBL and u-boot-2021 68 | # =================== 69 | CVI_UPDATE_HEADER_SIZE = SIZE_1K 70 | UIMAG_SIZE = 16 * SIZE_1M 71 | 72 | # kernel image loading buffer 73 | UIMAG_ADDR = DRAM_BASE + 24 * SIZE_1M 74 | CVI_UPDATE_HEADER_ADDR = UIMAG_ADDR - CVI_UPDATE_HEADER_SIZE 75 | 76 | # FSBL decompress buffer 77 | FSBL_UNZIP_ADDR = UIMAG_ADDR 78 | FSBL_UNZIP_SIZE = UIMAG_SIZE 79 | 80 | assert UIMAG_ADDR + UIMAG_SIZE <= BOOTLOGO_ADDR 81 | 82 | # u-boot's run address and entry point 83 | CONFIG_SYS_TEXT_BASE = DRAM_BASE + 2 * SIZE_1M 84 | # u-boot's init stack point is only used before board_init_f() 85 | CONFIG_SYS_INIT_SP_ADDR = UIMAG_ADDR + UIMAG_SIZE 86 | -------------------------------------------------------------------------------- /configs/licheervnano/partition_sd.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /configs/licheervnano/patches/fsbl/0002-add-debug-mode.patch: -------------------------------------------------------------------------------- 1 | From 0e02a58c09c8f520838e372578b14d979a737d18 Mon Sep 17 00:00:00 2001 2 | From: Justin Hammond 3 | Date: Thu, 18 Apr 2024 13:38:27 +0000 4 | Subject: [PATCH] add debug mode 5 | 6 | --- 7 | plat/sg200x/bl2/bl2_opt.c | 15 +++++++++++++++ 8 | 1 file changed, 15 insertions(+) 9 | 10 | diff --git a/plat/sg200x/bl2/bl2_opt.c b/plat/sg200x/bl2/bl2_opt.c 11 | index c73fa55..013d5de 100644 12 | --- a/plat/sg200x/bl2/bl2_opt.c 13 | +++ b/plat/sg200x/bl2/bl2_opt.c 14 | @@ -419,6 +419,21 @@ retry_from_flash: 15 | 16 | switch_rtc_mode_2nd_stage(); 17 | 18 | + if (!(mmio_read_32(GPIO_BASE + 0x050) & (1 << 30))) { 19 | + NOTICE("=========================================\n"); 20 | + NOTICE("|| Debug Mode ||\n"); 21 | + NOTICE("|| ||\n"); 22 | + NOTICE("=========================================\n"); 23 | + 24 | + mmio_setbits_32(0x3003024, 1 << 6); /* reset the small core */ 25 | + 26 | + /* pinmux was set for jtag by default */ 27 | + 28 | + while(1) 29 | + ; 30 | + } 31 | + 32 | + 33 | if (monitor_entry) { 34 | NOTICE("Jump to monitor at 0x%lx.\n", monitor_entry); 35 | jump_to_monitor(monitor_entry, loader_2nd_entry); 36 | -- 37 | 2.43.0 38 | 39 | -------------------------------------------------------------------------------- /configs/licheervnano/settings.mk: -------------------------------------------------------------------------------- 1 | CHIP=sg200x 2 | UBOOT_CHIP=sg2002 3 | UBOOT_BOARD=licheervnano_sd 4 | BOOT_CPU=riscv 5 | ARCH=riscv 6 | DDR_CFG=ddr3_1866_x16 7 | PARTITION_FILE=partition_sd.xml 8 | STORAGE_TYPE=sd 9 | 10 | PACKAGES += " wireless-regdb wpasupplicant cvi-pinmux-cv181x" 11 | 12 | IMAGE_ADDITIONS += "aic8800-firmware" -------------------------------------------------------------------------------- /configs/licheervnano/u-boot/cvi_board_init.c: -------------------------------------------------------------------------------- 1 | __attribute__((optimize("O0"))) 2 | // 1.26ms 3 | void suck_loop(uint64_t loop) { 4 | loop = loop * 50 * 100; 5 | uint64_t a; 6 | while (loop > 0) { 7 | a = loop / (uint64_t)99; 8 | a = loop / (uint64_t)77; 9 | a = loop / (uint64_t)55; 10 | a = loop / (uint64_t)33; 11 | a = loop / (uint64_t)11; 12 | a = loop / (uint64_t)999; 13 | a = loop / (uint64_t)777; 14 | a = loop / (uint64_t)555; 15 | a = loop / (uint64_t)333; 16 | a = loop / (uint64_t)111; 17 | a = loop / (uint64_t)9999; 18 | a = loop / (uint64_t)7777; 19 | a = loop / (uint64_t)5555; 20 | a = loop / (uint64_t)3333; 21 | a = loop / (uint64_t)1111; 22 | a = loop / (uint64_t)99999; 23 | a = loop / (uint64_t)77777; 24 | a = loop / (uint64_t)55555; 25 | a = loop / (uint64_t)33333; 26 | a = loop / (uint64_t)11111; 27 | loop--; 28 | } 29 | } 30 | 31 | int cvi_board_init(void) 32 | { 33 | uint32_t val; 34 | 35 | // wifi power reset 36 | mmio_write_32(0x0300104C, 0x3); // GPIOA 26 37 | val = mmio_read_32(0x03020004); // GPIOA DIR 38 | val |= (1 << 26); // output 39 | mmio_write_32(0x03020004, val); 40 | 41 | val = mmio_read_32(0x03020000); // signal level 42 | val &= ~(1 << 26); // set level to low 43 | mmio_write_32(0x03020000, val); 44 | 45 | suck_loop(200); 46 | 47 | val = mmio_read_32(0x03020000); // signal level 48 | val |= (1 << 26); // set level to high 49 | mmio_write_32(0x03020000, val); 50 | 51 | // wifi sdio pinmux 52 | mmio_write_32(0x030010D0, 0x0); // D3 53 | mmio_write_32(0x030010D4, 0x0); // D2 54 | mmio_write_32(0x030010D8, 0x0); // D1 55 | mmio_write_32(0x030010DC, 0x0); // D0 56 | mmio_write_32(0x030010E0, 0x0); // CMD 57 | mmio_write_32(0x030010E4, 0x0); // CLK 58 | 59 | // LED 60 | //mmio_write_32(0x03001038, 0x3); // SD0_PWR_EN/XGPIOA_14 61 | PINMUX_CONFIG(SD0_PWR_EN, XGPIOA_14); 62 | 63 | // uart bluetooth 64 | //mmio_write_32(0x03001070, 0x1); // GPIOA 28 UART1 TX 65 | //mmio_write_32(0x03001074, 0x1); // GPIOA 29 UART1 RX 66 | //mmio_write_32(0x03001068, 0x4); // GPIOA 18 UART1 CTS 67 | //mmio_write_32(0x03001064, 0x4); // GPIOA 19 UART1 RTS 68 | 69 | // PWM 70 | //mmio_write_32(0x03001068, 0x2); // GPIOA 18 PWM 6 71 | 72 | // lcd reset 73 | mmio_write_32(0x030010A4, 0x0); // PWRGPIO 0 GPIO_MODE 74 | 75 | // lcd backlight 76 | //mmio_write_32(0x030010EC, 0x0); // GPIOB 0 PWM0_BUCK 77 | mmio_write_32(0x030010EC, 0x3); // GPIOB 0 GPIO_MODE 78 | val = mmio_read_32(0x03021004); // GPIOB DIR 79 | val |= (1 << 0); // output 80 | mmio_write_32(0x03021004, val); 81 | val = mmio_read_32(0x03021000); // signal level 82 | val |= (1 << 0); // set level to high 83 | mmio_write_32(0x03021000, val); 84 | 85 | // camera function 86 | mmio_write_32(0x0300116C, 0x5); // RX4N CAM_MCLK0 87 | 88 | // camera/tp i2c 89 | mmio_write_32(0x03001090, 0x5); // PWR_GPIO6 IIC4_SCL 90 | mmio_write_32(0x03001098, 0x5); // PWR_GPIO8 IIC4_SDA 91 | 92 | // tp function 93 | mmio_write_32(0x03001084, 0x3); // PWR_SEQ1 PWR_GPIO[3] 94 | mmio_write_32(0x03001088, 0x3); // PWR_SEQ2 PWR_GPIO[4] 95 | mmio_write_32(0x05027078, 0x11);// Unlock PWR_GPIO[3] 96 | mmio_write_32(0x0502707c, 0x11);// Unlock PWR_GPIO[4] 97 | 98 | // bitbang i2c for maixcam 99 | #ifdef MAIXCAM 100 | mmio_write_32(0x0300105C, 0x3);// GPIOA 23 GPIO_MODE 101 | mmio_write_32(0x03001060, 0x3);// GPIOA 24 GPIO_MODE 102 | #endif 103 | // wait hardware bootup 104 | suck_loop(100); 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /configs/licheervnano/u-boot/cvitek.h: -------------------------------------------------------------------------------- 1 | /* 2 | *VO control GPIOs 3 | */ 4 | #define VO_GPIO_RESET_PORT portb 5 | #define VO_GPIO_RESET_INDEX 5 6 | #define VO_GPIO_RESET_ACTIVE GPIO_ACTIVE_LOW 7 | #define VO_GPIO_PWM_PORT portb 8 | #define VO_GPIO_PWM_INDEX 4 9 | #define VO_GPIO_PWM_ACTIVE GPIO_ACTIVE_HIGH 10 | #define VO_GPIO_POWER_CT_PORT portb 11 | #define VO_GPIO_POWER_CT_INDEX 3 12 | #define VO_GPIO_POWER_CT_ACTIVE GPIO_ACTIVE_HIGH 13 | -------------------------------------------------------------------------------- /configs/licheervnano/u-boot/defconfig: -------------------------------------------------------------------------------- 1 | CONFIG_RISCV=y 2 | CONFIG_SYS_MALLOC_F_LEN=0x2000 3 | CONFIG_NR_DRAM_BANKS=1 4 | CONFIG_DM_GPIO=y 5 | CONFIG_DEFAULT_DEVICE_TREE="soph_asic" 6 | CONFIG_IDENT_STRING="LicheeRVNano" 7 | CONFIG_ARCH_RV64I=y 8 | CONFIG_RISCV_SMODE=y 9 | CONFIG_DISTRO_DEFAULTS=y 10 | CONFIG_FIT=y 11 | # CONFIG_ARCH_FIXUP_FDT_MEMORY is not set 12 | CONFIG_SD_BOOT=y 13 | CONFIG_BOOTDELAY=1 14 | CONFIG_LOGLEVEL=10 15 | # CONFIG_SYS_DEVICE_NULLDEV is not set 16 | CONFIG_DISPLAY_CPUINFO=y 17 | CONFIG_DISPLAY_BOARDINFO_LATE=y 18 | CONFIG_SYS_PROMPT="soph# " 19 | CONFIG_CMD_CONFIG=y 20 | CONFIG_CMD_SBI=y 21 | CONFIG_CMD_BOOTMENU=y 22 | # CONFIG_CMD_XIMG is not set 23 | # CONFIG_CMD_CRC32 is not set 24 | CONFIG_CMD_MEMINFO=y 25 | CONFIG_CMD_MEMTEST=y 26 | CONFIG_SYS_ALT_MEMTEST=y 27 | # CONFIG_CMD_LZMADEC is not set 28 | # CONFIG_CMD_UNLZ4 is not set 29 | # CONFIG_CMD_UNZIP is not set 30 | CONFIG_CMD_CLK=y 31 | CONFIG_CMD_DM=y 32 | CONFIG_CMD_GPIO=y 33 | CONFIG_CMD_GPT=y 34 | # CONFIG_RANDOM_UUID is not set 35 | CONFIG_CMD_I2C=y 36 | # CONFIG_CMD_LOADS is not set 37 | CONFIG_CMD_LSBLK=y 38 | CONFIG_CMD_MBR=y 39 | CONFIG_CMD_MMC=y 40 | # CONFIG_CMD_ITEST is not set 41 | CONFIG_CMD_DNS=y 42 | CONFIG_CMD_CACHE=y 43 | CONFIG_CMD_CLS=y 44 | CONFIG_CMD_DIAG=y 45 | CONFIG_CMD_LOG=y 46 | CONFIG_CMD_CVI_VO=y 47 | CONFIG_CMD_CVISOUND=y 48 | # CONFIG_CMD_CVI_UPDATE is not set 49 | # CONFIG_ISO_PARTITION is not set 50 | CONFIG_ENV_IS_IN_FAT=y 51 | CONFIG_ENV_FAT_INTERFACE="mmc" 52 | CONFIG_ENV_FAT_DEVICE_AND_PART="0" 53 | CONFIG_ENV_FAT_FILE="uboot.env" 54 | CONFIG_BOOTP_SEND_HOSTNAME=y 55 | CONFIG_NET_RANDOM_ETHADDR=y 56 | CONFIG_BUTTON=y 57 | CONFIG_BUTTON_GPIO=y 58 | CONFIG_UDP_FUNCTION_FASTBOOT=y 59 | CONFIG_FASTBOOT_BUF_ADDR=0x81800000 60 | CONFIG_FASTBOOT_BUF_SIZE=0x1000000 61 | CONFIG_FASTBOOT_FLASH=y 62 | CONFIG_FASTBOOT_FLASH_MMC_DEV=0 63 | CONFIG_DWAPB_GPIO=y 64 | CONFIG_DM_I2C=y 65 | CONFIG_SYS_I2C_DW=y 66 | CONFIG_LED=y 67 | CONFIG_LED_BLINK=y 68 | CONFIG_LED_GPIO=y 69 | CONFIG_MMC=y 70 | CONFIG_MMC_SDHCI=y 71 | CONFIG_MMC_SDHCI_SDMA=y 72 | CONFIG_MMC_SDHCI_CVITEK=y 73 | CONFIG_MTD=y 74 | CONFIG_PHY_CVITEK=y 75 | CONFIG_DM_ETH=y 76 | CONFIG_ETH_DESIGNWARE=y 77 | CONFIG_SYS_NS16550=y 78 | CONFIG_CVI_SOUND_DRIVERS=y 79 | CONFIG_SPI=y 80 | CONFIG_LZ4=y 81 | CONFIG_LZMA=y 82 | # CONFIG_TOOLS_LIBCRYPTO is not set 83 | -------------------------------------------------------------------------------- /configs/settings.mk: -------------------------------------------------------------------------------- 1 | KERNELREV="2" 2 | FSBLVERSION=1.0.0 3 | PACKAGES="ca-certificates debian-archive-keyring dosfstools binutils file tree sudo bash-completion u-boot-menu openssh-server network-manager dnsmasq-base libpam-systemd ppp libengine-pkcs11-openssl iptables systemd-timesyncd vim usbutils parted exfatprogs systemd-sysv i2c-tools net-tools ethtool avahi-utils sudo gnupg rsync gpiod u-boot-tools libubootenv-tool" 4 | 5 | IMAGE_ADDITIONS="usb-gadget" -------------------------------------------------------------------------------- /scripts/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:sid as builder 2 | 3 | ARG DEBIAN_FRONTEND=noninteractive 4 | 5 | RUN apt-get update \ 6 | && apt-get install -y eatmydata \ 7 | && eatmydata apt-get install -y --no-install-recommends \ 8 | qemu-user-static mtools sbuild-debian-developer-setup \ 9 | binfmt-support gdisk kpartx sbuild \ 10 | parted ca-certificates dh-make \ 11 | autoconf automake autotools-dev bc \ 12 | build-essential cpio curl sudo \ 13 | dosfstools e2fsprogs fdisk flex gawk \ 14 | git gperf kmod libexpat-dev \ 15 | libgmp-dev libmpc-dev libmpfr-dev libssl-dev \ 16 | libtool mmdebstrap openssl parted \ 17 | patchutils python3 python3-dev python3-distutils \ 18 | python3-setuptools swig gnupg \ 19 | systemd-container texinfo zlib1g-dev wget arch-test \ 20 | linux-image-generic genimage joe mc zip \ 21 | fakeroot git kernel-wedge quilt ccache flex bison \ 22 | libssl-dev dh-exec rsync libelf-dev bc gcc-riscv64-unknown-elf \ 23 | && git clone --depth 1 https://github.com/milkv-duo/host-tools.git /host-tools \ 24 | && rm -rf /host-tools/gcc/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-elf \ 25 | && rm -rf /host-tools/gcc/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu \ 26 | && rm -rf /host-tools/gcc/gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf 27 | 28 | 29 | 30 | 31 | FROM builder as build_image 32 | WORKDIR /builder 33 | ADD scripts/ /builder/ 34 | 35 | CMD /bin/bash 36 | -------------------------------------------------------------------------------- /scripts/addons/aic8800-firmware/addon.mk: -------------------------------------------------------------------------------- 1 | $(BUILDDIR)/aic8800-firmware-stamp: 2 | @echo "$(COLOUR_GREEN)Installing aic8800-firmware for $(BOARD)$(END_COLOUR)" 3 | @rm -rf $(BUILDDIR)/aic8800-firmware 4 | @git clone --depth 1 https://github.com/armbian/firmware.git $(BUILDDIR)/aic8800-firmware 5 | @mkdir -p /rootfs/lib/firmware/aic8800_sdio/aic8800/ 6 | @cp -a $(BUILDDIR)/aic8800-firmware/aic8800/SDIO/aic8800/ /rootfs/lib/firmware/aic8800_sdio/ 7 | # This is the DUOS firmware 8 | @cp -a $(BUILDDIR)/aic8800-firmware/aic8800/SDIO/aic8800D80/* /rootfs/lib/firmware/aic8800_sdio/aic8800/ 9 | @touch $@ 10 | -------------------------------------------------------------------------------- /scripts/addons/ethernet-leds/addon.mk: -------------------------------------------------------------------------------- 1 | $(BUILDDIR)/ethernet-leds-stamp: 2 | @echo "$(COLOUR_GREEN)Installing ethernet leds for $(BOARD)$(END_COLOUR)" 3 | @mkdir -p /rootfs/etc/systemd/system/ 4 | @cp -a addons/ethernet-leds/ethernet-leds.service /rootfs/etc/systemd/system/ 5 | @mkdir -p /rootfs/tmp/install/ 6 | @echo " ethernet-leds" >> /rootfs/tmp/install/systemd-enable 7 | @touch $@ 8 | -------------------------------------------------------------------------------- /scripts/addons/ethernet-leds/ethernet-leds.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ethernet Led Triggers 3 | After=network.target 4 | StartLimitIntervalSec=0 5 | 6 | [Service] 7 | Type=oneshot 8 | ExecStart=/bin/bash -c "/bin/echo end0 > /sys/class/leds/orange/device_name" 9 | ExecStart=/bin/bash -c "/bin/echo 1 > /sys/class/leds/orange/tx" 10 | ExecStart=/bin/bash -c "/bin/echo 1 > /sys/class/leds/orange/rx" 11 | 12 | [Install] 13 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /scripts/addons/hciattach-service/addon.mk: -------------------------------------------------------------------------------- 1 | $(BUILDDIR)/hciattach-service-stamp: 2 | @echo "$(COLOUR_GREEN)Installing hciattach systemd service for $(BOARD)$(END_COLOUR)" 3 | @mkdir -p /rootfs/etc/systemd/system/ 4 | @cp -a addons/hciattach-service/hciattach.service /rootfs/etc/systemd/system/ 5 | @mkdir -p /rootfs/tmp/install/ 6 | @echo " hciattach bluetooth" >> /rootfs/tmp/install/systemd-enable 7 | @touch $@ 8 | -------------------------------------------------------------------------------- /scripts/addons/hciattach-service/hciattach.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Attach Bluetooth to UART 3 | After=dev-ttyS4.device 4 | Before=bluetooth.service 5 | 6 | [Service] 7 | Type=forking 8 | ExecStart=/usr/bin/hciattach -s 1500000 /dev/ttyS4 any 1500000 flow nosleep 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /scripts/addons/usb-gadget/addon.mk: -------------------------------------------------------------------------------- 1 | $(BUILDDIR)/usb-gadget-stamp: 2 | @echo "$(COLOUR_GREEN)Installing usb-gadget for $(BOARD)$(END_COLOUR)" 3 | @mkdir -p /rootfs/usr/sbin /rootfs/etc/systemd/system/ /rootfs/etc/network/interfaces.d/ 4 | @cp -a addons/usb-gadget/run_usb.sh /rootfs/usr/sbin/ 5 | @chmod +x /rootfs/usr/sbin/run_usb.sh 6 | @cp -a addons/usb-gadget/usb-gadget*.service /rootfs/etc/systemd/system/ 7 | @cp -a addons/usb-gadget/usb0 /rootfs/etc/network/interfaces.d/ 8 | @mkdir -p /rootfs/tmp/install/ 9 | @echo " usb-gadget-rndis usb-gadget-rndis-usb0" >> /rootfs/tmp/install/systemd-enable 10 | @touch $@ 11 | -------------------------------------------------------------------------------- /scripts/addons/usb-gadget/run_usb.sh: -------------------------------------------------------------------------------- 1 | CLASS=acm 2 | VID=0x3346 3 | PID=0x1003 4 | MSC_PID=0x1008 5 | RNDIS_PID=0x1009 6 | UVC_PID=0x100A 7 | UAC_PID=0x100B 8 | ADB_VID=0x18D1 9 | ADB_PID=0x4EE0 10 | ADB_PID_M1=0x4EE2 11 | ADB_PID_M2=0x4EE4 12 | MANUFACTURER="Cvitek" 13 | PRODUCT="USB Com Port" 14 | PRODUCT_RNDIS="RNDIS" 15 | PRODUCT_UVC="UVC" 16 | PRODUCT_UAC="UAC" 17 | PRODUCT_ADB="ADB" 18 | ADBD_PATH=/usr/bin/ 19 | SERIAL="0123456789" 20 | MSC_FILE=$3 21 | CVI_DIR=/tmp/usb 22 | CVI_GADGET=$CVI_DIR/usb_gadget/cvitek 23 | CVI_FUNC=$CVI_GADGET/functions 24 | FUNC_NUM=0 25 | MAX_EP_NUM=4 26 | TMP_NUM=0 27 | INTF_NUM=0 28 | EP_IN=0 29 | EP_OUT=0 30 | 31 | case "$2" in 32 | acm) 33 | CLASS=acm 34 | ;; 35 | msc) 36 | CLASS=mass_storage 37 | PID=$MSC_PID 38 | ;; 39 | cvg) 40 | CLASS=cvg 41 | ;; 42 | rndis) 43 | CLASS=rndis 44 | PID=$RNDIS_PID 45 | PRODUCT=$PRODUCT_RNDIS 46 | ;; 47 | uvc) 48 | CLASS=uvc 49 | PID=$UVC_PID 50 | PRODUCT=$PRODUCT_UVC 51 | ;; 52 | uac1) 53 | CLASS=uac1 54 | PID=$UAC_PID 55 | PRODUCT=$PRODUCT_UAC 56 | ;; 57 | adb) 58 | CLASS=ffs.adb 59 | VID=$ADB_VID 60 | PID=$ADB_PID 61 | PRODUCT=$PRODUCT_ADB 62 | ;; 63 | *) 64 | if [ "$1" = "probe" ] ; then 65 | echo "Usage: $0 probe {acm|msc|cvg|rndis|uvc|uac1|adb}" 66 | exit 1 67 | fi 68 | esac 69 | 70 | calc_func() { 71 | FUNC_NUM=$(ls $CVI_GADGET/functions -l | grep ^d | wc -l) 72 | echo "$FUNC_NUM file(s)" 73 | } 74 | 75 | res_check() { 76 | TMP_NUM=$(find $CVI_GADGET/functions/ -name "acm*" | wc -l) 77 | EP_OUT=$(($EP_OUT+$TMP_NUM)) 78 | TMP_NUM=$(($TMP_NUM * 2)) 79 | EP_IN=$(($EP_IN+$TMP_NUM)) 80 | INTF_NUM=$(($INTF_NUM+$TMP_NUM)) 81 | TMP_NUM=$(find $CVI_GADGET/functions/ -name "mass_storage*" | wc -l) 82 | EP_IN=$(($EP_IN+$TMP_NUM)) 83 | EP_OUT=$(($EP_OUT+$TMP_NUM)) 84 | INTF_NUM=$(($INTF_NUM+$TMP_NUM)) 85 | TMP_NUM=$(find $CVI_GADGET/functions/ -name "cvg*" | wc -l) 86 | EP_IN=$(($EP_IN+$TMP_NUM)) 87 | EP_OUT=$(($EP_OUT+$TMP_NUM)) 88 | INTF_NUM=$(($INTF_NUM+$TMP_NUM)) 89 | TMP_NUM=$(find $CVI_GADGET/functions/ -name "rndis*" | wc -l) 90 | EP_OUT=$(($EP_OUT+$TMP_NUM)) 91 | TMP_NUM=$(($TMP_NUM * 2)) 92 | EP_IN=$(($EP_IN+$TMP_NUM)) 93 | INTF_NUM=$(($INTF_NUM+$TMP_NUM)) 94 | TMP_NUM=$(find $CVI_GADGET/functions/ -name "uvc*" | wc -l) 95 | TMP_NUM=$(($TMP_NUM * 2)) 96 | EP_IN=$(($EP_IN+$TMP_NUM)) 97 | INTF_NUM=$(($INTF_NUM+$TMP_NUM)) 98 | TMP_NUM=$(find $CVI_GADGET/functions/ -name "uac1*" | wc -l) 99 | TMP_NUM=$(($TMP_NUM * 2)) 100 | EP_IN=$(($EP_IN+$TMP_NUM)) 101 | EP_OUT=$(($EP_OUT+$TMP_NUM)) 102 | INTF_NUM=$(($INTF_NUM+$TMP_NUM)) 103 | TMP_NUM=$(find $CVI_GADGET/functions/ -name ffs.adb | wc -l) 104 | EP_IN=$(($EP_IN+$TMP_NUM)) 105 | EP_OUT=$(($EP_OUT+$TMP_NUM)) 106 | INTF_NUM=$(($INTF_NUM+$TMP_NUM)) 107 | 108 | if [ "$CLASS" = "acm" ] ; then 109 | EP_IN=$(($EP_IN+2)) 110 | EP_OUT=$(($EP_OUT+1)) 111 | fi 112 | if [ "$CLASS" = "mass_storage" ] ; then 113 | EP_IN=$(($EP_IN+1)) 114 | EP_OUT=$(($EP_OUT+1)) 115 | fi 116 | if [ "$CLASS" = "cvg" ] ; then 117 | EP_IN=$(($EP_IN+1)) 118 | EP_OUT=$(($EP_OUT+1)) 119 | fi 120 | if [ "$CLASS" = "rndis" ] ; then 121 | EP_IN=$(($EP_IN+2)) 122 | EP_OUT=$(($EP_OUT+1)) 123 | fi 124 | if [ "$CLASS" = "uvc" ] ; then 125 | EP_IN=$(($EP_IN+2)) 126 | fi 127 | if [ "$CLASS" = "uac1" ] ; then 128 | EP_IN=$(($EP_IN+1)) 129 | EP_OUT=$(($EP_OUT+1)) 130 | fi 131 | if [ "$CLASS" = "ffs.adb" ] ; then 132 | EP_IN=$(($EP_IN+1)) 133 | EP_OUT=$(($EP_OUT+1)) 134 | fi 135 | echo "$EP_IN in ep" 136 | echo "$EP_OUT out ep" 137 | if [ $EP_IN -gt $MAX_EP_NUM ]; then 138 | echo "reach maximum resource" 139 | exit 1 140 | fi 141 | if [ $EP_OUT -gt $MAX_EP_NUM ]; then 142 | echo "reach maximum resource" 143 | exit 1 144 | fi 145 | } 146 | 147 | probe() { 148 | if [ ! -d $CVI_DIR ]; then 149 | mkdir $CVI_DIR 150 | fi 151 | if [ ! -d $CVI_DIR/usb_gadget ]; then 152 | # Enale USB ConfigFS 153 | mount none $CVI_DIR -t configfs 154 | # Create gadget dev 155 | mkdir $CVI_GADGET 156 | # Set the VID and PID 157 | echo $VID >$CVI_GADGET/idVendor 158 | echo $PID >$CVI_GADGET/idProduct 159 | # Set the product information string 160 | mkdir $CVI_GADGET/strings/0x409 161 | echo $MANUFACTURER>$CVI_GADGET/strings/0x409/manufacturer 162 | echo $PRODUCT>$CVI_GADGET/strings/0x409/product 163 | echo $SERIAL>$CVI_GADGET/strings/0x409/serialnumber 164 | # Set the USB configuration 165 | mkdir $CVI_GADGET/configs/c.1 166 | mkdir $CVI_GADGET/configs/c.1/strings/0x409 167 | echo "config1">$CVI_GADGET/configs/c.1/strings/0x409/configuration 168 | # Set the MaxPower of USB descriptor 169 | echo 120 >$CVI_GADGET/configs/c.1/MaxPower 170 | fi 171 | # get current functions number 172 | calc_func 173 | # assign the class code for composite device 174 | if [ ! $FUNC_NUM -eq 0 ]; then 175 | echo 0xEF >$CVI_GADGET/bDeviceClass 176 | echo 0x02 >$CVI_GADGET/bDeviceSubClass 177 | echo 0x01 >$CVI_GADGET/bDeviceProtocol 178 | fi 179 | # resource check 180 | res_check 181 | # create the desired function 182 | if [ "$CLASS" = "ffs.adb" ] ; then 183 | # adb shall be the last function to probe. Override the pid/vid 184 | echo $VID >$CVI_GADGET/idVendor 185 | echo $PID >$CVI_GADGET/idProduct 186 | # choose pid for different function number 187 | if [ $INTF_NUM -eq 1 ]; then 188 | echo $ADB_PID_M1 >$CVI_GADGET/idProduct 189 | fi 190 | if [ $INTF_NUM -eq 2 ]; then 191 | echo $ADB_PID_M2 >$CVI_GADGET/idProduct 192 | fi 193 | mkdir $CVI_GADGET/functions/$CLASS 194 | else 195 | mkdir $CVI_GADGET/functions/$CLASS.usb$FUNC_NUM 196 | fi 197 | if [ "$CLASS" = "mass_storage" ] ; then 198 | echo $MSC_FILE >$CVI_GADGET/functions/$CLASS.usb$FUNC_NUM/lun.0/file 199 | fi 200 | if [ "$CLASS" = "rndis" ] ; then 201 | #OS STRING 202 | echo 1 >$CVI_GADGET/os_desc/use 203 | echo 0xcd >$CVI_GADGET/os_desc/b_vendor_code 204 | echo MSFT100 >$CVI_GADGET/os_desc/qw_sign 205 | #COMPATIBLE ID 206 | echo RNDIS >$CVI_FUNC/rndis.usb$FUNC_NUM/os_desc/interface.rndis/compatible_id 207 | #MAKE c.1 THE ONE ASSOCIATED WITH OS DESCRIPTORS 208 | ln -s $CVI_GADGET/configs/c.1 $CVI_GADGET/os_desc 209 | #MAKE "Icons" EXTENDED PROPERTY 210 | mkdir $CVI_FUNC/rndis.usb$FUNC_NUM/os_desc/interface.rndis/Icons 211 | echo 2 >$CVI_FUNC/rndis.usb$FUNC_NUM/os_desc/interface.rndis/Icons/type 212 | echo "%SystemRoot%\\system32\\shell32.dll,-233" >$CVI_FUNC/rndis.usb$FUNC_NUM/os_desc/interface.rndis/Icons/data 213 | #MAKE "Label" EXTENDED PROPERTY 214 | mkdir $CVI_FUNC/rndis.usb$FUNC_NUM/os_desc/interface.rndis/Label 215 | echo 1 >$CVI_FUNC/rndis.usb$FUNC_NUM/os_desc/interface.rndis/Label/type 216 | echo "XYZ Device" >$CVI_FUNC/rndis.usb$FUNC_NUM/os_desc/interface.rndis/Label/data 217 | fi 218 | 219 | } 220 | 221 | start() { 222 | # link this function to the configuration 223 | calc_func 224 | if [ $FUNC_NUM -eq 0 ]; then 225 | echo "Functions Empty!" 226 | exit 1 227 | fi 228 | if [ -d $CVI_GADGET/functions/ffs.adb ]; then 229 | FUNC_NUM=$(($FUNC_NUM-1)) 230 | fi 231 | for i in `seq 0 $(($FUNC_NUM-1))`; 232 | do 233 | find $CVI_GADGET/functions/ -name "*.usb$i" | xargs -I % ln -s % $CVI_GADGET/configs/c.1 234 | done 235 | if [ -d $CVI_GADGET/functions/ffs.adb ]; then 236 | ln -s $CVI_GADGET/functions/ffs.adb $CVI_GADGET/configs/c.1 237 | mkdir /dev/usb-ffs/adb -p 238 | mount -t functionfs adb /dev/usb-ffs/adb 239 | if [ -f $ADBD_PATH/adbd ]; then 240 | $ADBD_PATH/adbd & 241 | fi 242 | else 243 | # Start the gadget driver 244 | UDC=`ls /sys/class/udc/ | awk '{print $1}'` 245 | echo ${UDC} >$CVI_GADGET/UDC 246 | fi 247 | } 248 | 249 | stop() { 250 | if [ -d $CVI_GADGET/configs/c.1/ffs.adb ]; then 251 | pkill adbd 252 | rm $CVI_GADGET/configs/c.1/ffs.adb 253 | else 254 | echo "" >$CVI_GADGET/UDC 255 | fi 256 | find $CVI_GADGET/configs/ -name "*.usb*" | xargs rm -f 257 | rmdir $CVI_GADGET/configs/c.*/strings/0x409/ 258 | tmp_dirs=$(find $CVI_GADGET/os_desc/c.* -type d) 259 | if [ -n tmp_dirs ]; then 260 | echo "remove os_desc!" 261 | rm -rf $CVI_GADGET/os_desc/c.*/ 262 | find $CVI_GADGET/functions/ -name Icons | xargs rmdir 263 | find $CVI_GADGET/functions/ -name Label | xargs rmdir 264 | fi 265 | rmdir $CVI_GADGET/configs/c.*/ 266 | rmdir $CVI_GADGET/functions/* 267 | rmdir $CVI_GADGET/strings/0x409/ 268 | rmdir $CVI_GADGET 269 | umount $CVI_DIR 270 | rmdir $CVI_DIR 271 | } 272 | 273 | case "$1" in 274 | start) 275 | start 276 | ;; 277 | stop) 278 | stop 279 | ;; 280 | probe) 281 | probe 282 | ;; 283 | UDC) 284 | UDC=`ls /sys/class/udc/ | awk '{print $1}'` 285 | echo ${UDC} >$CVI_GADGET/UDC 286 | ;; 287 | *) 288 | echo "Usage: $0 probe {acm|msc|cvg|uvc|uac1} {file (msc)}" 289 | echo "Usage: $0 start" 290 | echo "Usage: $0 stop" 291 | exit 1 292 | esac 293 | exit $? 294 | -------------------------------------------------------------------------------- /scripts/addons/usb-gadget/usb-gadget-acm.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ACM USB Gadget Support 3 | After=network.target 4 | Before=usb-gadget.service 5 | Conflicts=usb-gadget-rndis.service 6 | Conflicts=usb-switch.service 7 | StartLimitIntervalSec=0 8 | 9 | [Service] 10 | Type=oneshot 11 | ExecStart=/bin/bash -c "/bin/echo device > /proc/cviusb/otg_role" 12 | ExecStart=sh /usr/sbin/run_usb.sh probe acm 13 | ExecStart=sh /usr/sbin/run_usb.sh start 14 | 15 | [Install] 16 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /scripts/addons/usb-gadget/usb-gadget-rndis-usb0.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=USB rndis DHCP Gadget Support 3 | After=usb-gadget.service 4 | After=ifup@usb0.service 5 | StartLimitIntervalSec=0 6 | 7 | [Service] 8 | Type=exec 9 | Restart=on-failure 10 | ExecStart=/usr/sbin/dnsmasq --conf-file=/dev/null --no-hosts --keep-in-foreground --bind-interfaces --except-interface=lo --clear-on-reload --strict-order --listen-address=10.42.0.1 --dhcp-range=10.42.0.10,10.42.0.254,60m --dhcp-leasefile=/var/lib/NetworkManager/dnsmasq-usb0.leases --pid-file=/run/nm-dnsmasq-usb0.pid --conf-dir=/etc/NetworkManager/dnsmasq-shared.d --dhcp-option=3 --dhcp-option=6 11 | 12 | 13 | [Install] 14 | WantedBy=sys-subsystem-net-devices-usb0.device -------------------------------------------------------------------------------- /scripts/addons/usb-gadget/usb-gadget-rndis.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=RNDIS USB Gadget Support 3 | After=network.target 4 | Before=usb-gadget.service 5 | Conflicts=usb-gadget-acm.service 6 | Conflicts=usb-switch.service 7 | StartLimitIntervalSec=0 8 | 9 | [Service] 10 | Type=oneshot 11 | ExecStart=/bin/bash -c "/bin/echo device > /proc/cviusb/otg_role" 12 | ExecStart=sh /usr/sbin/run_usb.sh probe rndis 13 | ExecStart=sh /usr/sbin/run_usb.sh start 14 | 15 | [Install] 16 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /scripts/addons/usb-gadget/usb0: -------------------------------------------------------------------------------- 1 | allow-hotplug usb0 2 | iface usb0 inet static 3 | address 10.42.0.1 4 | netmask 255.255.255.0 5 | -------------------------------------------------------------------------------- /scripts/addons/usb-switch/addon.mk: -------------------------------------------------------------------------------- 1 | $(BUILDDIR)/usb-switch-stamp: 2 | @echo "$(COLOUR_GREEN)Installing USB Switch for $(BOARD)$(END_COLOUR)" 3 | @mkdir -p /rootfs/etc/systemd/system/ 4 | @cp -a addons/usb-switch/usb-switch.service /rootfs/etc/systemd/system/ 5 | @mkdir -p /rootfs/tmp/install/ 6 | @touch $@ 7 | -------------------------------------------------------------------------------- /scripts/addons/usb-switch/usb-switch.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Enable USB Switch 3 | After=network.target 4 | Conflicts=usb-gadget-rndis.service 5 | Conflicts=usb-gadget-acm.service 6 | StartLimitIntervalSec=0 7 | 8 | [Service] 9 | Type=oneshot 10 | ExecStart=/bin/bash -c "/usr/bin/gpioset gpiochip1 5=1" 11 | ExecStart=/bin/bash -c "/usr/bin/gpioset gpiochip0 30=1" 12 | 13 | [Install] 14 | WantedBy=multi-user.target -------------------------------------------------------------------------------- /scripts/deb/cvitek-fsbl/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: cvitek-fsbl 2 | Architecture: riscv64 3 | Maintainer: @fishwaldo 4 | Priority: optional 5 | Version: 1.0.0 6 | Description: First Stage Boot Loader for the CV18xx and SG200X series of RISC-V SoC's 7 | -------------------------------------------------------------------------------- /scripts/genimage_emmc.cfg: -------------------------------------------------------------------------------- 1 | image sdcard.img { 2 | hdimage { 3 | partition-table-type="mbr" 4 | } 5 | partition root { 6 | partition-type = 0x83 7 | bootable = true 8 | image = "root.ext4" 9 | } 10 | } 11 | image root.ext4 { 12 | ext4 { 13 | label="root" 14 | use-mke2fs=true 15 | } 16 | mountpoint = "/" 17 | size = 150% 18 | } 19 | 20 | -------------------------------------------------------------------------------- /scripts/genimage_sd.cfg: -------------------------------------------------------------------------------- 1 | image sdcard.img { 2 | hdimage { 3 | partition-table-type="mbr" 4 | } 5 | partition boot { 6 | partition-type = 0x0b 7 | bootable = true 8 | image = "boot.vfat" 9 | } 10 | partition root { 11 | partition-type = 0x83 12 | image = "root.ext4" 13 | } 14 | } 15 | image boot.vfat { 16 | vfat { 17 | label="boot" 18 | } 19 | mountpoint = "/boot" 20 | size = 100M 21 | } 22 | image root.ext4 { 23 | ext4 { 24 | label="root" 25 | use-mke2fs=true 26 | } 27 | mountpoint = "/" 28 | size = 150% 29 | } 30 | 31 | -------------------------------------------------------------------------------- /scripts/python/XmlParser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import logging 4 | import os 5 | import re 6 | import sys 7 | import xml.etree.ElementTree as ET 8 | 9 | FORMAT = "%(levelname)s: %(message)s" 10 | logging.basicConfig(level=logging.INFO, format=FORMAT) 11 | Storage_EMMC = 0 12 | Storage_SPINAND = 1 13 | Storage_SPINOR = 2 14 | LBA_SIZE = 512 15 | 16 | 17 | class XmlParser: 18 | @staticmethod 19 | def parse_size(size): 20 | units = {"B": 1, "K": 2 ** 10, "M": 2 ** 20, "G": 2 ** 30, "T": 2 ** 40} 21 | size = size.upper() 22 | logging.debug("parsing size %s" % size) 23 | if not re.match(r" ", size): 24 | size = re.sub(r"([BKMGT])", r" \1", size) 25 | try: 26 | number, unit = [string.strip() for string in size.split()] 27 | except ValueError: 28 | number = size 29 | unit = "B" 30 | 31 | ret = int(float(number) * units[unit]) 32 | 33 | return ret 34 | 35 | def parse(self, install=None): 36 | try: 37 | tree = ET.parse(self.xml) 38 | except Exception: 39 | logging.error(self.xml + " is not a vaild xml file") 40 | raise 41 | 42 | root = tree.getroot() 43 | self.storage = root.attrib["type"] 44 | install_dir = install 45 | parts = [] 46 | for part in root: 47 | p = dict() 48 | if "size_in_kb" in part.attrib: 49 | p["part_size"] = int(part.attrib["size_in_kb"]) * 1024 50 | elif "size_in_b" in part.attrib: 51 | p["part_size"] = int(part.attrib["size_in_b"]) 52 | else: 53 | p["part_size"] = sys.maxsize 54 | # Assign 0 means biggest number 55 | 56 | if part.attrib["file"] and install_dir is not None: 57 | path = os.path.join(install_dir, part.attrib["file"]) 58 | try: 59 | file_size = os.stat(path).st_size 60 | except Exception: 61 | file_size = 0 62 | if file_size > p["part_size"]: 63 | logging.error( 64 | "Image: %s(%d) is larger than partition size(%d)" 65 | % (part.attrib["file"], file_size, p["part_size"]) 66 | ) 67 | raise OverflowError 68 | p["file_path"] = path 69 | logging.debug("size of " + path + " : " + str(file_size)) 70 | else: 71 | file_size = 0 72 | 73 | p["file_size"] = int(file_size) 74 | p["file_name"] = part.attrib["file"] 75 | p["label"] = part.attrib["label"] 76 | p["mountpoint"] = ( 77 | part.attrib["mountpoint"] if "mountpoint" in part.attrib else None 78 | ) 79 | p["type"] = part.attrib["type"] if "type" in part.attrib else "" 80 | p["options"] = part.attrib["options"] if "options" in part.attrib else None 81 | 82 | parts.append(p) 83 | 84 | if self.storage == "emmc": 85 | self.__calEmmcOffset(parts) 86 | elif self.storage == "spinor": 87 | self.__calNorOffset(parts) 88 | elif self.storage == "spinand": 89 | self.__calNandOffset(parts) 90 | elif self.storage == "sd": 91 | self.__calNandOffset(parts) 92 | elif self.storage == "none": 93 | self.__calNandOffset(parts) 94 | 95 | else: 96 | logging.error("Unknown storage type") 97 | raise ValueError(self.storage) 98 | for p in parts: 99 | self.parts[p["label"]] = p 100 | return parts 101 | 102 | def __calEmmcOffset(self, parts): 103 | # EMMC will program gpt in the beggining of the emmc, start from 8192 104 | start = 0 105 | for p in parts: 106 | p["offset"] = start 107 | start += p["part_size"] 108 | 109 | def __calNandOffset(self, parts): 110 | start = 0 111 | for p in parts: 112 | p["offset"] = start 113 | start += p["part_size"] 114 | 115 | def __calNorOffset(self, parts): 116 | start = 0 117 | for p in parts: 118 | p["offset"] = start 119 | start += p["part_size"] 120 | 121 | def getStorage(self): 122 | return self.storage 123 | 124 | def __init__(self, xml): 125 | self.xml = xml 126 | self.storage = "emmc" 127 | self.parts = dict() 128 | -------------------------------------------------------------------------------- /scripts/python/mk_imgHeader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import argparse 4 | import logging 5 | import os 6 | from XmlParser import XmlParser 7 | 8 | FORMAT = "%(levelname)s: %(message)s" 9 | logging.basicConfig(level=logging.INFO, format=FORMAT) 10 | 11 | 12 | def main(): 13 | parser = argparse.ArgumentParser(description="Create imgs.h for u-boot") 14 | parser.add_argument("xml", help="path to partition xml") 15 | parser.add_argument("output", help="output folder") 16 | args = parser.parse_args() 17 | 18 | parser = XmlParser(args.xml) 19 | parts = parser.parse() 20 | storage = parser.getStorage() 21 | with open(os.path.join(args.output, "imgs.h"), "w") as of: 22 | of.write("char imgs[][255] = {") 23 | if storage == "emmc": 24 | of.write('"fip.bin",\n') 25 | for p in parts: 26 | if p["file_name"] != "": 27 | of.write('"%s",\n' % p["file_name"]) 28 | of.write("};") 29 | 30 | 31 | if __name__ == "__main__": 32 | main() 33 | -------------------------------------------------------------------------------- /scripts/python/mkcvipart.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | import argparse 4 | import logging 5 | import os 6 | import sys 7 | from XmlParser import XmlParser 8 | 9 | FORMAT = "%(levelname)s: %(message)s" 10 | logging.basicConfig(level=logging.INFO, format=FORMAT) 11 | 12 | 13 | def parse_args(): 14 | parser = argparse.ArgumentParser(description="Create cvipart.h and fw_env.config") 15 | parser.add_argument("xml", help="path to partition xml") 16 | parser.add_argument("output", help="output folder") 17 | parser.add_argument( 18 | "--fw_env", 19 | help="create fw_env.config with the parameter the script will create cvipart.h for u-boot", 20 | action="store_true", 21 | ) 22 | parser.add_argument( 23 | "--block_size", 24 | help="set block size for spinand, default is 128KB", 25 | default=128 * 1024, 26 | ) 27 | 28 | parser.add_argument( 29 | "-v", "--verbose", help="increase output verbosity", action="store_true" 30 | ) 31 | args = parser.parse_args() 32 | if args.verbose: 33 | logging.debug("Enable more verbose output") 34 | logging.getLogger().setLevel(level=logging.DEBUG) 35 | 36 | return args 37 | 38 | 39 | def gen_cvipart_h(output, parser): 40 | logging.info("generating cvipart.h") 41 | parts = parser.parse() 42 | with open(os.path.join(output, "cvipart.h"), "w") as of: 43 | of.write("/* this file should be generated by mkcvipart.py,") 44 | of.write("please do not modify this file manually*/\n\n") 45 | of.write("#ifndef CVIPART_H\n") 46 | of.write("#define CVIPART_H\n") 47 | env_exist = True 48 | env_bak = False 49 | 50 | # Generate ENV_OFFSET 51 | if "ENV" in parser.parts: 52 | label = "ENV" 53 | elif "U-BOOT ENV" in parser.parts: 54 | label = "U-BOOT ENV" 55 | else: 56 | # If no ENV or U-BOOT ENV has been set in partition.xml, we assume 57 | # there is no env support 58 | of.write("#ifndef CONFIG_ENV_IS_NOWHERE\n#define CONFIG_ENV_IS_NOWHERE\n#endif\n") 59 | of.write("#define CONFIG_ENV_SIZE 0x20000\n") 60 | env_exist = False 61 | 62 | if env_exist and "ENV_BAK" in parser.parts: 63 | env_bak = True 64 | 65 | LBA_SIZE = 1 66 | if parser.getStorage() == "emmc": 67 | if env_exist: 68 | of.write("#define CONFIG_ENV_IS_IN_MMC\n") 69 | of.write("#define CONFIG_ENV_SECT_SIZE 0x40000\n") 70 | of.write("#define CONFIG_SYS_MMC_ENV_DEV 0\n") 71 | of.write("#define CONFIG_SYS_MMC_ENV_PART 0\n") 72 | 73 | # Generintg BLKDEV 74 | of.write("#define PART_LAYOUT ") 75 | of.write("\"blkdevparts=mmcblk0:") 76 | for i, p in enumerate(parts): 77 | if p["part_size"] != sys.maxsize: 78 | part_size = str(int(p["part_size"] / 1024)) + "K" 79 | else: 80 | part_size = "-" 81 | if part_size == "-" or i == len(parts) - 1: 82 | comma = ";" 83 | else: 84 | comma = "," 85 | of.write("%s(%s)%s" % (part_size, p["label"], comma)) 86 | of.write("mmcblk0boot0:1M(fip),1M(fip_bak);\"") 87 | of.write("\n") 88 | 89 | for i, p in enumerate(parts): 90 | if p["label"] == "ROOTFS": 91 | of.write('#define ROOTFS_DEV "/dev/mmcblk0p%d"\n' % (i + 1)) 92 | 93 | elif parser.getStorage() == "spinand": 94 | if env_exist: 95 | of.write("#define CONFIG_ENV_IS_IN_NAND\n") 96 | of.write("#define CONFIG_ENV_SECT_SIZE 0x40000\n") 97 | # Generintg MTDPART 98 | of.write("#define PART_LAYOUT ") 99 | of.write('"mtdparts=cvsnfc:') 100 | for i, p in enumerate(parts): 101 | if p["part_size"] != sys.maxsize: 102 | part_size = str(int(p["part_size"] / 1024)) + "K" 103 | else: 104 | part_size = "-" 105 | if part_size == "-" or i == len(parts) - 1: 106 | comma = "\"\n" 107 | else: 108 | comma = "," 109 | of.write("%s(%s)%s" % (part_size, p["label"], comma)) 110 | 111 | elif parser.getStorage() == "spinor": 112 | if env_exist: 113 | of.write("#define CONFIG_ENV_IS_IN_SPI_FLASH\n") 114 | of.write("#define CONFIG_ENV_SECT_SIZE 0x10000\n") 115 | # Generintg MTDPART 116 | of.write("#define PART_LAYOUT ") 117 | of.write('"mtdparts=10000000.cvi-spif:') 118 | for i, p in enumerate(parts): 119 | if p["part_size"] != sys.maxsize: 120 | part_size = str(int(p["part_size"] / 1024)) + "K" 121 | else: 122 | part_size = "-" 123 | if part_size == "-" or i == len(parts) - 1: 124 | comma = '"\n' 125 | else: 126 | comma = "," 127 | of.write("%s(%s)%s" % (part_size, p["label"], comma)) 128 | 129 | for i, p in enumerate(parts): 130 | if p["label"] == "ROOTFS": 131 | of.write('#define ROOTFS_DEV "/dev/mtdblock%d"\n' % i) 132 | break 133 | 134 | elif parser.getStorage() == "sd": 135 | of.write('#define PART_LAYOUT ""\n') 136 | for i, p in enumerate(parts): 137 | if p["label"] == "ROOTFS": 138 | of.write('#define ROOTFS_DEV "/dev/mmcblk0p%d"\n' % (i+1)) 139 | break 140 | of.write('#define PARTS_OFFSET ""\n') 141 | 142 | elif parser.getStorage() == "none": 143 | of.write('#define PART_LAYOUT ""\n') 144 | of.write('#define ROOTFS_DEV ""\n') 145 | of.write('#define PARTS_OFFSET ""\n') 146 | 147 | if env_exist: 148 | of.write( 149 | "#define CONFIG_ENV_OFFSET 0x%X\n" 150 | % (parser.parts[label]["offset"]) 151 | ) 152 | if env_bak: 153 | of.write( 154 | "#define CONFIG_ENV_OFFSET_REDUND 0x%X\n" 155 | % (parser.parts["ENV_BAK"]["offset"] * LBA_SIZE) 156 | ) 157 | of.write("#define CONFIG_SYS_REDUNDAND_ENVIRONMENT\n") 158 | of.write( 159 | "#define CONFIG_ENV_SIZE 0x%X\n" % parser.parts[label]["part_size"] 160 | ) 161 | 162 | # Generintg PART_ENV 163 | if parser.getStorage() == "emmc": 164 | LBA_SIZE = 512 165 | 166 | if parser.getStorage() != "none" and parser.getStorage() != "sd": 167 | of.write("#define PARTS_OFFSET \\\n") 168 | for i, p in enumerate(parts): 169 | of.write('"%s_PART_OFFSET=0x%x\\0" \\\n' % (p["label"], int(p["offset"] / LBA_SIZE))) 170 | if i == len(parts) - 1: 171 | of.write( 172 | '"%s_PART_SIZE=0x%x\\0"\n' 173 | % (p["label"], int(p["part_size"] / LBA_SIZE)) 174 | ) 175 | else: 176 | of.write( 177 | '"%s_PART_SIZE=0x%x\\0" \\\n' 178 | % (p["label"], int(p["part_size"] / LBA_SIZE)) 179 | ) 180 | 181 | for i, p in enumerate(parts): 182 | if p["label"] == 'BOOT': 183 | of.write('#define SPL_%s_PART_OFFSET 0x%x\n' % (p["label"], int(p["offset"] / LBA_SIZE))) 184 | elif p["label"] == 'jump': 185 | of.write('#define SPL_%s_PART_OFFSET 0x%x\n' % ("BOOT", 0)) 186 | of.write("#endif") 187 | logging.info("Done!") 188 | 189 | 190 | def gen_fw_config(output, parser, block_size=128 * 1024): 191 | logging.info("generating fw_env.config") 192 | parts = parser.parse() 193 | part_index = -1 194 | with open(os.path.join(output, "fw_env.config"), "w") as of: 195 | for i in range(len(parts)): 196 | if parts[i]["label"] == "ENV" or parts[i]["label"] == "U-BOOT ENV" or parts[i]["label"] == "ENV_BAK": 197 | part_index = i 198 | if parser.storage == "spinand": 199 | of.write( 200 | "/dev/mtd%d 0x%x 0x%x 0x%x\n" 201 | % (part_index, 0, parts[part_index]["part_size"], block_size) 202 | ) 203 | elif parser.storage == "emmc": 204 | of.write( 205 | "/dev/mmcblk0 0x%x 0x%x\n" 206 | % ((parts[part_index]["offset"] * 512), parts[part_index]["part_size"]) 207 | ) 208 | elif parser.storage == "spinor": 209 | of.write( 210 | "/dev/mtd%d 0x%x 0x%x 0x%x\n" 211 | % (part_index, 0, parts[part_index]["part_size"], 64 * 1024) 212 | ) 213 | if part_index == -1: 214 | logging.info( 215 | "There is no ENV or U-BOOT ENV partition in partition.xml ignore generating fw_env.config" 216 | ) 217 | if os.path.isfile("fw_env.config"): 218 | os.remove("fw_env.config") 219 | return 220 | 221 | 222 | def main(): 223 | args = parse_args() 224 | parser = XmlParser(args.xml) 225 | if not args.fw_env: 226 | gen_cvipart_h(args.output, parser) 227 | else: 228 | gen_fw_config(args.output, parser, args.block_size) 229 | 230 | 231 | if __name__ == "__main__": 232 | main() 233 | -------------------------------------------------------------------------------- /scripts/python/mmap_conv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import logging 4 | import argparse 5 | import importlib.util 6 | from os.path import basename, splitext, abspath 7 | from collections import OrderedDict 8 | import random 9 | 10 | 11 | MEMMAP_PREFIX = "CVIMMAP_" 12 | 13 | 14 | def sort_mmap(mlist): 15 | base = mlist.get("CVIMMAP_DRAM_BASE") 16 | if not base: 17 | base = 0 18 | 19 | mm = mlist.items() 20 | 21 | mm = sorted(mm, key=lambda x: x[1]) 22 | mm = sorted(mm, key=lambda x: x[0]) 23 | 24 | return OrderedDict(mm) 25 | 26 | 27 | def parse_mmap(mmap_module): 28 | try: 29 | mmap = mmap_module.MemoryMap 30 | except AttributeError: 31 | logging.error("Memory map file must have 'class MemoryMap'") 32 | raise 33 | 34 | no_prefix = getattr(mmap_module.MemoryMap, "_no_prefix", []) 35 | 36 | mlist = OrderedDict() 37 | 38 | for attr in mmap.__dict__: 39 | if attr.startswith("_"): 40 | continue 41 | 42 | value = getattr(mmap, attr) 43 | if attr not in no_prefix: 44 | attr = MEMMAP_PREFIX + attr 45 | mlist[attr] = int(value) 46 | 47 | return sort_mmap(mlist) 48 | 49 | 50 | def int_to_si(n): 51 | off = "" 52 | 53 | for i in [0x80000000, 0x100000000]: 54 | if n >= i: 55 | off = "offset " 56 | n -= i 57 | break 58 | 59 | if n < 1024 * 1024: 60 | s = "{0}KiB".format(n / 1024) 61 | else: 62 | s = "{0}MiB".format(n / (1024 * 1024)) 63 | 64 | return off + s 65 | 66 | 67 | def mmap_to_ld(mlist): 68 | mlist = ["{0:s} = {1:#x};".format(a, v) for a, v in mlist.items()] 69 | 70 | conf = "\n".join(mlist) 71 | return conf 72 | 73 | 74 | def mmap_to_conf(mlist): 75 | mlist = ["{0:s}={1:#x}".format(a, v) for a, v in mlist.items()] 76 | 77 | conf = "\n".join(mlist) 78 | return conf 79 | 80 | 81 | def mmap_to_h(mlist): 82 | mlist = ["#define {0:s} {1:#x} /* {2} */".format(a, v, int_to_si(v)) for a, v in mlist.items()] 83 | 84 | r = random.randint(0x80000000, 0xFFFFFFFF) 85 | 86 | conf = ( 87 | "#ifndef __BOARD_MMAP__{0:08x}__\n" 88 | "#define __BOARD_MMAP__{0:08x}__\n\n" 89 | "{1}\n\n" 90 | "#endif /* __BOARD_MMAP__{0:08x}__ */\n".format(r, "\n".join(mlist)) 91 | ) 92 | return conf 93 | 94 | 95 | def main(): 96 | logging.basicConfig( 97 | format="%(levelname)8s:%(module)s: %(message)s", level=logging.NOTSET 98 | ) 99 | 100 | parser = argparse.ArgumentParser(description="Generate mmap.h") 101 | parser.add_argument("--type", choices=["h", "conf", "ld"], required=True) 102 | parser.add_argument("MAP_FILE", type=str, nargs=1) 103 | parser.add_argument("OUTPUT", type=str, nargs=1) 104 | args = parser.parse_args() 105 | 106 | map_file_path = args.MAP_FILE[0] 107 | logging.info("map_file_path is at %s", map_file_path) 108 | map_name = splitext(basename(map_file_path))[0] 109 | 110 | # Load map_file as python module 111 | spec = importlib.util.spec_from_file_location(map_name, map_file_path) 112 | mmap_module = importlib.util.module_from_spec(spec) 113 | spec.loader.exec_module(mmap_module) 114 | 115 | mlist = parse_mmap(mmap_module) 116 | 117 | if args.type == "h": 118 | out = mmap_to_h(mlist) 119 | elif args.type == "conf": 120 | out = mmap_to_conf(mlist) 121 | elif args.type == "ld": 122 | out = mmap_to_ld(mlist) 123 | 124 | out_path = abspath(args.OUTPUT[0]) 125 | logging.info("Generate to %s", out_path) 126 | with open(out_path, "w") as fp: 127 | fp.write(out) 128 | 129 | 130 | if __name__ == "__main__": 131 | main() 132 | -------------------------------------------------------------------------------- /scripts/python/raw2cimg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | import logging 4 | import argparse 5 | import os 6 | from array import array 7 | import binascii 8 | from XmlParser import XmlParser 9 | from tempfile import TemporaryDirectory 10 | import shutil 11 | 12 | MAX_LOAD_SIZE = 16 * 1024 * 1024 13 | CHUNK_TYPE_DONT_CARE = 0 14 | CHUNK_TYPE_CRC_CHECK = 1 15 | FORMAT = "%(levelname)s: %(message)s" 16 | logging.basicConfig(level=logging.INFO, format=FORMAT) 17 | 18 | 19 | def parse_Args(): 20 | parser = argparse.ArgumentParser(description="Create CVITEK device image") 21 | 22 | parser.add_argument( 23 | "file_path", 24 | metavar="file_path", 25 | type=str, 26 | help="the file you want to pack with cvitek image header", 27 | ) 28 | parser.add_argument( 29 | "output_dir", 30 | metavar="output_folder_path", 31 | type=str, 32 | help="the folder path to install dir inclued fip,rootfs and kernel", 33 | ) 34 | parser.add_argument("xml", help="path to partition xml") 35 | parser.add_argument( 36 | "-v", "--verbose", help="increase output verbosity", action="store_true" 37 | ) 38 | args = parser.parse_args() 39 | if args.verbose: 40 | logging.debug("Enable more verbose output") 41 | logging.getLogger().setLevel(level=logging.DEBUG) 42 | 43 | return args 44 | 45 | 46 | class ImagerBuilder(object): 47 | def __init__(self, storage: int, output_path): 48 | self.storage = storage 49 | self.output_path = output_path 50 | 51 | def packHeader(self, part): 52 | """ 53 | Header format total 64 bytes 54 | 4 Bytes: Magic 55 | 4 Bytes: Version 56 | 4 Bytes: Chunk header size 57 | 4 Bytes: Total chunks 58 | 4 Bytes: File size 59 | 32 Bytes: Extra Flags 60 | 12 Bytes: Reserved 61 | """ 62 | with open(part["file_path"], "rb") as fd: 63 | magic = fd.read(4) 64 | if magic == b"CIMG": 65 | logging.debug("%s has been packed, skip it!" % part["file_name"]) 66 | return 67 | fd.seek(0) 68 | Magic = array("b", [ord(c) for c in "CIMG"]) 69 | Version = array("I", [1]) 70 | chunk_header_sz = 64 71 | Chunk_sz = array("I", [chunk_header_sz]) 72 | chunk_counts = part["file_size"] // MAX_LOAD_SIZE 73 | remain = part["file_size"] - MAX_LOAD_SIZE * chunk_counts 74 | if (remain != 0): 75 | chunk_counts = chunk_counts + 1 76 | Totak_chunk = array("I", [chunk_counts]) 77 | File_sz = array("I", [part["file_size"] + (chunk_counts * chunk_header_sz)]) 78 | try: 79 | label = part["label"] 80 | except KeyError: 81 | label = "gpt" 82 | Extra_flags = array("B", [ord(c) for c in label]) 83 | for _ in range(len(label), 32): 84 | Extra_flags.append(ord("\0")) 85 | 86 | img = open(os.path.join(self.output_path, part["file_name"]), "wb") 87 | # Write Header 88 | for h in [Magic, Version, Chunk_sz, Totak_chunk, File_sz, Extra_flags]: 89 | h.tofile(img) 90 | img.seek(64) 91 | total_size = part["file_size"] 92 | offset = part["offset"] 93 | part_sz = part["part_size"] 94 | op_len = 0 95 | while total_size: 96 | chunk_sz = min(MAX_LOAD_SIZE, total_size) 97 | chunk = fd.read(chunk_sz) 98 | crc = binascii.crc32(chunk) & 0xFFFFFFFF 99 | if chunk_sz == MAX_LOAD_SIZE: 100 | op_len += chunk_sz 101 | else: 102 | op_len = part_sz - op_len 103 | chunk_header = self._getChunkHeader(chunk_sz, offset, op_len, crc) 104 | img.write(chunk_header) 105 | img.write(chunk) 106 | total_size -= chunk_sz 107 | offset += chunk_sz 108 | img.close() 109 | 110 | def _getChunkHeader(self, size: int, offset: int, part_sz: int, crc32: int): 111 | """ 112 | Header format total 64 bytes 113 | 4 Bytes: Chunk Type 114 | 4 Bytes: Chunk data size 115 | 4 Bytes: Program part offset 116 | 4 Bytes: Program part size 117 | 4 Bytes: Crc32 checksum 118 | """ 119 | logging.info("size:%x, offset:%x, part_sz:%x, crc:%x" % (size, offset, part_sz, crc32)) 120 | Chunk = array( 121 | "I", 122 | [ 123 | CHUNK_TYPE_CRC_CHECK, 124 | size, 125 | offset, 126 | part_sz, 127 | crc32, 128 | 0, 129 | 0, 130 | 0, 131 | 0, 132 | 0, 133 | 0, 134 | 0, 135 | 0, 136 | 0, 137 | 0, 138 | 0, 139 | ], 140 | ) 141 | return Chunk 142 | 143 | 144 | def main(): 145 | args = parse_Args() 146 | xmlParser = XmlParser(args.xml) 147 | install_dir = os.path.dirname(args.file_path) 148 | parts = xmlParser.parse(install_dir) 149 | storage = xmlParser.getStorage() 150 | tmp = TemporaryDirectory() 151 | imgBuilder = ImagerBuilder(storage, tmp.name) 152 | for p in parts: 153 | # Since xml parser will parse with abspath and the user input path can 154 | # be relative path, use file name to check. 155 | if os.path.basename(args.file_path) == p["file_name"]: 156 | if ( 157 | storage != "emmc" and storage != "spinor" 158 | and p["file_size"] > p["part_size"] - 128 * 1024 159 | and p["mountpoint"] 160 | and p["mountpoint"] != "" 161 | ): 162 | logging.error( 163 | "Imaege is too big, it will cause mount partition failed!!" 164 | ) 165 | raise ValueError 166 | imgBuilder.packHeader(p) 167 | tmp_path = os.path.join(tmp.name, p["file_name"]) 168 | out_path = os.path.join(args.output_dir, p["file_name"]) 169 | logging.debug("Moving %s -> %s" % (tmp_path, out_path)) 170 | shutil.move(tmp_path, out_path) 171 | logging.info("Packing %s done!" % (p["file_name"])) 172 | 173 | 174 | if __name__ == "__main__": 175 | main() 176 | -------------------------------------------------------------------------------- /scripts/setup_rootfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | set -ex 4 | 5 | BOARD=$(cat /tmp/install/board) 6 | HOSTNAME=$(cat /tmp/install/hostname) 7 | STORAGETYPE=$(cat /tmp/install/storage) 8 | 9 | 10 | export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true 11 | export LC_ALL=C LANGUAGE=C LANG=C 12 | 13 | /var/lib/dpkg/info/base-passwd.preinst install || true 14 | /var/lib/dpkg/info/sgml-base.preinst install || true 15 | 16 | mkdir -p /etc/sgml 17 | mount proc -t proc /proc 18 | mount -B sys /sys 19 | mount -B run /run 20 | mount -B dev /dev 21 | #mount devpts -t devpts /dev/pts 22 | dpkg --configure -a 23 | 24 | unset DEBIAN_FRONTEND DEBCONF_NONINTERACTIVE_SEEN 25 | 26 | # 27 | # Change root password to 'rv' 28 | # 29 | usermod --password "$(echo rv | openssl passwd -1 -stdin)" root 30 | 31 | # 32 | # Add a new user debian and its passwd is `rv` 33 | # 34 | mkdir -p /home/debian 35 | useradd --password dummy \ 36 | -G cdrom,floppy,sudo,audio,dip,video,plugdev \ 37 | --home-dir /home/debian --shell /bin/bash debian || true 38 | chown debian:debian /home/debian 39 | # Set password to 'debian' 40 | usermod --password "$(echo rv | openssl passwd -1 -stdin)" debian || true 41 | 42 | # Set up fstab 43 | cat > /etc/fstab < 45 | /dev/root / auto defaults 1 1 46 | EOF 47 | 48 | if [ "$STORAGETYPE" = "sd" ]; then 49 | cat >> /etc/fstab < /etc/systemd/system/finalize-image.service <> /etc/default/u-boot 116 | u-boot-update 117 | if [ "$STORAGETYPE" = "sd" ]; then 118 | sed -i -e 's|fdtdir /usr/lib/|fdtdir /fdt/|' /boot/extlinux/extlinux.conf 119 | sed -i -e 's|linux /boot/|linux /|' /boot/extlinux/extlinux.conf 120 | sed -i -e "s|U_BOOT_FDT_DIR=\".*\"|U_BOOT_FDT_DIR=\"/fdt/linux-image-$BOARD-\"|" /etc/default/u-boot 121 | else 122 | sed -i -e 's|fdtdir /usr/lib/|fdtdir /boot/fdt/|' /boot/extlinux/extlinux.conf 123 | fi 124 | 125 | cat /boot/extlinux/extlinux.conf 126 | 127 | # Set hostname 128 | cat /tmp/install/hostname > /etc/hostname 129 | 130 | # 131 | cat >> /etc/hosts << EOF 132 | 127.0.0.1 ${HOSTNAME} 133 | EOF 134 | 135 | # 136 | # Enable system services 137 | # 138 | systemctl enable finalize-image.service 139 | if [ -f /tmp/install/systemd-enable ]; then 140 | systemctl enable `cat /tmp/install/systemd-enable` 141 | fi 142 | 143 | # Update source list 144 | 145 | rm -rf /etc/apt/sources.list.d/multistrap-debian.list 146 | 147 | apt-key add /tmp/install/public-key.asc 148 | 149 | cat > /etc/apt/sources.list < /etc/fw_env.config 155 | mkenvimage -s 0x20000 -o /boot/uboot.env /etc/u-boot-initial-env 156 | 157 | 158 | # 159 | # Clean apt cache on the system 160 | # 161 | apt-get clean 162 | 163 | 164 | rm -rf /var/cache/* 165 | find /var/lib/apt/lists -type f -not -name '*.gpg' -print0 | xargs -0 rm -f 166 | find /var/log -type f -print0 | xargs -0 truncate --size=0 167 | --------------------------------------------------------------------------------